diff --git a/packages/assets-controllers/CHANGELOG.md b/packages/assets-controllers/CHANGELOG.md index b2211ffd559..c8d303a1544 100644 --- a/packages/assets-controllers/CHANGELOG.md +++ b/packages/assets-controllers/CHANGELOG.md @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Fixed + +- Fixed `MultichainBalancesController` not retrying balance fetches after unlock, leaving token lists empty; now retries after unlock. ([#8579](https://github.com/MetaMask/core/pull/8579)) + ### Added - Expose missing public `CurrencyRateController` methods through its messenger ([#8561](https://github.com/MetaMask/core/pull/8561)) diff --git a/packages/assets-controllers/src/MultichainBalancesController/MultichainBalancesController.test.ts b/packages/assets-controllers/src/MultichainBalancesController/MultichainBalancesController.test.ts index 84fec30388a..14b9f72cac6 100644 --- a/packages/assets-controllers/src/MultichainBalancesController/MultichainBalancesController.test.ts +++ b/packages/assets-controllers/src/MultichainBalancesController/MultichainBalancesController.test.ts @@ -158,6 +158,7 @@ function getRestrictedMessenger( 'AccountsController:accountRemoved', 'AccountsController:accountBalancesUpdated', 'MultichainAssetsController:accountAssetListUpdated', + 'KeyringController:stateChange', ], }); return multichainBalancesControllerMessenger; diff --git a/packages/assets-controllers/src/MultichainBalancesController/MultichainBalancesController.ts b/packages/assets-controllers/src/MultichainBalancesController/MultichainBalancesController.ts index a8c58ed4a61..d2db1e89fd0 100644 --- a/packages/assets-controllers/src/MultichainBalancesController/MultichainBalancesController.ts +++ b/packages/assets-controllers/src/MultichainBalancesController/MultichainBalancesController.ts @@ -16,7 +16,10 @@ import type { CaipAssetType, AccountBalancesUpdatedEventPayload, } from '@metamask/keyring-api'; -import type { KeyringControllerGetStateAction } from '@metamask/keyring-controller'; +import type { + KeyringControllerGetStateAction, + KeyringControllerStateChangeEvent, +} from '@metamask/keyring-controller'; import type { InternalAccount } from '@metamask/keyring-internal-api'; import { KeyringClient } from '@metamask/keyring-snap-client'; import type { Messenger } from '@metamask/messenger'; @@ -105,7 +108,8 @@ type AllowedEvents = | AccountsControllerAccountAddedEvent | AccountsControllerAccountRemovedEvent | AccountsControllerAccountBalancesUpdatesEvent - | MultichainAssetsControllerAccountAssetListUpdatedEvent; + | MultichainAssetsControllerAccountAssetListUpdatedEvent + | KeyringControllerStateChangeEvent; /** * Messenger type for the MultichainBalancesController. */ @@ -190,6 +194,31 @@ export class MultichainBalancesController extends BaseController< await this.#handleOnAccountAssetListUpdated(updatedAccountAssets); }, ); + + // When the keyring transitions from locked → unlocked, fetch balances for + // any non-EVM account that had its balance fetch skipped while locked. + let previouslyUnlocked = this.messenger.call( + 'KeyringController:getState', + ).isUnlocked; + this.messenger.subscribe( + 'KeyringController:stateChange', + ({ isUnlocked }) => { + const justUnlocked = isUnlocked && !previouslyUnlocked; + previouslyUnlocked = isUnlocked; + if (!justUnlocked) { + return; + } + for (const account of this.#listAccounts()) { + const hasBalance = + this.state.balances[account.id] && + Object.keys(this.state.balances[account.id]).length > 0; + if (!hasBalance) { + // eslint-disable-next-line no-void + void this.updateBalance(account.id); + } + } + }, + ); } /**