From f22848c363c045ff7c32ae76bf5c06accc44596c Mon Sep 17 00:00:00 2001 From: Salah-Eddine Saakoun Date: Wed, 10 Sep 2025 00:31:00 +0200 Subject: [PATCH] refactor: migrate MultichainAccountService to @metamask/messenger --- .../multichain-account-service/CHANGELOG.md | 5 + .../multichain-account-service/package.json | 1 + .../src/MultichainAccountService.test.ts | 126 ++++++++++-------- .../src/providers/EvmAccountProvider.test.ts | 18 +-- .../src/providers/SolAccountProvider.test.ts | 18 +-- .../src/tests/messenger.ts | 71 ++++++---- .../multichain-account-service/src/types.ts | 12 +- yarn.lock | 1 + 8 files changed, 131 insertions(+), 121 deletions(-) diff --git a/packages/multichain-account-service/CHANGELOG.md b/packages/multichain-account-service/CHANGELOG.md index 5c43ecc56a6..259dfe8031f 100644 --- a/packages/multichain-account-service/CHANGELOG.md +++ b/packages/multichain-account-service/CHANGELOG.md @@ -13,6 +13,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Add `multichainAccountGroupCreated` event emitted from wallet level when new groups are created. - Add `multichainAccountGroupUpdated` event emitted from wallet level when groups are synchronized. +### Changed + +- **BREAKING:** Use new `Messenger` from `@metamask/messenger` ([#6544](https://github.com/MetaMask/core/pull/6544)) + - Previously, `MultichainAccountService` accepted a `RestrictedMessenger` instance from `@metamask/base-controller`. + ## [0.7.0] ### Added diff --git a/packages/multichain-account-service/package.json b/packages/multichain-account-service/package.json index ed2d142c934..2a7abd11350 100644 --- a/packages/multichain-account-service/package.json +++ b/packages/multichain-account-service/package.json @@ -53,6 +53,7 @@ "@metamask/keyring-internal-api": "^8.1.0", "@metamask/keyring-snap-client": "^7.0.0", "@metamask/keyring-utils": "^3.1.0", + "@metamask/messenger": "^0.2.0", "@metamask/snaps-sdk": "^9.0.0", "@metamask/snaps-utils": "^11.0.0", "@metamask/superstruct": "^3.1.0", diff --git a/packages/multichain-account-service/src/MultichainAccountService.test.ts b/packages/multichain-account-service/src/MultichainAccountService.test.ts index 1b2562dda1f..dad09cfe618 100644 --- a/packages/multichain-account-service/src/MultichainAccountService.test.ts +++ b/packages/multichain-account-service/src/MultichainAccountService.test.ts @@ -1,6 +1,5 @@ /* eslint-disable jsdoc/require-jsdoc */ -import type { Messenger } from '@metamask/base-controller'; import type { KeyringAccount } from '@metamask/keyring-api'; import { EthAccountType, SolAccountType } from '@metamask/keyring-api'; import { KeyringTypes, type KeyringObject } from '@metamask/keyring-controller'; @@ -27,14 +26,9 @@ import { makeMockAccountProvider, mockAsInternalAccount, setupAccountProvider, + type RootMessenger, } from './tests'; -import type { - AllowedActions, - AllowedEvents, - MultichainAccountServiceActions, - MultichainAccountServiceEvents, - MultichainAccountServiceMessenger, -} from './types'; +import type { MultichainAccountServiceMessenger } from './types'; // Mock providers. jest.mock('./providers/EvmAccountProvider', () => { @@ -80,22 +74,17 @@ function mockAccountProvider( } function setup({ - messenger = getRootMessenger(), + rootMessenger = getRootMessenger(), keyrings = [MOCK_HD_KEYRING_1, MOCK_HD_KEYRING_2], accounts, }: { - messenger?: Messenger< - MultichainAccountServiceActions | AllowedActions, - MultichainAccountServiceEvents | AllowedEvents - >; + rootMessenger?: RootMessenger; keyrings?: KeyringObject[]; accounts?: KeyringAccount[]; } = {}): { service: MultichainAccountService; - messenger: Messenger< - MultichainAccountServiceActions | AllowedActions, - MultichainAccountServiceEvents | AllowedEvents - >; + rootMessenger: RootMessenger; + messenger: MultichainAccountServiceMessenger; mocks: Mocks; } { const mocks: Mocks = { @@ -118,7 +107,7 @@ function setup({ keyrings: mocks.KeyringController.keyrings, })); - messenger.registerActionHandler( + rootMessenger.registerActionHandler( 'KeyringController:getState', mocks.KeyringController.getState, ); @@ -128,7 +117,7 @@ function setup({ () => accounts, ); - messenger.registerActionHandler( + rootMessenger.registerActionHandler( 'AccountsController:listMultichainAccounts', mocks.AccountsController.listMultichainAccounts, ); @@ -147,12 +136,20 @@ function setup({ ); } + const messenger = getMultichainAccountServiceMessenger(rootMessenger); + const service = new MultichainAccountService({ - messenger: getMultichainAccountServiceMessenger(messenger), + messenger, }); + service.init(); - return { service, messenger, mocks }; + return { + service, + rootMessenger, + messenger, + mocks, + }; } describe('MultichainAccountService', () => { @@ -365,7 +362,7 @@ describe('MultichainAccountService', () => { it('syncs the appropriate wallet and update reverse mapping on AccountsController:accountAdded', () => { const accounts = [account1, account3]; // No `account2` for now. - const { service, messenger, mocks } = setup({ accounts, keyrings }); + const { service, rootMessenger, mocks } = setup({ accounts, keyrings }); const wallet1 = service.getMultichainAccountWallet({ entropySource: entropy1, @@ -374,7 +371,7 @@ describe('MultichainAccountService', () => { // Now we're adding `account2`. mocks.EvmAccountProvider.accounts = [account1, account2]; - messenger.publish( + rootMessenger.publish( 'AccountsController:accountAdded', mockAsInternalAccount(account2), ); @@ -405,7 +402,7 @@ describe('MultichainAccountService', () => { .get(); const accounts = [account1]; // No `otherAccount1` for now. - const { service, messenger, mocks } = setup({ accounts, keyrings }); + const { service, rootMessenger, mocks } = setup({ accounts, keyrings }); const wallet1 = service.getMultichainAccountWallet({ entropySource: entropy1, @@ -414,7 +411,7 @@ describe('MultichainAccountService', () => { // Now we're adding `account2`. mocks.EvmAccountProvider.accounts = [account1, otherAccount1]; - messenger.publish( + rootMessenger.publish( 'AccountsController:accountAdded', mockAsInternalAccount(otherAccount1), ); @@ -446,12 +443,12 @@ describe('MultichainAccountService', () => { .get(); const accounts = [account1]; // No `otherAccount1` for now. - const { messenger, mocks } = setup({ accounts, keyrings }); + const { rootMessenger, messenger, mocks } = setup({ accounts, keyrings }); const publishSpy = jest.spyOn(messenger, 'publish'); // Now we're adding `otherAccount1` to an existing group. mocks.EvmAccountProvider.accounts = [account1, otherAccount1]; - messenger.publish( + rootMessenger.publish( 'AccountsController:accountAdded', mockAsInternalAccount(otherAccount1), ); @@ -465,7 +462,7 @@ describe('MultichainAccountService', () => { it('creates new detected wallets and update reverse mapping on AccountsController:accountAdded', () => { const accounts = [account1, account2]; // No `account3` for now (associated with "Wallet 2"). - const { service, messenger, mocks } = setup({ + const { service, rootMessenger, mocks } = setup({ accounts, keyrings: [keyring1], }); @@ -483,7 +480,7 @@ describe('MultichainAccountService', () => { // Now we're adding `account3`. mocks.KeyringController.keyrings = [keyring1, keyring2]; mocks.EvmAccountProvider.accounts = [account1, account2, account3]; - messenger.publish( + rootMessenger.publish( 'AccountsController:accountAdded', mockAsInternalAccount(account3), ); @@ -507,7 +504,10 @@ describe('MultichainAccountService', () => { it('ignores non-BIP-44 accounts on AccountsController:accountAdded', () => { const accounts = [account1]; - const { service, messenger } = setup({ accounts, keyrings }); + const { service, rootMessenger } = setup({ + accounts, + keyrings, + }); const wallet1 = service.getMultichainAccountWallet({ entropySource: entropy1, @@ -517,7 +517,7 @@ describe('MultichainAccountService', () => { expect(oldMultichainAccounts[0].getAccounts()).toHaveLength(1); // Now we're publishing a new account that is not BIP-44 compatible. - messenger.publish( + rootMessenger.publish( 'AccountsController:accountAdded', mockAsInternalAccount(MOCK_SNAP_ACCOUNT_2), ); @@ -529,7 +529,7 @@ describe('MultichainAccountService', () => { it('syncs the appropriate wallet and update reverse mapping on AccountsController:accountRemoved', () => { const accounts = [account1, account2]; - const { service, messenger, mocks } = setup({ accounts, keyrings }); + const { service, rootMessenger, mocks } = setup({ accounts, keyrings }); const wallet1 = service.getMultichainAccountWallet({ entropySource: entropy1, @@ -538,7 +538,7 @@ describe('MultichainAccountService', () => { // Now we're removing `account2`. mocks.EvmAccountProvider.accounts = [account1]; - messenger.publish('AccountsController:accountRemoved', account2.id); + rootMessenger.publish('AccountsController:accountRemoved', account2.id); expect(wallet1.getMultichainAccountGroups()).toHaveLength(1); const walletAndMultichainAccount2 = service.getAccountContext( @@ -572,7 +572,9 @@ describe('MultichainAccountService', () => { .withGroupIndex(0) .get(); - const { service, messenger } = setup({ accounts: [mockEvmAccount] }); + const { service, messenger } = setup({ + accounts: [mockEvmAccount], + }); const publishSpy = jest.spyOn(messenger, 'publish'); const nextGroup = await service.createNextMultichainAccountGroup({ @@ -626,7 +628,9 @@ describe('MultichainAccountService', () => { .withGroupIndex(0) .get(); - const { service, messenger } = setup({ accounts: [mockEvmAccount] }); + const { service, messenger } = setup({ + accounts: [mockEvmAccount], + }); const publishSpy = jest.spyOn(messenger, 'publish'); const group = await service.createMultichainAccountGroup({ @@ -747,9 +751,9 @@ describe('MultichainAccountService', () => { describe('actions', () => { it('gets a multichain account with MultichainAccountService:getMultichainAccount', () => { const accounts = [MOCK_HD_ACCOUNT_1]; - const { messenger } = setup({ accounts }); + const { rootMessenger } = setup({ accounts }); - const group = messenger.call( + const group = rootMessenger.call( 'MultichainAccountService:getMultichainAccountGroup', { entropySource: MOCK_HD_KEYRING_1.metadata.id, groupIndex: 0 }, ); @@ -758,9 +762,9 @@ describe('MultichainAccountService', () => { it('gets multichain accounts with MultichainAccountService:getMultichainAccounts', () => { const accounts = [MOCK_HD_ACCOUNT_1]; - const { messenger } = setup({ accounts }); + const { rootMessenger } = setup({ accounts }); - const groups = messenger.call( + const groups = rootMessenger.call( 'MultichainAccountService:getMultichainAccountGroups', { entropySource: MOCK_HD_KEYRING_1.metadata.id }, ); @@ -769,9 +773,9 @@ describe('MultichainAccountService', () => { it('gets multichain account wallet with MultichainAccountService:getMultichainAccountWallet', () => { const accounts = [MOCK_HD_ACCOUNT_1]; - const { messenger } = setup({ accounts }); + const { rootMessenger } = setup({ accounts }); - const wallet = messenger.call( + const wallet = rootMessenger.call( 'MultichainAccountService:getMultichainAccountWallet', { entropySource: MOCK_HD_KEYRING_1.metadata.id }, ); @@ -780,9 +784,9 @@ describe('MultichainAccountService', () => { it('gets multichain account wallet with MultichainAccountService:getMultichainAccountWallets', () => { const accounts = [MOCK_HD_ACCOUNT_1]; - const { messenger } = setup({ accounts }); + const { rootMessenger } = setup({ accounts }); - const wallets = messenger.call( + const wallets = rootMessenger.call( 'MultichainAccountService:getMultichainAccountWallets', ); expect(wallets.length).toBeGreaterThan(0); @@ -790,9 +794,9 @@ describe('MultichainAccountService', () => { it('create the next multichain account group with MultichainAccountService:createNextMultichainAccountGroup', async () => { const accounts = [MOCK_HD_ACCOUNT_1]; - const { messenger } = setup({ accounts }); + const { rootMessenger } = setup({ accounts }); - const nextGroup = await messenger.call( + const nextGroup = await rootMessenger.call( 'MultichainAccountService:createNextMultichainAccountGroup', { entropySource: MOCK_HD_KEYRING_1.metadata.id }, ); @@ -803,9 +807,9 @@ describe('MultichainAccountService', () => { it('creates a multichain account group with MultichainAccountService:createMultichainAccountGroup', async () => { const accounts = [MOCK_HD_ACCOUNT_1]; - const { messenger } = setup({ accounts }); + const { rootMessenger } = setup({ accounts }); - const firstGroup = await messenger.call( + const firstGroup = await rootMessenger.call( 'MultichainAccountService:createMultichainAccountGroup', { entropySource: MOCK_HD_KEYRING_1.metadata.id, @@ -827,11 +831,11 @@ describe('MultichainAccountService', () => { .withEntropySource(MOCK_HD_KEYRING_2.metadata.id) .withGroupIndex(0) .get(); - const { messenger, mocks } = setup({ + const { rootMessenger, mocks } = setup({ accounts: [mockEvmAccount1, mockSolAccount1], }); - await messenger.call( + await rootMessenger.call( 'MultichainAccountService:alignWallet', MOCK_HD_KEYRING_1.metadata.id, ); @@ -852,11 +856,11 @@ describe('MultichainAccountService', () => { .withEntropySource(MOCK_HD_KEYRING_2.metadata.id) .withGroupIndex(0) .get(); - const { messenger, mocks } = setup({ + const { rootMessenger, mocks } = setup({ accounts: [mockEvmAccount1, mockSolAccount1], }); - await messenger.call('MultichainAccountService:alignWallets'); + await rootMessenger.call('MultichainAccountService:alignWallets'); expect(mocks.EvmAccountProvider.createAccounts).toHaveBeenCalledWith({ entropySource: MOCK_HD_KEYRING_2.metadata.id, @@ -869,17 +873,19 @@ describe('MultichainAccountService', () => { }); it('sets basic functionality with MultichainAccountService:setBasicFunctionality', async () => { - const { messenger } = setup({ accounts: [MOCK_HD_ACCOUNT_1] }); + const { rootMessenger } = setup({ + accounts: [MOCK_HD_ACCOUNT_1], + }); // This tests the action handler registration expect( - await messenger.call( + await rootMessenger.call( 'MultichainAccountService:setBasicFunctionality', true, ), ).toBeUndefined(); expect( - await messenger.call( + await rootMessenger.call( 'MultichainAccountService:setBasicFunctionality', false, ), @@ -887,11 +893,11 @@ describe('MultichainAccountService', () => { }); it('gets alignment progress with MultichainAccountService:getIsAlignmentInProgress', () => { - const { messenger } = setup({ + const { rootMessenger } = setup({ accounts: [MOCK_HD_ACCOUNT_1], }); - const isInProgress = messenger.call( + const isInProgress = rootMessenger.call( 'MultichainAccountService:getIsAlignmentInProgress', ); @@ -920,11 +926,13 @@ describe('MultichainAccountService', () => { let solProvider: SolAccountProvider; beforeEach(() => { - const { messenger } = setup({ accounts: [MOCK_HD_ACCOUNT_1] }); + const { rootMessenger } = setup({ + accounts: [MOCK_HD_ACCOUNT_1], + }); // Create actual SolAccountProvider instance for wrapping solProvider = new SolAccountProvider( - getMultichainAccountServiceMessenger(messenger), + getMultichainAccountServiceMessenger(rootMessenger), ); // Spy on the provider methods @@ -935,7 +943,7 @@ describe('MultichainAccountService', () => { jest.spyOn(solProvider, 'isAccountCompatible'); wrapper = new AccountProviderWrapper( - getMultichainAccountServiceMessenger(messenger), + getMultichainAccountServiceMessenger(rootMessenger), solProvider, ); }); diff --git a/packages/multichain-account-service/src/providers/EvmAccountProvider.test.ts b/packages/multichain-account-service/src/providers/EvmAccountProvider.test.ts index b75b7e80221..b4efb05cbe3 100644 --- a/packages/multichain-account-service/src/providers/EvmAccountProvider.test.ts +++ b/packages/multichain-account-service/src/providers/EvmAccountProvider.test.ts @@ -1,4 +1,3 @@ -import type { Messenger } from '@metamask/base-controller'; import { type KeyringMetadata } from '@metamask/keyring-controller'; import type { EthKeyring, @@ -17,13 +16,8 @@ import { MOCK_HD_ACCOUNT_2, MOCK_HD_KEYRING_1, MockAccountBuilder, + type RootMessenger, } from '../tests'; -import type { - AllowedActions, - AllowedEvents, - MultichainAccountServiceActions, - MultichainAccountServiceEvents, -} from '../types'; class MockEthKeyring implements EthKeyring { readonly type = 'MockEthKeyring'; @@ -90,17 +84,11 @@ function setup({ messenger = getRootMessenger(), accounts = [], }: { - messenger?: Messenger< - MultichainAccountServiceActions | AllowedActions, - MultichainAccountServiceEvents | AllowedEvents - >; + messenger?: RootMessenger; accounts?: InternalAccount[]; } = {}): { provider: EvmAccountProvider; - messenger: Messenger< - MultichainAccountServiceActions | AllowedActions, - MultichainAccountServiceEvents | AllowedEvents - >; + messenger: RootMessenger; keyring: MockEthKeyring; mocks: { getAccountByAddress: jest.Mock; diff --git a/packages/multichain-account-service/src/providers/SolAccountProvider.test.ts b/packages/multichain-account-service/src/providers/SolAccountProvider.test.ts index 52720d5d62e..7b8a9167512 100644 --- a/packages/multichain-account-service/src/providers/SolAccountProvider.test.ts +++ b/packages/multichain-account-service/src/providers/SolAccountProvider.test.ts @@ -1,5 +1,4 @@ import { isBip44Account } from '@metamask/account-api'; -import type { Messenger } from '@metamask/base-controller'; import type { SnapKeyring } from '@metamask/eth-snap-keyring'; import type { KeyringMetadata } from '@metamask/keyring-controller'; import type { @@ -17,13 +16,8 @@ import { MOCK_SOL_ACCOUNT_1, MOCK_SOL_DISCOVERED_ACCOUNT_1, MockAccountBuilder, + type RootMessenger, } from '../tests'; -import type { - AllowedActions, - AllowedEvents, - MultichainAccountServiceActions, - MultichainAccountServiceEvents, -} from '../types'; class MockSolanaKeyring { readonly type = 'MockSolanaKeyring'; @@ -94,17 +88,11 @@ function setup({ messenger = getRootMessenger(), accounts = [], }: { - messenger?: Messenger< - MultichainAccountServiceActions | AllowedActions, - MultichainAccountServiceEvents | AllowedEvents - >; + messenger?: RootMessenger; accounts?: InternalAccount[]; } = {}): { provider: AccountProviderWrapper; - messenger: Messenger< - MultichainAccountServiceActions | AllowedActions, - MultichainAccountServiceEvents | AllowedEvents - >; + messenger: RootMessenger; keyring: MockSolanaKeyring; mocks: { handleRequest: jest.Mock; diff --git a/packages/multichain-account-service/src/tests/messenger.ts b/packages/multichain-account-service/src/tests/messenger.ts index 92922839293..cb3c40903a9 100644 --- a/packages/multichain-account-service/src/tests/messenger.ts +++ b/packages/multichain-account-service/src/tests/messenger.ts @@ -1,42 +1,57 @@ -import { Messenger } from '@metamask/base-controller'; +import { + Messenger, + MOCK_ANY_NAMESPACE, + type MessengerActions, + type MessengerEvents, + type MockAnyNamespace, +} from '@metamask/messenger'; -import type { - AllowedActions, - AllowedEvents, - MultichainAccountServiceActions, - MultichainAccountServiceEvents, - MultichainAccountServiceMessenger, -} from '../types'; +import type { MultichainAccountServiceMessenger } from '../types'; + +type AllMultichainAccountServiceActions = + MessengerActions; + +type AllMultichainAccountServiceEvents = + MessengerEvents; + +export type RootMessenger = Messenger< + MockAnyNamespace, + AllMultichainAccountServiceActions, + AllMultichainAccountServiceEvents +>; /** - * Creates a new root messenger instance for testing. + * Creates and returns a root messenger for testing * - * @returns A new Messenger instance. + * @returns A messenger instance */ -export function getRootMessenger() { - return new Messenger< - MultichainAccountServiceActions | AllowedActions, - MultichainAccountServiceEvents | AllowedEvents - >(); +export function getRootMessenger(): RootMessenger { + return new Messenger({ + namespace: MOCK_ANY_NAMESPACE, + }); } /** * Retrieves a restricted messenger for the MultichainAccountService. * - * @param messenger - The root messenger instance. Defaults to a new Messenger created by getRootMessenger(). + * @param rootMessenger - The root messenger instance. Defaults to a new Messenger created by getRootMessenger(). * @returns The restricted messenger for the MultichainAccountService. */ export function getMultichainAccountServiceMessenger( - messenger: ReturnType, + rootMessenger: RootMessenger, ): MultichainAccountServiceMessenger { - return messenger.getRestricted({ - name: 'MultichainAccountService', - allowedEvents: [ - 'KeyringController:stateChange', - 'AccountsController:accountAdded', - 'AccountsController:accountRemoved', - ], - allowedActions: [ + const messenger = new Messenger< + 'MultichainAccountService', + AllMultichainAccountServiceActions, + AllMultichainAccountServiceEvents, + RootMessenger + >({ + namespace: 'MultichainAccountService', + parent: rootMessenger, + }); + rootMessenger.delegate({ + messenger, + actions: [ 'AccountsController:getAccount', 'AccountsController:getAccountByAddress', 'AccountsController:listMultichainAccounts', @@ -46,5 +61,11 @@ export function getMultichainAccountServiceMessenger( 'NetworkController:findNetworkClientIdByChainId', 'NetworkController:getNetworkClientById', ], + events: [ + 'KeyringController:stateChange', + 'AccountsController:accountAdded', + 'AccountsController:accountRemoved', + ], }); + return messenger; } diff --git a/packages/multichain-account-service/src/types.ts b/packages/multichain-account-service/src/types.ts index 3249f063772..ed0a1990f64 100644 --- a/packages/multichain-account-service/src/types.ts +++ b/packages/multichain-account-service/src/types.ts @@ -9,13 +9,13 @@ import type { AccountsControllerGetAccountByAddressAction, AccountsControllerListMultichainAccountsAction, } from '@metamask/accounts-controller'; -import type { RestrictedMessenger } from '@metamask/base-controller'; import type { KeyringAccount } from '@metamask/keyring-api'; import type { KeyringControllerGetStateAction, KeyringControllerStateChangeEvent, KeyringControllerWithKeyringAction, } from '@metamask/keyring-controller'; +import type { Messenger } from '@metamask/messenger'; import type { NetworkControllerFindNetworkClientIdByChainIdAction, NetworkControllerGetNetworkClientByIdAction, @@ -115,7 +115,7 @@ export type MultichainAccountServiceEvents = * All actions registered by other modules that {@link MultichainAccountService} * calls. */ -export type AllowedActions = +type AllowedActions = | AccountsControllerListMultichainAccountsAction | AccountsControllerGetAccountAction | AccountsControllerGetAccountByAddressAction @@ -129,7 +129,7 @@ export type AllowedActions = * All events published by other modules that {@link MultichainAccountService} * subscribes to. */ -export type AllowedEvents = +type AllowedEvents = | KeyringControllerStateChangeEvent | AccountsControllerAccountAddedEvent | AccountsControllerAccountRemovedEvent; @@ -138,10 +138,8 @@ export type AllowedEvents = * The messenger restricted to actions and events that * {@link MultichainAccountService} needs to access. */ -export type MultichainAccountServiceMessenger = RestrictedMessenger< +export type MultichainAccountServiceMessenger = Messenger< 'MultichainAccountService', MultichainAccountServiceActions | AllowedActions, - MultichainAccountServiceEvents | AllowedEvents, - AllowedActions['type'], - AllowedEvents['type'] + MultichainAccountServiceEvents | AllowedEvents >; diff --git a/yarn.lock b/yarn.lock index 0cf2a57b624..b81d3e6dc76 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3829,6 +3829,7 @@ __metadata: "@metamask/keyring-internal-api": "npm:^8.1.0" "@metamask/keyring-snap-client": "npm:^7.0.0" "@metamask/keyring-utils": "npm:^3.1.0" + "@metamask/messenger": "npm:^0.2.0" "@metamask/providers": "npm:^22.1.0" "@metamask/snaps-controllers": "npm:^14.0.1" "@metamask/snaps-sdk": "npm:^9.0.0"