@gear-js/api
Version:
A JavaScript library that provides functionality to connect GEAR Component APIs.
111 lines (108 loc) • 3.81 kB
JavaScript
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 };