Create canister and install code with wasm_module

Hello.
I can create the canister(s) using the new operation, referring to the actor class

Variant №1
Example: (very roughly and briefly)

actor class ObjectActor() = this{};
let oa: = await ObjectActor();
//ID new canister
let p: = Principal.fromActor(oa);

Variant №2
I can also create an empty canister. And use it when necessary.
Example:

public func create_canister_empty_with_cycles(settings: ?canister_settings, amount : ?Nat)
      : async { canister_id : canister_id } { 
            ExperimentalCycles.add(100_000_000_000); 
            let canister_new_with_cycles = 
                  await IC.provisional_create_canister_with_cycles({ settings : ?canister_settings; amount : ?Nat;});

  return canister_new_with_cycles
};

Next, using template in the specification.
Apparently, I can update an empty (and not empty) canister. I use the canister_id obtained above.

install_code : shared {
arg : [Nat8];
wasm_module : wasm_module;
mode : { #reinstall; #upgrade; #install };
canister_id : canister_id;
} → async ();

Question: how do I compile the code of the actor class(ObjectActor) in wasm_module?
Is it possible to use it dynamically in the IC today?

You can compile the actor class to suitable wasm just by passing it as the root file to the moc compiler (or making it the main file of a dfx actor).

You’re main difficulty will then be quoting the code (and its serialized argument) as a couple of blobs in Motoko to pass to IC.install_code We don’t currently expose an official way for users to to serialize shared types to blobs.

(FTR: the way the compiler currently compiles an actor that imports an actor class is to recursively invoke the compiler on the actor class, embed the binary of the class as a blob in the importer, and compile a helper function for the class constructor that serializes the argument to a blob, creates and installs a new actor with the new blob and then casts the principal to the expected interface.)

3 Likes

Hi, Claudio. Thanks. The problem was adding cycles, but I solved it. I realized that it is better to use standard methods. Apparently, if you update the wasm code with install_code (wash_module), the built-in logic of the actor’s work ( functions, properties)it will be unavailable for calls from outside it.

Excuse me, is there a way to convert wasm to blob now? Our business needs this install_code function very much

We haven’t added anything to give you access to the wasm blob of an imported actor class.

If you already have the wasm on disk, you can try to (manually) encode it as a blob literal.
There some examples of using Text literals constrained to type Blob to introduce blobs here:

Unfortunately, we don’t have any direct way to include a file as a Text or Blob literal, but could conceivably add that in future.

There a simple example in our tests of installing a miminal wasm file constructed from blob literal here.

1 Like

If you want to do this on the client side, you can use ic-repl, see the install.sh example: GitHub - chenyan2002/ic-repl

Thanks, let me see
This can bring me a lot of banzhu

I tried to convert wasm to blob format, but because the program was too large, the blob data reached 1.2m and the program could not be executed.
I want to use the motoko code method to perform code update and installation operations

1 Like

+1 for this request - I too would love to be able to add a function in a Motoko canister that installs another Motoko canister.

I believe you can with actor classes. See this.

The catch is that the Motoko canister that’s being installed needs to be defined in source at compile time and imported by the “parent” Motoko canister.

There’s no way to dynamically install a Motoko canister, i.e. with arbitrary wasm passed in at runtime. At least that’s my understanding of this thread…

2 Likes

Aha! This is exactly what I was looking for - thank you!

As a follow-up here - how can one add a controller (rather than set a controller) for a newly-created canister, similar to what’s described here?

(Or even better, is it possible to specify controllers when creating a canister from Motoko in the first place?)

I think this may have been a silly question, as it looks like the example provided above demonstrates setting multiple controllers. Assuming this is correct, please disregard!

1 Like

Hi @claudio,

I need to update a canister’s actor class that was dynamically created by another canister and I’m just wondering how to do this.

I have a function that takes a wasm module:


    public func updateManagerCanisterWasm() : async () {
      let IC : Management.Management = actor (Environment.Default);
      let updateResult = await (
        IC.install_code(
          {
            mode = #upgrade(null);
            canister_id = Principal.fromText("ljxqq-4iaaa-aaaal-qjd4a-cai");
            wasm_module = "";
            arg = Blob.fromArray([]);
            sender_canister_version = null;
          }),
      );
    };

But I need this file:

for the wasm_module property…

Any help appreciated.

Sorry for the delay, I’m on holiday without a laptop.

There is way to do this, briefly described here, but without any examples:

A bad example from our tests is this line

But the test isn’t really meant for user consumption…