自然数のインクリメント
このチュートリアルでは、単一の Actor を作成し、カウンターをインクリメントし値の永続性を説明するための、いくつかの基本的な関数を提供するプログラムを書くことになります。
このチュートリアルでは、Actor は Counter
と名付けます。
このプログラムは currentValue
変数を使用して、カウンタの現在値を表す自然数を格納します。
このプログラムは下記の関数呼び出しをサポートします。
-
increment
関数呼び出しは、現在の値を更新し、1 だけ増加させます(戻り値はありません)。 -
get
関数呼び出しは、カウンターの現在値を問い合わせ、返します。 -
set
関数呼び出しは、引数で指定した任意の数値に現在の値を更新します。
このチュートリアルでは、デプロイされた Canister スマートコントラクトの関数を呼び出すことで、カウンターをインクリメントする方法を簡単に説明します。 カウンターの値をインクリメントして照会する関数を複数回呼び出すことで、変数のステートつまり変数の値が、呼び出している間、永続化されることを確認できます。
始める前に
チュートリアルを始める前に、下記を確認してください。
-
Download and install で説明されているように、DFINITY Canister SDK パッケージをダウンロードしインストール済み。
-
コンピュータ上で動作しているローカルの Canister 実行環境をすべて停止済み。
このチュートリアルの所要時間は約 20 分です。
新規プロジェクトを作成する
このチュートリアル用に新しいプロジェクトディレクトリを作成するには
-
ローカルのコンピューターでターミナルシェルをまだ開いていない場合、開きます。
-
Internet Computer プロジェクトで使用しているフォルダがある場合は、そこに移動します。
-
下記のコマンドを実行することで、新規プロジェクトを作成します。
dfx new my_counter
このコマンドは、あなたのプロジェクトに新しい
my_counter
プロジェクトを作成します。 -
下記のコマンドを実行することで、プロジェクトディレクトリに移動します。
cd my_counter
デフォルトの設定を変更する
新規プロジェクトを作成すると、デフォルトの dfx.json
設定ファイルがプロジェクトディレクトリに追加されることは、すでにお分かりでしょう。
このチュートリアルでは、デフォルトの設定を変更することで、プロジェクトのメインプログラムに別の名前を使用します。
設定ファイル dfx.json
を変更するには
-
テキストエディタで
dfx.json
設定ファイルを開き、デフォルトのmain
設定をmain.mo
からincrement_counter.mo
へ変更します。例えば、下記です。
"main": "src/my_counter/increment_counter.mo",
このチュートリアルでは、ソースファイルの名前を
main.mo
からincrement_counter.mo
に変更し、設定ファイルdfx.json
の設定でコンパイルされるソースファイルを決める方法を簡単に説明します。より複雑な Dapp では、依存関係を持つ複数のソースファイルがあり、
dfx.json
設定ファイルの設定を使用して管理する必要があるかもしれません。 このようなシナリオでは、複数の Canister スマートコントラクトとプログラムがdfx.json
ファイルに定義されているので、複数のファイルがすべてmain.mo
という名前になっていると混乱するかもしれません。それ以外のデフォルトの設定はそのままで大丈夫です。
-
変更を保存して
dfx.json
ファイルを閉じて続行します。 -
ソースコードディレクトリ
src
にあるメインプログラムのファイル名を、設定ファイルdfx.json
で指定した名前に合わせ、下記のコマンドを実行することで変更します。mv src/my_counter/main.mo src/my_counter/increment_counter.mo
デフォルトのプログラムを変更する
ここまでのところ、プロジェクトのメインプログラムの名前を変更しただけです。
次のステップは src/my_counter/increment_counter.mo
ファイルのコードを修正して、 Counter
という名前の Actor を定義し、 increment
、get
、set
関数を実装することです。
デフォルトのテンプレートのソースコードを変更するには
-
必要であれば、まだプロジェクトディレクトリにいることを確認します。
-
テキストエディタで
src/my_counter/increment_counter.mo
ファイルを開き、既存の中身を削除します。 -
下記のサンプルコードをコピーして、
increment_counter.mo
ファイルに貼り付けます。// シンプルな Counter Actor を作成する。 actor Counter { stable var currentValue : Nat = 0; // increment 関数でカウンターをインクリメントする。 public func increment() : async () { currentValue += 1; }; // get 関数でカウンター値を読み取る。 public query func get() : async Nat { currentValue }; // set 関数で任意の値を書き込む。 public func set(n: Nat) : async () { currentValue := n; }; }
下記で、このサンプルプログラムを詳しく見てみましょう。
-
この例では、変数
currentValue
の宣言にstable
キーワードが含まれており、ステート(設定、増加、取得が可能な値)を永続化していることがわかります。このキーワードは、プログラムがアップグレードされたときに、変数の値が変更されないことを保証します。
-
変数
currentValue
の宣言は、その型が自然数 (Nat
) であることも指定しています。 -
このプログラムには、2 つのパブリックな更新メソッド
increment
関数とset
関数、1 つの照会メソッドget
関数が含まれています。
stable 変数と flexible 変数の詳細は、 Motoko Programming Language Guide の Stable variables and upgrade methods をご覧ください。
照会と更新の違いについての詳細は、Canisters include both program and state の Query and update methods をご覧ください。
-
-
変更を保存し、ファイルを閉じて続行します。
ローカルの Canister 実行環境を起動する
my_counter
プロジェクトをビルドする前に、Internet Computer ブロックチェーンをシミュレートするローカルの Canister 実行環境 または Internet Computer ブロックチェーンメインネットに接続する必要があります。
ローカルの Canister 実行環境を起動するには dfx.json
ファイルが必要なので、プロジェクトのルートディレクトリにいることを確認する必要があります。
このチュートリアルでは、1つのターミナルでネットワーク操作を開始・確認し、もう1つのターミナルでプロジェクトを管理できるように、別々のターミナルシェルを2つ用意する必要があります。
ローカルの Canister 実行環境を起動するには
-
ローカルのコンピューターで新しいターミナルウィンドウまたはタブを開きます。
-
必要であれば、プロジェクトのルートディレクトリに移動します。
-
2つのターミナル を開く必要があります。
-
現在の作業ディレクトリ は、project ディレクトリ である必要があります。
-
-
下記のコマンドを実行することで、コンピュータのローカルの Canister 実行環境を起動します。
dfx start
ローカルの Canister 実行環境を起動すると、ターミナルにネットワーク操作に関するメッセージが表示されます。
-
ネットワーク操作を表示しているターミナルを開いたままにして、フォーカスを新規プロジェクトを作成した元のターミナルに切り替えてください。
Dapp の登録、ビルド、デプロイを行う
開発環境で動作しているローカルの Canister 実行環境に接続すると、ローカルで Dapp の登録、ビルド、デプロイを行うことができます。
Dapp をローカルにデプロイするには
-
必要であれば、まだプロジェクトのルートディレクトリにいることを確認します。
-
下記のコマンドを実行することで、アプリを登録、ビルド、デプロイします。
dfx deploy
dfx deploy
コマンドの出力は、実行した操作に関する情報を表示します。
デプロイされた Canister スマートコントラクトのメソッドを呼び出す
Canister スマートコントラクトを正常にデプロイしたら、Canister が提供するメソッドを呼び出すエンドユーザーをシミュレートできます。
このチュートリアルでは、カウンターの値を照会する get
メソッド、呼び出されるたびにカウンターを増加させる increment
メソッド、そしてカウンターを指定した任意の値に更新するための引数を渡す set
メソッドを呼び出します。
デプロイされた Canister スマートコントラクトのメソッドを呼び出すテストをするには
-
下記のコマンドを実行して
get
関数を呼び出し、デプロイされた Canister のcurrentValue
変数の現在の値を読み取ります。dfx canister call my_counter get
このコマンドは
currentValue
変数の現在の値 0 を返します。(0 : nat)
-
下記のコマンドを実行して
increment
関数を呼び出し、デプロイされた Canister のcurrentValue
変数の値を1つインクリメントします。dfx canister call my_counter increment
このコマンドは変数の値を増加させ、そのステートを変化させますが、結果は返しません。
-
下記のコマンドを再実行して、デプロイされた Canister の
currentValue
変数の現在値を取得します。dfx canister call my_counter get
このコマンドは、下記の通り、
currentValue
変数の更新された値 1 を返します。(1 : nat)
-
追加のコマンドを実行して、他のメソッドを呼び出したり異なる値を使ったりして、実体験します。
例えば、下記のようなコマンドで、カウンターの値を設定したり、返したりしてみてください。
dfx canister call my_counter set '(987)' dfx canister call my_counter get
これにより、
currentValue
の更新された値 987 を返します。 追加のコマンドを実行します。dfx canister call my_counter increment dfx canister call my_counter get
インクリメントされた
currentValue
988 を返します。
ブラウザー上での関数のテスト
キャニスター・インターフェース記述言語(Candid または IDL と呼ばれることが多い)は、canister スマートコントラクトの署名を指定するための共通言語を提供します。Candid は、異なる言語で書かれていたり、異なるツールでアクセスされる canister スマートコントラクトを扱うための統一された方法を提供します。 例えば、Candid は、基礎となるプログラムが Rust、JavaScript、Motoko のいずれであっても、一貫した表示となります。また、Candid は、dfx コマンドラインインターフェイスや Network Nervous System Dapp などの異なるツールが、サービスに対する共通の記述を共有できるようにします。
Actor の型注釈に基づいて、Candid はテストやデバッグのために canister の関数を呼び出すことができる Web インターフェースも提供しています。
dfx deploy
または dfx canister install
コマンドを使用してプロジェクトをローカルの canister 実行環境にデプロイした後、ブラウザで Candid インターフェイスのエンドポイントにアクセスできます。
この Web インターフェイス(Candid UI)は、サービスの説明を決められた形式で表現しており、フロントエンドのコードを書くことなく、関数をすばやく表示してテストしたり、さまざまなデータタイプを入力して実験したりすることができます。
Candid の Web インターフェースを使って canister の関数をテストするには、以下のようにします:
-
現在のプロジェクトに関連する Candid UI の canister の識別子を、
dfx canister id __Candid_UI
コマンドを使って見つけます。dfx canister id __Candid_UI
このコマンドは、Candid UIの canister 識別子を以下のような出力で表示します。
r7inp-6aaaa-aaaaa-aaabq-cai
-
Candid UI の canister 識別子をクリップボードで使用できるようにコピーします。
-
ローカルの canister 実行環境を停止した場合は、以下のコマンドを実行してローカルで再起動します。
dfx start --background
-
ブラウザを開き、設定ファイルである
dfx.json
で指定されたアドレスとポート番号に移動します。デフォルトでは、ローカルの canister 実行環境は、
127.0.0.1:8000
のアドレスとポート番号にバインドされます。 -
必要な
canisterId
パラメータと、dfx canister id __Candid_UI
コマンドで返される Candid UI の canister 識別子を URL に追加します。例えば、完全な URL は以下のようになりますが、
CANDID-UI-CANISTER-IDENTIFIER
はdfx canister id __Candid_UI
コマンドで返された値になります。http://127.0.0.1:8000/?canisterId=<CANDID-UI-CANISTER-IDENTIFIER>
例えば、上記の Candid UI の canister 識別子の例では、以下のようになります。
http://127.0.0.1:8000/?canisterId=r7inp-6aaaa-aaaaa-aaabq-cai
ブラウザには、canister の識別子を指定するか、Candid の説明(
.did
)ファイルを選択するためのフォームが表示されます。 このフィールドは、対話したい canister の識別子を参照することに注意してください(最後のステップで使用した Candid UI の canister 識別子とは異なります)。 -
テストしたい canister の識別子を「 Provide a canister ID 」フィールドに指定し、「 Go 」をクリックしてサービスの説明を表示します。
使用する canister の識別子がわからない場合は、
dfx canister id
コマンドを実行して、特定の canister 名の識別子を調べることができます。 例えば、my_counter
という名前の canister の識別子を得るには、次のようにします:dfx canister id my_counter
-
Dappで定義されている関数の呼び出しと型のリストを確認します。
-
関数に合った型の値を入力するか、「 Random 」をクリックして値を生成し、「 Call 」または「 Query 」をクリックして結果を確認します。
なお、データ型によっては、Candid インターフェースに、関数をテストするための追加の設定が表示される場合があります。 例えば、関数が配列を取る場合は、値を入力する前に配列のアイテム数を指定する必要があるかもしれません。
+