テキスト引数を渡す
このチュートリアルでは、デフォルトプログラムの簡単なバリエーションとして、1つのテキスト引数を1つの Actor に渡し、コードをコンパイルして Canister スマートコントラクトを作成し、その引数を取得することを行います。 このドキュメントでは、Canister スマートコントラクトと Canister という用語は同義語とします。
このチュートリアルでは、Candid インターフェース記述言語(IDL)を使ってターミナルのコマンドラインで引数を渡す方法と、テキスト引数に複数の値を受け取れるようにプログラムを修正する方法を説明します。
始める前に
このチュートリアルを始める前に、以下のことを確認してください:
-
ダウンロードとインストール に記載されている DFINITY Canister SDK パッケージをダウンロードしてインストールしていること
-
ローカルコンピュータ上のすべての Canister 実行環境を止めていること
このチュートリアルの所要時間は20分程度です。
新しいプロジェクトを作成する
このチュートリアルで利用する新しいプロジェクトを作成する手順は以下になります。
-
ローカルコンピュータ上でターミナルシェルを、まだ開いていなければ開きます。
-
別のフォルダを利用しているなら、Internet Computer プロジェクトで使うフォルダに移動します。
-
以下のコマンドを実行して、新しいプロジェクトを作成します。
dfx new location_hello
-
以下のコマンドを実行して、プロジェクトディレクトリに移動します。
cd location_hello
デフォルト設定を変更する
デフォルトプロジェクトを探索する チュートリアルでは、新しいプロジェクトを作成すると、デフォルトの dfx.json
設定ファイルがプロジェクトディレクトリに追加されることを確認しました。
ここではファイルのデフォルト設定を見て、使用したいプロジェクトの設定を正確に反映しているかどうかを常に確認する必要があります。
このチュートリアルでは、デフォルトの設定を変更して、使用しない設定を削除します。
設定ファイル dfx.json
を変更するには以下のようにします。
-
dfx.json
設定ファイルをテキストエディタで開きます。 -
location_hello
プロジェクトのデフォルト設定を確認します。 -
不要な設定をすべて削除します。
このチュートリアルでは、フロントエンドのアセットを作成しないので、ファイルから
location_hello_assets
の設定をすべて削除することができます。 -
変更内容を保存し、ファイルを閉じて次に進みます。
デフォルトプログラムを変更する
デフォルトプロジェクトを探索する チュートリアルでは、新しいプロジェクトを作成すると、デフォルト src
ディレクトリが、テンプレート main.mo
ファイルと共に作成されることがわかりました。
デフォルトのテンプレートソースコードを変更するには以下のようにします。
-
src/location_hello/main.mo
ソースコードファイルをテキストエディタで開きます。 -
デフォルトのソースコードを修正して、
greet
関数をlocation
関数に、name
引数をcity
引数に置き換えます。例:
actor { public func location(city : Text) : async Text { return "Hello, " # city # "!"; }; };
-
変更内容を保存し、ファイルを閉じて次に進みます。
ローカル Canister 実行環境を起動する
プロジェクトをビルドする前に、ローカルの Canister 実行環境か、 Internet Computer ブロックチェーンメインネットに接続する必要があります。
Canister 実行環境をローカルで起動するには、dfx.json
ファイルが必要なので、プロジェクトのルートディレクトリにいることを確認してください。
このチュートリアルでは、2つの独立したターミナルシェルを用意して、1つのターミナルでネットワーク操作を開始・確認し、別のターミナルでプロジェクトを管理できるようにします。
ローカル Canister 実行環境を起動するには以下のようにします。
-
新しいターミナルウィンドウまたはタブを開きます。
-
必要であれば、プロジェクトのルートディレクトリに移動してください。
-
2つのターミナル を開いている必要があります。
-
プロジェクトディレクトリ を カレントワーキングディレクトリ にする必要があります。
-
-
以下のコマンドを実行して、ローカルコンピュータ上で Canister 実行環境を起動します。
dfx start
受信したネットワーク接続を許可するかどうかのプロンプトが表示されたら、Allow をクリックします。
-
ネットワーク操作が表示されているターミナルを開いたまま、プロジェクトを作成した元のターミナルに注目します。
Dapp の登録、ビルド、デプロイ
ローカル Canister 実行環境に接続すると、ローカルで Dapp の登録、ビルド、デプロイを行うことができます。
Dapp をローカルでデプロイするには以下のようにします。
-
必要に応じて、プロジェクトのルートディレクトリにいることを確認します。
-
以下のコマンドを実行して、アプリケーションの登録、ビルド、デプロイを行います。
dfx deploy
dfx deploy
コマンドの出力には、実行する操作に関する情報が表示されます。
テキスト引数を渡す
これで、ローカル Cansiter 実行環境に Canister スマートコントラクト としてプログラムがデプロイされ、dfx canister call
コマンドを使ってプログラムをテストすることができます。
ローカルにデプロイしたプログラムをテストするには以下のようにします。
-
以下のコマンドを実行して、プログラムの中で
location
メソッドを呼び出し、text
型のcity
引数を渡すには、次のコマンドを実行します。dfx canister call location_hello location "San Francisco"
この場合の引数には、
San
とFrancisco
の間にスペースが含まれているため、引数を引用符で囲む必要があります。 このコマンドは以下のような出力を表示します。("Hello, San Francisco!")
引数がスペースを含んでおらず、テキストを引用符で囲む必要がなければ、Candid インターフェース記述言語に次のようにデータ型を推測させることができます。
dfx canister call location_hello location Paris
Candid はデータを
Text
型と推測し、プログラムの出力を以下のようなテキストとして返します。("Hello, Paris!")
-
プログラム内で
location
メソッドを呼び出し、city
の引数をCandid インターフェース記述言語のテキスト引数の構文を使って明示的に渡します。dfx canister call location_hello location '("San Francisco and Paris")'
このコマンドは、以下のような出力を表示します。
("Hello, San Francisco and Paris!")
プログラムは1つのテキスト引数しか受け付けないため、複数の文字列を指定すると最初の引数のみが返されます。
例えば、このコマンドを試してみてください。
dfx canister call location_hello location '("San Francisco","Paris","Rome")'
最初の引数である
("Hello, San Francisco!")
のみが返されます。
プログラムのソースコードを修正する
このチュートリアルで学んだことを発展させるために、ソースコードを修正して異なる結果を返すようにしてみましょう。
例えば、location
関数を修正して、複数の都市名を返すようにしてみましょう。
ソースコードを変更して実験するには以下のようにします。
-
テキストエディタで設定ファイル
dfx.json
を開き、デフォルトのlocation_hello
の設定をfavorite_cities
に変更します。このステップでは、Canister 名と Canister スマートコントラクトのメインプログラムへのパスの両方を、
favorite_cities
を使用するために変更する必要があります。 -
変更内容を保存して、
dfx.json
ファイルを閉じて、次に進みます。 -
以下のコマンドを実行して、
location_hello
のソースファイルディレクトリを、dfx.json
設定ファイルで指定した名前に合わせてコピーします。cp -r src/location_hello src/favorite_cities
-
テキストエディターで
src/favorite_cities/main.mo
ファイルを開きます。 -
以下のコードサンプルをコピー&ペーストして、
location
関数を2つの新しい関数で置き換えます。例:
actor { public func location(cities : [Text]) : async Text { return "Hello, from " # (debug_show cities) # "!"; }; public func location_pretty(cities : [Text]) : async Text { var str = "Hello from "; for (city in cities.vals()) { str := str # city #", "; }; return str # "bon voyage!"; } };
このコード例では、
Text
が角括弧([ ]
)で囲まれていることにお気づきかもしれません。Text
それ自体は UTF-8 の文字の集まりを表しています。 角括弧で囲まれた型は、その型が 配列 であることを示しています。 したがって、この文脈では、[Text]
は、UTF-8 文字の集まりの配列を示し、プログラムが複数のテキスト文字列を受け入れて返すことができるようになります。また、このコードサンプルでは、配列に対する
apply
処理の基本的なフォーマットを使用しており、次のように抽象化することができます。public func apply<A, B>(fs : [A -> B], xs : [A]) : [B] { var ys : [B] = []; for (f in fs.vals()) { ys := append<B>(ys, map<A, B>(f, xs)); }; ys; };
-
以下のコマンドを実行して、Dapp を登録、ビルド、デプロイします。
dfx deploy
-
以下のコマンドを実行して、プログラムの中で
location
メソッドを呼び出し、city
引数を Candid インターフェース記述の構文を使って渡します。dfx canister call favorite_cities location '(vec {"San Francisco";"Paris";"Rome"})'
このコマンドは、Candid インターフェース記述の構文にある
(vec { val1; val2; val3; })
を用いて、値のベクトルを返します。 インターフェイス記述言語 Candid の詳細については、Candid 言語ガイドをご覧ください。このコマンドは、以下のような出力を表示します。
("Hello, from ["San Francisco", "Paris", "Rome"]!")
-
以下のコマンドを実行して、プログラムの中で
location_pretty
メソッドを呼び出し、インターフェイス記述の構文を使ってcity
の引数を渡します。dfx canister call favorite_cities location_pretty '(vec {"San Francisco";"Paris";"Rome"})'
このコマンドは、以下のような出力を表示します。
("Hello from San Francisco, Paris, Rome, bon voyage!")
ブラウザー上での関数のテスト
キャニスター・インターフェース記述言語(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 インターフェースに、関数をテストするための追加の設定が表示される場合があります。 例えば、関数が配列を取る場合は、値を入力する前に配列のアイテム数を指定する必要があるかもしれません。
+ この例では、各関数はテキスト文字列の配列を受け取ります。そのため、まず配列の長さを選択し、各項目に値を設定してから Call をクリックします。
+