diff --git a/packages/api-derive/src/chain/getBlock.ts b/packages/api-derive/src/chain/getBlock.ts index b45f3dcfa5..436e6fa4cf 100644 --- a/packages/api-derive/src/chain/getBlock.ts +++ b/packages/api-derive/src/chain/getBlock.ts @@ -25,17 +25,20 @@ import { memo } from '../util'; */ export function getBlock (instanceId: string, api: ApiInterfaceRx): (hash: Uint8Array | string) => Observable { return memo(instanceId, (blockHash: Uint8Array | string): Observable => - api.queryAt(blockHash).pipe( - switchMap((queryAt) => - combineLatest([ - api.rpc.chain.getBlock(blockHash), - queryAt.system.events(), - queryAt.session - ? queryAt.session.validators() - : of([]) - ]) - ), - map(([signedBlock, events, validators]) => + combineLatest([ + api.rpc.chain.getBlock(blockHash), + api.queryAt(blockHash).pipe( + switchMap((queryAt) => + combineLatest([ + queryAt.system.events(), + queryAt.session + ? queryAt.session.validators() + : of([]) + ]) + ) + ) + ]).pipe( + map(([signedBlock, [events, validators]]) => createSignedBlockExtended(api.registry, signedBlock, events, validators) ), catchError((): Observable => diff --git a/packages/api-derive/src/chain/getHeader.ts b/packages/api-derive/src/chain/getHeader.ts index c53420954e..f890da2c91 100644 --- a/packages/api-derive/src/chain/getHeader.ts +++ b/packages/api-derive/src/chain/getHeader.ts @@ -25,17 +25,18 @@ import { memo } from '../util'; * console.log(`block #${number} was authored by ${author}`); * ``` */ -export function getHeader (instanceId: string, api: ApiInterfaceRx): (hash: Uint8Array | string) => Observable { - return memo(instanceId, (hash: Uint8Array | string): Observable => - api.queryAt(hash).pipe( - switchMap((queryAt) => - combineLatest([ - api.rpc.chain.getHeader(hash), +export function getHeader (instanceId: string, api: ApiInterfaceRx): (blockHash: Uint8Array | string) => Observable { + return memo(instanceId, (blockHash: Uint8Array | string): Observable => + combineLatest([ + api.rpc.chain.getHeader(blockHash), + api.queryAt(blockHash).pipe( + switchMap((queryAt) => queryAt.session ? queryAt.session.validators() : of([] as AccountId[]) - ]) - ), + ) + ) + ]).pipe( map(([header, validators]) => createHeaderExtended(header.registry, header, validators) ), diff --git a/packages/api-derive/src/chain/subscribeNewBlocks.ts b/packages/api-derive/src/chain/subscribeNewBlocks.ts index 7a374a7fc6..914c103638 100644 --- a/packages/api-derive/src/chain/subscribeNewBlocks.ts +++ b/packages/api-derive/src/chain/subscribeNewBlocks.ts @@ -21,15 +21,15 @@ export function subscribeNewBlocks (instanceId: string, api: ApiInterfaceRx): () const blockHash = header.createdAtHash || header.hash; // we get the block first, setting up the registry - return api.queryAt(blockHash).pipe( - switchMap((queryAt) => - combineLatest([ - of(header), - api.rpc.chain.getBlock(blockHash), + return combineLatest([ + of(header), + api.rpc.chain.getBlock(blockHash), + api.queryAt(blockHash).pipe( + switchMap((queryAt) => queryAt.system.events() - ]) + ) ) - ); + ]); }), map(([header, block, events]) => createSignedBlockExtended(block.registry, block, events, header.validators) diff --git a/packages/api-derive/src/tx/events.ts b/packages/api-derive/src/tx/events.ts index 98a1d7e61e..039ffdf67b 100644 --- a/packages/api-derive/src/tx/events.ts +++ b/packages/api-derive/src/tx/events.ts @@ -16,13 +16,14 @@ interface Result { export function events (instanceId: string, api: ApiInterfaceRx): (at: Hash) => Observable { return memo(instanceId, (blockHash: Hash) => - api.queryAt(blockHash).pipe( - switchMap((queryAt) => - combineLatest([ - api.rpc.chain.getBlock(blockHash), + combineLatest([ + api.rpc.chain.getBlock(blockHash), + api.queryAt(blockHash).pipe( + switchMap((queryAt) => queryAt.system.events() - ]) - ), + ) + ) + ]).pipe( map(([block, events]): Result => ({ block, events })) ) ); diff --git a/packages/api-derive/src/tx/signingInfo.ts b/packages/api-derive/src/tx/signingInfo.ts index f643af5978..e72f05536a 100644 --- a/packages/api-derive/src/tx/signingInfo.ts +++ b/packages/api-derive/src/tx/signingInfo.ts @@ -32,20 +32,23 @@ function nextNonce (api: ApiInterfaceRx, address: string): Observable { function signingHeader (api: ApiInterfaceRx): Observable
{ return combineLatest([ - api.rpc.chain.getHeader(), - api.rpc.chain.getFinalizedHead() - ]).pipe( - switchMap(([bestHeader, finHash]) => - // retrieve the headers - in the case of the current block, we use the parent - // to minimize (not completely remove) the impact that forks do have on the system - // (when at genesis, just return the current header as the last known) - bestHeader.parentHash.isEmpty - ? of([bestHeader, bestHeader]) - : combineLatest([ - api.rpc.chain.getHeader(bestHeader.parentHash), - api.rpc.chain.getHeader(finHash) - ]) + api.rpc.chain.getHeader().pipe( + switchMap((header) => + // check for chains at genesis (until block 1 is produced, e.g. 6s), since + // we do need to allow transactions at chain start (also dev/seal chains) + header.parentHash.isEmpty + ? of(header) + // in the case of the current block, we use the parent to minimize the + // impact of forks on the system, but not completely remove it + : api.rpc.chain.getHeader(header.parentHash) + ) ), + api.rpc.chain.getFinalizedHead().pipe( + switchMap((hash) => + api.rpc.chain.getHeader(hash) + ) + ) + ]).pipe( map(([current, finalized]) => // determine the hash to use, current when lag > max, else finalized current.number.unwrap().sub(finalized.number.unwrap()).gt(MAX_FINALITY_LAG) diff --git a/packages/api-derive/src/util/approvalFlagsToBools.ts b/packages/api-derive/src/util/approvalFlagsToBools.ts index 7ba85ada5d..c382d606d3 100644 --- a/packages/api-derive/src/util/approvalFlagsToBools.ts +++ b/packages/api-derive/src/util/approvalFlagsToBools.ts @@ -8,14 +8,14 @@ import type { ApprovalFlag } from '@polkadot/types/interfaces/elections'; export function approvalFlagsToBools (flags: Vec | ApprovalFlag[]): boolean[] { const bools: boolean[] = []; - flags.forEach((flag: ApprovalFlag): void => { - const str = flag.toString(2); + for (let i = 0; i < flags.length; i++) { + const str = flags[i].toString(2); // read from lowest bit to highest for (const bit of str.split('').reverse()) { bools.push(!!parseInt(bit, 10)); } - }); + } // slice off trailing "false" values, as in substrate const lastApproval = bools.lastIndexOf(true); diff --git a/packages/api-derive/src/util/cacheImpl.ts b/packages/api-derive/src/util/cacheImpl.ts index cba31b9981..c1006e2de2 100644 --- a/packages/api-derive/src/util/cacheImpl.ts +++ b/packages/api-derive/src/util/cacheImpl.ts @@ -10,10 +10,8 @@ export const deriveMapCache: DeriveCache = { mapCache.delete(key); }, forEach: (cb: (key: string, value: any) => void): void => { - const entries = mapCache.entries(); - - for (const entry in entries) { - cb(entry[0], entry[1]); + for (const [k, v] of mapCache.entries()) { + cb(k, v); } }, get: (key: string): T | undefined => {