From 6b7b6ded33b3343192d852bff14a6372a34ad615 Mon Sep 17 00:00:00 2001 From: Chad Nehemiah Date: Sun, 13 Oct 2024 20:55:33 -0500 Subject: [PATCH] feat: ensure that we fetch node info per estimation (#3324) * fix: ensure that we fetch node info per estimation * docs: add changeset * fix: use auto refreshing cache mechanism * docs: update changesets * fix: ensure setInterval is cleared * fix: remove unnecessary changes * Trigger CI * fix: clear interval prop * fix: update how consensus params are checked * Fixing chain cache internals * Adding tests * Removing log call * Making field optional --------- Co-authored-by: Anderson Arboleya --- .changeset/silent-otters-accept.md | 5 ++ .../account/src/providers/operations.graphql | 10 ++++ .../account/src/providers/provider.test.ts | 27 +++++++++++ packages/account/src/providers/provider.ts | 46 +++++++++++++++++-- 4 files changed, 85 insertions(+), 3 deletions(-) create mode 100644 .changeset/silent-otters-accept.md diff --git a/.changeset/silent-otters-accept.md b/.changeset/silent-otters-accept.md new file mode 100644 index 00000000000..66edb3e905a --- /dev/null +++ b/.changeset/silent-otters-accept.md @@ -0,0 +1,5 @@ +--- +"@fuel-ts/account": patch +--- + +feat: ensure that we fetch node info per estimation \ No newline at end of file diff --git a/packages/account/src/providers/operations.graphql b/packages/account/src/providers/operations.graphql index a05f0a1e8a6..67efe338593 100644 --- a/packages/account/src/providers/operations.graphql +++ b/packages/account/src/providers/operations.graphql @@ -786,6 +786,16 @@ query isUserAccount( } } +query getConsensusParametersVersion { + chain { + latestBlock { + header { + consensusParametersVersion + } + } + } +} + subscription submitAndAwait($encodedTransaction: HexString!) { submitAndAwait(tx: $encodedTransaction) { ...transactionStatusSubscriptionFragment diff --git a/packages/account/src/providers/provider.test.ts b/packages/account/src/providers/provider.test.ts index b4472c586d0..eea8adcd4e1 100644 --- a/packages/account/src/providers/provider.test.ts +++ b/packages/account/src/providers/provider.test.ts @@ -2190,4 +2190,31 @@ Supported fuel-core version: ${mock.supportedVersion}.` expect([baseAssetId, ASSET_A, ASSET_B].includes(balance.assetId)).toBeTruthy(); }); }); + + test('should not refetch consensus params in less than 1min', async () => { + using launched = await setupTestProviderAndWallets(); + + const provider = await Provider.create(launched.provider.url); + const fetchChainAndNodeInfo = vi.spyOn(provider, 'fetchChainAndNodeInfo'); + + // calling twice + await provider.autoRefetchConfigs(); + await provider.autoRefetchConfigs(); + + expect(fetchChainAndNodeInfo).toHaveBeenCalledTimes(1); + }); + + test('should refetch consensus params if >1 min has passed', async () => { + using launched = await setupTestProviderAndWallets(); + + const provider = await Provider.create(launched.provider.url); + const fetchChainAndNodeInfo = vi.spyOn(provider, 'fetchChainAndNodeInfo'); + + // calling twice + await provider.autoRefetchConfigs(); + provider.consensusParametersTimestamp = 0; + await provider.autoRefetchConfigs(); + + expect(fetchChainAndNodeInfo).toHaveBeenCalledTimes(2); + }); }); diff --git a/packages/account/src/providers/provider.ts b/packages/account/src/providers/provider.ts index daa721ed78f..4552f4d4f56 100644 --- a/packages/account/src/providers/provider.ts +++ b/packages/account/src/providers/provider.ts @@ -419,6 +419,9 @@ export default class Provider { /** @hidden */ private static nodeInfoCache: NodeInfoCache = {}; + /** @hidden */ + public consensusParametersTimestamp?: number; + options: ProviderOptions = { timeout: undefined, resourceCacheTTL: undefined, @@ -601,17 +604,20 @@ export default class Provider { /** * Return the chain and node information. - * + * @param ignoreCache - If true, ignores the cache and re-fetch configs. * @returns A promise that resolves to the Chain and NodeInfo. */ - async fetchChainAndNodeInfo() { + async fetchChainAndNodeInfo(ignoreCache: boolean = false) { let nodeInfo: NodeInfo; let chain: ChainInfo; try { + if (ignoreCache) { + throw new Error(`Jumps to the catch block andre-fetch`); + } nodeInfo = this.getNode(); chain = this.getChain(); - } catch (error) { + } catch (_err) { const data = await this.operations.getChainAndNodeInfo(); nodeInfo = { @@ -623,9 +629,13 @@ export default class Provider { }; Provider.ensureClientVersionIsSupported(nodeInfo); + chain = processGqlChain(data.chain); + Provider.chainInfoCache[this.urlWithoutAuth] = chain; Provider.nodeInfoCache[this.urlWithoutAuth] = nodeInfo; + + this.consensusParametersTimestamp = Date.now(); } return { @@ -1149,6 +1159,34 @@ Supported fuel-core version: ${supportedVersion}.` return results; } + public async autoRefetchConfigs() { + const now = Date.now(); + const diff = now - (this.consensusParametersTimestamp ?? 0); + + if (diff < 60000) { + return; + } + + const chainInfo = this.getChain(); + + const { + consensusParameters: { version: previous }, + } = chainInfo; + + const { + chain: { + latestBlock: { + header: { consensusParametersVersion: current }, + }, + }, + } = await this.operations.getConsensusParametersVersion(); + + if (previous !== current) { + // calling with true to skip cache + await this.fetchChainAndNodeInfo(true); + } + } + /** * Estimates the transaction gas and fee based on the provided transaction request. * @param transactionRequest - The transaction request object. @@ -1158,6 +1196,8 @@ Supported fuel-core version: ${supportedVersion}.` const { transactionRequest } = params; let { gasPrice } = params; + await this.autoRefetchConfigs(); + const chainInfo = this.getChain(); const { gasPriceFactor, maxGasPerTx } = this.getGasConfig();