🌐

Dfinity Examples を動かしてみる (その2 Hello cycles編)

2021/08/11に公開

1. Dfinity Examples とは

Dfinityの gitに examples という motokoのサンプルプログラムがある。これを動かして触ってみることで motokoの基本を身につけさせようということだろう。

今回はサイクルの扱いを学ぶために hello cycles というプログラムを動かしてみる

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