UNPKG

@gear-js/api

Version:

A JavaScript library that provides functionality to connect GEAR Component APIs.

111 lines (108 loc) 3.81 kB
import { isU8a, isHex, isNumber } from '@polkadot/util'; import '@polkadot/types'; import 'assert'; import { CreateType } from '../metadata/create-type.js'; import '../metadata/programMetadata.js'; import { GetBlockError } from '../errors/blocks.errors.js'; class GearBlock { api; subscribeNewHeads; constructor(api) { this.api = api; api.isReady.then(() => { this.subscribeNewHeads = api.derive.chain.subscribeNewHeads; }); } /** * Get data of particular block by blockNumber or blockHash * @param hashOrNumber * @returns */ async get(hashOrNumber) { const hash = isU8a(hashOrNumber) || isHex(hashOrNumber) ? hashOrNumber : await this.getBlockHash(+hashOrNumber); try { return await this.api.rpc.chain.getBlock(hash); } catch (error) { throw new GetBlockError(error.message, hash); } } /** * Get blockHash by number * @param number number of block * @returns blockHash */ async getBlockHash(number) { return await this.api.rpc.chain.getBlockHash(number); } /** * Get block number * @param hash * @returns Compact<BlockNumber> */ async getBlockNumber(hash) { const block = await this.get(hash); return block.block.header.number; } async getBlockTimestamp(blockOrHashOrNumber) { const block = isHex(blockOrHashOrNumber) || isU8a(blockOrHashOrNumber) || isNumber(blockOrHashOrNumber) ? await this.get(blockOrHashOrNumber) : blockOrHashOrNumber; const tsAsU8a = block.block.extrinsics.find((value) => value.method.method === 'set' && value.method.section === 'timestamp').data; const ts = CreateType.create('Compact<u64>', tsAsU8a); return ts; } /** * Get all extrinsic of particular block * @param blockHash hash of particular block * @returns Vec of extrinsics */ async getExtrinsics(blockHash) { return (await this.get(blockHash)).block.extrinsics; } /** * Get all events of particular block * @param blockHash hash of particular block * @returns Vec of events */ async getEvents(blockHash) { const apiAt = await this.api.at(blockHash); return apiAt.query.system.events(); } /** * Get hash of last finalized block * @returns Hash of finalized head */ async getFinalizedHead() { return this.api.rpc.chain.getFinalizedHead(); } async subscribeToHeadsFrom(from, cb, blocks = 'latest') { let blockNumber = typeof from === 'string' ? (await this.getBlockNumber(from)).toNumber() : from; const lastHeader = blocks === 'finalized' ? await this.api.rpc.chain.getHeader(await this.getFinalizedHead()) : await this.api.rpc.chain.getHeader(); let lastHeadNumber = lastHeader.number.toNumber(); let unsubscribed = false; const unsub = await this.api.rpc.chain[blocks === 'finalized' ? 'subscribeFinalizedHeads' : 'subscribeNewHeads']((header) => { lastHeadNumber = header.number.toNumber(); if (blockNumber >= lastHeadNumber) { cb(header); } }); let oldBlocksSub = async () => { while (!unsubscribed && lastHeadNumber > blockNumber) { const hash = await this.api.rpc.chain.getBlockHash(blockNumber); const header = await this.api.rpc.chain.getHeader(hash); await cb(header); blockNumber++; } }; oldBlocksSub(); return () => { unsubscribed = true; oldBlocksSub = null; unsub(); }; } } export { GearBlock };