はじめに
本連載では、カスタムブロックチェーンを構築するためのフレームワークであるSubstrateの概要と使い方について、全6回で解説します。
第4回では、Polkadotjsを用いたクライアント操作や、JavaScriptでSubstrateのノードと通信する機能の実装をおこないます。
本記事は、過去にコンセンサス・ベイスが主宰していたオンラインサロンの記事です。記事は2017年~2018年にかけて執筆されたため、一部は、既に古くなっている可能性があります。あらかじめご了承ください。
Polkadot/api-cliを用いたSubstrate操作
Substrateのカスタムチェーンと通信を行なうために、polkadot-jsと呼ばれるPolkadot/SubstrateのためのJavaScript製のツール・ライブラリがあります。polkadot-jsを用いることで、WebやコマンドラインからSubstrateチェーンにアクセスするためのアプリケーションを実装することがでいます。
まず、polkadot-jsのAPI clientを用いて、コマンドラインからSubstrateのカスタムチェーンにアクセスしてみましょう。
Clientを用いる前に、ローカル環境でSubstrateのノードを起動しておきます。
コマンド1. substrate devチェーンの起動
$ substrate --dev
インストール
Polkadot/api-cliの利用方法はいくつかありますが、ここではpolkadot-js/toolをローカルにインストールする方法を紹介します。
Substrateを起動しているコンソールとは別のコンソールを立ち上げ、コマンド2を入力してください。事前に、JavaScriptパッケージマネージャーであるyarnをインストールしておいてください。
コマンド2. polkadot-js/toolのインストール
$ git clone https://github.com/polkadot-js/tools.git
$ cd tools
$ yarn instal
polkadot-js/toolのインストールが完了すると、コマンド3の形式で、API clientを利用することができます。
コマンド3. api-cliの使い方
$ yarn run:api [options] <...params>
続いて、API clientの具体的な使い方を見てみましょう。
残高の取得
Substrate上のアカウントのUnit残高を取得するには、
コマンド4. AliceのUnit残高の取得
$ yarn run:api query.balances.freeBalance \
5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY
yarn run v1.15.2
$ ./packages/api-cli/src/index.js query.balances.freeBalance 5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY
{
"freeBalance": 1048576
}
✨ Done in 1.38s.
通信が成功すると、Aliceの残高がJSON形式で取得できます。
トランザクションの発行
続いて、AliceからBobにUnitを送金するトランザクションを発行してみましょう。Balanceを操作するトランザクションの発行には、
コマンド5. AliceからBobに10000 Unitsを送金
$ yarn run:api tx.balances.transfer \
5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty 10000 \
--seed "//Alice"
yarn run v1.15.2
$ ./packages/api-cli/src/index.js tx.balances.transfer 5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty 10000 --seed //Alice
{
"transfer": {
"events": [],
"status": {
"Ready": null
}
}
}
{
"transfer": {
"events": [
{
"phase": {
"ApplyExtrinsic": 2
},
"event": {
"index": "0x0202",
"data": [
"5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY",
"5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty",
10000,
0
]
},
"topics": []
},
{
"phase": {
"ApplyExtrinsic": 2
},
"event": {
"index": "0x0000",
"data": []
},
"topics": []
}
],
"status": {
"Finalized": "0x3bb9839e62c6b3dc28d9a624e410ae2e788aef79592ae33cbf68eb921c2c8bbe"
}
}
}
✨ Done in 2.11s.
トランザクションが成功すると、transferのイベントやステータス情報がJSON形式で確認できます。
Polkadot/apiを用いたアプリケーション開発
APIクライアントの使い方が分かったところで、Polkadot/apiを組み込んだ独自アプリケーションの開発に挑戦してみましょう。
本稿では、空のプロジェクトにpolkadot/apiモジュールをインポートして利用する方法を紹介します。
プロジェクトの作成
まず、コマンド6を用いて、yarnの新規プロジェクトを初期化し、polkadot/apiモジュールをインポートします。サンプルコード用のファイルとして、空のindex.jsも作成しています。
コマンド6. polkadot/apiを組み込んだプロジェクトの作成
$ mkdir myproject
$ cd myproject
$ yarn init
yarn init v1.15.2
question name (myproject):
question version (1.0.0):
question description:
question entry point (index.js):
question repository url:
question author:
question license (MIT):
question private:
success Saved package.json
$ yarn add @polkadot/api@0.80.1
$ touch index.js
コネクションの確立とチェーンの情報取得
プロジェクトの作成が完了したら、さきほど作成した index.js ファイルをエディタで開き、コード1 の内容を記述します。
コード1では、ローカルで立ち上げているSubstrateノードに対して ws://127.0.0.1:9944 のエンドポイントでapiオブジェクトを作成し、通信を確立しています。apiを通じて情報を取得する場合、非同期通信となるため、async functionやawaitを用いています。
コード1. index.js: ノードとのコネクションの確立とチェーンの情報取得
const { ApiPromise, WsProvider } = require('@polkadot/api');
async function main () {
const provider = new WsProvider('ws://127.0.0.1:9944');
const api = await ApiPromise.create(provider);
const chain = await api.rpc.system.chain();
console.log(`You are connected to chain ${chain}`);
}
main().catch(console.error).finally(() => process.exit());
index.jsの編集が完了したら、コンソールからコマンド7を用いてプログラムを実行してみましょう。正しくノードに接続できれば、立ち上げているチェーンの名前(Development)の表示がされます。
コマンド7. index.jsの実行と結果表示
$ node index.js
You are connected to chain Development
残高の取得
続いて、Aliceの残高を取得するプログラムをコード2に示します。コード1と同様に、index.jsを編集してコード2の内容を記述してください。
コード2. index.js: Aliceの残高を取得
const { ApiPromise, WsProvider } = require('@polkadot/api');
const Alice = '5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY';
async function main () {
const provider = new WsProvider('ws://127.0.0.1:9944');
const api = await ApiPromise.create(provider);
let balance = await api.query.balances.freeBalance(Alice);
console.log(`Alice`);
console.log(` address: ${Alice}`);
console.log(` balance: ${balance}`);
}
main().catch(console.error).finally(() => process.exit());
さきほどと同様に、コマンド8でindex.jsを実行すると、Aliceのアドレスと残高が表示されるはずです。
コマンド8. index.jsの実行とAliceの残高表示
$ node index.js
Alice
address: 5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY
balance: 1038575
残高の監視
プログラムの実行時だけでなく、アカウントの残高を監視し、変更があった場合にアクションを実行することもできます。
コード3に示すとおり、残高を取得するapiの引数にコールバック関数を指定すると、残高の変更があった場合にコールバック関数を実行できます。
プログラムがすぐに終了しないよう、コード1, 2と比較して最終行のfinally()関数の呼び出しがなくなっていることにも注意してください。
コード3. index.js: Aliceの残高監視とコールバック関数の設定
const { ApiPromise, WsProvider } = require('@polkadot/api');
const Alice = '5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY';
async function main () {
const provider = new WsProvider('ws://127.0.0.1:9944');
const api = await ApiPromise.create(provider);
api.query.balances.freeBalance(Alice, (balance) => {
console.log(`Alice`);
console.log(` address: ${Alice}`);
console.log(` balance: ${balance}`);
});
}
main().catch(console.error);
コマンド9を用いてindex.jsを実行し、第3回で紹介したSubstrate/ Polkadot Potral(https://polkadot.js.org/apps/#/explorer)にブラウザでアクセスしてトランザクションを発行するか、本稿のコマンド5などを用いてAliceの残高を更新してみてください。ここでは、BobからAliceに10000 Unitsの送金をおこなった場合の実行例を示しています。
コマンド9. index.jsの実行とAliceの残高監視
$ node index.js
Alice
address: 5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY
balance: 1038575
Alice
address: 5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY
balance: 1048575
上記のプログラムは常に起動し続けるため、終了する場合は「Ctrl + C」などでプログラムを終了してください。
送金の実行
最後に、api経由で送金トランザクションの発行を試してみましょう。コード4に、AliceからBobに10000 Unitsを送金するコード例を示します。コード3と同様に、Bobの残高を監視して、更新があった場合に表示するようにしています。
送金をおこなうには、Keyringモジュールを用いて送金者(Alice)の鍵をインポートし、トランザクションを作成したあとに送金者のアカウントで署名をおこないます。
コード4. index.js: AliceからBobに送金
const { ApiPromise, WsProvider } = require('@polkadot/api');
const { Keyring } = require('@polkadot/keyring');
const Bob = '5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty';
async function main () {
const provider = new WsProvider('ws://127.0.0.1:9944');
const api = await ApiPromise.create(provider);
api.query.balances.freeBalance(Bob, (balance) => {
console.log(`Bob`);
console.log(` address: ${Bob}`);
console.log(` balance: ${balance}`);
});
const keyring = new Keyring({ type: 'sr25519' });
const alice = keyring.addFromUri('//Alice');
const transfer = api.tx.balances.transfer(Bob, 10000);
const hash = await transfer.signAndSend(alice);
console.log('Transfer sent with hash', hash.toHex());
}
main().catch(console.error);
コード4の実行結果例をコマンド10に示します。はじめにBobの現在の残高が表示され、トランザクションが発行されるとそのハッシュが表示されます。トランザクションがブロックに取り込まれると、Bobの残高が更新され、その結果が表示されます。
コマンド10. index.jsの実行とAliceからBobへの送金結果
$ node index.js
Bob
address: 5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty
balance: 1060920
Transfer sent with hash 0xe9431c1d64cd9c525c37122b07ada9024e4fe8b533fb3e9db83cbc8a3dcabf8a
Bob
address: 5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty
balance: 1070920
本稿では、Polkadotjsを用いて、コンソールやJavaScriptのアプリケーションからSubstrateのノードと通信する手法について紹介しました。
第5回では、Rustを用いて実装した独自のRuntimeをSubstrateチェーン上にデプロイし、動作を確認する手法について紹介します。
以上
参考文献:
- What is Substrate? – Parity
https://www.parity.io/what-is-substrate/ - Substrate Developer Hub
https://docs.substrate.dev/ - Substrate: The platform for blockchain innovators – Github
https://github.com/paritytech/substrate - polkadot-js/app – Github
https://github.com/polkadot-js/apps - polkadot-js/api
https://polkadot.js.org/api/
ブロックチェーン学習に最適の書籍の紹介
図解即戦力 ブロックチェーンのしくみと開発がこれ1冊でしっかりわかる教科書
本書は、ブロックチェーン技術に興味を持ったエンジニアや、その仕組みを学び、自分の仕事に活かしたいビジネスパーソンを対象にして、ブロックチェーンのコア技術とネットワーク維持の仕組みを平易な言葉で解説しています。この本を読んだうえで、実際にコードを書くような専門書、ブロックチェーンビジネスの解説書を読むことで、理解度が飛躍的に高まるでしょう。(はじめにより)
会社紹介
弊社(コンセンサス・ベイス株式会社)は、2015年設立の国内で最も古いブロックチェーン専門企業です。これまでに、大手企業の顧客を中心に、日本トップクラスのブロックチェーンの開発・コンサルティング実績があります。ブロックチェーンに関わるビジネスコンサル・システム開発・教育・講演などご希望でしたら、お気軽にお問い合わせください。
会社ホームページ
https://www.consensus-base.com/
免責事項
本記事に掲載されている記事の内容につきましては、正しい情報を提供することに務めてはおりますが、提供している記事の内容及び参考資料からいかなる損失や損害などの被害が発生したとしても、弊社では責任を負いかねます。実施される際には、法律事務所にご相談ください。
技術・サービス・実装方法等のレビュー、その他解説・分析・意見につきましてはblock-chani.jp運営者の個人的見解です。正確性・正当性を保証するものではありません。本記事掲載の記事内容のご利用は読者様個人の判断により自己責任でお願いいたします。