From 6ee14990b53c7129ba0af6f0ab9683ce3542fd70 Mon Sep 17 00:00:00 2001 From: grypez <143971198+grypez@users.noreply.github.com> Date: Thu, 28 May 2026 12:26:09 -0500 Subject: [PATCH 01/26] feat(wallet): add AccountsController and ConnectivityController Co-Authored-By: Claude Sonnet 4.6 --- .../instances/accounts-controller.ts | 63 +++++++++++++++++++ .../instances/connectivity-controller.ts | 43 +++++++++++++ .../src/initialization/instances/index.ts | 2 + packages/wallet/src/utilities.ts | 17 +++++ 4 files changed, 125 insertions(+) create mode 100644 packages/wallet/src/initialization/instances/accounts-controller.ts create mode 100644 packages/wallet/src/initialization/instances/connectivity-controller.ts diff --git a/packages/wallet/src/initialization/instances/accounts-controller.ts b/packages/wallet/src/initialization/instances/accounts-controller.ts new file mode 100644 index 0000000000..6d3f267fac --- /dev/null +++ b/packages/wallet/src/initialization/instances/accounts-controller.ts @@ -0,0 +1,63 @@ +import { + AccountsController, + AccountsControllerMessenger, +} from '@metamask/accounts-controller'; +import { + Messenger, + MessengerActions, + MessengerEvents, +} from '@metamask/messenger'; + +import type { DefaultActions, DefaultEvents, RootMessenger } from '../defaults'; +import type { InitializationConfiguration } from '../types'; + +// TODO: AccountsController is deprecated in favour of AccountTreeController +// and MultichainAccountService. Migrate once those controllers are wired into +// the wallet initialization (both still depend on AccountsController at the +// messenger level, so it must remain present in the meantime). +type AllowedActions = MessengerActions; + +type AllowedEvents = MessengerEvents; + +export const accountsController: InitializationConfiguration< + AccountsController, + AccountsControllerMessenger +> = { + name: 'AccountsController', + init: ({ state, messenger }) => + new AccountsController({ + state, + messenger, + }), + getMessenger: (parent: RootMessenger) => { + const accountsControllerMessenger = new Messenger< + 'AccountsController', + AllowedActions, + AllowedEvents, + typeof parent + >({ + namespace: 'AccountsController', + parent, + }); + + parent.delegate({ + messenger: accountsControllerMessenger, + actions: [ + 'KeyringController:getState', + 'KeyringController:getKeyringsByType', + ], + events: [ + // AccountsController subscribes to :stateChange internally; the + // delegation must match until that package migrates to :stateChanged. + // eslint-disable-next-line no-restricted-syntax + 'KeyringController:stateChange', + 'SnapKeyring:accountAssetListUpdated', + 'SnapKeyring:accountBalancesUpdated', + 'SnapKeyring:accountTransactionsUpdated', + 'MultichainNetworkController:networkDidChange', + ], + }); + + return accountsControllerMessenger; + }, +}; diff --git a/packages/wallet/src/initialization/instances/connectivity-controller.ts b/packages/wallet/src/initialization/instances/connectivity-controller.ts new file mode 100644 index 0000000000..7e92c491ee --- /dev/null +++ b/packages/wallet/src/initialization/instances/connectivity-controller.ts @@ -0,0 +1,43 @@ +import { + CONNECTIVITY_STATUSES, + ConnectivityAdapter, + ConnectivityController, + ConnectivityControllerMessenger, + ConnectivityStatus, +} from '@metamask/connectivity-controller'; +import { Messenger } from '@metamask/messenger'; + +import type { DefaultActions, DefaultEvents, RootMessenger } from '../defaults'; +import type { InitializationConfiguration } from '../types'; + +// TODO: For now, we assume we are always online. +class AlwaysOnlineAdapter implements ConnectivityAdapter { + async getStatus(): Promise { + return CONNECTIVITY_STATUSES.Online; + } + + onConnectivityChange(_callback: (status: ConnectivityStatus) => void): void { + // no-op + } + + destroy(): void { + // no-op + } +} + +export const connectivityController: InitializationConfiguration< + ConnectivityController, + ConnectivityControllerMessenger +> = { + name: 'ConnectivityController', + init: ({ messenger }) => + new ConnectivityController({ + messenger, + connectivityAdapter: new AlwaysOnlineAdapter(), + }), + getMessenger: (parent: RootMessenger) => + new Messenger<'ConnectivityController', never, never, typeof parent>({ + namespace: 'ConnectivityController', + parent, + }), +}; diff --git a/packages/wallet/src/initialization/instances/index.ts b/packages/wallet/src/initialization/instances/index.ts index 28a3bf2f23..648fa5e402 100644 --- a/packages/wallet/src/initialization/instances/index.ts +++ b/packages/wallet/src/initialization/instances/index.ts @@ -1 +1,3 @@ +export { accountsController } from './accounts-controller'; +export { connectivityController } from './connectivity-controller'; export { keyringController } from './keyring-controller'; diff --git a/packages/wallet/src/utilities.ts b/packages/wallet/src/utilities.ts index 4630dd5460..e3f9814fda 100644 --- a/packages/wallet/src/utilities.ts +++ b/packages/wallet/src/utilities.ts @@ -24,3 +24,20 @@ export async function importSecretRecoveryPhrase( mnemonic, ); } + +/** + * Initialize the wallet object with a randomly generated secret recovery phrase. + * + * @param wallet - The wallet object. + * @param password - The password to the MetaMask wallet (not the SRP). + */ +export async function createSecretRecoveryPhrase( + wallet: Wallet, + password: string, +): Promise { + // TODO: This should use the new MultichainAccountService. + await wallet.messenger.call( + 'KeyringController:createNewVaultAndKeychain', + password, + ); +} From e744c916772eb80d986f8c2836e7ff6351a37baf Mon Sep 17 00:00:00 2001 From: grypez <143971198+grypez@users.noreply.github.com> Date: Thu, 28 May 2026 12:26:12 -0500 Subject: [PATCH 02/26] chore(wallet): add changelog entries for AccountsController and ConnectivityController Co-Authored-By: Claude Sonnet 4.6 --- packages/wallet/CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/wallet/CHANGELOG.md b/packages/wallet/CHANGELOG.md index 77cb0f75b1..7d2c9b3673 100644 --- a/packages/wallet/CHANGELOG.md +++ b/packages/wallet/CHANGELOG.md @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Added + +- Add `AccountsController` and `ConnectivityController` as default initialized controllers ([#8924](https://github.com/MetaMask/core/pull/8924)) + ## [1.0.1] ### Changed From e85be4e0a5b83ed9a6b2ae8d503de951c37e4ed8 Mon Sep 17 00:00:00 2001 From: grypez <143971198+grypez@users.noreply.github.com> Date: Thu, 28 May 2026 12:26:17 -0500 Subject: [PATCH 03/26] test(wallet): add tests for AccountsController and ConnectivityController initialization Co-Authored-By: Claude Sonnet 4.6 --- packages/wallet/src/Wallet.test.ts | 34 ++++++++++++- .../instances/accounts-controller.ts | 3 +- .../instances/connectivity-controller.test.ts | 51 +++++++++++++++++++ .../instances/connectivity-controller.ts | 26 +++++++++- packages/wallet/src/utilities.test.ts | 31 +++++++++++ packages/wallet/tsconfig.build.json | 2 + 6 files changed, 143 insertions(+), 4 deletions(-) create mode 100644 packages/wallet/src/initialization/instances/connectivity-controller.test.ts create mode 100644 packages/wallet/src/utilities.test.ts diff --git a/packages/wallet/src/Wallet.test.ts b/packages/wallet/src/Wallet.test.ts index a3a8dca781..be5a999659 100644 --- a/packages/wallet/src/Wallet.test.ts +++ b/packages/wallet/src/Wallet.test.ts @@ -1,10 +1,14 @@ +import { CONNECTIVITY_STATUSES } from '@metamask/connectivity-controller'; import { Messenger } from '@metamask/messenger'; import { Json } from '@metamask/utils'; import { webcrypto } from 'crypto'; import MockEncryptor from '../../keyring-controller/tests/mocks/mockEncryptor'; import * as initializationModule from './initialization/initialization'; -import { importSecretRecoveryPhrase } from './utilities'; +import { + createSecretRecoveryPhrase, + importSecretRecoveryPhrase, +} from './utilities'; import { Wallet } from './Wallet'; const TEST_SRP = 'test test test test test test test test test test test ball'; @@ -176,6 +180,34 @@ describe('Wallet', () => { expect(spy).toHaveBeenCalledTimes(1); }); + describe('AccountsController', () => { + it('tracks accounts created via KeyringController', async () => { + const wallet = new Wallet({}); + await createSecretRecoveryPhrase(wallet, TEST_PASSWORD); + + const keyringAccounts = await wallet.messenger.call( + 'KeyringController:getAccounts', + ); + const trackedAddresses = Object.values( + wallet.state.AccountsController.internalAccounts.accounts, + ).map((account) => account.address); + + expect(trackedAddresses).toStrictEqual(keyringAccounts); + }); + }); + + describe('ConnectivityController', () => { + it('reports online connectivity status', async () => { + const wallet = new Wallet({}); + + await new Promise((resolve) => process.nextTick(resolve)); + + expect(wallet.state.ConnectivityController.connectivityStatus).toBe( + CONNECTIVITY_STATUSES.Online, + ); + }); + }); + describe('KeyringController', () => { it('can unlock and populate accounts', async () => { const wallet = await setupWallet(); diff --git a/packages/wallet/src/initialization/instances/accounts-controller.ts b/packages/wallet/src/initialization/instances/accounts-controller.ts index 6d3f267fac..c4903d2d7f 100644 --- a/packages/wallet/src/initialization/instances/accounts-controller.ts +++ b/packages/wallet/src/initialization/instances/accounts-controller.ts @@ -1,6 +1,7 @@ import { AccountsController, AccountsControllerMessenger, + AccountsControllerState, } from '@metamask/accounts-controller'; import { Messenger, @@ -26,7 +27,7 @@ export const accountsController: InitializationConfiguration< name: 'AccountsController', init: ({ state, messenger }) => new AccountsController({ - state, + state: (state ?? {}) as AccountsControllerState, messenger, }), getMessenger: (parent: RootMessenger) => { diff --git a/packages/wallet/src/initialization/instances/connectivity-controller.test.ts b/packages/wallet/src/initialization/instances/connectivity-controller.test.ts new file mode 100644 index 0000000000..39f8904faf --- /dev/null +++ b/packages/wallet/src/initialization/instances/connectivity-controller.test.ts @@ -0,0 +1,51 @@ +import { CONNECTIVITY_STATUSES } from '@metamask/connectivity-controller'; +import { Messenger } from '@metamask/messenger'; + +import { + AlwaysOnlineAdapter, + connectivityController, +} from './connectivity-controller'; + +describe('AlwaysOnlineAdapter', () => { + it('returns Online from getStatus', async () => { + const adapter = new AlwaysOnlineAdapter(); + const status = await adapter.getStatus(); + + expect(status).toBe(CONNECTIVITY_STATUSES.Online); + }); + + it('onConnectivityChange is a no-op', () => { + const adapter = new AlwaysOnlineAdapter(); + const callback = jest.fn(); + + adapter.onConnectivityChange(callback); + + expect(callback).not.toHaveBeenCalled(); + }); + + it('destroy is a no-op', () => { + const adapter = new AlwaysOnlineAdapter(); + + expect(() => adapter.destroy()).not.toThrow(); + }); +}); + +describe('connectivityController', () => { + it('reports online status after initialization', async () => { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const parent = new Messenger<'Root', any, any>({ namespace: 'Root' }); + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const messenger = connectivityController.getMessenger(parent as any); + const controller = connectivityController.init({ + messenger, + state: undefined, + options: {}, + }); + + await controller.init(); + + expect(controller.state.connectivityStatus).toBe( + CONNECTIVITY_STATUSES.Online, + ); + }); +}); diff --git a/packages/wallet/src/initialization/instances/connectivity-controller.ts b/packages/wallet/src/initialization/instances/connectivity-controller.ts index 7e92c491ee..060f6168f4 100644 --- a/packages/wallet/src/initialization/instances/connectivity-controller.ts +++ b/packages/wallet/src/initialization/instances/connectivity-controller.ts @@ -10,16 +10,38 @@ import { Messenger } from '@metamask/messenger'; import type { DefaultActions, DefaultEvents, RootMessenger } from '../defaults'; import type { InitializationConfiguration } from '../types'; -// TODO: For now, we assume we are always online. -class AlwaysOnlineAdapter implements ConnectivityAdapter { +/** + * A connectivity adapter that unconditionally reports the device as online. + * + * This is a temporary placeholder until a real platform-specific adapter + * (one that observes actual network events) is injected by the consumer. + */ +export class AlwaysOnlineAdapter implements ConnectivityAdapter { + /** + * Returns the current connectivity status. + * + * @returns A promise that always resolves to the online status. + */ async getStatus(): Promise { return CONNECTIVITY_STATUSES.Online; } + /** + * Registers a callback for connectivity changes. + * + * This adapter never changes status, so the callback is never invoked. + * + * @param _callback - The callback to register. + */ onConnectivityChange(_callback: (status: ConnectivityStatus) => void): void { // no-op } + /** + * Cleans up any resources held by this adapter. + * + * This adapter holds no resources, so this is a no-op. + */ destroy(): void { // no-op } diff --git a/packages/wallet/src/utilities.test.ts b/packages/wallet/src/utilities.test.ts new file mode 100644 index 0000000000..37b1f804bb --- /dev/null +++ b/packages/wallet/src/utilities.test.ts @@ -0,0 +1,31 @@ +import { webcrypto } from 'crypto'; + +import { createSecretRecoveryPhrase } from './utilities'; +import { Wallet } from './Wallet'; + +const TEST_PASSWORD = 'testpass'; + +describe('createSecretRecoveryPhrase', () => { + beforeAll(() => { + // We can remove this once we drop Node 18 + // eslint-disable-next-line n/no-unsupported-features/node-builtins + globalThis.crypto ??= webcrypto as typeof globalThis.crypto; + + // eslint-disable-next-line no-restricted-syntax + if (!('CryptoKey' in globalThis)) { + Object.defineProperty(globalThis, 'CryptoKey', { + value: webcrypto.CryptoKey, + }); + } + }); + + it('creates a vault and populates accounts', async () => { + const wallet = new Wallet({}); + + await createSecretRecoveryPhrase(wallet, TEST_PASSWORD); + + expect( + await wallet.messenger.call('KeyringController:getAccounts'), + ).toHaveLength(1); + }); +}); diff --git a/packages/wallet/tsconfig.build.json b/packages/wallet/tsconfig.build.json index b16ce7cfcd..a971bc355d 100644 --- a/packages/wallet/tsconfig.build.json +++ b/packages/wallet/tsconfig.build.json @@ -6,7 +6,9 @@ "rootDir": "./src" }, "references": [ + { "path": "../accounts-controller/tsconfig.build.json" }, { "path": "../base-controller/tsconfig.build.json" }, + { "path": "../connectivity-controller/tsconfig.build.json" }, { "path": "../keyring-controller/tsconfig.build.json" }, { "path": "../messenger/tsconfig.build.json" } ], From a9e2a08b549dc72ffd75c9279567087b545943b3 Mon Sep 17 00:00:00 2001 From: grypez <143971198+grypez@users.noreply.github.com> Date: Mon, 1 Jun 2026 08:59:15 -0500 Subject: [PATCH 04/26] refactor(wallet): simplify AccountsController messenger instantiation Use explicit type annotation instead of verbose generic type parameters, leveraging the exported AccountsControllerMessenger type. Co-Authored-By: Claude Sonnet 4.6 --- .../instances/accounts-controller.ts | 24 +++++-------------- 1 file changed, 6 insertions(+), 18 deletions(-) diff --git a/packages/wallet/src/initialization/instances/accounts-controller.ts b/packages/wallet/src/initialization/instances/accounts-controller.ts index c4903d2d7f..f036c449eb 100644 --- a/packages/wallet/src/initialization/instances/accounts-controller.ts +++ b/packages/wallet/src/initialization/instances/accounts-controller.ts @@ -3,11 +3,7 @@ import { AccountsControllerMessenger, AccountsControllerState, } from '@metamask/accounts-controller'; -import { - Messenger, - MessengerActions, - MessengerEvents, -} from '@metamask/messenger'; +import { Messenger } from '@metamask/messenger'; import type { DefaultActions, DefaultEvents, RootMessenger } from '../defaults'; import type { InitializationConfiguration } from '../types'; @@ -16,10 +12,6 @@ import type { InitializationConfiguration } from '../types'; // and MultichainAccountService. Migrate once those controllers are wired into // the wallet initialization (both still depend on AccountsController at the // messenger level, so it must remain present in the meantime). -type AllowedActions = MessengerActions; - -type AllowedEvents = MessengerEvents; - export const accountsController: InitializationConfiguration< AccountsController, AccountsControllerMessenger @@ -31,15 +23,11 @@ export const accountsController: InitializationConfiguration< messenger, }), getMessenger: (parent: RootMessenger) => { - const accountsControllerMessenger = new Messenger< - 'AccountsController', - AllowedActions, - AllowedEvents, - typeof parent - >({ - namespace: 'AccountsController', - parent, - }); + const accountsControllerMessenger: AccountsControllerMessenger = + new Messenger({ + namespace: 'AccountsController', + parent, + }); parent.delegate({ messenger: accountsControllerMessenger, From 17ebad6e70f0722d3a4628677b85a00ed181e69e Mon Sep 17 00:00:00 2001 From: grypez <143971198+grypez@users.noreply.github.com> Date: Mon, 1 Jun 2026 08:59:27 -0500 Subject: [PATCH 05/26] feat(wallet): make ConnectivityController adapter injectable and call init Add connectivityAdapter to instanceOptions so mobile and extension can supply a platform-specific adapter. Fall back to AlwaysOnlineAdapter when none is provided. Call controller.init() from the factory so the initial connectivity status is always fetched on construction. Co-Authored-By: Claude Sonnet 4.6 --- .../instances/connectivity-controller.ts | 12 ++++++++---- packages/wallet/src/types.ts | 4 ++++ 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/packages/wallet/src/initialization/instances/connectivity-controller.ts b/packages/wallet/src/initialization/instances/connectivity-controller.ts index 060f6168f4..721743cda5 100644 --- a/packages/wallet/src/initialization/instances/connectivity-controller.ts +++ b/packages/wallet/src/initialization/instances/connectivity-controller.ts @@ -52,11 +52,15 @@ export const connectivityController: InitializationConfiguration< ConnectivityControllerMessenger > = { name: 'ConnectivityController', - init: ({ messenger }) => - new ConnectivityController({ + init: ({ messenger, options }) => { + const controller = new ConnectivityController({ messenger, - connectivityAdapter: new AlwaysOnlineAdapter(), - }), + connectivityAdapter: + options.connectivityAdapter ?? new AlwaysOnlineAdapter(), + }); + controller.init().catch(console.error); + return controller; + }, getMessenger: (parent: RootMessenger) => new Messenger<'ConnectivityController', never, never, typeof parent>({ namespace: 'ConnectivityController', diff --git a/packages/wallet/src/types.ts b/packages/wallet/src/types.ts index 4d385c85a9..08940be9ca 100644 --- a/packages/wallet/src/types.ts +++ b/packages/wallet/src/types.ts @@ -1,3 +1,4 @@ +import type { ConnectivityAdapter } from '@metamask/connectivity-controller'; import { KeyringControllerOptions } from '@metamask/keyring-controller'; import type { Json } from '@metamask/utils'; @@ -20,6 +21,9 @@ export type WalletOptions = { }; export type InstanceSpecificOptions = { + connectivityController?: { + connectivityAdapter?: ConnectivityAdapter; + }; keyringController?: { encryptor?: GenericEncryptor; keyringBuilders?: KeyringControllerOptions['keyringBuilders']; From 135e5959ee56053c7d1f45aba8eccf2b2a9d2a2f Mon Sep 17 00:00:00 2001 From: grypez <143971198+grypez@users.noreply.github.com> Date: Mon, 1 Jun 2026 08:59:38 -0500 Subject: [PATCH 06/26] test(wallet): update ConnectivityController test to reflect factory-fired init Co-Authored-By: Claude Sonnet 4.6 --- .../initialization/instances/connectivity-controller.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/wallet/src/initialization/instances/connectivity-controller.test.ts b/packages/wallet/src/initialization/instances/connectivity-controller.test.ts index 39f8904faf..0200d0dc77 100644 --- a/packages/wallet/src/initialization/instances/connectivity-controller.test.ts +++ b/packages/wallet/src/initialization/instances/connectivity-controller.test.ts @@ -42,7 +42,7 @@ describe('connectivityController', () => { options: {}, }); - await controller.init(); + await new Promise((resolve) => process.nextTick(resolve)); expect(controller.state.connectivityStatus).toBe( CONNECTIVITY_STATUSES.Online, From 2286e06a484010d4673795ce49b6cb498bffc2ae Mon Sep 17 00:00:00 2001 From: grypez <143971198+grypez@users.noreply.github.com> Date: Mon, 1 Jun 2026 08:59:49 -0500 Subject: [PATCH 07/26] test(wallet): use setupWallet in AccountsController test Co-Authored-By: Claude Sonnet 4.6 --- packages/wallet/src/Wallet.test.ts | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/packages/wallet/src/Wallet.test.ts b/packages/wallet/src/Wallet.test.ts index be5a999659..7e7a7cd708 100644 --- a/packages/wallet/src/Wallet.test.ts +++ b/packages/wallet/src/Wallet.test.ts @@ -5,10 +5,7 @@ import { webcrypto } from 'crypto'; import MockEncryptor from '../../keyring-controller/tests/mocks/mockEncryptor'; import * as initializationModule from './initialization/initialization'; -import { - createSecretRecoveryPhrase, - importSecretRecoveryPhrase, -} from './utilities'; +import { importSecretRecoveryPhrase } from './utilities'; import { Wallet } from './Wallet'; const TEST_SRP = 'test test test test test test test test test test test ball'; @@ -182,8 +179,7 @@ describe('Wallet', () => { describe('AccountsController', () => { it('tracks accounts created via KeyringController', async () => { - const wallet = new Wallet({}); - await createSecretRecoveryPhrase(wallet, TEST_PASSWORD); + const wallet = await setupWallet(); const keyringAccounts = await wallet.messenger.call( 'KeyringController:getAccounts', From 7bdf8fd3a89fac4622f5fcfb2aeef53316324cf5 Mon Sep 17 00:00:00 2001 From: grypez <143971198+grypez@users.noreply.github.com> Date: Mon, 1 Jun 2026 09:31:48 -0500 Subject: [PATCH 08/26] test(wallet): consolidate utilities tests into Wallet.test.ts Co-Authored-By: Claude Sonnet 4.6 --- packages/wallet/src/Wallet.test.ts | 17 ++++++++++++++- packages/wallet/src/utilities.test.ts | 31 --------------------------- 2 files changed, 16 insertions(+), 32 deletions(-) delete mode 100644 packages/wallet/src/utilities.test.ts diff --git a/packages/wallet/src/Wallet.test.ts b/packages/wallet/src/Wallet.test.ts index 7e7a7cd708..362537b3df 100644 --- a/packages/wallet/src/Wallet.test.ts +++ b/packages/wallet/src/Wallet.test.ts @@ -5,7 +5,10 @@ import { webcrypto } from 'crypto'; import MockEncryptor from '../../keyring-controller/tests/mocks/mockEncryptor'; import * as initializationModule from './initialization/initialization'; -import { importSecretRecoveryPhrase } from './utilities'; +import { + createSecretRecoveryPhrase, + importSecretRecoveryPhrase, +} from './utilities'; import { Wallet } from './Wallet'; const TEST_SRP = 'test test test test test test test test test test test ball'; @@ -204,6 +207,18 @@ describe('Wallet', () => { }); }); + describe('createSecretRecoveryPhrase', () => { + it('creates a vault and populates accounts', async () => { + const wallet = new Wallet({}); + + await createSecretRecoveryPhrase(wallet, TEST_PASSWORD); + + expect( + await wallet.messenger.call('KeyringController:getAccounts'), + ).toHaveLength(1); + }); + }); + describe('KeyringController', () => { it('can unlock and populate accounts', async () => { const wallet = await setupWallet(); diff --git a/packages/wallet/src/utilities.test.ts b/packages/wallet/src/utilities.test.ts deleted file mode 100644 index 37b1f804bb..0000000000 --- a/packages/wallet/src/utilities.test.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { webcrypto } from 'crypto'; - -import { createSecretRecoveryPhrase } from './utilities'; -import { Wallet } from './Wallet'; - -const TEST_PASSWORD = 'testpass'; - -describe('createSecretRecoveryPhrase', () => { - beforeAll(() => { - // We can remove this once we drop Node 18 - // eslint-disable-next-line n/no-unsupported-features/node-builtins - globalThis.crypto ??= webcrypto as typeof globalThis.crypto; - - // eslint-disable-next-line no-restricted-syntax - if (!('CryptoKey' in globalThis)) { - Object.defineProperty(globalThis, 'CryptoKey', { - value: webcrypto.CryptoKey, - }); - } - }); - - it('creates a vault and populates accounts', async () => { - const wallet = new Wallet({}); - - await createSecretRecoveryPhrase(wallet, TEST_PASSWORD); - - expect( - await wallet.messenger.call('KeyringController:getAccounts'), - ).toHaveLength(1); - }); -}); From 5f7cd5fa09c9877c9669cc3c79a52b6e4c26181e Mon Sep 17 00:00:00 2001 From: grypez <143971198+grypez@users.noreply.github.com> Date: Mon, 1 Jun 2026 12:43:28 -0500 Subject: [PATCH 09/26] feat(wallet): don't call ConnectivityController.init() from factory Co-Authored-By: Claude Sonnet 4.6 --- packages/wallet/src/Wallet.test.ts | 4 +--- .../instances/connectivity-controller.test.ts | 4 +--- .../initialization/instances/connectivity-controller.ts | 9 +++------ 3 files changed, 5 insertions(+), 12 deletions(-) diff --git a/packages/wallet/src/Wallet.test.ts b/packages/wallet/src/Wallet.test.ts index 362537b3df..8ff1ed4175 100644 --- a/packages/wallet/src/Wallet.test.ts +++ b/packages/wallet/src/Wallet.test.ts @@ -196,11 +196,9 @@ describe('Wallet', () => { }); describe('ConnectivityController', () => { - it('reports online connectivity status', async () => { + it('reports online connectivity status', () => { const wallet = new Wallet({}); - await new Promise((resolve) => process.nextTick(resolve)); - expect(wallet.state.ConnectivityController.connectivityStatus).toBe( CONNECTIVITY_STATUSES.Online, ); diff --git a/packages/wallet/src/initialization/instances/connectivity-controller.test.ts b/packages/wallet/src/initialization/instances/connectivity-controller.test.ts index 0200d0dc77..c2da7a8187 100644 --- a/packages/wallet/src/initialization/instances/connectivity-controller.test.ts +++ b/packages/wallet/src/initialization/instances/connectivity-controller.test.ts @@ -31,7 +31,7 @@ describe('AlwaysOnlineAdapter', () => { }); describe('connectivityController', () => { - it('reports online status after initialization', async () => { + it('reports online status after initialization', () => { // eslint-disable-next-line @typescript-eslint/no-explicit-any const parent = new Messenger<'Root', any, any>({ namespace: 'Root' }); // eslint-disable-next-line @typescript-eslint/no-explicit-any @@ -42,8 +42,6 @@ describe('connectivityController', () => { options: {}, }); - await new Promise((resolve) => process.nextTick(resolve)); - expect(controller.state.connectivityStatus).toBe( CONNECTIVITY_STATUSES.Online, ); diff --git a/packages/wallet/src/initialization/instances/connectivity-controller.ts b/packages/wallet/src/initialization/instances/connectivity-controller.ts index 721743cda5..66d19941b6 100644 --- a/packages/wallet/src/initialization/instances/connectivity-controller.ts +++ b/packages/wallet/src/initialization/instances/connectivity-controller.ts @@ -52,15 +52,12 @@ export const connectivityController: InitializationConfiguration< ConnectivityControllerMessenger > = { name: 'ConnectivityController', - init: ({ messenger, options }) => { - const controller = new ConnectivityController({ + init: ({ messenger, options }) => + new ConnectivityController({ messenger, connectivityAdapter: options.connectivityAdapter ?? new AlwaysOnlineAdapter(), - }); - controller.init().catch(console.error); - return controller; - }, + }), getMessenger: (parent: RootMessenger) => new Messenger<'ConnectivityController', never, never, typeof parent>({ namespace: 'ConnectivityController', From 3efac138bac9ab64598a1c460be0ae337c681d6e Mon Sep 17 00:00:00 2001 From: grypez <143971198+grypez@users.noreply.github.com> Date: Mon, 1 Jun 2026 12:49:24 -0500 Subject: [PATCH 10/26] deps(wallet): add accounts-controller and connectivity-controller as explicit dependencies Co-Authored-By: Claude Sonnet 4.6 --- packages/wallet/package.json | 2 ++ yarn.lock | 2 ++ 2 files changed, 4 insertions(+) diff --git a/packages/wallet/package.json b/packages/wallet/package.json index 2f75bb0c42..50682919f5 100644 --- a/packages/wallet/package.json +++ b/packages/wallet/package.json @@ -53,8 +53,10 @@ "test:watch": "NODE_OPTIONS=--experimental-vm-modules jest --watch" }, "dependencies": { + "@metamask/accounts-controller": "^38.1.2", "@metamask/base-controller": "^9.1.0", "@metamask/browser-passworder": "^6.0.0", + "@metamask/connectivity-controller": "^0.2.0", "@metamask/keyring-controller": "^26.0.0", "@metamask/messenger": "^1.2.0", "@metamask/scure-bip39": "^2.1.1", diff --git a/yarn.lock b/yarn.lock index c00b46658d..f10fd9879f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5883,9 +5883,11 @@ __metadata: version: 0.0.0-use.local resolution: "@metamask/wallet@workspace:packages/wallet" dependencies: + "@metamask/accounts-controller": "npm:^38.1.2" "@metamask/auto-changelog": "npm:^6.1.0" "@metamask/base-controller": "npm:^9.1.0" "@metamask/browser-passworder": "npm:^6.0.0" + "@metamask/connectivity-controller": "npm:^0.2.0" "@metamask/keyring-controller": "npm:^26.0.0" "@metamask/messenger": "npm:^1.2.0" "@metamask/scure-bip39": "npm:^2.1.1" From b1364f71ba434f305af4744d1d5cdcb4fc6724c1 Mon Sep 17 00:00:00 2001 From: grypez <143971198+grypez@users.noreply.github.com> Date: Mon, 1 Jun 2026 13:02:57 -0500 Subject: [PATCH 11/26] docs: Update README.md with package dep links --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 125343e1c9..effbfcaef3 100644 --- a/README.md +++ b/README.md @@ -565,7 +565,9 @@ linkStyle default opacity:0.5 user_operation_controller --> polling_controller; user_operation_controller --> transaction_controller; user_operation_controller --> eth_block_tracker; + wallet --> accounts_controller; wallet --> base_controller; + wallet --> connectivity_controller; wallet --> keyring_controller; wallet --> messenger; ``` From 784be659bb8b2eb0de6e84969cec0717ea23b7ad Mon Sep 17 00:00:00 2001 From: grypez <143971198+grypez@users.noreply.github.com> Date: Mon, 1 Jun 2026 13:12:00 -0500 Subject: [PATCH 12/26] chore: add CODEOWNERS rule for accounts-controller wallet initialization Co-Authored-By: Claude Sonnet 4.6 --- .github/CODEOWNERS | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 0da6d8a878..fd24da621f 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -129,6 +129,7 @@ /packages/profile-metrics-controller @MetaMask/mobile-platform @MetaMask/extension-platform ## Initialization +/packages/wallet/src/initialization/instances/accounts-controller.ts @MetaMask/accounts-engineers @MetaMask/core-platform /packages/wallet/src/initialization/instances/keyring-controller.ts @MetaMask/accounts-engineers @MetaMask/core-platform ## Package Release related From af010be091a201b358e93374d26a84e5371bfdfc Mon Sep 17 00:00:00 2001 From: grypez <143971198+grypez@users.noreply.github.com> Date: Mon, 1 Jun 2026 13:12:59 -0500 Subject: [PATCH 13/26] chore: explicitly own wallet initialization instances subpath in CODEOWNERS Co-Authored-By: Claude Sonnet 4.6 --- .github/CODEOWNERS | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index fd24da621f..7447972b22 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -130,6 +130,7 @@ ## Initialization /packages/wallet/src/initialization/instances/accounts-controller.ts @MetaMask/accounts-engineers @MetaMask/core-platform +/packages/wallet/src/initialization/instances/connectivity-controller.ts @MetaMask/core-platform /packages/wallet/src/initialization/instances/keyring-controller.ts @MetaMask/accounts-engineers @MetaMask/core-platform ## Package Release related From b701b1e0fcf4455a2e2de81102eab6e37a19dc18 Mon Sep 17 00:00:00 2001 From: grypez <143971198+grypez@users.noreply.github.com> Date: Mon, 1 Jun 2026 13:39:08 -0500 Subject: [PATCH 14/26] refactor(wallet): remove explicit Messenger type params from ConnectivityController factory Co-Authored-By: Claude Sonnet 4.6 --- .../src/initialization/instances/connectivity-controller.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/wallet/src/initialization/instances/connectivity-controller.ts b/packages/wallet/src/initialization/instances/connectivity-controller.ts index 66d19941b6..6bdc12636e 100644 --- a/packages/wallet/src/initialization/instances/connectivity-controller.ts +++ b/packages/wallet/src/initialization/instances/connectivity-controller.ts @@ -59,7 +59,7 @@ export const connectivityController: InitializationConfiguration< options.connectivityAdapter ?? new AlwaysOnlineAdapter(), }), getMessenger: (parent: RootMessenger) => - new Messenger<'ConnectivityController', never, never, typeof parent>({ + new Messenger({ namespace: 'ConnectivityController', parent, }), From eb4d185e43361fb09833c34b3890a566d3c45aa9 Mon Sep 17 00:00:00 2001 From: grypez <143971198+grypez@users.noreply.github.com> Date: Mon, 1 Jun 2026 13:57:01 -0500 Subject: [PATCH 15/26] fix(accounts-controller): make state optional in constructor Co-Authored-By: Claude Sonnet 4.6 --- 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 e5216b49b1..db2e29095a 100644 --- a/packages/accounts-controller/src/AccountsController.ts +++ b/packages/accounts-controller/src/AccountsController.ts @@ -327,7 +327,7 @@ export class AccountsController extends BaseController< state, }: { messenger: AccountsControllerMessenger; - state: AccountsControllerState; + state?: AccountsControllerState; }) { const accountIdByAddress = constructAccountIdByAddress( state?.internalAccounts?.accounts ?? {}, From 29825d5fd35e7ea95d0d09c94122679e4f6089e5 Mon Sep 17 00:00:00 2001 From: grypez <143971198+grypez@users.noreply.github.com> Date: Mon, 1 Jun 2026 13:58:13 -0500 Subject: [PATCH 16/26] refactor(wallet): drop AccountsController state cast and TODO comment Co-Authored-By: Claude Sonnet 4.6 --- .../src/initialization/instances/accounts-controller.ts | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/packages/wallet/src/initialization/instances/accounts-controller.ts b/packages/wallet/src/initialization/instances/accounts-controller.ts index f036c449eb..b22e476040 100644 --- a/packages/wallet/src/initialization/instances/accounts-controller.ts +++ b/packages/wallet/src/initialization/instances/accounts-controller.ts @@ -1,17 +1,12 @@ import { AccountsController, AccountsControllerMessenger, - AccountsControllerState, } from '@metamask/accounts-controller'; import { Messenger } from '@metamask/messenger'; import type { DefaultActions, DefaultEvents, RootMessenger } from '../defaults'; import type { InitializationConfiguration } from '../types'; -// TODO: AccountsController is deprecated in favour of AccountTreeController -// and MultichainAccountService. Migrate once those controllers are wired into -// the wallet initialization (both still depend on AccountsController at the -// messenger level, so it must remain present in the meantime). export const accountsController: InitializationConfiguration< AccountsController, AccountsControllerMessenger @@ -19,7 +14,7 @@ export const accountsController: InitializationConfiguration< name: 'AccountsController', init: ({ state, messenger }) => new AccountsController({ - state: (state ?? {}) as AccountsControllerState, + state, messenger, }), getMessenger: (parent: RootMessenger) => { From 7cb173f7f86529f6b8a4822854f05398126ebefe Mon Sep 17 00:00:00 2001 From: grypez <143971198+grypez@users.noreply.github.com> Date: Mon, 1 Jun 2026 13:58:34 -0500 Subject: [PATCH 17/26] refactor(wallet): require connectivityAdapter when connectivityController options are provided Co-Authored-By: Claude Sonnet 4.6 --- packages/wallet/src/types.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/wallet/src/types.ts b/packages/wallet/src/types.ts index 08940be9ca..3225eac464 100644 --- a/packages/wallet/src/types.ts +++ b/packages/wallet/src/types.ts @@ -22,7 +22,7 @@ export type WalletOptions = { export type InstanceSpecificOptions = { connectivityController?: { - connectivityAdapter?: ConnectivityAdapter; + connectivityAdapter: ConnectivityAdapter; }; keyringController?: { encryptor?: GenericEncryptor; From 878145ea7202ff8e702f7dfa8eb7e7903c8e825f Mon Sep 17 00:00:00 2001 From: grypez <143971198+grypez@users.noreply.github.com> Date: Mon, 1 Jun 2026 16:55:45 -0500 Subject: [PATCH 18/26] refactor(wallet): require connectivityAdapter as a top-level WalletOptions field Co-Authored-By: Claude Sonnet 4.6 --- packages/wallet/src/Wallet.ts | 6 ++++++ .../src/initialization/instances/connectivity-controller.ts | 3 +-- packages/wallet/src/types.ts | 1 + 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/packages/wallet/src/Wallet.ts b/packages/wallet/src/Wallet.ts index 02386c991e..f80f2c0d1c 100644 --- a/packages/wallet/src/Wallet.ts +++ b/packages/wallet/src/Wallet.ts @@ -45,6 +45,12 @@ export class Wallet { this.#instances = initialize({ ...options, messenger: this.#messenger, + instanceOptions: { + ...options.instanceOptions, + connectivityController: { + connectivityAdapter: options.connectivityAdapter, + }, + }, }); this.#controllerMetadata = Object.fromEntries( diff --git a/packages/wallet/src/initialization/instances/connectivity-controller.ts b/packages/wallet/src/initialization/instances/connectivity-controller.ts index 6bdc12636e..521bb8ecde 100644 --- a/packages/wallet/src/initialization/instances/connectivity-controller.ts +++ b/packages/wallet/src/initialization/instances/connectivity-controller.ts @@ -55,8 +55,7 @@ export const connectivityController: InitializationConfiguration< init: ({ messenger, options }) => new ConnectivityController({ messenger, - connectivityAdapter: - options.connectivityAdapter ?? new AlwaysOnlineAdapter(), + connectivityAdapter: options.connectivityAdapter, }), getMessenger: (parent: RootMessenger) => new Messenger({ diff --git a/packages/wallet/src/types.ts b/packages/wallet/src/types.ts index 3225eac464..7bbcb8b78b 100644 --- a/packages/wallet/src/types.ts +++ b/packages/wallet/src/types.ts @@ -11,6 +11,7 @@ import { GenericEncryptor } from './initialization/instances/keyring-controller' import { InitializationConfiguration } from './initialization/types'; export type WalletOptions = { + connectivityAdapter: ConnectivityAdapter; messenger?: RootMessenger; state?: Record | undefined>; initializationConfigurations?: InitializationConfiguration< From 087aa7107c1f3940a303f650e294752b56d0eb97 Mon Sep 17 00:00:00 2001 From: grypez <143971198+grypez@users.noreply.github.com> Date: Mon, 1 Jun 2026 16:55:53 -0500 Subject: [PATCH 19/26] test(wallet): pass AlwaysOnlineAdapter explicitly in wallet tests Co-Authored-By: Claude Sonnet 4.6 --- packages/wallet/src/Wallet.test.ts | 12 ++++++++---- .../instances/connectivity-controller.test.ts | 2 +- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/packages/wallet/src/Wallet.test.ts b/packages/wallet/src/Wallet.test.ts index 8ff1ed4175..e7a116cfc5 100644 --- a/packages/wallet/src/Wallet.test.ts +++ b/packages/wallet/src/Wallet.test.ts @@ -5,6 +5,7 @@ import { webcrypto } from 'crypto'; import MockEncryptor from '../../keyring-controller/tests/mocks/mockEncryptor'; import * as initializationModule from './initialization/initialization'; +import { AlwaysOnlineAdapter } from './initialization/instances/connectivity-controller'; import { createSecretRecoveryPhrase, importSecretRecoveryPhrase, @@ -15,7 +16,7 @@ const TEST_SRP = 'test test test test test test test test test test test ball'; const TEST_PASSWORD = 'testpass'; async function setupWallet(): Promise { - const wallet = new Wallet({}); + const wallet = new Wallet({ connectivityAdapter: new AlwaysOnlineAdapter() }); await importSecretRecoveryPhrase(wallet, TEST_PASSWORD, TEST_SRP); @@ -63,6 +64,7 @@ describe('Wallet', () => { it('supports passing instance options', async () => { const wallet = new Wallet({ + connectivityAdapter: new AlwaysOnlineAdapter(), instanceOptions: { keyringController: { encryptor: new MockEncryptor(), @@ -91,6 +93,7 @@ describe('Wallet', () => { class DummyService {} const wallet = new Wallet({ + connectivityAdapter: new AlwaysOnlineAdapter(), initializationConfigurations: [ { name: 'KeyringController', @@ -135,7 +138,7 @@ describe('Wallet', () => { NoMeta: { state: {} }, }); - const wallet = new Wallet({}); + const wallet = new Wallet({ connectivityAdapter: new AlwaysOnlineAdapter() }); expect(wallet.controllerMetadata).toStrictEqual({ WithMeta: fakeMetadata, @@ -197,7 +200,7 @@ describe('Wallet', () => { describe('ConnectivityController', () => { it('reports online connectivity status', () => { - const wallet = new Wallet({}); + const wallet = new Wallet({ connectivityAdapter: new AlwaysOnlineAdapter() }); expect(wallet.state.ConnectivityController.connectivityStatus).toBe( CONNECTIVITY_STATUSES.Online, @@ -207,7 +210,7 @@ describe('Wallet', () => { describe('createSecretRecoveryPhrase', () => { it('creates a vault and populates accounts', async () => { - const wallet = new Wallet({}); + const wallet = new Wallet({ connectivityAdapter: new AlwaysOnlineAdapter() }); await createSecretRecoveryPhrase(wallet, TEST_PASSWORD); @@ -232,6 +235,7 @@ describe('Wallet', () => { '{"data":"iOD5pIcPeRZYQ4WdEMsNYoZ3xBxWBafIU8Cr4nD0X4zBvrOA06tGen3sKQ/ValasXSweLnzH9Fk2frkPYmqeJWBtTNYFwdHPe7P970ThZwreSXN1Sqrx9Ad+YzmIN0y89Yg3KrUodPWaRgIZmgWbfDon6ADPgeEDkX0/GAEYET39O7Rx/gL+rcaTpxnpHPTgHiLbhRHWGsS3z+JVomSqoLAO5XVvrJWenO6R3Nzm62BaJaSPrf/pwstZqhSvxTq8hnQf7aR81hWfwYTxNBVG7TC/dniSQ8K5So6PvUN5nzAqvtzzHT2TagOuxQkX88Zi17P8os21jNmNdA90IGYroD+b/mppyRIgRYWtAUQZH9ji36atEuFupszbg8Qw1iaL3EQyUogC30Cpj9ko5bbqhYgqmFHF0J/kflhPHKuO6d4tgSmhYpTumydQRjxaPnlghIS5YI4W+7p9HVBpb+c6IPUz9y/x3Ngbp+ukJwOnXt2U/eZhXrJzi2z1x/nzPg4fzDJoM7k=","iv":"yrZsyC7dso/q7pQ48YX3vw==","keyMetadata":{"algorithm":"PBKDF2","params":{"iterations":600000}},"salt":"s7nIrMWK1lcZVjfdmES1DBML8Uz4ja2fpm8zUz1lWI0="}'; const wallet = new Wallet({ + connectivityAdapter: new AlwaysOnlineAdapter(), state: { KeyringController: { vault, diff --git a/packages/wallet/src/initialization/instances/connectivity-controller.test.ts b/packages/wallet/src/initialization/instances/connectivity-controller.test.ts index c2da7a8187..8e3e9f5687 100644 --- a/packages/wallet/src/initialization/instances/connectivity-controller.test.ts +++ b/packages/wallet/src/initialization/instances/connectivity-controller.test.ts @@ -39,7 +39,7 @@ describe('connectivityController', () => { const controller = connectivityController.init({ messenger, state: undefined, - options: {}, + options: { connectivityAdapter: new AlwaysOnlineAdapter() }, }); expect(controller.state.connectivityStatus).toBe( From 9879a05256b4424bad971053569663337f53142f Mon Sep 17 00:00:00 2001 From: grypez <143971198+grypez@users.noreply.github.com> Date: Mon, 1 Jun 2026 18:38:35 -0500 Subject: [PATCH 20/26] fix: lint --- packages/wallet/src/Wallet.test.ts | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/packages/wallet/src/Wallet.test.ts b/packages/wallet/src/Wallet.test.ts index 0dd85eef8f..2cb876f898 100644 --- a/packages/wallet/src/Wallet.test.ts +++ b/packages/wallet/src/Wallet.test.ts @@ -154,7 +154,9 @@ describe('Wallet', () => { NoMeta: { state: {} }, }); - const wallet = new Wallet({ connectivityAdapter: new AlwaysOnlineAdapter() }); + const wallet = new Wallet({ + connectivityAdapter: new AlwaysOnlineAdapter(), + }); expect(wallet.controllerMetadata).toStrictEqual({ WithMeta: fakeMetadata, @@ -216,7 +218,9 @@ describe('Wallet', () => { describe('ConnectivityController', () => { it('reports online connectivity status', () => { - const wallet = new Wallet({ connectivityAdapter: new AlwaysOnlineAdapter() }); + const wallet = new Wallet({ + connectivityAdapter: new AlwaysOnlineAdapter(), + }); expect(wallet.state.ConnectivityController.connectivityStatus).toBe( CONNECTIVITY_STATUSES.Online, @@ -226,7 +230,9 @@ describe('Wallet', () => { describe('createSecretRecoveryPhrase', () => { it('creates a vault and populates accounts', async () => { - const wallet = new Wallet({ connectivityAdapter: new AlwaysOnlineAdapter() }); + const wallet = new Wallet({ + connectivityAdapter: new AlwaysOnlineAdapter(), + }); await createSecretRecoveryPhrase(wallet, TEST_PASSWORD); From 0bc503fb5114fb9234e6553a55e7baf4a0308097 Mon Sep 17 00:00:00 2001 From: grypez <143971198+grypez@users.noreply.github.com> Date: Mon, 1 Jun 2026 19:44:31 -0500 Subject: [PATCH 21/26] refactor(wallet): remove createSecretRecoveryPhrase utility Co-Authored-By: Claude Sonnet 4.6 --- packages/wallet/src/Wallet.test.ts | 19 +------------------ packages/wallet/src/utilities.ts | 17 ----------------- 2 files changed, 1 insertion(+), 35 deletions(-) diff --git a/packages/wallet/src/Wallet.test.ts b/packages/wallet/src/Wallet.test.ts index 2cb876f898..1a70dce41d 100644 --- a/packages/wallet/src/Wallet.test.ts +++ b/packages/wallet/src/Wallet.test.ts @@ -7,10 +7,7 @@ import { webcrypto } from 'crypto'; import MockEncryptor from '../../keyring-controller/tests/mocks/mockEncryptor'; import * as initializationModule from './initialization/initialization'; import { AlwaysOnlineAdapter } from './initialization/instances/connectivity-controller'; -import { - createSecretRecoveryPhrase, - importSecretRecoveryPhrase, -} from './utilities'; +import { importSecretRecoveryPhrase } from './utilities'; import { Wallet } from './Wallet'; const TEST_SRP = 'test test test test test test test test test test test ball'; @@ -228,20 +225,6 @@ describe('Wallet', () => { }); }); - describe('createSecretRecoveryPhrase', () => { - it('creates a vault and populates accounts', async () => { - const wallet = new Wallet({ - connectivityAdapter: new AlwaysOnlineAdapter(), - }); - - await createSecretRecoveryPhrase(wallet, TEST_PASSWORD); - - expect( - await wallet.messenger.call('KeyringController:getAccounts'), - ).toHaveLength(1); - }); - }); - describe('KeyringController', () => { it('can unlock and populate accounts', async () => { const wallet = await setupWallet(); diff --git a/packages/wallet/src/utilities.ts b/packages/wallet/src/utilities.ts index e3f9814fda..4630dd5460 100644 --- a/packages/wallet/src/utilities.ts +++ b/packages/wallet/src/utilities.ts @@ -24,20 +24,3 @@ export async function importSecretRecoveryPhrase( mnemonic, ); } - -/** - * Initialize the wallet object with a randomly generated secret recovery phrase. - * - * @param wallet - The wallet object. - * @param password - The password to the MetaMask wallet (not the SRP). - */ -export async function createSecretRecoveryPhrase( - wallet: Wallet, - password: string, -): Promise { - // TODO: This should use the new MultichainAccountService. - await wallet.messenger.call( - 'KeyringController:createNewVaultAndKeychain', - password, - ); -} From 488b4c6f1cc86ad1d483d1654b1781146c901822 Mon Sep 17 00:00:00 2001 From: grypez <143971198+grypez@users.noreply.github.com> Date: Mon, 1 Jun 2026 20:10:51 -0500 Subject: [PATCH 22/26] chore(wallet): mark connectivityAdapter requirement as breaking in changelog Co-Authored-By: Claude Sonnet 4.6 --- packages/wallet/CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/wallet/CHANGELOG.md b/packages/wallet/CHANGELOG.md index 15d61516b2..14eaf56ea2 100644 --- a/packages/wallet/CHANGELOG.md +++ b/packages/wallet/CHANGELOG.md @@ -9,7 +9,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added -- Add `AccountsController` and `ConnectivityController` as default initialized controllers ([#8924](https://github.com/MetaMask/core/pull/8924)) +- **BREAKING:** Add `AccountsController` and `ConnectivityController` as default initialized controllers ([#8924](https://github.com/MetaMask/core/pull/8924)) + - `connectivityAdapter` is now a required top-level field in `WalletOptions`. Pass `AlwaysOnlineAdapter` from `@metamask/wallet` for environments without platform network APIs. - Add `keyringV2Builders` to the `keyringController` instance options, forwarded to the `KeyringController` constructor ([#8956](https://github.com/MetaMask/core/pull/8956)) - **BREAKING:** Add `StorageService` initialization ([#8946](https://github.com/MetaMask/core/pull/8946)) - Passing `instanceOptions.storageService.storage` is now required. From 367e85d6ac59a3deebd34550cf7058e3f8e82280 Mon Sep 17 00:00:00 2001 From: grypez <143971198+grypez@users.noreply.github.com> Date: Tue, 2 Jun 2026 05:16:08 -0500 Subject: [PATCH 23/26] refactor(wallet): move connectivityAdapter into instanceOptions Pass the connectivity adapter through `instanceOptions.connectivityController` instead of a top-level `WalletOptions.connectivityAdapter` field, and make the `connectivityController` instance options required. This drops the constructor glue that re-wrapped the top-level option and keeps the wallet defaults compatible across mobile and extension, since each consumer supplies its own adapter. Supersedes the top-level field introduced in 878145ea7, per PR review feedback. Co-Authored-By: Claude Opus 4.8 --- packages/wallet/CHANGELOG.md | 2 +- packages/wallet/src/Wallet.test.ts | 34 ++++++++++++++++++++++++------ packages/wallet/src/Wallet.ts | 6 ------ packages/wallet/src/types.ts | 3 +-- 4 files changed, 30 insertions(+), 15 deletions(-) diff --git a/packages/wallet/CHANGELOG.md b/packages/wallet/CHANGELOG.md index 14eaf56ea2..a59595744a 100644 --- a/packages/wallet/CHANGELOG.md +++ b/packages/wallet/CHANGELOG.md @@ -10,7 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - **BREAKING:** Add `AccountsController` and `ConnectivityController` as default initialized controllers ([#8924](https://github.com/MetaMask/core/pull/8924)) - - `connectivityAdapter` is now a required top-level field in `WalletOptions`. Pass `AlwaysOnlineAdapter` from `@metamask/wallet` for environments without platform network APIs. + - Passing `instanceOptions.connectivityController.connectivityAdapter` is now required. - Add `keyringV2Builders` to the `keyringController` instance options, forwarded to the `KeyringController` constructor ([#8956](https://github.com/MetaMask/core/pull/8956)) - **BREAKING:** Add `StorageService` initialization ([#8946](https://github.com/MetaMask/core/pull/8946)) - Passing `instanceOptions.storageService.storage` is now required. diff --git a/packages/wallet/src/Wallet.test.ts b/packages/wallet/src/Wallet.test.ts index 1a70dce41d..702d24a761 100644 --- a/packages/wallet/src/Wallet.test.ts +++ b/packages/wallet/src/Wallet.test.ts @@ -15,8 +15,10 @@ const TEST_PASSWORD = 'testpass'; async function setupWallet(): Promise { const wallet = new Wallet({ - connectivityAdapter: new AlwaysOnlineAdapter(), instanceOptions: { + connectivityController: { + connectivityAdapter: new AlwaysOnlineAdapter(), + }, storageService: { storage: new InMemoryStorageAdapter(), }, @@ -69,8 +71,10 @@ describe('Wallet', () => { it('supports passing instance options', async () => { const wallet = new Wallet({ - connectivityAdapter: new AlwaysOnlineAdapter(), instanceOptions: { + connectivityController: { + connectivityAdapter: new AlwaysOnlineAdapter(), + }, keyringController: { encryptor: new MockEncryptor(), }, @@ -101,7 +105,6 @@ describe('Wallet', () => { class DummyService {} const wallet = new Wallet({ - connectivityAdapter: new AlwaysOnlineAdapter(), initializationConfigurations: [ { name: 'KeyringController', @@ -117,6 +120,9 @@ describe('Wallet', () => { }, ], instanceOptions: { + connectivityController: { + connectivityAdapter: new AlwaysOnlineAdapter(), + }, storageService: { storage: new InMemoryStorageAdapter(), }, @@ -152,7 +158,14 @@ describe('Wallet', () => { }); const wallet = new Wallet({ - connectivityAdapter: new AlwaysOnlineAdapter(), + instanceOptions: { + connectivityController: { + connectivityAdapter: new AlwaysOnlineAdapter(), + }, + storageService: { + storage: new InMemoryStorageAdapter(), + }, + }, }); expect(wallet.controllerMetadata).toStrictEqual({ @@ -216,7 +229,14 @@ describe('Wallet', () => { describe('ConnectivityController', () => { it('reports online connectivity status', () => { const wallet = new Wallet({ - connectivityAdapter: new AlwaysOnlineAdapter(), + instanceOptions: { + connectivityController: { + connectivityAdapter: new AlwaysOnlineAdapter(), + }, + storageService: { + storage: new InMemoryStorageAdapter(), + }, + }, }); expect(wallet.state.ConnectivityController.connectivityStatus).toBe( @@ -240,13 +260,15 @@ describe('Wallet', () => { '{"data":"iOD5pIcPeRZYQ4WdEMsNYoZ3xBxWBafIU8Cr4nD0X4zBvrOA06tGen3sKQ/ValasXSweLnzH9Fk2frkPYmqeJWBtTNYFwdHPe7P970ThZwreSXN1Sqrx9Ad+YzmIN0y89Yg3KrUodPWaRgIZmgWbfDon6ADPgeEDkX0/GAEYET39O7Rx/gL+rcaTpxnpHPTgHiLbhRHWGsS3z+JVomSqoLAO5XVvrJWenO6R3Nzm62BaJaSPrf/pwstZqhSvxTq8hnQf7aR81hWfwYTxNBVG7TC/dniSQ8K5So6PvUN5nzAqvtzzHT2TagOuxQkX88Zi17P8os21jNmNdA90IGYroD+b/mppyRIgRYWtAUQZH9ji36atEuFupszbg8Qw1iaL3EQyUogC30Cpj9ko5bbqhYgqmFHF0J/kflhPHKuO6d4tgSmhYpTumydQRjxaPnlghIS5YI4W+7p9HVBpb+c6IPUz9y/x3Ngbp+ukJwOnXt2U/eZhXrJzi2z1x/nzPg4fzDJoM7k=","iv":"yrZsyC7dso/q7pQ48YX3vw==","keyMetadata":{"algorithm":"PBKDF2","params":{"iterations":600000}},"salt":"s7nIrMWK1lcZVjfdmES1DBML8Uz4ja2fpm8zUz1lWI0="}'; const wallet = new Wallet({ - connectivityAdapter: new AlwaysOnlineAdapter(), state: { KeyringController: { vault, }, }, instanceOptions: { + connectivityController: { + connectivityAdapter: new AlwaysOnlineAdapter(), + }, storageService: { storage: new InMemoryStorageAdapter(), }, diff --git a/packages/wallet/src/Wallet.ts b/packages/wallet/src/Wallet.ts index 1d4475a14e..5ba1566599 100644 --- a/packages/wallet/src/Wallet.ts +++ b/packages/wallet/src/Wallet.ts @@ -45,12 +45,6 @@ export class Wallet { this.#instances = initialize({ ...options, messenger: this.#messenger, - instanceOptions: { - ...options.instanceOptions, - connectivityController: { - connectivityAdapter: options.connectivityAdapter, - }, - }, }); this.#controllerMetadata = Object.fromEntries( diff --git a/packages/wallet/src/types.ts b/packages/wallet/src/types.ts index 6092ca2df5..905ad3e208 100644 --- a/packages/wallet/src/types.ts +++ b/packages/wallet/src/types.ts @@ -12,7 +12,6 @@ import { GenericEncryptor } from './initialization/instances/keyring-controller' import { InitializationConfiguration } from './initialization/types'; export type WalletOptions = { - connectivityAdapter: ConnectivityAdapter; messenger?: RootMessenger; state?: Record | undefined>; initializationConfigurations?: InitializationConfiguration< @@ -23,7 +22,7 @@ export type WalletOptions = { }; export type InstanceSpecificOptions = { - connectivityController?: { + connectivityController: { connectivityAdapter: ConnectivityAdapter; }; keyringController?: { From 4c48cc7f1dc50faf137b87a7a386881dc73a8e55 Mon Sep 17 00:00:00 2001 From: grypez <143971198+grypez@users.noreply.github.com> Date: Tue, 2 Jun 2026 05:19:43 -0500 Subject: [PATCH 24/26] chore: mirror accounts-controller ownership for wallet init file Drop @MetaMask/core-platform as co-owner of the wallet accounts-controller initialization file so it matches the ownership of the accounts-controller package itself (@MetaMask/accounts-engineers), per PR review feedback. Co-Authored-By: Claude Opus 4.8 --- .github/CODEOWNERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index f51cbacf22..e5d214706a 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -129,7 +129,7 @@ /packages/profile-metrics-controller @MetaMask/mobile-platform @MetaMask/extension-platform ## Initialization -/packages/wallet/src/initialization/instances/accounts-controller.ts @MetaMask/accounts-engineers @MetaMask/core-platform +/packages/wallet/src/initialization/instances/accounts-controller.ts @MetaMask/accounts-engineers /packages/wallet/src/initialization/instances/connectivity-controller.ts @MetaMask/core-platform /packages/wallet/src/initialization/instances/keyring-controller.ts @MetaMask/accounts-engineers @MetaMask/core-platform From f450e56bc8dcb1fe3bc1ff565671f805e50fe3f5 Mon Sep 17 00:00:00 2001 From: grypez <143971198+grypez@users.noreply.github.com> Date: Tue, 2 Jun 2026 07:47:58 -0500 Subject: [PATCH 25/26] chore(accounts-controller): add changelog entry for optional constructor state Document that the `AccountsController` constructor's `state` option is now optional, introduced in this PR alongside the wallet default-controller work. Co-Authored-By: Claude Opus 4.8 --- packages/accounts-controller/CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/accounts-controller/CHANGELOG.md b/packages/accounts-controller/CHANGELOG.md index 812cb46320..706ea115fe 100644 --- a/packages/accounts-controller/CHANGELOG.md +++ b/packages/accounts-controller/CHANGELOG.md @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Changed + +- The `state` option of the `AccountsController` constructor is now optional, defaulting to the controller's default state when omitted ([#8924](https://github.com/MetaMask/core/pull/8924)) + ## [38.1.2] ### Changed From 02b1f3275b4422984bc37319d2b33b2759a03bbe Mon Sep 17 00:00:00 2001 From: grypez <143971198+grypez@users.noreply.github.com> Date: Tue, 2 Jun 2026 14:19:41 -0500 Subject: [PATCH 26/26] refactor(wallet): migrate accounts and connectivity instances to per-directory convention Move the AccountsController and ConnectivityController initialization configs into their own directories to match the per-controller layout established by the ApprovalController instance, so the package isn't left in two styles. - accounts-controller/accounts-controller.ts - connectivity-controller/{connectivity-controller,types,always-online-adapter}.ts with colocated tests, pulling AlwaysOnlineAdapter into its own sibling file (mirroring the keyring encryptor split) and extracting the connectivity instance options into a ConnectivityControllerInstanceOptions type. Co-Authored-By: Claude Opus 4.8 --- .github/CODEOWNERS | 4 +-- packages/wallet/src/Wallet.test.ts | 2 +- .../accounts-controller.ts | 8 +++-- .../always-online-adapter.test.ts | 27 +++++++++++++++++ .../always-online-adapter.ts} | 23 -------------- .../connectivity-controller.test.ts | 30 ++----------------- .../connectivity-controller.ts | 29 ++++++++++++++++++ .../connectivity-controller/types.ts | 13 ++++++++ .../src/initialization/instances/index.ts | 4 +-- packages/wallet/src/types.ts | 6 ++-- 10 files changed, 84 insertions(+), 62 deletions(-) rename packages/wallet/src/initialization/instances/{ => accounts-controller}/accounts-controller.ts (89%) create mode 100644 packages/wallet/src/initialization/instances/connectivity-controller/always-online-adapter.test.ts rename packages/wallet/src/initialization/instances/{connectivity-controller.ts => connectivity-controller/always-online-adapter.ts} (60%) rename packages/wallet/src/initialization/instances/{ => connectivity-controller}/connectivity-controller.test.ts (52%) create mode 100644 packages/wallet/src/initialization/instances/connectivity-controller/connectivity-controller.ts create mode 100644 packages/wallet/src/initialization/instances/connectivity-controller/types.ts diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index dcfb6f9743..b4eafeb5ac 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -129,9 +129,9 @@ /packages/profile-metrics-controller @MetaMask/mobile-platform @MetaMask/extension-platform ## Initialization -/packages/wallet/src/initialization/instances/accounts-controller.ts @MetaMask/accounts-engineers +/packages/wallet/src/initialization/instances/accounts-controller/ @MetaMask/accounts-engineers /packages/wallet/src/initialization/instances/approval-controller/ @MetaMask/confirmations -/packages/wallet/src/initialization/instances/connectivity-controller.ts @MetaMask/core-platform +/packages/wallet/src/initialization/instances/connectivity-controller/ @MetaMask/core-platform /packages/wallet/src/initialization/instances/keyring-controller.ts @MetaMask/accounts-engineers @MetaMask/core-platform ## Package Release related diff --git a/packages/wallet/src/Wallet.test.ts b/packages/wallet/src/Wallet.test.ts index 702d24a761..aa2447b37a 100644 --- a/packages/wallet/src/Wallet.test.ts +++ b/packages/wallet/src/Wallet.test.ts @@ -6,7 +6,7 @@ import { webcrypto } from 'crypto'; import MockEncryptor from '../../keyring-controller/tests/mocks/mockEncryptor'; import * as initializationModule from './initialization/initialization'; -import { AlwaysOnlineAdapter } from './initialization/instances/connectivity-controller'; +import { AlwaysOnlineAdapter } from './initialization/instances/connectivity-controller/always-online-adapter'; import { importSecretRecoveryPhrase } from './utilities'; import { Wallet } from './Wallet'; diff --git a/packages/wallet/src/initialization/instances/accounts-controller.ts b/packages/wallet/src/initialization/instances/accounts-controller/accounts-controller.ts similarity index 89% rename from packages/wallet/src/initialization/instances/accounts-controller.ts rename to packages/wallet/src/initialization/instances/accounts-controller/accounts-controller.ts index b22e476040..89023affb3 100644 --- a/packages/wallet/src/initialization/instances/accounts-controller.ts +++ b/packages/wallet/src/initialization/instances/accounts-controller/accounts-controller.ts @@ -4,8 +4,12 @@ import { } from '@metamask/accounts-controller'; import { Messenger } from '@metamask/messenger'; -import type { DefaultActions, DefaultEvents, RootMessenger } from '../defaults'; -import type { InitializationConfiguration } from '../types'; +import type { + DefaultActions, + DefaultEvents, + RootMessenger, +} from '../../defaults'; +import type { InitializationConfiguration } from '../../types'; export const accountsController: InitializationConfiguration< AccountsController, diff --git a/packages/wallet/src/initialization/instances/connectivity-controller/always-online-adapter.test.ts b/packages/wallet/src/initialization/instances/connectivity-controller/always-online-adapter.test.ts new file mode 100644 index 0000000000..417438a541 --- /dev/null +++ b/packages/wallet/src/initialization/instances/connectivity-controller/always-online-adapter.test.ts @@ -0,0 +1,27 @@ +import { CONNECTIVITY_STATUSES } from '@metamask/connectivity-controller'; + +import { AlwaysOnlineAdapter } from './always-online-adapter'; + +describe('AlwaysOnlineAdapter', () => { + it('returns Online from getStatus', async () => { + const adapter = new AlwaysOnlineAdapter(); + const status = await adapter.getStatus(); + + expect(status).toBe(CONNECTIVITY_STATUSES.Online); + }); + + it('onConnectivityChange is a no-op', () => { + const adapter = new AlwaysOnlineAdapter(); + const callback = jest.fn(); + + adapter.onConnectivityChange(callback); + + expect(callback).not.toHaveBeenCalled(); + }); + + it('destroy is a no-op', () => { + const adapter = new AlwaysOnlineAdapter(); + + expect(() => adapter.destroy()).not.toThrow(); + }); +}); diff --git a/packages/wallet/src/initialization/instances/connectivity-controller.ts b/packages/wallet/src/initialization/instances/connectivity-controller/always-online-adapter.ts similarity index 60% rename from packages/wallet/src/initialization/instances/connectivity-controller.ts rename to packages/wallet/src/initialization/instances/connectivity-controller/always-online-adapter.ts index 521bb8ecde..9630eae0f6 100644 --- a/packages/wallet/src/initialization/instances/connectivity-controller.ts +++ b/packages/wallet/src/initialization/instances/connectivity-controller/always-online-adapter.ts @@ -1,14 +1,8 @@ import { CONNECTIVITY_STATUSES, ConnectivityAdapter, - ConnectivityController, - ConnectivityControllerMessenger, ConnectivityStatus, } from '@metamask/connectivity-controller'; -import { Messenger } from '@metamask/messenger'; - -import type { DefaultActions, DefaultEvents, RootMessenger } from '../defaults'; -import type { InitializationConfiguration } from '../types'; /** * A connectivity adapter that unconditionally reports the device as online. @@ -46,20 +40,3 @@ export class AlwaysOnlineAdapter implements ConnectivityAdapter { // no-op } } - -export const connectivityController: InitializationConfiguration< - ConnectivityController, - ConnectivityControllerMessenger -> = { - name: 'ConnectivityController', - init: ({ messenger, options }) => - new ConnectivityController({ - messenger, - connectivityAdapter: options.connectivityAdapter, - }), - getMessenger: (parent: RootMessenger) => - new Messenger({ - namespace: 'ConnectivityController', - parent, - }), -}; diff --git a/packages/wallet/src/initialization/instances/connectivity-controller.test.ts b/packages/wallet/src/initialization/instances/connectivity-controller/connectivity-controller.test.ts similarity index 52% rename from packages/wallet/src/initialization/instances/connectivity-controller.test.ts rename to packages/wallet/src/initialization/instances/connectivity-controller/connectivity-controller.test.ts index 8e3e9f5687..5cc10d0976 100644 --- a/packages/wallet/src/initialization/instances/connectivity-controller.test.ts +++ b/packages/wallet/src/initialization/instances/connectivity-controller/connectivity-controller.test.ts @@ -1,34 +1,8 @@ import { CONNECTIVITY_STATUSES } from '@metamask/connectivity-controller'; import { Messenger } from '@metamask/messenger'; -import { - AlwaysOnlineAdapter, - connectivityController, -} from './connectivity-controller'; - -describe('AlwaysOnlineAdapter', () => { - it('returns Online from getStatus', async () => { - const adapter = new AlwaysOnlineAdapter(); - const status = await adapter.getStatus(); - - expect(status).toBe(CONNECTIVITY_STATUSES.Online); - }); - - it('onConnectivityChange is a no-op', () => { - const adapter = new AlwaysOnlineAdapter(); - const callback = jest.fn(); - - adapter.onConnectivityChange(callback); - - expect(callback).not.toHaveBeenCalled(); - }); - - it('destroy is a no-op', () => { - const adapter = new AlwaysOnlineAdapter(); - - expect(() => adapter.destroy()).not.toThrow(); - }); -}); +import { AlwaysOnlineAdapter } from './always-online-adapter'; +import { connectivityController } from './connectivity-controller'; describe('connectivityController', () => { it('reports online status after initialization', () => { diff --git a/packages/wallet/src/initialization/instances/connectivity-controller/connectivity-controller.ts b/packages/wallet/src/initialization/instances/connectivity-controller/connectivity-controller.ts new file mode 100644 index 0000000000..43f681879e --- /dev/null +++ b/packages/wallet/src/initialization/instances/connectivity-controller/connectivity-controller.ts @@ -0,0 +1,29 @@ +import { + ConnectivityController, + ConnectivityControllerMessenger, +} from '@metamask/connectivity-controller'; +import { Messenger } from '@metamask/messenger'; + +import type { + DefaultActions, + DefaultEvents, + RootMessenger, +} from '../../defaults'; +import type { InitializationConfiguration } from '../../types'; + +export const connectivityController: InitializationConfiguration< + ConnectivityController, + ConnectivityControllerMessenger +> = { + name: 'ConnectivityController', + init: ({ messenger, options }) => + new ConnectivityController({ + messenger, + connectivityAdapter: options.connectivityAdapter, + }), + getMessenger: (parent: RootMessenger) => + new Messenger({ + namespace: 'ConnectivityController', + parent, + }), +}; diff --git a/packages/wallet/src/initialization/instances/connectivity-controller/types.ts b/packages/wallet/src/initialization/instances/connectivity-controller/types.ts new file mode 100644 index 0000000000..e7df03a212 --- /dev/null +++ b/packages/wallet/src/initialization/instances/connectivity-controller/types.ts @@ -0,0 +1,13 @@ +import type { ConnectivityAdapter } from '@metamask/connectivity-controller'; + +/** + * Per-instance options for the wallet's `ConnectivityController`. + */ +export type ConnectivityControllerInstanceOptions = { + /** + * Platform-specific adapter that observes the device's network connectivity. + * Required because connectivity is inherently platform-specific; node-like + * environments can pass the exported `AlwaysOnlineAdapter`. + */ + connectivityAdapter: ConnectivityAdapter; +}; diff --git a/packages/wallet/src/initialization/instances/index.ts b/packages/wallet/src/initialization/instances/index.ts index 1e93e0be8d..8042e64a03 100644 --- a/packages/wallet/src/initialization/instances/index.ts +++ b/packages/wallet/src/initialization/instances/index.ts @@ -1,5 +1,5 @@ -export { accountsController } from './accounts-controller'; +export { accountsController } from './accounts-controller/accounts-controller'; export { approvalController } from './approval-controller/approval-controller'; -export { connectivityController } from './connectivity-controller'; +export { connectivityController } from './connectivity-controller/connectivity-controller'; export { keyringController } from './keyring-controller'; export { storageService } from './storage-service'; diff --git a/packages/wallet/src/types.ts b/packages/wallet/src/types.ts index d8fdad9b88..198ae04542 100644 --- a/packages/wallet/src/types.ts +++ b/packages/wallet/src/types.ts @@ -1,4 +1,3 @@ -import type { ConnectivityAdapter } from '@metamask/connectivity-controller'; import { KeyringControllerOptions } from '@metamask/keyring-controller'; import { StorageAdapter } from '@metamask/storage-service'; import type { Json } from '@metamask/utils'; @@ -9,6 +8,7 @@ import type { RootMessenger, } from './initialization/defaults'; import type { ApprovalControllerInstanceOptions } from './initialization/instances/approval-controller/types'; +import type { ConnectivityControllerInstanceOptions } from './initialization/instances/connectivity-controller/types'; import { GenericEncryptor } from './initialization/instances/keyring-controller'; import { InitializationConfiguration } from './initialization/types'; @@ -24,9 +24,7 @@ export type WalletOptions = { export type InstanceSpecificOptions = { approvalController?: ApprovalControllerInstanceOptions; - connectivityController: { - connectivityAdapter: ConnectivityAdapter; - }; + connectivityController: ConnectivityControllerInstanceOptions; keyringController?: { encryptor?: GenericEncryptor; keyringBuilders?: KeyringControllerOptions['keyringBuilders'];