Dfinity Examples を動かしてみる (その2 Hello cycles編)
1. Dfinity Examples とは
Dfinityの gitに examples という motokoのサンプルプログラムがある。これを動かして触ってみることで motokoの基本を身につけさせようということだろう。
今回はサイクルの扱いを学ぶために hello cycles というプログラムを動かしてみる
今回はこれをローカルでまず動かして、そのあとIC上のキャニスターで動かしてみたい。
2. 事前準備
事前準備は「その1 calc編」で完了しているので省略。
3. ローカルネットワークでの動作確認
dfx.json
hello_cycles も calcと同じように Main.mo だけのシンプルなプログラムだが、dfx.jsonの内容が少し追加されている。
$ cd hello_cycles
$ cat dfx.json
{
"canisters": {
"hello_cycles": {
"main": "src/hello_cycles/main.mo",
"type": "motoko"
}
},
"defaults": {
"build": {
"packtool": ""
}
},
"dfx": "0.7.2",
"networks": {
"local": {
"bind": "127.0.0.1:8000",
"type": "ephemeral"
}
},
"version": 1
}
うーん、"default" と "networks"、そして "version"が追加されている。これらの設定はあえて必要なのだろうか。とりあえずこのままで進めてみる。
dfx の起動とキャニスターのインストール
$ cd examples/motoko/hello_cycles
$ dfx start
ローカルネットワークを起動し、別ターミナルで、キャニスターを作成。
$ dfx canister create --all
Creating a wallet canister on the local network.
The wallet canister on the "local" network for user "default" is "rwlgt-iiaaa-aaaaa-aaaaa-cai"
Creating canister "hello_cycles"...
"hello_cycles" canister created with canister id: "rrkah-fqaaa-aaaaa-aaaaq-cai"
Walletキャニスターと hello_cyclesキャニスターが作成される。
つづいて、ビルドとインストール。
$ dfx build
$ dfx canister install --all
Creating UI canister on the local network.
The UI canister on the "local" network is "ryjl3-tyaaa-aaaaa-aaaba-cai"
Installing code for canister hello_cycles, with canister_id rrkah-fqaaa-aaaaa-aaaaq-cai
UIキャニスターというのが作成される。そして hello_cyclesキャニスターがインストールされる。UIキャニスターというのはよくわからないが、アクセスするとWebのフォーム画面が出てくる。まあとりあえず、気にしなくていいだろう。
hello_cyclesを動かしてみる
サイクル残高の確認
$ dfx canister call hello_cycles wallet_balance
(4_000_000_000_000)
4Tの残高。wallet_balanceという関数だが、walletではなく、 hello_cyclesキャニスターのサイクル残高を表示している。
デフォルトwalletからサイクルを送信
2TサイクルをデフォルトWalletから hello_cycles canisterに送信
$ dfx canister call $(dfx identity get-wallet) wallet_send "(record { canister = principal \"$(dfx canister id hello_cycles)\"; amount = (2000000000000:nat64); } )"
(variant { 17_724 })
再度残高の確認
$ dfx canister call hello_cycles wallet_balance
(4_000_010_000_000)
残高を確認すると、2T送ったにもかかわらず、10Mしか増えていない。これは wallet_receive 関数で最大 10Mまでしか受け取れないようになっているから。残りは返金される。
今度は逆に、canister から wallet にサイクルを送る。
$ dfx canister call hello_cycles transfer "(func \"$(dfx identity get-wallet)\".\"wallet_receive\", 5000000)"
(record { refunded = 0 })
再度残高の確認
$ dfx canister call hello_cycles wallet_balance
(4_000_005_000_000)
残高が減っている。これで、ローカルネットワークでキャニスター間のサイクルのやり取りができることが確認できた。
4. IC上で動かしてみる
次に、こんどはIC上の実際のキャニスターを使ってサイクルのやりとりを行ってみたい。
ローカルで動かしていた dfx サーバは止めておく。
ICへのインストール
ローカルで動かしているプロジェクトをIC上のキャニスターで動かすためにはどうすればいいかよくわからないので、色々試してみる。
canister_ids.jsonの手動作成
canister_ids.jsonにはその名の通りプロジェクトで利用するキャニスターのIDが入っている。dfx canister create を実行するとこのファイルができ、ローカルの場合は .dfx/local の下に作成される。
今回は canister create をしないので、自動では作成されない。canister create をすると .dfx/ic の下にできると思うが、ためしにプロジェクト直下に作成してみる。
$ cat canister_ids.json
{
"hello_cycles": {
"ic": "wd7ks-taaaa-aaaah-aamca-cai"
}
}
wd7ks-taaaa-aaaah-aamca-cai はすでに使用しているキャニスター。
dfx build
IC上で利用する場合は dfx build に --network ic オプションが必要。
$ dfx build --network ic
Building canisters...
あっさり終わり、.dfx/ic 配下にキャニスターが作成される。
dfx canister install
ICのキャニスターにインストールしてみる。
$ dfx canister --network ic install hello_cycles --mode='reinstall'
Reinstalling code for canister hello_cycles, with canister_id wd7ks-taaaa-aaaah-aamca-cai
ぐはー、みごとに入った。すばらしい。
ICでの動作確認
サイクル残高確認
$ dfx canister --network ic call hello_cycles wallet_balance
(3_897_930_059_369)
残高が表示された。これ合ってるのだろうか。直接スタータスを見てみる。
$ dfx canister --network ic status wd7ks-taaaa-aaaah-aamca-cai
Canister status call result for wd7ks-taaaa-aaaah-aamca-cai.
<Skip>
Balance: 3_899_930_056_247 Cycles
なんか残高に違いがある。なぜだろう。2B違うのはかなりの違いだが。
canister から wallet にサイクルを送る。
残高が合ってないのは不安だが、とりあえずキャニスターからwalletにサイクルを3T送ってみる。
$ dfx canister --network ic call hello_cycles transfer "(func \"$(dfx identity --network ic get-wallet)\".\"wallet_receive\", 3000000000000)"
(record { refunded = 0 })
送れたぽい。残高を確認。
$ dfx canister --network ic call hello_cycles wallet_balance
(897_829_893_766)
3T減っている。次にWalletを確認。
$ dfx canister --no-wallet --network ic status xxxxx-sqaaa-aaaah-aalmq-cai
<SKIP>
Balance: 65_721_728_006_788 Cycles
おお、みごとに増えている!これで不要なキャニスターから貴重なサイクルを取り返すことができるようになった。
5. 関数
定義されている関数の一覧
wallet_balance : () -> async Nat
wallet canister の残高を確認。
The wallet_receive : () -> { amount : Nat64 }
サイクルを受け取る。
The transfer : (shared () -> (), Nat) -> async { refunded : Nat }
任意の共有関数にサイクルを転送する。
Discussion