自然数のインクリメント

このチュートリアルでは、単一の Actor を作成し、カウンターをインクリメントし値の永続性を説明するための、いくつかの基本的な関数を提供するプログラムを書くことになります。

このチュートリアルでは、Actor は Counter と名付けます。 このプログラムは currentValue 変数を使用して、カウンタの現在値を表す自然数を格納します。 このプログラムは下記の関数呼び出しをサポートします。

  • increment 関数呼び出しは、現在の値を更新し、1 だけ増加させます(戻り値はありません)。

  • get 関数呼び出しは、カウンターの現在値を問い合わせ、返します。

  • set 関数呼び出しは、引数で指定した任意の数値に現在の値を更新します。

このチュートリアルでは、デプロイされた Canister スマートコントラクトの関数を呼び出すことで、カウンターをインクリメントする方法を簡単に説明します。 カウンターの値をインクリメントして照会する関数を複数回呼び出すことで、変数のステートつまり変数の値が、呼び出している間、永続化されることを確認できます。

始める前に

チュートリアルを始める前に、下記を確認してください。

  • Download and install で説明されているように、DFINITY Canister SDK パッケージをダウンロードしインストール済み。

  • コンピュータ上で動作しているローカルの Canister 実行環境をすべて停止済み。

このチュートリアルの所要時間は約 20 分です。

新規プロジェクトを作成する

このチュートリアル用に新しいプロジェクトディレクトリを作成するには

  1. ローカルのコンピューターでターミナルシェルをまだ開いていない場合、開きます。

  2. Internet Computer プロジェクトで使用しているフォルダがある場合は、そこに移動します。

  3. 下記のコマンドを実行することで、新規プロジェクトを作成します。

    dfx new my_counter

    このコマンドは、あなたのプロジェクトに新しい my_counter プロジェクトを作成します。

  4. 下記のコマンドを実行することで、プロジェクトディレクトリに移動します。

    cd my_counter

デフォルトの設定を変更する

新規プロジェクトを作成すると、デフォルトの dfx.json 設定ファイルがプロジェクトディレクトリに追加されることは、すでにお分かりでしょう。 このチュートリアルでは、デフォルトの設定を変更することで、プロジェクトのメインプログラムに別の名前を使用します。

設定ファイル dfx.json を変更するには

  1. テキストエディタで 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 という名前になっていると混乱するかもしれません。

    それ以外のデフォルトの設定はそのままで大丈夫です。

  2. 変更を保存して dfx.json ファイルを閉じて続行します。

  3. ソースコードディレクトリ src にあるメインプログラムのファイル名を、設定ファイル dfx.json で指定した名前に合わせ、下記のコマンドを実行することで変更します。

    mv src/my_counter/main.mo src/my_counter/increment_counter.mo

デフォルトのプログラムを変更する

ここまでのところ、プロジェクトのメインプログラムの名前を変更しただけです。 次のステップは src/my_counter/increment_counter.mo ファイルのコードを修正して、 Counter という名前の Actor を定義し、 incrementgetset 関数を実装することです。

デフォルトのテンプレートのソースコードを変更するには

  1. 必要であれば、まだプロジェクトディレクトリにいることを確認します。

  2. テキストエディタで src/my_counter/increment_counter.mo ファイルを開き、既存の中身を削除します。

  3. 下記のサンプルコードをコピーして、 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 GuideStable variables and upgrade methods をご覧ください。

    照会と更新の違いについての詳細は、Canisters include both program and stateQuery and update methods をご覧ください。

  4. 変更を保存し、ファイルを閉じて続行します。

ローカルの Canister 実行環境を起動する

my_counter プロジェクトをビルドする前に、Internet Computer ブロックチェーンをシミュレートするローカルの Canister 実行環境 または Internet Computer ブロックチェーンメインネットに接続する必要があります。

ローカルの Canister 実行環境を起動するには dfx.json ファイルが必要なので、プロジェクトのルートディレクトリにいることを確認する必要があります。 このチュートリアルでは、1つのターミナルでネットワーク操作を開始・確認し、もう1つのターミナルでプロジェクトを管理できるように、別々のターミナルシェルを2つ用意する必要があります。

ローカルの Canister 実行環境を起動するには

  1. ローカルのコンピューターで新しいターミナルウィンドウまたはタブを開きます。

  2. 必要であれば、プロジェクトのルートディレクトリに移動します。

    • 2つのターミナル を開く必要があります。

    • 現在の作業ディレクトリ は、project ディレクトリ である必要があります。

  3. 下記のコマンドを実行することで、コンピュータのローカルの Canister 実行環境を起動します。

    dfx start

    ローカルの Canister 実行環境を起動すると、ターミナルにネットワーク操作に関するメッセージが表示されます。

  4. ネットワーク操作を表示しているターミナルを開いたままにして、フォーカスを新規プロジェクトを作成した元のターミナルに切り替えてください。

