本文主要是介绍dfinity开发——动态创建Canister与Canister的控制器管理,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
前言
这是dfinity中动态创建Canister例子,就是在A.mo 的actor中动态创建B.mo中的actor类。
项目
1.首先创建一个项目
dfx new CanisterMGT
2.启动项目
cd CanisterMGT
dfx start --clean
3.在项目下创建types.mo 和 sub.mo文件
4.types.mo是canister所需要的类型和属性,添加如下代码:
module{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 : { controllers : [Principal] };//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 ();};
}
5.sub.mo是接下要在main.mo里面创建的canistet,sub.mo里面的代码就是它自身要实现的代码,但cycleBalance() 和wallet_receive()这两个属性是必须要添加在里面的,有必要也添加下canister的升级代码。
import Cycles "mo:base/ExperimentalCycles";
import Nat "mo:base/Nat";shared({caller}) actor class Sub(installer : Principal) = this
{public query({caller}) func cycleBalance() : async Nat{Cycles.balance()};public shared({caller}) func wallet_receive() : async Nat {Cycles.accept(Cycles.available())};public shared query ({caller}) func whoami() : async Principal {caller};stable var counter = 0;public query func get() : async Nat{return counter;};public func inc() : async () {counter += 1;};
}
6.main.mo是创建canister的代码
import Types "./types";
import Cycles "mo:base/ExperimentalCycles";
import RBT "mo:base/RBTree";
import Nat "mo:base/Nat";
import Principal "mo:base/Principal";
import Sub "./sub";
import Array "mo:base/Array";actor Self
{public type canister_info = {canister_id : Principal;id:Nat;};//获取当前pidpublic shared query ({caller}) func whoami() : async Principal {caller};//获取当前canister idpublic shared query ({caller}) func getCanisterId() : async Principal{Principal.fromActor(Self);};//记录创建的canister个数private stable var subs_index : Nat = 0;private let subs = RBT.RBTree<Nat, Principal>(Nat.compare); //存储创建的sub canisterprivate let IC : Types.ICActor = actor "aaaaa-aa"; private let CYCLE_LIMIT = 50; //创建canister要分配的cycle//动态创建canister的函数,返回创建的canisister idpublic shared({caller}) func createSub() : async canister_info{Cycles.add(CYCLE_LIMIT);let sub = await Sub.Sub(caller);let principal = Principal.fromActor(sub);await IC.update_settings({canister_id = principal;settings = {freezing_threshold = ?20;controllers = ?[principal]; //控制器是它自身memory_allocation = ?0;compute_allocation = ?0;}});subs.put(b_index, principal);subs_index += 1;let canister_info = {canister_id = principal;id = subs_index;}};//获取canister的控制器public func get_controllers(canister_id : Principal) : async [Principal] {let status = await IC.canister_status({ canister_id = canister_id });return status.settings.controllers;};
};
7.运行项目
dfx deploy
8.调用创建canister的接口
dfx canister call CanisterMGT createSub
动态创建第一个canister
(base) dalao@dalaodeMacBook-Pro CanisterMGT % dfx canister call CanisterMGT createSub
(record { id = 1 : nat; canister_id = principal "r7inp-6aaaa-aaaaa-aaabq-cai" })
9.现在来访问新创建的这个canister里面的属性
查看cycles,这50个是刚刚转进去的
(base) dalao@dalaodeMacBook-Pro CanisterMGT % dfx canister call r7inp-6aaaa-aaaaa-aaabq-cai cycleBalance
(50 : nat)
计数
base) dalao@dalaodeMacBook-Pro CanisterMGT % dfx canister call r7inp-6aaaa-aaaaa-aaabq-cai get
(0 : nat)
(base) dalao@dalaodeMacBook-Pro CanisterMGT % dfx canister call r7inp-6aaaa-aaaaa-aaabq-cai inc
()
(base) dalao@dalaodeMacBook-Pro CanisterMGT % dfx canister call r7inp-6aaaa-aaaaa-aaabq-cai get
(1 : nat)
(base) dalao@dalaodeMacBook-Pro CanisterMGT % dfx canister call r7inp-6aaaa-aaaaa-aaabq-cai inc
()
(base) dalao@dalaodeMacBook-Pro CanisterMGT % dfx canister call r7inp-6aaaa-aaaaa-aaabq-cai get
(2 : nat)
然后再创建一个canister
(base) dalao@dalaodeMacBook-Pro CanisterMGT % dfx canister call CanisterMGT createSub
(record { id = 2 : nat; canister_id = principal "rkp4c-7iaaa-aaaaa-aaaca-cai" })
访问里面的属性
(base) dalao@dalaodeMacBook-Pro CanisterMGT % dfx canister call rkp4c-7iaaa-aaaaa-aaaca-cai get
(0 : nat)
(base) dalao@dalaodeMacBook-Pro CanisterMGT % dfx canister call rkp4c-7iaaa-aaaaa-aaaca-cai inc
()
(base) dalao@dalaodeMacBook-Pro CanisterMGT % dfx canister call rkp4c-7iaaa-aaaaa-aaaca-cai get
(1 : nat)
(base) dalao@dalaodeMacBook-Pro CanisterMGT %
10.查看控制状态
如果canister当前只有一个控制器,它是拒绝外部访问它的控制器
(base) dalao@dalaodeMacBook-Pro CanisterMGT % dfx canister call CanisterMGT get_controllers '(principal "r7inp-6aaaa-aaaaa-aaabq-cai")'
Error: The Replica returned an error: code 4, message: "Only the controllers of the canister r7inp-6aaaa-aaaaa-aaabq-cai can control it.
Canister's controllers: r7inp-6aaaa-aaaaa-aaabq-cai
Sender's ID: rrkah-fqaaa-aaaaa-aaaaq-cai"
11.创建canister分配过去的cycle记得回收,我在测试的时创建一堆canister之后,退出环境之后才记得没有回收cycle,现在还在找办法找回来。
这篇关于dfinity开发——动态创建Canister与Canister的控制器管理的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!