From d7c70494efa2fdbb349806388de82f6bc2da360e Mon Sep 17 00:00:00 2001 From: Filippo Vecchiato Date: Fri, 23 Aug 2024 10:46:05 +0200 Subject: [PATCH 1/3] promise batching across services and controllers --- src/services/accounts/AccountsAssetsService.ts | 5 +---- src/services/accounts/AccountsPoolAssetsService.ts | 4 +--- src/services/accounts/AccountsStakingPayoutsService.ts | 8 ++++---- src/services/blocks/BlocksService.ts | 2 +- src/services/pallets/PalletsStakingProgressService.ts | 9 ++++----- 5 files changed, 11 insertions(+), 17 deletions(-) diff --git a/src/services/accounts/AccountsAssetsService.ts b/src/services/accounts/AccountsAssetsService.ts index 9fb3b06af..00da5b523 100644 --- a/src/services/accounts/AccountsAssetsService.ts +++ b/src/services/accounts/AccountsAssetsService.ts @@ -63,13 +63,10 @@ export class AccountsAssetsService extends AbstractService { */ async fetchAssetBalances(hash: BlockHash, address: string, assets: number[]): Promise { const { api } = this; - const historicApi = await api.at(hash); - + const [historicApi, { number }] = await Promise.all([api.at(hash), api.rpc.chain.getHeader(hash)]); // Check if this runtime has the assets pallet this.checkAssetsError(historicApi); - const { number } = await api.rpc.chain.getHeader(hash); - let response; if (assets.length === 0) { /** diff --git a/src/services/accounts/AccountsPoolAssetsService.ts b/src/services/accounts/AccountsPoolAssetsService.ts index 4d0175ffd..4f44ff003 100644 --- a/src/services/accounts/AccountsPoolAssetsService.ts +++ b/src/services/accounts/AccountsPoolAssetsService.ts @@ -67,13 +67,11 @@ export class AccountsPoolAssetsService extends AbstractService { assets: number[], ): Promise { const { api } = this; - const historicApi = await api.at(hash); + const [historicApi, { number }] = await Promise.all([api.at(hash), api.rpc.chain.getHeader(hash)]); // Check if this runtime has the PoolAssets pallet this.checkPoolAssetsError(historicApi); - const { number } = await api.rpc.chain.getHeader(hash); - let response; if (assets.length === 0) { /** diff --git a/src/services/accounts/AccountsStakingPayoutsService.ts b/src/services/accounts/AccountsStakingPayoutsService.ts index 08bf6b772..33f99485f 100644 --- a/src/services/accounts/AccountsStakingPayoutsService.ts +++ b/src/services/accounts/AccountsStakingPayoutsService.ts @@ -296,10 +296,10 @@ export class AccountsStakingPayoutsService extends AbstractService { : await this.api.rpc.chain.getBlockHash(earlyErasBlockInfo[era - 1].end); let reward: Option = historicApi.registry.createType('Option'); - - const blockInfo = await this.api.rpc.chain.getBlock(nextEraStartBlockHash); - - const allRecords = await historicApi.query.system.events(); + const [blockInfo, allRecords] = await Promise.all([ + this.api.rpc.chain.getBlock(nextEraStartBlockHash), + historicApi.query.system.events(), + ]); blockInfo.block.extrinsics.forEach((index) => { allRecords diff --git a/src/services/blocks/BlocksService.ts b/src/services/blocks/BlocksService.ts index 1e0072f26..8af029d5f 100644 --- a/src/services/blocks/BlocksService.ts +++ b/src/services/blocks/BlocksService.ts @@ -682,7 +682,7 @@ export class BlocksService extends AbstractService { * @param registry type registry of the block the call belongs to */ private parseGenericCall(genericCall: GenericCall, registry: Registry): ISanitizedCall { - const newArgs = {}; + const newArgs: Record = {}; // Pull out the struct of arguments to this call const callArgs = genericCall.get('args') as Struct; diff --git a/src/services/pallets/PalletsStakingProgressService.ts b/src/services/pallets/PalletsStakingProgressService.ts index abcfb76a7..b6b47f0ac 100644 --- a/src/services/pallets/PalletsStakingProgressService.ts +++ b/src/services/pallets/PalletsStakingProgressService.ts @@ -40,7 +40,7 @@ export class PalletsStakingProgressService extends AbstractService { api.rpc.chain.getHeader(hash), ]); - let eraElectionStatus; + let eraElectionPromise; /** * Polkadot runtimes v0.8.30 and above do not support eraElectionStatus, so we check * to see if eraElectionStatus is mounted to the api, and if were running on a @@ -48,11 +48,10 @@ export class PalletsStakingProgressService extends AbstractService { * we do nothing and let `eraElectionStatus` stay undefined. */ if (historicApi.query.staking.eraElectionStatus) { - eraElectionStatus = await historicApi.query.staking.eraElectionStatus(); + eraElectionPromise = await historicApi.query.staking.eraElectionStatus(); } - - const { eraLength, eraProgress, sessionLength, sessionProgress, activeEra } = - await this.deriveSessionAndEraProgress(historicApi); + const [eraElectionStatus, { eraLength, eraProgress, sessionLength, sessionProgress, activeEra }] = + await Promise.all([eraElectionPromise, this.deriveSessionAndEraProgress(historicApi)]); const unappliedSlashesAtActiveEra = await historicApi.query.staking.unappliedSlashes(activeEra); From fb7af56b6386fd13bd0f5685cb1610ce86514f75 Mon Sep 17 00:00:00 2001 From: Filippo Vecchiato Date: Fri, 23 Aug 2024 12:56:30 +0200 Subject: [PATCH 2/3] injects historic api to fee calculation to reduce promises --- src/services/blocks/BlocksService.ts | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/src/services/blocks/BlocksService.ts b/src/services/blocks/BlocksService.ts index 8af029d5f..cc44e14fe 100644 --- a/src/services/blocks/BlocksService.ts +++ b/src/services/blocks/BlocksService.ts @@ -195,6 +195,8 @@ export class BlocksService extends AbstractService { } const previousBlockHash = await this.fetchPreviousBlockHash(number); + const prevBlockHistoricApi = await api.at(previousBlockHash); + // get previous block hash historic api and inject it where needed to save calls per extrinic /** * Fee calculation logic. This runs the extrinsics concurrently. */ @@ -203,7 +205,17 @@ export class BlocksService extends AbstractService { for (let idx = 0; idx < block.extrinsics.length; ++idx) { feeTasks.push( pQueue.run(async () => { - await this.resolveExtFees(extrinsics, block, idx, noFees, previousBlockHash, specVersion, specName); + await this.resolveExtFees( + extrinsics, + block, + idx, + noFees, + previousBlockHash, + specVersion, + specName, + // Inject historic api here or undefined if not available, should save at least two calls per extrinsic + prevBlockHistoricApi, + ); }), ); } @@ -241,9 +253,10 @@ export class BlocksService extends AbstractService { previousBlockHash: BlockHash, specVersion: u32, specName: Text, + historicApi?: ApiDecoration<'promise'>, ) { const { api } = this; - + // Inject historic api here or undefined if not available if (noFees) { extrinsics[idx].info = {}; return; @@ -340,7 +353,7 @@ export class BlocksService extends AbstractService { class: dispatchClass, partialFee, weight, - } = await this.fetchQueryInfo(block.extrinsics[idx], previousBlockHash); + } = await this.fetchQueryInfo(block.extrinsics[idx], previousBlockHash, historicApi); const versionedWeight = (weight as Weight).refTime ? (weight as Weight).refTime.unwrap() : (weight as WeightV1); let finalPartialFee = partialFee.toString(), @@ -361,6 +374,7 @@ export class BlocksService extends AbstractService { previousBlockHash, weightInfo.weight, versionedWeight.toString(), + historicApi, ); dispatchFeeType = 'postDispatch'; @@ -371,6 +385,7 @@ export class BlocksService extends AbstractService { previousBlockHash, weightInfo.weight, versionedWeight.toString(), + historicApi, ); dispatchFeeType = 'postDispatch'; this.hasQueryFeeApi.setRegisterWithCall(specVersion.toNumber()); @@ -402,9 +417,10 @@ export class BlocksService extends AbstractService { previousBlockHash: BlockHash, extrinsicSuccessWeight: Weight, estWeight: string, + historicApi?: ApiDecoration<'promise'>, ): Promise { const { api } = this; - const apiAt = await api.at(previousBlockHash); + const apiAt = historicApi || (await api.at(previousBlockHash)); let inclusionFee; if (apiAt.call.transactionPaymentApi.queryFeeDetails) { @@ -430,9 +446,11 @@ export class BlocksService extends AbstractService { private async fetchQueryInfo( ext: GenericExtrinsic, previousBlockHash: BlockHash, + historicApi?: ApiDecoration<'promise'>, ): Promise { const { api } = this; - const apiAt = await api.at(previousBlockHash); + // mMove historic api to an injection and only if undefined get it + const apiAt = historicApi || (await api.at(previousBlockHash)); if (apiAt.call.transactionPaymentApi.queryInfo) { const u8a = ext.toU8a(); return apiAt.call.transactionPaymentApi.queryInfo(u8a, u8a.length); From 9eb63ef534115522242e5ed3882d1cb8f727e2e6 Mon Sep 17 00:00:00 2001 From: Filippo Vecchiato Date: Fri, 23 Aug 2024 12:59:17 +0200 Subject: [PATCH 3/3] adds notes to injected historic api --- src/services/blocks/BlocksService.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/services/blocks/BlocksService.ts b/src/services/blocks/BlocksService.ts index cc44e14fe..48b70be96 100644 --- a/src/services/blocks/BlocksService.ts +++ b/src/services/blocks/BlocksService.ts @@ -196,7 +196,6 @@ export class BlocksService extends AbstractService { const previousBlockHash = await this.fetchPreviousBlockHash(number); const prevBlockHistoricApi = await api.at(previousBlockHash); - // get previous block hash historic api and inject it where needed to save calls per extrinic /** * Fee calculation logic. This runs the extrinsics concurrently. */ @@ -256,7 +255,6 @@ export class BlocksService extends AbstractService { historicApi?: ApiDecoration<'promise'>, ) { const { api } = this; - // Inject historic api here or undefined if not available if (noFees) { extrinsics[idx].info = {}; return; @@ -420,6 +418,7 @@ export class BlocksService extends AbstractService { historicApi?: ApiDecoration<'promise'>, ): Promise { const { api } = this; + // Get injected historicApi for previousBlockHash or create a new one const apiAt = historicApi || (await api.at(previousBlockHash)); let inclusionFee; @@ -449,7 +448,7 @@ export class BlocksService extends AbstractService { historicApi?: ApiDecoration<'promise'>, ): Promise { const { api } = this; - // mMove historic api to an injection and only if undefined get it + // Get injected historicApi for previousBlockHash or create a new one const apiAt = historicApi || (await api.at(previousBlockHash)); if (apiAt.call.transactionPaymentApi.queryInfo) { const u8a = ext.toU8a();