From 8c3c673e0292fe9ccc1dabbd36c8e7410e5a9f81 Mon Sep 17 00:00:00 2001 From: Hassan Malik Date: Tue, 10 Feb 2026 11:04:56 -0500 Subject: [PATCH 01/37] test: update tests with new controller state --- .../src/AccountsController.test.ts | 261 ++++++++++++++++++ 1 file changed, 261 insertions(+) diff --git a/packages/accounts-controller/src/AccountsController.test.ts b/packages/accounts-controller/src/AccountsController.test.ts index 546febe3cfe..f2aa68534cc 100644 --- a/packages/accounts-controller/src/AccountsController.test.ts +++ b/packages/accounts-controller/src/AccountsController.test.ts @@ -65,6 +65,7 @@ const actualUUID = jest.requireActual('uuid').v4; // We also use uuid.v4 in our const defaultState: AccountsControllerState = { internalAccounts: { accounts: {}, + accountIdByAddress: {}, selectedAccount: '', }, }; @@ -378,6 +379,9 @@ describe('AccountsController', () => { accounts: { [mockSnapAccount.id]: mockSnapAccount, }, + accountIdByAddress: { + [mockSnapAccount.address]: mockSnapAccount.id, + }, selectedAccount: mockSnapAccount.id, }, }, @@ -422,6 +426,9 @@ describe('AccountsController', () => { accounts: { [mockSnapAccount.id]: mockSnapAccount, }, + accountIdByAddress: { + [mockSnapAccount.address]: mockSnapAccount.id, + }, selectedAccount: mockSnapAccount.id, }, }, @@ -466,6 +473,9 @@ describe('AccountsController', () => { accounts: { [mockSnapAccount.id]: mockSnapAccount, }, + accountIdByAddress: { + [mockSnapAccount.address]: mockSnapAccount.id, + }, selectedAccount: mockSnapAccount.id, }, }, @@ -511,6 +521,9 @@ describe('AccountsController', () => { accounts: { [mockSnapAccount.id]: mockSnapAccount, }, + accountIdByAddress: { + [mockSnapAccount.address]: mockSnapAccount.id, + }, selectedAccount: mockSnapAccount.id, }, }, @@ -558,6 +571,9 @@ describe('AccountsController', () => { accounts: { [mockSnapAccount.id]: mockSnapAccount, }, + accountIdByAddress: { + [mockSnapAccount.address]: mockSnapAccount.id, + }, selectedAccount: mockSnapAccount.id, }, }, @@ -587,6 +603,7 @@ describe('AccountsController', () => { initialState: { internalAccounts: { accounts: {}, + accountIdByAddress: {}, selectedAccount: '', }, }, @@ -627,6 +644,7 @@ describe('AccountsController', () => { initialState: { internalAccounts: { accounts: {}, + accountIdByAddress: {}, selectedAccount: '', }, }, @@ -665,6 +683,7 @@ describe('AccountsController', () => { initialState: { internalAccounts: { accounts: {}, + accountIdByAddress: {}, selectedAccount: '', }, }, @@ -708,6 +727,10 @@ describe('AccountsController', () => { [mockAccount.id]: mockAccount, [mockAccount3.id]: mockAccount3, }, + accountIdByAddress: { + [mockAccount.address]: mockAccount.id, + [mockAccount3.address]: mockAccount3.id, + }, selectedAccount: mockAccount.id, }, }, @@ -777,6 +800,10 @@ describe('AccountsController', () => { [mockAccount.id]: mockAccount, [mockAccount4.id]: mockAccount4, }, + accountIdByAddress: { + [mockAccount.address]: mockAccount.id, + [mockAccount3.address]: mockAccount3.id, + }, selectedAccount: mockAccount.id, }, }, @@ -852,6 +879,10 @@ describe('AccountsController', () => { [mockAccount.id]: mockAccount, [mockAccount4.id]: mockAccount4, }, + accountIdByAddress: { + [mockAccount.address]: mockAccount.id, + [mockAccount4.address]: mockAccount4.id, + }, selectedAccount: mockAccount.id, }, }, @@ -913,6 +944,9 @@ describe('AccountsController', () => { accounts: { [mockAccount.id]: mockAccount, }, + accountIdByAddress: { + [mockAccount.address]: mockAccount.id, + }, selectedAccount: mockAccount.id, }, }, @@ -961,6 +995,10 @@ describe('AccountsController', () => { [mockAccount.id]: mockAccount, [mockAccount2.id]: mockAccount2, }, + accountIdByAddress: { + [mockAccount.address]: mockAccount.id, + [mockAccount2.address]: mockAccount2.id, + }, selectedAccount: mockAccount.id, }, }, @@ -1030,6 +1068,10 @@ describe('AccountsController', () => { [mockAccount.id]: mockAccount, [mockAccount2WithCustomName.id]: mockAccount2WithCustomName, }, + accountIdByAddress: { + [mockAccount.address]: mockAccount.id, + [mockAccount2WithCustomName.address]: mockAccount2WithCustomName.id, + }, selectedAccount: mockAccount.id, }, }, @@ -1101,6 +1143,7 @@ describe('AccountsController', () => { initialState: { internalAccounts: { accounts: {}, + accountIdByAddress: {}, selectedAccount: 'missing', }, }, @@ -1143,6 +1186,10 @@ describe('AccountsController', () => { [mockAccount.id]: mockAccount, [mockAccount3.id]: mockAccount3, }, + accountIdByAddress: { + [mockAccount.address]: mockAccount.id, + [mockAccount3.address]: mockAccount3.id, + }, selectedAccount: mockAccount.id, }, }, @@ -1178,6 +1225,9 @@ describe('AccountsController', () => { accounts: { [mockAccount.id]: mockAccount, }, + accountIdByAddress: { + [mockAccount.address]: mockAccount.id, + }, selectedAccount: mockAccount.id, }, }, @@ -1245,6 +1295,10 @@ describe('AccountsController', () => { [mockAccount.id]: mockAccount, [mockAccount2.id]: mockAccount2, }, + accountIdByAddress: { + [mockAccount.address]: mockAccount.id, + [mockAccount2.address]: mockAccount2.id, + }, selectedAccount: mockAccount.id, }, }, @@ -1301,6 +1355,10 @@ describe('AccountsController', () => { [mockAccount.id]: mockAccount, [mockAccount2.id]: mockAccount2, }, + accountIdByAddress: { + [mockAccount.address]: mockAccount.id, + [mockAccount2.address]: mockAccount2.id, + }, selectedAccount: 'missing-account', }, }, @@ -1365,6 +1423,10 @@ describe('AccountsController', () => { [mockAccount.id]: mockAccount, [mockAccount2.id]: mockAccount2WithoutLastSelected, }, + accountIdByAddress: { + [mockAccount.address]: mockAccount.id, + [mockAccount2.address]: mockAccount2.id, + }, selectedAccount: 'missing-account', }, }, @@ -1437,6 +1499,10 @@ describe('AccountsController', () => { [mockAccount.id]: mockAccountWithoutLastSelected, [mockAccount2.id]: mockAccount2WithoutLastSelected, }, + accountIdByAddress: { + [mockAccount.address]: mockAccount.id, + [mockAccount2.address]: mockAccount2.id, + }, selectedAccount: 'missing-account', }, }, @@ -1480,6 +1546,10 @@ describe('AccountsController', () => { [mockAccount.id]: mockAccount, [mockAccount3.id]: mockAccount3, }, + accountIdByAddress: { + [mockAccount.address]: mockAccount.id, + [mockAccount3.address]: mockAccount3.id, + }, selectedAccount: mockAccount.id, }, }, @@ -1557,6 +1627,9 @@ describe('AccountsController', () => { accounts: { [mockInitialAccount.id]: mockInitialAccount, }, + accountIdByAddress: { + [mockInitialAccount.address]: mockInitialAccount.id, + }, selectedAccount: mockInitialAccount.id, }, }, @@ -1635,6 +1708,10 @@ describe('AccountsController', () => { [mockExistingAccount1.id]: mockExistingAccount1, [mockExistingAccount2.id]: mockExistingAccount2, }, + accountIdByAddress: { + [mockExistingAccount1.address]: mockExistingAccount1.id, + [mockExistingAccount2.address]: mockExistingAccount2.id, + }, selectedAccount: 'unknown', }, }, @@ -1677,6 +1754,7 @@ describe('AccountsController', () => { initialState: { internalAccounts: { accounts: {}, + accountIdByAddress: {}, selectedAccount: '', }, }, @@ -1751,6 +1829,9 @@ describe('AccountsController', () => { accounts: { [account.id]: account, }, + accountIdByAddress: { + [account.address]: account.id, + }, selectedAccount: account.id, }, }, @@ -1858,6 +1939,11 @@ describe('AccountsController', () => { [mockNewerEvmAccount.id]: mockNewerEvmAccount, [mockBtcAccount.id]: mockBtcAccount, }, + accountIdByAddress: { + [mockOlderEvmAccount.address]: mockOlderEvmAccount.id, + [mockNewerEvmAccount.address]: mockNewerEvmAccount.id, + [mockBtcAccount.address]: mockBtcAccount.id, + }, selectedAccount: mockNewerEvmAccount.id, }, }, @@ -1883,6 +1969,10 @@ describe('AccountsController', () => { [mockOlderEvmAccount.id]: mockOlderEvmAccount, [mockBtcAccount.id]: mockBtcAccount, }, + accountIdByAddress: { + [mockOlderEvmAccount.address]: mockOlderEvmAccount.id, + [mockBtcAccount.address]: mockBtcAccount.id, + }, selectedAccount: mockBtcAccount.id, }, }, @@ -1908,6 +1998,9 @@ describe('AccountsController', () => { accounts: { [mockOlderEvmAccount.id]: mockOlderEvmAccount, }, + accountIdByAddress: { + [mockOlderEvmAccount.address]: mockOlderEvmAccount.id, + }, selectedAccount: mockOlderEvmAccount.id, }, }, @@ -2007,6 +2100,7 @@ describe('AccountsController', () => { initialState: { internalAccounts: { accounts: {}, + accountIdByAddress: {}, selectedAccount: '', }, }, @@ -2072,6 +2166,7 @@ describe('AccountsController', () => { initialState: { internalAccounts: { accounts: {}, + accountIdByAddress: {}, selectedAccount: '', }, }, @@ -2125,6 +2220,7 @@ describe('AccountsController', () => { initialState: { internalAccounts: { accounts: {}, + accountIdByAddress: {}, selectedAccount: '', }, }, @@ -2176,6 +2272,9 @@ describe('AccountsController', () => { accounts: { [mockAccount.id]: mockAccount, }, + accountIdByAddress: { + [mockAccount.address]: mockAccount.id, + }, selectedAccount: mockAccount.id, }, }, @@ -2246,6 +2345,7 @@ describe('AccountsController', () => { initialState: { internalAccounts: { accounts: {}, + accountIdByAddress: {}, selectedAccount: '', }, }, @@ -2318,6 +2418,7 @@ describe('AccountsController', () => { initialState: { internalAccounts: { accounts: {}, + accountIdByAddress: {}, selectedAccount: '', }, }, @@ -2390,6 +2491,7 @@ describe('AccountsController', () => { initialState: { internalAccounts: { accounts: {}, + accountIdByAddress: {}, selectedAccount: '', }, }, @@ -2440,6 +2542,7 @@ describe('AccountsController', () => { initialState: { internalAccounts: { accounts: {}, + accountIdByAddress: {}, selectedAccount: '', }, }, @@ -2539,6 +2642,10 @@ describe('AccountsController', () => { [mockExistingAccount1.id]: mockExistingAccount1, [mockExistingAccount2.id]: mockExistingAccount2, }, + accountIdByAddress: { + [mockExistingAccount1.address]: mockExistingAccount1.id, + [mockExistingAccount2.address]: mockExistingAccount2.id, + }, selectedAccount: 'unknown', }, }, @@ -2621,6 +2728,9 @@ describe('AccountsController', () => { accounts: { [mockHdAccount.id]: mockHdAccount, }, + accountIdByAddress: { + [mockHdAccount.address]: mockHdAccount.id, + }, selectedAccount: mockHdAccount.id, }, }, @@ -2708,6 +2818,9 @@ describe('AccountsController', () => { accounts: { [mockHdAccount.id]: mockHdAccount, }, + accountIdByAddress: { + [mockHdAccount.address]: mockHdAccount.id, + }, selectedAccount: mockHdAccount.id, }, }, @@ -2735,6 +2848,7 @@ describe('AccountsController', () => { initialState: { internalAccounts: { accounts: {}, + accountIdByAddress: {}, selectedAccount: '', }, }, @@ -2745,6 +2859,9 @@ describe('AccountsController', () => { accounts: { [mockAccount.id]: mockAccount, }, + accountIdByAddress: { + [mockAccount.address]: mockAccount.id, + }, selectedAccount: mockAccount.id, }, }); @@ -2754,6 +2871,9 @@ describe('AccountsController', () => { accounts: { [mockAccount.id]: mockAccount, }, + accountIdByAddress: { + [mockAccount.address]: mockAccount.id, + }, selectedAccount: mockAccount.id, }, }); @@ -2764,6 +2884,9 @@ describe('AccountsController', () => { initialState: { internalAccounts: { accounts: { [mockAccount.id]: mockAccount }, + accountIdByAddress: { + [mockAccount.address]: mockAccount.id, + }, selectedAccount: mockAccount.id, }, }, @@ -2777,6 +2900,9 @@ describe('AccountsController', () => { accounts: { [mockAccount.id]: mockAccount, }, + accountIdByAddress: { + [mockAccount.address]: mockAccount.id, + }, selectedAccount: mockAccount.id, }, }); @@ -2789,6 +2915,9 @@ describe('AccountsController', () => { initialState: { internalAccounts: { accounts: { [mockAccount.id]: mockAccount }, + accountIdByAddress: { + [mockAccount.address]: mockAccount.id, + }, selectedAccount: mockAccount.id, }, }, @@ -2803,6 +2932,9 @@ describe('AccountsController', () => { initialState: { internalAccounts: { accounts: { [mockAccount.id]: mockAccount }, + accountIdByAddress: { + [mockAccount.address]: mockAccount.id, + }, selectedAccount: mockAccount.id, }, }, @@ -2824,6 +2956,11 @@ describe('AccountsController', () => { [mockAccount2.id]: mockAccount2, [mockAccount3.id]: mockAccount3, }, + accountIdByAddress: { + [mockAccount.address]: mockAccount.id, + [mockAccount2.address]: mockAccount2.id, + [mockAccount3.address]: mockAccount3.id, + }, selectedAccount: mockAccount.id, }, }, @@ -2863,6 +3000,11 @@ describe('AccountsController', () => { [mockNewerEvmAccount.id]: mockNewerEvmAccount, [mockBtcAccount.id]: mockBtcAccount, }, + accountIdByAddress: { + [mockOlderEvmAccount.address]: mockOlderEvmAccount.id, + [mockNewerEvmAccount.address]: mockNewerEvmAccount.id, + [mockBtcAccount.address]: mockBtcAccount.id, + }, selectedAccount: lastSelectedAccount.id, }, }, @@ -2879,6 +3021,9 @@ describe('AccountsController', () => { accounts: { [mockBtcAccount.id]: mockBtcAccount, }, + accountIdByAddress: { + [mockBtcAccount.address]: mockBtcAccount.id, + }, selectedAccount: mockBtcAccount.id, }, }, @@ -2894,6 +3039,7 @@ describe('AccountsController', () => { initialState: { internalAccounts: { accounts: {}, + accountIdByAddress: {}, selectedAccount: '', }, }, @@ -2938,6 +3084,11 @@ describe('AccountsController', () => { [mockNewerEvmAccount.id]: mockNewerEvmAccount, [mockBtcAccount.id]: mockBtcAccount, }, + accountIdByAddress: { + [mockOlderEvmAccount.address]: mockOlderEvmAccount.id, + [mockNewerEvmAccount.address]: mockNewerEvmAccount.id, + [mockBtcAccount.address]: mockBtcAccount.id, + }, selectedAccount: selectedAccount.id, }, }, @@ -2963,6 +3114,11 @@ describe('AccountsController', () => { [mockNewerEvmAccount.id]: mockNewerEvmAccount, [mockBtcAccount.id]: mockBtcAccount, }, + accountIdByAddress: { + [mockOlderEvmAccount.address]: mockOlderEvmAccount.id, + [mockNewerEvmAccount.address]: mockNewerEvmAccount.id, + [mockBtcAccount.address]: mockBtcAccount.id, + }, selectedAccount: mockBtcAccount.id, }, }, @@ -2981,6 +3137,7 @@ describe('AccountsController', () => { initialState: { internalAccounts: { accounts: {}, + accountIdByAddress: {}, selectedAccount: '', }, }, @@ -3009,6 +3166,11 @@ describe('AccountsController', () => { [mockAccount2.id]: mockAccount2, [mockNonEvmAccount.id]: mockNonEvmAccount, }, + accountIdByAddress: { + [mockAccount.address]: mockAccount.id, + [mockAccount2.address]: mockAccount2.id, + [mockNonEvmAccount.address]: mockNonEvmAccount.id, + }, selectedAccount: mockAccount.id, }, }, @@ -3105,6 +3267,15 @@ describe('AccountsController', () => { [mockBtcMainnetAccount2.id]: mockBtcMainnetAccount2, [mockBtcTestnetAccount.id]: mockBtcTestnetAccount, }, + accountIdByAddress: { + [mockAccount.address]: mockAccount.id, + [mockAccount2.address]: mockAccount2.id, + [mockErc4337MainnetAccount.address]: mockErc4337MainnetAccount.id, + [mockErc4337TestnetAccount.address]: mockErc4337TestnetAccount.id, + [mockBtcMainnetAccount.address]: mockBtcMainnetAccount.id, + [mockBtcMainnetAccount2.address]: mockBtcMainnetAccount2.id, + [mockBtcTestnetAccount.address]: mockBtcTestnetAccount.id, + }, selectedAccount: mockAccount.id, }, }, @@ -3122,6 +3293,10 @@ describe('AccountsController', () => { [mockAccount.id]: mockAccount, [mockAccount2.id]: mockAccount2, }, + accountIdByAddress: { + [mockAccount.address]: mockAccount.id, + [mockAccount2.address]: mockAccount2.id, + }, selectedAccount: mockAccount.id, }, }, @@ -3142,6 +3317,9 @@ describe('AccountsController', () => { initialState: { internalAccounts: { accounts: { [mockAccount.id]: mockAccount }, + accountIdByAddress: { + [mockAccount.address]: mockAccount.id, + }, selectedAccount: mockAccount.id, }, }, @@ -3157,6 +3335,9 @@ describe('AccountsController', () => { initialState: { internalAccounts: { accounts: { [mockAccount.id]: mockAccount }, + accountIdByAddress: { + [mockAccount.address]: mockAccount.id, + }, selectedAccount: mockAccount.id, }, }, @@ -3177,6 +3358,10 @@ describe('AccountsController', () => { [mockAccount.id]: mockAccount, [mockAccount2.id]: mockAccount2, }, + accountIdByAddress: { + [mockAccount.address]: mockAccount.id, + [mockAccount2.address]: mockAccount2.id, + }, selectedAccount: mockAccount.id, }, }, @@ -3210,6 +3395,10 @@ describe('AccountsController', () => { [mockAccount.id]: mockAccount, [mockNonEvmAccount.id]: mockNonEvmAccount, }, + accountIdByAddress: { + [mockAccount.address]: mockAccount.id, + [mockNonEvmAccount.address]: mockNonEvmAccount.id, + }, selectedAccount: mockAccount.id, }, }, @@ -3243,6 +3432,9 @@ describe('AccountsController', () => { initialState: { internalAccounts: { accounts: { [mockAccount.id]: mockAccount }, + accountIdByAddress: { + [mockAccount.address]: mockAccount.id, + }, selectedAccount: mockAccount.id, }, }, @@ -3272,6 +3464,10 @@ describe('AccountsController', () => { [mockAccount.id]: mockAccount, [mockAccount2.id]: mockAccount2, }, + accountIdByAddress: { + [mockAccount.address]: mockAccount.id, + [mockAccount2.address]: mockAccount2.id, + }, selectedAccount: mockAccount.id, }, }, @@ -3332,6 +3528,9 @@ describe('AccountsController', () => { initialState: { internalAccounts: { accounts: { [mockAccount.id]: mockAccount }, + accountIdByAddress: { + [mockAccount.address]: mockAccount.id, + }, selectedAccount: mockAccount.id, }, }, @@ -3352,6 +3551,9 @@ describe('AccountsController', () => { initialState: { internalAccounts: { accounts: { [mockAccount.id]: mockAccount }, + accountIdByAddress: { + [mockAccount.address]: mockAccount.id, + }, selectedAccount: mockAccount.id, }, }, @@ -3371,6 +3573,9 @@ describe('AccountsController', () => { initialState: { internalAccounts: { accounts: { [mockAccount.id]: mockAccount }, + accountIdByAddress: { + [mockAccount.address]: mockAccount.id, + }, selectedAccount: mockAccount.id, }, }, @@ -3402,6 +3607,10 @@ describe('AccountsController', () => { [mockAccount.id]: mockAccount, [mockAccountWithName.id]: mockAccountWithName, }, + accountIdByAddress: { + [mockAccount.address]: mockAccount.id, + [mockAccountWithName.address]: mockAccountWithName.id, + }, selectedAccount: mockAccount.id, }, }, @@ -3419,6 +3628,9 @@ describe('AccountsController', () => { initialState: { internalAccounts: { accounts: { [mockAccount.id]: mockAccount }, + accountIdByAddress: { + [mockAccount.address]: mockAccount.id, + }, selectedAccount: mockAccount.id, }, }, @@ -3497,6 +3709,9 @@ describe('AccountsController', () => { accounts: { [mockAccount.id]: mockAccount, }, + accountIdByAddress: { + [mockAccount.address]: mockAccount.id, + }, selectedAccount: mockAccount.id, }, }, @@ -3536,6 +3751,9 @@ describe('AccountsController', () => { accounts: { [mockAccount.id]: mockAccount, }, + accountIdByAddress: { + [mockAccount.address]: mockAccount.id, + }, selectedAccount: mockAccount.id, }, }, @@ -3584,6 +3802,9 @@ describe('AccountsController', () => { initialState: { internalAccounts: { accounts: { [mockAccount.id]: mockAccount }, + accountIdByAddress: { + [mockAccount.address]: mockAccount.id, + }, selectedAccount: mockAccount.id, }, }, @@ -3601,6 +3822,9 @@ describe('AccountsController', () => { initialState: { internalAccounts: { accounts: { [mockAccount.id]: mockAccount }, + accountIdByAddress: { + [mockAccount.address]: mockAccount.id, + }, selectedAccount: mockAccount.id, }, }, @@ -3626,6 +3850,10 @@ describe('AccountsController', () => { [mockAccount.id]: mockAccount, [mockNonEvmAccount.id]: mockNonEvmAccount, }, + accountIdByAddress: { + [mockAccount.address]: mockAccount.id, + [mockNonEvmAccount.address]: mockNonEvmAccount.id, + }, selectedAccount: mockAccount.id, }, }, @@ -3662,6 +3890,9 @@ describe('AccountsController', () => { initialState: { internalAccounts: { accounts: { [mockAccount.id]: mockAccount }, + accountIdByAddress: { + [mockAccount.address]: mockAccount.id, + }, selectedAccount: mockAccount.id, }, }, @@ -3692,6 +3923,10 @@ describe('AccountsController', () => { [mockAccount.id]: mockAccount, [mockNonEvmAccount.id]: mockNonEvmAccount, }, + accountIdByAddress: { + [mockAccount.address]: mockAccount.id, + [mockNonEvmAccount.address]: mockNonEvmAccount.id, + }, selectedAccount: mockAccount.id, }, }, @@ -3721,6 +3956,10 @@ describe('AccountsController', () => { [mockAccount.id]: mockAccount, [mockNonEvmAccount.id]: mockNonEvmAccount, }, + accountIdByAddress: { + [mockAccount.address]: mockAccount.id, + [mockNonEvmAccount.address]: mockNonEvmAccount.id, + }, selectedAccount: mockAccount.id, }, }, @@ -3744,6 +3983,9 @@ describe('AccountsController', () => { initialState: { internalAccounts: { accounts: { [mockAccount.id]: mockAccount }, + accountIdByAddress: { + [mockAccount.address]: mockAccount.id, + }, selectedAccount: mockAccount.id, }, }, @@ -3772,6 +4014,10 @@ describe('AccountsController', () => { [mockAccount.id]: mockAccount, [mockAccount2.id]: mockAccount2, }, + accountIdByAddress: { + [mockAccount.address]: mockAccount.id, + [mockAccount2.address]: mockAccount2.id, + }, selectedAccount: mockAccount.id, }, }, @@ -3809,6 +4055,9 @@ describe('AccountsController', () => { initialState: { internalAccounts: { accounts: { [mockAccount.id]: mockAccount }, + accountIdByAddress: { + [mockAccount.address]: mockAccount.id, + }, selectedAccount: mockAccount.id, }, }, @@ -3828,6 +4077,9 @@ describe('AccountsController', () => { initialState: { internalAccounts: { accounts: { [mockAccount.id]: mockAccount }, + accountIdByAddress: { + [mockAccount.address]: mockAccount.id, + }, selectedAccount: mockAccount.id, }, }, @@ -3853,6 +4105,9 @@ describe('AccountsController', () => { initialState: { internalAccounts: { accounts: { [mockAccount.id]: mockAccount }, + accountIdByAddress: { + [mockAccount.address]: mockAccount.id, + }, selectedAccount: mockAccount.id, }, }, @@ -3873,6 +4128,9 @@ describe('AccountsController', () => { initialState: { internalAccounts: { accounts: { [mockAccount.id]: mockAccount }, + accountIdByAddress: { + [mockAccount.address]: mockAccount.id, + }, selectedAccount: mockAccount.id, }, }, @@ -3916,6 +4174,7 @@ describe('AccountsController', () => { ).toMatchInlineSnapshot(` Object { "internalAccounts": Object { + "accountIdByAddress": Object {}, "accounts": Object {}, "selectedAccount": "", }, @@ -3935,6 +4194,7 @@ describe('AccountsController', () => { ).toMatchInlineSnapshot(` Object { "internalAccounts": Object { + "accountIdByAddress": Object {}, "accounts": Object {}, "selectedAccount": "", }, @@ -3954,6 +4214,7 @@ describe('AccountsController', () => { ).toMatchInlineSnapshot(` Object { "internalAccounts": Object { + "accountIdByAddress": Object {}, "accounts": Object {}, "selectedAccount": "", }, From 9b006a55145cd093a7d0dc3c8d7e4936f0701187 Mon Sep 17 00:00:00 2001 From: Hassan Malik Date: Tue, 10 Feb 2026 11:05:29 -0500 Subject: [PATCH 02/37] chore: add new state to strict state typing --- packages/accounts-controller/src/typing.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/accounts-controller/src/typing.ts b/packages/accounts-controller/src/typing.ts index 1160df39ab3..44b03ef03ab 100644 --- a/packages/accounts-controller/src/typing.ts +++ b/packages/accounts-controller/src/typing.ts @@ -31,5 +31,6 @@ export type AccountsControllerStrictState = IsAccountControllerState<{ internalAccounts: { accounts: Record; selectedAccount: InternalAccount['id']; + accountIdByAddress: Record; }; }>; From 5238f32031a343fdca076628eb44929cbe573a27 Mon Sep 17 00:00:00 2001 From: Hassan Malik Date: Tue, 10 Feb 2026 11:06:30 -0500 Subject: [PATCH 03/37] feat: add getAccountIdByAddress mapping and update getAccountByAddress method to use O(1) lookup --- packages/accounts-controller/src/AccountsController.ts | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/packages/accounts-controller/src/AccountsController.ts b/packages/accounts-controller/src/AccountsController.ts index 58aace7d3fd..d55842bfc52 100644 --- a/packages/accounts-controller/src/AccountsController.ts +++ b/packages/accounts-controller/src/AccountsController.ts @@ -58,6 +58,7 @@ export type AccountId = string; export type AccountsControllerState = { internalAccounts: { accounts: Record; + accountIdByAddress: Record; selectedAccount: string; // id of the selected account }; }; @@ -228,6 +229,7 @@ const accountsControllerMetadata = { const defaultState: AccountsControllerState = { internalAccounts: { accounts: {}, + accountIdByAddress: {}, selectedAccount: '', }, }; @@ -437,9 +439,8 @@ export class AccountsController extends BaseController< * @returns The account with the specified address, or undefined if not found. */ getAccountByAddress(address: string): InternalAccount | undefined { - return this.listMultichainAccounts().find( - (account) => account.address.toLowerCase() === address.toLowerCase(), - ); + const accountId = this.state.internalAccounts.accountIdByAddress[address]; + return accountId ? this.getAccount(accountId) : undefined; } /** @@ -857,6 +858,7 @@ export class AccountsController extends BaseController< for (const patch of [patches.snap, patches.normal]) { for (const account of patch.removed) { delete internalAccounts.accounts[account.id]; + delete internalAccounts.accountIdByAddress[account.address]; diff.removed.push(account.id); } @@ -885,6 +887,8 @@ export class AccountsController extends BaseController< }, }; + internalAccounts.accountIdByAddress[account.address] = account.id; + diff.added.push(internalAccounts.accounts[account.id]); } } From 665ca3bcd649a3f8383d0bea9adcd6b5634122d6 Mon Sep 17 00:00:00 2001 From: Hassan Malik Date: Tue, 10 Feb 2026 11:14:31 -0500 Subject: [PATCH 04/37] chore: update changelog --- packages/accounts-controller/CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/packages/accounts-controller/CHANGELOG.md b/packages/accounts-controller/CHANGELOG.md index 473d223b096..f920d1a50ff 100644 --- a/packages/accounts-controller/CHANGELOG.md +++ b/packages/accounts-controller/CHANGELOG.md @@ -7,6 +7,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Added + +- **BREAKING:** Add `accountIdByAddress` mapping to state and update `getAccountByAddress` function ([#7893](https://github.com/MetaMask/core/pull/7893)) + - This state was added to improve lookup times for an account by address from O(n) to O(1). + ### Changed - Bump `@metamask/eth-snap-keyring` from `^18.0.0` to `^19.0.0` ([#7857](https://github.com/MetaMask/core/pull/7857)) From 56edc9c000b2cba3fd7a221a8fb858d2fb6387f8 Mon Sep 17 00:00:00 2001 From: Hassan Malik Date: Tue, 10 Feb 2026 11:32:31 -0500 Subject: [PATCH 05/37] fix: address bugbot comments --- .../src/AccountsController.ts | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/packages/accounts-controller/src/AccountsController.ts b/packages/accounts-controller/src/AccountsController.ts index d55842bfc52..ddddb3559c5 100644 --- a/packages/accounts-controller/src/AccountsController.ts +++ b/packages/accounts-controller/src/AccountsController.ts @@ -439,7 +439,8 @@ export class AccountsController extends BaseController< * @returns The account with the specified address, or undefined if not found. */ getAccountByAddress(address: string): InternalAccount | undefined { - const accountId = this.state.internalAccounts.accountIdByAddress[address]; + const accountId = + this.state.internalAccounts.accountIdByAddress[address.toLowerCase()]; return accountId ? this.getAccount(accountId) : undefined; } @@ -572,6 +573,8 @@ export class AccountsController extends BaseController< const existingInternalAccounts = this.state.internalAccounts.accounts; const internalAccounts: AccountsControllerState['internalAccounts']['accounts'] = {}; + const accountIdByAddress: AccountsControllerState['internalAccounts']['accountIdByAddress'] = + {}; const { keyrings } = this.messenger.call('KeyringController:getState'); for (const keyring of keyrings) { @@ -611,6 +614,9 @@ export class AccountsController extends BaseController< }, }; + accountIdByAddress[internalAccount.address.toLowerCase()] = + internalAccount.id; + // Increment the account index for this keyring. keyringAccountIndexes.set(keyringTypeName, keyringAccountIndex + 1); } @@ -618,6 +624,7 @@ export class AccountsController extends BaseController< this.#update((state) => { state.internalAccounts.accounts = internalAccounts; + state.internalAccounts.accountIdByAddress = accountIdByAddress; }); } @@ -858,7 +865,9 @@ export class AccountsController extends BaseController< for (const patch of [patches.snap, patches.normal]) { for (const account of patch.removed) { delete internalAccounts.accounts[account.id]; - delete internalAccounts.accountIdByAddress[account.address]; + delete internalAccounts.accountIdByAddress[ + account.address.toLowerCase() + ]; diff.removed.push(account.id); } @@ -887,7 +896,9 @@ export class AccountsController extends BaseController< }, }; - internalAccounts.accountIdByAddress[account.address] = account.id; + internalAccounts.accountIdByAddress[ + account.address.toLowerCase() + ] = account.id; diff.added.push(internalAccounts.accounts[account.id]); } From 67be1db8f92242c15fbd6623659835b177acfbe8 Mon Sep 17 00:00:00 2001 From: Hassan Malik Date: Tue, 10 Feb 2026 11:32:58 -0500 Subject: [PATCH 06/37] fix: lint fix --- packages/accounts-controller/src/AccountsController.test.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/accounts-controller/src/AccountsController.test.ts b/packages/accounts-controller/src/AccountsController.test.ts index f2aa68534cc..ea0e6686f2d 100644 --- a/packages/accounts-controller/src/AccountsController.test.ts +++ b/packages/accounts-controller/src/AccountsController.test.ts @@ -1070,7 +1070,8 @@ describe('AccountsController', () => { }, accountIdByAddress: { [mockAccount.address]: mockAccount.id, - [mockAccount2WithCustomName.address]: mockAccount2WithCustomName.id, + [mockAccount2WithCustomName.address]: + mockAccount2WithCustomName.id, }, selectedAccount: mockAccount.id, }, From a08cf5b6b4813d489e8a3220bcfb999cc5d8da6f Mon Sep 17 00:00:00 2001 From: Hassan Malik Date: Tue, 10 Feb 2026 11:51:30 -0500 Subject: [PATCH 07/37] fix: update test --- .../src/ProfileMetricsController.test.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/profile-metrics-controller/src/ProfileMetricsController.test.ts b/packages/profile-metrics-controller/src/ProfileMetricsController.test.ts index 350cfe5a6fc..0e5d330cf77 100644 --- a/packages/profile-metrics-controller/src/ProfileMetricsController.test.ts +++ b/packages/profile-metrics-controller/src/ProfileMetricsController.test.ts @@ -150,6 +150,10 @@ describe('ProfileMetricsController', () => { [account1.id]: account1, [account2.id]: account2, }, + accountIdByAddress: { + [account1.address]: account1.id, + [account2.address]: account2.id, + }, selectedAccount: account1.id, }, }; From 263f1d754c2b203c5e31dffff0ca7252337de19c Mon Sep 17 00:00:00 2001 From: Hassan Malik Date: Tue, 10 Feb 2026 11:54:39 -0500 Subject: [PATCH 08/37] fix: fix test --- packages/accounts-controller/src/AccountsController.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/accounts-controller/src/AccountsController.test.ts b/packages/accounts-controller/src/AccountsController.test.ts index ea0e6686f2d..893cc501ea2 100644 --- a/packages/accounts-controller/src/AccountsController.test.ts +++ b/packages/accounts-controller/src/AccountsController.test.ts @@ -802,7 +802,7 @@ describe('AccountsController', () => { }, accountIdByAddress: { [mockAccount.address]: mockAccount.id, - [mockAccount3.address]: mockAccount3.id, + [mockAccount4.address]: mockAccount4.id, }, selectedAccount: mockAccount.id, }, From b5e251d657ff5ca5fbab59484b349dc9ab1d35b9 Mon Sep 17 00:00:00 2001 From: Hassan Malik Date: Tue, 10 Feb 2026 12:42:50 -0500 Subject: [PATCH 09/37] refactor: change accountIdByAddress to not be persisted --- .../src/AccountsController.test.ts | 518 +++++++++--------- .../src/AccountsController.ts | 27 +- packages/accounts-controller/src/typing.ts | 2 +- .../src/ProfileMetricsController.test.ts | 8 +- 4 files changed, 275 insertions(+), 280 deletions(-) diff --git a/packages/accounts-controller/src/AccountsController.test.ts b/packages/accounts-controller/src/AccountsController.test.ts index 893cc501ea2..f15cc3fdadf 100644 --- a/packages/accounts-controller/src/AccountsController.test.ts +++ b/packages/accounts-controller/src/AccountsController.test.ts @@ -65,9 +65,9 @@ const actualUUID = jest.requireActual('uuid').v4; // We also use uuid.v4 in our const defaultState: AccountsControllerState = { internalAccounts: { accounts: {}, - accountIdByAddress: {}, selectedAccount: '', }, + accountIdByAddress: {}, }; const mockGetKeyringByType = jest.fn(); @@ -379,11 +379,11 @@ describe('AccountsController', () => { accounts: { [mockSnapAccount.id]: mockSnapAccount, }, - accountIdByAddress: { - [mockSnapAccount.address]: mockSnapAccount.id, - }, selectedAccount: mockSnapAccount.id, }, + accountIdByAddress: { + [mockSnapAccount.address]: mockSnapAccount.id, + }, }, messenger, }); @@ -426,11 +426,11 @@ describe('AccountsController', () => { accounts: { [mockSnapAccount.id]: mockSnapAccount, }, - accountIdByAddress: { - [mockSnapAccount.address]: mockSnapAccount.id, - }, selectedAccount: mockSnapAccount.id, }, + accountIdByAddress: { + [mockSnapAccount.address]: mockSnapAccount.id, + }, }, messenger, }); @@ -473,11 +473,11 @@ describe('AccountsController', () => { accounts: { [mockSnapAccount.id]: mockSnapAccount, }, - accountIdByAddress: { - [mockSnapAccount.address]: mockSnapAccount.id, - }, selectedAccount: mockSnapAccount.id, }, + accountIdByAddress: { + [mockSnapAccount.address]: mockSnapAccount.id, + }, }, messenger, }); @@ -521,11 +521,11 @@ describe('AccountsController', () => { accounts: { [mockSnapAccount.id]: mockSnapAccount, }, - accountIdByAddress: { - [mockSnapAccount.address]: mockSnapAccount.id, - }, selectedAccount: mockSnapAccount.id, }, + accountIdByAddress: { + [mockSnapAccount.address]: mockSnapAccount.id, + }, }, messenger, }); @@ -571,11 +571,11 @@ describe('AccountsController', () => { accounts: { [mockSnapAccount.id]: mockSnapAccount, }, - accountIdByAddress: { - [mockSnapAccount.address]: mockSnapAccount.id, - }, selectedAccount: mockSnapAccount.id, }, + accountIdByAddress: { + [mockSnapAccount.address]: mockSnapAccount.id, + }, }, messenger, }); @@ -603,9 +603,9 @@ describe('AccountsController', () => { initialState: { internalAccounts: { accounts: {}, - accountIdByAddress: {}, selectedAccount: '', }, + accountIdByAddress: {}, }, messenger, }); @@ -644,9 +644,9 @@ describe('AccountsController', () => { initialState: { internalAccounts: { accounts: {}, - accountIdByAddress: {}, selectedAccount: '', }, + accountIdByAddress: {}, }, messenger, }); @@ -683,9 +683,9 @@ describe('AccountsController', () => { initialState: { internalAccounts: { accounts: {}, - accountIdByAddress: {}, selectedAccount: '', }, + accountIdByAddress: {}, }, messenger, }); @@ -727,12 +727,12 @@ describe('AccountsController', () => { [mockAccount.id]: mockAccount, [mockAccount3.id]: mockAccount3, }, - accountIdByAddress: { - [mockAccount.address]: mockAccount.id, - [mockAccount3.address]: mockAccount3.id, - }, selectedAccount: mockAccount.id, }, + accountIdByAddress: { + [mockAccount.address]: mockAccount.id, + [mockAccount3.address]: mockAccount3.id, + }, }, messenger, }); @@ -800,12 +800,12 @@ describe('AccountsController', () => { [mockAccount.id]: mockAccount, [mockAccount4.id]: mockAccount4, }, - accountIdByAddress: { - [mockAccount.address]: mockAccount.id, - [mockAccount4.address]: mockAccount4.id, - }, selectedAccount: mockAccount.id, }, + accountIdByAddress: { + [mockAccount.address]: mockAccount.id, + [mockAccount4.address]: mockAccount4.id, + }, }, messenger, }); @@ -879,12 +879,12 @@ describe('AccountsController', () => { [mockAccount.id]: mockAccount, [mockAccount4.id]: mockAccount4, }, - accountIdByAddress: { - [mockAccount.address]: mockAccount.id, - [mockAccount4.address]: mockAccount4.id, - }, selectedAccount: mockAccount.id, }, + accountIdByAddress: { + [mockAccount.address]: mockAccount.id, + [mockAccount4.address]: mockAccount4.id, + }, }, messenger, }); @@ -944,11 +944,11 @@ describe('AccountsController', () => { accounts: { [mockAccount.id]: mockAccount, }, - accountIdByAddress: { - [mockAccount.address]: mockAccount.id, - }, selectedAccount: mockAccount.id, }, + accountIdByAddress: { + [mockAccount.address]: mockAccount.id, + }, }, messenger, }); @@ -995,12 +995,12 @@ describe('AccountsController', () => { [mockAccount.id]: mockAccount, [mockAccount2.id]: mockAccount2, }, - accountIdByAddress: { - [mockAccount.address]: mockAccount.id, - [mockAccount2.address]: mockAccount2.id, - }, selectedAccount: mockAccount.id, }, + accountIdByAddress: { + [mockAccount.address]: mockAccount.id, + [mockAccount2.address]: mockAccount2.id, + }, }, messenger, }); @@ -1068,13 +1068,13 @@ describe('AccountsController', () => { [mockAccount.id]: mockAccount, [mockAccount2WithCustomName.id]: mockAccount2WithCustomName, }, - accountIdByAddress: { - [mockAccount.address]: mockAccount.id, - [mockAccount2WithCustomName.address]: - mockAccount2WithCustomName.id, - }, selectedAccount: mockAccount.id, }, + accountIdByAddress: { + [mockAccount.address]: mockAccount.id, + [mockAccount2WithCustomName.address]: + mockAccount2WithCustomName.id, + }, }, messenger, }); @@ -1144,9 +1144,9 @@ describe('AccountsController', () => { initialState: { internalAccounts: { accounts: {}, - accountIdByAddress: {}, selectedAccount: 'missing', }, + accountIdByAddress: {}, }, messenger, }); @@ -1187,12 +1187,12 @@ describe('AccountsController', () => { [mockAccount.id]: mockAccount, [mockAccount3.id]: mockAccount3, }, - accountIdByAddress: { - [mockAccount.address]: mockAccount.id, - [mockAccount3.address]: mockAccount3.id, - }, selectedAccount: mockAccount.id, }, + accountIdByAddress: { + [mockAccount.address]: mockAccount.id, + [mockAccount3.address]: mockAccount3.id, + }, }, messenger, }); @@ -1226,11 +1226,11 @@ describe('AccountsController', () => { accounts: { [mockAccount.id]: mockAccount, }, - accountIdByAddress: { - [mockAccount.address]: mockAccount.id, - }, selectedAccount: mockAccount.id, }, + accountIdByAddress: { + [mockAccount.address]: mockAccount.id, + }, }, messenger, }); @@ -1296,12 +1296,12 @@ describe('AccountsController', () => { [mockAccount.id]: mockAccount, [mockAccount2.id]: mockAccount2, }, - accountIdByAddress: { - [mockAccount.address]: mockAccount.id, - [mockAccount2.address]: mockAccount2.id, - }, selectedAccount: mockAccount.id, }, + accountIdByAddress: { + [mockAccount.address]: mockAccount.id, + [mockAccount2.address]: mockAccount2.id, + }, }, messenger, }); @@ -1356,12 +1356,12 @@ describe('AccountsController', () => { [mockAccount.id]: mockAccount, [mockAccount2.id]: mockAccount2, }, - accountIdByAddress: { - [mockAccount.address]: mockAccount.id, - [mockAccount2.address]: mockAccount2.id, - }, selectedAccount: 'missing-account', }, + accountIdByAddress: { + [mockAccount.address]: mockAccount.id, + [mockAccount2.address]: mockAccount2.id, + }, }, messenger, }); @@ -1424,12 +1424,12 @@ describe('AccountsController', () => { [mockAccount.id]: mockAccount, [mockAccount2.id]: mockAccount2WithoutLastSelected, }, - accountIdByAddress: { - [mockAccount.address]: mockAccount.id, - [mockAccount2.address]: mockAccount2.id, - }, selectedAccount: 'missing-account', }, + accountIdByAddress: { + [mockAccount.address]: mockAccount.id, + [mockAccount2.address]: mockAccount2.id, + }, }, messenger, }); @@ -1500,12 +1500,12 @@ describe('AccountsController', () => { [mockAccount.id]: mockAccountWithoutLastSelected, [mockAccount2.id]: mockAccount2WithoutLastSelected, }, - accountIdByAddress: { - [mockAccount.address]: mockAccount.id, - [mockAccount2.address]: mockAccount2.id, - }, selectedAccount: 'missing-account', }, + accountIdByAddress: { + [mockAccount.address]: mockAccount.id, + [mockAccount2.address]: mockAccount2.id, + }, }, messenger, }); @@ -1547,12 +1547,12 @@ describe('AccountsController', () => { [mockAccount.id]: mockAccount, [mockAccount3.id]: mockAccount3, }, - accountIdByAddress: { - [mockAccount.address]: mockAccount.id, - [mockAccount3.address]: mockAccount3.id, - }, selectedAccount: mockAccount.id, }, + accountIdByAddress: { + [mockAccount.address]: mockAccount.id, + [mockAccount3.address]: mockAccount3.id, + }, }, messenger, }); @@ -1628,11 +1628,11 @@ describe('AccountsController', () => { accounts: { [mockInitialAccount.id]: mockInitialAccount, }, - accountIdByAddress: { - [mockInitialAccount.address]: mockInitialAccount.id, - }, selectedAccount: mockInitialAccount.id, }, + accountIdByAddress: { + [mockInitialAccount.address]: mockInitialAccount.id, + }, }, messenger, }); @@ -1709,12 +1709,12 @@ describe('AccountsController', () => { [mockExistingAccount1.id]: mockExistingAccount1, [mockExistingAccount2.id]: mockExistingAccount2, }, - accountIdByAddress: { - [mockExistingAccount1.address]: mockExistingAccount1.id, - [mockExistingAccount2.address]: mockExistingAccount2.id, - }, selectedAccount: 'unknown', }, + accountIdByAddress: { + [mockExistingAccount1.address]: mockExistingAccount1.id, + [mockExistingAccount2.address]: mockExistingAccount2.id, + }, }, messenger, }); @@ -1755,9 +1755,9 @@ describe('AccountsController', () => { initialState: { internalAccounts: { accounts: {}, - accountIdByAddress: {}, selectedAccount: '', }, + accountIdByAddress: {}, }, messenger, }); @@ -1830,11 +1830,11 @@ describe('AccountsController', () => { accounts: { [account.id]: account, }, - accountIdByAddress: { - [account.address]: account.id, - }, selectedAccount: account.id, }, + accountIdByAddress: { + [account.address]: account.id, + }, }, messenger, }); @@ -1940,13 +1940,13 @@ describe('AccountsController', () => { [mockNewerEvmAccount.id]: mockNewerEvmAccount, [mockBtcAccount.id]: mockBtcAccount, }, - accountIdByAddress: { - [mockOlderEvmAccount.address]: mockOlderEvmAccount.id, - [mockNewerEvmAccount.address]: mockNewerEvmAccount.id, - [mockBtcAccount.address]: mockBtcAccount.id, - }, selectedAccount: mockNewerEvmAccount.id, }, + accountIdByAddress: { + [mockOlderEvmAccount.address]: mockOlderEvmAccount.id, + [mockNewerEvmAccount.address]: mockNewerEvmAccount.id, + [mockBtcAccount.address]: mockBtcAccount.id, + }, }, messenger, }); @@ -1970,12 +1970,12 @@ describe('AccountsController', () => { [mockOlderEvmAccount.id]: mockOlderEvmAccount, [mockBtcAccount.id]: mockBtcAccount, }, - accountIdByAddress: { - [mockOlderEvmAccount.address]: mockOlderEvmAccount.id, - [mockBtcAccount.address]: mockBtcAccount.id, - }, selectedAccount: mockBtcAccount.id, }, + accountIdByAddress: { + [mockOlderEvmAccount.address]: mockOlderEvmAccount.id, + [mockBtcAccount.address]: mockBtcAccount.id, + }, }, messenger, }); @@ -1999,11 +1999,11 @@ describe('AccountsController', () => { accounts: { [mockOlderEvmAccount.id]: mockOlderEvmAccount, }, - accountIdByAddress: { - [mockOlderEvmAccount.address]: mockOlderEvmAccount.id, - }, selectedAccount: mockOlderEvmAccount.id, }, + accountIdByAddress: { + [mockOlderEvmAccount.address]: mockOlderEvmAccount.id, + }, }, messenger, }); @@ -2101,9 +2101,9 @@ describe('AccountsController', () => { initialState: { internalAccounts: { accounts: {}, - accountIdByAddress: {}, selectedAccount: '', }, + accountIdByAddress: {}, }, messenger, }); @@ -2167,9 +2167,9 @@ describe('AccountsController', () => { initialState: { internalAccounts: { accounts: {}, - accountIdByAddress: {}, selectedAccount: '', }, + accountIdByAddress: {}, }, messenger, }); @@ -2221,9 +2221,9 @@ describe('AccountsController', () => { initialState: { internalAccounts: { accounts: {}, - accountIdByAddress: {}, selectedAccount: '', }, + accountIdByAddress: {}, }, messenger, }); @@ -2273,11 +2273,11 @@ describe('AccountsController', () => { accounts: { [mockAccount.id]: mockAccount, }, - accountIdByAddress: { - [mockAccount.address]: mockAccount.id, - }, selectedAccount: mockAccount.id, }, + accountIdByAddress: { + [mockAccount.address]: mockAccount.id, + }, }, messenger, }); @@ -2346,9 +2346,9 @@ describe('AccountsController', () => { initialState: { internalAccounts: { accounts: {}, - accountIdByAddress: {}, selectedAccount: '', }, + accountIdByAddress: {}, }, messenger, }); @@ -2419,9 +2419,9 @@ describe('AccountsController', () => { initialState: { internalAccounts: { accounts: {}, - accountIdByAddress: {}, selectedAccount: '', }, + accountIdByAddress: {}, }, messenger, }); @@ -2492,9 +2492,9 @@ describe('AccountsController', () => { initialState: { internalAccounts: { accounts: {}, - accountIdByAddress: {}, selectedAccount: '', }, + accountIdByAddress: {}, }, messenger, }); @@ -2543,9 +2543,9 @@ describe('AccountsController', () => { initialState: { internalAccounts: { accounts: {}, - accountIdByAddress: {}, selectedAccount: '', }, + accountIdByAddress: {}, }, messenger, }); @@ -2643,12 +2643,12 @@ describe('AccountsController', () => { [mockExistingAccount1.id]: mockExistingAccount1, [mockExistingAccount2.id]: mockExistingAccount2, }, - accountIdByAddress: { - [mockExistingAccount1.address]: mockExistingAccount1.id, - [mockExistingAccount2.address]: mockExistingAccount2.id, - }, selectedAccount: 'unknown', }, + accountIdByAddress: { + [mockExistingAccount1.address]: mockExistingAccount1.id, + [mockExistingAccount2.address]: mockExistingAccount2.id, + }, }, messenger, }); @@ -2729,11 +2729,11 @@ describe('AccountsController', () => { accounts: { [mockHdAccount.id]: mockHdAccount, }, - accountIdByAddress: { - [mockHdAccount.address]: mockHdAccount.id, - }, selectedAccount: mockHdAccount.id, }, + accountIdByAddress: { + [mockHdAccount.address]: mockHdAccount.id, + }, }, messenger, }); @@ -2819,11 +2819,11 @@ describe('AccountsController', () => { accounts: { [mockHdAccount.id]: mockHdAccount, }, - accountIdByAddress: { - [mockHdAccount.address]: mockHdAccount.id, - }, selectedAccount: mockHdAccount.id, }, + accountIdByAddress: { + [mockHdAccount.address]: mockHdAccount.id, + }, }, messenger, }); @@ -2849,9 +2849,9 @@ describe('AccountsController', () => { initialState: { internalAccounts: { accounts: {}, - accountIdByAddress: {}, selectedAccount: '', }, + accountIdByAddress: {}, }, }); @@ -2860,11 +2860,9 @@ describe('AccountsController', () => { accounts: { [mockAccount.id]: mockAccount, }, - accountIdByAddress: { - [mockAccount.address]: mockAccount.id, - }, selectedAccount: mockAccount.id, }, + accountIdByAddress: {}, }); expect(accountsController.state).toStrictEqual({ @@ -2872,11 +2870,9 @@ describe('AccountsController', () => { accounts: { [mockAccount.id]: mockAccount, }, - accountIdByAddress: { - [mockAccount.address]: mockAccount.id, - }, selectedAccount: mockAccount.id, }, + accountIdByAddress: {}, }); }); @@ -2885,11 +2881,11 @@ describe('AccountsController', () => { initialState: { internalAccounts: { accounts: { [mockAccount.id]: mockAccount }, - accountIdByAddress: { - [mockAccount.address]: mockAccount.id, - }, selectedAccount: mockAccount.id, }, + accountIdByAddress: { + [mockAccount.address]: mockAccount.id, + }, }, }); @@ -2901,11 +2897,11 @@ describe('AccountsController', () => { accounts: { [mockAccount.id]: mockAccount, }, - accountIdByAddress: { - [mockAccount.address]: mockAccount.id, - }, selectedAccount: mockAccount.id, }, + accountIdByAddress: { + [mockAccount.address]: mockAccount.id, + }, }); }); }); @@ -2916,11 +2912,11 @@ describe('AccountsController', () => { initialState: { internalAccounts: { accounts: { [mockAccount.id]: mockAccount }, - accountIdByAddress: { - [mockAccount.address]: mockAccount.id, - }, selectedAccount: mockAccount.id, }, + accountIdByAddress: { + [mockAccount.address]: mockAccount.id, + }, }, }); @@ -2933,11 +2929,11 @@ describe('AccountsController', () => { initialState: { internalAccounts: { accounts: { [mockAccount.id]: mockAccount }, - accountIdByAddress: { - [mockAccount.address]: mockAccount.id, - }, selectedAccount: mockAccount.id, }, + accountIdByAddress: { + [mockAccount.address]: mockAccount.id, + }, }, }); @@ -2957,13 +2953,13 @@ describe('AccountsController', () => { [mockAccount2.id]: mockAccount2, [mockAccount3.id]: mockAccount3, }, - accountIdByAddress: { - [mockAccount.address]: mockAccount.id, - [mockAccount2.address]: mockAccount2.id, - [mockAccount3.address]: mockAccount3.id, - }, selectedAccount: mockAccount.id, }, + accountIdByAddress: { + [mockAccount.address]: mockAccount.id, + [mockAccount2.address]: mockAccount2.id, + [mockAccount3.address]: mockAccount3.id, + }, }, }); @@ -3001,13 +2997,13 @@ describe('AccountsController', () => { [mockNewerEvmAccount.id]: mockNewerEvmAccount, [mockBtcAccount.id]: mockBtcAccount, }, - accountIdByAddress: { - [mockOlderEvmAccount.address]: mockOlderEvmAccount.id, - [mockNewerEvmAccount.address]: mockNewerEvmAccount.id, - [mockBtcAccount.address]: mockBtcAccount.id, - }, selectedAccount: lastSelectedAccount.id, }, + accountIdByAddress: { + [mockOlderEvmAccount.address]: mockOlderEvmAccount.id, + [mockNewerEvmAccount.address]: mockNewerEvmAccount.id, + [mockBtcAccount.address]: mockBtcAccount.id, + }, }, }); @@ -3022,11 +3018,11 @@ describe('AccountsController', () => { accounts: { [mockBtcAccount.id]: mockBtcAccount, }, - accountIdByAddress: { - [mockBtcAccount.address]: mockBtcAccount.id, - }, selectedAccount: mockBtcAccount.id, }, + accountIdByAddress: { + [mockBtcAccount.address]: mockBtcAccount.id, + }, }, }); @@ -3040,9 +3036,9 @@ describe('AccountsController', () => { initialState: { internalAccounts: { accounts: {}, - accountIdByAddress: {}, selectedAccount: '', }, + accountIdByAddress: {}, }, }); @@ -3085,13 +3081,13 @@ describe('AccountsController', () => { [mockNewerEvmAccount.id]: mockNewerEvmAccount, [mockBtcAccount.id]: mockBtcAccount, }, - accountIdByAddress: { - [mockOlderEvmAccount.address]: mockOlderEvmAccount.id, - [mockNewerEvmAccount.address]: mockNewerEvmAccount.id, - [mockBtcAccount.address]: mockBtcAccount.id, - }, selectedAccount: selectedAccount.id, }, + accountIdByAddress: { + [mockOlderEvmAccount.address]: mockOlderEvmAccount.id, + [mockNewerEvmAccount.address]: mockNewerEvmAccount.id, + [mockBtcAccount.address]: mockBtcAccount.id, + }, }, }); @@ -3115,13 +3111,13 @@ describe('AccountsController', () => { [mockNewerEvmAccount.id]: mockNewerEvmAccount, [mockBtcAccount.id]: mockBtcAccount, }, - accountIdByAddress: { - [mockOlderEvmAccount.address]: mockOlderEvmAccount.id, - [mockNewerEvmAccount.address]: mockNewerEvmAccount.id, - [mockBtcAccount.address]: mockBtcAccount.id, - }, selectedAccount: mockBtcAccount.id, }, + accountIdByAddress: { + [mockOlderEvmAccount.address]: mockOlderEvmAccount.id, + [mockNewerEvmAccount.address]: mockNewerEvmAccount.id, + [mockBtcAccount.address]: mockBtcAccount.id, + }, }, }); @@ -3138,9 +3134,9 @@ describe('AccountsController', () => { initialState: { internalAccounts: { accounts: {}, - accountIdByAddress: {}, selectedAccount: '', }, + accountIdByAddress: {}, }, }); @@ -3167,13 +3163,13 @@ describe('AccountsController', () => { [mockAccount2.id]: mockAccount2, [mockNonEvmAccount.id]: mockNonEvmAccount, }, - accountIdByAddress: { - [mockAccount.address]: mockAccount.id, - [mockAccount2.address]: mockAccount2.id, - [mockNonEvmAccount.address]: mockNonEvmAccount.id, - }, selectedAccount: mockAccount.id, }, + accountIdByAddress: { + [mockAccount.address]: mockAccount.id, + [mockAccount2.address]: mockAccount2.id, + [mockNonEvmAccount.address]: mockNonEvmAccount.id, + }, }, }); @@ -3268,17 +3264,17 @@ describe('AccountsController', () => { [mockBtcMainnetAccount2.id]: mockBtcMainnetAccount2, [mockBtcTestnetAccount.id]: mockBtcTestnetAccount, }, - accountIdByAddress: { - [mockAccount.address]: mockAccount.id, - [mockAccount2.address]: mockAccount2.id, - [mockErc4337MainnetAccount.address]: mockErc4337MainnetAccount.id, - [mockErc4337TestnetAccount.address]: mockErc4337TestnetAccount.id, - [mockBtcMainnetAccount.address]: mockBtcMainnetAccount.id, - [mockBtcMainnetAccount2.address]: mockBtcMainnetAccount2.id, - [mockBtcTestnetAccount.address]: mockBtcTestnetAccount.id, - }, selectedAccount: mockAccount.id, }, + accountIdByAddress: { + [mockAccount.address]: mockAccount.id, + [mockAccount2.address]: mockAccount2.id, + [mockErc4337MainnetAccount.address]: mockErc4337MainnetAccount.id, + [mockErc4337TestnetAccount.address]: mockErc4337TestnetAccount.id, + [mockBtcMainnetAccount.address]: mockBtcMainnetAccount.id, + [mockBtcMainnetAccount2.address]: mockBtcMainnetAccount2.id, + [mockBtcTestnetAccount.address]: mockBtcTestnetAccount.id, + }, }, }); expect( @@ -3294,12 +3290,12 @@ describe('AccountsController', () => { [mockAccount.id]: mockAccount, [mockAccount2.id]: mockAccount2, }, - accountIdByAddress: { - [mockAccount.address]: mockAccount.id, - [mockAccount2.address]: mockAccount2.id, - }, selectedAccount: mockAccount.id, }, + accountIdByAddress: { + [mockAccount.address]: mockAccount.id, + [mockAccount2.address]: mockAccount2.id, + }, }, }); @@ -3318,11 +3314,11 @@ describe('AccountsController', () => { initialState: { internalAccounts: { accounts: { [mockAccount.id]: mockAccount }, - accountIdByAddress: { - [mockAccount.address]: mockAccount.id, - }, selectedAccount: mockAccount.id, }, + accountIdByAddress: { + [mockAccount.address]: mockAccount.id, + }, }, }); const result = accountsController.getAccountExpect(mockAccount.id); @@ -3336,11 +3332,11 @@ describe('AccountsController', () => { initialState: { internalAccounts: { accounts: { [mockAccount.id]: mockAccount }, - accountIdByAddress: { - [mockAccount.address]: mockAccount.id, - }, selectedAccount: mockAccount.id, }, + accountIdByAddress: { + [mockAccount.address]: mockAccount.id, + }, }, }); @@ -3359,12 +3355,12 @@ describe('AccountsController', () => { [mockAccount.id]: mockAccount, [mockAccount2.id]: mockAccount2, }, - accountIdByAddress: { - [mockAccount.address]: mockAccount.id, - [mockAccount2.address]: mockAccount2.id, - }, selectedAccount: mockAccount.id, }, + accountIdByAddress: { + [mockAccount.address]: mockAccount.id, + [mockAccount2.address]: mockAccount2.id, + }, }, }); @@ -3396,12 +3392,12 @@ describe('AccountsController', () => { [mockAccount.id]: mockAccount, [mockNonEvmAccount.id]: mockNonEvmAccount, }, - accountIdByAddress: { - [mockAccount.address]: mockAccount.id, - [mockNonEvmAccount.address]: mockNonEvmAccount.id, - }, selectedAccount: mockAccount.id, }, + accountIdByAddress: { + [mockAccount.address]: mockAccount.id, + [mockNonEvmAccount.address]: mockNonEvmAccount.id, + }, }, }); @@ -3433,11 +3429,11 @@ describe('AccountsController', () => { initialState: { internalAccounts: { accounts: { [mockAccount.id]: mockAccount }, - accountIdByAddress: { - [mockAccount.address]: mockAccount.id, - }, selectedAccount: mockAccount.id, }, + accountIdByAddress: { + [mockAccount.address]: mockAccount.id, + }, }, }; @@ -3465,12 +3461,12 @@ describe('AccountsController', () => { [mockAccount.id]: mockAccount, [mockAccount2.id]: mockAccount2, }, - accountIdByAddress: { - [mockAccount.address]: mockAccount.id, - [mockAccount2.address]: mockAccount2.id, - }, selectedAccount: mockAccount.id, }, + accountIdByAddress: { + [mockAccount.address]: mockAccount.id, + [mockAccount2.address]: mockAccount2.id, + }, }, }); @@ -3529,11 +3525,11 @@ describe('AccountsController', () => { initialState: { internalAccounts: { accounts: { [mockAccount.id]: mockAccount }, - accountIdByAddress: { - [mockAccount.address]: mockAccount.id, - }, selectedAccount: mockAccount.id, }, + accountIdByAddress: { + [mockAccount.address]: mockAccount.id, + }, }, }); accountsController.setAccountName(mockAccount.id, 'new name'); @@ -3552,11 +3548,11 @@ describe('AccountsController', () => { initialState: { internalAccounts: { accounts: { [mockAccount.id]: mockAccount }, - accountIdByAddress: { - [mockAccount.address]: mockAccount.id, - }, selectedAccount: mockAccount.id, }, + accountIdByAddress: { + [mockAccount.address]: mockAccount.id, + }, }, }); @@ -3574,11 +3570,11 @@ describe('AccountsController', () => { initialState: { internalAccounts: { accounts: { [mockAccount.id]: mockAccount }, - accountIdByAddress: { - [mockAccount.address]: mockAccount.id, - }, selectedAccount: mockAccount.id, }, + accountIdByAddress: { + [mockAccount.address]: mockAccount.id, + }, }, }); @@ -3608,12 +3604,12 @@ describe('AccountsController', () => { [mockAccount.id]: mockAccount, [mockAccountWithName.id]: mockAccountWithName, }, - accountIdByAddress: { - [mockAccount.address]: mockAccount.id, - [mockAccountWithName.address]: mockAccountWithName.id, - }, selectedAccount: mockAccount.id, }, + accountIdByAddress: { + [mockAccount.address]: mockAccount.id, + [mockAccountWithName.address]: mockAccountWithName.id, + }, }, }); @@ -3629,11 +3625,11 @@ describe('AccountsController', () => { initialState: { internalAccounts: { accounts: { [mockAccount.id]: mockAccount }, - accountIdByAddress: { - [mockAccount.address]: mockAccount.id, - }, selectedAccount: mockAccount.id, }, + accountIdByAddress: { + [mockAccount.address]: mockAccount.id, + }, }, }); accountsController.updateAccountMetadata(mockAccount.id, { @@ -3710,11 +3706,11 @@ describe('AccountsController', () => { accounts: { [mockAccount.id]: mockAccount, }, - accountIdByAddress: { - [mockAccount.address]: mockAccount.id, - }, selectedAccount: mockAccount.id, }, + accountIdByAddress: { + [mockAccount.address]: mockAccount.id, + }, }, messenger, }); @@ -3752,11 +3748,11 @@ describe('AccountsController', () => { accounts: { [mockAccount.id]: mockAccount, }, - accountIdByAddress: { - [mockAccount.address]: mockAccount.id, - }, selectedAccount: mockAccount.id, }, + accountIdByAddress: { + [mockAccount.address]: mockAccount.id, + }, }, messenger, }); @@ -3803,11 +3799,11 @@ describe('AccountsController', () => { initialState: { internalAccounts: { accounts: { [mockAccount.id]: mockAccount }, - accountIdByAddress: { - [mockAccount.address]: mockAccount.id, - }, selectedAccount: mockAccount.id, }, + accountIdByAddress: { + [mockAccount.address]: mockAccount.id, + }, }, }); @@ -3823,11 +3819,11 @@ describe('AccountsController', () => { initialState: { internalAccounts: { accounts: { [mockAccount.id]: mockAccount }, - accountIdByAddress: { - [mockAccount.address]: mockAccount.id, - }, selectedAccount: mockAccount.id, }, + accountIdByAddress: { + [mockAccount.address]: mockAccount.id, + }, }, }); @@ -3851,12 +3847,12 @@ describe('AccountsController', () => { [mockAccount.id]: mockAccount, [mockNonEvmAccount.id]: mockNonEvmAccount, }, - accountIdByAddress: { - [mockAccount.address]: mockAccount.id, - [mockNonEvmAccount.address]: mockNonEvmAccount.id, - }, selectedAccount: mockAccount.id, }, + accountIdByAddress: { + [mockAccount.address]: mockAccount.id, + [mockNonEvmAccount.address]: mockNonEvmAccount.id, + }, }, }); @@ -3891,11 +3887,11 @@ describe('AccountsController', () => { initialState: { internalAccounts: { accounts: { [mockAccount.id]: mockAccount }, - accountIdByAddress: { - [mockAccount.address]: mockAccount.id, - }, selectedAccount: mockAccount.id, }, + accountIdByAddress: { + [mockAccount.address]: mockAccount.id, + }, }, messenger, }); @@ -3924,12 +3920,12 @@ describe('AccountsController', () => { [mockAccount.id]: mockAccount, [mockNonEvmAccount.id]: mockNonEvmAccount, }, - accountIdByAddress: { - [mockAccount.address]: mockAccount.id, - [mockNonEvmAccount.address]: mockNonEvmAccount.id, - }, selectedAccount: mockAccount.id, }, + accountIdByAddress: { + [mockAccount.address]: mockAccount.id, + [mockNonEvmAccount.address]: mockNonEvmAccount.id, + }, }, messenger, }); @@ -3957,12 +3953,12 @@ describe('AccountsController', () => { [mockAccount.id]: mockAccount, [mockNonEvmAccount.id]: mockNonEvmAccount, }, - accountIdByAddress: { - [mockAccount.address]: mockAccount.id, - [mockNonEvmAccount.address]: mockNonEvmAccount.id, - }, selectedAccount: mockAccount.id, }, + accountIdByAddress: { + [mockAccount.address]: mockAccount.id, + [mockNonEvmAccount.address]: mockNonEvmAccount.id, + }, }, messenger, }); @@ -3984,11 +3980,11 @@ describe('AccountsController', () => { initialState: { internalAccounts: { accounts: { [mockAccount.id]: mockAccount }, - accountIdByAddress: { - [mockAccount.address]: mockAccount.id, - }, selectedAccount: mockAccount.id, }, + accountIdByAddress: { + [mockAccount.address]: mockAccount.id, + }, }, messenger, }); @@ -4015,12 +4011,12 @@ describe('AccountsController', () => { [mockAccount.id]: mockAccount, [mockAccount2.id]: mockAccount2, }, - accountIdByAddress: { - [mockAccount.address]: mockAccount.id, - [mockAccount2.address]: mockAccount2.id, - }, selectedAccount: mockAccount.id, }, + accountIdByAddress: { + [mockAccount.address]: mockAccount.id, + [mockAccount2.address]: mockAccount2.id, + }, }, messenger, }); @@ -4056,11 +4052,11 @@ describe('AccountsController', () => { initialState: { internalAccounts: { accounts: { [mockAccount.id]: mockAccount }, - accountIdByAddress: { - [mockAccount.address]: mockAccount.id, - }, selectedAccount: mockAccount.id, }, + accountIdByAddress: { + [mockAccount.address]: mockAccount.id, + }, }, messenger, }); @@ -4078,11 +4074,11 @@ describe('AccountsController', () => { initialState: { internalAccounts: { accounts: { [mockAccount.id]: mockAccount }, - accountIdByAddress: { - [mockAccount.address]: mockAccount.id, - }, selectedAccount: mockAccount.id, }, + accountIdByAddress: { + [mockAccount.address]: mockAccount.id, + }, }, messenger, }); @@ -4106,11 +4102,11 @@ describe('AccountsController', () => { initialState: { internalAccounts: { accounts: { [mockAccount.id]: mockAccount }, - accountIdByAddress: { - [mockAccount.address]: mockAccount.id, - }, selectedAccount: mockAccount.id, }, + accountIdByAddress: { + [mockAccount.address]: mockAccount.id, + }, }, messenger, }); @@ -4129,11 +4125,11 @@ describe('AccountsController', () => { initialState: { internalAccounts: { accounts: { [mockAccount.id]: mockAccount }, - accountIdByAddress: { - [mockAccount.address]: mockAccount.id, - }, selectedAccount: mockAccount.id, }, + accountIdByAddress: { + [mockAccount.address]: mockAccount.id, + }, }, messenger, }); @@ -4175,7 +4171,6 @@ describe('AccountsController', () => { ).toMatchInlineSnapshot(` Object { "internalAccounts": Object { - "accountIdByAddress": Object {}, "accounts": Object {}, "selectedAccount": "", }, @@ -4195,7 +4190,6 @@ describe('AccountsController', () => { ).toMatchInlineSnapshot(` Object { "internalAccounts": Object { - "accountIdByAddress": Object {}, "accounts": Object {}, "selectedAccount": "", }, @@ -4214,8 +4208,8 @@ describe('AccountsController', () => { ), ).toMatchInlineSnapshot(` Object { + "accountIdByAddress": Object {}, "internalAccounts": Object { - "accountIdByAddress": Object {}, "accounts": Object {}, "selectedAccount": "", }, diff --git a/packages/accounts-controller/src/AccountsController.ts b/packages/accounts-controller/src/AccountsController.ts index ddddb3559c5..b03ebf00a92 100644 --- a/packages/accounts-controller/src/AccountsController.ts +++ b/packages/accounts-controller/src/AccountsController.ts @@ -58,9 +58,9 @@ export type AccountId = string; export type AccountsControllerState = { internalAccounts: { accounts: Record; - accountIdByAddress: Record; selectedAccount: string; // id of the selected account }; + accountIdByAddress: Record; }; export type AccountsControllerGetStateAction = ControllerGetStateAction< @@ -224,14 +224,20 @@ const accountsControllerMetadata = { includeInDebugSnapshot: false, usedInUi: true, }, + accountIdByAddress: { + includeInStateLogs: false, + persist: false, + includeInDebugSnapshot: false, + usedInUi: true, + }, }; const defaultState: AccountsControllerState = { internalAccounts: { accounts: {}, - accountIdByAddress: {}, selectedAccount: '', }, + accountIdByAddress: {}, }; export const EMPTY_ACCOUNT = { @@ -439,8 +445,7 @@ export class AccountsController extends BaseController< * @returns The account with the specified address, or undefined if not found. */ getAccountByAddress(address: string): InternalAccount | undefined { - const accountId = - this.state.internalAccounts.accountIdByAddress[address.toLowerCase()]; + const accountId = this.state.accountIdByAddress[address.toLowerCase()]; return accountId ? this.getAccount(accountId) : undefined; } @@ -573,7 +578,7 @@ export class AccountsController extends BaseController< const existingInternalAccounts = this.state.internalAccounts.accounts; const internalAccounts: AccountsControllerState['internalAccounts']['accounts'] = {}; - const accountIdByAddress: AccountsControllerState['internalAccounts']['accountIdByAddress'] = + const accountIdByAddress: AccountsControllerState['accountIdByAddress'] = {}; const { keyrings } = this.messenger.call('KeyringController:getState'); @@ -624,7 +629,7 @@ export class AccountsController extends BaseController< this.#update((state) => { state.internalAccounts.accounts = internalAccounts; - state.internalAccounts.accountIdByAddress = accountIdByAddress; + state.accountIdByAddress = accountIdByAddress; }); } @@ -860,14 +865,12 @@ export class AccountsController extends BaseController< this.#update( (state) => { - const { internalAccounts } = state; + const { internalAccounts, accountIdByAddress } = state; for (const patch of [patches.snap, patches.normal]) { for (const account of patch.removed) { delete internalAccounts.accounts[account.id]; - delete internalAccounts.accountIdByAddress[ - account.address.toLowerCase() - ]; + delete accountIdByAddress[account.address.toLowerCase()]; diff.removed.push(account.id); } @@ -896,9 +899,7 @@ export class AccountsController extends BaseController< }, }; - internalAccounts.accountIdByAddress[ - account.address.toLowerCase() - ] = account.id; + accountIdByAddress[account.address.toLowerCase()] = account.id; diff.added.push(internalAccounts.accounts[account.id]); } diff --git a/packages/accounts-controller/src/typing.ts b/packages/accounts-controller/src/typing.ts index 44b03ef03ab..81d038ac998 100644 --- a/packages/accounts-controller/src/typing.ts +++ b/packages/accounts-controller/src/typing.ts @@ -31,6 +31,6 @@ export type AccountsControllerStrictState = IsAccountControllerState<{ internalAccounts: { accounts: Record; selectedAccount: InternalAccount['id']; - accountIdByAddress: Record; }; + accountIdByAddress: Record; }>; diff --git a/packages/profile-metrics-controller/src/ProfileMetricsController.test.ts b/packages/profile-metrics-controller/src/ProfileMetricsController.test.ts index 0e5d330cf77..876e25b2db9 100644 --- a/packages/profile-metrics-controller/src/ProfileMetricsController.test.ts +++ b/packages/profile-metrics-controller/src/ProfileMetricsController.test.ts @@ -150,12 +150,12 @@ describe('ProfileMetricsController', () => { [account1.id]: account1, [account2.id]: account2, }, - accountIdByAddress: { - [account1.address]: account1.id, - [account2.address]: account2.id, - }, selectedAccount: account1.id, }, + accountIdByAddress: { + [account1.address]: account1.id, + [account2.address]: account2.id, + }, }; }, ); From b76f861201ccb1c19ec4b71422696251c97fe6e6 Mon Sep 17 00:00:00 2001 From: Hassan Malik Date: Tue, 10 Feb 2026 13:23:09 -0500 Subject: [PATCH 10/37] fix: address bugbot comment --- .../accounts-controller/src/AccountsController.test.ts | 8 ++++++-- packages/accounts-controller/src/AccountsController.ts | 9 +++++++++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/packages/accounts-controller/src/AccountsController.test.ts b/packages/accounts-controller/src/AccountsController.test.ts index f15cc3fdadf..ef0fb5b936e 100644 --- a/packages/accounts-controller/src/AccountsController.test.ts +++ b/packages/accounts-controller/src/AccountsController.test.ts @@ -2862,7 +2862,9 @@ describe('AccountsController', () => { }, selectedAccount: mockAccount.id, }, - accountIdByAddress: {}, + accountIdByAddress: { + [mockAccount.address]: mockAccount.id, + }, }); expect(accountsController.state).toStrictEqual({ @@ -2872,7 +2874,9 @@ describe('AccountsController', () => { }, selectedAccount: mockAccount.id, }, - accountIdByAddress: {}, + accountIdByAddress: { + [mockAccount.address]: mockAccount.id, + }, }); }); diff --git a/packages/accounts-controller/src/AccountsController.ts b/packages/accounts-controller/src/AccountsController.ts index b03ebf00a92..fa602a6679b 100644 --- a/packages/accounts-controller/src/AccountsController.ts +++ b/packages/accounts-controller/src/AccountsController.ts @@ -640,9 +640,18 @@ export class AccountsController extends BaseController< */ loadBackup(backup: AccountsControllerState): void { if (backup.internalAccounts) { + const accountIdByAddress = Object.values( + backup.internalAccounts.accounts, + ).reduce((acc, account) => { + acc[account.address.toLowerCase()] = account.id; + return acc; + }, + {}, + ); this.update( (currentState: WritableDraft) => { currentState.internalAccounts = backup.internalAccounts; + currentState.accountIdByAddress = accountIdByAddress; }, ); } From 4fbd0b03a70bc3adc59edee92b4eff9cc98e05f1 Mon Sep 17 00:00:00 2001 From: Hassan Malik Date: Tue, 10 Feb 2026 13:28:18 -0500 Subject: [PATCH 11/37] fix: fix profilemetricscontroller test --- packages/accounts-controller/src/AccountsController.ts | 4 ++++ .../src/ProfileMetricsController.test.ts | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/packages/accounts-controller/src/AccountsController.ts b/packages/accounts-controller/src/AccountsController.ts index fa602a6679b..4f926f4fe5d 100644 --- a/packages/accounts-controller/src/AccountsController.ts +++ b/packages/accounts-controller/src/AccountsController.ts @@ -619,6 +619,7 @@ export class AccountsController extends BaseController< }, }; + // FIXME: We should not lowercase all addresses since some accounts addresses might be case-sensitive accountIdByAddress[internalAccount.address.toLowerCase()] = internalAccount.id; @@ -643,6 +644,7 @@ export class AccountsController extends BaseController< const accountIdByAddress = Object.values( backup.internalAccounts.accounts, ).reduce((acc, account) => { + // FIXME: We should not lowercase all addresses since some accounts addresses might be case-sensitive acc[account.address.toLowerCase()] = account.id; return acc; }, @@ -879,6 +881,7 @@ export class AccountsController extends BaseController< for (const patch of [patches.snap, patches.normal]) { for (const account of patch.removed) { delete internalAccounts.accounts[account.id]; + // FIXME: We should not lowercase all addresses since some accounts addresses might be case-sensitive delete accountIdByAddress[account.address.toLowerCase()]; diff.removed.push(account.id); @@ -908,6 +911,7 @@ export class AccountsController extends BaseController< }, }; + // FIXME: We should not lowercase all addresses since some accounts addresses might be case-sensitive accountIdByAddress[account.address.toLowerCase()] = account.id; diff.added.push(internalAccounts.accounts[account.id]); diff --git a/packages/profile-metrics-controller/src/ProfileMetricsController.test.ts b/packages/profile-metrics-controller/src/ProfileMetricsController.test.ts index 876e25b2db9..511d1556bd0 100644 --- a/packages/profile-metrics-controller/src/ProfileMetricsController.test.ts +++ b/packages/profile-metrics-controller/src/ProfileMetricsController.test.ts @@ -106,6 +106,10 @@ describe('ProfileMetricsController', () => { }, selectedAccount: account1.id, }, + accountIdByAddress: { + [account1.address]: account1.id, + [account2.address]: account2.id, + }, }; }, ); From 0dd19040381f4b1fe3621863bd85d6e80fff9ac9 Mon Sep 17 00:00:00 2001 From: Hassan Malik Date: Tue, 10 Feb 2026 13:57:57 -0500 Subject: [PATCH 12/37] fix: lint fix --- packages/accounts-controller/src/AccountsController.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/accounts-controller/src/AccountsController.ts b/packages/accounts-controller/src/AccountsController.ts index 4f926f4fe5d..e0d2b8f78d1 100644 --- a/packages/accounts-controller/src/AccountsController.ts +++ b/packages/accounts-controller/src/AccountsController.ts @@ -643,7 +643,8 @@ export class AccountsController extends BaseController< if (backup.internalAccounts) { const accountIdByAddress = Object.values( backup.internalAccounts.accounts, - ).reduce((acc, account) => { + ).reduce( + (acc, account) => { // FIXME: We should not lowercase all addresses since some accounts addresses might be case-sensitive acc[account.address.toLowerCase()] = account.id; return acc; From 45f7c300d908c6477ede369109090be0e1e9c2ba Mon Sep 17 00:00:00 2001 From: Hassan Malik Date: Tue, 10 Feb 2026 14:24:43 -0500 Subject: [PATCH 13/37] fix: rehydrate accountIdByAddress in constructor --- packages/accounts-controller/src/AccountsController.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/packages/accounts-controller/src/AccountsController.ts b/packages/accounts-controller/src/AccountsController.ts index e0d2b8f78d1..a697b721aa1 100644 --- a/packages/accounts-controller/src/AccountsController.ts +++ b/packages/accounts-controller/src/AccountsController.ts @@ -296,6 +296,13 @@ export class AccountsController extends BaseController< messenger: AccountsControllerMessenger; state: AccountsControllerState; }) { + const accountIdByAddress = Object.values( + state.internalAccounts.accounts, + ).reduce((acc, account) => { + // FIXME: We should not lowercase all addresses since some accounts addresses might be case-sensitive + acc[account.address.toLowerCase()] = account.id; + return acc; + }, {}); super({ messenger, name: controllerName, @@ -303,6 +310,7 @@ export class AccountsController extends BaseController< state: { ...defaultState, ...state, + accountIdByAddress, }, }); From 7991aeb21f02a07ce6366eef019738ab1d9a6305 Mon Sep 17 00:00:00 2001 From: Hassan Malik Date: Tue, 10 Feb 2026 14:37:52 -0500 Subject: [PATCH 14/37] fix: update token selectors test --- .../src/selectors/token-selectors.test.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/packages/assets-controllers/src/selectors/token-selectors.test.ts b/packages/assets-controllers/src/selectors/token-selectors.test.ts index 6b3126d8c08..bc124ca0ab2 100644 --- a/packages/assets-controllers/src/selectors/token-selectors.test.ts +++ b/packages/assets-controllers/src/selectors/token-selectors.test.ts @@ -467,6 +467,16 @@ const mockAccountControllerState: AccountsControllerState = { }, selectedAccount: 'd7f11451-9d79-4df4-a012-afd253443639', }, + accountIdByAddress: { + '0x2bd63233fe369b0f13eaf25292af5a9b63d2b7ab': + 'd7f11451-9d79-4df4-a012-afd253443639', + '0x0413078b85a6cb85f8f75181ad1a23d265d49202': + '2c311cc8-eeeb-48c7-a629-bb1d9c146b47', + '4KTpypSSbugxHe67NC9JURQWfCBNKdQTo4K8rZmYapS7': + '2d89e6a0-b4e6-45a8-a707-f10cef143b42', + '7XrST6XEcmjwTVrdfGcH6JFvaiSnokB8LdWCviMuGBjc': + '40fe5e20-525a-4434-bb83-c51ce5560a8c', + }, }; const mockMultichainBalancesControllerState = { From 9764f02c13f94dbc254125c069121298704a49b5 Mon Sep 17 00:00:00 2001 From: Hassan Malik Date: Tue, 10 Feb 2026 14:56:08 -0500 Subject: [PATCH 15/37] fix: make test consistent with actual behavior --- .../assets-controllers/src/selectors/token-selectors.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/assets-controllers/src/selectors/token-selectors.test.ts b/packages/assets-controllers/src/selectors/token-selectors.test.ts index bc124ca0ab2..4a4a966e96b 100644 --- a/packages/assets-controllers/src/selectors/token-selectors.test.ts +++ b/packages/assets-controllers/src/selectors/token-selectors.test.ts @@ -472,9 +472,9 @@ const mockAccountControllerState: AccountsControllerState = { 'd7f11451-9d79-4df4-a012-afd253443639', '0x0413078b85a6cb85f8f75181ad1a23d265d49202': '2c311cc8-eeeb-48c7-a629-bb1d9c146b47', - '4KTpypSSbugxHe67NC9JURQWfCBNKdQTo4K8rZmYapS7': + '4ktpypsbugxhe67nc9jurqwfcbnkdqto4k8rzmyaps7': '2d89e6a0-b4e6-45a8-a707-f10cef143b42', - '7XrST6XEcmjwTVrdfGcH6JFvaiSnokB8LdWCviMuGBjc': + '7xrst6xecmjwtvrdfgch6jfvaisnokb8ldwcvimugbjc': '40fe5e20-525a-4434-bb83-c51ce5560a8c', }, }; From 00a1a4aee7b07f8b4385fa53425943ee486bbb22 Mon Sep 17 00:00:00 2001 From: Hassan Malik Date: Tue, 10 Feb 2026 15:10:21 -0500 Subject: [PATCH 16/37] fix: fix test --- .../assets-controllers/src/selectors/token-selectors.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/assets-controllers/src/selectors/token-selectors.test.ts b/packages/assets-controllers/src/selectors/token-selectors.test.ts index 4a4a966e96b..73be7e610e1 100644 --- a/packages/assets-controllers/src/selectors/token-selectors.test.ts +++ b/packages/assets-controllers/src/selectors/token-selectors.test.ts @@ -472,7 +472,7 @@ const mockAccountControllerState: AccountsControllerState = { 'd7f11451-9d79-4df4-a012-afd253443639', '0x0413078b85a6cb85f8f75181ad1a23d265d49202': '2c311cc8-eeeb-48c7-a629-bb1d9c146b47', - '4ktpypsbugxhe67nc9jurqwfcbnkdqto4k8rzmyaps7': + '4ktpypssbugxhe67nc9jurqwfcbnkdqto4k8rzmyaps7': '2d89e6a0-b4e6-45a8-a707-f10cef143b42', '7xrst6xecmjwtvrdfgch6jfvaisnokb8ldwcvimugbjc': '40fe5e20-525a-4434-bb83-c51ce5560a8c', From 6f6b805c35fdcd8354dac14458e8883f4dbad637 Mon Sep 17 00:00:00 2001 From: Hassan Malik Date: Wed, 11 Feb 2026 13:24:31 -0500 Subject: [PATCH 17/37] fix: fix test --- packages/accounts-controller/src/AccountsController.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/accounts-controller/src/AccountsController.test.ts b/packages/accounts-controller/src/AccountsController.test.ts index cbde252a775..9bc8a8e295f 100644 --- a/packages/accounts-controller/src/AccountsController.test.ts +++ b/packages/accounts-controller/src/AccountsController.test.ts @@ -4212,7 +4212,7 @@ describe('AccountsController', () => { ), ).toMatchInlineSnapshot(` Object { - "accountIdByAddress": Object {}, + "accountIdByAddress": {}, "internalAccounts": Object { "accounts": Object {}, "selectedAccount": "", From b4e1d52552e4297bbd7bd0f41b41d5964f7590f1 Mon Sep 17 00:00:00 2001 From: Hassan Malik Date: Wed, 11 Feb 2026 13:50:12 -0500 Subject: [PATCH 18/37] fix: fix test --- packages/accounts-controller/src/AccountsController.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/accounts-controller/src/AccountsController.test.ts b/packages/accounts-controller/src/AccountsController.test.ts index 9bc8a8e295f..b73bc9768c0 100644 --- a/packages/accounts-controller/src/AccountsController.test.ts +++ b/packages/accounts-controller/src/AccountsController.test.ts @@ -4213,8 +4213,8 @@ describe('AccountsController', () => { ).toMatchInlineSnapshot(` Object { "accountIdByAddress": {}, - "internalAccounts": Object { - "accounts": Object {}, + "internalAccounts": { + "accounts": {}, "selectedAccount": "", }, } From dd8ae7d18f3ff077bb77e093c07be3b17ad1e0a5 Mon Sep 17 00:00:00 2001 From: Hassan Malik Date: Wed, 11 Feb 2026 15:46:59 -0500 Subject: [PATCH 19/37] fix: update test --- packages/accounts-controller/src/AccountsController.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/accounts-controller/src/AccountsController.test.ts b/packages/accounts-controller/src/AccountsController.test.ts index b73bc9768c0..ffd12c2f644 100644 --- a/packages/accounts-controller/src/AccountsController.test.ts +++ b/packages/accounts-controller/src/AccountsController.test.ts @@ -4211,7 +4211,7 @@ describe('AccountsController', () => { 'usedInUi', ), ).toMatchInlineSnapshot(` - Object { + { "accountIdByAddress": {}, "internalAccounts": { "accounts": {}, From e20977964fd4faafa815efe668ccebfd39a1e9ba Mon Sep 17 00:00:00 2001 From: Hassan Malik Date: Mon, 16 Feb 2026 11:35:29 -0500 Subject: [PATCH 20/37] refactor: move accountIdByAddress logic into util --- .../src/AccountsController.ts | 18 ++++-------------- .../accounts-controller/src/utils.test.ts | 19 +++++++++++++++++++ packages/accounts-controller/src/utils.ts | 12 ++++++++++++ 3 files changed, 35 insertions(+), 14 deletions(-) diff --git a/packages/accounts-controller/src/AccountsController.ts b/packages/accounts-controller/src/AccountsController.ts index a697b721aa1..d87e0d6525a 100644 --- a/packages/accounts-controller/src/AccountsController.ts +++ b/packages/accounts-controller/src/AccountsController.ts @@ -42,6 +42,7 @@ import type { MultichainNetworkControllerNetworkDidChangeEvent } from './types'; import type { AccountsControllerStrictState } from './typing'; import type { HdSnapKeyringAccount } from './utils'; import { + constructAccountIdByAddress, getEvmDerivationPathForIndex, getEvmGroupIndexFromAddressIndex, getUUIDFromAddressOfNormalAccount, @@ -296,13 +297,9 @@ export class AccountsController extends BaseController< messenger: AccountsControllerMessenger; state: AccountsControllerState; }) { - const accountIdByAddress = Object.values( + const accountIdByAddress = constructAccountIdByAddress( state.internalAccounts.accounts, - ).reduce((acc, account) => { - // FIXME: We should not lowercase all addresses since some accounts addresses might be case-sensitive - acc[account.address.toLowerCase()] = account.id; - return acc; - }, {}); + ); super({ messenger, name: controllerName, @@ -649,15 +646,8 @@ export class AccountsController extends BaseController< */ loadBackup(backup: AccountsControllerState): void { if (backup.internalAccounts) { - const accountIdByAddress = Object.values( + const accountIdByAddress = constructAccountIdByAddress( backup.internalAccounts.accounts, - ).reduce( - (acc, account) => { - // FIXME: We should not lowercase all addresses since some accounts addresses might be case-sensitive - acc[account.address.toLowerCase()] = account.id; - return acc; - }, - {}, ); this.update( (currentState: WritableDraft) => { diff --git a/packages/accounts-controller/src/utils.test.ts b/packages/accounts-controller/src/utils.test.ts index b118cc4836a..93c17b7b4b4 100644 --- a/packages/accounts-controller/src/utils.test.ts +++ b/packages/accounts-controller/src/utils.test.ts @@ -3,10 +3,12 @@ import type { KeyringObject } from '@metamask/keyring-controller'; import { KeyringTypes } from '@metamask/keyring-controller'; import { + constructAccountIdByAddress, getEvmGroupIndexFromAddressIndex, isNormalKeyringType, isSimpleKeyringType, } from './utils'; +import { createMockInternalAccount } from './tests/mocks'; describe('utils', () => { describe('isNormalKeyringType', () => { @@ -132,4 +134,21 @@ describe('utils', () => { ); }); }); + + describe('constructAccountIdByAddress', () => { + it('returns the account id by address for a map of accounts', () => { + const accounts = createMockInternalAccount({ + id: '1', + address: '0x123abc', + }); + + const accountIdByAddress = constructAccountIdByAddress({ + [accounts.id]: accounts, + }); + + expect(accountIdByAddress).toStrictEqual({ + '0x123abc': accounts.id, + }); + }); + }); }); diff --git a/packages/accounts-controller/src/utils.ts b/packages/accounts-controller/src/utils.ts index e2bbcc93fbd..3b964bb7af7 100644 --- a/packages/accounts-controller/src/utils.ts +++ b/packages/accounts-controller/src/utils.ts @@ -8,6 +8,8 @@ import { sha256 } from 'ethereum-cryptography/sha256'; import type { V4Options } from 'uuid'; import { v4 as uuid } from 'uuid'; +import { AccountId } from './AccountsController'; + /** * Returns the name of the keyring type. * @@ -206,3 +208,13 @@ export function isHdSnapKeyringAccount( ): account is HdSnapKeyringAccount { return is(account.options, HdSnapKeyringAccountOptionsStruct); } + +export function constructAccountIdByAddress( + accountsMap: Record, +): Record { + const accounts = Object.values(accountsMap); + return accounts.reduce>((acc, account) => { + acc[account.address.toLowerCase()] = account.id; + return acc; + }, {}); +} From ceb8b26d5bd0bc8e05b2c301b454ba48e077f333 Mon Sep 17 00:00:00 2001 From: Hassan Malik Date: Mon, 16 Feb 2026 11:42:02 -0500 Subject: [PATCH 21/37] fix: lint fix --- packages/accounts-controller/src/utils.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/accounts-controller/src/utils.test.ts b/packages/accounts-controller/src/utils.test.ts index 93c17b7b4b4..b006848c155 100644 --- a/packages/accounts-controller/src/utils.test.ts +++ b/packages/accounts-controller/src/utils.test.ts @@ -2,13 +2,13 @@ import { toChecksumAddress } from '@ethereumjs/util'; import type { KeyringObject } from '@metamask/keyring-controller'; import { KeyringTypes } from '@metamask/keyring-controller'; +import { createMockInternalAccount } from './tests/mocks'; import { constructAccountIdByAddress, getEvmGroupIndexFromAddressIndex, isNormalKeyringType, isSimpleKeyringType, } from './utils'; -import { createMockInternalAccount } from './tests/mocks'; describe('utils', () => { describe('isNormalKeyringType', () => { From 68d4694217c39aaa14ee50fc766a3d3ef41c6e69 Mon Sep 17 00:00:00 2001 From: Hassan Malik Date: Fri, 20 Feb 2026 11:20:24 -0500 Subject: [PATCH 22/37] chore: update changelog --- packages/accounts-controller/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/accounts-controller/CHANGELOG.md b/packages/accounts-controller/CHANGELOG.md index f8897ebec54..aafeebe9251 100644 --- a/packages/accounts-controller/CHANGELOG.md +++ b/packages/accounts-controller/CHANGELOG.md @@ -9,7 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added -- **BREAKING:** Add `accountIdByAddress` mapping to state and update `getAccountByAddress` function ([#7893](https://github.com/MetaMask/core/pull/7893)) +- Add `accountIdByAddress` mapping to state and update `getAccountByAddress` function ([#7893](https://github.com/MetaMask/core/pull/7893)) - This state was added to improve lookup times for an account by address from O(n) to O(1). ## [36.0.1] From 79ad9c8bd2fd6f4c73134444bf0c8289afe3e993 Mon Sep 17 00:00:00 2001 From: Hassan Malik Date: Tue, 24 Feb 2026 10:27:57 -0500 Subject: [PATCH 23/37] fix: update import --- packages/accounts-controller/src/utils.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/accounts-controller/src/utils.test.ts b/packages/accounts-controller/src/utils.test.ts index b006848c155..f75a279aa0f 100644 --- a/packages/accounts-controller/src/utils.test.ts +++ b/packages/accounts-controller/src/utils.test.ts @@ -2,13 +2,13 @@ import { toChecksumAddress } from '@ethereumjs/util'; import type { KeyringObject } from '@metamask/keyring-controller'; import { KeyringTypes } from '@metamask/keyring-controller'; -import { createMockInternalAccount } from './tests/mocks'; import { constructAccountIdByAddress, getEvmGroupIndexFromAddressIndex, isNormalKeyringType, isSimpleKeyringType, } from './utils'; +import { createMockInternalAccount } from '../tests/mocks'; describe('utils', () => { describe('isNormalKeyringType', () => { From b51eceb350d69f87af28343f15c1d293711ddd20 Mon Sep 17 00:00:00 2001 From: Hassan Malik Date: Tue, 24 Feb 2026 10:51:44 -0500 Subject: [PATCH 24/37] fix: update import type --- packages/accounts-controller/src/utils.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/accounts-controller/src/utils.ts b/packages/accounts-controller/src/utils.ts index 3b964bb7af7..d88182623ab 100644 --- a/packages/accounts-controller/src/utils.ts +++ b/packages/accounts-controller/src/utils.ts @@ -8,7 +8,7 @@ import { sha256 } from 'ethereum-cryptography/sha256'; import type { V4Options } from 'uuid'; import { v4 as uuid } from 'uuid'; -import { AccountId } from './AccountsController'; +import type { AccountId } from './AccountsController'; /** * Returns the name of the keyring type. From 7cbd7910e44afcf443054152068f2663d715e71c Mon Sep 17 00:00:00 2001 From: Hassan Malik Date: Fri, 27 Feb 2026 15:34:15 -0500 Subject: [PATCH 25/37] refactor: use util to create accountIdByAddress in updateAccounts --- packages/accounts-controller/src/AccountsController.ts | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/packages/accounts-controller/src/AccountsController.ts b/packages/accounts-controller/src/AccountsController.ts index c9b1d185f0f..c734e0c7cf1 100644 --- a/packages/accounts-controller/src/AccountsController.ts +++ b/packages/accounts-controller/src/AccountsController.ts @@ -633,8 +633,6 @@ export class AccountsController extends BaseController< const existingInternalAccounts = this.state.internalAccounts.accounts; const internalAccounts: AccountsControllerState['internalAccounts']['accounts'] = {}; - const accountIdByAddress: AccountsControllerState['accountIdByAddress'] = - {}; const { keyrings } = this.messenger.call('KeyringController:getState'); for (const keyring of keyrings) { @@ -674,10 +672,6 @@ export class AccountsController extends BaseController< }, }; - // FIXME: We should not lowercase all addresses since some accounts addresses might be case-sensitive - accountIdByAddress[internalAccount.address.toLowerCase()] = - internalAccount.id; - // Increment the account index for this keyring. keyringAccountIndexes.set(keyringTypeName, keyringAccountIndex + 1); } @@ -685,7 +679,7 @@ export class AccountsController extends BaseController< this.#update((state) => { state.internalAccounts.accounts = internalAccounts; - state.accountIdByAddress = accountIdByAddress; + state.accountIdByAddress = constructAccountIdByAddress(internalAccounts); }); } From cf1427639643161d9db78b47c2b356506d4b903a Mon Sep 17 00:00:00 2001 From: Hassan Malik Date: Mon, 2 Mar 2026 13:04:38 -0500 Subject: [PATCH 26/37] refactor: remove toLowerCase --- packages/accounts-controller/src/AccountsController.ts | 8 +++----- packages/accounts-controller/src/utils.ts | 2 +- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/packages/accounts-controller/src/AccountsController.ts b/packages/accounts-controller/src/AccountsController.ts index c734e0c7cf1..ceb347c203e 100644 --- a/packages/accounts-controller/src/AccountsController.ts +++ b/packages/accounts-controller/src/AccountsController.ts @@ -490,7 +490,7 @@ export class AccountsController extends BaseController< * @returns The account with the specified address, or undefined if not found. */ getAccountByAddress(address: string): InternalAccount | undefined { - const accountId = this.state.accountIdByAddress[address.toLowerCase()]; + const accountId = this.state.accountIdByAddress[address]; return accountId ? this.getAccount(accountId) : undefined; } @@ -926,8 +926,7 @@ export class AccountsController extends BaseController< for (const patch of [patches.snap, patches.normal]) { for (const account of patch.removed) { delete internalAccounts.accounts[account.id]; - // FIXME: We should not lowercase all addresses since some accounts addresses might be case-sensitive - delete accountIdByAddress[account.address.toLowerCase()]; + delete accountIdByAddress[account.address]; diff.removed.push(account.id); } @@ -956,8 +955,7 @@ export class AccountsController extends BaseController< }, }; - // FIXME: We should not lowercase all addresses since some accounts addresses might be case-sensitive - accountIdByAddress[account.address.toLowerCase()] = account.id; + accountIdByAddress[account.address] = account.id; diff.added.push(internalAccounts.accounts[account.id]); } diff --git a/packages/accounts-controller/src/utils.ts b/packages/accounts-controller/src/utils.ts index d88182623ab..5620031d37b 100644 --- a/packages/accounts-controller/src/utils.ts +++ b/packages/accounts-controller/src/utils.ts @@ -214,7 +214,7 @@ export function constructAccountIdByAddress( ): Record { const accounts = Object.values(accountsMap); return accounts.reduce>((acc, account) => { - acc[account.address.toLowerCase()] = account.id; + acc[account.address] = account.id; return acc; }, {}); } From d69804aa194bf8724d6f21515078722925a1092f Mon Sep 17 00:00:00 2001 From: Hassan Malik Date: Tue, 3 Mar 2026 10:40:16 -0500 Subject: [PATCH 27/37] fix: account for empty state --- packages/accounts-controller/src/AccountsController.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/accounts-controller/src/AccountsController.ts b/packages/accounts-controller/src/AccountsController.ts index ceb347c203e..6c29d8f1ff5 100644 --- a/packages/accounts-controller/src/AccountsController.ts +++ b/packages/accounts-controller/src/AccountsController.ts @@ -318,7 +318,7 @@ export class AccountsController extends BaseController< state: AccountsControllerState; }) { const accountIdByAddress = constructAccountIdByAddress( - state.internalAccounts.accounts, + state?.internalAccounts?.accounts ?? {}, ); super({ messenger, From 0eb28104d3afbe6b0256fa8a8890fb0ca09b569b Mon Sep 17 00:00:00 2001 From: Hassan Malik Date: Tue, 3 Mar 2026 11:00:34 -0500 Subject: [PATCH 28/37] test: add tests to fix coverage --- .../src/AccountsController.test.ts | 34 ++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/packages/accounts-controller/src/AccountsController.test.ts b/packages/accounts-controller/src/AccountsController.test.ts index 93aeb900ba7..017b284002d 100644 --- a/packages/accounts-controller/src/AccountsController.test.ts +++ b/packages/accounts-controller/src/AccountsController.test.ts @@ -290,14 +290,17 @@ function buildAccountsControllerMessenger( * @param options - The options object. * @param [options.initialState] - The initial state to use for the AccountsController. * @param [options.messenger] - The root messenger to use for creating the AccountsController messenger. + * @param [options.overrideState] - The state to override the initial state with. * @returns An instance of the AccountsController class. */ function setupAccountsController({ initialState = {}, messenger = buildMessenger(), + overrideState = null, }: { initialState?: Partial; messenger?: RootMessenger; + overrideState?: AccountsControllerState | null; }): { accountsController: AccountsController; messenger: RootMessenger; @@ -309,7 +312,7 @@ function setupAccountsController({ const accountsController = new AccountsController({ messenger: accountsControllerMessenger, - state: { ...defaultState, ...initialState }, + state: overrideState ?? { ...defaultState, ...initialState }, }); const triggerMultichainNetworkChange = ( @@ -349,6 +352,35 @@ describe('AccountsController', () => { lastSelected: 22222, }); + describe('constructor', () => { + it('should construct the accountIdByAddress correctly', () => { + const { accountsController } = setupAccountsController({ + initialState: { + internalAccounts: { + accounts: { + [mockAccount.id]: mockAccount, + }, + selectedAccount: mockAccount.id, + }, + }, + }); + + expect(accountsController.state.accountIdByAddress).toStrictEqual({ + [mockAccount.address]: mockAccount.id, + }); + }); + + it('should handle empty state', () => { + const { accountsController } = setupAccountsController({ + // @ts-expect-error - We want to test empty state here. + overrideState: {}, + }); + // No accounts, no accountIdByAddress + // Initial state + expect(accountsController.state.accountIdByAddress).toStrictEqual({}); + }); + }); + describe('onSnapStateChange', () => { it('enables an account if the Snap is enabled and not blocked', async () => { const messenger = buildMessenger(); From 564fb85e51e0a0eb27222f5f0a3cde563942c5dd Mon Sep 17 00:00:00 2001 From: Hassan Malik Date: Tue, 3 Mar 2026 20:37:19 -0500 Subject: [PATCH 29/37] refactor: add fallback cache lookup --- packages/accounts-controller/src/AccountsController.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/accounts-controller/src/AccountsController.ts b/packages/accounts-controller/src/AccountsController.ts index 6c29d8f1ff5..258e79ae6c2 100644 --- a/packages/accounts-controller/src/AccountsController.ts +++ b/packages/accounts-controller/src/AccountsController.ts @@ -490,7 +490,10 @@ export class AccountsController extends BaseController< * @returns The account with the specified address, or undefined if not found. */ getAccountByAddress(address: string): InternalAccount | undefined { - const accountId = this.state.accountIdByAddress[address]; + // We need to have a fallback as a cache miss might be attributed to a checksummed address being passed. + const accountId = + this.state.accountIdByAddress[address] ?? + this.state.accountIdByAddress[address.toLowerCase()]; return accountId ? this.getAccount(accountId) : undefined; } From 851b40765bd4195ace7c6de676a34ce1a3e62b4e Mon Sep 17 00:00:00 2001 From: Hassan Malik Date: Wed, 4 Mar 2026 15:26:54 -0500 Subject: [PATCH 30/37] fix: revert token selector test change --- .../src/selectors/token-selectors.test.ts | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/packages/assets-controllers/src/selectors/token-selectors.test.ts b/packages/assets-controllers/src/selectors/token-selectors.test.ts index 73be7e610e1..6b3126d8c08 100644 --- a/packages/assets-controllers/src/selectors/token-selectors.test.ts +++ b/packages/assets-controllers/src/selectors/token-selectors.test.ts @@ -467,16 +467,6 @@ const mockAccountControllerState: AccountsControllerState = { }, selectedAccount: 'd7f11451-9d79-4df4-a012-afd253443639', }, - accountIdByAddress: { - '0x2bd63233fe369b0f13eaf25292af5a9b63d2b7ab': - 'd7f11451-9d79-4df4-a012-afd253443639', - '0x0413078b85a6cb85f8f75181ad1a23d265d49202': - '2c311cc8-eeeb-48c7-a629-bb1d9c146b47', - '4ktpypssbugxhe67nc9jurqwfcbnkdqto4k8rzmyaps7': - '2d89e6a0-b4e6-45a8-a707-f10cef143b42', - '7xrst6xecmjwtvrdfgch6jfvaisnokb8ldwcvimugbjc': - '40fe5e20-525a-4434-bb83-c51ce5560a8c', - }, }; const mockMultichainBalancesControllerState = { From 8010515537bb7593dff220524316749afc9ec0e0 Mon Sep 17 00:00:00 2001 From: Hassan Malik Date: Wed, 4 Mar 2026 15:27:17 -0500 Subject: [PATCH 31/37] refactor: change var name --- packages/accounts-controller/src/utils.test.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/accounts-controller/src/utils.test.ts b/packages/accounts-controller/src/utils.test.ts index f75a279aa0f..618494cf268 100644 --- a/packages/accounts-controller/src/utils.test.ts +++ b/packages/accounts-controller/src/utils.test.ts @@ -137,17 +137,17 @@ describe('utils', () => { describe('constructAccountIdByAddress', () => { it('returns the account id by address for a map of accounts', () => { - const accounts = createMockInternalAccount({ + const account = createMockInternalAccount({ id: '1', address: '0x123abc', }); const accountIdByAddress = constructAccountIdByAddress({ - [accounts.id]: accounts, + [account.id]: account, }); expect(accountIdByAddress).toStrictEqual({ - '0x123abc': accounts.id, + '0x123abc': account.id, }); }); }); From ba5c67279d22df1fb932d977cd88349f60434b7c Mon Sep 17 00:00:00 2001 From: Hassan Malik Date: Wed, 4 Mar 2026 15:32:56 -0500 Subject: [PATCH 32/37] refactor: update type to be narrower --- packages/accounts-controller/src/AccountsController.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/accounts-controller/src/AccountsController.ts b/packages/accounts-controller/src/AccountsController.ts index 258e79ae6c2..ca5287a0e5e 100644 --- a/packages/accounts-controller/src/AccountsController.ts +++ b/packages/accounts-controller/src/AccountsController.ts @@ -70,7 +70,7 @@ export type AccountsControllerState = { accounts: Record; selectedAccount: string; // id of the selected account }; - accountIdByAddress: Record; + accountIdByAddress: Record; }; /** From ebcfd98d3ca5d422aef855a1174eb15f62fe0125 Mon Sep 17 00:00:00 2001 From: Hassan Malik Date: Thu, 5 Mar 2026 08:47:21 -0500 Subject: [PATCH 33/37] refactor: add logging for cache miss --- .../accounts-controller/src/AccountsController.ts | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/packages/accounts-controller/src/AccountsController.ts b/packages/accounts-controller/src/AccountsController.ts index 1323c97594e..2815b1fef81 100644 --- a/packages/accounts-controller/src/AccountsController.ts +++ b/packages/accounts-controller/src/AccountsController.ts @@ -492,9 +492,16 @@ export class AccountsController extends BaseController< */ getAccountByAddress(address: string): InternalAccount | undefined { // We need to have a fallback as a cache miss might be attributed to a checksummed address being passed. - const accountId = - this.state.accountIdByAddress[address] ?? - this.state.accountIdByAddress[address.toLowerCase()]; + let accountId = this.state.accountIdByAddress[address]; + if (!accountId) { + const lowercasedAddress = address.toLowerCase(); + accountId = this.state.accountIdByAddress[lowercasedAddress]; + if (accountId) { + log( + `Cache missed for account id: ${accountId}, received address: "${address}", matched address: "${lowercasedAddress}"`, + ); + } + } return accountId ? this.getAccount(accountId) : undefined; } From b185e88a0f1ad535077057f93e57f9dac3de410d Mon Sep 17 00:00:00 2001 From: Hassan Malik Date: Thu, 5 Mar 2026 08:50:22 -0500 Subject: [PATCH 34/37] refactor: update logic --- packages/accounts-controller/src/AccountsController.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/accounts-controller/src/AccountsController.ts b/packages/accounts-controller/src/AccountsController.ts index 2815b1fef81..fcfd0dae64d 100644 --- a/packages/accounts-controller/src/AccountsController.ts +++ b/packages/accounts-controller/src/AccountsController.ts @@ -500,9 +500,10 @@ export class AccountsController extends BaseController< log( `Cache missed for account id: ${accountId}, received address: "${address}", matched address: "${lowercasedAddress}"`, ); + return this.getAccount(accountId); } } - return accountId ? this.getAccount(accountId) : undefined; + return undefined; } /** From b132a1e06ca160b863e0c0d1897a353c46126740 Mon Sep 17 00:00:00 2001 From: Hassan Malik Date: Thu, 5 Mar 2026 08:59:34 -0500 Subject: [PATCH 35/37] test: add test --- .../src/AccountsController.test.ts | 34 ++++++++++++++++++- .../src/AccountsController.ts | 3 +- 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/packages/accounts-controller/src/AccountsController.test.ts b/packages/accounts-controller/src/AccountsController.test.ts index 017b284002d..7054d87f4be 100644 --- a/packages/accounts-controller/src/AccountsController.test.ts +++ b/packages/accounts-controller/src/AccountsController.test.ts @@ -1,5 +1,5 @@ import { deriveStateFromMetadata } from '@metamask/base-controller'; -import { InfuraNetworkType } from '@metamask/controller-utils'; +import { InfuraNetworkType, toChecksumHexAddress } from '@metamask/controller-utils'; import type { AccountAssetListUpdatedEventPayload, AccountBalancesUpdatedEventPayload, @@ -144,6 +144,21 @@ const mockAccount4: InternalAccount = { }, }; +const mockAccount5: InternalAccount = { + id: 'mock-id5', + address: '0x4f3e8a2c1d7b6e9f0a5c8d2b1e7f3a6c9d0e4b5a', + options: {}, + methods: [...ETH_EOA_METHODS], + type: EthAccountType.Eoa, + scopes: [EthScope.Eoa], + metadata: { + name: '', + keyring: { type: KeyringTypes.hd }, + importTime: 1691565967600, + lastSelected: 1955565967656, + }, +}; + class MockNormalAccountUUID { readonly #accountIds: Record = {}; @@ -3904,6 +3919,23 @@ describe('AccountsController', () => { expect(account).toStrictEqual(mockNonEvmAccount); }); + + it('can handle a checksummed address', () => { + const { accountsController } = setupAccountsController({ + initialState: { + internalAccounts: { + accounts: { [mockAccount5.id]: mockAccount5 }, + selectedAccount: mockAccount5.id, + }, + }, + }); + + const checksummedAddress = toChecksumHexAddress(mockAccount5.address); + const account = + accountsController.getAccountByAddress(checksummedAddress); + + expect(account).toStrictEqual(mockAccount5); + }); }); describe('actions', () => { diff --git a/packages/accounts-controller/src/AccountsController.ts b/packages/accounts-controller/src/AccountsController.ts index fcfd0dae64d..2815b1fef81 100644 --- a/packages/accounts-controller/src/AccountsController.ts +++ b/packages/accounts-controller/src/AccountsController.ts @@ -500,10 +500,9 @@ export class AccountsController extends BaseController< log( `Cache missed for account id: ${accountId}, received address: "${address}", matched address: "${lowercasedAddress}"`, ); - return this.getAccount(accountId); } } - return undefined; + return accountId ? this.getAccount(accountId) : undefined; } /** From c0380f99a03adf3d87adb17d5ce2b91a56911d01 Mon Sep 17 00:00:00 2001 From: Hassan Malik Date: Thu, 5 Mar 2026 09:00:31 -0500 Subject: [PATCH 36/37] fix: lint fix --- packages/accounts-controller/src/AccountsController.test.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/accounts-controller/src/AccountsController.test.ts b/packages/accounts-controller/src/AccountsController.test.ts index 7054d87f4be..1e5d530ea62 100644 --- a/packages/accounts-controller/src/AccountsController.test.ts +++ b/packages/accounts-controller/src/AccountsController.test.ts @@ -1,5 +1,8 @@ import { deriveStateFromMetadata } from '@metamask/base-controller'; -import { InfuraNetworkType, toChecksumHexAddress } from '@metamask/controller-utils'; +import { + InfuraNetworkType, + toChecksumHexAddress, +} from '@metamask/controller-utils'; import type { AccountAssetListUpdatedEventPayload, AccountBalancesUpdatedEventPayload, From 2c7a6ea4427506033c5064f3ec67652c885a1e36 Mon Sep 17 00:00:00 2001 From: Hassan Malik Date: Thu, 5 Mar 2026 09:44:01 -0500 Subject: [PATCH 37/37] refactor: apply code review --- packages/accounts-controller/CHANGELOG.md | 3 ++- .../accounts-controller/src/AccountsController.test.ts | 4 ++-- packages/accounts-controller/src/AccountsController.ts | 7 ++++++- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/packages/accounts-controller/CHANGELOG.md b/packages/accounts-controller/CHANGELOG.md index 415c349a8b2..9810571fe8f 100644 --- a/packages/accounts-controller/CHANGELOG.md +++ b/packages/accounts-controller/CHANGELOG.md @@ -9,8 +9,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added -- Add `accountIdByAddress` mapping to state and update `getAccountByAddress` function ([#7893](https://github.com/MetaMask/core/pull/7893)) +- Add `accountIdByAddress` mapping to state ([#7893](https://github.com/MetaMask/core/pull/7893)) - This state was added to improve lookup times for an account by address from O(n) to O(1). + - `getAccountByAddress` also leverages this new map, thus, should be slightly faster too. - Add logging capabilities ([#8118](https://github.com/MetaMask/core/pull/8118/)) - Expose missing public `AccountsController` methods through its messenger ([#7976](https://github.com/MetaMask/core/pull/7976/)) - The following actions are now available: diff --git a/packages/accounts-controller/src/AccountsController.test.ts b/packages/accounts-controller/src/AccountsController.test.ts index 1e5d530ea62..6fe0bd849b8 100644 --- a/packages/accounts-controller/src/AccountsController.test.ts +++ b/packages/accounts-controller/src/AccountsController.test.ts @@ -371,7 +371,7 @@ describe('AccountsController', () => { }); describe('constructor', () => { - it('should construct the accountIdByAddress correctly', () => { + it('constructs the accountIdByAddress correctly', () => { const { accountsController } = setupAccountsController({ initialState: { internalAccounts: { @@ -388,7 +388,7 @@ describe('AccountsController', () => { }); }); - it('should handle empty state', () => { + it('handles empty state', () => { const { accountsController } = setupAccountsController({ // @ts-expect-error - We want to test empty state here. overrideState: {}, diff --git a/packages/accounts-controller/src/AccountsController.ts b/packages/accounts-controller/src/AccountsController.ts index 2815b1fef81..5bd67e9a36f 100644 --- a/packages/accounts-controller/src/AccountsController.ts +++ b/packages/accounts-controller/src/AccountsController.ts @@ -494,11 +494,16 @@ export class AccountsController extends BaseController< // We need to have a fallback as a cache miss might be attributed to a checksummed address being passed. let accountId = this.state.accountIdByAddress[address]; if (!accountId) { + // FIXME: We should not need lower-cased addresses, but some consumers might + // still be using non-normalized addresses. For now we keep it + // for convenience, but we will need to remove this fallback + // at some point. + // NOTE: We should only hit that branch for EVM accounts only. const lowercasedAddress = address.toLowerCase(); accountId = this.state.accountIdByAddress[lowercasedAddress]; if (accountId) { log( - `Cache missed for account id: ${accountId}, received address: "${address}", matched address: "${lowercasedAddress}"`, + `Cache missed for account ID: ${accountId}, received address: "${address}", matched address: "${lowercasedAddress}"`, ); } }