Motoko actor class canister id

Currently if we want to access current canister id in nested modules we need to pass canister id as init arg:

shared ({ caller }) actor class Canister(canisterId : Principal) {...

Would be helpful if we could access the canister id like this:

shared ({ caller; canister }) actor class Canister() {...

here canister : Principal

What do you think?

1 Like

If you want the self reference of the resulting actor, we have a syntax for that:

actor class Client() = self {
  ...
}

EDIT: Ah, I see you want the creator of the new canister. I don’t think that is conveyed by the protocol. But you can probably get hold of the controllers list.

In this case I cannot get canister id anywhere other than inside that actor class.

For example I want pass current canister id to class or func from another file:

// a.mo
class A1(x : actor{}) {};
class A2(x : Principal) {};
class A3(x : () -> Principal) {};

// main.mo
actor class Client() = self {
  let a1 = A1(self); // error "cannot use self before self has been defined"
  let a2 = A2(Principal.fromActor(self)); // error "cannot use self before self has been defined"

  func getCanisterId() : Principal = Principal.fromActor(self);
  let a3 = A3(getCanisterId); // error "cannot use getCanisterId before self has been defined"
}

No, creator is caller in that example.

I recall discussing this cannot use self error with @claudio earlier. IIRC we concluded that this is a definedness analysis bug (infelicity) in Motoko, and the self binding should be available in the initialisation code of the actor.

1 Like

Are there plans to change this?

Even if self is not defined, the error for a3/A3 in the example above is surprising.

It’s not really surprising, just conservative. The class might apply the function, dereferencing self before defined.

But I would like to make it easier to get the self principal.

The simplest might be to just add extra syntax for this particular case: principal_from_actor . Then the definedness analysis can distinguish this from an ordinary library function and treat it specially.

Yes, I thought the error would happen there, in the class, if the class applies the function directly in the constructor. Probably that’s too hard to check, hence we don’t allow to even pass the function to the class.