diff --git a/packages/assets-controllers/CHANGELOG.md b/packages/assets-controllers/CHANGELOG.md index 7afe00820d8..4fbffa19f1c 100644 --- a/packages/assets-controllers/CHANGELOG.md +++ b/packages/assets-controllers/CHANGELOG.md @@ -14,6 +14,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed - Correct the polling rate for the DeFiPositionsController from 1 minute to 10 minutes. ([#6242](https://github.com/MetaMask/core/pull/6242)) +- Fix `AccountTrackerController` to force block number update to avoid stale cached native balances ([#6250](https://github.com/MetaMask/core/pull/6250)) ## [73.0.2] diff --git a/packages/assets-controllers/src/AccountTrackerController.ts b/packages/assets-controllers/src/AccountTrackerController.ts index fdaf30ae9b8..4caf0327912 100644 --- a/packages/assets-controllers/src/AccountTrackerController.ts +++ b/packages/assets-controllers/src/AccountTrackerController.ts @@ -17,7 +17,6 @@ import { safelyExecuteWithTimeout, toChecksumHexAddress, } from '@metamask/controller-utils'; -import type { SafeEventEmitterProvider } from '@metamask/eth-json-rpc-provider'; import EthQuery from '@metamask/eth-query'; import type { NetworkClientId, @@ -280,11 +279,7 @@ export class AccountTrackerController extends StaticIntervalPollingController { - const { chainId, ethQuery, provider } = + const { chainId, ethQuery, provider, blockTracker } = this.#getCorrectNetworkClient(networkClientId); const { accountsByChainId } = this.state; const { isMultiAccountBalancesEnabled } = this.messagingSystem.call( @@ -370,6 +367,13 @@ export class AccountTrackerController extends StaticIntervalPollingController + blockTracker?.checkForLatestBlock?.(), + ); + const stakedBalancesPromise = this.#includeStakedAssets ? this.#getStakedBalanceForChain(accountsToUpdate, networkClientId) : Promise.resolve({}); @@ -385,15 +389,22 @@ export class AccountTrackerController extends StaticIntervalPollingController + contract.balances(accountsToUpdate, [ + '0x0000000000000000000000000000000000000000', + ]) as Promise, + false, + 3_000, // 3s max call for multicall contract call + ); - accountsToUpdate.forEach((address, index) => { - accountsForChain[address] = { - balance: (nativeBalances[index] as BigNumber).toHexString(), - }; - }); + if (nativeBalances) { + accountsToUpdate.forEach((address, index) => { + accountsForChain[address] = { + balance: nativeBalances[index].toHexString(), + }; + }); + } } else { // Process accounts in batches using reduceInBatchesSerially await reduceInBatchesSerially({ @@ -421,17 +432,19 @@ export class AccountTrackerController extends StaticIntervalPollingController; + const stakedBalanceResult = await safelyExecuteWithTimeout( + async () => + (await stakedBalancesPromise) as Record, + ); - Object.entries(stakedBalanceResult).forEach(([address, balance]) => { - accountsForChain[address] = { - ...accountsForChain[address], - stakedBalance: balance, - }; - }); + Object.entries(stakedBalanceResult ?? {}).forEach( + ([address, balance]) => { + accountsForChain[address] = { + ...accountsForChain[address], + stakedBalance: balance, + }; + }, + ); // After all batches are processed, return the updated data return { chainId, accountsForChain }; diff --git a/tests/fake-block-tracker.ts b/tests/fake-block-tracker.ts index 55439211f1a..52474b9ae4a 100644 --- a/tests/fake-block-tracker.ts +++ b/tests/fake-block-tracker.ts @@ -30,4 +30,8 @@ export class FakeBlockTracker extends PollingBlockTracker { override async getLatestBlock() { return this.#latestBlockNumber; } + + override async checkForLatestBlock(): Promise { + return this.#latestBlockNumber; + } }