2.1 「Motoko Advanced」は Ledger Actor を使用して動的にキャニスターを作成します
例:
トピックに直接進みます。次に、Ledger Actor を使用してキャニスターを動的に作成する例を示します。
A.mo のアクター内に B.mo のアクター クラスを動的に作成する場合は、次のようにします。
1. まず Types.mo モジュールを作成し、その中に次のコードを記述します。
module IC{
public type canister_settings = {
freezing_threshold : ?Nat;
controllers : ?[Principal];
memory_allocation : ?Nat;
compute_allocation : ?Nat;
};
public type definite_canister_settings = {
freezing_threshold : Nat;
controllers : [Principal];
memory_allocation : Nat;
compute_allocation : Nat;
};
public type user_id = Principal;
public type wasm_module = [Nat8];
public type canister_id = Principal;
public type ICActor = actor {
canister_status : shared {
canister_id : canister_id } -> async {
status : {
#stopped; #stopping; #running };
memory_size : Nat;
cycles : Nat;
settings : definite_canister_settings;
module_hash : ?[Nat8];
};
create_canister : shared {
settings : ?canister_settings } -> async {
canister_id : canister_id;
};
delete_canister : shared {
canister_id : canister_id } -> async ();
deposit_cycles : shared {
canister_id : canister_id } -> async ();
install_code : shared {
arg : [Nat8];
wasm_module : wasm_module;
mode : {
#reinstall; #upgrade; #install };
canister_id : canister_id;
} -> async ();
provisional_create_canister_with_cycles : shared {
settings : ?canister_settings;
amount : ?Nat;
} -> async {
canister_id : canister_id };
provisional_top_up_canister : shared {
canister_id : canister_id;
amount : Nat;
} -> async ();
raw_rand : shared () -> async [Nat8];
start_canister : shared {
canister_id : canister_id } -> async ();
stop_canister : shared {
canister_id : canister_id } -> async ();
uninstall_code : shared {
canister_id : canister_id } -> async ();
update_settings : shared {
canister_id : Principal;
settings : canister_settings;
} -> async ();
};
}
次に、A.mo に Type を導入します。
import Types "./Types";
2. A.mo と B.mo の両方に次の基本ライブラリ ファイルを導入します。
import Cycles "mo:base/ExperimentalCycles"; //目前为实验版,后续会更新
次のコードを追加します。
public query({
caller}) func cycleBalance() : async Nat{
Cycles.balance()
};
public shared({
caller}) func wallet_receive() : async Nat {
Cycles.accept(Cycles.available())
};
3. レジャー アクターを呼び出して B キャニスターを作成します。
B.mo がおおよそ次のスタイルを持つと仮定します。
//import ...
shared({
caller}) actor class B(installer : Principal) = this{
//...
};
A.mo に次のコードを追加します (コードの一部のみを抽出します)。
import RBT "mo:base/RBTree"; //RB树的库文件
import Nat "mo:base/Nat";
import Principal "mo:base/Principal";
import B "./B.mo";
private stable var b_index : Nat = 0;
private let Bs = RBT.RBTree<Nat, Principal>(Nat.compare); //存储创建的B canister
private let IC : Types.IC.ICActor = actor "aaaaa-aa"; //ledger actor的ID
private let CYCLE_LIMIT = 1_000_000_000_000; //根据需要进行分配
//动态创建canister的函数
public shared({
caller}) func createB() : async Result.Result<Principal, Text>{
Cycles.add(CYCLE_LIMIT);
let b = await B.B(caller);
let principal = Principal.fromActor(b);
await IC.update_settings({
canister_id = principal;
settings = {
freezing_threshold = ?2592000;
controllers = ?[caller]; //A不作为B的控制者的写法
memory_allocation = ?0;
compute_allocation = ?0;
}
});
Bs.put(b_index, principal);
b_index += 1;
#ok(principal)
};
完了。