SubstrateのRuntime StorageからCurlでデータを取得する方法

# 要約
- タイトルのことをやりたいと思った時に迷わないガイドが英語含めてないように思う。（※単なる調査不足か、思うだけであるかもしれません。）
- いつもそうですが、日本語の記事は存在しないので、後からもう一度自分がやる時のことも考えてメモします。

# 私が想定したユースケース
- ある処理をSubstrateのoff-chain workerで処理することを想定します。
- そのある処理では、オンチェーンのデータの状態を判断して、処理が必要なものだけ、off-chainからオンチェーンに連携したいとします。
- その場合、off-chain workerからオンチェーンのデータを取得する必要があります。
- その時、どうやって値を取得するか考えた時にHTTPのインターフェースで実装しようと思い、今回の件を調べています。
- ★ただ、この設計が有効かは現在、検証中です。

# 参考にした記事
- Parity TechnologiesのShawn Tabriziさんの二つの記事を参考にしました。[Querying Substrate Storage via RPC](https://www.shawntabrizi.com/substrate/querying-substrate-storage-via-rpc/)　と　[Porting Web3.js to Polkadot.js](https://www.shawntabrizi.com/substrate/porting-web3-js-to-polkadot-js/)　です。
- 本文中に本記事より、コマンドを引用させて頂いています。

# 予備知識
- SubstrateにはRPCインターフェースが実装されているので、そこに投げ込む。
- SubstrateのストレージはKey-Valueデータベースになっている。
- HEX文字列を使用して一定の決まりに従ってリクエストを行う。
- HEX変換等にはPolkadot.jsのライブラリを使用する。

# 今回の手順
- 環境構築
- substrate node templateモジュールの実行
- Curlコマンドによるデータ取得テスト

## 環境構築
- ※前提として、substrate-node-moduleがインストールされていて、実行可能な状態にある状態から始めます。
- npmをインストールする。
- browserifyをインストールする。

```
npm install -g browserify
```

- polkadot関連のライブラリをインストールします。

```
 npm install @polkadot/api
 npm install @polkadot/util
 npm install @polkadot/util-crypto
 npm install @polkadot/keyring
```

- 次にデータコンバート用に使用するhtmlファイルにインポートするためのjsファイルを作成していきます。
- 以下のファイルを作成します。「before_bundle.js」とします。

```
 let api = require("@polkadot/api");
 let util = require("@polkadot/util");
 let util_crypto = require("@polkadot/util-crypto");
 let keyring = require("@polkadot/keyring");

 window.api = api;
 window.util = util;
 window.util_crypto = util_crypto;
 window.keyring = keyring;
```

- browserifyを使用して、htmlからインポート可能な形式に変換していきます。

```
browserify before_bundle.js -o bundle.js
```

- bundle.jsが作成されるので、「Test.html」を作成してインポートさせます。

```
<html>
<head>
</head>
<body>
<script src="bundle.js"></script>
hello world
</body>
</html>

```

- Test.htmlをブラウザで開き、開発者ツールを使って、Consoleウィンドウを開いてエラーが出なければ環境構築は成功になります。

![20210304_polkadotjs.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/628255/6f00cf71-5aec-b8b2-0344-3a3cb2935794.png)

## substrate-node-templateの起動
- 今回はテストとして、ローカルのSubstrateノードに投げるので、起動しておいて下さい。
- TemplateModuleのdoSomething関数を実行して値をオンチェーンに格納しておいて下さい。私は以下の画面の通り「５」を格納しています。

## Curlコマンドによるデータ取得テスト
- Shawn Tabriziの記事によると「モジュール名」「ストレージ名」・・・の順で指定すれば良いことがわかりますので、やっていきます。
- 今回は、Substrate-node-templateにデフォルトで準備されている「pallet-template」の「something」値を取得してみます。以下の画面の赤枠の「templateModule」がモジュール名、「something」がストレージ名になります。
- ★★先頭を大文字にしないと正しく動作しないようです。理由は未調査です。
- Consoleウインドウに以下のようにタイプして実行します。

```
util_crypto.xxhashAsHex("TemplateModule", 128)
util_crypto.xxhashAsHex("Something", 128)
```

![20210304_polkadot2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/628255/9c0f29ac-fb4c-e7f2-1d42-375957f9117a.png)

- コンソールで上記を実行すると以下の値が取得出来たと思います。

```
0x177e6857fb1d0e409376122fee3ad4f8
0xe7f330bb2c4867b06952a0331407518e
```

![20210304_polkadotjs3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/628255/7a0af3e0-6122-b207-44ab-bad0b46e9b55.png)

- コマンドから以下の要領でCurlコマンドを使用してリクエストしてみます。
- 「params」に今回取得した値を設定しますが、連結する際に後ろにくる値の「0x」は削除して連結して下さい。

```
curl -H "Content-Type: application/json" -d '{"id":1, "jsonrpc":"2.0", "method": "state_getStorage", "params": ["0x177e6857fb1d0e409376122fee3ad4f8e7f330bb2c4867b06952a0331407518e"]}' http://localhost:9933/
```

- 以下が取得出来たはずです。

```
{"jsonrpc":"2.0","result":"0x05000000","id":1}
```

- これをStringに変換します。
- またブラウザのConsoleに戻って以下を実行します。

```
util.hexToBn("0x05000000", { isLe: true }).toString()
```

- 以下が取得出来、確かにオンチェーンに格納されている５が取得出来たことを確認出来ます。

```
"5"
```

# まとめ
- 今回英語文献を参考にしながら、知識をつなぎ合わせてデータを取得するところまでをやりました。
- いつも思うことはSubstrateをやる時に母国語で記載されたドキュメントがもっと豊富にあれば、みんなで知識を共有することで同じハマり方をせず、次にやる人が自分がハマった箇所ではハマらず、次の課題に取り組めることを思うと、日本語文献を増やしたいと思っています。
- Substrateを日本語圏でやっている人がいれば是非知見を共有させて下さい。
- Telegramに[日本語チャンネル](https://t.me/substratejapan)があるので、是非そちらにも。