前几篇文章介绍了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()); }); 还有更多查询方式可以参考官方文档,就不一一列出了。 —- 编译者/作者:松果 玩币族申明:玩币族作为开放的资讯翻译/分享平台,所提供的所有资讯仅代表作者个人观点,与玩币族平台立场无关,且不构成任何投资理财建议。文章版权归原作者所有。 |
【Substrate开发教程】14 - 使用polkadot-js API获取链上信息
2020-10-27 松果 来源:区块链网络
LOADING...
相关阅读:
- 佳予解币:比特币蓄力上攻以太再陷震荡2020-10-27
- BTC维持1.3万美元的比特币鲸鱼数量创下新的ATH2020-10-27
- 市场情报公司Glassnode最新报告:2020年BTC减半,各项指标表明—长线策略2020-10-27
- 马智涛:区块链和其他技术为数据生产力的解放提供支持2020-10-27
- 支付清算领域的公链是下一个风口?2020-10-27