Canister creating another canister in mainnet using a certain number of Cycles

Greetings everyone! In an instance where a canister would create another canister in mainnet. I always get an issue that there are not enough cycles to create a canister. With this issue how could I create a canister multiple times. An example would be the code below.

Canister A creating Canister B

try {
                    Cycles.add(1_500_000_000_000);
                    let newDirectoryActor = await ConsumerDirectoryClass.ConsumerDirectory();
                    let directoryActorId : Principal = await newDirectoryActor.consumerDirectory_getCanisterId();
                    let adminCanister : Principal = await AdminApp.admin_getPrincipal();
                    await ICUTIL.updateCanisterSettings(directoryActorId, [adminAccount, adminCanister, Principal.fromActor(ConsumerApp)]);
                    await ICUTIL.depositCycles(Principal.fromActor(ConsumerApp));
                    await AdminApp.admin_createCanister(directoryActorId, #consumerDirect);
                    Debug.print(debug_show(directoryActorId));
                    consumer_directoryCount := consumer_directoryCount + 1;
                    listOfConsumerDirectory := List.push<ConsumerDirectoryClass.ConsumerDirectory>(newDirectoryActor, listOfConsumerDirectory);
                } catch (e) {
                    return #err(Error.message(e));
                };

Canister B will try to create Canister C but it fails

                    try {
                        Cycles.add(150_000_000_000);
                        let newConsumerActor = await ConsumerActorClass.ConsumerDatabase(consumerId, firstName, lastName, birthday, country, email, profilePicture);
                        let newConsumerId : CanisterId = await newConsumerActor.consumer_getCanisterId();
                        let adminCanister : Principal = await AdminApp.admin_getPrincipal();
                        await ICUTIL.updateCanisterSettings(newConsumerId, [adminCanister, adminAccount, Principal.fromActor(cannister_self)]);
                        await ICUTIL.depositCycles(Principal.fromActor(cannister_self));
                        await AdminApp.admin_createCanister(newConsumerId, #consumerData);
                        mapOfConsumer.put(consumerId, newConsumerActor);
                        Debug.print(debug_show (newConsumerId));
                        return #ok(newConsumerId);
                    } catch (e) {
                        return #err(Error.message(e));
                    };

Is there a way for canister C to be created, I place 2T cycles already and based on computation in “Cycles.add” it is already enough to create a couple of canister C. Thank you very much!

I’m trying to do something similar in this actor, which by executing a public function, must create a canister of type client.

import Client “Client”;
actor Factory {
public shared ({caller}) func createClient(ammount: Nat): async Client.Client {
let client = await Client.Client(caller);
return client;
};
}

And it throws me this error:

Call was rejected:
Request ID: 8e45fe5e7cd26500bfd61c88ea51e0c04a86745c7b43614ee8d6be2b08805abc
Reject code: 4
Reject text: Creating a canister requires a fee of 7_692_307_692 that is deducted from the canister’s initial balance but only 0 cycles were received with the create_canister request.
Have you been able to make any progress towards the solution?

This seems to have solved my cyclos problem but in my case I still have problems of another type. Apparently the “services” can only contain functions and in the actors that I want to create I also need them to have some state variables

Hi this code actually solved the problem. Thank you very much! May I know if it’s mutable or immutable? Usually for this situation, I create another function inside the other canister then I would just call them.

Example:

Factory

let client = await Client.Client(caller);
await client.function_name(arg_x : type_x)

Client

public func(arg_x: type_x) : async () {
    value := arg_x;
}
1 Like

The canister creation is relatively simple - you can use the ExperimentalCycles API to add cycles to the call before making it.

The more complicated issue is how you manage the canisters that have been created. I think a proper example would demonstrate

  • Deleting and reclaiming cycles
  • Upgrading child canisters
  • Using the Management Canister’s check_status api

Hi kpeacock! ExperimentalCycles only works on local deployment. Deployment in the IC would require a different method as mentioned by ArielRobotti. :slight_smile: