币圈信息网 币圈新闻 【Substrasdfste开发教程】14 – 使用polkasdfsdot-js API获取链上信息

【Substrasdfste开发教程】14 – 使用polkasdfsdot-js API获取链上信息

前几篇文章介绍了Substrate的一些理论知识和substrate-node-template的使

前几篇文章介绍了Substrate的一些理论知识和substrate-node-template的使用,这篇文章介绍polkadot.js API以及如何使用它和Substrate区块链进行交互。

安装substrate-front-end-template

这篇文章介绍的polkadot-js API的使用是基于substrate-front-end-template的,安装该项目的方法在之前的文章:《创建第一条Substrate区块链》介绍过,可按文中方法自行安装。

安装polkadot.js

polkadot.js是可以和Substrate区块链交互的JS API,使用如下命令安装JS API到React项目:

yarn add @polkadot/api

安装好后,在package.json的dependencies下可以找到已安装的依赖:

polkadot.js相关概念

1、元数据(Metadata)

当连接到节点时,@polkadot/api的接口是动态生成的,要做的第一件事就是检索元数据,并根据元数据信息装饰API,以如下形式构成接口:

api.<type>.<module>.<section>

包括如下一些分组:

consts:所有运行时常量,如api.consts.balances.existentialDeposit;query:所有链上状态信息,如api.query.system.account(<accountId>);tx:所有交易信息,如api.tx.balances.transfer(<accountId>, <value>);events:事件,如api.query.system.events();

2、链默认值(Chain Defaults)

除了元数据接口方式,polkadot.js API还提供直接的API接口,包括:

api.genesisHash:所连接的链的初始哈希;api.runtimeMetadata:从链中检索到的元数据;api.runtimeVersion:链运行时版本;api.libraryInfo:API的版本,如目前使用的是@polkadot/api v2.2.1;

创建实例

修改substrate-front-end/src/App.js的代码如下:

主要代码有:导入polkadot/api提供的组件

import { ApiPromise, WsProvider } from \’@polkadot/api\’;

通过WebSocket Provider创建api对象

const wsProvider = new WsProvider(\’wss://rpc.polkadot.io\’);const api = await ApiPromise.create({ provider: wsProvider });

使用api对象获取链的初始哈希(genesisHash)

api.genesisHash.toHex()

使用yarn start启动前端界面,效果如下:

这里获取的是polkadot主网的genesisHash,把ws地址换成

ws://localhost:9944

可以获取本地节点的genesisHash,前提是先启动本地node节点。

cd substrate-node-template./target/release/node-template –dev

效果如下:

可以看到波卡主网和我本地节点的genesisHash:

波卡主网:0x91b171bb158e2d3848fa23a9f1c25182fb8e20313b2c1eb49219da7a70ce90c3本地节点:0x5aba5001fc1aa6b5593d643c69a02272146f5cc4c0adba3d4084b70c8934d9b3

查询运行时常量(Runtime constants)

api.consts.babe.epochDuration.toNumber()

表示一个epoch占用的slot数量,每当一个新的epoch开始时,会启动一个新的会话(session)。

epochDuration是常量,可以直接获取,不需要await,修改substrate-front-end/src/App.js的代码如下:

效果如下:

查询链上状态(State queries)

查询链上状态数据使用api.query,而query后的<module>名字是当连到Substrate节点时动态创建的,取决于连接的Substrate网络加载了什么pallet。如查询指定账户的余额的代码如下:

const ADDR = \’5DTestUPts3kjeXSTMyerHihn1uwMfLj8vU8sqF7qYrFabHE\’;const now = await api.query.timestamp.now();const { nonce, data: balance } = await api.query.system.account(ADDR);console.log(`${now}: balance of ${balance.free} and a nonce of ${nonce}`);

RPC查询(RPC queries)

api.rpc使用api.query相同的样式,如获取Substrate区块链名和最后一个区块头的编号和哈希值:

const chain = await api.rpc.system.chain();const lastHeader = await api.rpc.chain.getHeader();console.log(`${chain}: last block #${lastHeader.number} has hash ${lastHeader.hash}`);

控制台打印结果如下:

Polkadot: last block #1941646 has hash 0xe482b5b950bcbc8d41240a953bc862b9ec72a4e46cd5183a176875d174cc6757

RPC倾向于使用订阅(监听)功能,下面的代码可以跟踪新区块的出块过程:

const chain = await api.rpc.system.chain(); await api.rpc.chain.subscribeNewHeads((lastHeader) => { console.log(`${chain}: last block #${lastHeader.number} has hash ${lastHeader.hash}`);});

控制台打印数据如下:

Polkadot网络每6秒出一个新区块。

订阅(Subscriptions)

使用api.query扩展之前的api.rpc查询

const unsub = await api.query.timestamp.now((moment) => { console.log(`The last block has a timestamp of ${moment}`);});

用这种方法返回的是取消订阅的函数,当不再需要监听时就可以调用这个函数。

带参数的订阅(Subscriptions with params)

const ADDR = \’5DTestUPts3kjeXSTMyerHihn1uwMfLj8vU8sqF7qYrFabHE\’;const unsub = await api.query.system.account(ADDR, ({ nonce, data: balance }) => { console.log(`free balance is ${balance.free} with ${balance.reserved} reserved and a nonce of ${nonce}`);});

订阅后,当账户余额发生变化时会自动调用回调函数中的代码。

订阅查询多个链上数值(Multi queries)

相同数据类型

const unsub = await api.query.system.account.multi([ADDR1, ADDR2], (balances) => { const [{ data: balance1 }, { data: balance2 }] = balances; console.log(`The balances are ${balance1.free} and ${balance2.free}`);});

不同数据类型

const unsub = await api.queryMulti([ api.query.timestamp.now, [api.query.system.account, ADDR]], ([now, { nonce, data: balance }]) => { console.log(`${now}: balance of ${balance.free} and a nonce of ${nonce}`);});

查询指定区块的状态信息

下面的例子分别查询某个账户两个相邻区块的余额,并计算它们的差值

const ADDR = \’5DTestUPts3kjeXSTMyerHihn1uwMfLj8vU8sqF7qYrFabHE\’;const lastHdr = await api.rpc.chain.getHeader();const [{ data: balanceNow }, { data: balancePrev }] = await Promise.all([ api.query.system.account.at(lastHdr.hash, ADDR), api.query.system.account.at(lastHdr.parentHash, ADDR)]);console.log(`The delta was ${balanceNow.free.sub(balancePrev.free)}`);

查询指定范围区块的状态信息

const lastHdr = await api.rpc.chain.getHeader();const startHdr = await api.rpc.chain.getBlockHash(lastHdr.number.unwrap().subn(500));const changes = await api.query.system.account.range([startHdr]);changes.forEach(([hash, value]) => { console.log(hash.toHex(), value.toHuman());});

还有更多查询方式可以参考官方文档,就不一一列出了。

本文来自网络,不代表币圈信息网立场,转载请注明出处:https://www.lpbwg.com/26196.html

作者: bqxxw

返回顶部