Canister installation arguments

I saw this in the 0.6.7 notes:
“Language support to enable canisters to take installation arguments.”

Is there documentation on this anywhere? Right now, I have to manually run an init script to store references to other canisters, and it’d be great to do this automatically.

3 Likes

Hi Norton!

So. Motoko does support this (the following compiles in 0.6.7), but dfx doesn’t yet let you supply installation arguments yet as far as I can tell.

actor class C(greeting : Text){
    public func greet(name : Text) : async Text {
        return greeting # name # "!";
    };
};

If you have a static set of canisters belonging to the same dfx project, then you should be able to just import them by name, but I assume you are doing something more challenging than that?

An example of static canister import is here, if that helps:

4 Likes

I have circular dependencies so that doesn’t quite work:

  • A depends on B to call B.foo()
  • B should only be callable by A: assert(caller == A)
2 Likes

Once installation arguments are support by dfx, I think you can solve this by abstracting B on the principal/id of A, installing B passing the pre-assigned canister id of A, and then installing A.

For now, you can instead use an currently undocumented feature of Motoko that let’s you assert the actor type of an id (without having to import it).

import "mo:base/Principal";
// don't import A!
actor B {
   let A = actor "bfozs-kwa73-7nadi" : actor { }; // asserts type of principal "bfozs…"
           // ^^^^^^^^^^^^^^^^^^^^^^^^ undocumented  syntax
   let pA = Principal.fromActor(a);

  public shared {caller} func foo() : async () {
     assert (caller == pA);
   …
  }
}
}

The drawback of this is that you’ll need to edit the code of B every time dfx is asked to create new canister ids, but you can probably write a script to automate this. The Text argument can also be a computed Text value, not just a literal, but you’ll need to enclose in parentheses. Grammar:

<exp> :=
   ...
   actor <text-like>
   actor (<exp>) 

<text-like ::=
   <text>          literal text id
  (<exp>)         computed text id

Coming soon (implemented, but not released), we will allow actors to import actor classes, so A could just import actor class B, and instantiate it passing the principal of A (obtained from the self binding), avoiding the need to hard-code the Id in some actor B.

Alternatively, have you considered add a one-time registration method to B, callable from A, to claim ownership of B by storing the principal of A in a private field, used in the assertion in foo() etc?

2 Likes