UNPKG

subculture

Version:

Polkadot.js and Substrate development utilities.

171 lines (165 loc) 4.74 kB
import { encodeAddress, decodeAddress } from '@polkadot/keyring'; import { isHex, hexToU8a } from '@polkadot/util'; import limit from 'p-limit'; import { range } from 'lodash'; /** * * Validate a substrate address * * @param address AddressOrPair * @param ss58Format number * @returns boolean */ const isValid = (address, ss58Format) => { try { encodeAddress(isHex(address) ? hexToU8a(address) : decodeAddress(address.toString(), undefined, ss58Format)); return true; } catch (error) { return false; } }; /** * * Shorten an address. Usefull in small UI lists etc. * * @param address AddressOrPair * @param sliceStart number * @param sliceEnd number * @param seperator string * @returns string */ const shorten = (address, sliceStart = 6, sliceEnd = 4, seperator) => { const addressString = address.toString(); return `${addressString.slice(0, sliceStart)}${seperator}${addressString.slice(-sliceEnd)}`; }; /** * * Last four characters of an address * * @param address AddressOrPair * @returns string */ const lastFour = (address) => address.toString().slice(-4); /** * * Get the latest block * * @param api ApiPromise * @returns SignedBlock */ const latest = async (api) => api.rpc.chain.getBlock(); /** * * Get the block at a certain blocknumber if it exists. * * @param api ApiPromise * @param nr number * @returns SignedBlock | null */ const at = async (api, nr) => { try { return await api.rpc.chain.getBlockHash(nr).then(hash => api.rpc.chain.getBlock(hash)); } catch (error) { return null; } }; /** * * Get the block number of a block. * * @param block SignedBlock * @returns number */ const numberOf = (block) => { return parseInt(block.block.header.number.toString().replace(/,/g, '')); }; /** * * Tails the chain for new blocks from a given blocknumber. * Awaits the callback for sequential processing. * * @nb If average callback processing time takes longer time than the average chain block time * the tailing will start to lagg behind the chain block production. * * @param api ApiPromise * @param nr number - block number to tail from * @param cb function - callback to invoke on new block * @returns function - unsubscribe */ const tail = async (api, nr, cb) => { const block = await at(api, nr); if (!block) { return await api.rpc.chain.subscribeFinalizedHeads(header => { return api.rpc.chain.getBlock(header.hash).then(async (block) => { return await cb(block); }); }); } else { await cb(block); return tail(api, nr + 1, cb); } }; /** * * Get a slice of blocks * * @param api ApiPromise * @param from number - start block * @param to number - end block * @returns Awaitable<SignedBlock[]> */ const slice = async (api, from, to, concurrency = 8) => { const pool = limit(concurrency); return (await Promise.all(range(from, to).map(nr => pool(async () => { const block = await at(api, nr); if (block) { return block; } })))).filter((block) => Boolean(block)); }; /** * * Fetch Events for a given block and return the pair. * * @param api ApiPromise * @param block SignedBlock * @returns BlockEventsPair */ const mapEventsToBlock = async (api, block) => { const blockEvents = await (await api.at(block.block.header.hash.toHex())).query.system.events(); return [block, blockEvents]; }; /** * * Get the extrinsics in a block mapped by its events. * * @param events Vec<EventRecord> * @param block SignedBlock * @param filter.method string * @returns GenericExtrinsic<AnyTuple>[] */ const mapToExtrinsics = (block, events, filter) => { return block.block.extrinsics.filter((ex, index) => Boolean(events.find(event => event.phase.isApplyExtrinsic && event.phase.asApplyExtrinsic.eq(index) && (!filter?.method || ex.method.method.toString() === filter.method)))); }; export { at, isValid, lastFour, latest, mapEventsToBlock, mapToExtrinsics, numberOf, shorten, slice, tail }; t => event.phase.isApplyExtrinsic && event.phase.asApplyExtrinsic.eq(index) && (!filter?.method || ex.method.method.toString() === filter.method)))); }; exports.at = at; exports.isValid = isValid; exports.lastFour = lastFour; exports.latest = latest; exports.mapEventsToBlock = mapEventsToBlock; exports.mapToExtrinsics = mapToExtrinsics; exports.numberOf = numberOf; exports.shorten = shorten; exports.slice = slice; exports.tail = tail;