Dapp の登録、ビルド、デプロイを行う

開発環境で動作しているローカルの Canister 実行環境に接続すると、ローカルで Dapp の登録、ビルド、デプロイを行うことができます。

Dapp をローカルにデプロイするには

  1. 必要であれば、まだプロジェクトのルートディレクトリにいることを確認します。

  2. 下記のコマンドを実行することで、アプリを登録、ビルド、デプロイします。

    dfx deploy

    dfx deploy コマンドの出力は、実行した操作に関する情報を表示します。

デプロイされた Canister スマートコントラクトのメソッドを呼び出す

Canister スマートコントラクトを正常にデプロイしたら、Canister が提供するメソッドを呼び出すエンドユーザーをシミュレートできます。 このチュートリアルでは、カウンターの値を照会する get メソッド、呼び出されるたびにカウンターを増加させる increment メソッド、そしてカウンターを指定した任意の値に更新するための引数を渡す set メソッドを呼び出します。

デプロイされた Canister スマートコントラクトのメソッドを呼び出すテストをするには

  1. 下記のコマンドを実行して get 関数を呼び出し、デプロイされた Canister の currentValue 変数の現在の値を読み取ります。

    dfx canister call my_counter get

    このコマンドは currentValue 変数の現在の値 0 を返します。

    (0 : nat)
  2. 下記のコマンドを実行して increment 関数を呼び出し、デプロイされた Canister の currentValue 変数の値を1つインクリメントします。

    dfx canister call my_counter increment

    このコマンドは変数の値を増加させ、そのステートを変化させますが、結果は返しません。

  3. 下記のコマンドを再実行して、デプロイされた Canister の currentValue 変数の現在値を取得します。

    dfx canister call my_counter get

    このコマンドは、下記の通り、currentValue 変数の更新された値 1 を返します。

    (1 : nat)
  4. 追加のコマンドを実行して、他のメソッドを呼び出したり異なる値を使ったりして、実体験します。

    例えば、下記のようなコマンドで、カウンターの値を設定したり、返したりしてみてください。

    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 の関数をテストするには、以下のようにします:

  1. 現在のプロジェクトに関連する Candid UI の canister の識別子を、dfx canister id __Candid_UI コマンドを使って見つけます。

    dfx canister id __Candid_UI

    このコマンドは、Candid UIの canister 識別子を以下のような出力で表示します。

    r7inp-6aaaa-aaaaa-aaabq-cai
  2. Candid UI の canister 識別子をクリップボードで使用できるようにコピーします。

  3. ローカルの canister 実行環境を停止した場合は、以下のコマンドを実行してローカルで再起動します。

    dfx start --background
  4. ブラウザを開き、設定ファイルである dfx.json で指定されたアドレスとポート番号に移動します。

    デフォルトでは、ローカルの canister 実行環境は、127.0.0.1:8000 のアドレスとポート番号にバインドされます。

  5. 必要な canisterId パラメータと、dfx canister id __Candid_UI コマンドで返される Candid UI の canister 識別子を URL に追加します。

    例えば、完全な URL は以下のようになりますが、CANDID-UI-CANISTER-IDENTIFIERdfx 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 識別子とは異なります)。

  6. テストしたい canister の識別子を「 Provide a canister ID 」フィールドに指定し、「 Go 」をクリックしてサービスの説明を表示します。

    使用する canister の識別子がわからない場合は、dfx canister id コマンドを実行して、特定の canister 名の識別子を調べることができます。 例えば、my_counter という名前の canister の識別子を得るには、次のようにします:

    dfx canister id my_counter
  7. Dappで定義されている関数の呼び出しと型のリストを確認します。

  8. 関数に合った型の値を入力するか、「 Random 」をクリックして値を生成し、「 Call 」または「 Query 」をクリックして結果を確認します。

    なお、データ型によっては、Candid インターフェースに、関数をテストするための追加の設定が表示される場合があります。 例えば、関数が配列を取る場合は、値を入力する前に配列のアイテム数を指定する必要があるかもしれません。

+ Counter functions

ローカルの Canister 実行環境を停止する

Dapp の実体験が終わったら、バックグラウンドで実行し続けないように、ローカルの Canister 実行環境を停止できます。

ローカルの Canister 実行環境を停止するには

  1. ネットワーク操作を表示するターミナルで、Control-C を押して、ローカルの Canister 実行環境を中断します。

  2. 下記のコマンドを実行して、ローカルの Canister 実行環境を停止します。

    dfx stop