Perhaps you could use the caller syntax in add_flower and then cache the principal of the first caller, denying calls from all others? But maybe I don’t understand the full intent.
The constructor parameters of the first canister can contain the principal of the second canister, so each canister in the array knows about the other canisters when installed, and then you can raise an error in the function if the caller is not that principal.
I am currently facing a challenge in invoking a method of one canister from another canister in a way that allows the initiating canister to perform the initialization. The issue I’m encountering is that the caller responsible for the initialization is the external entity who initialized the canister, rather than the canister itself. How can I structure my code to enable a canister to autonomously initialize another canister and call its methods, rather than relying on external initialization
I’m not sure I’ve captured what you want, but perhaps this works for you:
actor class C(delegate : Principal) {
public shared ctxt func init() : async () {
assert(ctxt.caller == delegate);
//...
}
}
Main.mo
import Class "Class";
import Principal "mo:base/Principal";
actor Main {
public shared ctxt func new() : async Class.C {
await Class.C(ctxt.caller);
};
public shared func test() : async Text {
let c1 = await new();
await c1.init(); // should succceed, caller is Main
let c2 = await Class.C(Principal.fromActor(c1));
try {
await(c2.init()); // should fail, caller is Main, not c1;
return "fail"
}
catch e {
};
return "ok";
}
}
(beware, the playgound only lets you spawn 5 canister per session, so you may have to reload the example if you call test more than once).
The solution that i ended up using was @infu’s. What i did was dfx canister update-settings flowerCanister --add-controller=<Id-of-canister-that-calls-addflower>
and then in add_flower method i added assert Principal.isController()