LibraVistaは、Facebook Libra のテストネット(Testnet)のエクスプローラーを提供するサービスです。
そのLibraVistaが、アカウント状態の取得や、Libraの発行(mint)を行うAPIサービスとしての「libra-vista-api」を公開しました。
なおLibraのアカウント(アドレス)自体は、事前に作成しておく必要があります。下記の関連ページをご参照下さい。
FacebookのLibra Testnetを試す[送金][mnemonic][recover]
例えばリクエストした任意のアカウント(アドレス)において、その状態として下記のようなレスポンスがJSONとして返ってきます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
{ "code": 0, "message": "success", "data": { "detail": { "address": "f7550da222f45c7d83da1d7b1417e6aa7d265ee75a9cd4c3ef8a6a975536b607", "balance": "70", "sequenceNumber": "2", "sentEventCount": "3", "receivedEventCount": "1" } }, "timestamp": 1562643370838 } |
addressはリクエストしたアカウントのアドレスです。balanceはそのアドレスが保存しているLibraの量、そしてLibraを受け取った回数(receivedEventCount)などが表示されているのが確認できます。
Libra Core と gRPC
Libra Core(Testnet)のソースは下記リンクのGithubにおいて公開されていますが、主にRust言語によって記述され、多くの.protoファイルが存在するのが確認できます。
https://github.com/libra/libra
Libraは、client(クライアント)とvalidator(検証者)間においてgRPCによる通信がおこなわれています。また様々な.protoファイルには、そのメッセージとインターフェイスが定義されています。このような仕組みによってイーサリアムにおけるweb3.jsと同じようなモジュールを、様々な言語によって構築できます。
https://developers.libra.org/docs/assets/papers/the-libra-blockchain.pdf から抜粋
そのようなgRPCでの仕様をラップし、HTTPによるAPIとしてテストネットを利用できるようにしたのが、libra-vista-apiです。
実際にLibraの本番環境が可動した時に、Moveによるスマートコントラクトも含めどのような開発の流れになるのかはまだまだ分かりませんが、2020年においてはFinTechにおいてもAPIエコノミーとしてのアプリ構築の流れがいよいよ加速していきそうです。
gRPCでLibraのTestnetと接続
下記コードはNode.jsによるコードで、gRPCによってLibraのTestnetと接続するクライアントを記述しています。具体的にはアカウント(f7550da222f〜)をリクエストし、そのアカウントの状態がバイナリデータとしてレスポンスされる機能を実装しています。
client.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
const grpc = require('grpc') const protoLoader = require('@grpc/proto-loader') const PROTO_PATH = __dirname + '/proto/admission_control.proto' const packageDefinition = protoLoader.loadSync( PROTO_PATH, { keepCase: true, longs: Number, enums: String, defaults: true, bytes: String, oneofs: true, } ) const protoDescriptor = grpc.loadPackageDefinition(packageDefinition); const client = new protoDescriptor.admission_control.AdmissionControl('ac.testnet.libra.org:8000', grpc.credentials.createInsecure()) const params = { address: Buffer.from('f7550da222f45c7d83da1d7b1417e6aa7d265ee75a9cd4c3ef8a6a975536b607', 'hex'), }; const request = {}; request['get_account_state_request'] = params; client.updateToLatestLedger({ client_known_version: 0, requested_items: [request], }, (error, response) => { if (!error) { console.log(response.response_items[0]['get_account_state_response']['account_state_with_proof']) } else { console.error(error) } }); |
3行目
admission_control.proto には、上述で引用したイラストの「admission control」機能に関するメッセージとインターフェイスとしてのServiceが記述されています。27行目のupdateToLatestLedgerはそのメソッドの一つで、admission_control.protoには下記のように記述されています。
1 2 3 |
rpc UpdateToLatestLedger( types.UpdateToLatestLedgerRequest) returns (types.UpdateToLatestLedgerResponse) {} |
リクエストとしてUpdateToLatestLedgerRequest、レスポンスとしてUpdateToLatestLedgerResponseが指定されているのが確認できます。この2つのメッセージの具体的な内容は、importされているget_with_proof.protoファイルで定義されています。つまりアカウントの状態(account state)は、このupdateToLatestLedgerメソッドがクエリの役目となり、定義されたメッセージをリクエストすることにより取得できます。
18行目
ac.testnet.libra.org:8000 と接続しています。Node.jsによるgRPCの記述は下記ページをご覧下さい。
起動の方法
まずプロジェクトを作成し、Node.jsでのgRPC実装に必要な2つのモジュールをインストールします。
1 2 |
$ npm init $ npm install grpc @grpc/proto-loader --save |
プロジェクト内で上述したファイル(client.js)を作成したら、同ディレクトリ上にprotoディレクトリを作成します(mkdir proto)。その中に admission_control.proto ファイルと、依存する他の.protoファイルも配置します。依存するファイルは主に libra/types/src/proto/ 内にあります。
本記事でのprotoディレクトリ内のファイル一覧
1 2 3 4 5 6 7 8 9 10 11 12 13 |
. ├── access_path.proto ├── account_state_blob.proto ├── admission_control.proto ├── events.proto ├── get_with_proof.proto ├── ledger_info.proto ├── mempool_status.proto ├── proof.proto ├── transaction.proto ├── transaction_info.proto ├── validator_change.proto └── vm_errors.proto |
client.jsを起動させます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
$ node client.js { version: 561120, blob: { blob: 'AQAAACEAAAABIX2mxrPhnxglz7Jnba7M47894DzyZkfHjfALNxslzJdEAAAAIAAAAPdVDaIi9Fx9g9odexQX5qp9Jl7nWpzUw++KapdVNrYHgB0sBAAAAAAAAAAAAAAAAAMAAAAAAAAAAwAAAAAAAAA=' }, proof: { ledger_info_to_transaction_info_proof: { non_default_siblings: [Array], bitmap: 561120 }, transaction_info: { signed_transaction_hash: 'vyJaEK1vyjlIpQDfyU0GZV5CDY9rU73NiIb44Z97gos=', state_root_hash: 'kvvJQw52Hoy2yOWZKhzthrqcCF3kHCOCv8UJyTivgi0=', event_root_hash: 'QUNDVU1VTEFUT1JfUExBQ0VIT0xERVJfSEFTSAAAAAA=', gas_used: 0 }, transaction_info_to_account_proof: { non_default_siblings: [Array], leaf: 'ZyZFQXo4mjIFO3Zt1x6FdyScYrXawFP/e2RXybuiLQM4GEpGxbZUK4pIJHnmGEBOXZJN9GE2iaDlDRlHEyJYpw==', bitmap: '//mA' } } } |
レスポンスとしてのアカウントの状態は、バイト列として返ってくるので(上述4行目のblob)、実際にはこの文字列からデータを切り出す必要があります。
参照ページ
Unpacking AccountResource in Python
参照ページ
‘libravista-api’, a developer-friendly API to Libra chain data, is released