From 5c69e3d1587ed4d810b1454545c5cce9e5717cbc Mon Sep 17 00:00:00 2001 From: Michele Esposito Date: Tue, 26 Aug 2025 14:43:20 +0200 Subject: [PATCH 01/69] refactor: migrate `ApprovalController` to `@metamask/messenger` --- packages/approval-controller/package.json | 1 + .../src/ApprovalController.test.ts | 77 ++++++++----------- .../src/ApprovalController.ts | 32 ++++---- yarn.lock | 1 + 4 files changed, 49 insertions(+), 62 deletions(-) diff --git a/packages/approval-controller/package.json b/packages/approval-controller/package.json index 2309e14830f..0d590c6fc92 100644 --- a/packages/approval-controller/package.json +++ b/packages/approval-controller/package.json @@ -48,6 +48,7 @@ }, "dependencies": { "@metamask/base-controller": "^8.2.0", + "@metamask/messenger": "^0.1.0", "@metamask/rpc-errors": "^7.0.2", "@metamask/utils": "^11.4.2", "nanoid": "^3.3.8" diff --git a/packages/approval-controller/src/ApprovalController.test.ts b/packages/approval-controller/src/ApprovalController.test.ts index 18cc824b451..c9ca5253d3f 100644 --- a/packages/approval-controller/src/ApprovalController.test.ts +++ b/packages/approval-controller/src/ApprovalController.test.ts @@ -1,6 +1,6 @@ /* eslint-disable jest/expect-expect */ -import { Messenger } from '@metamask/base-controller'; +import { Messenger } from '@metamask/messenger'; import { errorCodes, JsonRpcError } from '@metamask/rpc-errors'; import { nanoid } from 'nanoid'; @@ -223,20 +223,28 @@ function getError(message: string, code?: number) { } /** - * Constructs a restricted messenger. + * Constructs a controller messenger. * - * @returns A restricted messenger. + * @returns A controller messenger. */ -function getRestrictedMessenger() { - const messenger = new Messenger< +function getMessengers() { + const rootMessenger = new Messenger< + 'Root', ApprovalControllerActions, ApprovalControllerEvents - >(); - return messenger.getRestricted({ - name: 'ApprovalController', - allowedActions: [], - allowedEvents: [], - }); + >({ namespace: 'Root' }); + return { + rootMessenger, + approvalControllerMessenger: new Messenger< + 'ApprovalController', + ApprovalControllerActions, + ApprovalControllerEvents, + typeof rootMessenger + >({ + namespace: 'ApprovalController', + parent: rootMessenger, + }), + }; } describe('approval controller', () => { @@ -250,7 +258,7 @@ describe('approval controller', () => { showApprovalRequest = jest.fn(); approvalController = new ApprovalController({ - messenger: getRestrictedMessenger(), + messenger: getMessengers().approvalControllerMessenger, showApprovalRequest, }); }); @@ -445,7 +453,7 @@ describe('approval controller', () => { it('does not throw on origin and type collision if type excluded', () => { approvalController = new ApprovalController({ - messenger: getRestrictedMessenger(), + messenger: getMessengers().approvalControllerMessenger, showApprovalRequest, typesExcludedFromRateLimiting: ['myType'], }); @@ -638,7 +646,7 @@ describe('approval controller', () => { it('gets the count when specifying origin and type with type excluded from rate limiting', () => { approvalController = new ApprovalController({ - messenger: getRestrictedMessenger(), + messenger: getMessengers().approvalControllerMessenger, showApprovalRequest, typesExcludedFromRateLimiting: [TYPE], }); @@ -678,7 +686,7 @@ describe('approval controller', () => { it('gets the total approval count with type excluded from rate limiting', () => { approvalController = new ApprovalController({ - messenger: getRestrictedMessenger(), + messenger: getMessengers().approvalControllerMessenger, showApprovalRequest, typesExcludedFromRateLimiting: ['type0'], }); @@ -1269,23 +1277,16 @@ describe('approval controller', () => { describe('actions', () => { it('addApprovalRequest: shouldShowRequest = true', async () => { - const messenger = new Messenger< - ApprovalControllerActions, - ApprovalControllerEvents - >(); + const { rootMessenger, approvalControllerMessenger } = getMessengers(); approvalController = new ApprovalController({ - messenger: messenger.getRestricted({ - name: controllerName, - allowedActions: [], - allowedEvents: [], - }), + messenger: approvalControllerMessenger, showApprovalRequest, }); // TODO: Either fix this lint violation or explain why it's necessary to ignore. // eslint-disable-next-line @typescript-eslint/no-floating-promises - messenger.call( + rootMessenger.call( 'ApprovalController:addRequest', { id: 'foo', origin: 'bar.baz', type: TYPE }, true, @@ -1295,23 +1296,16 @@ describe('approval controller', () => { }); it('addApprovalRequest: shouldShowRequest = false', async () => { - const messenger = new Messenger< - ApprovalControllerActions, - ApprovalControllerEvents - >(); + const { rootMessenger, approvalControllerMessenger } = getMessengers(); approvalController = new ApprovalController({ - messenger: messenger.getRestricted({ - name: controllerName, - allowedActions: [], - allowedEvents: [], - }), + messenger: approvalControllerMessenger, showApprovalRequest, }); // TODO: Either fix this lint violation or explain why it's necessary to ignore. // eslint-disable-next-line @typescript-eslint/no-floating-promises - messenger.call( + rootMessenger.call( 'ApprovalController:addRequest', { id: 'foo', origin: 'bar.baz', type: TYPE }, false, @@ -1321,17 +1315,10 @@ describe('approval controller', () => { }); it('updateRequestState', () => { - const messenger = new Messenger< - ApprovalControllerActions, - ApprovalControllerEvents - >(); + const { rootMessenger, approvalControllerMessenger } = getMessengers(); approvalController = new ApprovalController({ - messenger: messenger.getRestricted({ - name: controllerName, - allowedActions: [], - allowedEvents: [], - }), + messenger: approvalControllerMessenger, showApprovalRequest, }); @@ -1344,7 +1331,7 @@ describe('approval controller', () => { requestState: { foo: 'bar' }, }); - messenger.call('ApprovalController:updateRequestState', { + rootMessenger.call('ApprovalController:updateRequestState', { id: 'foo', requestState: { foo: 'foobar' }, }); diff --git a/packages/approval-controller/src/ApprovalController.ts b/packages/approval-controller/src/ApprovalController.ts index 5b7398a83f8..cf675a35f19 100644 --- a/packages/approval-controller/src/ApprovalController.ts +++ b/packages/approval-controller/src/ApprovalController.ts @@ -2,8 +2,8 @@ import type { ControllerGetStateAction } from '@metamask/base-controller'; import { BaseController, type ControllerStateChangeEvent, - type RestrictedMessenger, -} from '@metamask/base-controller'; +} from '@metamask/base-controller/next'; +import type { Messenger } from '@metamask/messenger'; import type { JsonRpcError, DataWithOptionalCause } from '@metamask/rpc-errors'; import { rpcErrors } from '@metamask/rpc-errors'; import type { Json, OptionalField } from '@metamask/utils'; @@ -119,12 +119,10 @@ export type ApprovalControllerState = { approvalFlows: ApprovalFlowState[]; }; -export type ApprovalControllerMessenger = RestrictedMessenger< +export type ApprovalControllerMessenger = Messenger< typeof controllerName, ApprovalControllerActions, - ApprovalControllerEvents, - never, - never + ApprovalControllerEvents >; // Option Types @@ -398,12 +396,12 @@ export class ApprovalController extends BaseController< * actions. */ private registerMessageHandlers(): void { - this.messagingSystem.registerActionHandler( + this.messenger.registerActionHandler( `${controllerName}:clearRequests` as const, this.clear.bind(this), ); - this.messagingSystem.registerActionHandler( + this.messenger.registerActionHandler( `${controllerName}:addRequest` as const, (opts: AddApprovalOptions, shouldShowRequest: boolean) => { if (shouldShowRequest) { @@ -413,47 +411,47 @@ export class ApprovalController extends BaseController< }, ); - this.messagingSystem.registerActionHandler( + this.messenger.registerActionHandler( `${controllerName}:hasRequest` as const, this.has.bind(this), ); - this.messagingSystem.registerActionHandler( + this.messenger.registerActionHandler( `${controllerName}:acceptRequest` as const, this.accept.bind(this), ); - this.messagingSystem.registerActionHandler( + this.messenger.registerActionHandler( `${controllerName}:rejectRequest` as const, this.reject.bind(this), ); - this.messagingSystem.registerActionHandler( + this.messenger.registerActionHandler( `${controllerName}:updateRequestState` as const, this.updateRequestState.bind(this), ); - this.messagingSystem.registerActionHandler( + this.messenger.registerActionHandler( `${controllerName}:startFlow` as const, this.startFlow.bind(this), ); - this.messagingSystem.registerActionHandler( + this.messenger.registerActionHandler( `${controllerName}:endFlow` as const, this.endFlow.bind(this), ); - this.messagingSystem.registerActionHandler( + this.messenger.registerActionHandler( `${controllerName}:setFlowLoadingText` as const, this.setFlowLoadingText.bind(this), ); - this.messagingSystem.registerActionHandler( + this.messenger.registerActionHandler( `${controllerName}:showSuccess` as const, this.success.bind(this), ); - this.messagingSystem.registerActionHandler( + this.messenger.registerActionHandler( `${controllerName}:showError` as const, this.error.bind(this), ); diff --git a/yarn.lock b/yarn.lock index a431876c636..d2066afdb79 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2547,6 +2547,7 @@ __metadata: dependencies: "@metamask/auto-changelog": "npm:^3.4.4" "@metamask/base-controller": "npm:^8.2.0" + "@metamask/messenger": "npm:^0.1.0" "@metamask/rpc-errors": "npm:^7.0.2" "@metamask/utils": "npm:^11.4.2" "@types/jest": "npm:^27.4.1" From 65c4c78a4182ea189fe274784529d601913544be Mon Sep 17 00:00:00 2001 From: Michele Esposito Date: Tue, 26 Aug 2025 14:45:53 +0200 Subject: [PATCH 02/69] update changelog --- packages/approval-controller/CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/approval-controller/CHANGELOG.md b/packages/approval-controller/CHANGELOG.md index dd9151626b3..41b63f9ae2d 100644 --- a/packages/approval-controller/CHANGELOG.md +++ b/packages/approval-controller/CHANGELOG.md @@ -9,6 +9,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed +- **BREAKING:** Use new `Messenger` from `@metamask/messenger` ([#6386](https://github.com/MetaMask/core/pull/6386)) + - Previously, `ApprovalController` accepted a `RestrictedMessenger` instance from `@metamask/base-controller`. - Bump `@metamask/utils` from `^11.2.0` to `^11.4.2` ([#6054](https://github.com/MetaMask/core/pull/6054)) - Bump `@metamask/base-controller` from `^8.0.0` to `^8.2.0` ([#5722](https://github.com/MetaMask/core/pull/5722), [#6284](https://github.com/MetaMask/core/pull/6284), [#6355](https://github.com/MetaMask/core/pull/6355)) From 0549ba06e5c06a1b2763d9db57e2c8f4a68edba4 Mon Sep 17 00:00:00 2001 From: Michele Esposito Date: Wed, 27 Aug 2025 14:53:47 +0200 Subject: [PATCH 03/69] refactor: migrate `TransactionController` to `@metamask/messenger` --- packages/transaction-controller/package.json | 1 + .../src/TransactionController.test.ts | 94 ++++++++----- .../src/TransactionController.ts | 127 ++++++++---------- .../src/utils/eip7702.test.ts | 38 ++++-- .../src/utils/feature-flags.test.ts | 40 ++++-- .../src/utils/swaps.test.ts | 38 ++++-- yarn.lock | 1 + 7 files changed, 205 insertions(+), 134 deletions(-) diff --git a/packages/transaction-controller/package.json b/packages/transaction-controller/package.json index e6029489768..865b31e7b93 100644 --- a/packages/transaction-controller/package.json +++ b/packages/transaction-controller/package.json @@ -57,6 +57,7 @@ "@metamask/base-controller": "^8.2.0", "@metamask/controller-utils": "^11.12.0", "@metamask/eth-query": "^4.0.0", + "@metamask/messenger": "^0.1.0", "@metamask/metamask-eth-abis": "^3.1.1", "@metamask/nonce-tracker": "^6.0.0", "@metamask/rpc-errors": "^7.0.2", diff --git a/packages/transaction-controller/src/TransactionController.test.ts b/packages/transaction-controller/src/TransactionController.test.ts index 1b81c49e974..5d62786bf75 100644 --- a/packages/transaction-controller/src/TransactionController.test.ts +++ b/packages/transaction-controller/src/TransactionController.test.ts @@ -4,7 +4,6 @@ import type { AddApprovalRequest, AddResult, } from '@metamask/approval-controller'; -import { Messenger } from '@metamask/base-controller'; import { ChainId, NetworkType, @@ -15,6 +14,7 @@ import { import type { SafeEventEmitterProvider } from '@metamask/eth-json-rpc-provider'; import EthQuery from '@metamask/eth-query'; import HttpProvider from '@metamask/ethjs-provider-http'; +import { Messenger } from '@metamask/messenger'; import type { BlockTracker, NetworkClientConfiguration, @@ -56,6 +56,7 @@ import type { MethodData, TransactionControllerActions, TransactionControllerEvents, + TransactionControllerMessenger, TransactionControllerOptions, } from './TransactionController'; import { TransactionController } from './TransactionController'; @@ -111,7 +112,8 @@ import { buildMockGetNetworkClientById, } from '../../network-controller/tests/helpers'; -type UnrestrictedMessenger = Messenger< +type RootMessenger = Messenger< + 'Root', TransactionControllerActions | AllowedActions, TransactionControllerEvents | AllowedEvents >; @@ -328,10 +330,7 @@ function buildMockGasFeeFlow(): jest.Mocked { * @returns A promise that resolves with the transaction meta when the transaction is finished. */ function waitForTransactionFinished( - messenger: Messenger< - TransactionControllerActions | AllowedActions, - TransactionControllerEvents | AllowedEvents - >, + messenger: TransactionControllerMessenger | RootMessenger, { confirmed = false } = {}, ): Promise { const eventName = confirmed @@ -657,19 +656,33 @@ describe('TransactionController', () => { listener(networkState); }); }; - const unrestrictedMessenger: UnrestrictedMessenger = new Messenger(); + const rootMessenger: RootMessenger = new Messenger({ + namespace: 'Root', + }); + const networkControllerMessenger = new Messenger< + 'NetworkController', + AllowedActions, + AllowedEvents, + typeof rootMessenger + >({ namespace: 'NetworkController', parent: rootMessenger }); const getNetworkClientById = buildMockGetNetworkClientById( mockNetworkClientConfigurationsByNetworkClientId, ); - unrestrictedMessenger.registerActionHandler( + networkControllerMessenger.registerActionHandler( 'NetworkController:getNetworkClientById', getNetworkClientById, ); const { addTransactionApprovalRequest = { state: 'pending' } } = messengerOptions; + const approvalControllerMessenger = new Messenger< + 'ApprovalController', + AllowedActions, + AllowedEvents, + typeof rootMessenger + >({ namespace: 'ApprovalController', parent: rootMessenger }); const mockTransactionApprovalRequest = mockAddTransactionApprovalRequest( - unrestrictedMessenger, + approvalControllerMessenger, addTransactionApprovalRequest, ); @@ -694,28 +707,38 @@ describe('TransactionController', () => { ...givenOptions, }; - const restrictedMessenger = + const transactionControllerMessenger: TransactionControllerMessenger = givenRestrictedMessenger ?? - unrestrictedMessenger.getRestricted({ - name: 'TransactionController', - allowedActions: [ - 'AccountsController:getSelectedAccount', - 'AccountsController:getState', - 'ApprovalController:addRequest', - 'NetworkController:getNetworkClientById', - 'NetworkController:findNetworkClientIdByChainId', - 'RemoteFeatureFlagController:getState', - ], - allowedEvents: [], - }); + new Messenger({ + namespace: 'TransactionController', + parent: rootMessenger, + }); + rootMessenger.delegate({ + messenger: transactionControllerMessenger, + actions: [ + 'AccountsController:getSelectedAccount', + 'AccountsController:getState', + 'ApprovalController:addRequest', + 'NetworkController:getNetworkClientById', + 'NetworkController:findNetworkClientIdByChainId', + 'RemoteFeatureFlagController:getState', + ], + }); + + const accountsControllerMessenger = new Messenger< + 'AccountsController', + AllowedActions, + AllowedEvents, + typeof rootMessenger + >({ namespace: 'AccountsController', parent: rootMessenger }); const mockGetSelectedAccount = jest.fn().mockReturnValue(selectedAccount); - unrestrictedMessenger.registerActionHandler( + accountsControllerMessenger.registerActionHandler( 'AccountsController:getSelectedAccount', mockGetSelectedAccount, ); - unrestrictedMessenger.registerActionHandler( + accountsControllerMessenger.registerActionHandler( 'AccountsController:getState', () => ({}) as never, ); @@ -724,14 +747,24 @@ describe('TransactionController', () => { featureFlags: {}, }); - unrestrictedMessenger.registerActionHandler( + const remoteFeatureFlagControllerMessenger = new Messenger< + 'RemoteFeatureFlagController', + AllowedActions, + AllowedEvents, + typeof rootMessenger + >({ + namespace: 'RemoteFeatureFlagController', + parent: rootMessenger, + }); + + remoteFeatureFlagControllerMessenger.registerActionHandler( 'RemoteFeatureFlagController:getState', remoteFeatureFlagControllerGetStateMock, ); const controller = new TransactionController({ ...otherOptions, - messenger: restrictedMessenger, + messenger: transactionControllerMessenger, } as TransactionControllerOptions); const state = givenOptions?.state; @@ -754,7 +787,8 @@ describe('TransactionController', () => { return { controller, - messenger: unrestrictedMessenger, + messenger: transactionControllerMessenger, + networkControllerMessenger, mockTransactionApprovalRequest, mockGetSelectedAccount, changeNetwork, @@ -783,7 +817,7 @@ describe('TransactionController', () => { * finally the mocked version of the action handler itself. */ function mockAddTransactionApprovalRequest( - messenger: UnrestrictedMessenger, + messenger: Messenger<'ApprovalController', AllowedActions, AllowedEvents>, options: | { state: 'approved'; @@ -6015,8 +6049,8 @@ describe('TransactionController', () => { }); it('uses the nonceTracker for the networkClientId matching the chainId', async () => { - const { controller, messenger } = setupController(); - messenger.registerActionHandler( + const { controller, networkControllerMessenger } = setupController(); + networkControllerMessenger.registerActionHandler( 'NetworkController:findNetworkClientIdByChainId', () => 'sepolia', ); diff --git a/packages/transaction-controller/src/TransactionController.ts b/packages/transaction-controller/src/TransactionController.ts index e8f0f025820..f2f937dd3b6 100644 --- a/packages/transaction-controller/src/TransactionController.ts +++ b/packages/transaction-controller/src/TransactionController.ts @@ -11,9 +11,8 @@ import type { import type { ControllerGetStateAction, ControllerStateChangeEvent, - RestrictedMessenger, -} from '@metamask/base-controller'; -import { BaseController } from '@metamask/base-controller'; +} from '@metamask/base-controller/next'; +import { BaseController } from '@metamask/base-controller/next'; import { query, ApprovalType, @@ -27,6 +26,7 @@ import type { GasFeeState, } from '@metamask/gas-fee-controller'; import type { KeyringControllerSignEip7702AuthorizationAction } from '@metamask/keyring-controller'; +import type { Messenger } from '@metamask/messenger'; import type { BlockTracker, NetworkClientId, @@ -671,12 +671,10 @@ export type TransactionControllerEvents = /** * The messenger of the {@link TransactionController}. */ -export type TransactionControllerMessenger = RestrictedMessenger< +export type TransactionControllerMessenger = Messenger< typeof controllerName, TransactionControllerActions | AllowedActions, - TransactionControllerEvents | AllowedEvents, - AllowedActions['type'], - AllowedEvents['type'] + TransactionControllerEvents | AllowedEvents >; /** @@ -868,7 +866,7 @@ export class TransactionController extends BaseController< }, }); - this.messagingSystem = messenger; + this.messenger = messenger; this.#afterAdd = hooks?.afterAdd ?? (() => Promise.resolve({})); this.#afterSign = hooks?.afterSign ?? (() => true); @@ -916,7 +914,7 @@ export class TransactionController extends BaseController< this.#transactionHistoryLimit = transactionHistoryLimit; const findNetworkClientIdByChainId = (chainId: Hex) => { - return this.messagingSystem.call( + return this.messenger.call( `NetworkController:findNetworkClientIdByChainId`, chainId, ); @@ -925,7 +923,7 @@ export class TransactionController extends BaseController< this.#multichainTrackingHelper = new MultichainTrackingHelper({ findNetworkClientIdByChainId, getNetworkClientById: ((networkClientId: NetworkClientId) => { - return this.messagingSystem.call( + return this.messenger.call( `NetworkController:getNetworkClientById`, networkClientId, ); @@ -937,10 +935,7 @@ export class TransactionController extends BaseController< createPendingTransactionTracker: this.#createPendingTransactionTracker.bind(this), onNetworkStateChange: (listener) => { - this.messagingSystem.subscribe( - 'NetworkController:stateChange', - listener, - ); + this.messenger.subscribe('NetworkController:stateChange', listener); }, }); @@ -956,12 +951,9 @@ export class TransactionController extends BaseController< getTransactions: () => this.state.transactions, getTransactionBatches: () => this.state.transactionBatches, layer1GasFeeFlows: this.#layer1GasFeeFlows, - messenger: this.messagingSystem, + messenger: this.messenger, onStateChange: (listener) => { - this.messagingSystem.subscribe( - 'TransactionController:stateChange', - listener, - ); + this.messenger.subscribe('TransactionController:stateChange', listener); }, }); @@ -996,7 +988,7 @@ export class TransactionController extends BaseController< includeTokenTransfers: this.#incomingTransactionOptions.includeTokenTransfers, isEnabled: this.#incomingTransactionOptions.isEnabled, - messenger: this.messagingSystem, + messenger: this.messenger, remoteTransactionSource: new AccountsApiRemoteTransactionSource(), trimTransactions: this.#trimTransactionsForState.bind(this), updateTransactions: this.#incomingTransactionOptions.updateTransactions, @@ -1008,7 +1000,7 @@ export class TransactionController extends BaseController< // when transactionsController state changes // check for pending transactions and start polling if there are any - this.messagingSystem.subscribe( + this.messenger.subscribe( 'TransactionController:stateChange', this.#checkForPendingTransactionAndStartPolling, ); @@ -1016,7 +1008,7 @@ export class TransactionController extends BaseController< new ResimulateHelper({ simulateTransaction: this.#updateSimulationData.bind(this), onTransactionsUpdate: (listener) => { - this.messagingSystem.subscribe( + this.messenger.subscribe( 'TransactionController:stateChange', listener, (controllerState) => controllerState.transactions, @@ -1060,7 +1052,7 @@ export class TransactionController extends BaseController< async addTransactionBatch( request: TransactionBatchRequest, ): Promise { - const { blockTracker } = this.messagingSystem.call( + const { blockTracker } = this.messenger.call( `NetworkController:getNetworkClientById`, request.networkClientId, ); @@ -1082,7 +1074,7 @@ export class TransactionController extends BaseController< getTransaction: (transactionId) => this.#getTransactionOrThrow(transactionId), isSimulationEnabled: this.#isSimulationEnabled, - messenger: this.messagingSystem, + messenger: this.messenger, publishBatchHook: this.#publishBatchHook, publicKeyEIP7702: this.#publicKeyEIP7702, publishTransaction: ( @@ -1107,7 +1099,7 @@ export class TransactionController extends BaseController< return isAtomicBatchSupported({ ...request, getEthQuery: (chainId) => this.#getEthQuery({ chainId }), - messenger: this.messagingSystem, + messenger: this.messenger, publicKeyEIP7702: this.#publicKeyEIP7702, }); } @@ -1331,7 +1323,7 @@ export class TransactionController extends BaseController< { isSwapsDisabled: this.#isSwapsDisabled, cancelTransaction: this.#rejectTransaction.bind(this), - messenger: this.messagingSystem, + messenger: this.messenger, }, ); @@ -1356,7 +1348,7 @@ export class TransactionController extends BaseController< ); } - this.messagingSystem.publish( + this.messenger.publish( `${controllerName}:unapprovedTransactionAdded`, addedTransactionMeta, ); @@ -1424,7 +1416,7 @@ export class TransactionController extends BaseController< txParams.value = '0x0'; }, afterSubmit: (newTransactionMeta) => { - this.messagingSystem.publish( + this.messenger.publish( `${controllerName}:transactionFinished`, newTransactionMeta, ); @@ -1463,7 +1455,7 @@ export class TransactionController extends BaseController< transactionId, transactionType: TransactionType.retry, afterSubmit: (newTransactionMeta) => { - this.messagingSystem.publish( + this.messenger.publish( `${controllerName}:speedupTransactionAdded`, newTransactionMeta, ); @@ -1579,12 +1571,12 @@ export class TransactionController extends BaseController< this.#addMetadata(newTransactionMeta); // speedUpTransaction has no approval request, so we assume the user has already approved the transaction - this.messagingSystem.publish(`${controllerName}:transactionApproved`, { + this.messenger.publish(`${controllerName}:transactionApproved`, { transactionMeta: newTransactionMeta, actionId, }); - this.messagingSystem.publish(`${controllerName}:transactionSubmitted`, { + this.messenger.publish(`${controllerName}:transactionSubmitted`, { transactionMeta: newTransactionMeta, actionId, }); @@ -1620,7 +1612,7 @@ export class TransactionController extends BaseController< ignoreDelegationSignatures, isSimulationEnabled: this.#isSimulationEnabled(), getSimulationConfig: this.#getSimulationConfig, - messenger: this.messagingSystem, + messenger: this.messenger, txParams: transaction, }); @@ -1649,7 +1641,7 @@ export class TransactionController extends BaseController< ethQuery, isSimulationEnabled: this.#isSimulationEnabled(), getSimulationConfig: this.#getSimulationConfig, - messenger: this.messagingSystem, + messenger: this.messenger, txParams: transaction, }); @@ -1796,7 +1788,7 @@ export class TransactionController extends BaseController< throw error; }); - this.messagingSystem.publish( + this.messenger.publish( `${controllerName}:transactionConfirmed`, updatedTransactionMeta, ); @@ -2140,7 +2132,7 @@ export class TransactionController extends BaseController< await updateTransactionLayer1GasFee({ layer1GasFeeFlows: this.#layer1GasFeeFlows, - messenger: this.messagingSystem, + messenger: this.messenger, provider, transactionMeta: updatedTransaction, }); @@ -2334,7 +2326,7 @@ export class TransactionController extends BaseController< status as TransactionStatus, ) ) { - this.messagingSystem.publish( + this.messenger.publish( `${controllerName}:transactionFinished`, updatedTransactionMeta, ); @@ -2468,7 +2460,7 @@ export class TransactionController extends BaseController< const gasFeeFlow = getGasFeeFlow( transactionMeta, this.#gasFeeFlows, - this.messagingSystem, + this.messenger, ) as GasFeeFlow; const ethQuery = new EthQuery(provider); @@ -2480,7 +2472,7 @@ export class TransactionController extends BaseController< return gasFeeFlow.getGasFees({ ethQuery, gasFeeControllerData, - messenger: this.messagingSystem, + messenger: this.messenger, transactionMeta, }); } @@ -2510,7 +2502,7 @@ export class TransactionController extends BaseController< return await getTransactionLayer1GasFee({ layer1GasFeeFlows: this.#layer1GasFeeFlows, - messenger: this.messagingSystem, + messenger: this.messenger, provider, transactionMeta: { txParams: transactionParams, @@ -2786,7 +2778,7 @@ export class TransactionController extends BaseController< gasFeeFlows: this.#gasFeeFlows, getGasFeeEstimates: this.#getGasFeeEstimates, getSavedGasFees: this.#getSavedGasFees.bind(this), - messenger: this.messagingSystem, + messenger: this.messenger, txMeta: transactionMeta, }), ); @@ -2796,7 +2788,7 @@ export class TransactionController extends BaseController< async () => await updateTransactionLayer1GasFee({ layer1GasFeeFlows: this.#layer1GasFeeFlows, - messenger: this.messagingSystem, + messenger: this.messenger, provider, transactionMeta, }), @@ -2903,13 +2895,10 @@ export class TransactionController extends BaseController< const updatedTransactionMeta = this.#getTransaction( transactionId, ) as TransactionMeta; - this.messagingSystem.publish( - `${controllerName}:transactionApproved`, - { - transactionMeta: updatedTransactionMeta, - actionId, - }, - ); + this.messenger.publish(`${controllerName}:transactionApproved`, { + transactionMeta: updatedTransactionMeta, + actionId, + }); } } catch (rawError: unknown) { const error = rawError as Error & { code?: number; data?: Json }; @@ -3041,7 +3030,7 @@ export class TransactionController extends BaseController< if (!(await this.#beforePublish(transactionMeta))) { log('Skipping publishing transaction based on hook'); - this.messagingSystem.publish( + this.messenger.publish( `${controllerName}:transactionPublishingSkipped`, transactionMeta, ); @@ -3121,11 +3110,11 @@ export class TransactionController extends BaseController< }, ); - this.messagingSystem.publish(`${controllerName}:transactionSubmitted`, { + this.messenger.publish(`${controllerName}:transactionSubmitted`, { transactionMeta, }); - this.messagingSystem.publish( + this.messenger.publish( `${controllerName}:transactionFinished`, transactionMeta, ); @@ -3183,7 +3172,7 @@ export class TransactionController extends BaseController< error: normalizeTxError(error ?? providerErrors.userRejectedRequest()), }; - this.messagingSystem.publish( + this.messenger.publish( `${controllerName}:transactionFinished`, updatedTransactionMeta, ); @@ -3193,7 +3182,7 @@ export class TransactionController extends BaseController< updatedTransactionMeta, ); - this.messagingSystem.publish(`${controllerName}:transactionRejected`, { + this.messenger.publish(`${controllerName}:transactionRejected`, { transactionMeta: updatedTransactionMeta, actionId, }); @@ -3295,7 +3284,7 @@ export class TransactionController extends BaseController< parentContext: traceContext, }); - return (await this.messagingSystem.call( + return (await this.messenger.call( 'ApprovalController:addRequest', { id, @@ -3431,7 +3420,7 @@ export class TransactionController extends BaseController< ); }); - this.messagingSystem.publish( + this.messenger.publish( `${controllerName}:incomingTransactionsReceived`, finalTransactions, ); @@ -3580,7 +3569,7 @@ export class TransactionController extends BaseController< ...transactionMeta, status: TransactionStatus.dropped as const, }; - this.messagingSystem.publish(`${controllerName}:transactionDropped`, { + this.messenger.publish(`${controllerName}:transactionDropped`, { transactionMeta: updatedTransactionMeta, }); this.updateTransaction( @@ -3670,7 +3659,7 @@ export class TransactionController extends BaseController< const signedAuthorizationList = await signAuthorizationList({ authorizationList, - messenger: this.messagingSystem, + messenger: this.messenger, transactionMeta, }); @@ -3762,7 +3751,7 @@ export class TransactionController extends BaseController< } #onTransactionStatusChange(transactionMeta: TransactionMeta) { - this.messagingSystem.publish(`${controllerName}:transactionStatusUpdated`, { + this.messenger.publish(`${controllerName}:transactionStatusUpdated`, { transactionMeta, }); } @@ -3785,7 +3774,7 @@ export class TransactionController extends BaseController< this.#markNonceDuplicatesDropped(transactionMeta.id); - this.messagingSystem.publish( + this.messenger.publish( `${controllerName}:transactionConfirmed`, transactionMeta, ); @@ -3816,7 +3805,7 @@ export class TransactionController extends BaseController< updateTransaction: this.updateTransaction.bind(this), }); - this.messagingSystem.publish( + this.messenger.publish( `${controllerName}:postTransactionBalanceUpdated`, { transactionMeta: updatedTransactionMeta, @@ -3880,7 +3869,7 @@ export class TransactionController extends BaseController< this.#multichainTrackingHelper.acquireNonceLockForChainIdKey({ chainId, }), - messenger: this.messagingSystem, + messenger: this.messenger, publishTransaction: (_ethQuery, transactionMeta) => this.#publishTransaction(_ethQuery, transactionMeta, { skipSubmitHistory: true, @@ -4230,7 +4219,7 @@ export class TransactionController extends BaseController< chainId, getSimulationConfig: this.#getSimulationConfig, isEIP7702GasFeeTokensEnabled: this.#isEIP7702GasFeeTokensEnabled, - messenger: this.messagingSystem, + messenger: this.messenger, publicKeyEIP7702: this.#publicKeyEIP7702, transactionMeta, }); @@ -4328,11 +4317,11 @@ export class TransactionController extends BaseController< } #getSelectedAccount() { - return this.messagingSystem.call('AccountsController:getSelectedAccount'); + return this.messenger.call('AccountsController:getSelectedAccount'); } #getInternalAccounts(): Hex[] { - const state = this.messagingSystem.call('AccountsController:getState'); + const state = this.messenger.call('AccountsController:getState'); return Object.values(state.internalAccounts?.accounts ?? {}) .filter((account) => account.type === 'eip155:eoa') @@ -4392,18 +4381,18 @@ export class TransactionController extends BaseController< isCustomNetwork, isSimulationEnabled: this.#isSimulationEnabled(), getSimulationConfig: this.#getSimulationConfig, - messenger: this.messagingSystem, + messenger: this.messenger, txMeta: transactionMeta, }); } #registerActionHandlers(): void { - this.messagingSystem.registerActionHandler( + this.messenger.registerActionHandler( `${controllerName}:estimateGas`, this.estimateGas.bind(this), ); - this.messagingSystem.registerActionHandler( + this.messenger.registerActionHandler( `${controllerName}:updateCustodialTransaction`, this.updateCustodialTransaction.bind(this), ); @@ -4477,7 +4466,7 @@ export class TransactionController extends BaseController< }; } - this.messagingSystem.publish(`${controllerName}:transactionFailed`, { + this.messenger.publish(`${controllerName}:transactionFailed`, { actionId, error: error.message, transactionMeta: newTransactionMeta, @@ -4485,7 +4474,7 @@ export class TransactionController extends BaseController< this.#onTransactionStatusChange(newTransactionMeta); - this.messagingSystem.publish( + this.messenger.publish( `${controllerName}:transactionFinished`, newTransactionMeta, ); diff --git a/packages/transaction-controller/src/utils/eip7702.test.ts b/packages/transaction-controller/src/utils/eip7702.test.ts index 1b70fa09db1..af58b1ea7ad 100644 --- a/packages/transaction-controller/src/utils/eip7702.test.ts +++ b/packages/transaction-controller/src/utils/eip7702.test.ts @@ -1,5 +1,10 @@ import { query } from '@metamask/controller-utils'; import type EthQuery from '@metamask/eth-query'; +import { + Messenger, + MessengerActions, + MessengerEvents, +} from '@metamask/messenger'; import type { RemoteFeatureFlagControllerGetStateAction } from '@metamask/remote-feature-flag-controller'; import type { Hex } from '@metamask/utils'; import { remove0x } from '@metamask/utils'; @@ -16,7 +21,6 @@ import { getEIP7702ContractAddresses, getEIP7702SupportedChains, } from './feature-flags'; -import { Messenger } from '../../../base-controller/src'; import type { KeyringControllerSignEip7702AuthorizationAction } from '../../../keyring-controller/src'; import type { TransactionControllerMessenger } from '../TransactionController'; import type { AuthorizationList } from '../types'; @@ -73,10 +77,10 @@ const AUTHORIZATION_LIST_MOCK: AuthorizationList = [ ]; describe('EIP-7702 Utils', () => { - let baseMessenger: Messenger< - | KeyringControllerSignEip7702AuthorizationAction - | RemoteFeatureFlagControllerGetStateAction, - never + let rootMessenger: Messenger< + 'Root', + MessengerActions, + MessengerEvents >; const getCodeMock = jest.mocked(query); @@ -95,21 +99,33 @@ describe('EIP-7702 Utils', () => { beforeEach(() => { jest.resetAllMocks(); - baseMessenger = new Messenger(); + rootMessenger = new Messenger({ namespace: 'Root' }); signAuthorizationMock = jest .fn() .mockResolvedValue(AUTHORIZATION_SIGNATURE_MOCK); - baseMessenger.registerActionHandler( + const keyringControllerMessenger = new Messenger< + 'KeyringController', + KeyringControllerSignEip7702AuthorizationAction, + never, + typeof rootMessenger + >({ + namespace: 'KeyringController', + parent: rootMessenger, + }); + keyringControllerMessenger.registerActionHandler( 'KeyringController:signEip7702Authorization', signAuthorizationMock, ); - controllerMessenger = baseMessenger.getRestricted({ - name: 'TransactionController', - allowedActions: ['KeyringController:signEip7702Authorization'], - allowedEvents: [], + controllerMessenger = new Messenger({ + namespace: 'TransactionController', + parent: rootMessenger, + }); + rootMessenger.delegate({ + messenger: controllerMessenger, + actions: ['KeyringController:signEip7702Authorization'], }); }); diff --git a/packages/transaction-controller/src/utils/feature-flags.test.ts b/packages/transaction-controller/src/utils/feature-flags.test.ts index 84bc2e1922a..652d3ec168e 100644 --- a/packages/transaction-controller/src/utils/feature-flags.test.ts +++ b/packages/transaction-controller/src/utils/feature-flags.test.ts @@ -1,4 +1,8 @@ -import { Messenger } from '@metamask/base-controller'; +import { + Messenger, + type MessengerActions, + type MessengerEvents, +} from '@metamask/messenger'; import type { RemoteFeatureFlagControllerGetStateAction } from '@metamask/remote-feature-flag-controller'; import type { Hex } from '@metamask/utils'; @@ -36,13 +40,21 @@ const GAS_BUFFER_4_MOCK = 1.4; const GAS_BUFFER_5_MOCK = 1.5; describe('Feature Flags Utils', () => { - let baseMessenger: Messenger< - RemoteFeatureFlagControllerGetStateAction, - never + let rootMessenger: Messenger< + 'Root', + MessengerActions, + MessengerEvents >; let controllerMessenger: TransactionControllerMessenger; + let remoteFeatureFlagControllerMessenger: Messenger< + 'RemoteFeatureFlagController', + RemoteFeatureFlagControllerGetStateAction, + never, + typeof rootMessenger + >; + let getFeatureFlagsMock: jest.MockedFn< RemoteFeatureFlagControllerGetStateAction['handler'] >; @@ -66,17 +78,25 @@ describe('Feature Flags Utils', () => { getFeatureFlagsMock = jest.fn(); - baseMessenger = new Messenger(); + rootMessenger = new Messenger({ namespace: 'Root' }); + + remoteFeatureFlagControllerMessenger = new Messenger({ + namespace: 'RemoteFeatureFlagController', + parent: rootMessenger, + }); - baseMessenger.registerActionHandler( + remoteFeatureFlagControllerMessenger.registerActionHandler( 'RemoteFeatureFlagController:getState', getFeatureFlagsMock, ); - controllerMessenger = baseMessenger.getRestricted({ - name: 'TransactionController', - allowedActions: ['RemoteFeatureFlagController:getState'], - allowedEvents: [], + controllerMessenger = new Messenger({ + namespace: 'TransactionController', + parent: rootMessenger, + }); + rootMessenger.delegate({ + messenger: controllerMessenger, + actions: ['RemoteFeatureFlagController:getState'], }); isValidSignatureMock.mockReturnValue(true); diff --git a/packages/transaction-controller/src/utils/swaps.test.ts b/packages/transaction-controller/src/utils/swaps.test.ts index 457aa0134c9..9f74710da54 100644 --- a/packages/transaction-controller/src/utils/swaps.test.ts +++ b/packages/transaction-controller/src/utils/swaps.test.ts @@ -1,5 +1,9 @@ -import { Messenger } from '@metamask/base-controller'; import { query } from '@metamask/controller-utils'; +import { + Messenger, + type MessengerActions, + type MessengerEvents, +} from '@metamask/messenger'; import { updateSwapsTransaction, @@ -9,13 +13,7 @@ import { } from './swaps'; import { flushPromises } from '../../../../tests/helpers'; import { CHAIN_IDS } from '../constants'; -import type { - AllowedActions, - AllowedEvents, - TransactionControllerActions, - TransactionControllerEvents, - TransactionControllerMessenger, -} from '../TransactionController'; +import type { TransactionControllerMessenger } from '../TransactionController'; import type { TransactionMeta } from '../types'; import { TransactionType, TransactionStatus } from '../types'; @@ -47,17 +45,29 @@ describe('updateSwapsTransaction', () => { destinationTokenSymbol: 'DAI', }, }; + const rootMessenger = new Messenger< + 'Root', + MessengerActions, + MessengerEvents + >({ + namespace: 'Root', + }); messenger = new Messenger< - TransactionControllerActions | AllowedActions, - TransactionControllerEvents | AllowedEvents - >().getRestricted({ - name: 'TransactionController', - allowedActions: [ + 'TransactionController', + MessengerActions, + MessengerEvents, + typeof rootMessenger + >({ + namespace: 'TransactionController', + parent: rootMessenger, + }); + rootMessenger.delegate({ + messenger, + actions: [ 'ApprovalController:addRequest', 'NetworkController:getNetworkClientById', 'NetworkController:findNetworkClientIdByChainId', ], - allowedEvents: [], }); request = { isSwapsDisabled: false, diff --git a/yarn.lock b/yarn.lock index d2066afdb79..b2e49bbd25f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4687,6 +4687,7 @@ __metadata: "@metamask/eth-query": "npm:^4.0.0" "@metamask/ethjs-provider-http": "npm:^0.3.0" "@metamask/gas-fee-controller": "npm:^24.0.0" + "@metamask/messenger": "npm:^0.1.0" "@metamask/metamask-eth-abis": "npm:^3.1.1" "@metamask/network-controller": "npm:^24.1.0" "@metamask/nonce-tracker": "npm:^6.0.0" From 4941db574ca265b318385899e5dc11de3c3ae919 Mon Sep 17 00:00:00 2001 From: Michele Esposito Date: Thu, 28 Aug 2025 11:52:16 +0200 Subject: [PATCH 04/69] refactor: migrate `NetworkController` to `@metamask/messenger` --- packages/network-controller/package.json | 1 + .../src/NetworkController.ts | 75 ++++++++----------- ...create-auto-managed-network-client.test.ts | 48 ++++-------- .../tests/NetworkController.test.ts | 53 +++++++------ packages/network-controller/tests/helpers.ts | 73 ++++++++++++++---- yarn.lock | 1 + 6 files changed, 134 insertions(+), 117 deletions(-) diff --git a/packages/network-controller/package.json b/packages/network-controller/package.json index 9a4abda1c09..c2d2898102d 100644 --- a/packages/network-controller/package.json +++ b/packages/network-controller/package.json @@ -55,6 +55,7 @@ "@metamask/eth-json-rpc-provider": "^4.1.8", "@metamask/eth-query": "^4.0.0", "@metamask/json-rpc-engine": "^10.0.3", + "@metamask/messenger": "^0.1.0", "@metamask/rpc-errors": "^7.0.2", "@metamask/swappable-obj-proxy": "^2.3.0", "@metamask/utils": "^11.4.2", diff --git a/packages/network-controller/src/NetworkController.ts b/packages/network-controller/src/NetworkController.ts index ceaef81f810..c4f2fee4f01 100644 --- a/packages/network-controller/src/NetworkController.ts +++ b/packages/network-controller/src/NetworkController.ts @@ -1,9 +1,8 @@ import type { ControllerGetStateAction, ControllerStateChangeEvent, - RestrictedMessenger, -} from '@metamask/base-controller'; -import { BaseController } from '@metamask/base-controller'; +} from '@metamask/base-controller/next'; +import { BaseController } from '@metamask/base-controller/next'; import type { Partialize } from '@metamask/controller-utils'; import { InfuraNetworkType, @@ -20,6 +19,7 @@ import { import type { ErrorReportingServiceCaptureExceptionAction } from '@metamask/error-reporting-service'; import type { PollingBlockTrackerOptions } from '@metamask/eth-block-tracker'; import EthQuery from '@metamask/eth-query'; +import type { Messenger } from '@metamask/messenger'; import { errorCodes } from '@metamask/rpc-errors'; import { createEventEmitterProxy } from '@metamask/swappable-obj-proxy'; import type { SwappableProxy } from '@metamask/swappable-obj-proxy'; @@ -603,12 +603,10 @@ export type NetworkControllerActions = */ type AllowedActions = ErrorReportingServiceCaptureExceptionAction; -export type NetworkControllerMessenger = RestrictedMessenger< +export type NetworkControllerMessenger = Messenger< typeof controllerName, NetworkControllerActions | AllowedActions, - NetworkControllerEvents | AllowedEvents, - AllowedActions['type'], - AllowedEvents['type'] + NetworkControllerEvents | AllowedEvents >; /** @@ -1229,7 +1227,7 @@ export class NetworkController extends BaseController< this.state.networkConfigurationsByChainId, ); - this.messagingSystem.registerActionHandler( + this.messenger.registerActionHandler( // TODO: Either fix this lint violation or explain why it's necessary to ignore. // eslint-disable-next-line @typescript-eslint/restrict-template-expressions `${this.name}:getEthQuery`, @@ -1238,80 +1236,80 @@ export class NetworkController extends BaseController< }, ); - this.messagingSystem.registerActionHandler( + this.messenger.registerActionHandler( // TODO: Either fix this lint violation or explain why it's necessary to ignore. // eslint-disable-next-line @typescript-eslint/restrict-template-expressions `${this.name}:getNetworkClientById`, this.getNetworkClientById.bind(this), ); - this.messagingSystem.registerActionHandler( + this.messenger.registerActionHandler( // TODO: Either fix this lint violation or explain why it's necessary to ignore. // eslint-disable-next-line @typescript-eslint/restrict-template-expressions `${this.name}:getEIP1559Compatibility`, this.getEIP1559Compatibility.bind(this), ); - this.messagingSystem.registerActionHandler( + this.messenger.registerActionHandler( // TODO: Either fix this lint violation or explain why it's necessary to ignore. // eslint-disable-next-line @typescript-eslint/restrict-template-expressions `${this.name}:setActiveNetwork`, this.setActiveNetwork.bind(this), ); - this.messagingSystem.registerActionHandler( + this.messenger.registerActionHandler( // TODO: Either fix this lint violation or explain why it's necessary to ignore. // eslint-disable-next-line @typescript-eslint/restrict-template-expressions `${this.name}:setProviderType`, this.setProviderType.bind(this), ); - this.messagingSystem.registerActionHandler( + this.messenger.registerActionHandler( // TODO: Either fix this lint violation or explain why it's necessary to ignore. // eslint-disable-next-line @typescript-eslint/restrict-template-expressions `${this.name}:findNetworkClientIdByChainId`, this.findNetworkClientIdByChainId.bind(this), ); - this.messagingSystem.registerActionHandler( + this.messenger.registerActionHandler( // TODO: Either fix this lint violation or explain why it's necessary to ignore. // eslint-disable-next-line @typescript-eslint/restrict-template-expressions `${this.name}:getNetworkConfigurationByChainId`, this.getNetworkConfigurationByChainId.bind(this), ); - this.messagingSystem.registerActionHandler( + this.messenger.registerActionHandler( // ESLint is mistaken here; `name` is a string. // eslint-disable-next-line @typescript-eslint/restrict-template-expressions `${this.name}:getNetworkConfigurationByNetworkClientId`, this.getNetworkConfigurationByNetworkClientId.bind(this), ); - this.messagingSystem.registerActionHandler( + this.messenger.registerActionHandler( `${this.name}:getSelectedNetworkClient`, this.getSelectedNetworkClient.bind(this), ); - this.messagingSystem.registerActionHandler( + this.messenger.registerActionHandler( `${this.name}:getSelectedChainId`, this.getSelectedChainId.bind(this), ); - this.messagingSystem.registerActionHandler( + this.messenger.registerActionHandler( // ESLint is mistaken here; `name` is a string. // eslint-disable-next-line @typescript-eslint/restrict-template-expressions `${this.name}:addNetwork`, this.addNetwork.bind(this), ); - this.messagingSystem.registerActionHandler( + this.messenger.registerActionHandler( // ESLint is mistaken here; `name` is a string. // eslint-disable-next-line @typescript-eslint/restrict-template-expressions `${this.name}:removeNetwork`, this.removeNetwork.bind(this), ); - this.messagingSystem.registerActionHandler( + this.messenger.registerActionHandler( // ESLint is mistaken here; `name` is a string. // eslint-disable-next-line @typescript-eslint/restrict-template-expressions `${this.name}:updateNetwork`, @@ -1535,15 +1533,9 @@ export class NetworkController extends BaseController< updateState?: (state: Draft) => void; } = {}, ) { - this.messagingSystem.publish( - 'NetworkController:networkWillChange', - this.state, - ); + this.messenger.publish('NetworkController:networkWillChange', this.state); this.#applyNetworkSelection(networkClientId, options); - this.messagingSystem.publish( - 'NetworkController:networkDidChange', - this.state, - ); + this.messenger.publish('NetworkController:networkDidChange', this.state); await this.lookupNetwork(); } @@ -1681,7 +1673,7 @@ export class NetworkController extends BaseController< const listener = () => { networkChanged = true; try { - this.messagingSystem.unsubscribe( + this.messenger.unsubscribe( 'NetworkController:networkDidChange', listener, ); @@ -1705,10 +1697,7 @@ export class NetworkController extends BaseController< } } }; - this.messagingSystem.subscribe( - 'NetworkController:networkDidChange', - listener, - ); + this.messenger.subscribe('NetworkController:networkDidChange', listener); let updatedNetworkStatus: NetworkStatus; let updatedIsEIP1559Compatible: boolean | undefined; @@ -1772,7 +1761,7 @@ export class NetworkController extends BaseController< } try { - this.messagingSystem.unsubscribe( + this.messenger.unsubscribe( 'NetworkController:networkDidChange', listener, ); @@ -1798,15 +1787,15 @@ export class NetworkController extends BaseController< if (isInfura) { if (updatedNetworkStatus === NetworkStatus.Available) { - this.messagingSystem.publish('NetworkController:infuraIsUnblocked'); + this.messenger.publish('NetworkController:infuraIsUnblocked'); } else if (updatedNetworkStatus === NetworkStatus.Blocked) { - this.messagingSystem.publish('NetworkController:infuraIsBlocked'); + this.messenger.publish('NetworkController:infuraIsBlocked'); } } else { // Always publish infuraIsUnblocked regardless of network status to // prevent consumers from being stuck in a blocked state if they were // previously connected to an Infura network that was blocked - this.messagingSystem.publish('NetworkController:infuraIsUnblocked'); + this.messenger.publish('NetworkController:infuraIsUnblocked'); } } @@ -2047,7 +2036,7 @@ export class NetworkController extends BaseController< }); }); - this.messagingSystem.publish( + this.messenger.publish( `${controllerName}:networkAdded`, newNetworkConfiguration, ); @@ -2384,7 +2373,7 @@ export class NetworkController extends BaseController< }); }); - this.messagingSystem.publish( + this.messenger.publish( 'NetworkController:networkRemoved', existingNetworkConfiguration, ); @@ -2788,7 +2777,7 @@ export class NetworkController extends BaseController< }, getRpcServiceOptions: this.#getRpcServiceOptions, getBlockTrackerOptions: this.#getBlockTrackerOptions, - messenger: this.messagingSystem, + messenger: this.messenger, isRpcFailoverEnabled: this.#isRpcFailoverEnabled, }); } else { @@ -2804,7 +2793,7 @@ export class NetworkController extends BaseController< }, getRpcServiceOptions: this.#getRpcServiceOptions, getBlockTrackerOptions: this.#getBlockTrackerOptions, - messenger: this.messagingSystem, + messenger: this.messenger, isRpcFailoverEnabled: this.#isRpcFailoverEnabled, }); } @@ -2966,7 +2955,7 @@ export class NetworkController extends BaseController< }, getRpcServiceOptions: this.#getRpcServiceOptions, getBlockTrackerOptions: this.#getBlockTrackerOptions, - messenger: this.messagingSystem, + messenger: this.messenger, isRpcFailoverEnabled: this.#isRpcFailoverEnabled, }), ] as const; @@ -2983,7 +2972,7 @@ export class NetworkController extends BaseController< }, getRpcServiceOptions: this.#getRpcServiceOptions, getBlockTrackerOptions: this.#getBlockTrackerOptions, - messenger: this.messagingSystem, + messenger: this.messenger, isRpcFailoverEnabled: this.#isRpcFailoverEnabled, }), ] as const; diff --git a/packages/network-controller/src/create-auto-managed-network-client.test.ts b/packages/network-controller/src/create-auto-managed-network-client.test.ts index 662b0f1a7df..bf555303429 100644 --- a/packages/network-controller/src/create-auto-managed-network-client.test.ts +++ b/packages/network-controller/src/create-auto-managed-network-client.test.ts @@ -1,18 +1,14 @@ -import { Messenger } from '@metamask/base-controller'; import { BUILT_IN_NETWORKS, NetworkType } from '@metamask/controller-utils'; import { createAutoManagedNetworkClient } from './create-auto-managed-network-client'; import * as createNetworkClientModule from './create-network-client'; -import type { - NetworkControllerActions, - NetworkControllerEvents, -} from './NetworkController'; import type { CustomNetworkClientConfiguration, InfuraNetworkClientConfiguration, } from './types'; import { NetworkClientType } from './types'; import { mockNetwork } from '../../../tests/mock-network'; +import { buildNetworkControllerMessenger } from '../tests/helpers'; describe('createAutoManagedNetworkClient', () => { const networkClientConfigurations: [ @@ -44,7 +40,7 @@ describe('createAutoManagedNetworkClient', () => { fetch, btoa, }), - messenger: getNetworkControllerMessenger(), + messenger: buildNetworkControllerMessenger(), isRpcFailoverEnabled: false, }); @@ -60,7 +56,7 @@ describe('createAutoManagedNetworkClient', () => { fetch, btoa, }), - messenger: getNetworkControllerMessenger(), + messenger: buildNetworkControllerMessenger(), isRpcFailoverEnabled: false, }); }).not.toThrow(); @@ -73,7 +69,7 @@ describe('createAutoManagedNetworkClient', () => { fetch, btoa, }), - messenger: getNetworkControllerMessenger(), + messenger: buildNetworkControllerMessenger(), isRpcFailoverEnabled: false, }); @@ -121,7 +117,7 @@ describe('createAutoManagedNetworkClient', () => { fetch, btoa, }), - messenger: getNetworkControllerMessenger(), + messenger: buildNetworkControllerMessenger(), isRpcFailoverEnabled: false, }); @@ -161,7 +157,7 @@ describe('createAutoManagedNetworkClient', () => { const getBlockTrackerOptions = () => ({ pollingInterval: 5000, }); - const messenger = getNetworkControllerMessenger(); + const messenger = buildNetworkControllerMessenger(); const { provider } = createAutoManagedNetworkClient({ networkClientConfiguration, @@ -220,7 +216,7 @@ describe('createAutoManagedNetworkClient', () => { const getBlockTrackerOptions = () => ({ pollingInterval: 5000, }); - const messenger = getNetworkControllerMessenger(); + const messenger = buildNetworkControllerMessenger(); const autoManagedNetworkClient = createAutoManagedNetworkClient({ networkClientConfiguration, @@ -288,7 +284,7 @@ describe('createAutoManagedNetworkClient', () => { const getBlockTrackerOptions = () => ({ pollingInterval: 5000, }); - const messenger = getNetworkControllerMessenger(); + const messenger = buildNetworkControllerMessenger(); const autoManagedNetworkClient = createAutoManagedNetworkClient({ networkClientConfiguration, @@ -337,7 +333,7 @@ describe('createAutoManagedNetworkClient', () => { fetch, btoa, }), - messenger: getNetworkControllerMessenger(), + messenger: buildNetworkControllerMessenger(), isRpcFailoverEnabled: false, }); @@ -396,7 +392,7 @@ describe('createAutoManagedNetworkClient', () => { fetch, btoa, }), - messenger: getNetworkControllerMessenger(), + messenger: buildNetworkControllerMessenger(), isRpcFailoverEnabled: false, }); @@ -457,7 +453,7 @@ describe('createAutoManagedNetworkClient', () => { const getBlockTrackerOptions = () => ({ pollingInterval: 5000, }); - const messenger = getNetworkControllerMessenger(); + const messenger = buildNetworkControllerMessenger(); const { blockTracker } = createAutoManagedNetworkClient({ networkClientConfiguration, @@ -512,7 +508,7 @@ describe('createAutoManagedNetworkClient', () => { const getBlockTrackerOptions = () => ({ pollingInterval: 5000, }); - const messenger = getNetworkControllerMessenger(); + const messenger = buildNetworkControllerMessenger(); const autoManagedNetworkClient = createAutoManagedNetworkClient({ networkClientConfiguration, @@ -574,7 +570,7 @@ describe('createAutoManagedNetworkClient', () => { const getBlockTrackerOptions = () => ({ pollingInterval: 5000, }); - const messenger = getNetworkControllerMessenger(); + const messenger = buildNetworkControllerMessenger(); const autoManagedNetworkClient = createAutoManagedNetworkClient({ networkClientConfiguration, @@ -632,7 +628,7 @@ describe('createAutoManagedNetworkClient', () => { fetch, btoa, }), - messenger: getNetworkControllerMessenger(), + messenger: buildNetworkControllerMessenger(), isRpcFailoverEnabled: false, }); // Start the block tracker @@ -646,19 +642,3 @@ describe('createAutoManagedNetworkClient', () => { }); } }); - -/** - * Constructs a NetworkController messenger. - * - * @returns The NetworkController messenger. - */ -function getNetworkControllerMessenger() { - return new Messenger< - NetworkControllerActions, - NetworkControllerEvents - >().getRestricted({ - name: 'NetworkController', - allowedActions: [], - allowedEvents: [], - }); -} diff --git a/packages/network-controller/tests/NetworkController.test.ts b/packages/network-controller/tests/NetworkController.test.ts index 784b6ab79cd..7981931fcb4 100644 --- a/packages/network-controller/tests/NetworkController.test.ts +++ b/packages/network-controller/tests/NetworkController.test.ts @@ -26,6 +26,7 @@ import { buildCustomNetworkClientConfiguration, buildCustomNetworkConfiguration, buildCustomRpcEndpoint, + buildErrorReportingServiceMessenger, buildInfuraNetworkClientConfiguration, buildInfuraNetworkConfiguration, buildInfuraRpcEndpoint, @@ -165,11 +166,11 @@ describe('NetworkController', () => { describe('constructor', () => { it('throws given an empty networkConfigurationsByChainId collection', () => { const messenger = buildRootMessenger(); - const restrictedMessenger = buildNetworkControllerMessenger(messenger); + const controllerMessenger = buildNetworkControllerMessenger(messenger); expect( () => new NetworkController({ - messenger: restrictedMessenger, + messenger: controllerMessenger, state: { networkConfigurationsByChainId: {}, }, @@ -186,11 +187,11 @@ describe('NetworkController', () => { it('throws if the key under which a network configuration is filed does not match the chain ID of that network configuration', () => { const messenger = buildRootMessenger(); - const restrictedMessenger = buildNetworkControllerMessenger(messenger); + const controllerMessenger = buildNetworkControllerMessenger(messenger); expect( () => new NetworkController({ - messenger: restrictedMessenger, + messenger: controllerMessenger, state: { networkConfigurationsByChainId: { '0x1337': buildCustomNetworkConfiguration({ @@ -212,11 +213,11 @@ describe('NetworkController', () => { it('throws if a network configuration has a defaultBlockExplorerUrlIndex that does not refer to an entry in blockExplorerUrls', () => { const messenger = buildRootMessenger(); - const restrictedMessenger = buildNetworkControllerMessenger(messenger); + const controllerMessenger = buildNetworkControllerMessenger(messenger); expect( () => new NetworkController({ - messenger: restrictedMessenger, + messenger: controllerMessenger, state: { networkConfigurationsByChainId: { '0x1337': buildCustomNetworkConfiguration({ @@ -245,11 +246,11 @@ describe('NetworkController', () => { it('throws if a network configuration has a non-empty blockExplorerUrls but an absent defaultBlockExplorerUrlIndex', () => { const messenger = buildRootMessenger(); - const restrictedMessenger = buildNetworkControllerMessenger(messenger); + const controllerMessenger = buildNetworkControllerMessenger(messenger); expect( () => new NetworkController({ - messenger: restrictedMessenger, + messenger: controllerMessenger, state: { networkConfigurationsByChainId: { '0x1337': buildCustomNetworkConfiguration({ @@ -277,11 +278,11 @@ describe('NetworkController', () => { it('throws if a network configuration has an invalid defaultRpcEndpointIndex', () => { const messenger = buildRootMessenger(); - const restrictedMessenger = buildNetworkControllerMessenger(messenger); + const controllerMessenger = buildNetworkControllerMessenger(messenger); expect( () => new NetworkController({ - messenger: restrictedMessenger, + messenger: controllerMessenger, state: { networkConfigurationsByChainId: { '0x1337': buildCustomNetworkConfiguration({ @@ -309,11 +310,11 @@ describe('NetworkController', () => { it('throws if more than one RPC endpoint across network configurations has the same networkClientId', () => { const messenger = buildRootMessenger(); - const restrictedMessenger = buildNetworkControllerMessenger(messenger); + const controllerMessenger = buildNetworkControllerMessenger(messenger); expect( () => new NetworkController({ - messenger: restrictedMessenger, + messenger: controllerMessenger, state: { networkConfigurationsByChainId: { '0x1337': buildCustomNetworkConfiguration({ @@ -352,13 +353,15 @@ describe('NetworkController', () => { describe('if selectedNetworkClientId does not match the networkClientId of an RPC endpoint in networkConfigurationsByChainId', () => { it('corrects selectedNetworkClientId to the default RPC endpoint of the first chain', () => { const messenger = buildRootMessenger(); - messenger.registerActionHandler( + const errorReportingServiceMessenger = + buildErrorReportingServiceMessenger(messenger); + errorReportingServiceMessenger.registerActionHandler( 'ErrorReportingService:captureException', jest.fn(), ); - const restrictedMessenger = buildNetworkControllerMessenger(messenger); + const controllerMessenger = buildNetworkControllerMessenger(messenger); const controller = new NetworkController({ - messenger: restrictedMessenger, + messenger: controllerMessenger, state: { selectedNetworkClientId: 'nonexistent', networkConfigurationsByChainId: { @@ -392,15 +395,17 @@ describe('NetworkController', () => { it('logs a Sentry error', () => { const messenger = buildRootMessenger(); + const errorReportingServiceMessenger = + buildErrorReportingServiceMessenger(messenger); const captureExceptionMock = jest.fn(); - messenger.registerActionHandler( + errorReportingServiceMessenger.registerActionHandler( 'ErrorReportingService:captureException', captureExceptionMock, ); - const restrictedMessenger = buildNetworkControllerMessenger(messenger); + const controllerMessenger = buildNetworkControllerMessenger(messenger); new NetworkController({ - messenger: restrictedMessenger, + messenger: controllerMessenger, state: { selectedNetworkClientId: 'nonexistent', networkConfigurationsByChainId: { @@ -441,11 +446,11 @@ describe('NetworkController', () => { invalidProjectId, )}"`, () => { const messenger = buildRootMessenger(); - const restrictedMessenger = buildNetworkControllerMessenger(messenger); + const controllerMessenger = buildNetworkControllerMessenger(messenger); expect( () => new NetworkController({ - messenger: restrictedMessenger, + messenger: controllerMessenger, state: {}, // @ts-expect-error We are intentionally passing bad input. infuraProjectId: invalidProjectId, @@ -2127,7 +2132,7 @@ describe('NetworkController', () => { }, infuraProjectId, }, - async ({ controller, messenger }) => { + async ({ controller, networkControllerMessenger }) => { const fakeProvider = buildFakeProvider([ // Called during provider initialization { @@ -2151,7 +2156,7 @@ describe('NetworkController', () => { const lookupNetworkPromise = controller.lookupNetwork(); const error = new Error('oops'); jest - .spyOn(messenger, 'unsubscribe') + .spyOn(networkControllerMessenger, 'unsubscribe') .mockImplementation((eventType) => { // This is okay. // eslint-disable-next-line jest/no-conditional-in-test @@ -2539,7 +2544,7 @@ describe('NetworkController', () => { }, infuraProjectId, }, - async ({ controller, messenger }) => { + async ({ controller, networkControllerMessenger }) => { const fakeProvider = buildFakeProvider([ // Called during provider initialization { @@ -2563,7 +2568,7 @@ describe('NetworkController', () => { const lookupNetworkPromise = controller.lookupNetwork(); const error = new Error('oops'); jest - .spyOn(messenger, 'unsubscribe') + .spyOn(networkControllerMessenger, 'unsubscribe') .mockImplementation((eventType) => { // This is okay. // eslint-disable-next-line jest/no-conditional-in-test diff --git a/packages/network-controller/tests/helpers.ts b/packages/network-controller/tests/helpers.ts index 77d6100549b..1a509bd1fb8 100644 --- a/packages/network-controller/tests/helpers.ts +++ b/packages/network-controller/tests/helpers.ts @@ -1,4 +1,3 @@ -import { Messenger } from '@metamask/base-controller'; import { ChainId, InfuraNetworkType, @@ -6,6 +5,11 @@ import { NetworksTicker, toHex, } from '@metamask/controller-utils'; +import { + Messenger, + type MessengerActions, + type MessengerEvents, +} from '@metamask/messenger'; import type { Hex } from '@metamask/utils'; import { v4 as uuidV4 } from 'uuid'; @@ -13,10 +17,6 @@ import { FakeBlockTracker } from '../../../tests/fake-block-tracker'; import { FakeProvider } from '../../../tests/fake-provider'; import type { FakeProviderStub } from '../../../tests/fake-provider'; import { buildTestObject } from '../../../tests/helpers'; -import type { - ExtractAvailableAction, - ExtractAvailableEvent, -} from '../../base-controller/tests/helpers'; import { type BuiltInNetworkClientId, type CustomNetworkClientId, @@ -42,9 +42,16 @@ import type { } from '../src/types'; import { NetworkClientType } from '../src/types'; +export type AllNetworkControllerActions = + MessengerActions; + +export type AllNetworkControllerEvents = + MessengerEvents; + export type RootMessenger = Messenger< - ExtractAvailableAction, - ExtractAvailableEvent + 'Root', + AllNetworkControllerActions, + AllNetworkControllerEvents >; /** @@ -76,22 +83,56 @@ export const TESTNET = { * @returns The messenger. */ export function buildRootMessenger(): RootMessenger { - return new Messenger(); + return new Messenger({ namespace: 'Root' }); } /** - * Build a restricted messenger for the network controller. + * Build a messenger for the network controller. * - * @param messenger - A messenger. - * @returns The network controller restricted messenger. + * @param rootMessenger - The root messenger. + * @returns The network controller messenger. */ export function buildNetworkControllerMessenger( - messenger = buildRootMessenger(), + rootMessenger = buildRootMessenger(), ): NetworkControllerMessenger { - return messenger.getRestricted({ - name: 'NetworkController', - allowedActions: ['ErrorReportingService:captureException'], - allowedEvents: [], + const networkControllerMessenger = new Messenger< + 'NetworkController', + AllNetworkControllerActions, + AllNetworkControllerEvents, + typeof rootMessenger + >({ + namespace: 'NetworkController', + parent: rootMessenger, + }); + rootMessenger.delegate({ + messenger: networkControllerMessenger, + actions: ['ErrorReportingService:captureException'], + }); + return networkControllerMessenger; +} + +/** + * Build a messenger for the error reporting service. + * + * @param rootMessenger - The root messenger. + * @returns The error reporting service messenger. + */ +export function buildErrorReportingServiceMessenger( + rootMessenger = buildRootMessenger(), +): Messenger< + 'ErrorReportingService', + AllNetworkControllerActions, + AllNetworkControllerEvents, + typeof rootMessenger +> { + return new Messenger< + 'ErrorReportingService', + AllNetworkControllerActions, + AllNetworkControllerEvents, + typeof rootMessenger + >({ + namespace: 'ErrorReportingService', + parent: rootMessenger, }); } diff --git a/yarn.lock b/yarn.lock index b2e49bbd25f..411ab461a55 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3951,6 +3951,7 @@ __metadata: "@metamask/eth-json-rpc-provider": "npm:^4.1.8" "@metamask/eth-query": "npm:^4.0.0" "@metamask/json-rpc-engine": "npm:^10.0.3" + "@metamask/messenger": "npm:^0.1.0" "@metamask/rpc-errors": "npm:^7.0.2" "@metamask/swappable-obj-proxy": "npm:^2.3.0" "@metamask/utils": "npm:^11.4.2" From 373c5c4f664078188a49833deeb66b00596a124d Mon Sep 17 00:00:00 2001 From: Michele Esposito Date: Thu, 28 Aug 2025 12:15:49 +0200 Subject: [PATCH 05/69] migrate `TransactionControllerIntegration.test.ts` --- .../TransactionControllerIntegration.test.ts | 110 +++++++++++++----- 1 file changed, 80 insertions(+), 30 deletions(-) diff --git a/packages/transaction-controller/src/TransactionControllerIntegration.test.ts b/packages/transaction-controller/src/TransactionControllerIntegration.test.ts index 3539d6b7982..d49269aff3f 100644 --- a/packages/transaction-controller/src/TransactionControllerIntegration.test.ts +++ b/packages/transaction-controller/src/TransactionControllerIntegration.test.ts @@ -5,7 +5,6 @@ import type { ApprovalControllerEvents, } from '@metamask/approval-controller'; import { ApprovalController } from '@metamask/approval-controller'; -import { Messenger } from '@metamask/base-controller'; import { ApprovalType, BUILT_IN_NETWORKS, @@ -13,6 +12,11 @@ import { InfuraNetworkType, NetworkType, } from '@metamask/controller-utils'; +import { + Messenger, + type MessengerActions, + type MessengerEvents, +} from '@metamask/messenger'; import { NetworkController, NetworkClientType, @@ -29,8 +33,7 @@ import { useFakeTimers } from 'sinon'; import { v4 as uuidV4 } from 'uuid'; import type { - TransactionControllerActions, - TransactionControllerEvents, + TransactionControllerMessenger, TransactionControllerOptions, } from './TransactionController'; import { TransactionController } from './TransactionController'; @@ -65,16 +68,25 @@ jest.mock('uuid', () => { }; }); -type UnrestrictedMessenger = Messenger< - | AccountsControllerActions - | ApprovalControllerActions +type AllTransactionControllerActions = + MessengerActions; + +type AllTransactionControllerEvents = + MessengerEvents; + +type AllActions = + | AllTransactionControllerActions | NetworkControllerActions - | TransactionControllerActions - | RemoteFeatureFlagControllerGetStateAction, - | ApprovalControllerEvents + | ApprovalControllerActions + | AccountsControllerActions + | RemoteFeatureFlagControllerGetStateAction; + +type AllEvents = + | AllTransactionControllerEvents | NetworkControllerEvents - | TransactionControllerEvents ->; + | ApprovalControllerEvents; + +type RootMessenger = Messenger<'Root', AllActions, AllEvents>; const uuidV4Mock = jest.mocked(uuidV4); @@ -158,13 +170,19 @@ const setupController = async ( ], }); - const unrestrictedMessenger: UnrestrictedMessenger = new Messenger(); + const rootMessenger: RootMessenger = new Messenger({ namespace: 'Root' }); + + const networkControllerMessenger = new Messenger< + 'NetworkController', + NetworkControllerActions, + NetworkControllerEvents, + typeof rootMessenger + >({ + namespace: 'NetworkController', + parent: rootMessenger, + }); const networkController = new NetworkController({ - messenger: unrestrictedMessenger.getRestricted({ - name: 'NetworkController', - allowedActions: [], - allowedEvents: [], - }), + messenger: networkControllerMessenger, infuraProjectId, getRpcServiceOptions: () => ({ fetch, @@ -177,19 +195,33 @@ const setupController = async ( assert(provider, 'Provider must be available'); assert(blockTracker, 'Provider must be available'); + const approvalControllerMessenger = new Messenger< + 'ApprovalController', + ApprovalControllerActions, + ApprovalControllerEvents, + typeof rootMessenger + >({ + namespace: 'ApprovalController', + parent: rootMessenger, + }); const approvalController = new ApprovalController({ - messenger: unrestrictedMessenger.getRestricted({ - name: 'ApprovalController', - allowedActions: [], - allowedEvents: [], - }), + messenger: approvalControllerMessenger, showApprovalRequest: jest.fn(), typesExcludedFromRateLimiting: [ApprovalType.Transaction], }); - const messenger = unrestrictedMessenger.getRestricted({ - name: 'TransactionController', - allowedActions: [ + const messenger = new Messenger< + 'TransactionController', + MessengerActions, + MessengerEvents, + typeof rootMessenger + >({ + namespace: 'TransactionController', + parent: rootMessenger, + }); + rootMessenger.delegate({ + messenger, + actions: [ 'AccountsController:getSelectedAccount', 'AccountsController:getState', 'ApprovalController:addRequest', @@ -197,24 +229,42 @@ const setupController = async ( 'NetworkController:findNetworkClientIdByChainId', 'RemoteFeatureFlagController:getState', ], - allowedEvents: ['NetworkController:stateChange'], + events: ['NetworkController:stateChange'], }); const mockGetSelectedAccount = jest .fn() .mockReturnValue(mockData.selectedAccount); - unrestrictedMessenger.registerActionHandler( + const accountsControllerMessenger = new Messenger< + 'AccountsController', + AccountsControllerActions, + never, + typeof rootMessenger + >({ + namespace: 'AccountsController', + parent: rootMessenger, + }); + accountsControllerMessenger.registerActionHandler( 'AccountsController:getSelectedAccount', mockGetSelectedAccount, ); - - unrestrictedMessenger.registerActionHandler( + accountsControllerMessenger.registerActionHandler( 'AccountsController:getState', () => ({}) as never, ); - unrestrictedMessenger.registerActionHandler( + const remoteFeatureFlagControllerMessenger = new Messenger< + 'RemoteFeatureFlagController', + RemoteFeatureFlagControllerGetStateAction, + never, + typeof rootMessenger + >({ + namespace: 'RemoteFeatureFlagController', + parent: rootMessenger, + }); + + remoteFeatureFlagControllerMessenger.registerActionHandler( 'RemoteFeatureFlagController:getState', () => ({ cacheTimestamp: 0, remoteFeatureFlags: {} }), ); From 38eb76d884636488d50cbb1e22022e4073811eec Mon Sep 17 00:00:00 2001 From: Michele Esposito Date: Thu, 28 Aug 2025 12:18:54 +0200 Subject: [PATCH 06/69] update changelogs --- packages/network-controller/CHANGELOG.md | 2 ++ packages/transaction-controller/CHANGELOG.md | 5 +++++ 2 files changed, 7 insertions(+) diff --git a/packages/network-controller/CHANGELOG.md b/packages/network-controller/CHANGELOG.md index a27b90aa487..8db1b2cfad0 100644 --- a/packages/network-controller/CHANGELOG.md +++ b/packages/network-controller/CHANGELOG.md @@ -9,6 +9,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed +- **BREAKING:** Use new `Messenger` from `@metamask/messenger` ([#6386](https://github.com/MetaMask/core/pull/6386)) + - Previously, `NetworkController` accepted a `RestrictedMessenger` instance from `@metamask/base-controller`. - Bump `@metamask/base-controller` from `^8.1.0` to `^8.2.0` ([#6355](https://github.com/MetaMask/core/pull/6355)) ### Deprecated diff --git a/packages/transaction-controller/CHANGELOG.md b/packages/transaction-controller/CHANGELOG.md index 8aa9728f041..78871994f54 100644 --- a/packages/transaction-controller/CHANGELOG.md +++ b/packages/transaction-controller/CHANGELOG.md @@ -7,6 +7,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Changed + +- **BREAKING:** Use new `Messenger` from `@metamask/messenger` ([#6386](https://github.com/MetaMask/core/pull/6386)) + - Previously, `TransactionController` accepted a `RestrictedMessenger` instance from `@metamask/base-controller`. + ## [60.1.0] ### Added From 5f3e1f3bbaf7d91ec6456bbbb315d7950fecba9f Mon Sep 17 00:00:00 2001 From: Michele Esposito Date: Thu, 28 Aug 2025 13:47:07 +0200 Subject: [PATCH 07/69] fix lint --- packages/approval-controller/src/ApprovalController.test.ts | 4 ++-- packages/transaction-controller/src/utils/eip7702.test.ts | 5 ++--- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/packages/approval-controller/src/ApprovalController.test.ts b/packages/approval-controller/src/ApprovalController.test.ts index c9ca5253d3f..1f068825377 100644 --- a/packages/approval-controller/src/ApprovalController.test.ts +++ b/packages/approval-controller/src/ApprovalController.test.ts @@ -236,12 +236,12 @@ function getMessengers() { return { rootMessenger, approvalControllerMessenger: new Messenger< - 'ApprovalController', + typeof controllerName, ApprovalControllerActions, ApprovalControllerEvents, typeof rootMessenger >({ - namespace: 'ApprovalController', + namespace: controllerName, parent: rootMessenger, }), }; diff --git a/packages/transaction-controller/src/utils/eip7702.test.ts b/packages/transaction-controller/src/utils/eip7702.test.ts index af58b1ea7ad..82be470ca94 100644 --- a/packages/transaction-controller/src/utils/eip7702.test.ts +++ b/packages/transaction-controller/src/utils/eip7702.test.ts @@ -2,10 +2,9 @@ import { query } from '@metamask/controller-utils'; import type EthQuery from '@metamask/eth-query'; import { Messenger, - MessengerActions, - MessengerEvents, + type MessengerActions, + type MessengerEvents, } from '@metamask/messenger'; -import type { RemoteFeatureFlagControllerGetStateAction } from '@metamask/remote-feature-flag-controller'; import type { Hex } from '@metamask/utils'; import { remove0x } from '@metamask/utils'; From f482a843f7250a8f873d3ccefd0a8b855e43d2d2 Mon Sep 17 00:00:00 2001 From: Michele Esposito Date: Wed, 3 Sep 2025 15:06:18 +0200 Subject: [PATCH 08/69] refactor: migrate `gas-fee-controller` to `@metamask/messenger` --- .../src/GasFeeController.test.ts | 81 ++++++++++++------- .../src/GasFeeController.ts | 26 +++--- .../src/StaticIntervalPollingController.ts | 8 ++ packages/polling-controller/src/index.ts | 1 + 4 files changed, 71 insertions(+), 45 deletions(-) diff --git a/packages/gas-fee-controller/src/GasFeeController.test.ts b/packages/gas-fee-controller/src/GasFeeController.test.ts index 53b1f821e82..1283549f0a5 100644 --- a/packages/gas-fee-controller/src/GasFeeController.test.ts +++ b/packages/gas-fee-controller/src/GasFeeController.test.ts @@ -1,16 +1,19 @@ -import { Messenger } from '@metamask/base-controller'; import { ChainId, convertHexToDecimal, toHex, } from '@metamask/controller-utils'; import EthQuery from '@metamask/eth-query'; +import { + Messenger, + MOCK_ANY_NAMESPACE, + type MessengerActions, + type MessengerEvents, + type MockAnyNamespace, +} from '@metamask/messenger'; import { NetworkController, NetworkStatus } from '@metamask/network-controller'; import type { - NetworkControllerGetEIP1559CompatibilityAction, - NetworkControllerGetNetworkClientByIdAction, - NetworkControllerGetStateAction, - NetworkControllerNetworkDidChangeEvent, + NetworkControllerMessenger, NetworkState, } from '@metamask/network-controller'; import type { Hex } from '@metamask/utils'; @@ -30,12 +33,11 @@ import { } from './gas-util'; import { GAS_ESTIMATE_TYPES, GasFeeController } from './GasFeeController'; import type { + GasFeeMessenger, GasFeeState, - GasFeeStateChange, GasFeeStateEthGasPrice, GasFeeStateFeeMarket, GasFeeStateLegacy, - GetGasFeeState, } from './GasFeeController'; jest.mock('./determineGasFeeCalculations'); @@ -48,39 +50,46 @@ const mockedDetermineGasFeeCalculations = const name = 'GasFeeController'; -type MainMessenger = Messenger< - | GetGasFeeState - | NetworkControllerGetStateAction - | NetworkControllerGetNetworkClientByIdAction - | NetworkControllerGetEIP1559CompatibilityAction, - GasFeeStateChange | NetworkControllerNetworkDidChangeEvent ->; +type AllGasFeeControllerActions = MessengerActions; +type AllGasFeeControllerEvents = MessengerEvents; + +type AllNetworkControllerActions = MessengerActions; +type AllNetworkControllerEvents = MessengerEvents; + +type AllActions = AllGasFeeControllerActions | AllNetworkControllerActions; +type AllEvents = AllGasFeeControllerEvents | AllNetworkControllerEvents; -const getMessenger = (): MainMessenger => { - return new Messenger(); +type RootMessenger = Messenger; + +const getRootMessenger = (): RootMessenger => { + return new Messenger({ namespace: MOCK_ANY_NAMESPACE }); }; const setupNetworkController = async ({ - unrestrictedMessenger, + rootMessenger, state, clock, initializeProvider = true, }: { - unrestrictedMessenger: MainMessenger; + rootMessenger: RootMessenger; state: Partial; clock: sinon.SinonFakeTimers; initializeProvider?: boolean; }) => { - const restrictedMessenger = unrestrictedMessenger.getRestricted({ - name: 'NetworkController', - allowedActions: [], - allowedEvents: [], + const networkControllerMessenger = new Messenger< + 'NetworkController', + MessengerActions, + MessengerEvents, + typeof rootMessenger + >({ + namespace: 'NetworkController', + parent: rootMessenger, }); const infuraProjectId = '123'; const networkController = new NetworkController({ - messenger: restrictedMessenger, + messenger: networkControllerMessenger, state, infuraProjectId, getRpcServiceOptions: () => ({ @@ -117,16 +126,26 @@ const setupNetworkController = async ({ return networkController; }; -const getRestrictedMessenger = (messenger: MainMessenger) => { - return messenger.getRestricted({ - name, - allowedActions: [ +const getGasFeeControllerMessenger = (rootMessenger: RootMessenger) => { + const gasFeeControllerMessenger = new Messenger< + 'GasFeeController', + AllGasFeeControllerActions, + AllGasFeeControllerEvents, + typeof rootMessenger + >({ + namespace: 'GasFeeController', + parent: rootMessenger, + }); + rootMessenger.delegate({ + messenger: gasFeeControllerMessenger, + actions: [ 'NetworkController:getState', 'NetworkController:getNetworkClientById', 'NetworkController:getEIP1559Compatibility', ], - allowedEvents: ['NetworkController:networkDidChange'], + events: ['NetworkController:networkDidChange'], }); + return gasFeeControllerMessenger; }; /** @@ -282,14 +301,14 @@ describe('GasFeeController', () => { interval?: number; initializeNetworkProvider?: boolean; } = {}) { - const messenger = getMessenger(); + const rootMessenger = getRootMessenger(); networkController = await setupNetworkController({ - unrestrictedMessenger: messenger, + rootMessenger, state: networkControllerState, clock, initializeProvider: initializeNetworkProvider, }); - const restrictedMessenger = getRestrictedMessenger(messenger); + const restrictedMessenger = getGasFeeControllerMessenger(rootMessenger); gasFeeController = new GasFeeController({ getProvider: jest.fn(), getChainId, diff --git a/packages/gas-fee-controller/src/GasFeeController.ts b/packages/gas-fee-controller/src/GasFeeController.ts index c26a08ee28b..d187077ad6f 100644 --- a/packages/gas-fee-controller/src/GasFeeController.ts +++ b/packages/gas-fee-controller/src/GasFeeController.ts @@ -1,14 +1,14 @@ import type { ControllerGetStateAction, ControllerStateChangeEvent, - RestrictedMessenger, -} from '@metamask/base-controller'; +} from '@metamask/base-controller/next'; import { convertHexToDecimal, safelyExecute, toHex, } from '@metamask/controller-utils'; import EthQuery from '@metamask/eth-query'; +import type { Messenger } from '@metamask/messenger'; import type { NetworkClientId, NetworkControllerGetEIP1559CompatibilityAction, @@ -18,7 +18,7 @@ import type { NetworkState, ProviderProxy, } from '@metamask/network-controller'; -import { StaticIntervalPollingController } from '@metamask/polling-controller'; +import { StaticIntervalPollingControllerNext } from '@metamask/polling-controller'; import type { Hex } from '@metamask/utils'; import { v1 as random } from 'uuid'; @@ -240,12 +240,10 @@ type AllowedActions = | NetworkControllerGetNetworkClientByIdAction | NetworkControllerGetEIP1559CompatibilityAction; -type GasFeeMessenger = RestrictedMessenger< +export type GasFeeMessenger = Messenger< typeof name, GasFeeControllerActions | AllowedActions, - GasFeeControllerEvents | NetworkControllerNetworkDidChangeEvent, - AllowedActions['type'], - NetworkControllerNetworkDidChangeEvent['type'] + GasFeeControllerEvents | NetworkControllerNetworkDidChangeEvent >; const defaultState: GasFeeState = { @@ -264,7 +262,7 @@ type GasFeePollingInput = { /** * Controller that retrieves gas fee estimate data and polls for updated data on a set interval */ -export class GasFeeController extends StaticIntervalPollingController()< +export class GasFeeController extends StaticIntervalPollingControllerNext()< typeof name, GasFeeState, GasFeeMessenger @@ -376,14 +374,14 @@ export class GasFeeController extends StaticIntervalPollingController() => StaticIntervalPollingControllerMixin( BaseController, ); + +export const StaticIntervalPollingControllerNext = < + PollingInput extends Json, +>() => + StaticIntervalPollingControllerMixin( + BaseControllerNext, + ); diff --git a/packages/polling-controller/src/index.ts b/packages/polling-controller/src/index.ts index ba1758c443b..f8104b9d5c9 100644 --- a/packages/polling-controller/src/index.ts +++ b/packages/polling-controller/src/index.ts @@ -6,6 +6,7 @@ export { export { StaticIntervalPollingControllerOnly, StaticIntervalPollingController, + StaticIntervalPollingControllerNext, } from './StaticIntervalPollingController'; export type { IPollingController } from './types'; From b1760391c7120b874f9c51cf07e93766bdf10407 Mon Sep 17 00:00:00 2001 From: Michele Esposito Date: Wed, 3 Sep 2025 22:38:46 +0200 Subject: [PATCH 09/69] migrate `NftController` messenger --- .../src/NftController.test.ts | 142 ++++++++++-------- .../assets-controllers/src/NftController.ts | 58 ++++--- 2 files changed, 105 insertions(+), 95 deletions(-) diff --git a/packages/assets-controllers/src/NftController.test.ts b/packages/assets-controllers/src/NftController.test.ts index 3004b667bad..fa172d12986 100644 --- a/packages/assets-controllers/src/NftController.test.ts +++ b/packages/assets-controllers/src/NftController.test.ts @@ -6,7 +6,6 @@ import type { } from '@metamask/accounts-controller'; import type { ApprovalControllerMessenger } from '@metamask/approval-controller'; import { ApprovalController } from '@metamask/approval-controller'; -import { Messenger } from '@metamask/base-controller'; import { IPFS_DEFAULT_GATEWAY_URL, ERC1155, @@ -22,14 +21,18 @@ import { convertHexToDecimal, } from '@metamask/controller-utils'; import type { InternalAccount } from '@metamask/keyring-internal-api'; -import type { - NetworkClientConfiguration, - NetworkClientId, +import { + MOCK_ANY_NAMESPACE, + Messenger, + type MessengerActions, + type MessengerEvents, + type MockAnyNamespace, +} from '@metamask/messenger'; +import { + type NetworkClientConfiguration, + type NetworkClientId, } from '@metamask/network-controller'; -import type { - BulkPhishingDetectionScanResponse, - PhishingControllerBulkScanUrlsAction, -} from '@metamask/phishing-controller'; +import type { BulkPhishingDetectionScanResponse } from '@metamask/phishing-controller'; import { RecommendedAction } from '@metamask/phishing-controller'; import { getDefaultPreferencesState, @@ -55,24 +58,29 @@ import type { Nft, NftControllerState, NftControllerMessenger, - AllowedActions as NftControllerAllowedActions, - AllowedEvents as NftControllerAllowedEvents, NFTStandardType, NftMetadata, } from './NftController'; import { NftController } from './NftController'; import type { Collection } from './NftDetectionController'; import { createMockInternalAccount } from '../../accounts-controller/src/tests/mocks'; -import type { - ExtractAvailableAction, - ExtractAvailableEvent, -} from '../../base-controller/tests/helpers'; import { buildCustomNetworkClientConfiguration, buildMockFindNetworkClientIdByChainId, buildMockGetNetworkClientById, } from '../../network-controller/tests/helpers'; +type AllActions = + | MessengerActions + | MessengerActions; + +type AllEvents = + | MessengerEvents + | MessengerEvents + | AccountsControllerSelectedAccountChangeEvent; + +type RootMessenger = Messenger; + const CRYPTOPUNK_ADDRESS = '0xb47e3cd837dDF8e4c57F05d70Ab865de6e193BBB'; const ERC721_KUDOSADDRESS = '0x2aEa4Add166EBf38b63d09a75dE1a7b94Aa24163'; const ERC721_KUDOS_TOKEN_ID = '1203'; @@ -223,15 +231,9 @@ function setupController({ defaultSelectedAccount?: InternalAccount; mockGetNetworkClientIdByChainId?: Record; } = {}) { - const messenger = new Messenger< - | ExtractAvailableAction - | NftControllerAllowedActions - | ExtractAvailableAction, - | ExtractAvailableEvent - | NftControllerAllowedEvents - | ExtractAvailableEvent - | AccountsControllerSelectedAccountChangeEvent - >(); + const messenger: RootMessenger = new Messenger({ + namespace: MOCK_ANY_NAMESPACE, + }); const getNetworkClientById = buildMockGetNetworkClientById( mockNetworkClientConfigurationsByNetworkClientId, @@ -328,10 +330,14 @@ function setupController({ mockGetERC1155TokenURI, ); - const approvalControllerMessenger = messenger.getRestricted({ - name: 'ApprovalController', - allowedActions: [], - allowedEvents: [], + const approvalControllerMessenger = new Messenger< + 'ApprovalController', + MessengerActions, + MessengerEvents, + RootMessenger + >({ + namespace: 'ApprovalController', + parent: messenger, }); const approvalController = new ApprovalController({ @@ -347,14 +353,18 @@ function setupController({ ); } - const nftControllerMessenger = messenger.getRestricted< + const nftControllerMessenger = new Messenger< typeof controllerName, - | PhishingControllerBulkScanUrlsAction['type'] - | NftControllerAllowedActions['type'], - NftControllerAllowedEvents['type'] + MessengerActions, + MessengerEvents, + RootMessenger >({ - name: controllerName, - allowedActions: [ + namespace: controllerName, + parent: messenger, + }); + messenger.delegate({ + messenger: nftControllerMessenger, + actions: [ 'ApprovalController:addRequest', 'AccountsController:getSelectedAccount', 'AccountsController:getAccount', @@ -368,7 +378,7 @@ function setupController({ 'NetworkController:findNetworkClientIdByChainId', 'PhishingController:bulkScanUrls', ], - allowedEvents: [ + events: [ 'AccountsController:selectedEvmAccountChange', 'PreferencesController:stateChange', ], @@ -376,7 +386,7 @@ function setupController({ const nftController = new NftController({ onNftAdded: jest.fn(), - messenger: nftControllerMessenger as NftControllerMessenger, + messenger: nftControllerMessenger, ...options, }); @@ -403,6 +413,7 @@ function setupController({ return { nftController, messenger, + nftControllerMessenger, approvalController, triggerPreferencesStateChange, triggerSelectedAccountChange, @@ -647,11 +658,11 @@ describe('NftController', () => { }); it('should error if the user does not own the suggested ERC721 NFT', async function () { - const { nftController, messenger } = setupController({ + const { nftController, nftControllerMessenger } = setupController({ getERC721OwnerOf: jest.fn().mockImplementation(() => '0x12345abcefg'), }); - const callActionSpy = jest.spyOn(messenger, 'call'); + const callActionSpy = jest.spyOn(nftControllerMessenger, 'call'); await expect(() => nftController.watchNft( @@ -686,11 +697,11 @@ describe('NftController', () => { }); it('should error if the user does not own the suggested ERC1155 NFT', async function () { - const { nftController, messenger } = setupController({ + const { nftController, nftControllerMessenger } = setupController({ getERC1155BalanceOf: jest.fn().mockImplementation(() => new BN(0)), }); - const callActionSpy = jest.spyOn(messenger, 'call'); + const callActionSpy = jest.spyOn(nftControllerMessenger, 'call'); await expect(() => nftController.watchNft( @@ -721,7 +732,7 @@ describe('NftController', () => { ); const { nftController, - messenger, + nftControllerMessenger, triggerPreferencesStateChange, triggerSelectedAccountChange, } = setupController({ @@ -748,7 +759,7 @@ describe('NftController', () => { (v4 as jest.Mock).mockImplementationOnce(() => requestId); const callActionSpy = jest - .spyOn(messenger, 'call') + .spyOn(nftControllerMessenger, 'call') // 1. `AccountsController:getAccount` .mockReturnValueOnce(OWNER_ACCOUNT) // 2. `AssetsContractController:getERC721OwnerOf` @@ -848,7 +859,7 @@ describe('NftController', () => { ); const { nftController, - messenger, + nftControllerMessenger, triggerPreferencesStateChange, triggerSelectedAccountChange, } = setupController({ @@ -874,7 +885,7 @@ describe('NftController', () => { (v4 as jest.Mock).mockImplementationOnce(() => requestId); const callActionSpy = jest - .spyOn(messenger, 'call') + .spyOn(nftControllerMessenger, 'call') // 1. `AccountsController:getAccount` .mockReturnValueOnce(OWNER_ACCOUNT) // 2. `AssetsContractController:getERC721OwnerOf` @@ -974,7 +985,7 @@ describe('NftController', () => { ); const { nftController, - messenger, + nftControllerMessenger, triggerPreferencesStateChange, triggerSelectedAccountChange, } = setupController({ @@ -1000,7 +1011,7 @@ describe('NftController', () => { (v4 as jest.Mock).mockImplementationOnce(() => requestId); const callActionSpy = jest - .spyOn(messenger, 'call') + .spyOn(nftControllerMessenger, 'call') // 1. `AccountsController:getAccount` .mockReturnValueOnce(OWNER_ACCOUNT) // 2. `AssetsContractController:getERC721OwnerOf` @@ -1100,7 +1111,7 @@ describe('NftController', () => { ); const { nftController, - messenger, + nftControllerMessenger, triggerPreferencesStateChange, triggerSelectedAccountChange, } = setupController({ @@ -1127,7 +1138,7 @@ describe('NftController', () => { (v4 as jest.Mock).mockImplementationOnce(() => requestId); const callActionSpy = jest - .spyOn(messenger, 'call') + .spyOn(nftControllerMessenger, 'call') // 1. `AccountsController:getAccount` .mockReturnValueOnce(OWNER_ACCOUNT) // 2. `AssetsContractController:getERC721OwnerOf` @@ -1228,7 +1239,7 @@ describe('NftController', () => { const { nftController, - messenger, + nftControllerMessenger, triggerPreferencesStateChange, triggerSelectedAccountChange, } = setupController({ @@ -1258,7 +1269,7 @@ describe('NftController', () => { (v4 as jest.Mock).mockImplementationOnce(() => requestId); const callActionSpy = jest - .spyOn(messenger, 'call') + .spyOn(nftControllerMessenger, 'call') // 1. `AccountsController:getAccount` .mockReturnValueOnce(OWNER_ACCOUNT) // 2. `AssetsContractController:getERC721OwnerOf` @@ -1361,20 +1372,23 @@ describe('NftController', () => { }), ); - const { nftController, messenger, triggerPreferencesStateChange } = - setupController({ - getAccount: jest.fn().mockReturnValue(OWNER_ACCOUNT), - getERC721OwnerOf: jest - .fn() - .mockRejectedValue(new Error('Not an ERC721 contract')), - getERC1155BalanceOf: jest.fn().mockResolvedValue(new BN(1)), - getERC721TokenURI: jest - .fn() - .mockRejectedValue(new Error('Not an ERC721 contract')), - getERC1155TokenURI: jest - .fn() - .mockResolvedValue('https://testtokenuri.com'), - }); + const { + nftController, + nftControllerMessenger, + triggerPreferencesStateChange, + } = setupController({ + getAccount: jest.fn().mockReturnValue(OWNER_ACCOUNT), + getERC721OwnerOf: jest + .fn() + .mockRejectedValue(new Error('Not an ERC721 contract')), + getERC1155BalanceOf: jest.fn().mockResolvedValue(new BN(1)), + getERC721TokenURI: jest + .fn() + .mockRejectedValue(new Error('Not an ERC721 contract')), + getERC1155TokenURI: jest + .fn() + .mockResolvedValue('https://testtokenuri.com'), + }); triggerPreferencesStateChange({ ...getDefaultPreferencesState(), isIpfsGatewayEnabled: true, @@ -1387,7 +1401,7 @@ describe('NftController', () => { (v4 as jest.Mock).mockImplementationOnce(() => requestId); const callActionSpy = jest - .spyOn(messenger, 'call') + .spyOn(nftControllerMessenger, 'call') // 1. `AccountsController:getAccount` .mockReturnValueOnce(OWNER_ACCOUNT) // 2. `AssetsContractController:getERC721OwnerOf` diff --git a/packages/assets-controllers/src/NftController.ts b/packages/assets-controllers/src/NftController.ts index b80785ce08b..1b78d1ec7a6 100644 --- a/packages/assets-controllers/src/NftController.ts +++ b/packages/assets-controllers/src/NftController.ts @@ -5,14 +5,11 @@ import type { AccountsControllerGetSelectedAccountAction, } from '@metamask/accounts-controller'; import type { AddApprovalRequest } from '@metamask/approval-controller'; -import type { - RestrictedMessenger, - ControllerStateChangeEvent, -} from '@metamask/base-controller'; import { BaseController, + type ControllerStateChangeEvent, type ControllerGetStateAction, -} from '@metamask/base-controller'; +} from '@metamask/base-controller/next'; import { safelyExecute, handleFetch, @@ -29,6 +26,7 @@ import { toHex, } from '@metamask/controller-utils'; import { type InternalAccount } from '@metamask/keyring-internal-api'; +import type { Messenger } from '@metamask/messenger'; import type { NetworkClientId, NetworkControllerGetNetworkClientByIdAction, @@ -264,12 +262,10 @@ export type NftControllerEvents = NftControllerStateChangeEvent; /** * The messenger of the {@link NftController}. */ -export type NftControllerMessenger = RestrictedMessenger< +export type NftControllerMessenger = Messenger< typeof controllerName, NftControllerActions | AllowedActions, - NftControllerEvents | AllowedEvents, - AllowedActions['type'], - AllowedEvents['type'] + NftControllerEvents | AllowedEvents >; export const getDefaultNftControllerState = (): NftControllerState => ({ @@ -359,7 +355,7 @@ export class NftController extends BaseController< }, }); - this.#selectedAccountId = this.messagingSystem.call( + this.#selectedAccountId = this.messenger.call( 'AccountsController:getSelectedAccount', ).id; this.#ipfsGateway = ipfsGateway; @@ -368,14 +364,14 @@ export class NftController extends BaseController< this.#isIpfsGatewayEnabled = isIpfsGatewayEnabled; this.#onNftAdded = onNftAdded; - this.messagingSystem.subscribe( + this.messenger.subscribe( 'PreferencesController:stateChange', // TODO: Either fix this lint violation or explain why it's necessary to ignore. // eslint-disable-next-line @typescript-eslint/no-misused-promises this.#onPreferencesControllerStateChange.bind(this), ); - this.messagingSystem.subscribe( + this.messenger.subscribe( 'AccountsController:selectedEvmAccountChange', // TODO: Either fix this lint violation or explain why it's necessary to ignore. // eslint-disable-next-line @typescript-eslint/no-misused-promises @@ -396,7 +392,7 @@ export class NftController extends BaseController< openSeaEnabled, isIpfsGatewayEnabled, }: PreferencesState) { - const selectedAccount = this.messagingSystem.call( + const selectedAccount = this.messenger.call( 'AccountsController:getSelectedAccount', ); this.#selectedAccountId = selectedAccount.id; @@ -703,7 +699,7 @@ export class NftController extends BaseController< ): Promise<[string, string]> { // try ERC721 uri try { - const uri = await this.messagingSystem.call( + const uri = await this.messenger.call( 'AssetsContractController:getERC721TokenURI', contractAddress, tokenId, @@ -716,7 +712,7 @@ export class NftController extends BaseController< // try ERC1155 uri try { - const tokenURI = await this.messagingSystem.call( + const tokenURI = await this.messenger.call( 'AssetsContractController:getERC1155TokenURI', contractAddress, tokenId, @@ -759,7 +755,7 @@ export class NftController extends BaseController< ): Promise { const { configuration: { chainId }, - } = this.messagingSystem.call( + } = this.messenger.call( 'NetworkController:getNetworkClientById', networkClientId, ); @@ -808,12 +804,12 @@ export class NftController extends BaseController< Pick > { const [name, symbol] = await Promise.all([ - this.messagingSystem.call( + this.messenger.call( 'AssetsContractController:getERC721AssetName', contractAddress, networkClientId, ), - this.messagingSystem.call( + this.messenger.call( 'AssetsContractController:getERC721AssetSymbol', contractAddress, networkClientId, @@ -1026,7 +1022,7 @@ export class NftController extends BaseController< const { allNftContracts } = this.state; const { configuration: { chainId }, - } = this.messagingSystem.call( + } = this.messenger.call( 'NetworkController:getNetworkClientById', networkClientId as NetworkClientId, ); @@ -1379,7 +1375,7 @@ export class NftController extends BaseController< ): Promise { // Checks the ownership for ERC-721. try { - const owner = await this.messagingSystem.call( + const owner = await this.messenger.call( 'AssetsContractController:getERC721OwnerOf', nftAddress, tokenId, @@ -1393,7 +1389,7 @@ export class NftController extends BaseController< // Checks the ownership for ERC-1155. try { - const balance = await this.messagingSystem.call( + const balance = await this.messenger.call( 'AssetsContractController:getERC1155BalanceOf', ownerAddress, nftAddress, @@ -1513,7 +1509,7 @@ export class NftController extends BaseController< ); const { configuration: { chainId }, - } = this.messagingSystem.call( + } = this.messenger.call( 'NetworkController:getNetworkClientById', networkClientId, ); @@ -1567,7 +1563,7 @@ export class NftController extends BaseController< const unsanitizedResults = await Promise.all( nftsWithChecksumAdr.map(async (nft) => { // Each NFT should have a chainId; convert nft.chainId to networkClientId - const networkClientId = this.messagingSystem.call( + const networkClientId = this.messenger.call( 'NetworkController:findNetworkClientIdByChainId', toHex(nft.chainId as number), ); @@ -1672,7 +1668,7 @@ export class NftController extends BaseController< const { configuration: { chainId }, - } = this.messagingSystem.call( + } = this.messenger.call( 'NetworkController:getNetworkClientById', networkClientId as NetworkClientId, ); @@ -1714,7 +1710,7 @@ export class NftController extends BaseController< const addressToSearch = this.#getAddressOrSelectedAddress(userAddress); const { configuration: { chainId }, - } = this.messagingSystem.call( + } = this.messenger.call( 'NetworkController:getNetworkClientById', networkClientId as NetworkClientId, ); @@ -1765,7 +1761,7 @@ export class NftController extends BaseController< const addressToSearch = this.#getAddressOrSelectedAddress(userAddress); const { configuration: { chainId }, - } = this.messagingSystem.call( + } = this.messenger.call( 'NetworkController:getNetworkClientById', networkClientId as NetworkClientId, ); @@ -1841,7 +1837,7 @@ export class NftController extends BaseController< const addressToSearch = this.#getAddressOrSelectedAddress(userAddress); const { configuration: { chainId }, - } = this.messagingSystem.call( + } = this.messenger.call( 'NetworkController:getNetworkClientById', networkClientId as NetworkClientId, ); @@ -1892,7 +1888,7 @@ export class NftController extends BaseController< const addressToSearch = this.#getAddressOrSelectedAddress(userAddress); const { configuration: { chainId }, - } = this.messagingSystem.call( + } = this.messenger.call( 'NetworkController:getNetworkClientById', networkClientId as NetworkClientId, ); @@ -2063,7 +2059,7 @@ export class NftController extends BaseController< } async _requestApproval(suggestedNftMeta: SuggestedNftMeta) { - return this.messagingSystem.call( + return this.messenger.call( 'ApprovalController:addRequest', { id: suggestedNftMeta.id, @@ -2092,7 +2088,7 @@ export class NftController extends BaseController< } // If the address is not defined (or empty), we fallback to the currently selected account's address - const selectedAccount = this.messagingSystem.call( + const selectedAccount = this.messenger.call( 'AccountsController:getAccount', this.#selectedAccountId, ); @@ -2205,7 +2201,7 @@ export class NftController extends BaseController< try { // Use bulkScanUrls to check all URLs at once - const bulkScanResponse = await this.messagingSystem.call( + const bulkScanResponse = await this.messenger.call( 'PhishingController:bulkScanUrls', urlsToCheck, ); From 01cd576bc6a1db03cd2faee1f35c9d5cbd9affce Mon Sep 17 00:00:00 2001 From: Michele Esposito Date: Wed, 3 Sep 2025 22:39:01 +0200 Subject: [PATCH 10/69] migrate `TokensController` messenger --- .../src/TokensController.test.ts | 66 ++++++++++++------- .../src/TokensController.ts | 40 ++++++----- 2 files changed, 62 insertions(+), 44 deletions(-) diff --git a/packages/assets-controllers/src/TokensController.test.ts b/packages/assets-controllers/src/TokensController.test.ts index 5dee2972864..0c43725a759 100644 --- a/packages/assets-controllers/src/TokensController.test.ts +++ b/packages/assets-controllers/src/TokensController.test.ts @@ -1,10 +1,9 @@ import { Contract } from '@ethersproject/contracts'; -import type { ApprovalStateChange } from '@metamask/approval-controller'; +import type { ApprovalControllerMessenger } from '@metamask/approval-controller'; import { ApprovalController, type ApprovalControllerState, } from '@metamask/approval-controller'; -import { Messenger } from '@metamask/base-controller'; import contractMaps from '@metamask/contract-metadata'; import { ApprovalType, @@ -14,6 +13,13 @@ import { InfuraNetworkType, } from '@metamask/controller-utils'; import type { InternalAccount } from '@metamask/keyring-internal-api'; +import { + Messenger, + MOCK_ANY_NAMESPACE, + type MockAnyNamespace, + type MessengerActions, + type MessengerEvents, +} from '@metamask/messenger'; import type { NetworkClientConfiguration, NetworkClientId, @@ -27,10 +33,6 @@ import { v1 as uuidV1 } from 'uuid'; import { FakeProvider } from '../../../tests/fake-provider'; import { createMockInternalAccount } from '../../accounts-controller/src/tests/mocks'; -import type { - ExtractAvailableAction, - ExtractAvailableEvent, -} from '../../base-controller/tests/helpers'; import { buildCustomNetworkClientConfiguration, buildMockGetNetworkClientById, @@ -41,8 +43,6 @@ import { TOKEN_END_POINT_API } from './token-service'; import type { Token } from './TokenRatesController'; import { TokensController } from './TokensController'; import type { - AllowedActions, - AllowedEvents, TokensControllerMessenger, TokensControllerState, } from './TokensController'; @@ -55,10 +55,15 @@ jest.mock('uuid', () => ({ jest.mock('./Standards/ERC20Standard'); jest.mock('./Standards/NftStandards/ERC1155/ERC1155Standard'); -type UnrestrictedMessenger = Messenger< - ExtractAvailableAction, - ExtractAvailableEvent | ApprovalStateChange ->; +type AllActions = + | MessengerActions + | MessengerActions; + +type AllEvents = + | MessengerEvents + | MessengerEvents; + +type RootMessenger = Messenger; const ContractMock = jest.mocked(Contract); const uuidV1Mock = jest.mocked(uuidV1); @@ -3483,7 +3488,7 @@ type WithControllerCallback = ({ changeNetwork: (networkControllerState: { selectedNetworkClientId: NetworkClientId; }) => void; - messenger: UnrestrictedMessenger; + messenger: RootMessenger; approvalController: ApprovalController; triggerSelectedAccountChange: (internalAccount: InternalAccount) => void; triggerAccountRemoved: (accountAddress: string) => void; @@ -3541,12 +3546,18 @@ async function withController( fn, ] = args.length === 2 ? args : [{}, args[0]]; - const messenger = new Messenger(); + const messenger: RootMessenger = new Messenger({ + namespace: MOCK_ANY_NAMESPACE, + }); - const approvalControllerMessenger = messenger.getRestricted({ - name: 'ApprovalController', - allowedActions: [], - allowedEvents: [], + const approvalControllerMessenger = new Messenger< + 'ApprovalController', + MessengerActions, + MessengerEvents, + RootMessenger + >({ + namespace: 'ApprovalController', + parent: messenger, }); const approvalController = new ApprovalController({ messenger: approvalControllerMessenger, @@ -3554,16 +3565,25 @@ async function withController( typesExcludedFromRateLimiting: [ApprovalType.WatchAsset], }); - const restrictedMessenger = messenger.getRestricted({ - name: 'TokensController', - allowedActions: [ + const tokensControllerMessenger = new Messenger< + 'TokensController', + MessengerActions, + MessengerEvents, + RootMessenger + >({ + namespace: 'TokensController', + parent: messenger, + }); + messenger.delegate({ + messenger: tokensControllerMessenger, + actions: [ 'ApprovalController:addRequest', 'NetworkController:getNetworkClientById', 'AccountsController:getAccount', 'AccountsController:getSelectedAccount', 'AccountsController:listAccounts', ], - allowedEvents: [ + events: [ 'NetworkController:networkDidChange', 'NetworkController:stateChange', 'AccountsController:selectedEvmAccountChange', @@ -3601,7 +3621,7 @@ async function withController( // where the provider can possibly be `undefined` if `networkClientId` is // not specified. provider: new FakeProvider(), - messenger: restrictedMessenger, + messenger: tokensControllerMessenger, ...options, }); diff --git a/packages/assets-controllers/src/TokensController.ts b/packages/assets-controllers/src/TokensController.ts index 190930e5995..cdd2cb9cbe4 100644 --- a/packages/assets-controllers/src/TokensController.ts +++ b/packages/assets-controllers/src/TokensController.ts @@ -8,11 +8,10 @@ import type { } from '@metamask/accounts-controller'; import type { AddApprovalRequest } from '@metamask/approval-controller'; import type { - RestrictedMessenger, ControllerGetStateAction, ControllerStateChangeEvent, -} from '@metamask/base-controller'; -import { BaseController } from '@metamask/base-controller'; +} from '@metamask/base-controller/next'; +import { BaseController } from '@metamask/base-controller/next'; import contractsMap from '@metamask/contract-metadata'; import { toChecksumHexAddress, @@ -27,6 +26,7 @@ import { } from '@metamask/controller-utils'; import type { KeyringControllerAccountRemovedEvent } from '@metamask/keyring-controller'; import type { InternalAccount } from '@metamask/keyring-internal-api'; +import type { Messenger } from '@metamask/messenger'; import { abiERC721 } from '@metamask/metamask-eth-abis'; import type { NetworkClientId, @@ -152,12 +152,10 @@ export type AllowedEvents = /** * The messenger of the {@link TokensController}. */ -export type TokensControllerMessenger = RestrictedMessenger< +export type TokensControllerMessenger = Messenger< typeof controllerName, TokensControllerActions | AllowedActions, - TokensControllerEvents | AllowedEvents, - AllowedActions['type'], - AllowedEvents['type'] + TokensControllerEvents | AllowedEvents >; export const getDefaultTokensState = (): TokensControllerState => { @@ -218,32 +216,32 @@ export class TokensController extends BaseController< this.#abortController = new AbortController(); - this.messagingSystem.registerActionHandler( + this.messenger.registerActionHandler( `${controllerName}:addDetectedTokens` as const, this.addDetectedTokens.bind(this), ); - this.messagingSystem.registerActionHandler( + this.messenger.registerActionHandler( `${controllerName}:addTokens` as const, this.addTokens.bind(this), ); - this.messagingSystem.subscribe( + this.messenger.subscribe( 'AccountsController:selectedEvmAccountChange', this.#onSelectedAccountChange.bind(this), ); - this.messagingSystem.subscribe( + this.messenger.subscribe( 'NetworkController:stateChange', this.#onNetworkStateChange.bind(this), ); - this.messagingSystem.subscribe( + this.messenger.subscribe( 'KeyringController:accountRemoved', (accountAddress: string) => this.#handleOnAccountRemoved(accountAddress), ); - this.messagingSystem.subscribe( + this.messenger.subscribe( 'TokenListController:stateChange', ({ tokensChainsCache }) => { const { allTokens } = this.state; @@ -413,7 +411,7 @@ export class TokensController extends BaseController< const releaseLock = await this.#mutex.acquire(); const { allTokens, allIgnoredTokens, allDetectedTokens } = this.state; - const chainIdToUse = this.messagingSystem.call( + const chainIdToUse = this.messenger.call( 'NetworkController:getNetworkClientById', networkClientId, ).configuration.chainId; @@ -499,7 +497,7 @@ export class TokensController extends BaseController< const { allTokens, allIgnoredTokens, allDetectedTokens } = this.state; const importedTokensMap: { [key: string]: true } = {}; - const interactingChainId = this.messagingSystem.call( + const interactingChainId = this.messenger.call( 'NetworkController:getNetworkClientById', networkClientId, ).configuration.chainId; @@ -575,7 +573,7 @@ export class TokensController extends BaseController< tokenAddressesToIgnore: string[], networkClientId: NetworkClientId, ) { - const interactingChainId = this.messagingSystem.call( + const interactingChainId = this.messenger.call( 'NetworkController:getNetworkClientById', networkClientId, ).configuration.chainId; @@ -733,7 +731,7 @@ export class TokensController extends BaseController< tokenAddress: string, networkClientId: NetworkClientId, ) { - const chainIdToUse = this.messagingSystem.call( + const chainIdToUse = this.messenger.call( 'NetworkController:getNetworkClientById', networkClientId, ).configuration.chainId; @@ -792,7 +790,7 @@ export class TokensController extends BaseController< #getProvider(networkClientId?: NetworkClientId): Web3Provider { return new Web3Provider( networkClientId - ? this.messagingSystem.call( + ? this.messenger.call( 'NetworkController:getNetworkClientById', networkClientId, ).provider @@ -1076,7 +1074,7 @@ export class TokensController extends BaseController< } async #requestApproval(suggestedAssetMeta: SuggestedAssetMeta) { - return this.messagingSystem.call( + return this.messenger.call( 'ApprovalController:addRequest', { id: suggestedAssetMeta.id, @@ -1098,12 +1096,12 @@ export class TokensController extends BaseController< } #getSelectedAccount() { - return this.messagingSystem.call('AccountsController:getSelectedAccount'); + return this.messenger.call('AccountsController:getSelectedAccount'); } #getSelectedAddress() { // If the address is not defined (or empty), we fallback to the currently selected account's address - const account = this.messagingSystem.call( + const account = this.messenger.call( 'AccountsController:getAccount', this.#selectedAccountId, ); From b72884fe9b59a92989d64016a9e0c3a1cf9de221 Mon Sep 17 00:00:00 2001 From: Michele Esposito Date: Wed, 3 Sep 2025 22:39:25 +0200 Subject: [PATCH 11/69] migrate `AssetsContractController` messenger --- packages/assets-controllers/package.json | 1 + .../src/AssetsContractController.test.ts | 69 +++++++++++++------ .../src/AssetsContractController.ts | 11 +-- yarn.lock | 1 + 4 files changed, 53 insertions(+), 29 deletions(-) diff --git a/packages/assets-controllers/package.json b/packages/assets-controllers/package.json index bb55e6ab4d7..798a03bb9f6 100644 --- a/packages/assets-controllers/package.json +++ b/packages/assets-controllers/package.json @@ -59,6 +59,7 @@ "@metamask/controller-utils": "^11.12.0", "@metamask/eth-query": "^4.0.0", "@metamask/keyring-api": "^20.1.0", + "@metamask/messenger": "^0.1.0", "@metamask/metamask-eth-abis": "^3.1.1", "@metamask/polling-controller": "^14.0.0", "@metamask/rpc-errors": "^7.0.2", diff --git a/packages/assets-controllers/src/AssetsContractController.test.ts b/packages/assets-controllers/src/AssetsContractController.test.ts index 5638e01c460..8c7320d8ab3 100644 --- a/packages/assets-controllers/src/AssetsContractController.test.ts +++ b/packages/assets-controllers/src/AssetsContractController.test.ts @@ -1,5 +1,4 @@ import { BigNumber } from '@ethersproject/bignumber'; -import { Messenger } from '@metamask/base-controller'; import { BUILT_IN_NETWORKS, ChainId, @@ -8,12 +7,18 @@ import { NetworkType, } from '@metamask/controller-utils'; import HttpProvider from '@metamask/ethjs-provider-http'; +import { + Messenger, + MOCK_ANY_NAMESPACE, + type MessengerActions, + type MessengerEvents, + type MockAnyNamespace, +} from '@metamask/messenger'; import type { Provider, NetworkClientId, - NetworkControllerActions, - NetworkControllerEvents, InfuraNetworkClientConfiguration, + NetworkControllerMessenger, } from '@metamask/network-controller'; import { NetworkController, @@ -30,12 +35,24 @@ import { } from './AssetsContractController'; import { SupportedTokenDetectionNetworks } from './assetsUtil'; import { mockNetwork } from '../../../tests/mock-network'; -import type { - ExtractAvailableAction, - ExtractAvailableEvent, -} from '../../base-controller/tests/helpers'; import { buildInfuraNetworkClientConfiguration } from '../../network-controller/tests/helpers'; +type AllAssetsContractControllerActions = + MessengerActions; + +type AllAssetsContractControllerEvents = + MessengerEvents; + +type AllNetworkControllerActions = MessengerActions; + +type AllNetworkControllerEvents = MessengerEvents; + +type RootMessenger = Messenger< + MockAnyNamespace, + AllAssetsContractControllerActions | AllNetworkControllerActions, + AllAssetsContractControllerEvents | AllNetworkControllerEvents +>; + const ERC20_UNI_ADDRESS = '0x1f9840a85d5af5bf1d1762f925bdaddc4201f984'; const ERC20_SAI_ADDRESS = '0x89d24a6b4ccb1b6faa2625fe562bdd9a23260359'; const ERC20_DAI_ADDRESS = '0x6b175474e89094c44da98b954eedeac495271d0f'; @@ -80,18 +97,19 @@ async function setupAssetContractControllers({ }; let provider: Provider; - const messenger = new Messenger< - | ExtractAvailableAction - | NetworkControllerActions, - | ExtractAvailableEvent - | NetworkControllerEvents - >(); + const messenger: RootMessenger = new Messenger({ + namespace: MOCK_ANY_NAMESPACE, + }); const networkController = new NetworkController({ infuraProjectId, - messenger: messenger.getRestricted({ - name: 'NetworkController', - allowedActions: [], - allowedEvents: [], + messenger: new Messenger< + 'NetworkController', + MessengerActions, + MessengerEvents, + RootMessenger + >({ + namespace: 'NetworkController', + parent: messenger, }), getRpcServiceOptions: () => ({ fetch, @@ -121,15 +139,24 @@ async function setupAssetContractControllers({ }), ); - const assetsContractMessenger = messenger.getRestricted({ - name: 'AssetsContractController', - allowedActions: [ + const assetsContractMessenger = new Messenger< + 'AssetsContractController', + MessengerActions, + MessengerEvents, + RootMessenger + >({ + namespace: 'AssetsContractController', + parent: messenger, + }); + messenger.delegate({ + messenger: assetsContractMessenger, + actions: [ 'NetworkController:getNetworkClientById', 'NetworkController:getNetworkConfigurationByNetworkClientId', 'NetworkController:getSelectedNetworkClient', 'NetworkController:getState', ], - allowedEvents: [ + events: [ 'PreferencesController:stateChange', 'NetworkController:networkDidChange', ], diff --git a/packages/assets-controllers/src/AssetsContractController.ts b/packages/assets-controllers/src/AssetsContractController.ts index 70403278730..2b903890858 100644 --- a/packages/assets-controllers/src/AssetsContractController.ts +++ b/packages/assets-controllers/src/AssetsContractController.ts @@ -2,11 +2,8 @@ import type { BigNumber } from '@ethersproject/bignumber'; import { Contract } from '@ethersproject/contracts'; import { Web3Provider } from '@ethersproject/providers'; -import type { - ActionConstraint, - RestrictedMessenger, -} from '@metamask/base-controller'; import { IPFS_DEFAULT_GATEWAY_URL } from '@metamask/controller-utils'; +import type { Messenger, ActionConstraint } from '@metamask/messenger'; import type { NetworkClientId, NetworkControllerGetNetworkClientByIdAction, @@ -205,12 +202,10 @@ export type AllowedEvents = /** * The messenger of the {@link AssetsContractController}. */ -export type AssetsContractControllerMessenger = RestrictedMessenger< +export type AssetsContractControllerMessenger = Messenger< typeof name, AssetsContractControllerActions | AllowedActions, - AssetsContractControllerEvents | AllowedEvents, - AllowedActions['type'], - AllowedEvents['type'] + AssetsContractControllerEvents | AllowedEvents >; export type StakedBalance = string | undefined; diff --git a/yarn.lock b/yarn.lock index e5cd8da65bd..274855637c5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2588,6 +2588,7 @@ __metadata: "@metamask/keyring-controller": "npm:^23.0.0" "@metamask/keyring-internal-api": "npm:^8.1.0" "@metamask/keyring-snap-client": "npm:^7.0.0" + "@metamask/messenger": "npm:^0.1.0" "@metamask/metamask-eth-abis": "npm:^3.1.1" "@metamask/multichain-account-service": "npm:^0.6.0" "@metamask/network-controller": "npm:^24.1.0" From 31c7ee09599751b130d985cd8b3a26d6b48aecb6 Mon Sep 17 00:00:00 2001 From: Michele Esposito Date: Wed, 3 Sep 2025 18:11:57 +0200 Subject: [PATCH 12/69] update changelogs --- packages/assets-controllers/CHANGELOG.md | 5 +++++ packages/gas-fee-controller/CHANGELOG.md | 2 ++ 2 files changed, 7 insertions(+) diff --git a/packages/assets-controllers/CHANGELOG.md b/packages/assets-controllers/CHANGELOG.md index 55d0645be09..032457253b1 100644 --- a/packages/assets-controllers/CHANGELOG.md +++ b/packages/assets-controllers/CHANGELOG.md @@ -7,6 +7,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Changed + +- **BREAKING:** Migrate `AssetsContractController`, `NftController`, and `TokensController` to new `Messenger` from `@metamask/messenger` ([#6386](https://github.com/MetaMask/core/pull/6386)) + - Previously, the controllers accepted a `RestrictedMessenger` instance from `@metamask/base-controller`. + ## [74.3.2] ### Changed diff --git a/packages/gas-fee-controller/CHANGELOG.md b/packages/gas-fee-controller/CHANGELOG.md index 376fe9c201b..45205d6c7a6 100644 --- a/packages/gas-fee-controller/CHANGELOG.md +++ b/packages/gas-fee-controller/CHANGELOG.md @@ -9,6 +9,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed +- **BREAKING:** Use new `Messenger` from `@metamask/messenger` ([#6386](https://github.com/MetaMask/core/pull/6386)) + - Previously, `GasFeeController` accepted a `RestrictedMessenger` instance from `@metamask/base-controller`. - Bump `@metamask/base-controller` from `^8.0.1` to `^8.2.0` ([#6284](https://github.com/MetaMask/core/pull/6284), [#6355](https://github.com/MetaMask/core/pull/6355)) - Bump `@metamask/controller-utils` from `^11.10.0` to `^11.12.0` ([#6069](https://github.com/MetaMask/core/pull/6069), [#6303](https://github.com/MetaMask/core/pull/6303)) - Bump `@metamask/utils` from `^11.2.0` to `^11.4.2` ([#6054](https://github.com/MetaMask/core/pull/6054)) From 1051a2eab8d1e2d8e96c9f4a85791a872160f9da Mon Sep 17 00:00:00 2001 From: Michele Esposito Date: Wed, 3 Sep 2025 23:30:26 +0200 Subject: [PATCH 13/69] fix `NetworkController` tests --- packages/network-controller/tests/NetworkController.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/network-controller/tests/NetworkController.test.ts b/packages/network-controller/tests/NetworkController.test.ts index 48961d5cb28..3384dfac124 100644 --- a/packages/network-controller/tests/NetworkController.test.ts +++ b/packages/network-controller/tests/NetworkController.test.ts @@ -2241,7 +2241,7 @@ describe('NetworkController', () => { }, infuraProjectId, }, - async ({ controller, messenger }) => { + async ({ controller, networkControllerMessenger }) => { const fakeProvider = buildFakeProvider([ // Called during provider initialization { @@ -2265,7 +2265,7 @@ describe('NetworkController', () => { const lookupNetworkPromise = controller.lookupNetwork(); const error = new Error('oops'); jest - .spyOn(messenger, 'unsubscribe') + .spyOn(networkControllerMessenger, 'unsubscribe') .mockImplementation((eventType) => { // This is okay. // eslint-disable-next-line jest/no-conditional-in-test From eeade8f6a307ae162c55bcbdc9b523ffa10f9e1f Mon Sep 17 00:00:00 2001 From: Michele Esposito Date: Wed, 3 Sep 2025 23:34:58 +0200 Subject: [PATCH 14/69] update eslint thresholds --- eslint-warning-thresholds.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eslint-warning-thresholds.json b/eslint-warning-thresholds.json index 44a46f64a62..8cf94d98bc7 100644 --- a/eslint-warning-thresholds.json +++ b/eslint-warning-thresholds.json @@ -82,7 +82,7 @@ }, "packages/assets-controllers/src/TokensController.test.ts": { "import-x/namespace": 1, - "import-x/order": 4, + "import-x/order": 3, "jest/no-conditional-in-test": 2 }, "packages/assets-controllers/src/TokensController.ts": { From edff4d4c9bba8883865250846eb0eeb52ea37340 Mon Sep 17 00:00:00 2001 From: Michele Esposito Date: Wed, 3 Sep 2025 18:20:01 +0200 Subject: [PATCH 15/69] remove `StaticIntervalPollingControllerNext` --- packages/gas-fee-controller/src/GasFeeController.ts | 4 ++-- .../src/StaticIntervalPollingController.ts | 10 +--------- packages/polling-controller/src/index.ts | 1 - 3 files changed, 3 insertions(+), 12 deletions(-) diff --git a/packages/gas-fee-controller/src/GasFeeController.ts b/packages/gas-fee-controller/src/GasFeeController.ts index d187077ad6f..6e223f1ac5b 100644 --- a/packages/gas-fee-controller/src/GasFeeController.ts +++ b/packages/gas-fee-controller/src/GasFeeController.ts @@ -18,7 +18,7 @@ import type { NetworkState, ProviderProxy, } from '@metamask/network-controller'; -import { StaticIntervalPollingControllerNext } from '@metamask/polling-controller'; +import { StaticIntervalPollingController } from '@metamask/polling-controller'; import type { Hex } from '@metamask/utils'; import { v1 as random } from 'uuid'; @@ -262,7 +262,7 @@ type GasFeePollingInput = { /** * Controller that retrieves gas fee estimate data and polls for updated data on a set interval */ -export class GasFeeController extends StaticIntervalPollingControllerNext()< +export class GasFeeController extends StaticIntervalPollingController()< typeof name, GasFeeState, GasFeeMessenger diff --git a/packages/polling-controller/src/StaticIntervalPollingController.ts b/packages/polling-controller/src/StaticIntervalPollingController.ts index 34f130ff96f..e71f3e44417 100644 --- a/packages/polling-controller/src/StaticIntervalPollingController.ts +++ b/packages/polling-controller/src/StaticIntervalPollingController.ts @@ -1,5 +1,4 @@ -import { BaseController } from '@metamask/base-controller'; -import { BaseController as BaseControllerNext } from '@metamask/base-controller/next'; +import { BaseController } from '@metamask/base-controller/next'; import type { Json } from '@metamask/utils'; import { @@ -90,10 +89,3 @@ export const StaticIntervalPollingController = () => StaticIntervalPollingControllerMixin( BaseController, ); - -export const StaticIntervalPollingControllerNext = < - PollingInput extends Json, ->() => - StaticIntervalPollingControllerMixin( - BaseControllerNext, - ); diff --git a/packages/polling-controller/src/index.ts b/packages/polling-controller/src/index.ts index f8104b9d5c9..ba1758c443b 100644 --- a/packages/polling-controller/src/index.ts +++ b/packages/polling-controller/src/index.ts @@ -6,7 +6,6 @@ export { export { StaticIntervalPollingControllerOnly, StaticIntervalPollingController, - StaticIntervalPollingControllerNext, } from './StaticIntervalPollingController'; export type { IPollingController } from './types'; From 3ec10e109d95a301a29a10f1cf6102a2598c70c2 Mon Sep 17 00:00:00 2001 From: Michele Esposito Date: Wed, 3 Sep 2025 18:20:30 +0200 Subject: [PATCH 16/69] migrate `bridge-controller` messenger --- packages/bridge-controller/package.json | 1 + .../src/bridge-controller.ts | 40 +++++++++---------- packages/bridge-controller/src/types.ts | 27 ++++++++----- 3 files changed, 38 insertions(+), 30 deletions(-) diff --git a/packages/bridge-controller/package.json b/packages/bridge-controller/package.json index 3761fea64ca..5c41768c341 100644 --- a/packages/bridge-controller/package.json +++ b/packages/bridge-controller/package.json @@ -56,6 +56,7 @@ "@metamask/controller-utils": "^11.12.0", "@metamask/gas-fee-controller": "^24.0.0", "@metamask/keyring-api": "^20.1.0", + "@metamask/messenger": "^0.1.0", "@metamask/metamask-eth-abis": "^3.1.1", "@metamask/multichain-network-controller": "^0.12.0", "@metamask/polling-controller": "^14.0.0", diff --git a/packages/bridge-controller/src/bridge-controller.ts b/packages/bridge-controller/src/bridge-controller.ts index c3b145910c8..8407b7247a7 100644 --- a/packages/bridge-controller/src/bridge-controller.ts +++ b/packages/bridge-controller/src/bridge-controller.ts @@ -1,7 +1,7 @@ import type { BigNumber } from '@ethersproject/bignumber'; import { Contract } from '@ethersproject/contracts'; import { Web3Provider } from '@ethersproject/providers'; -import type { StateMetadata } from '@metamask/base-controller'; +import type { StateMetadata } from '@metamask/base-controller/next'; import type { TraceCallback } from '@metamask/controller-utils'; import { abiERC20 } from '@metamask/metamask-eth-abis'; import type { NetworkClientId } from '@metamask/network-controller'; @@ -213,31 +213,31 @@ export class BridgeController extends StaticIntervalPollingController fn?.()) as TraceCallback); // Register action handlers - this.messagingSystem.registerActionHandler( + this.messenger.registerActionHandler( `${BRIDGE_CONTROLLER_NAME}:setChainIntervalLength`, this.setChainIntervalLength.bind(this), ); - this.messagingSystem.registerActionHandler( + this.messenger.registerActionHandler( `${BRIDGE_CONTROLLER_NAME}:updateBridgeQuoteRequestParams`, this.updateBridgeQuoteRequestParams.bind(this), ); - this.messagingSystem.registerActionHandler( + this.messenger.registerActionHandler( `${BRIDGE_CONTROLLER_NAME}:resetState`, this.resetState.bind(this), ); - this.messagingSystem.registerActionHandler( + this.messenger.registerActionHandler( `${BRIDGE_CONTROLLER_NAME}:getBridgeERC20Allowance`, this.getBridgeERC20Allowance.bind(this), ); - this.messagingSystem.registerActionHandler( + this.messenger.registerActionHandler( `${BRIDGE_CONTROLLER_NAME}:trackUnifiedSwapBridgeEvent`, this.trackUnifiedSwapBridgeEvent.bind(this), ); - this.messagingSystem.registerActionHandler( + this.messenger.registerActionHandler( `${BRIDGE_CONTROLLER_NAME}:stopPollingForQuotes`, this.stopPollingForQuotes.bind(this), ); - this.messagingSystem.registerActionHandler( + this.messenger.registerActionHandler( `${BRIDGE_CONTROLLER_NAME}:fetchQuotes`, this.fetchQuotes.bind(this), ); @@ -334,7 +334,7 @@ export class BridgeController extends StaticIntervalPollingController => { - const bridgeFeatureFlags = getBridgeFeatureFlags(this.messagingSystem); + const bridgeFeatureFlags = getBridgeFeatureFlags(this.messenger); // If featureId is specified, retrieve the quoteRequestOverrides for that featureId const quoteRequestOverrides = featureId ? bridgeFeatureFlags.quoteRequestOverrides?.[featureId] @@ -385,9 +385,9 @@ export class BridgeController extends StaticIntervalPollingController { return { - ...this.messagingSystem.call('MultichainAssetsRatesController:getState'), - ...this.messagingSystem.call('CurrencyRateController:getState'), - ...this.messagingSystem.call('TokenRatesController:getState'), + ...this.messenger.call('MultichainAssetsRatesController:getState'), + ...this.messenger.call('CurrencyRateController:getState'), + ...this.messenger.call('TokenRatesController:getState'), ...this.state, }; }; @@ -437,7 +437,7 @@ export class BridgeController extends StaticIntervalPollingController { const { state } = this; const { srcChainId } = state.quoteRequest; - const bridgeFeatureFlags = getBridgeFeatureFlags(this.messagingSystem); + const bridgeFeatureFlags = getBridgeFeatureFlags(this.messenger); const refreshRateOverride = srcChainId ? bridgeFeatureFlags.chains[formatChainIdToCaip(srcChainId)]?.refreshRate @@ -608,7 +608,7 @@ export class BridgeController extends StaticIntervalPollingController; + +export type BridgeControllerStateChangeEvent = ControllerStateChangeEvent< + typeof BRIDGE_CONTROLLER_NAME, + BridgeControllerState +>; + // Maps to BridgeController function names export type BridgeControllerActions = + | BridgeControllerGetStateAction | BridgeControllerAction | BridgeControllerAction | BridgeControllerAction @@ -336,10 +348,7 @@ export type BridgeControllerActions = | BridgeControllerAction | BridgeControllerAction; -export type BridgeControllerEvents = ControllerStateChangeEvent< - typeof BRIDGE_CONTROLLER_NAME, - BridgeControllerState ->; +export type BridgeControllerEvents = BridgeControllerStateChangeEvent; export type AllowedActions = | AccountsControllerGetSelectedMultichainAccountAction @@ -356,10 +365,8 @@ export type AllowedEvents = never; /** * The messenger for the BridgeController. */ -export type BridgeControllerMessenger = RestrictedMessenger< +export type BridgeControllerMessenger = Messenger< typeof BRIDGE_CONTROLLER_NAME, BridgeControllerActions | AllowedActions, - BridgeControllerEvents | AllowedEvents, - AllowedActions['type'], - AllowedEvents['type'] + BridgeControllerEvents | AllowedEvents >; From e795b14b4120cc3c9c5f354f1bf8601d30f2ecee Mon Sep 17 00:00:00 2001 From: Michele Esposito Date: Wed, 3 Sep 2025 22:31:38 +0200 Subject: [PATCH 17/69] migrate `BridgeStatusController` messenger --- .../src/bridge-status-controller.test.ts | 98 +++++++++++-------- .../src/bridge-status-controller.ts | 63 ++++++------ .../bridge-status-controller/src/types.ts | 8 +- .../src/utils/transaction.test.ts | 18 ++-- .../src/utils/transaction.ts | 22 ++--- 5 files changed, 107 insertions(+), 102 deletions(-) diff --git a/packages/bridge-status-controller/src/bridge-status-controller.test.ts b/packages/bridge-status-controller/src/bridge-status-controller.test.ts index f95b11fc3da..cb6a79f0d03 100644 --- a/packages/bridge-status-controller/src/bridge-status-controller.test.ts +++ b/packages/bridge-status-controller/src/bridge-status-controller.test.ts @@ -1,10 +1,7 @@ /* eslint-disable jest/no-conditional-in-test */ /* eslint-disable jest/no-restricted-matchers */ -import type { AccountsControllerActions } from '@metamask/accounts-controller'; -import { Messenger } from '@metamask/base-controller'; import type { - BridgeControllerActions, - BridgeControllerEvents, + BridgeControllerMessenger, TxData, } from '@metamask/bridge-controller'; import { @@ -16,13 +13,18 @@ import { } from '@metamask/bridge-controller'; import { ChainId } from '@metamask/bridge-controller'; import { ActionTypes, FeeType } from '@metamask/bridge-controller'; +import { + Messenger, + MOCK_ANY_NAMESPACE, + type MessengerActions, + type MessengerEvents, + type MockAnyNamespace, +} from '@metamask/messenger'; import { TransactionType, TransactionStatus, } from '@metamask/transaction-controller'; import type { - TransactionControllerActions, - TransactionControllerEvents, TransactionMeta, TransactionParams, } from '@metamask/transaction-controller'; @@ -35,10 +37,6 @@ import { DEFAULT_BRIDGE_STATUS_CONTROLLER_STATE, MAX_ATTEMPTS, } from './constants'; -import type { - BridgeStatusControllerActions, - BridgeStatusControllerEvents, -} from './types'; import { type BridgeId, type StartPollingForBridgeTxStatusArgsSerialized, @@ -52,6 +50,22 @@ import * as transactionUtils from './utils/transaction'; import { flushPromises } from '../../../tests/helpers'; import { CHAIN_IDS } from '../../bridge-controller/src/constants/chains'; +type AllBridgeStatusControllerActions = + MessengerActions; + +type AllBridgeStatusControllerEvents = + MessengerEvents; + +type AllBridgeControllerActions = MessengerActions; + +type AllBridgeControllerEvents = MessengerEvents; + +type RootMessenger = Messenger< + MockAnyNamespace, + AllBridgeStatusControllerActions | AllBridgeControllerActions, + AllBridgeStatusControllerEvents | AllBridgeControllerEvents +>; + jest.mock('uuid', () => ({ v4: () => 'test-uuid-1234', })); @@ -3292,19 +3306,16 @@ describe('BridgeStatusController', () => { }); describe('subscription handlers', () => { - let mockBridgeStatusMessenger: jest.Mocked; + let mockMessenger: RootMessenger; + let mockBridgeStatusMessenger: Messenger< + 'BridgeStatusController', + MessengerActions, + MessengerEvents, + RootMessenger + >; let mockTrackEventFn: jest.Mock; let bridgeStatusController: BridgeStatusController; - let mockMessenger: Messenger< - | BridgeStatusControllerActions - | TransactionControllerActions - | BridgeControllerActions - | AccountsControllerActions, - | BridgeStatusControllerEvents - | TransactionControllerEvents - | BridgeControllerEvents - >; let mockFetchFn: jest.Mock; const consoleFn = console.warn; let consoleFnSpy: jest.SpyInstance; @@ -3314,37 +3325,38 @@ describe('BridgeStatusController', () => { jest.clearAllMocks(); // eslint-disable-next-line no-empty-function consoleFnSpy = jest.spyOn(console, 'warn').mockImplementation(() => {}); - mockMessenger = new Messenger< - | BridgeStatusControllerActions - | TransactionControllerActions - | BridgeControllerActions - | AccountsControllerActions, - | BridgeStatusControllerEvents - | TransactionControllerEvents - | BridgeControllerEvents - >(); - - jest.spyOn(mockMessenger, 'call').mockImplementation((..._args) => { - return Promise.resolve(); - }); - - mockBridgeStatusMessenger = mockMessenger.getRestricted({ - name: BRIDGE_STATUS_CONTROLLER_NAME, - allowedActions: [ + mockMessenger = new Messenger({ namespace: MOCK_ANY_NAMESPACE }); + mockBridgeStatusMessenger = new Messenger({ + namespace: BRIDGE_STATUS_CONTROLLER_NAME, + parent: mockMessenger, + }); + mockMessenger.delegate({ + messenger: mockBridgeStatusMessenger, + actions: [ 'TransactionController:getState', 'BridgeController:trackUnifiedSwapBridgeEvent', 'AccountsController:getAccountByAddress', ], - allowedEvents: [ + events: [ 'TransactionController:transactionFailed', 'TransactionController:transactionConfirmed', ], - }) as never; + }); + + jest + .spyOn(mockBridgeStatusMessenger, 'call') + .mockImplementation((..._args) => { + return Promise.resolve(); + }); - const mockBridgeMessenger = mockMessenger.getRestricted({ - name: 'BridgeController', - allowedActions: [], - allowedEvents: [], + const mockBridgeMessenger = new Messenger< + 'BridgeController', + MessengerActions, + MessengerEvents, + RootMessenger + >({ + namespace: 'BridgeController', + parent: mockMessenger, }); mockTrackEventFn = jest.fn(); new BridgeController({ diff --git a/packages/bridge-status-controller/src/bridge-status-controller.ts b/packages/bridge-status-controller/src/bridge-status-controller.ts index 2194c1dcb27..7fdc0f711eb 100644 --- a/packages/bridge-status-controller/src/bridge-status-controller.ts +++ b/packages/bridge-status-controller/src/bridge-status-controller.ts @@ -165,23 +165,23 @@ export class BridgeStatusController extends StaticIntervalPollingController fn?.()) as TraceCallback); // Register action handlers - this.messagingSystem.registerActionHandler( + this.messenger.registerActionHandler( `${BRIDGE_STATUS_CONTROLLER_NAME}:startPollingForBridgeTxStatus`, this.startPollingForBridgeTxStatus.bind(this), ); - this.messagingSystem.registerActionHandler( + this.messenger.registerActionHandler( `${BRIDGE_STATUS_CONTROLLER_NAME}:wipeBridgeStatus`, this.wipeBridgeStatus.bind(this), ); - this.messagingSystem.registerActionHandler( + this.messenger.registerActionHandler( `${BRIDGE_STATUS_CONTROLLER_NAME}:resetState`, this.resetState.bind(this), ); - this.messagingSystem.registerActionHandler( + this.messenger.registerActionHandler( `${BRIDGE_STATUS_CONTROLLER_NAME}:submitTx`, this.submitTx.bind(this), ); - this.messagingSystem.registerActionHandler( + this.messenger.registerActionHandler( `${BRIDGE_STATUS_CONTROLLER_NAME}:restartPollingForFailedAttempts`, this.restartPollingForFailedAttempts.bind(this), ); @@ -189,7 +189,7 @@ export class BridgeStatusController extends StaticIntervalPollingController { const { type, status, id } = transactionMeta; @@ -221,7 +221,7 @@ export class BridgeStatusController extends StaticIntervalPollingController { const { type, id, chainId } = transactionMeta; @@ -277,10 +277,10 @@ export class BridgeStatusController extends StaticIntervalPollingController } | { signature: string }; @@ -774,12 +774,9 @@ export class BridgeStatusController extends StaticIntervalPollingController['result'], ): Promise => { const transactionHash = await hashPromise; - const finalTransactionMeta: TransactionMeta | undefined = - this.messagingSystem - .call('TransactionController:getState') - .transactions.find( - (tx: TransactionMeta) => tx.hash === transactionHash, - ); + const finalTransactionMeta: TransactionMeta | undefined = this.messenger + .call('TransactionController:getState') + .transactions.find((tx: TransactionMeta) => tx.hash === transactionHash); if (!finalTransactionMeta) { throw new Error( 'Failed to submit cross-chain swap tx: txMeta for txHash was not found', @@ -848,7 +845,7 @@ export class BridgeStatusController extends StaticIntervalPollingController => { const actionId = generateActionId().toString(); - const selectedAccount = this.messagingSystem.call( + const selectedAccount = this.messenger.call( 'AccountsController:getAccountByAddress', trade.from, ); @@ -858,7 +855,7 @@ export class BridgeStatusController extends StaticIntervalPollingController & QuoteMetadata, ) => { const resetApproval = await getUSDTAllowanceResetTx( - this.messagingSystem, + this.messenger, quoteResponse, ); if (resetApproval) { @@ -915,7 +912,7 @@ export class BridgeStatusController extends StaticIntervalPollingController { - const { gasFeeEstimates } = this.messagingSystem.call( + const { gasFeeEstimates } = this.messenger.call( 'GasFeeController:getState', ); const { estimates: txGasFeeEstimates } = await this.#estimateGasFeeFn({ @@ -951,11 +948,11 @@ export class BridgeStatusController extends StaticIntervalPollingController[0], - 'messagingSystem' | 'estimateGasFeeFn' + 'messenger' | 'estimateGasFeeFn' >, ) => { const transactionParams = await getAddTransactionBatchParams({ - messagingSystem: this.messagingSystem, + messenger: this.messenger, estimateGasFeeFn: this.#estimateGasFeeFn, ...args, }); @@ -976,7 +973,7 @@ export class BridgeStatusController extends StaticIntervalPollingController & QuoteMetadata, isStxEnabledOnClient: boolean, ): Promise> => { - this.messagingSystem.call('BridgeController:stopPollingForQuotes'); + this.messenger.call('BridgeController:stopPollingForQuotes'); const selectedAccount = this.#getMultichainSelectedAccount(); if (!selectedAccount) { @@ -1091,7 +1088,7 @@ export class BridgeStatusController extends StaticIntervalPollingController id === txMetaId); @@ -1222,7 +1219,7 @@ export class BridgeStatusController extends StaticIntervalPollingController; diff --git a/packages/bridge-status-controller/src/utils/transaction.test.ts b/packages/bridge-status-controller/src/utils/transaction.test.ts index 16b9a44428c..6efb7760301 100644 --- a/packages/bridge-status-controller/src/utils/transaction.test.ts +++ b/packages/bridge-status-controller/src/utils/transaction.test.ts @@ -1349,7 +1349,7 @@ describe('Bridge Status Controller Transaction Utils', () => { const result = await getAddTransactionBatchParams({ quoteResponse: mockQuoteResponse, - messagingSystem: mockMessagingSystem, + messenger: mockMessagingSystem, isBridgeTx: true, trade: mockQuoteResponse.trade, approval: mockQuoteResponse.approval, @@ -1372,7 +1372,7 @@ describe('Bridge Status Controller Transaction Utils', () => { const result = await getAddTransactionBatchParams({ quoteResponse: mockQuoteResponse, - messagingSystem: mockMessagingSystem, + messenger: mockMessagingSystem, isBridgeTx: false, trade: mockQuoteResponse.trade, estimateGasFeeFn: jest.fn().mockResolvedValue({}), @@ -1395,7 +1395,7 @@ describe('Bridge Status Controller Transaction Utils', () => { const result = await getAddTransactionBatchParams({ quoteResponse: mockQuoteResponse, - messagingSystem: mockMessagingSystem, + messenger: mockMessagingSystem, isBridgeTx: true, trade: mockQuoteResponse.trade, resetApproval: mockQuoteResponse.resetApproval, @@ -1474,7 +1474,7 @@ describe('Bridge Status Controller Transaction Utils', () => { }; findAndUpdateTransactionsInBatch({ - messagingSystem: mockMessagingSystem, + messenger: mockMessagingSystem, batchId, txDataByType, updateTransactionFn: mockUpdateTransactionFn, @@ -1518,7 +1518,7 @@ describe('Bridge Status Controller Transaction Utils', () => { }; findAndUpdateTransactionsInBatch({ - messagingSystem: mockMessagingSystem, + messenger: mockMessagingSystem, batchId, txDataByType, updateTransactionFn: mockUpdateTransactionFn, @@ -1552,7 +1552,7 @@ describe('Bridge Status Controller Transaction Utils', () => { }; findAndUpdateTransactionsInBatch({ - messagingSystem: mockMessagingSystem, + messenger: mockMessagingSystem, batchId, txDataByType, updateTransactionFn: mockUpdateTransactionFn, @@ -1590,7 +1590,7 @@ describe('Bridge Status Controller Transaction Utils', () => { }; findAndUpdateTransactionsInBatch({ - messagingSystem: mockMessagingSystem, + messenger: mockMessagingSystem, batchId, txDataByType, updateTransactionFn: mockUpdateTransactionFn, @@ -1632,7 +1632,7 @@ describe('Bridge Status Controller Transaction Utils', () => { }; findAndUpdateTransactionsInBatch({ - messagingSystem: mockMessagingSystem, + messenger: mockMessagingSystem, batchId, txDataByType, updateTransactionFn: mockUpdateTransactionFn, @@ -1662,7 +1662,7 @@ describe('Bridge Status Controller Transaction Utils', () => { // Test with bridge transaction (not swap) findAndUpdateTransactionsInBatch({ - messagingSystem: mockMessagingSystem, + messenger: mockMessagingSystem, batchId, txDataByType, updateTransactionFn: mockUpdateTransactionFn, diff --git a/packages/bridge-status-controller/src/utils/transaction.ts b/packages/bridge-status-controller/src/utils/transaction.ts index 5e81afbf42f..05ee5fed206 100644 --- a/packages/bridge-status-controller/src/utils/transaction.ts +++ b/packages/bridge-status-controller/src/utils/transaction.ts @@ -246,7 +246,7 @@ export const toBatchTxParams = ( }; export const getAddTransactionBatchParams = async ({ - messagingSystem, + messenger, isBridgeTx, approval, resetApproval, @@ -263,7 +263,7 @@ export const getAddTransactionBatchParams = async ({ requireApproval = false, estimateGasFeeFn, }: { - messagingSystem: BridgeStatusControllerMessenger; + messenger: BridgeStatusControllerMessenger; isBridgeTx: boolean; trade: TxData; quoteResponse: Omit & QuoteMetadata; @@ -273,7 +273,7 @@ export const getAddTransactionBatchParams = async ({ requireApproval?: boolean; }) => { const isGasless = gasIncluded || gasless7702; - const selectedAccount = messagingSystem.call( + const selectedAccount = messenger.call( 'AccountsController:getAccountByAddress', trade.from, ); @@ -283,7 +283,7 @@ export const getAddTransactionBatchParams = async ({ ); } const hexChainId = formatChainIdToHex(trade.chainId); - const networkClientId = messagingSystem.call( + const networkClientId = messenger.call( 'NetworkController:findNetworkClientIdByChainId', hexChainId, ); @@ -295,7 +295,7 @@ export const getAddTransactionBatchParams = async ({ if (resetApproval) { const gasFees = await calculateGasFees( disable7702, - messagingSystem, + messenger, estimateGasFeeFn, resetApproval, networkClientId, @@ -312,7 +312,7 @@ export const getAddTransactionBatchParams = async ({ if (approval) { const gasFees = await calculateGasFees( disable7702, - messagingSystem, + messenger, estimateGasFeeFn, approval, networkClientId, @@ -328,7 +328,7 @@ export const getAddTransactionBatchParams = async ({ } const gasFees = await calculateGasFees( disable7702, - messagingSystem, + messenger, estimateGasFeeFn, trade, networkClientId, @@ -358,19 +358,17 @@ export const getAddTransactionBatchParams = async ({ }; export const findAndUpdateTransactionsInBatch = ({ - messagingSystem, + messenger, updateTransactionFn, batchId, txDataByType, }: { - messagingSystem: BridgeStatusControllerMessenger; + messenger: BridgeStatusControllerMessenger; updateTransactionFn: typeof TransactionController.prototype.updateTransaction; batchId: string; txDataByType: { [key in TransactionType]?: string }; }) => { - const txs = messagingSystem.call( - 'TransactionController:getState', - ).transactions; + const txs = messenger.call('TransactionController:getState').transactions; const txBatch: { approvalMeta?: TransactionMeta; tradeMeta?: TransactionMeta; From 19c7d6aee70ba44b8bcccf426f87ee5144b17295 Mon Sep 17 00:00:00 2001 From: Michele Esposito Date: Wed, 3 Sep 2025 21:58:21 +0200 Subject: [PATCH 18/69] migrate `TokenDetectionController` messenger --- .../src/TokenDetectionController.test.ts | 56 +++++++++++++---- .../src/TokenDetectionController.ts | 63 +++++++++---------- 2 files changed, 74 insertions(+), 45 deletions(-) diff --git a/packages/assets-controllers/src/TokenDetectionController.test.ts b/packages/assets-controllers/src/TokenDetectionController.test.ts index f112e984cd2..8667f7516cb 100644 --- a/packages/assets-controllers/src/TokenDetectionController.test.ts +++ b/packages/assets-controllers/src/TokenDetectionController.test.ts @@ -1,5 +1,4 @@ import type { AddApprovalRequest } from '@metamask/approval-controller'; -import { Messenger } from '@metamask/base-controller'; import { ChainId, NetworkType, @@ -8,6 +7,13 @@ import { } from '@metamask/controller-utils'; import type { KeyringControllerState } from '@metamask/keyring-controller'; import type { InternalAccount } from '@metamask/keyring-internal-api'; +import { + MOCK_ANY_NAMESPACE, + Messenger, + MessengerActions, + MessengerEvents, + MockAnyNamespace, +} from '@metamask/messenger'; import { getDefaultNetworkControllerState, RpcEndpointType, @@ -150,23 +156,48 @@ const mockNetworkConfigurations: Record = { }, }; -type MainMessenger = Messenger< - AllowedActions | AddApprovalRequest, - AllowedEvents +type AllTokenDetectionControllerActions = + MessengerActions; + +type AllTokenDetectionControllerEvents = + MessengerEvents; + +type RootMessenger = Messenger< + MockAnyNamespace, + AllTokenDetectionControllerActions, + AllTokenDetectionControllerEvents >; +/** + * Builds a root messenger for testing. + * + * @returns The root messenger. + */ +function buildRootMessenger(): RootMessenger { + return new Messenger({ namespace: MOCK_ANY_NAMESPACE }); +} + /** * Builds a messenger that `TokenDetectionController` can use to communicate with other controllers. * - * @param messenger - The main messenger. - * @returns The restricted messenger. + * @param messenger - The root messenger. + * @returns The controller messenger. */ function buildTokenDetectionControllerMessenger( - messenger: MainMessenger = new Messenger(), + messenger = buildRootMessenger(), ): TokenDetectionControllerMessenger { - return messenger.getRestricted({ - name: controllerName, - allowedActions: [ + const tokenDetectionControllerMessenger = new Messenger< + 'TokenDetectionController', + AllTokenDetectionControllerActions, + AllTokenDetectionControllerEvents, + RootMessenger + >({ + namespace: controllerName, + parent: messenger, + }); + messenger.delegate({ + messenger: tokenDetectionControllerMessenger, + actions: [ 'AccountsController:getAccount', 'AccountsController:getSelectedAccount', 'KeyringController:getState', @@ -180,7 +211,7 @@ function buildTokenDetectionControllerMessenger( 'TokensController:addTokens', 'NetworkController:findNetworkClientIdByChainId', ], - allowedEvents: [ + events: [ 'AccountsController:selectedEvmAccountChange', 'KeyringController:lock', 'KeyringController:unlock', @@ -190,6 +221,7 @@ function buildTokenDetectionControllerMessenger( 'TransactionController:transactionConfirmed', ], }); + return tokenDetectionControllerMessenger; } const mockMultiChainAccountsService = () => { @@ -3625,7 +3657,7 @@ async function withController( ): Promise { const [{ ...rest }, fn] = args.length === 2 ? args : [{}, args[0]]; const { options, isKeyringUnlocked, mocks } = rest; - const messenger = new Messenger(); + const messenger = buildRootMessenger(); const mockGetAccount = jest.fn(); messenger.registerActionHandler( diff --git a/packages/assets-controllers/src/TokenDetectionController.ts b/packages/assets-controllers/src/TokenDetectionController.ts index c577af329a2..399a9e83c5a 100644 --- a/packages/assets-controllers/src/TokenDetectionController.ts +++ b/packages/assets-controllers/src/TokenDetectionController.ts @@ -4,10 +4,9 @@ import type { AccountsControllerSelectedEvmAccountChangeEvent, } from '@metamask/accounts-controller'; import type { - RestrictedMessenger, ControllerGetStateAction, ControllerStateChangeEvent, -} from '@metamask/base-controller'; +} from '@metamask/base-controller/next'; import contractMap from '@metamask/contract-metadata'; import { ASSET_TYPES, @@ -21,6 +20,7 @@ import type { KeyringControllerLockEvent, KeyringControllerUnlockEvent, } from '@metamask/keyring-controller'; +import type { Messenger } from '@metamask/messenger'; import type { NetworkClientId, NetworkControllerFindNetworkClientIdByChainIdAction, @@ -150,12 +150,10 @@ export type AllowedEvents = | PreferencesControllerStateChangeEvent | TransactionControllerTransactionConfirmedEvent; -export type TokenDetectionControllerMessenger = RestrictedMessenger< +export type TokenDetectionControllerMessenger = Messenger< typeof controllerName, TokenDetectionControllerActions | AllowedActions, - TokenDetectionControllerEvents | AllowedEvents, - AllowedActions['type'], - AllowedEvents['type'] + TokenDetectionControllerEvents | AllowedEvents >; /** The input to start polling for the {@link TokenDetectionController} */ @@ -269,7 +267,7 @@ export class TokenDetectionController extends StaticIntervalPollingController { + this.messenger.subscribe('KeyringController:unlock', async () => { this.#isUnlocked = true; await this.#restartTokenDetection(); }); - this.messagingSystem.subscribe('KeyringController:lock', () => { + this.messenger.subscribe('KeyringController:lock', () => { this.#isUnlocked = false; this.#stopPolling(); }); - this.messagingSystem.subscribe( + this.messenger.subscribe( 'TokenListController:stateChange', // TODO: Either fix this lint violation or explain why it's necessary to ignore. // eslint-disable-next-line @typescript-eslint/no-misused-promises @@ -388,7 +385,7 @@ export class TokenDetectionController extends StaticIntervalPollingController { - const { networkConfigurationsByChainId } = this.messagingSystem.call( + const { networkConfigurationsByChainId } = this.messenger.call( 'NetworkController:getState', ); @@ -429,7 +426,7 @@ export class TokenDetectionController extends StaticIntervalPollingController { await this.detectTokens({ @@ -526,10 +523,10 @@ export class TokenDetectionController extends StaticIntervalPollingController Date: Wed, 3 Sep 2025 21:52:53 +0200 Subject: [PATCH 19/69] migrate `DeFiPositionsController` messenger --- .../DeFiPositionsController.test.ts | 48 +++++++++++++------ .../DeFiPositionsController.ts | 22 ++++----- 2 files changed, 43 insertions(+), 27 deletions(-) diff --git a/packages/assets-controllers/src/DeFiPositionsController/DeFiPositionsController.test.ts b/packages/assets-controllers/src/DeFiPositionsController/DeFiPositionsController.test.ts index 937d4626697..40378e76dda 100644 --- a/packages/assets-controllers/src/DeFiPositionsController/DeFiPositionsController.test.ts +++ b/packages/assets-controllers/src/DeFiPositionsController/DeFiPositionsController.test.ts @@ -1,4 +1,11 @@ import { BtcAccountType } from '@metamask/keyring-api'; +import { + MOCK_ANY_NAMESPACE, + Messenger, + type MessengerActions, + type MessengerEvents, + type MockAnyNamespace, +} from '@metamask/messenger'; import * as calculateDefiMetrics from './calculate-defi-metrics'; import type { DeFiPositionsControllerMessenger } from './DeFiPositionsController'; @@ -10,11 +17,6 @@ import * as fetchPositions from './fetch-positions'; import * as groupDeFiPositions from './group-defi-positions'; import { flushPromises } from '../../../../tests/helpers'; import { createMockInternalAccount } from '../../../accounts-controller/src/tests/mocks'; -import { Messenger } from '../../../base-controller/src/Messenger'; -import type { - ExtractAvailableAction, - ExtractAvailableEvent, -} from '../../../base-controller/tests/helpers'; import type { InternalAccount, TransactionMeta, @@ -35,9 +37,16 @@ const OWNER_ACCOUNTS = [ }), ]; -type MainMessenger = Messenger< - ExtractAvailableAction, - ExtractAvailableEvent +type AllDefiPositionsControllerActions = + MessengerActions; + +type AllDefiPositionsControllerEvents = + MessengerEvents; + +type RootMessenger = Messenger< + MockAnyNamespace, + AllDefiPositionsControllerActions, + AllDefiPositionsControllerEvents >; /** @@ -64,7 +73,9 @@ function setupController({ mockCalculateDefiMetrics?: jest.Mock; mockTrackEvent?: jest.Mock; } = {}) { - const messenger: MainMessenger = new Messenger(); + const messenger: RootMessenger = new Messenger({ + namespace: MOCK_ANY_NAMESPACE, + }); const mockListAccounts = jest.fn().mockReturnValue(OWNER_ACCOUNTS); messenger.registerActionHandler( @@ -72,10 +83,19 @@ function setupController({ mockListAccounts, ); - const restrictedMessenger = messenger.getRestricted({ - name: 'DeFiPositionsController', - allowedActions: ['AccountsController:listAccounts'], - allowedEvents: [ + const defiPositionControllerMessenger = new Messenger< + 'DeFiPositionsController', + AllDefiPositionsControllerActions, + AllDefiPositionsControllerEvents, + RootMessenger + >({ + namespace: 'DeFiPositionsController', + parent: messenger, + }); + messenger.delegate({ + messenger: defiPositionControllerMessenger, + actions: ['AccountsController:listAccounts'], + events: [ 'KeyringController:unlock', 'KeyringController:lock', 'TransactionController:transactionConfirmed', @@ -104,7 +124,7 @@ function setupController({ groupDeFiPositionsSpy.mockImplementation(mockGroupDeFiPositions); const controller = new DeFiPositionsController({ - messenger: restrictedMessenger, + messenger: defiPositionControllerMessenger, isEnabled, trackEvent: mockTrackEvent, }); diff --git a/packages/assets-controllers/src/DeFiPositionsController/DeFiPositionsController.ts b/packages/assets-controllers/src/DeFiPositionsController/DeFiPositionsController.ts index 0d31dabd664..612c86fd582 100644 --- a/packages/assets-controllers/src/DeFiPositionsController/DeFiPositionsController.ts +++ b/packages/assets-controllers/src/DeFiPositionsController/DeFiPositionsController.ts @@ -5,11 +5,11 @@ import type { import type { ControllerGetStateAction, ControllerStateChangeEvent, - RestrictedMessenger, StateMetadata, -} from '@metamask/base-controller'; +} from '@metamask/base-controller/next'; import type { KeyringControllerUnlockEvent } from '@metamask/keyring-controller'; import type { KeyringControllerLockEvent } from '@metamask/keyring-controller'; +import type { Messenger } from '@metamask/messenger'; import { StaticIntervalPollingController } from '@metamask/polling-controller'; import type { TransactionControllerTransactionConfirmedEvent } from '@metamask/transaction-controller'; import type { Hex } from '@metamask/utils'; @@ -119,12 +119,10 @@ export type AllowedEvents = /** * The messenger of the {@link DeFiPositionsController}. */ -export type DeFiPositionsControllerMessenger = RestrictedMessenger< +export type DeFiPositionsControllerMessenger = Messenger< typeof controllerName, DeFiPositionsControllerActions | AllowedActions, - DeFiPositionsControllerEvents | AllowedEvents, - AllowedActions['type'], - AllowedEvents['type'] + DeFiPositionsControllerEvents | AllowedEvents >; /** @@ -172,15 +170,15 @@ export class DeFiPositionsController extends StaticIntervalPollingController()< this.#fetchPositions = buildPositionFetcher(); this.#isEnabled = isEnabled; - this.messagingSystem.subscribe('KeyringController:unlock', () => { + this.messenger.subscribe('KeyringController:unlock', () => { this.startPolling(null); }); - this.messagingSystem.subscribe('KeyringController:lock', () => { + this.messenger.subscribe('KeyringController:lock', () => { this.stopAllPolling(); }); - this.messagingSystem.subscribe( + this.messenger.subscribe( 'TransactionController:transactionConfirmed', async (transactionMeta) => { if (!this.#isEnabled()) { @@ -191,7 +189,7 @@ export class DeFiPositionsController extends StaticIntervalPollingController()< }, ); - this.messagingSystem.subscribe( + this.messenger.subscribe( 'AccountsController:accountAdded', async (account) => { if (!this.#isEnabled() || !account.type.startsWith('eip155:')) { @@ -210,9 +208,7 @@ export class DeFiPositionsController extends StaticIntervalPollingController()< return; } - const accounts = this.messagingSystem.call( - 'AccountsController:listAccounts', - ); + const accounts = this.messenger.call('AccountsController:listAccounts'); const initialResult: { accountAddress: string; From ae155459be41defec6bd2a9542ea47033798b729 Mon Sep 17 00:00:00 2001 From: Michele Esposito Date: Wed, 3 Sep 2025 21:53:06 +0200 Subject: [PATCH 20/69] migrate `MultichainAssetsRatesController` messenger --- .../MultichainAssetsRatesController.test.ts | 91 ++++++++++++++----- .../MultichainAssetsRatesController.ts | 36 +++----- 2 files changed, 82 insertions(+), 45 deletions(-) diff --git a/packages/assets-controllers/src/MultichainAssetsRatesController/MultichainAssetsRatesController.test.ts b/packages/assets-controllers/src/MultichainAssetsRatesController/MultichainAssetsRatesController.test.ts index 135ce11da97..b22ccb79e5c 100644 --- a/packages/assets-controllers/src/MultichainAssetsRatesController/MultichainAssetsRatesController.test.ts +++ b/packages/assets-controllers/src/MultichainAssetsRatesController/MultichainAssetsRatesController.test.ts @@ -1,21 +1,40 @@ -import { Messenger } from '@metamask/base-controller'; import { SolScope } from '@metamask/keyring-api'; import { SolMethod } from '@metamask/keyring-api'; import { SolAccountType } from '@metamask/keyring-api'; import { KeyringTypes } from '@metamask/keyring-controller'; import type { InternalAccount } from '@metamask/keyring-internal-api'; import { KeyringClient } from '@metamask/keyring-snap-client'; +import { + MOCK_ANY_NAMESPACE, + Messenger, + type MessengerActions, + type MessengerEvents, + type MockAnyNamespace, +} from '@metamask/messenger'; import type { OnAssetHistoricalPriceResponse } from '@metamask/snaps-sdk'; import { useFakeTimers } from 'sinon'; import { v4 as uuidv4 } from 'uuid'; import { MultichainAssetsRatesController } from '.'; import { + type MultichainAssetsRatesControllerMessenger, type AllowedActions, type AllowedEvents, } from './MultichainAssetsRatesController'; import { advanceTime } from '../../../../tests/helpers'; +type AllMultichainAssetsRateControllerActions = + MessengerActions; + +type AllMultichainAssetsRateControllerEvents = + MessengerEvents; + +type RootMessenger = Messenger< + MockAnyNamespace, + AllMultichainAssetsRateControllerActions, + AllMultichainAssetsRateControllerEvents +>; + // A fake non‑EVM account (with Snap metadata) that meets the controller’s criteria. const fakeNonEvmAccount: InternalAccount = { id: 'account1', @@ -118,7 +137,9 @@ const setupController = ({ >; accountsAssets?: InternalAccount[]; } = {}) => { - const messenger = new Messenger(); + const messenger: RootMessenger = new Messenger({ + namespace: MOCK_ANY_NAMESPACE, + }); messenger.registerActionHandler( 'MultichainAssetsController:getState', @@ -155,16 +176,25 @@ const setupController = ({ currentCurrency: 'USD', })); - const multichainAssetsRatesControllerMessenger = messenger.getRestricted({ - name: 'MultichainAssetsRatesController', - allowedActions: [ + const multichainAssetsRatesControllerMessenger: Messenger< + 'MultichainAssetsRatesController', + AllMultichainAssetsRateControllerActions, + AllMultichainAssetsRateControllerEvents, + RootMessenger + > = new Messenger({ + namespace: 'MultichainAssetsRatesController', + parent: messenger, + }); + messenger.delegate({ + messenger: multichainAssetsRatesControllerMessenger, + actions: [ 'AccountsController:listMultichainAccounts', 'SnapController:handleRequest', 'CurrencyRateController:getState', 'MultichainAssetsController:getState', 'AccountsController:getSelectedMultichainAccount', ], - allowedEvents: [ + events: [ 'AccountsController:accountAdded', 'KeyringController:lock', 'KeyringController:unlock', @@ -913,7 +943,9 @@ describe('MultichainAssetsRatesController', () => { }; // Set up controller with custom accounts and assets configuration - const messenger = new Messenger(); + const messenger: RootMessenger = new Messenger({ + namespace: MOCK_ANY_NAMESPACE, + }); // Mock MultichainAssetsController state with one account having no assets messenger.registerActionHandler( @@ -970,24 +1002,35 @@ describe('MultichainAssetsRatesController', () => { snapHandler, ); + const multichainAssetsRatesControllerMessenger = new Messenger< + 'MultichainAssetsRatesController', + AllMultichainAssetsRateControllerActions, + AllMultichainAssetsRateControllerEvents, + RootMessenger + >({ + namespace: 'MultichainAssetsRatesController', + parent: messenger, + }); + messenger.delegate({ + messenger: multichainAssetsRatesControllerMessenger, + actions: [ + 'MultichainAssetsController:getState', + 'AccountsController:listMultichainAccounts', + 'AccountsController:getSelectedMultichainAccount', + 'CurrencyRateController:getState', + 'SnapController:handleRequest', + ], + events: [ + 'KeyringController:lock', + 'KeyringController:unlock', + 'AccountsController:accountAdded', + 'CurrencyRateController:stateChange', + 'MultichainAssetsController:accountAssetListUpdated', + ], + }); + const controller = new MultichainAssetsRatesController({ - messenger: messenger.getRestricted({ - name: 'MultichainAssetsRatesController', - allowedActions: [ - 'MultichainAssetsController:getState', - 'AccountsController:listMultichainAccounts', - 'AccountsController:getSelectedMultichainAccount', - 'CurrencyRateController:getState', - 'SnapController:handleRequest', - ], - allowedEvents: [ - 'KeyringController:lock', - 'KeyringController:unlock', - 'AccountsController:accountAdded', - 'CurrencyRateController:stateChange', - 'MultichainAssetsController:accountAssetListUpdated', - ], - }), + messenger: multichainAssetsRatesControllerMessenger, }); await controller.updateAssetsRates(); diff --git a/packages/assets-controllers/src/MultichainAssetsRatesController/MultichainAssetsRatesController.ts b/packages/assets-controllers/src/MultichainAssetsRatesController/MultichainAssetsRatesController.ts index e0177b32b16..d2e2217566e 100644 --- a/packages/assets-controllers/src/MultichainAssetsRatesController/MultichainAssetsRatesController.ts +++ b/packages/assets-controllers/src/MultichainAssetsRatesController/MultichainAssetsRatesController.ts @@ -4,16 +4,16 @@ import type { AccountsControllerGetSelectedMultichainAccountAction, } from '@metamask/accounts-controller'; import type { - RestrictedMessenger, ControllerStateChangeEvent, ControllerGetStateAction, -} from '@metamask/base-controller'; +} from '@metamask/base-controller/next'; import { type CaipAssetType, isEvmAccountType } from '@metamask/keyring-api'; import type { KeyringControllerLockEvent, KeyringControllerUnlockEvent, } from '@metamask/keyring-controller'; import type { InternalAccount } from '@metamask/keyring-internal-api'; +import type { Messenger } from '@metamask/messenger'; import { StaticIntervalPollingController } from '@metamask/polling-controller'; import type { HandleSnapRequest } from '@metamask/snaps-controllers'; import type { @@ -144,12 +144,10 @@ export type AllowedEvents = /** * Messenger type for the MultichainAssetsRatesController. */ -export type MultichainAssetsRatesControllerMessenger = RestrictedMessenger< +export type MultichainAssetsRatesControllerMessenger = Messenger< typeof controllerName, MultichainAssetsRatesControllerActions | AllowedActions, - MultichainAssetsRatesControllerEvents | AllowedEvents, - AllowedActions['type'], - AllowedEvents['type'] + MultichainAssetsRatesControllerEvents | AllowedEvents >; /** @@ -195,7 +193,7 @@ export class MultichainAssetsRatesController extends StaticIntervalPollingContro * @param options - Constructor options. * @param options.interval - The polling interval in milliseconds. * @param options.state - The initial state. - * @param options.messenger - A reference to the messaging system. + * @param options.messenger - A reference to the messenger. */ constructor({ interval = 18000, @@ -219,22 +217,22 @@ export class MultichainAssetsRatesController extends StaticIntervalPollingContro this.setIntervalLength(interval); // Subscribe to keyring lock/unlock events. - this.messagingSystem.subscribe('KeyringController:lock', () => { + this.messenger.subscribe('KeyringController:lock', () => { this.#isUnlocked = false; }); - this.messagingSystem.subscribe('KeyringController:unlock', () => { + this.messenger.subscribe('KeyringController:unlock', () => { this.#isUnlocked = true; }); - ({ accountsAssets: this.#accountsAssets } = this.messagingSystem.call( + ({ accountsAssets: this.#accountsAssets } = this.messenger.call( 'MultichainAssetsController:getState', )); - ({ currentCurrency: this.#currentCurrency } = this.messagingSystem.call( + ({ currentCurrency: this.#currentCurrency } = this.messenger.call( 'CurrencyRateController:getState', )); - this.messagingSystem.subscribe( + this.messenger.subscribe( 'CurrencyRateController:stateChange', async (currentCurrency: string) => { this.#currentCurrency = currentCurrency; @@ -244,7 +242,7 @@ export class MultichainAssetsRatesController extends StaticIntervalPollingContro currencyRateControllerState.currentCurrency, ); - this.messagingSystem.subscribe( + this.messenger.subscribe( 'MultichainAssetsController:accountAssetListUpdated', async ({ assets }) => { const newAccountAssets = Object.entries(assets).map( @@ -295,9 +293,7 @@ export class MultichainAssetsRatesController extends StaticIntervalPollingContro * @returns An array of internal accounts. */ #listMultichainAccounts(): InternalAccount[] { - return this.messagingSystem.call( - 'AccountsController:listMultichainAccounts', - ); + return this.messenger.call('AccountsController:listMultichainAccounts'); } /** @@ -425,11 +421,9 @@ export class MultichainAssetsRatesController extends StaticIntervalPollingContro const selectedAccount = account ?? - this.messagingSystem.call( - 'AccountsController:getSelectedMultichainAccount', - ); + this.messenger.call('AccountsController:getSelectedMultichainAccount'); try { - const historicalPricesResponse = await this.messagingSystem.call( + const historicalPricesResponse = await this.messenger.call( 'SnapController:handleRequest', { snapId: selectedAccount?.metadata.snap?.id as SnapId, @@ -660,7 +654,7 @@ export class MultichainAssetsRatesController extends StaticIntervalPollingContro | undefined > { try { - return (await this.messagingSystem.call('SnapController:handleRequest', { + return (await this.messenger.call('SnapController:handleRequest', { snapId, origin: 'metamask', handler, From c70832cf12fb4a356fa4bf50eceb702b9e94ac24 Mon Sep 17 00:00:00 2001 From: Michele Esposito Date: Wed, 3 Sep 2025 21:53:20 +0200 Subject: [PATCH 21/69] migrate `AccountTrackerController` messenger --- .../src/AccountTrackerController.test.ts | 54 ++++++++++++------- .../src/AccountTrackerController.ts | 47 ++++++++-------- 2 files changed, 57 insertions(+), 44 deletions(-) diff --git a/packages/assets-controllers/src/AccountTrackerController.test.ts b/packages/assets-controllers/src/AccountTrackerController.test.ts index 0feb16c36de..befaedbae97 100644 --- a/packages/assets-controllers/src/AccountTrackerController.test.ts +++ b/packages/assets-controllers/src/AccountTrackerController.test.ts @@ -1,6 +1,12 @@ -import { Messenger } from '@metamask/base-controller'; import { query, toChecksumHexAddress } from '@metamask/controller-utils'; import type { InternalAccount } from '@metamask/keyring-internal-api'; +import { + MOCK_ANY_NAMESPACE, + Messenger, + type MessengerActions, + type MessengerEvents, + type MockAnyNamespace, +} from '@metamask/messenger'; import { type NetworkClientId, type NetworkClientConfiguration, @@ -10,25 +16,29 @@ import { getDefaultPreferencesState } from '@metamask/preferences-controller'; import BN from 'bn.js'; import { useFakeTimers, type SinonFakeTimers } from 'sinon'; -import type { - AccountTrackerControllerMessenger, - AllowedActions, - AllowedEvents, -} from './AccountTrackerController'; +import type { AccountTrackerControllerMessenger } from './AccountTrackerController'; import { AccountTrackerController } from './AccountTrackerController'; import { getTokenBalancesForMultipleAddresses } from './multicall'; import { FakeProvider } from '../../../tests/fake-provider'; import { advanceTime } from '../../../tests/helpers'; import { createMockInternalAccount } from '../../accounts-controller/src/tests/mocks'; -import type { - ExtractAvailableAction, - ExtractAvailableEvent, -} from '../../base-controller/tests/helpers'; import { buildCustomNetworkClientConfiguration, buildMockGetNetworkClientById, } from '../../network-controller/tests/helpers'; +type AllAccountTrackerControllerActions = + MessengerActions; + +type AllAccountTrackerControllerEvents = + MessengerEvents; + +type RootMessenger = Messenger< + MockAnyNamespace, + AllAccountTrackerControllerActions, + AllAccountTrackerControllerEvents +>; + jest.mock('@metamask/controller-utils', () => { return { ...jest.requireActual('@metamask/controller-utils'), @@ -1209,10 +1219,9 @@ async function withController( testFunction, ] = args.length === 2 ? args : [{}, args[0]]; - const messenger = new Messenger< - ExtractAvailableAction | AllowedActions, - ExtractAvailableEvent | AllowedEvents - >(); + const messenger: RootMessenger = new Messenger({ + namespace: MOCK_ANY_NAMESPACE, + }); const mockGetSelectedAccount = jest.fn().mockReturnValue(selectedAccount); messenger.registerActionHandler( @@ -1318,16 +1327,25 @@ async function withController( mockNetworkState, ); - const accountTrackerMessenger = messenger.getRestricted({ - name: 'AccountTrackerController', - allowedActions: [ + const accountTrackerMessenger = new Messenger< + 'AccountTrackerController', + AllAccountTrackerControllerActions, + AllAccountTrackerControllerEvents, + RootMessenger + >({ + namespace: 'AccountTrackerController', + parent: messenger, + }); + messenger.delegate({ + messenger: accountTrackerMessenger, + actions: [ 'NetworkController:getNetworkClientById', 'NetworkController:getState', 'PreferencesController:getState', 'AccountsController:getSelectedAccount', 'AccountsController:listAccounts', ], - allowedEvents: ['AccountsController:selectedEvmAccountChange'], + events: ['AccountsController:selectedEvmAccountChange'], }); const triggerSelectedAccountChange = (account: InternalAccount) => { diff --git a/packages/assets-controllers/src/AccountTrackerController.ts b/packages/assets-controllers/src/AccountTrackerController.ts index 907f99b6098..294f8e5ad4f 100644 --- a/packages/assets-controllers/src/AccountTrackerController.ts +++ b/packages/assets-controllers/src/AccountTrackerController.ts @@ -8,14 +8,14 @@ import type { import type { ControllerStateChangeEvent, ControllerGetStateAction, - RestrictedMessenger, -} from '@metamask/base-controller'; +} from '@metamask/base-controller/next'; import { query, safelyExecuteWithTimeout, toChecksumHexAddress, } from '@metamask/controller-utils'; import EthQuery from '@metamask/eth-query'; +import type { Messenger } from '@metamask/messenger'; import type { NetworkClient, NetworkClientId, @@ -194,12 +194,10 @@ export type AllowedEvents = /** * The messenger of the {@link AccountTrackerController}. */ -export type AccountTrackerControllerMessenger = RestrictedMessenger< +export type AccountTrackerControllerMessenger = Messenger< typeof controllerName, AccountTrackerControllerActions | AllowedActions, - AccountTrackerControllerEvents | AllowedEvents, - AllowedActions['type'], - AllowedEvents['type'] + AccountTrackerControllerEvents | AllowedEvents >; /** The input to start polling for the {@link AccountTrackerController} */ @@ -229,7 +227,7 @@ export class AccountTrackerController extends StaticIntervalPollingController { if (newAddress !== prevAddress) { @@ -307,12 +305,12 @@ export class AccountTrackerController extends StaticIntervalPollingController toChecksumHexAddress(internalAccount.address), @@ -366,12 +364,12 @@ export class AccountTrackerController extends StaticIntervalPollingController { - const { networkConfigurationsByChainId } = this.messagingSystem.call( + const { networkConfigurationsByChainId } = this.messenger.call( 'NetworkController:getState', ); const cfg = networkConfigurationsByChainId[chainId]; const { networkClientId } = cfg.rpcEndpoints[cfg.defaultRpcEndpointIndex]; - const client = this.messagingSystem.call( + const client = this.messenger.call( 'NetworkController:getNetworkClientById', networkClientId, ); @@ -379,12 +377,12 @@ export class AccountTrackerController extends StaticIntervalPollingController { - const { networkConfigurationsByChainId } = this.messagingSystem.call( + const { networkConfigurationsByChainId } = this.messenger.call( 'NetworkController:getState', ); const cfg = networkConfigurationsByChainId[chainId]; const { networkClientId } = cfg.rpcEndpoints[cfg.defaultRpcEndpointIndex]; - return this.messagingSystem.call( + return this.messenger.call( 'NetworkController:getNetworkClientById', networkClientId, ); @@ -400,13 +398,12 @@ export class AccountTrackerController extends StaticIntervalPollingController Date: Wed, 3 Sep 2025 21:53:31 +0200 Subject: [PATCH 22/69] migrate `CurrencyRateController` messenger --- .../src/CurrencyRateController.test.ts | 102 ++++++++++-------- .../src/CurrencyRateController.ts | 12 +-- 2 files changed, 64 insertions(+), 50 deletions(-) diff --git a/packages/assets-controllers/src/CurrencyRateController.test.ts b/packages/assets-controllers/src/CurrencyRateController.test.ts index c927e9ca400..a713f387f6f 100644 --- a/packages/assets-controllers/src/CurrencyRateController.test.ts +++ b/packages/assets-controllers/src/CurrencyRateController.test.ts @@ -1,32 +1,43 @@ -import { Messenger } from '@metamask/base-controller'; import { ChainId, NetworkType, NetworksTicker, } from '@metamask/controller-utils'; -import type { NetworkControllerGetNetworkClientByIdAction } from '@metamask/network-controller'; +import { + MOCK_ANY_NAMESPACE, + Messenger, + type MessengerActions, + type MessengerEvents, + type MockAnyNamespace, +} from '@metamask/messenger'; import nock from 'nock'; import { useFakeTimers } from 'sinon'; import { advanceTime } from '../../../tests/helpers'; -import type { - CurrencyRateStateChange, - GetCurrencyRateState, -} from './CurrencyRateController'; +import type { CurrencyRateMessenger } from './CurrencyRateController'; import { CurrencyRateController } from './CurrencyRateController'; -const name = 'CurrencyRateController' as const; +const namespace = 'CurrencyRateController' as const; + +type AllCurrencyRateControllerActions = MessengerActions; + +type AllCurrencyRateControllerEvents = MessengerEvents; + +type RootMessenger = Messenger< + MockAnyNamespace, + AllCurrencyRateControllerActions, + AllCurrencyRateControllerEvents +>; /** - * Constructs a restricted messenger. + * Constructs a messenger for CurrencyRateController. * - * @returns A restricted messenger. + * @returns A controller messenger. */ -function getRestrictedMessenger() { - const messenger = new Messenger< - GetCurrencyRateState | NetworkControllerGetNetworkClientByIdAction, - CurrencyRateStateChange - >(); +function getCurrencyRateControllerMessenger(): CurrencyRateMessenger { + const messenger: RootMessenger = new Messenger({ + namespace: MOCK_ANY_NAMESPACE, + }); messenger.registerActionHandler( 'NetworkController:getNetworkClientById', jest.fn().mockImplementation((networkClientId) => { @@ -52,14 +63,19 @@ function getRestrictedMessenger() { } }), ); - return messenger.getRestricted< - typeof name, - NetworkControllerGetNetworkClientByIdAction['type'] + const currencyRateControllerMessenger = new Messenger< + typeof namespace, + AllCurrencyRateControllerActions, + AllCurrencyRateControllerEvents, + RootMessenger >({ - name, - allowedActions: ['NetworkController:getNetworkClientById'], - allowedEvents: [], + namespace, + }); + messenger.delegate({ + messenger: currencyRateControllerMessenger, + actions: ['NetworkController:getNetworkClientById'], }); + return currencyRateControllerMessenger; } const getStubbedDate = () => { @@ -77,7 +93,7 @@ describe('CurrencyRateController', () => { }); it('should set default state', () => { - const messenger = getRestrictedMessenger(); + const messenger = getCurrencyRateControllerMessenger(); const controller = new CurrencyRateController({ messenger }); expect(controller.state).toStrictEqual({ @@ -95,7 +111,7 @@ describe('CurrencyRateController', () => { }); it('should initialize with initial state', () => { - const messenger = getRestrictedMessenger(); + const messenger = getCurrencyRateControllerMessenger(); const existingState = { currentCurrency: 'rep' }; const controller = new CurrencyRateController({ messenger, @@ -118,7 +134,7 @@ describe('CurrencyRateController', () => { it('should not poll before being started', async () => { const fetchMultiExchangeRateStub = jest.fn(); - const messenger = getRestrictedMessenger(); + const messenger = getCurrencyRateControllerMessenger(); const controller = new CurrencyRateController({ interval: 100, fetchMultiExchangeRate: fetchMultiExchangeRateStub, @@ -150,7 +166,7 @@ describe('CurrencyRateController', () => { usd: 22, }, }); - const messenger = getRestrictedMessenger(); + const messenger = getCurrencyRateControllerMessenger(); const controller = new CurrencyRateController({ interval: 100, fetchMultiExchangeRate: fetchMultiExchangeRateStub, @@ -188,7 +204,7 @@ describe('CurrencyRateController', () => { it('should not poll after being stopped', async () => { const fetchMultiExchangeRateStub = jest.fn(); - const messenger = getRestrictedMessenger(); + const messenger = getCurrencyRateControllerMessenger(); const controller = new CurrencyRateController({ interval: 100, fetchMultiExchangeRate: fetchMultiExchangeRateStub, @@ -214,7 +230,7 @@ describe('CurrencyRateController', () => { it('should poll correctly after being started, stopped, and started again', async () => { const fetchMultiExchangeRateStub = jest.fn(); - const messenger = getRestrictedMessenger(); + const messenger = getCurrencyRateControllerMessenger(); const controller = new CurrencyRateController({ interval: 100, fetchMultiExchangeRate: fetchMultiExchangeRateStub, @@ -245,7 +261,7 @@ describe('CurrencyRateController', () => { const fetchMultiExchangeRateStub = jest .fn() .mockResolvedValue({ eth: { [currentCurrency]: 10, usd: 111 } }); - const messenger = getRestrictedMessenger(); + const messenger = getCurrencyRateControllerMessenger(); const controller = new CurrencyRateController({ interval: 10, fetchMultiExchangeRate: fetchMultiExchangeRateStub, @@ -297,7 +313,7 @@ describe('CurrencyRateController', () => { }, }; }); - const messenger = getRestrictedMessenger(); + const messenger = getCurrencyRateControllerMessenger(); const controller = new CurrencyRateController({ fetchMultiExchangeRate: fetchMultiExchangeRateStub, messenger, @@ -337,7 +353,7 @@ describe('CurrencyRateController', () => { eth: { [currentCurrency]: 10, usd: 11 }, btc: { [currentCurrency]: 10, usd: 11 }, }); - const messenger = getRestrictedMessenger(); + const messenger = getCurrencyRateControllerMessenger(); const controller = new CurrencyRateController({ interval: 10, fetchMultiExchangeRate: fetchMultiExchangeRateStub, @@ -394,7 +410,7 @@ describe('CurrencyRateController', () => { it('should add usd rate to state when includeUsdRate is configured true', async () => { const fetchMultiExchangeRateStub = jest.fn().mockResolvedValue({}); - const messenger = getRestrictedMessenger(); + const messenger = getCurrencyRateControllerMessenger(); const controller = new CurrencyRateController({ includeUsdRate: true, fetchMultiExchangeRate: fetchMultiExchangeRateStub, @@ -418,7 +434,7 @@ describe('CurrencyRateController', () => { .get('/data/pricemulti?fsyms=ETH&tsyms=xyz') .reply(200, { ETH: { XYZ: 2000.42 } }) .persist(); - const messenger = getRestrictedMessenger(); + const messenger = getCurrencyRateControllerMessenger(); const controller = new CurrencyRateController({ messenger, state: { currentCurrency: 'xyz' }, @@ -450,7 +466,7 @@ describe('CurrencyRateController', () => { }) .persist(); - const messenger = getRestrictedMessenger(); + const messenger = getCurrencyRateControllerMessenger(); const controller = new CurrencyRateController({ messenger, state: { currentCurrency: 'xyz' }, @@ -480,7 +496,7 @@ describe('CurrencyRateController', () => { }, }, }; - const messenger = getRestrictedMessenger(); + const messenger = getCurrencyRateControllerMessenger(); const controller = new CurrencyRateController({ messenger, state }); // Error should still be thrown @@ -505,7 +521,7 @@ describe('CurrencyRateController', () => { POL: { XYZ: 0.3 }, }) .persist(); - const messenger = getRestrictedMessenger(); + const messenger = getCurrencyRateControllerMessenger(); const controller = new CurrencyRateController({ messenger, state: { currentCurrency: 'xyz' }, @@ -548,7 +564,7 @@ describe('CurrencyRateController', () => { }) .persist(); - const messenger = getRestrictedMessenger(); + const messenger = getCurrencyRateControllerMessenger(); const controller = new CurrencyRateController({ messenger, state: { currentCurrency: 'xyz' }, @@ -576,7 +592,7 @@ describe('CurrencyRateController', () => { describe('useExternalServices', () => { it('should not fetch exchange rates when useExternalServices is false', async () => { const fetchMultiExchangeRateStub = jest.fn(); - const messenger = getRestrictedMessenger(); + const messenger = getCurrencyRateControllerMessenger(); const controller = new CurrencyRateController({ useExternalServices: () => false, fetchMultiExchangeRate: fetchMultiExchangeRateStub, @@ -600,7 +616,7 @@ describe('CurrencyRateController', () => { it('should not poll when useExternalServices is false', async () => { const fetchMultiExchangeRateStub = jest.fn(); - const messenger = getRestrictedMessenger(); + const messenger = getCurrencyRateControllerMessenger(); const controller = new CurrencyRateController({ useExternalServices: () => false, interval: 100, @@ -623,7 +639,7 @@ describe('CurrencyRateController', () => { it('should not fetch exchange rates when useExternalServices is false even with multiple currencies', async () => { const fetchMultiExchangeRateStub = jest.fn(); - const messenger = getRestrictedMessenger(); + const messenger = getCurrencyRateControllerMessenger(); const controller = new CurrencyRateController({ useExternalServices: () => false, fetchMultiExchangeRate: fetchMultiExchangeRateStub, @@ -647,7 +663,7 @@ describe('CurrencyRateController', () => { it('should not fetch exchange rates when useExternalServices is false even with testnet currencies', async () => { const fetchMultiExchangeRateStub = jest.fn(); - const messenger = getRestrictedMessenger(); + const messenger = getCurrencyRateControllerMessenger(); const controller = new CurrencyRateController({ useExternalServices: () => false, fetchMultiExchangeRate: fetchMultiExchangeRateStub, @@ -671,7 +687,7 @@ describe('CurrencyRateController', () => { it('should not fetch exchange rates when useExternalServices is false even with includeUsdRate true', async () => { const fetchMultiExchangeRateStub = jest.fn(); - const messenger = getRestrictedMessenger(); + const messenger = getCurrencyRateControllerMessenger(); const controller = new CurrencyRateController({ useExternalServices: () => false, includeUsdRate: true, @@ -699,7 +715,7 @@ describe('CurrencyRateController', () => { const fetchMultiExchangeRateStub = jest .fn() .mockResolvedValue({ eth: { usd: 2000, eur: 1800 } }); - const messenger = getRestrictedMessenger(); + const messenger = getCurrencyRateControllerMessenger(); const controller = new CurrencyRateController({ useExternalServices: () => true, fetchMultiExchangeRate: fetchMultiExchangeRateStub, @@ -731,7 +747,7 @@ describe('CurrencyRateController', () => { const fetchMultiExchangeRateStub = jest .fn() .mockResolvedValue({ eth: { usd: 2000, gbp: 1600 } }); - const messenger = getRestrictedMessenger(); + const messenger = getCurrencyRateControllerMessenger(); const controller = new CurrencyRateController({ fetchMultiExchangeRate: fetchMultiExchangeRateStub, messenger, @@ -761,7 +777,7 @@ describe('CurrencyRateController', () => { const fetchMultiExchangeRateStub = jest .fn() .mockRejectedValue(new Error('API Error')); - const messenger = getRestrictedMessenger(); + const messenger = getCurrencyRateControllerMessenger(); const controller = new CurrencyRateController({ useExternalServices: () => false, fetchMultiExchangeRate: fetchMultiExchangeRateStub, diff --git a/packages/assets-controllers/src/CurrencyRateController.ts b/packages/assets-controllers/src/CurrencyRateController.ts index ccff37886a2..12811f5b43e 100644 --- a/packages/assets-controllers/src/CurrencyRateController.ts +++ b/packages/assets-controllers/src/CurrencyRateController.ts @@ -1,12 +1,12 @@ import type { - RestrictedMessenger, ControllerGetStateAction, ControllerStateChangeEvent, -} from '@metamask/base-controller'; +} from '@metamask/base-controller/next'; import { TESTNET_TICKER_SYMBOLS, FALL_BACK_VS_CURRENCY, } from '@metamask/controller-utils'; +import type { Messenger } from '@metamask/messenger'; import type { NetworkControllerGetNetworkClientByIdAction } from '@metamask/network-controller'; import { StaticIntervalPollingController } from '@metamask/polling-controller'; import { Mutex } from 'async-mutex'; @@ -51,12 +51,10 @@ export type CurrencyRateControllerActions = GetCurrencyRateState; type AllowedActions = NetworkControllerGetNetworkClientByIdAction; -type CurrencyRateMessenger = RestrictedMessenger< +export type CurrencyRateMessenger = Messenger< typeof name, CurrencyRateControllerActions | AllowedActions, - CurrencyRateControllerEvents, - AllowedActions['type'], - never + CurrencyRateControllerEvents >; const metadata = { @@ -103,7 +101,7 @@ export class CurrencyRateController extends StaticIntervalPollingController Date: Wed, 3 Sep 2025 21:53:41 +0200 Subject: [PATCH 23/69] migrate `TokenBalancesController` messenger --- .../src/TokenBalancesController.test.ts | 57 ++++++++++++++----- .../src/TokenBalancesController.ts | 36 ++++++------ 2 files changed, 60 insertions(+), 33 deletions(-) diff --git a/packages/assets-controllers/src/TokenBalancesController.test.ts b/packages/assets-controllers/src/TokenBalancesController.test.ts index 637eda6a0a0..bc43e93f4b8 100644 --- a/packages/assets-controllers/src/TokenBalancesController.test.ts +++ b/packages/assets-controllers/src/TokenBalancesController.test.ts @@ -1,6 +1,12 @@ -import { Messenger } from '@metamask/base-controller'; import { toHex } from '@metamask/controller-utils'; import type { InternalAccount } from '@metamask/keyring-internal-api'; +import { + Messenger, + MOCK_ANY_NAMESPACE, + type MessengerActions, + type MessengerEvents, + type MockAnyNamespace, +} from '@metamask/messenger'; import type { NetworkState } from '@metamask/network-controller'; import type { PreferencesState } from '@metamask/preferences-controller'; import { CHAIN_IDS } from '@metamask/transaction-controller'; @@ -13,6 +19,7 @@ import type { AllowedEvents, TokenBalancesControllerActions, TokenBalancesControllerEvents, + TokenBalancesControllerMessenger, TokenBalancesControllerState, } from './TokenBalancesController'; import { TokenBalancesController } from './TokenBalancesController'; @@ -21,6 +28,18 @@ import { advanceTime } from '../../../tests/helpers'; import { createMockInternalAccount } from '../../accounts-controller/src/tests/mocks'; import type { RpcEndpoint } from '../../network-controller/src/NetworkController'; +type AllTokenBalancesControllerActions = + MessengerActions; + +type AllTokenBalancesControllerEvents = + MessengerEvents; + +type RootMessenger = Messenger< + MockAnyNamespace, + AllTokenBalancesControllerActions, + AllTokenBalancesControllerEvents +>; + // Mock safelyExecuteWithTimeout jest.mock('@metamask/controller-utils', () => ({ ...jest.requireActual('@metamask/controller-utils'), @@ -46,14 +65,22 @@ const setupController = ({ tokens?: Partial; listAccounts?: InternalAccount[]; } = {}) => { - const messenger = new Messenger< - TokenBalancesControllerActions | AllowedActions, - TokenBalancesControllerEvents | AllowedEvents - >(); - - const tokenBalancesMessenger = messenger.getRestricted({ - name: 'TokenBalancesController', - allowedActions: [ + const messenger: RootMessenger = new Messenger({ + namespace: MOCK_ANY_NAMESPACE, + }); + + const tokenBalancesControllerMessenger = new Messenger< + 'TokenBalancesController', + AllTokenBalancesControllerActions, + AllTokenBalancesControllerEvents, + RootMessenger + >({ + namespace: 'TokenBalancesController', + parent: messenger, + }); + messenger.delegate({ + messenger: tokenBalancesControllerMessenger, + actions: [ 'NetworkController:getState', 'NetworkController:getNetworkClientById', 'PreferencesController:getState', @@ -63,7 +90,7 @@ const setupController = ({ 'AccountTrackerController:updateNativeBalances', 'AccountTrackerController:updateStakedBalances', ], - allowedEvents: [ + events: [ 'NetworkController:stateChange', 'PreferencesController:stateChange', 'TokensController:stateChange', @@ -131,7 +158,7 @@ const setupController = ({ }), ); const controller = new TokenBalancesController({ - messenger: tokenBalancesMessenger, + messenger: tokenBalancesControllerMessenger, ...config, }); const updateSpy = jest.spyOn(controller, 'update' as never); @@ -140,6 +167,7 @@ const setupController = ({ controller, updateSpy, messenger, + tokenBalancesControllerMessenger, }; }; @@ -1134,7 +1162,7 @@ describe('TokenBalancesController', () => { const accountAddress = '0x1111111111111111111111111111111111111111'; const chainId = '0x1'; - const { controller, messenger } = setupController({ + const { controller, tokenBalancesControllerMessenger } = setupController({ config: { useAccountsAPI: false, allowExternalServices: () => true }, tokens: { allTokens: { @@ -1150,7 +1178,10 @@ describe('TokenBalancesController', () => { }); // Set up spy for event publishing - const publishSpy = jest.spyOn(messenger, 'publish'); + const publishSpy = jest.spyOn( + tokenBalancesControllerMessenger, + 'publish', + ); jest .spyOn(multicall, 'getTokenBalancesForMultipleAddresses') diff --git a/packages/assets-controllers/src/TokenBalancesController.ts b/packages/assets-controllers/src/TokenBalancesController.ts index 0555a044451..87577b9e8a1 100644 --- a/packages/assets-controllers/src/TokenBalancesController.ts +++ b/packages/assets-controllers/src/TokenBalancesController.ts @@ -6,8 +6,7 @@ import type { import type { ControllerGetStateAction, ControllerStateChangeEvent, - RestrictedMessenger, -} from '@metamask/base-controller'; +} from '@metamask/base-controller/next'; import { BNToHex, isValidHexAddress, @@ -15,6 +14,7 @@ import { toHex, } from '@metamask/controller-utils'; import type { KeyringControllerAccountRemovedEvent } from '@metamask/keyring-controller'; +import type { Messenger } from '@metamask/messenger'; import type { NetworkControllerGetNetworkClientByIdAction, NetworkControllerGetStateAction, @@ -104,12 +104,10 @@ export type AllowedEvents = | NetworkControllerStateChangeEvent | KeyringControllerAccountRemovedEvent; -export type TokenBalancesControllerMessenger = RestrictedMessenger< +export type TokenBalancesControllerMessenger = Messenger< typeof CONTROLLER, TokenBalancesControllerActions | AllowedActions, - TokenBalancesControllerEvents | AllowedEvents, - AllowedActions['type'], - AllowedEvents['type'] + TokenBalancesControllerEvents | AllowedEvents >; export type TokenBalancesControllerOptions = { @@ -186,13 +184,13 @@ export class TokenBalancesController extends StaticIntervalPollingController<{ this.setIntervalLength(interval); // initial token state & subscriptions - const { allTokens, allDetectedTokens } = this.messagingSystem.call( + const { allTokens, allDetectedTokens } = this.messenger.call( 'TokensController:getState', ); this.#allTokens = allTokens; this.#detectedTokens = allDetectedTokens; - this.messagingSystem.subscribe( + this.messenger.subscribe( 'TokensController:stateChange', (tokensState: TokensControllerState) => { this.#onTokensChanged(tokensState).catch((error) => { @@ -200,11 +198,11 @@ export class TokenBalancesController extends StaticIntervalPollingController<{ }); }, ); - this.messagingSystem.subscribe( + this.messenger.subscribe( 'NetworkController:stateChange', this.#onNetworkChanged, ); - this.messagingSystem.subscribe( + this.messenger.subscribe( 'KeyringController:accountRemoved', this.#onAccountRemoved, ); @@ -220,12 +218,12 @@ export class TokenBalancesController extends StaticIntervalPollingController<{ } readonly #getProvider = (chainId: ChainIdHex): Web3Provider => { - const { networkConfigurationsByChainId } = this.messagingSystem.call( + const { networkConfigurationsByChainId } = this.messenger.call( 'NetworkController:getState', ); const cfg = networkConfigurationsByChainId[chainId]; const { networkClientId } = cfg.rpcEndpoints[cfg.defaultRpcEndpointIndex]; - const client = this.messagingSystem.call( + const client = this.messenger.call( 'NetworkController:getNetworkClientById', networkClientId, ); @@ -233,12 +231,12 @@ export class TokenBalancesController extends StaticIntervalPollingController<{ }; readonly #getNetworkClient = (chainId: ChainIdHex) => { - const { networkConfigurationsByChainId } = this.messagingSystem.call( + const { networkConfigurationsByChainId } = this.messenger.call( 'NetworkController:getState', ); const cfg = networkConfigurationsByChainId[chainId]; const { networkClientId } = cfg.rpcEndpoints[cfg.defaultRpcEndpointIndex]; - return this.messagingSystem.call( + return this.messenger.call( 'NetworkController:getNetworkClientById', networkClientId, ); @@ -254,12 +252,10 @@ export class TokenBalancesController extends StaticIntervalPollingController<{ return; } - const { address: selected } = this.messagingSystem.call( + const { address: selected } = this.messenger.call( 'AccountsController:getSelectedAccount', ); - const allAccounts = this.messagingSystem.call( - 'AccountsController:listAccounts', - ); + const allAccounts = this.messenger.call('AccountsController:listAccounts'); const aggregated: ProcessedBalance[] = []; let remainingChains = [...targetChains]; @@ -365,7 +361,7 @@ export class TokenBalancesController extends StaticIntervalPollingController<{ balance: balance.value ? BNToHex(balance.value) : '0x0', })); - this.messagingSystem.call( + this.messenger.call( 'AccountTrackerController:updateNativeBalances', balanceUpdates, ); @@ -392,7 +388,7 @@ export class TokenBalancesController extends StaticIntervalPollingController<{ stakedBalance: balance.value ? toHex(balance.value) : '0x0', })); - this.messagingSystem.call( + this.messenger.call( 'AccountTrackerController:updateStakedBalances', stakedBalanceUpdates, ); From 20420e577423c716b12c5fc8f7aada0718e51621 Mon Sep 17 00:00:00 2001 From: Michele Esposito Date: Wed, 3 Sep 2025 21:56:16 +0200 Subject: [PATCH 24/69] migrate `TokenRatesController` messenger --- .../src/TokenRatesController.test.ts | 52 +++++++++++++------ .../src/TokenRatesController.ts | 20 ++++--- 2 files changed, 46 insertions(+), 26 deletions(-) diff --git a/packages/assets-controllers/src/TokenRatesController.test.ts b/packages/assets-controllers/src/TokenRatesController.test.ts index 4ae02821024..4d1639ddbcf 100644 --- a/packages/assets-controllers/src/TokenRatesController.test.ts +++ b/packages/assets-controllers/src/TokenRatesController.test.ts @@ -1,5 +1,3 @@ -import type { AddApprovalRequest } from '@metamask/approval-controller'; -import { Messenger } from '@metamask/base-controller'; import { ChainId, InfuraNetworkType, @@ -8,6 +6,13 @@ import { toHex, } from '@metamask/controller-utils'; import type { InternalAccount } from '@metamask/keyring-internal-api'; +import { + Messenger, + MOCK_ANY_NAMESPACE, + type MessengerActions, + type MessengerEvents, + type MockAnyNamespace, +} from '@metamask/messenger'; import type { NetworkClientConfiguration, NetworkClientId, @@ -36,8 +41,6 @@ import type { } from './token-prices-service/abstract-token-prices-service'; import { controllerName, TokenRatesController } from './TokenRatesController'; import type { - AllowedActions, - AllowedEvents, Token, TokenRatesControllerMessenger, TokenRatesControllerState, @@ -51,35 +54,52 @@ const defaultSelectedAccount = createMockInternalAccount({ }); const mockTokenAddress = '0x0000000000000000000000000000000000000010'; -type MainMessenger = Messenger< - AllowedActions | AddApprovalRequest, - AllowedEvents +type AllTokenRatesControllerActions = + MessengerActions; + +type AllTokenRatesControllerEvents = + MessengerEvents; + +type RootMessenger = Messenger< + MockAnyNamespace, + AllTokenRatesControllerActions, + AllTokenRatesControllerEvents >; /** * Builds a messenger that `TokenRatesController` can use to communicate with other controllers. * - * @param messenger - The main messenger. - * @returns The restricted messenger. + * @param messenger - The root messenger. + * @returns The controller messenger. */ function buildTokenRatesControllerMessenger( - messenger: MainMessenger = new Messenger(), + messenger: RootMessenger = new Messenger({ namespace: MOCK_ANY_NAMESPACE }), ): TokenRatesControllerMessenger { - return messenger.getRestricted({ - name: controllerName, - allowedActions: [ + const tokenRatesControllerMessenger = new Messenger< + 'TokenRatesController', + AllTokenRatesControllerActions, + AllTokenRatesControllerEvents, + RootMessenger + >({ + namespace: controllerName, + parent: messenger, + }); + messenger.delegate({ + messenger: tokenRatesControllerMessenger, + actions: [ 'TokensController:getState', 'NetworkController:getNetworkClientById', 'NetworkController:getState', 'AccountsController:getAccount', 'AccountsController:getSelectedAccount', ], - allowedEvents: [ + events: [ 'TokensController:stateChange', 'NetworkController:stateChange', 'AccountsController:selectedEvmAccountChange', ], }); + return tokenRatesControllerMessenger; } describe('TokenRatesController', () => { @@ -2735,7 +2755,9 @@ async function withController( mockTokensControllerState, mockNetworkState, } = rest; - const messenger = new Messenger(); + const messenger: RootMessenger = new Messenger({ + namespace: MOCK_ANY_NAMESPACE, + }); const mockTokensState = jest.fn(); messenger.registerActionHandler( diff --git a/packages/assets-controllers/src/TokenRatesController.ts b/packages/assets-controllers/src/TokenRatesController.ts index e6785ab97c7..d66f734d190 100644 --- a/packages/assets-controllers/src/TokenRatesController.ts +++ b/packages/assets-controllers/src/TokenRatesController.ts @@ -6,13 +6,13 @@ import type { import type { ControllerGetStateAction, ControllerStateChangeEvent, - RestrictedMessenger, -} from '@metamask/base-controller'; +} from '@metamask/base-controller/next'; import { safelyExecute, toChecksumHexAddress, FALL_BACK_VS_CURRENCY, } from '@metamask/controller-utils'; +import type { Messenger } from '@metamask/messenger'; import type { NetworkControllerGetNetworkClientByIdAction, NetworkControllerGetStateAction, @@ -157,12 +157,10 @@ export type TokenRatesControllerEvents = TokenRatesControllerStateChangeEvent; /** * The messenger of the {@link TokenRatesController} for communication. */ -export type TokenRatesControllerMessenger = RestrictedMessenger< +export type TokenRatesControllerMessenger = Messenger< typeof controllerName, TokenRatesControllerActions | AllowedActions, - TokenRatesControllerEvents | AllowedEvents, - AllowedActions['type'], - AllowedEvents['type'] + TokenRatesControllerEvents | AllowedEvents >; /** @@ -293,7 +291,7 @@ export class TokenRatesController extends StaticIntervalPollingController { - const { networkConfigurationsByChainId } = this.messagingSystem.call( + const { networkConfigurationsByChainId } = this.messenger.call( 'NetworkController:getState', ); From 1afff1ac7575ad9b09ad400de92636a70bb20351 Mon Sep 17 00:00:00 2001 From: Michele Esposito Date: Wed, 3 Sep 2025 22:08:00 +0200 Subject: [PATCH 25/69] migrate `TokenListController` messenger --- .../src/TokenListController.test.ts | 53 +++++++++++++------ .../src/TokenListController.ts | 14 +++-- 2 files changed, 43 insertions(+), 24 deletions(-) diff --git a/packages/assets-controllers/src/TokenListController.test.ts b/packages/assets-controllers/src/TokenListController.test.ts index 5acfe9f7eda..774aa995052 100644 --- a/packages/assets-controllers/src/TokenListController.test.ts +++ b/packages/assets-controllers/src/TokenListController.test.ts @@ -1,4 +1,3 @@ -import { Messenger } from '@metamask/base-controller'; import { ChainId, NetworkType, @@ -6,16 +5,19 @@ import { toHex, InfuraNetworkType, } from '@metamask/controller-utils'; +import { + Messenger, + MOCK_ANY_NAMESPACE, + type MessengerActions, + type MessengerEvents, + type MockAnyNamespace, +} from '@metamask/messenger'; import type { NetworkState } from '@metamask/network-controller'; import type { Hex } from '@metamask/utils'; import nock from 'nock'; import * as sinon from 'sinon'; import { advanceTime } from '../../../tests/helpers'; -import type { - ExtractAvailableAction, - ExtractAvailableEvent, -} from '../../base-controller/tests/helpers'; import { buildCustomNetworkClientConfiguration, buildInfuraNetworkClientConfiguration, @@ -29,7 +31,7 @@ import type { } from './TokenListController'; import { TokenListController } from './TokenListController'; -const name = 'TokenListController'; +const namespace = 'TokenListController'; const timestamp = Date.now(); const sampleMainnetTokenList = [ @@ -470,21 +472,40 @@ const expiredCacheExistingState: TokenListState = { preventPollingOnNetworkRestart: false, }; -type MainMessenger = Messenger< - ExtractAvailableAction, - ExtractAvailableEvent +type AllTokenListControllerActions = + MessengerActions; + +type AllTokenListControllerEvents = + MessengerEvents; + +type RootMessenger = Messenger< + MockAnyNamespace, + AllTokenListControllerActions, + AllTokenListControllerEvents >; -const getMessenger = (): MainMessenger => { - return new Messenger(); +const getMessenger = (): RootMessenger => { + return new Messenger({ namespace: MOCK_ANY_NAMESPACE }); }; -const getRestrictedMessenger = (messenger: MainMessenger) => { - return messenger.getRestricted({ - name, - allowedActions: ['NetworkController:getNetworkClientById'], - allowedEvents: ['NetworkController:stateChange'], +const getRestrictedMessenger = ( + messenger: RootMessenger, +): TokenListControllerMessenger => { + const tokenListControllerMessenger = new Messenger< + typeof namespace, + AllTokenListControllerActions, + AllTokenListControllerEvents, + RootMessenger + >({ + namespace, + parent: messenger, + }); + messenger.delegate({ + messenger: tokenListControllerMessenger, + actions: ['NetworkController:getNetworkClientById'], + events: ['NetworkController:stateChange'], }); + return tokenListControllerMessenger; }; describe('TokenListController', () => { diff --git a/packages/assets-controllers/src/TokenListController.ts b/packages/assets-controllers/src/TokenListController.ts index f7957c3be80..38119a729ed 100644 --- a/packages/assets-controllers/src/TokenListController.ts +++ b/packages/assets-controllers/src/TokenListController.ts @@ -1,9 +1,9 @@ import type { ControllerGetStateAction, ControllerStateChangeEvent, - RestrictedMessenger, -} from '@metamask/base-controller'; +} from '@metamask/base-controller/next'; import { safelyExecute } from '@metamask/controller-utils'; +import type { Messenger } from '@metamask/messenger'; import type { NetworkControllerStateChangeEvent, NetworkState, @@ -68,12 +68,10 @@ type AllowedActions = NetworkControllerGetNetworkClientByIdAction; type AllowedEvents = NetworkControllerStateChangeEvent; -export type TokenListControllerMessenger = RestrictedMessenger< +export type TokenListControllerMessenger = Messenger< typeof name, TokenListControllerActions | AllowedActions, - TokenListControllerEvents | AllowedEvents, - AllowedActions['type'], - AllowedEvents['type'] + TokenListControllerEvents | AllowedEvents >; const metadata = { @@ -163,7 +161,7 @@ export class TokenListController extends StaticIntervalPollingController Date: Wed, 3 Sep 2025 21:59:03 +0200 Subject: [PATCH 26/69] fix `TokenDetectionController` test --- .../src/TokenDetectionController.test.ts | 20 +++++++++---------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/packages/assets-controllers/src/TokenDetectionController.test.ts b/packages/assets-controllers/src/TokenDetectionController.test.ts index 8667f7516cb..8b7f0fd3efa 100644 --- a/packages/assets-controllers/src/TokenDetectionController.test.ts +++ b/packages/assets-controllers/src/TokenDetectionController.test.ts @@ -1,4 +1,3 @@ -import type { AddApprovalRequest } from '@metamask/approval-controller'; import { ChainId, NetworkType, @@ -10,9 +9,9 @@ import type { InternalAccount } from '@metamask/keyring-internal-api'; import { MOCK_ANY_NAMESPACE, Messenger, - MessengerActions, - MessengerEvents, - MockAnyNamespace, + type MessengerActions, + type MessengerEvents, + type MockAnyNamespace, } from '@metamask/messenger'; import { getDefaultNetworkControllerState, @@ -44,11 +43,7 @@ import { } from './multi-chain-accounts-service/mocks/mock-get-balances'; import { MOCK_GET_SUPPORTED_NETWORKS_RESPONSE } from './multi-chain-accounts-service/mocks/mock-get-supported-networks'; import { TOKEN_END_POINT_API } from './token-service'; -import type { - AllowedActions, - AllowedEvents, - TokenDetectionControllerMessenger, -} from './TokenDetectionController'; +import type { TokenDetectionControllerMessenger } from './TokenDetectionController'; import { STATIC_MAINNET_TOKEN_LIST, TokenDetectionController, @@ -3758,12 +3753,15 @@ async function withController( .mockResolvedValue(undefined), ); - const callActionSpy = jest.spyOn(messenger, 'call'); + const tokenDetectionControllerMessenger = + buildTokenDetectionControllerMessenger(messenger); + + const callActionSpy = jest.spyOn(tokenDetectionControllerMessenger, 'call'); const controller = new TokenDetectionController({ getBalancesInSingleCall: jest.fn(), trackMetaMetricsEvent: jest.fn(), - messenger: buildTokenDetectionControllerMessenger(messenger), + messenger: tokenDetectionControllerMessenger, useAccountsAPI: false, platform: 'extension', ...options, From f4b79ec1b277effd1c234d4bbd0cf92c4810a372 Mon Sep 17 00:00:00 2001 From: Michele Esposito Date: Wed, 3 Sep 2025 21:59:08 +0200 Subject: [PATCH 27/69] update lockfile --- yarn.lock | 1 + 1 file changed, 1 insertion(+) diff --git a/yarn.lock b/yarn.lock index f6f7362761a..c1c8f7344be 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2739,6 +2739,7 @@ __metadata: "@metamask/eth-json-rpc-provider": "npm:^4.1.8" "@metamask/gas-fee-controller": "npm:^24.0.0" "@metamask/keyring-api": "npm:^20.1.0" + "@metamask/messenger": "npm:^0.1.0" "@metamask/metamask-eth-abis": "npm:^3.1.1" "@metamask/multichain-network-controller": "npm:^0.12.0" "@metamask/network-controller": "npm:^24.1.0" From b7ebf4edac591fc36d96e3d74f92cbadf3b6cfcc Mon Sep 17 00:00:00 2001 From: Michele Esposito Date: Thu, 4 Sep 2025 11:37:22 +0200 Subject: [PATCH 28/69] update changelogs --- packages/assets-controllers/CHANGELOG.md | 9 +++++++++ packages/bridge-controller/CHANGELOG.md | 2 ++ packages/bridge-status-controller/CHANGELOG.md | 5 +++++ packages/polling-controller/CHANGELOG.md | 2 ++ 4 files changed, 18 insertions(+) diff --git a/packages/assets-controllers/CHANGELOG.md b/packages/assets-controllers/CHANGELOG.md index 032457253b1..d10d9d99600 100644 --- a/packages/assets-controllers/CHANGELOG.md +++ b/packages/assets-controllers/CHANGELOG.md @@ -9,6 +9,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed +- **BREAKING:** Migrate the following controllers to the new `Messenger` from `@metamask/messenger` ([#6444](https://github.com/MetaMask/core/pull/6444)) + - `AccountTrackerController` + - `CurrencyRateController` + - `DeFiPositionController` + - `MultichainAssetsRatesController` + - `TokenBalancesController` + - `TokenDetectionController` + - `TokenListController` + - `TokenRatesController` - **BREAKING:** Migrate `AssetsContractController`, `NftController`, and `TokensController` to new `Messenger` from `@metamask/messenger` ([#6386](https://github.com/MetaMask/core/pull/6386)) - Previously, the controllers accepted a `RestrictedMessenger` instance from `@metamask/base-controller`. diff --git a/packages/bridge-controller/CHANGELOG.md b/packages/bridge-controller/CHANGELOG.md index 24acd0f3d81..1e576d00771 100644 --- a/packages/bridge-controller/CHANGELOG.md +++ b/packages/bridge-controller/CHANGELOG.md @@ -9,6 +9,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed +- **BREAKING:** Use new `Messenger` from `@metamask/messenger` ([#6444](https://github.com/MetaMask/core/pull/6444)) + - Previously, `BridgeController` accepted a `RestrictedMessenger` instance from `@metamask/base-controller`. - **BREAKING** Rename QuotesError and InputSourceDestinationSwitched events to match segment schema ([#6447](https://github.com/MetaMask/core/pull/6447)) ## [41.4.0] diff --git a/packages/bridge-status-controller/CHANGELOG.md b/packages/bridge-status-controller/CHANGELOG.md index 5076c5c31bb..108f7037a75 100644 --- a/packages/bridge-status-controller/CHANGELOG.md +++ b/packages/bridge-status-controller/CHANGELOG.md @@ -7,6 +7,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Changed + +- **BREAKING:** Use new `Messenger` from `@metamask/messenger` ([#6444](https://github.com/MetaMask/core/pull/6444)) + - Previously, `BridgeStatusController` accepted a `RestrictedMessenger` instance from `@metamask/base-controller`. + ## [41.0.0] ### Fixed diff --git a/packages/polling-controller/CHANGELOG.md b/packages/polling-controller/CHANGELOG.md index 60f094cd4d6..20a0e0c675b 100644 --- a/packages/polling-controller/CHANGELOG.md +++ b/packages/polling-controller/CHANGELOG.md @@ -9,6 +9,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed +- **BREAKING:** Use new `Messenger` from `@metamask/messenger` for `StaticIntervalPollingController` ([#6444](https://github.com/MetaMask/core/pull/6444)) + - Previously, `StaticIntervalPollingController` accepted a `RestrictedMessenger` instance from `@metamask/base-controller`. - Bump `@metamask/base-controller` from `^8.0.1` to `^8.2.0` ([#6284](https://github.com/MetaMask/core/pull/6284), [#6355](https://github.com/MetaMask/core/pull/6355)) - Bump `@metamask/controller-utils` from `^11.10.0` to `^11.12.0` ([#6069](https://github.com/MetaMask/core/pull/6069), [#6303](https://github.com/MetaMask/core/pull/6303)) - Bump `@metamask/utils` from `^11.2.0` to `^11.4.2` ([#6054](https://github.com/MetaMask/core/pull/6054)) From 0267ab28ad124ae22213650be6842ea993348c3f Mon Sep 17 00:00:00 2001 From: Michele Esposito Date: Tue, 23 Sep 2025 13:15:00 +0200 Subject: [PATCH 29/69] rename `anonymous` to `inclueInDebugSnapshot` --- .../src/ApprovalController.test.ts | 2 +- .../approval-controller/src/ApprovalController.ts | 13 ++++++++----- .../assets-controllers/src/NftController.test.ts | 2 +- packages/assets-controllers/src/NftController.ts | 9 +++++---- .../assets-controllers/src/TokensController.test.ts | 2 +- packages/assets-controllers/src/TokensController.ts | 9 +++++---- .../gas-fee-controller/src/GasFeeController.test.ts | 2 +- packages/gas-fee-controller/src/GasFeeController.ts | 13 +++++++------ .../network-controller/src/NetworkController.ts | 6 +++--- .../tests/NetworkController.test.ts | 4 ++-- .../src/TransactionController.test.ts | 2 +- .../src/TransactionController.ts | 13 +++++++------ 12 files changed, 42 insertions(+), 35 deletions(-) diff --git a/packages/approval-controller/src/ApprovalController.test.ts b/packages/approval-controller/src/ApprovalController.test.ts index 5bf81cb1539..d570e5d5f52 100644 --- a/packages/approval-controller/src/ApprovalController.test.ts +++ b/packages/approval-controller/src/ApprovalController.test.ts @@ -1707,7 +1707,7 @@ describe('approval controller', () => { deriveStateFromMetadata( approvalController.state, approvalController.metadata, - 'anonymous', + 'includeInDebugSnapshot', ), ).toMatchInlineSnapshot(` Object { diff --git a/packages/approval-controller/src/ApprovalController.ts b/packages/approval-controller/src/ApprovalController.ts index 680649afe05..f2e7efe13c3 100644 --- a/packages/approval-controller/src/ApprovalController.ts +++ b/packages/approval-controller/src/ApprovalController.ts @@ -1,4 +1,7 @@ -import type { ControllerGetStateAction } from '@metamask/base-controller'; +import type { + ControllerGetStateAction, + StateMetadata, +} from '@metamask/base-controller/next'; import { BaseController, type ControllerStateChangeEvent, @@ -26,23 +29,23 @@ export const APPROVAL_TYPE_RESULT_SUCCESS = 'result_success'; const controllerName = 'ApprovalController'; -const stateMetadata = { +const stateMetadata: StateMetadata = { pendingApprovals: { includeInStateLogs: true, persist: false, - anonymous: true, + includeInDebugSnapshot: true, usedInUi: true, }, pendingApprovalCount: { includeInStateLogs: true, persist: false, - anonymous: false, + includeInDebugSnapshot: false, usedInUi: true, }, approvalFlows: { includeInStateLogs: true, persist: false, - anonymous: false, + includeInDebugSnapshot: false, usedInUi: true, }, }; diff --git a/packages/assets-controllers/src/NftController.test.ts b/packages/assets-controllers/src/NftController.test.ts index 548ecba192a..cb3bddac5de 100644 --- a/packages/assets-controllers/src/NftController.test.ts +++ b/packages/assets-controllers/src/NftController.test.ts @@ -5914,7 +5914,7 @@ describe('NftController', () => { deriveStateFromMetadata( controller.state, controller.metadata, - 'anonymous', + 'includeInDebugSnapshot', ), ).toMatchInlineSnapshot(`Object {}`); }); diff --git a/packages/assets-controllers/src/NftController.ts b/packages/assets-controllers/src/NftController.ts index 32f2897631a..9dfd924efd6 100644 --- a/packages/assets-controllers/src/NftController.ts +++ b/packages/assets-controllers/src/NftController.ts @@ -9,6 +9,7 @@ import { BaseController, type ControllerStateChangeEvent, type ControllerGetStateAction, + StateMetadata, } from '@metamask/base-controller/next'; import { safelyExecute, @@ -206,23 +207,23 @@ export type NftControllerState = { ignoredNfts: Nft[]; }; -const nftControllerMetadata = { +const nftControllerMetadata: StateMetadata = { allNftContracts: { includeInStateLogs: false, persist: true, - anonymous: false, + includeInDebugSnapshot: false, usedInUi: true, }, allNfts: { includeInStateLogs: false, persist: true, - anonymous: false, + includeInDebugSnapshot: false, usedInUi: true, }, ignoredNfts: { includeInStateLogs: false, persist: true, - anonymous: false, + includeInDebugSnapshot: false, usedInUi: false, }, }; diff --git a/packages/assets-controllers/src/TokensController.test.ts b/packages/assets-controllers/src/TokensController.test.ts index 70360eedea5..b84f5a901b5 100644 --- a/packages/assets-controllers/src/TokensController.test.ts +++ b/packages/assets-controllers/src/TokensController.test.ts @@ -3483,7 +3483,7 @@ describe('TokensController', () => { deriveStateFromMetadata( controller.state, controller.metadata, - 'anonymous', + 'includeInDebugSnapshot', ), ).toMatchInlineSnapshot(`Object {}`); }); diff --git a/packages/assets-controllers/src/TokensController.ts b/packages/assets-controllers/src/TokensController.ts index fb5ec04e60a..8a45509a468 100644 --- a/packages/assets-controllers/src/TokensController.ts +++ b/packages/assets-controllers/src/TokensController.ts @@ -10,6 +10,7 @@ import type { AddApprovalRequest } from '@metamask/approval-controller'; import type { ControllerGetStateAction, ControllerStateChangeEvent, + StateMetadata, } from '@metamask/base-controller/next'; import { BaseController } from '@metamask/base-controller/next'; import contractsMap from '@metamask/contract-metadata'; @@ -88,23 +89,23 @@ export type TokensControllerState = { allDetectedTokens: { [chainId: Hex]: { [key: string]: Token[] } }; }; -const metadata = { +const metadata: StateMetadata = { allTokens: { includeInStateLogs: false, persist: true, - anonymous: false, + includeInDebugSnapshot: false, usedInUi: true, }, allIgnoredTokens: { includeInStateLogs: false, persist: true, - anonymous: false, + includeInDebugSnapshot: false, usedInUi: true, }, allDetectedTokens: { includeInStateLogs: false, persist: true, - anonymous: false, + includeInDebugSnapshot: false, usedInUi: true, }, }; diff --git a/packages/gas-fee-controller/src/GasFeeController.test.ts b/packages/gas-fee-controller/src/GasFeeController.test.ts index 28537bcfcb4..9e736d00018 100644 --- a/packages/gas-fee-controller/src/GasFeeController.test.ts +++ b/packages/gas-fee-controller/src/GasFeeController.test.ts @@ -1297,7 +1297,7 @@ describe('GasFeeController', () => { deriveStateFromMetadata( gasFeeController.state, gasFeeController.metadata, - 'anonymous', + 'includeInDebugSnapshot', ), ).toMatchInlineSnapshot(`Object {}`); }); diff --git a/packages/gas-fee-controller/src/GasFeeController.ts b/packages/gas-fee-controller/src/GasFeeController.ts index 5e9289f2334..be6fe7b3fb0 100644 --- a/packages/gas-fee-controller/src/GasFeeController.ts +++ b/packages/gas-fee-controller/src/GasFeeController.ts @@ -1,6 +1,7 @@ import type { ControllerGetStateAction, ControllerStateChangeEvent, + StateMetadata, } from '@metamask/base-controller/next'; import { convertHexToDecimal, @@ -160,35 +161,35 @@ type FallbackGasFeeEstimates = { networkCongestion: null; }; -const metadata = { +const metadata: StateMetadata = { gasFeeEstimatesByChainId: { includeInStateLogs: true, persist: true, - anonymous: false, + includeInDebugSnapshot: false, usedInUi: true, }, gasFeeEstimates: { includeInStateLogs: true, persist: true, - anonymous: false, + includeInDebugSnapshot: false, usedInUi: true, }, estimatedGasFeeTimeBounds: { includeInStateLogs: true, persist: true, - anonymous: false, + includeInDebugSnapshot: false, usedInUi: true, }, gasEstimateType: { includeInStateLogs: true, persist: true, - anonymous: false, + includeInDebugSnapshot: false, usedInUi: true, }, nonRPCGasFeeApisDisabled: { includeInStateLogs: true, persist: true, - anonymous: false, + includeInDebugSnapshot: false, usedInUi: false, }, }; diff --git a/packages/network-controller/src/NetworkController.ts b/packages/network-controller/src/NetworkController.ts index 49cb110a3a7..5ddfc752c3e 100644 --- a/packages/network-controller/src/NetworkController.ts +++ b/packages/network-controller/src/NetworkController.ts @@ -1200,19 +1200,19 @@ export class NetworkController extends BaseController< selectedNetworkClientId: { includeInStateLogs: true, persist: true, - anonymous: false, + includeInDebugSnapshot: false, usedInUi: true, }, networksMetadata: { includeInStateLogs: true, persist: true, - anonymous: false, + includeInDebugSnapshot: false, usedInUi: true, }, networkConfigurationsByChainId: { includeInStateLogs: true, persist: true, - anonymous: false, + includeInDebugSnapshot: false, usedInUi: true, }, }, diff --git a/packages/network-controller/tests/NetworkController.test.ts b/packages/network-controller/tests/NetworkController.test.ts index d69a93d46fd..24231afca51 100644 --- a/packages/network-controller/tests/NetworkController.test.ts +++ b/packages/network-controller/tests/NetworkController.test.ts @@ -1,7 +1,7 @@ // A lot of the tests in this file have conditionals. /* eslint-disable jest/no-conditional-in-test */ -import { deriveStateFromMetadata } from '@metamask/base-controller'; +import { deriveStateFromMetadata } from '@metamask/base-controller/next'; import { BuiltInNetworkName, ChainId, @@ -14512,7 +14512,7 @@ describe('NetworkController', () => { deriveStateFromMetadata( controller.state, controller.metadata, - 'anonymous', + 'includeInDebugSnapshot', ), ).toMatchInlineSnapshot(`Object {}`); }); diff --git a/packages/transaction-controller/src/TransactionController.test.ts b/packages/transaction-controller/src/TransactionController.test.ts index c4c135e949c..4cd35b905a2 100644 --- a/packages/transaction-controller/src/TransactionController.test.ts +++ b/packages/transaction-controller/src/TransactionController.test.ts @@ -8016,7 +8016,7 @@ describe('TransactionController', () => { deriveStateFromMetadata( controller.state, controller.metadata, - 'anonymous', + 'includeInDebugSnapshot', ), ).toMatchInlineSnapshot(`Object {}`); }); diff --git a/packages/transaction-controller/src/TransactionController.ts b/packages/transaction-controller/src/TransactionController.ts index e4588002f7e..832e9e8e786 100644 --- a/packages/transaction-controller/src/TransactionController.ts +++ b/packages/transaction-controller/src/TransactionController.ts @@ -11,6 +11,7 @@ import type { import type { ControllerGetStateAction, ControllerStateChangeEvent, + StateMetadata, } from '@metamask/base-controller/next'; import { BaseController } from '@metamask/base-controller/next'; import { @@ -182,35 +183,35 @@ import { * Metadata for the TransactionController state, describing how to "anonymize" * the state and which parts should be persisted. */ -const metadata = { +const metadata: StateMetadata = { transactions: { includeInStateLogs: true, persist: true, - anonymous: false, + includeInDebugSnapshot: false, usedInUi: true, }, transactionBatches: { includeInStateLogs: true, persist: true, - anonymous: false, + includeInDebugSnapshot: false, usedInUi: true, }, methodData: { includeInStateLogs: true, persist: true, - anonymous: false, + includeInDebugSnapshot: false, usedInUi: true, }, lastFetchedBlockNumbers: { includeInStateLogs: true, persist: true, - anonymous: false, + includeInDebugSnapshot: false, usedInUi: false, }, submitHistory: { includeInStateLogs: true, persist: true, - anonymous: false, + includeInDebugSnapshot: false, usedInUi: false, }, }; From d899417655423aaf3a6b50cbbca84c677e601929 Mon Sep 17 00:00:00 2001 From: Michele Esposito Date: Tue, 23 Sep 2025 13:17:44 +0200 Subject: [PATCH 30/69] update tsconfig and README --- README.md | 4 ++++ packages/approval-controller/tsconfig.build.json | 3 +++ packages/approval-controller/tsconfig.json | 3 +++ packages/assets-controllers/tsconfig.build.json | 1 + packages/assets-controllers/tsconfig.json | 1 + packages/network-controller/tsconfig.build.json | 3 ++- packages/network-controller/tsconfig.json | 3 ++- packages/transaction-controller/tsconfig.build.json | 1 + packages/transaction-controller/tsconfig.json | 1 + 9 files changed, 18 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 4eab983a1dc..fb4cf4a5ee3 100644 --- a/README.md +++ b/README.md @@ -153,8 +153,10 @@ linkStyle default opacity:0.5 announcement_controller --> base_controller; app_metadata_controller --> base_controller; approval_controller --> base_controller; + approval_controller --> messenger; assets_controllers --> base_controller; assets_controllers --> controller_utils; + assets_controllers --> messenger; assets_controllers --> polling_controller; assets_controllers --> account_tree_controller; assets_controllers --> accounts_controller; @@ -246,6 +248,7 @@ linkStyle default opacity:0.5 network_controller --> controller_utils; network_controller --> eth_json_rpc_provider; network_controller --> json_rpc_engine; + network_controller --> messenger; network_controller --> error_reporting_service; network_enablement_controller --> base_controller; network_enablement_controller --> controller_utils; @@ -292,6 +295,7 @@ linkStyle default opacity:0.5 signature_controller --> controller_utils; signature_controller --> accounts_controller; signature_controller --> approval_controller; + signature_controller --> gator_permissions_controller; signature_controller --> keyring_controller; signature_controller --> logging_controller; signature_controller --> network_controller; diff --git a/packages/approval-controller/tsconfig.build.json b/packages/approval-controller/tsconfig.build.json index 779d385a6ab..249f327913d 100644 --- a/packages/approval-controller/tsconfig.build.json +++ b/packages/approval-controller/tsconfig.build.json @@ -8,6 +8,9 @@ "references": [ { "path": "../base-controller/tsconfig.build.json" + }, + { + "path": "../messenger/tsconfig.build.json" } ], "include": ["../../types", "./src"] diff --git a/packages/approval-controller/tsconfig.json b/packages/approval-controller/tsconfig.json index f2d7b67ff66..cb296895b28 100644 --- a/packages/approval-controller/tsconfig.json +++ b/packages/approval-controller/tsconfig.json @@ -6,6 +6,9 @@ "references": [ { "path": "../base-controller" + }, + { + "path": "../messenger" } ], "include": ["../../types", "./src"] diff --git a/packages/assets-controllers/tsconfig.build.json b/packages/assets-controllers/tsconfig.build.json index bca6a835d37..851f7d485ee 100644 --- a/packages/assets-controllers/tsconfig.build.json +++ b/packages/assets-controllers/tsconfig.build.json @@ -13,6 +13,7 @@ { "path": "../controller-utils/tsconfig.build.json" }, { "path": "../keyring-controller/tsconfig.build.json" }, { "path": "../network-controller/tsconfig.build.json" }, + { "path": "../messenger/tsconfig.build.json" }, { "path": "../preferences-controller/tsconfig.build.json" }, { "path": "../polling-controller/tsconfig.build.json" }, { "path": "../permission-controller/tsconfig.build.json" }, diff --git a/packages/assets-controllers/tsconfig.json b/packages/assets-controllers/tsconfig.json index 2b0acd993f8..01db9a79264 100644 --- a/packages/assets-controllers/tsconfig.json +++ b/packages/assets-controllers/tsconfig.json @@ -12,6 +12,7 @@ { "path": "../controller-utils" }, { "path": "../keyring-controller" }, { "path": "../network-controller" }, + { "path": "../messenger" }, { "path": "../preferences-controller" }, { "path": "../phishing-controller" }, { "path": "../polling-controller" }, diff --git a/packages/network-controller/tsconfig.build.json b/packages/network-controller/tsconfig.build.json index fb5b1cb08e5..894e58c9650 100644 --- a/packages/network-controller/tsconfig.build.json +++ b/packages/network-controller/tsconfig.build.json @@ -10,7 +10,8 @@ { "path": "../controller-utils/tsconfig.build.json" }, { "path": "../eth-json-rpc-provider/tsconfig.build.json" }, { "path": "../json-rpc-engine/tsconfig.build.json" }, - { "path": "../error-reporting-service/tsconfig.build.json" } + { "path": "../error-reporting-service/tsconfig.build.json" }, + { "path": "../messenger/tsconfig.build.json" } ], "include": ["../../types", "./src"] } diff --git a/packages/network-controller/tsconfig.json b/packages/network-controller/tsconfig.json index cc0926fbd0c..6542199fa4f 100644 --- a/packages/network-controller/tsconfig.json +++ b/packages/network-controller/tsconfig.json @@ -9,7 +9,8 @@ { "path": "../controller-utils" }, { "path": "../eth-json-rpc-provider" }, { "path": "../json-rpc-engine" }, - { "path": "../error-reporting-service" } + { "path": "../error-reporting-service" }, + { "path": "../messenger" } ], "include": ["../../types", "../../tests", "./src", "./tests"] } diff --git a/packages/transaction-controller/tsconfig.build.json b/packages/transaction-controller/tsconfig.build.json index 716dda8820b..6e04a4ba1d8 100644 --- a/packages/transaction-controller/tsconfig.build.json +++ b/packages/transaction-controller/tsconfig.build.json @@ -12,6 +12,7 @@ { "path": "../controller-utils/tsconfig.build.json" }, { "path": "../gas-fee-controller/tsconfig.build.json" }, { "path": "../network-controller/tsconfig.build.json" }, + { "path": "../messenger/tsconfig.build.json" }, { "path": "../remote-feature-flag-controller/tsconfig.build.json" } ], "include": ["../../types", "./src"] diff --git a/packages/transaction-controller/tsconfig.json b/packages/transaction-controller/tsconfig.json index b839b37eed5..1e328031877 100644 --- a/packages/transaction-controller/tsconfig.json +++ b/packages/transaction-controller/tsconfig.json @@ -11,6 +11,7 @@ { "path": "../controller-utils" }, { "path": "../gas-fee-controller" }, { "path": "../network-controller" }, + { "path": "../messenger" }, { "path": "../remote-feature-flag-controller" } ], "include": ["../../types", "./src", "./tests"] From b2a2585e617847c63e7fbba63f50013b0c269494 Mon Sep 17 00:00:00 2001 From: Michele Esposito Date: Tue, 23 Sep 2025 13:48:17 +0200 Subject: [PATCH 31/69] refactor: use `MockAnyNetwork` --- .../src/ApprovalController.test.ts | 23 ++++-- .../tests/NetworkController.test.ts | 9 +-- packages/network-controller/tests/helpers.ts | 31 +------- .../src/TransactionController.test.ts | 75 +++++++------------ 4 files changed, 50 insertions(+), 88 deletions(-) diff --git a/packages/approval-controller/src/ApprovalController.test.ts b/packages/approval-controller/src/ApprovalController.test.ts index d570e5d5f52..5afdfdf1898 100644 --- a/packages/approval-controller/src/ApprovalController.test.ts +++ b/packages/approval-controller/src/ApprovalController.test.ts @@ -1,7 +1,13 @@ /* eslint-disable jest/expect-expect */ import { deriveStateFromMetadata } from '@metamask/base-controller/next'; -import { Messenger } from '@metamask/messenger'; +import { + MOCK_ANY_NAMESPACE, + Messenger, + type MessengerActions, + type MessengerEvents, + type MockAnyNamespace, +} from '@metamask/messenger'; import { errorCodes, JsonRpcError } from '@metamask/rpc-errors'; import { nanoid } from 'nanoid'; @@ -10,6 +16,7 @@ import type { AddApprovalOptions, ApprovalControllerActions, ApprovalControllerEvents, + ApprovalControllerMessenger, ErrorOptions, StartFlowOptions, SuccessOptions, @@ -29,6 +36,12 @@ import { jest.mock('nanoid'); +type AllActions = MessengerActions; + +type AllEvents = MessengerEvents; + +type RootMessenger = Messenger; + const nanoidMock = jest.mocked(nanoid); const PENDING_APPROVALS_STORE_KEY = 'pendingApprovals'; @@ -229,11 +242,9 @@ function getError(message: string, code?: number) { * @returns A controller messenger. */ function getMessengers() { - const rootMessenger = new Messenger< - 'Root', - ApprovalControllerActions, - ApprovalControllerEvents - >({ namespace: 'Root' }); + const rootMessenger: RootMessenger = new Messenger({ + namespace: MOCK_ANY_NAMESPACE, + }); return { rootMessenger, approvalControllerMessenger: new Messenger< diff --git a/packages/network-controller/tests/NetworkController.test.ts b/packages/network-controller/tests/NetworkController.test.ts index 24231afca51..4841f92b647 100644 --- a/packages/network-controller/tests/NetworkController.test.ts +++ b/packages/network-controller/tests/NetworkController.test.ts @@ -27,7 +27,6 @@ import { buildCustomNetworkClientConfiguration, buildCustomNetworkConfiguration, buildCustomRpcEndpoint, - buildErrorReportingServiceMessenger, buildInfuraNetworkClientConfiguration, buildInfuraNetworkConfiguration, buildInfuraRpcEndpoint, @@ -354,9 +353,7 @@ describe('NetworkController', () => { describe('if selectedNetworkClientId does not match the networkClientId of an RPC endpoint in networkConfigurationsByChainId', () => { it('corrects selectedNetworkClientId to the default RPC endpoint of the first chain', () => { const messenger = buildRootMessenger(); - const errorReportingServiceMessenger = - buildErrorReportingServiceMessenger(messenger); - errorReportingServiceMessenger.registerActionHandler( + messenger.registerActionHandler( 'ErrorReportingService:captureException', jest.fn(), ); @@ -396,10 +393,8 @@ describe('NetworkController', () => { it('logs a Sentry error', () => { const messenger = buildRootMessenger(); - const errorReportingServiceMessenger = - buildErrorReportingServiceMessenger(messenger); const captureExceptionMock = jest.fn(); - errorReportingServiceMessenger.registerActionHandler( + messenger.registerActionHandler( 'ErrorReportingService:captureException', captureExceptionMock, ); diff --git a/packages/network-controller/tests/helpers.ts b/packages/network-controller/tests/helpers.ts index 1a509bd1fb8..bff0d7f5010 100644 --- a/packages/network-controller/tests/helpers.ts +++ b/packages/network-controller/tests/helpers.ts @@ -7,8 +7,10 @@ import { } from '@metamask/controller-utils'; import { Messenger, + type MockAnyNamespace, type MessengerActions, type MessengerEvents, + MOCK_ANY_NAMESPACE, } from '@metamask/messenger'; import type { Hex } from '@metamask/utils'; import { v4 as uuidV4 } from 'uuid'; @@ -49,7 +51,7 @@ export type AllNetworkControllerEvents = MessengerEvents; export type RootMessenger = Messenger< - 'Root', + MockAnyNamespace, AllNetworkControllerActions, AllNetworkControllerEvents >; @@ -83,7 +85,7 @@ export const TESTNET = { * @returns The messenger. */ export function buildRootMessenger(): RootMessenger { - return new Messenger({ namespace: 'Root' }); + return new Messenger({ namespace: MOCK_ANY_NAMESPACE }); } /** @@ -111,31 +113,6 @@ export function buildNetworkControllerMessenger( return networkControllerMessenger; } -/** - * Build a messenger for the error reporting service. - * - * @param rootMessenger - The root messenger. - * @returns The error reporting service messenger. - */ -export function buildErrorReportingServiceMessenger( - rootMessenger = buildRootMessenger(), -): Messenger< - 'ErrorReportingService', - AllNetworkControllerActions, - AllNetworkControllerEvents, - typeof rootMessenger -> { - return new Messenger< - 'ErrorReportingService', - AllNetworkControllerActions, - AllNetworkControllerEvents, - typeof rootMessenger - >({ - namespace: 'ErrorReportingService', - parent: rootMessenger, - }); -} - /** * Builds an object that satisfies the NetworkClient shape, but using a fake * provider and block tracker which doesn't make any requests. diff --git a/packages/transaction-controller/src/TransactionController.test.ts b/packages/transaction-controller/src/TransactionController.test.ts index 4cd35b905a2..16a15c67a1e 100644 --- a/packages/transaction-controller/src/TransactionController.test.ts +++ b/packages/transaction-controller/src/TransactionController.test.ts @@ -15,7 +15,13 @@ import { import type { SafeEventEmitterProvider } from '@metamask/eth-json-rpc-provider'; import EthQuery from '@metamask/eth-query'; import HttpProvider from '@metamask/ethjs-provider-http'; -import { Messenger } from '@metamask/messenger'; +import { + Messenger, + type MockAnyNamespace, + type MessengerActions, + type MessengerEvents, + MOCK_ANY_NAMESPACE, +} from '@metamask/messenger'; import type { BlockTracker, NetworkClientConfiguration, @@ -52,11 +58,7 @@ import { PendingTransactionTracker } from './helpers/PendingTransactionTracker'; import { shouldResimulate } from './helpers/ResimulateHelper'; import { ExtraTransactionsPublishHook } from './hooks/ExtraTransactionsPublishHook'; import type { - AllowedActions, - AllowedEvents, MethodData, - TransactionControllerActions, - TransactionControllerEvents, TransactionControllerMessenger, TransactionControllerOptions, } from './TransactionController'; @@ -113,10 +115,16 @@ import { buildMockGetNetworkClientById, } from '../../network-controller/tests/helpers'; +type AllTransactionControllerActions = + MessengerActions; + +type AllTransactionControllerEvents = + MessengerEvents; + type RootMessenger = Messenger< - 'Root', - TransactionControllerActions | AllowedActions, - TransactionControllerEvents | AllowedEvents + MockAnyNamespace, + AllTransactionControllerActions, + AllTransactionControllerEvents >; const MOCK_V1_UUID = '9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d'; @@ -662,32 +670,20 @@ describe('TransactionController', () => { }); }; const rootMessenger: RootMessenger = new Messenger({ - namespace: 'Root', - }); - const networkControllerMessenger = new Messenger< - 'NetworkController', - AllowedActions, - AllowedEvents, - typeof rootMessenger - >({ namespace: 'NetworkController', parent: rootMessenger }); + namespace: MOCK_ANY_NAMESPACE, + }); const getNetworkClientById = buildMockGetNetworkClientById( mockNetworkClientConfigurationsByNetworkClientId, ); - networkControllerMessenger.registerActionHandler( + rootMessenger.registerActionHandler( 'NetworkController:getNetworkClientById', getNetworkClientById, ); const { addTransactionApprovalRequest = { state: 'pending' } } = messengerOptions; - const approvalControllerMessenger = new Messenger< - 'ApprovalController', - AllowedActions, - AllowedEvents, - typeof rootMessenger - >({ namespace: 'ApprovalController', parent: rootMessenger }); const mockTransactionApprovalRequest = mockAddTransactionApprovalRequest( - approvalControllerMessenger, + rootMessenger, addTransactionApprovalRequest, ); @@ -730,20 +726,13 @@ describe('TransactionController', () => { ], }); - const accountsControllerMessenger = new Messenger< - 'AccountsController', - AllowedActions, - AllowedEvents, - typeof rootMessenger - >({ namespace: 'AccountsController', parent: rootMessenger }); - const mockGetSelectedAccount = jest.fn().mockReturnValue(selectedAccount); - accountsControllerMessenger.registerActionHandler( + rootMessenger.registerActionHandler( 'AccountsController:getSelectedAccount', mockGetSelectedAccount, ); - accountsControllerMessenger.registerActionHandler( + rootMessenger.registerActionHandler( 'AccountsController:getState', () => ({}) as never, ); @@ -752,17 +741,7 @@ describe('TransactionController', () => { featureFlags: {}, }); - const remoteFeatureFlagControllerMessenger = new Messenger< - 'RemoteFeatureFlagController', - AllowedActions, - AllowedEvents, - typeof rootMessenger - >({ - namespace: 'RemoteFeatureFlagController', - parent: rootMessenger, - }); - - remoteFeatureFlagControllerMessenger.registerActionHandler( + rootMessenger.registerActionHandler( 'RemoteFeatureFlagController:getState', remoteFeatureFlagControllerGetStateMock, ); @@ -793,7 +772,7 @@ describe('TransactionController', () => { return { controller, messenger: transactionControllerMessenger, - networkControllerMessenger, + rootMessenger, mockTransactionApprovalRequest, mockGetSelectedAccount, changeNetwork, @@ -822,7 +801,7 @@ describe('TransactionController', () => { * finally the mocked version of the action handler itself. */ function mockAddTransactionApprovalRequest( - messenger: Messenger<'ApprovalController', AllowedActions, AllowedEvents>, + messenger: RootMessenger, options: | { state: 'approved'; @@ -6082,8 +6061,8 @@ describe('TransactionController', () => { }); it('uses the nonceTracker for the networkClientId matching the chainId', async () => { - const { controller, networkControllerMessenger } = setupController(); - networkControllerMessenger.registerActionHandler( + const { controller, rootMessenger } = setupController(); + rootMessenger.registerActionHandler( 'NetworkController:findNetworkClientIdByChainId', () => 'sepolia', ); From f786d7bb4ba1cf1b628a0f8f222b095c0f4485a4 Mon Sep 17 00:00:00 2001 From: Michele Esposito Date: Tue, 23 Sep 2025 13:49:55 +0200 Subject: [PATCH 32/69] update messenger to 0.3.0 --- packages/transaction-controller/package.json | 2 +- yarn.lock | 9 +-------- 2 files changed, 2 insertions(+), 9 deletions(-) diff --git a/packages/transaction-controller/package.json b/packages/transaction-controller/package.json index 7a1a80fb9a9..adc3e1c57fe 100644 --- a/packages/transaction-controller/package.json +++ b/packages/transaction-controller/package.json @@ -57,7 +57,7 @@ "@metamask/base-controller": "^8.4.0", "@metamask/controller-utils": "^11.14.0", "@metamask/eth-query": "^4.0.0", - "@metamask/messenger": "^0.1.0", + "@metamask/messenger": "^0.3.0", "@metamask/metamask-eth-abis": "^3.1.1", "@metamask/nonce-tracker": "^6.0.0", "@metamask/rpc-errors": "^7.0.2", diff --git a/yarn.lock b/yarn.lock index 001868b6d24..d73f8f63a2e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3824,13 +3824,6 @@ __metadata: languageName: unknown linkType: soft -"@metamask/messenger@npm:^0.1.0": - version: 0.1.0 - resolution: "@metamask/messenger@npm:0.1.0" - checksum: 10/5d6105865255e72571df143c648ebfb42b04ead24cd6bade758f0340eafba3790d9ff0818bd06fbda17799e3253ac05df51d9e13ebfd0c710e68fd1c0d1007a9 - languageName: node - linkType: hard - "@metamask/messenger@npm:^0.3.0, @metamask/messenger@workspace:packages/messenger": version: 0.0.0-use.local resolution: "@metamask/messenger@workspace:packages/messenger" @@ -4793,7 +4786,7 @@ __metadata: "@metamask/eth-query": "npm:^4.0.0" "@metamask/ethjs-provider-http": "npm:^0.3.0" "@metamask/gas-fee-controller": "npm:^24.0.0" - "@metamask/messenger": "npm:^0.1.0" + "@metamask/messenger": "npm:^0.3.0" "@metamask/metamask-eth-abis": "npm:^3.1.1" "@metamask/network-controller": "npm:^24.2.0" "@metamask/nonce-tracker": "npm:^6.0.0" From c07c63dfd57939465cf386a82b78ff63cd592e79 Mon Sep 17 00:00:00 2001 From: Michele Esposito Date: Tue, 23 Sep 2025 13:54:35 +0200 Subject: [PATCH 33/69] fix `NftController` lint --- packages/assets-controllers/src/NftController.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/assets-controllers/src/NftController.ts b/packages/assets-controllers/src/NftController.ts index 9dfd924efd6..8a18e547b5f 100644 --- a/packages/assets-controllers/src/NftController.ts +++ b/packages/assets-controllers/src/NftController.ts @@ -9,7 +9,7 @@ import { BaseController, type ControllerStateChangeEvent, type ControllerGetStateAction, - StateMetadata, + type StateMetadata, } from '@metamask/base-controller/next'; import { safelyExecute, From cf380bd510987373efb12c74b174fe016d022a92 Mon Sep 17 00:00:00 2001 From: Michele Esposito Date: Tue, 23 Sep 2025 14:04:51 +0200 Subject: [PATCH 34/69] fix changelogs --- packages/polling-controller/CHANGELOG.md | 4 ++++ packages/transaction-controller/CHANGELOG.md | 10 +++++----- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/packages/polling-controller/CHANGELOG.md b/packages/polling-controller/CHANGELOG.md index 6a4a8b3fff1..d10662fdc96 100644 --- a/packages/polling-controller/CHANGELOG.md +++ b/packages/polling-controller/CHANGELOG.md @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Added + +- Add `StaticIntervalPollingControllerNext` to extend from `@metamask/base-controller/next` ([#6386](https://github.com/MetaMask/core/pull/6386)) + ### Changed - Bump `@metamask/base-controller` from `^8.0.1` to `^8.4.0` ([#6284](https://github.com/MetaMask/core/pull/6284), [#6355](https://github.com/MetaMask/core/pull/6355), [#6465](https://github.com/MetaMask/core/pull/6465), [#6632](https://github.com/MetaMask/core/pull/6632)) diff --git a/packages/transaction-controller/CHANGELOG.md b/packages/transaction-controller/CHANGELOG.md index 5c2f9c79059..de3c351b3d7 100644 --- a/packages/transaction-controller/CHANGELOG.md +++ b/packages/transaction-controller/CHANGELOG.md @@ -7,6 +7,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Changed + +- **BREAKING:** Use new `Messenger` from `@metamask/messenger` ([#6386](https://github.com/MetaMask/core/pull/6386)) + - Previously, `TransactionController` accepted a `RestrictedMessenger` instance from `@metamask/base-controller`. + ## [60.4.0] ### Added @@ -43,11 +48,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Add `isGasFeeIncluded` to `TransactionMeta`, `TransactionBatchRequest` and `addTransaction` options so the client can signal that MetaMask is compensated for the gas fee by the transaction ([#6428](https://github.com/MetaMask/core/pull/6428)) - Add optional `gasUsed` property to `TransactionMeta`, returned by the transaction simulation result ([#6410](https://github.com/MetaMask/core/pull/6410)) -### Changed - -- **BREAKING:** Use new `Messenger` from `@metamask/messenger` ([#6386](https://github.com/MetaMask/core/pull/6386)) - - Previously, `TransactionController` accepted a `RestrictedMessenger` instance from `@metamask/base-controller`. - ## [60.1.0] ### Added From d8541b39ad85ac81659048550b380105cac46fcc Mon Sep 17 00:00:00 2001 From: Michele Esposito Date: Tue, 23 Sep 2025 14:07:57 +0200 Subject: [PATCH 35/69] add entry to gas-fee-controller changelog --- packages/gas-fee-controller/CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/gas-fee-controller/CHANGELOG.md b/packages/gas-fee-controller/CHANGELOG.md index 6a3c877bbab..b8c1c7ea06c 100644 --- a/packages/gas-fee-controller/CHANGELOG.md +++ b/packages/gas-fee-controller/CHANGELOG.md @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - Add two new controller state metadata properties: `includeInStateLogs` and `usedInUi` ([#6473](https://github.com/MetaMask/core/pull/6473)) +- Export `GasFeeMessenger` type ([#6386](https://github.com/MetaMask/core/pull/6386)) ### Changed From fa9084b5e406fa7f7db56f518a0ce00f3b775e19 Mon Sep 17 00:00:00 2001 From: Michele Esposito Date: Tue, 23 Sep 2025 15:18:59 +0200 Subject: [PATCH 36/69] migrate leftover `messagingSystem` usage --- packages/assets-controllers/src/TokenBalancesController.ts | 4 ++-- .../bridge-status-controller/src/bridge-status-controller.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/assets-controllers/src/TokenBalancesController.ts b/packages/assets-controllers/src/TokenBalancesController.ts index 09688ae36e2..db8ba047d8e 100644 --- a/packages/assets-controllers/src/TokenBalancesController.ts +++ b/packages/assets-controllers/src/TokenBalancesController.ts @@ -259,12 +259,12 @@ export class TokenBalancesController extends StaticIntervalPollingController<{ ); // Register action handlers for polling interval control - this.messagingSystem.registerActionHandler( + this.messenger.registerActionHandler( `TokenBalancesController:updateChainPollingConfigs`, this.updateChainPollingConfigs.bind(this), ); - this.messagingSystem.registerActionHandler( + this.messenger.registerActionHandler( `TokenBalancesController:getChainPollingConfig`, this.getChainPollingConfig.bind(this), ); diff --git a/packages/bridge-status-controller/src/bridge-status-controller.ts b/packages/bridge-status-controller/src/bridge-status-controller.ts index 9369c66e31f..ae57a883577 100644 --- a/packages/bridge-status-controller/src/bridge-status-controller.ts +++ b/packages/bridge-status-controller/src/bridge-status-controller.ts @@ -187,7 +187,7 @@ export class BridgeStatusController extends StaticIntervalPollingController Date: Tue, 23 Sep 2025 15:24:09 +0200 Subject: [PATCH 37/69] fix changelogs --- packages/bridge-controller/CHANGELOG.md | 7 +++++-- packages/gas-fee-controller/CHANGELOG.md | 2 +- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/packages/bridge-controller/CHANGELOG.md b/packages/bridge-controller/CHANGELOG.md index e89855a914a..78f32d0cb74 100644 --- a/packages/bridge-controller/CHANGELOG.md +++ b/packages/bridge-controller/CHANGELOG.md @@ -7,6 +7,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Changed + +- **BREAKING:** Use new `Messenger` from `@metamask/messenger` ([#6444](https://github.com/MetaMask/core/pull/6444)) + - Previously, `BridgeController` accepted a `RestrictedMessenger` instance from `@metamask/base-controller`. + ## [44.0.0] ### Changed @@ -62,8 +67,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed -- **BREAKING:** Use new `Messenger` from `@metamask/messenger` ([#6444](https://github.com/MetaMask/core/pull/6444)) - - Previously, `BridgeController` accepted a `RestrictedMessenger` instance from `@metamask/base-controller`. - **BREAKING** Rename QuotesError and InputSourceDestinationSwitched events to match segment schema ([#6447](https://github.com/MetaMask/core/pull/6447)) - Bump `@metamask/base-controller` from `^8.2.0` to `^8.3.0` ([#6465](https://github.com/MetaMask/core/pull/6465)) - **BREAKING** Rename `gasless7702` to `gasIncluded7702` in QuoteRequest and Quote types diff --git a/packages/gas-fee-controller/CHANGELOG.md b/packages/gas-fee-controller/CHANGELOG.md index b8c1c7ea06c..374de43f2a6 100644 --- a/packages/gas-fee-controller/CHANGELOG.md +++ b/packages/gas-fee-controller/CHANGELOG.md @@ -10,7 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - Add two new controller state metadata properties: `includeInStateLogs` and `usedInUi` ([#6473](https://github.com/MetaMask/core/pull/6473)) -- Export `GasFeeMessenger` type ([#6386](https://github.com/MetaMask/core/pull/6386)) +- Export `GasFeeMessenger` type ([#6386](https://github.com/MetaMask/core/pull/6386), [#6444](https://github.com/MetaMask/core/pull/6444)) ### Changed From 126e88c8950bdbd609b1d3dc0adc69735b0a3ed3 Mon Sep 17 00:00:00 2001 From: Michele Esposito Date: Tue, 23 Sep 2025 15:27:39 +0200 Subject: [PATCH 38/69] apply suggestion from @mcmire --- packages/assets-controllers/CHANGELOG.md | 4 ++++ packages/bridge-controller/CHANGELOG.md | 4 ++++ packages/bridge-controller/src/index.ts | 1 + 3 files changed, 9 insertions(+) diff --git a/packages/assets-controllers/CHANGELOG.md b/packages/assets-controllers/CHANGELOG.md index 50c5704a7e6..fd4558f8455 100644 --- a/packages/assets-controllers/CHANGELOG.md +++ b/packages/assets-controllers/CHANGELOG.md @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Added + +- Add export for `CurrencyRateMessenger` ([#6444](https://github.com/MetaMask/core/pull/6444)) + ### Changed - **BREAKING:** Migrate the following controllers to the new `Messenger` from `@metamask/messenger` ([#6444](https://github.com/MetaMask/core/pull/6444)) diff --git a/packages/bridge-controller/CHANGELOG.md b/packages/bridge-controller/CHANGELOG.md index 78f32d0cb74..9ca7e8c6786 100644 --- a/packages/bridge-controller/CHANGELOG.md +++ b/packages/bridge-controller/CHANGELOG.md @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Added + +- Add `BridgeControllerGetStateAction` type ([#6444](https://github.com/MetaMask/core/pull/6444)) + ### Changed - **BREAKING:** Use new `Messenger` from `@metamask/messenger` ([#6444](https://github.com/MetaMask/core/pull/6444)) diff --git a/packages/bridge-controller/src/index.ts b/packages/bridge-controller/src/index.ts index 53f9ee0fa27..c4fa4f16416 100644 --- a/packages/bridge-controller/src/index.ts +++ b/packages/bridge-controller/src/index.ts @@ -57,6 +57,7 @@ export { RequestStatus, BridgeUserAction, BridgeBackgroundAction, + type BridgeControllerGetStateAction, } from './types'; export { From d927cc4310619c053b4e7459a5f6fd1dd281b826 Mon Sep 17 00:00:00 2001 From: Michele Esposito Date: Wed, 24 Sep 2025 15:09:23 +0200 Subject: [PATCH 39/69] migrate `BlockTrackerPollingController` --- packages/polling-controller/CHANGELOG.md | 8 ++------ .../src/BlockTrackerPollingController.test.ts | 14 +++++++------- .../src/BlockTrackerPollingController.ts | 2 +- 3 files changed, 10 insertions(+), 14 deletions(-) diff --git a/packages/polling-controller/CHANGELOG.md b/packages/polling-controller/CHANGELOG.md index 37725c16de7..abf9b7b8c97 100644 --- a/packages/polling-controller/CHANGELOG.md +++ b/packages/polling-controller/CHANGELOG.md @@ -7,14 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] -### Added - -- Add `StaticIntervalPollingControllerNext` to extend from `@metamask/base-controller/next` ([#6386](https://github.com/MetaMask/core/pull/6386)) - ### Changed -- **BREAKING:** Use new `Messenger` from `@metamask/messenger` for `StaticIntervalPollingController` ([#6444](https://github.com/MetaMask/core/pull/6444)) - - Previously, `StaticIntervalPollingController` accepted a `RestrictedMessenger` instance from `@metamask/base-controller`. +- **BREAKING:** Use new `Messenger` from `@metamask/messenger` for `StaticIntervalPollingController` and `BlockTrackerPollingController` ([#6444](https://github.com/MetaMask/core/pull/6444)) + - Previously, `StaticIntervalPollingController` and `BlockTrackerPollingController` accepted a `RestrictedMessenger` instance from `@metamask/base-controller`. - Bump `@metamask/base-controller` from `^8.0.1` to `^8.4.0` ([#6284](https://github.com/MetaMask/core/pull/6284), [#6355](https://github.com/MetaMask/core/pull/6355), [#6465](https://github.com/MetaMask/core/pull/6465), [#6632](https://github.com/MetaMask/core/pull/6632)) - Bump `@metamask/controller-utils` from `^11.10.0` to `^11.14.0` ([#6069](https://github.com/MetaMask/core/pull/6069), [#6303](https://github.com/MetaMask/core/pull/6303), [#6620](https://github.com/MetaMask/core/pull/6620), [#6629](https://github.com/MetaMask/core/pull/6629)) - Bump `@metamask/utils` from `^11.2.0` to `^11.4.2` ([#6054](https://github.com/MetaMask/core/pull/6054)) diff --git a/packages/polling-controller/src/BlockTrackerPollingController.test.ts b/packages/polling-controller/src/BlockTrackerPollingController.test.ts index d5c8615a3ff..5824691a81c 100644 --- a/packages/polling-controller/src/BlockTrackerPollingController.test.ts +++ b/packages/polling-controller/src/BlockTrackerPollingController.test.ts @@ -1,4 +1,8 @@ -import { Messenger } from '@metamask/base-controller'; +import { + MOCK_ANY_NAMESPACE, + Messenger, + MockAnyNamespace, +} from '@metamask/messenger'; import type { NetworkClient } from '@metamask/network-controller'; import EventEmitter from 'events'; import { useFakeTimers } from 'sinon'; @@ -43,17 +47,13 @@ class TestBlockTracker extends EventEmitter { describe('BlockTrackerPollingController', () => { let clock: sinon.SinonFakeTimers; - // TODO: Replace `any` with type - // eslint-disable-next-line @typescript-eslint/no-explicit-any - let mockMessenger: any; + let mockMessenger: Messenger; let controller: ChildBlockTrackerPollingController; let mainnetBlockTracker: TestBlockTracker; let goerliBlockTracker: TestBlockTracker; let sepoliaBlockTracker: TestBlockTracker; beforeEach(() => { - // TODO: Replace `any` with type - // eslint-disable-next-line @typescript-eslint/no-explicit-any - mockMessenger = new Messenger(); + mockMessenger = new Messenger({ namespace: MOCK_ANY_NAMESPACE }); controller = new ChildBlockTrackerPollingController({ messenger: mockMessenger, metadata: {}, diff --git a/packages/polling-controller/src/BlockTrackerPollingController.ts b/packages/polling-controller/src/BlockTrackerPollingController.ts index f7221768f90..6f4725577e3 100644 --- a/packages/polling-controller/src/BlockTrackerPollingController.ts +++ b/packages/polling-controller/src/BlockTrackerPollingController.ts @@ -1,4 +1,4 @@ -import { BaseController } from '@metamask/base-controller'; +import { BaseController } from '@metamask/base-controller/next'; import type { NetworkClientId, NetworkClient, From 601100bd065ce9fa368cc01f1f455333840848b8 Mon Sep 17 00:00:00 2001 From: Michele Esposito Date: Wed, 24 Sep 2025 15:10:19 +0200 Subject: [PATCH 40/69] update tsconfig and README --- README.md | 2 ++ packages/polling-controller/tsconfig.build.json | 3 ++- packages/polling-controller/tsconfig.json | 3 ++- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index fb4cf4a5ee3..baa962a1511 100644 --- a/README.md +++ b/README.md @@ -173,6 +173,7 @@ linkStyle default opacity:0.5 bridge_controller --> base_controller; bridge_controller --> controller_utils; bridge_controller --> gas_fee_controller; + bridge_controller --> messenger; bridge_controller --> multichain_network_controller; bridge_controller --> polling_controller; bridge_controller --> accounts_controller; @@ -305,6 +306,7 @@ linkStyle default opacity:0.5 token_search_discovery_controller --> base_controller; transaction_controller --> base_controller; transaction_controller --> controller_utils; + transaction_controller --> messenger; transaction_controller --> accounts_controller; transaction_controller --> approval_controller; transaction_controller --> eth_json_rpc_provider; diff --git a/packages/polling-controller/tsconfig.build.json b/packages/polling-controller/tsconfig.build.json index ac0df4920c6..c55f67af5af 100644 --- a/packages/polling-controller/tsconfig.build.json +++ b/packages/polling-controller/tsconfig.build.json @@ -8,7 +8,8 @@ "references": [ { "path": "../base-controller/tsconfig.build.json" }, { "path": "../controller-utils/tsconfig.build.json" }, - { "path": "../network-controller/tsconfig.build.json" } + { "path": "../network-controller/tsconfig.build.json" }, + { "path": "../messenger/tsconfig.build.json" } ], "include": ["../../types", "./src"] } diff --git a/packages/polling-controller/tsconfig.json b/packages/polling-controller/tsconfig.json index 9f1187b22dc..ca0d50a83f4 100644 --- a/packages/polling-controller/tsconfig.json +++ b/packages/polling-controller/tsconfig.json @@ -7,7 +7,8 @@ "references": [ { "path": "../base-controller" }, { "path": "../controller-utils" }, - { "path": "../network-controller" } + { "path": "../network-controller" }, + { "path": "../messenger" } ], "include": ["../../types", "./src", "../../tests"] } From 6d0f21d74d46b575c862dcfeda1a423fed68e4f4 Mon Sep 17 00:00:00 2001 From: Michele Esposito Date: Wed, 24 Sep 2025 15:12:15 +0200 Subject: [PATCH 41/69] fix test types --- .../src/BlockTrackerPollingController.test.ts | 2 +- .../src/StaticIntervalPollingController.test.ts | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/polling-controller/src/BlockTrackerPollingController.test.ts b/packages/polling-controller/src/BlockTrackerPollingController.test.ts index 5824691a81c..88321e80b97 100644 --- a/packages/polling-controller/src/BlockTrackerPollingController.test.ts +++ b/packages/polling-controller/src/BlockTrackerPollingController.test.ts @@ -1,7 +1,7 @@ import { MOCK_ANY_NAMESPACE, Messenger, - MockAnyNamespace, + type MockAnyNamespace, } from '@metamask/messenger'; import type { NetworkClient } from '@metamask/network-controller'; import EventEmitter from 'events'; diff --git a/packages/polling-controller/src/StaticIntervalPollingController.test.ts b/packages/polling-controller/src/StaticIntervalPollingController.test.ts index 797f431bc88..380465867e8 100644 --- a/packages/polling-controller/src/StaticIntervalPollingController.test.ts +++ b/packages/polling-controller/src/StaticIntervalPollingController.test.ts @@ -1,4 +1,8 @@ -import { Messenger } from '@metamask/base-controller'; +import { + MOCK_ANY_NAMESPACE, + Messenger, + type MockAnyNamespace, +} from '@metamask/messenger'; import { createDeferredPromise } from '@metamask/utils'; import { useFakeTimers } from 'sinon'; @@ -39,14 +43,10 @@ class ChildBlockTrackerPollingController extends StaticIntervalPollingController describe('StaticIntervalPollingController', () => { let clock: sinon.SinonFakeTimers; - // TODO: Replace `any` with type - // eslint-disable-next-line @typescript-eslint/no-explicit-any - let mockMessenger: any; + let mockMessenger: Messenger; let controller: ChildBlockTrackerPollingController; beforeEach(() => { - // TODO: Replace `any` with type - // eslint-disable-next-line @typescript-eslint/no-explicit-any - mockMessenger = new Messenger(); + mockMessenger = new Messenger({ namespace: MOCK_ANY_NAMESPACE }); controller = new ChildBlockTrackerPollingController({ messenger: mockMessenger, metadata: {}, From 36cfd5d05682a1981f18d5ec75c953d9bc29255f Mon Sep 17 00:00:00 2001 From: Michele Esposito Date: Mon, 29 Sep 2025 10:21:28 +0200 Subject: [PATCH 42/69] migrate `MultichainAssetsController` messenger --- .../MultichainAssetsController.test.ts | 62 +++++++++------- .../MultichainAssetsController.ts | 73 +++++++++---------- 2 files changed, 72 insertions(+), 63 deletions(-) diff --git a/packages/assets-controllers/src/MultichainAssetsController/MultichainAssetsController.test.ts b/packages/assets-controllers/src/MultichainAssetsController/MultichainAssetsController.test.ts index 9f07e38a6ab..1bc95642ae5 100644 --- a/packages/assets-controllers/src/MultichainAssetsController/MultichainAssetsController.test.ts +++ b/packages/assets-controllers/src/MultichainAssetsController/MultichainAssetsController.test.ts @@ -1,4 +1,4 @@ -import { deriveStateFromMetadata, Messenger } from '@metamask/base-controller'; +import { deriveStateFromMetadata } from '@metamask/base-controller/next'; import type { AccountAssetListUpdatedEventPayload, CaipAssetTypeOrId, @@ -11,6 +11,13 @@ import { } from '@metamask/keyring-api'; import { KeyringTypes } from '@metamask/keyring-controller'; import type { InternalAccount } from '@metamask/keyring-internal-api'; +import { + Messenger, + MOCK_ANY_NAMESPACE, + type MessengerActions, + type MessengerEvents, + type MockAnyNamespace, +} from '@metamask/messenger'; import type { PermissionConstraint } from '@metamask/permission-controller'; import type { SubjectPermissions } from '@metamask/permission-controller'; import type { Snap } from '@metamask/snaps-utils'; @@ -27,10 +34,6 @@ import type { MultichainAssetsControllerState, } from './MultichainAssetsController'; import { advanceTime } from '../../../../tests/helpers'; -import type { - ExtractAvailableAction, - ExtractAvailableEvent, -} from '../../../base-controller/tests/helpers'; const mockSolanaAccount: InternalAccount = { type: 'solana:data-account', @@ -216,21 +219,26 @@ const mockGetMetadataReturnValue: AssetMetadataResponse | undefined = { /** * The union of actions that the root messenger allows. */ -type RootAction = ExtractAvailableAction; +type RootAction = MessengerActions; /** * The union of events that the root messenger allows. */ -type RootEvent = ExtractAvailableEvent; +type RootEvent = MessengerEvents; + +/** + * The root messenger type. + */ +type RootMessenger = Messenger; /** - * Constructs the unrestricted messenger. This can be used to call actions and + * Constructs the root messenger. This can be used to call actions and * publish events within the tests for this controller. * - * @returns The unrestricted messenger suited for MultichainAssetsController. + * @returns The root messenger suited for MultichainAssetsController. */ -function getRootMessenger(): Messenger { - return new Messenger(); +function getRootMessenger(): RootMessenger { + return new Messenger({ namespace: MOCK_ANY_NAMESPACE }); } const setupController = ({ @@ -248,20 +256,24 @@ const setupController = ({ const messenger = getRootMessenger(); const multichainAssetsControllerMessenger: MultichainAssetsControllerMessenger = - messenger.getRestricted({ - name: 'MultichainAssetsController', - allowedActions: [ - 'AccountsController:listMultichainAccounts', - 'SnapController:handleRequest', - 'SnapController:getAll', - 'PermissionController:getPermissions', - ], - allowedEvents: [ - 'AccountsController:accountAdded', - 'AccountsController:accountRemoved', - 'AccountsController:accountAssetListUpdated', - ], + new Messenger({ + namespace: 'MultichainAssetsController', + parent: messenger, }); + messenger.delegate({ + messenger: multichainAssetsControllerMessenger, + actions: [ + 'AccountsController:listMultichainAccounts', + 'SnapController:handleRequest', + 'SnapController:getAll', + 'PermissionController:getPermissions', + ], + events: [ + 'AccountsController:accountAdded', + 'AccountsController:accountRemoved', + 'AccountsController:accountAssetListUpdated', + ], + }); const mockSnapHandleRequest = jest.fn(); messenger.registerActionHandler( @@ -827,7 +839,7 @@ describe('MultichainAssetsController', () => { deriveStateFromMetadata( controller.state, controller.metadata, - 'anonymous', + 'includeInDebugSnapshot', ), ).toMatchInlineSnapshot(`Object {}`); }); diff --git a/packages/assets-controllers/src/MultichainAssetsController/MultichainAssetsController.ts b/packages/assets-controllers/src/MultichainAssetsController/MultichainAssetsController.ts index 5b477a83c70..81358d1378a 100644 --- a/packages/assets-controllers/src/MultichainAssetsController/MultichainAssetsController.ts +++ b/packages/assets-controllers/src/MultichainAssetsController/MultichainAssetsController.ts @@ -8,8 +8,8 @@ import { BaseController, type ControllerGetStateAction, type ControllerStateChangeEvent, - type RestrictedMessenger, -} from '@metamask/base-controller'; + type StateMetadata, +} from '@metamask/base-controller/next'; import { isEvmAccountType } from '@metamask/keyring-api'; import type { AccountAssetListUpdatedEventPayload, @@ -18,6 +18,7 @@ import type { } from '@metamask/keyring-api'; import type { InternalAccount } from '@metamask/keyring-internal-api'; import { KeyringClient } from '@metamask/keyring-snap-client'; +import type { Messenger } from '@metamask/messenger'; import type { GetPermissions, PermissionConstraint, @@ -141,12 +142,10 @@ type AllowedEvents = /** * Messenger type for the MultichainAssetsController. */ -export type MultichainAssetsControllerMessenger = RestrictedMessenger< +export type MultichainAssetsControllerMessenger = Messenger< typeof controllerName, MultichainAssetsControllerActions | AllowedActions, - MultichainAssetsControllerEvents | AllowedEvents, - AllowedActions['type'], - AllowedEvents['type'] + MultichainAssetsControllerEvents | AllowedEvents >; /** @@ -156,20 +155,21 @@ export type MultichainAssetsControllerMessenger = RestrictedMessenger< * using the `persist` flag; and if they can be sent to Sentry or not, using * the `anonymous` flag. */ -const assetsControllerMetadata = { - assetsMetadata: { - includeInStateLogs: false, - persist: true, - anonymous: false, - usedInUi: true, - }, - accountsAssets: { - includeInStateLogs: false, - persist: true, - anonymous: false, - usedInUi: true, - }, -}; +const assetsControllerMetadata: StateMetadata = + { + assetsMetadata: { + includeInStateLogs: false, + persist: true, + includeInDebugSnapshot: false, + usedInUi: true, + }, + accountsAssets: { + includeInStateLogs: false, + persist: true, + includeInDebugSnapshot: false, + usedInUi: true, + }, + }; // TODO: make this controller extends StaticIntervalPollingController and update all assetsMetadata once a day. @@ -202,15 +202,15 @@ export class MultichainAssetsController extends BaseController< this.#snaps = {}; - this.messagingSystem.subscribe( + this.messenger.subscribe( 'AccountsController:accountAdded', async (account) => await this.#handleOnAccountAddedEvent(account), ); - this.messagingSystem.subscribe( + this.messenger.subscribe( 'AccountsController:accountRemoved', async (account) => await this.#handleOnAccountRemovedEvent(account), ); - this.messagingSystem.subscribe( + this.messenger.subscribe( 'AccountsController:accountAssetListUpdated', async (event) => await this.#handleAccountAssetListUpdatedEvent(event), ); @@ -237,7 +237,7 @@ export class MultichainAssetsController extends BaseController< * actions. */ #registerMessageHandlers() { - this.messagingSystem.registerActionHandler( + this.messenger.registerActionHandler( 'MultichainAssetsController:getAssetMetadata', this.getAssetMetadata.bind(this), ); @@ -323,7 +323,7 @@ export class MultichainAssetsController extends BaseController< // Trigger fetching metadata for new assets await this.#refreshAssetsMetadata(Array.from(assetsForMetadataRefresh)); - this.messagingSystem.publish(`${controllerName}:accountAssetListUpdated`, { + this.messenger.publish(`${controllerName}:accountAssetListUpdated`, { assets: accountsAndAssetsToUpdate, }); } @@ -364,17 +364,14 @@ export class MultichainAssetsController extends BaseController< this.update((state) => { state.accountsAssets[account.id] = assets; }); - this.messagingSystem.publish( - `${controllerName}:accountAssetListUpdated`, - { - assets: { - [account.id]: { - added: assets, - removed: [], - }, + this.messenger.publish(`${controllerName}:accountAssetListUpdated`, { + assets: { + [account.id]: { + added: assets, + removed: [], }, }, - ); + }); } } @@ -510,7 +507,7 @@ export class MultichainAssetsController extends BaseController< */ #getAllSnaps(): Snap[] { // TODO: Use dedicated SnapController's action once available for this: - return this.messagingSystem + return this.messenger .call('SnapController:getAll') .filter((snap) => snap.enabled && !snap.blocked); } @@ -524,7 +521,7 @@ export class MultichainAssetsController extends BaseController< #getSnapsPermissions( origin: string, ): SubjectPermissions { - return this.messagingSystem.call( + return this.messenger.call( 'PermissionController:getPermissions', origin, ) as SubjectPermissions; @@ -542,7 +539,7 @@ export class MultichainAssetsController extends BaseController< snapId: string, ): Promise { try { - return (await this.messagingSystem.call('SnapController:handleRequest', { + return (await this.messenger.call('SnapController:handleRequest', { snapId: snapId as SnapId, origin: 'metamask', handler: HandlerType.OnAssetsLookup, @@ -584,7 +581,7 @@ export class MultichainAssetsController extends BaseController< #getClient(snapId: string): KeyringClient { return new KeyringClient({ send: async (request: JsonRpcRequest) => - (await this.messagingSystem.call('SnapController:handleRequest', { + (await this.messenger.call('SnapController:handleRequest', { snapId: snapId as SnapId, origin: 'metamask', handler: HandlerType.OnKeyringRequest, From bffbca08bdff8de61065a96975acaf6895d78594 Mon Sep 17 00:00:00 2001 From: Michele Esposito Date: Mon, 29 Sep 2025 10:40:19 +0200 Subject: [PATCH 43/69] rename `anonymous` to `includeInDebugSnapshot` --- .../src/AccountTrackerController.test.ts | 2 +- .../src/AccountTrackerController.ts | 5 +++-- .../src/CurrencyRateController.test.ts | 10 +++++----- .../src/CurrencyRateController.ts | 7 ++++--- .../DeFiPositionsController.test.ts | 4 ++-- .../DeFiPositionsController.ts | 4 ++-- .../MultichainAssetsRatesController.test.ts | 2 +- .../MultichainAssetsRatesController.ts | 7 ++++--- .../src/TokenBalancesController.test.ts | 2 +- .../src/TokenBalancesController.ts | 5 +++-- .../src/TokenListController.test.ts | 2 +- .../src/TokenListController.ts | 7 ++++--- .../src/TokenRatesController.test.ts | 2 +- .../src/TokenRatesController.ts | 5 +++-- .../src/bridge-controller.test.ts | 4 ++-- .../bridge-controller/src/bridge-controller.ts | 18 +++++++++--------- .../src/bridge-status-controller.test.ts | 2 +- .../src/bridge-status-controller.ts | 4 ++-- 18 files changed, 49 insertions(+), 43 deletions(-) diff --git a/packages/assets-controllers/src/AccountTrackerController.test.ts b/packages/assets-controllers/src/AccountTrackerController.test.ts index 2f5d80abbad..b999ceed0e9 100644 --- a/packages/assets-controllers/src/AccountTrackerController.test.ts +++ b/packages/assets-controllers/src/AccountTrackerController.test.ts @@ -1293,7 +1293,7 @@ describe('AccountTrackerController', () => { deriveStateFromMetadata( controller.state, controller.metadata, - 'anonymous', + 'includeInDebugSnapshot', ), ).toMatchInlineSnapshot(`Object {}`); }); diff --git a/packages/assets-controllers/src/AccountTrackerController.ts b/packages/assets-controllers/src/AccountTrackerController.ts index 2e9966fcb9a..a4bac5fd620 100644 --- a/packages/assets-controllers/src/AccountTrackerController.ts +++ b/packages/assets-controllers/src/AccountTrackerController.ts @@ -8,6 +8,7 @@ import type { import type { ControllerStateChangeEvent, ControllerGetStateAction, + StateMetadata, } from '@metamask/base-controller/next'; import { query, @@ -120,11 +121,11 @@ export type AccountTrackerControllerState = { accountsByChainId: Record; }; -const accountTrackerMetadata = { +const accountTrackerMetadata: StateMetadata = { accountsByChainId: { includeInStateLogs: false, persist: true, - anonymous: false, + includeInDebugSnapshot: false, usedInUi: true, }, }; diff --git a/packages/assets-controllers/src/CurrencyRateController.test.ts b/packages/assets-controllers/src/CurrencyRateController.test.ts index 03e304098bc..e11d7683785 100644 --- a/packages/assets-controllers/src/CurrencyRateController.test.ts +++ b/packages/assets-controllers/src/CurrencyRateController.test.ts @@ -798,14 +798,14 @@ describe('CurrencyRateController', () => { describe('metadata', () => { it('includes expected state in debug snapshots', () => { const controller = new CurrencyRateController({ - messenger: getRestrictedMessenger(), + messenger: getCurrencyRateControllerMessenger(), }); expect( deriveStateFromMetadata( controller.state, controller.metadata, - 'anonymous', + 'includeInDebugSnapshot', ), ).toMatchInlineSnapshot(` Object { @@ -823,7 +823,7 @@ describe('CurrencyRateController', () => { it('includes expected state in state logs', () => { const controller = new CurrencyRateController({ - messenger: getRestrictedMessenger(), + messenger: getCurrencyRateControllerMessenger(), }); expect( @@ -848,7 +848,7 @@ describe('CurrencyRateController', () => { it('persists expected state', () => { const controller = new CurrencyRateController({ - messenger: getRestrictedMessenger(), + messenger: getCurrencyRateControllerMessenger(), }); expect( @@ -873,7 +873,7 @@ describe('CurrencyRateController', () => { it('exposes expected state to UI', () => { const controller = new CurrencyRateController({ - messenger: getRestrictedMessenger(), + messenger: getCurrencyRateControllerMessenger(), }); expect( diff --git a/packages/assets-controllers/src/CurrencyRateController.ts b/packages/assets-controllers/src/CurrencyRateController.ts index 66da864fab8..a116e8ac337 100644 --- a/packages/assets-controllers/src/CurrencyRateController.ts +++ b/packages/assets-controllers/src/CurrencyRateController.ts @@ -1,6 +1,7 @@ import type { ControllerGetStateAction, ControllerStateChangeEvent, + StateMetadata, } from '@metamask/base-controller/next'; import { TESTNET_TICKER_SYMBOLS, @@ -57,17 +58,17 @@ export type CurrencyRateMessenger = Messenger< CurrencyRateControllerEvents >; -const metadata = { +const metadata: StateMetadata = { currentCurrency: { includeInStateLogs: true, persist: true, - anonymous: true, + includeInDebugSnapshot: true, usedInUi: true, }, currencyRates: { includeInStateLogs: true, persist: true, - anonymous: true, + includeInDebugSnapshot: true, usedInUi: true, }, }; diff --git a/packages/assets-controllers/src/DeFiPositionsController/DeFiPositionsController.test.ts b/packages/assets-controllers/src/DeFiPositionsController/DeFiPositionsController.test.ts index 7ddc2b9c408..cd5b5f3f8dc 100644 --- a/packages/assets-controllers/src/DeFiPositionsController/DeFiPositionsController.test.ts +++ b/packages/assets-controllers/src/DeFiPositionsController/DeFiPositionsController.test.ts @@ -1,4 +1,4 @@ -import { deriveStateFromMetadata } from '@metamask/base-controller'; +import { deriveStateFromMetadata } from '@metamask/base-controller/next'; import { BtcAccountType } from '@metamask/keyring-api'; import { MOCK_ANY_NAMESPACE, @@ -532,7 +532,7 @@ describe('DeFiPositionsController', () => { deriveStateFromMetadata( controller.state, controller.metadata, - 'anonymous', + 'includeInDebugSnapshot', ), ).toMatchInlineSnapshot(`Object {}`); }); diff --git a/packages/assets-controllers/src/DeFiPositionsController/DeFiPositionsController.ts b/packages/assets-controllers/src/DeFiPositionsController/DeFiPositionsController.ts index a6b5730fa0f..9b53e15443c 100644 --- a/packages/assets-controllers/src/DeFiPositionsController/DeFiPositionsController.ts +++ b/packages/assets-controllers/src/DeFiPositionsController/DeFiPositionsController.ts @@ -70,13 +70,13 @@ const controllerMetadata: StateMetadata = { allDeFiPositions: { includeInStateLogs: false, persist: false, - anonymous: false, + includeInDebugSnapshot: false, usedInUi: true, }, allDeFiPositionsCount: { includeInStateLogs: false, persist: false, - anonymous: false, + includeInDebugSnapshot: false, usedInUi: false, }, }; diff --git a/packages/assets-controllers/src/MultichainAssetsRatesController/MultichainAssetsRatesController.test.ts b/packages/assets-controllers/src/MultichainAssetsRatesController/MultichainAssetsRatesController.test.ts index 9dda89b4342..7ce1cdc7b9c 100644 --- a/packages/assets-controllers/src/MultichainAssetsRatesController/MultichainAssetsRatesController.test.ts +++ b/packages/assets-controllers/src/MultichainAssetsRatesController/MultichainAssetsRatesController.test.ts @@ -1080,7 +1080,7 @@ describe('MultichainAssetsRatesController', () => { deriveStateFromMetadata( controller.state, controller.metadata, - 'anonymous', + 'includeInDebugSnapshot', ), ).toMatchInlineSnapshot(` Object { diff --git a/packages/assets-controllers/src/MultichainAssetsRatesController/MultichainAssetsRatesController.ts b/packages/assets-controllers/src/MultichainAssetsRatesController/MultichainAssetsRatesController.ts index 866a6057c2b..4aa863496d0 100644 --- a/packages/assets-controllers/src/MultichainAssetsRatesController/MultichainAssetsRatesController.ts +++ b/packages/assets-controllers/src/MultichainAssetsRatesController/MultichainAssetsRatesController.ts @@ -6,6 +6,7 @@ import type { import type { ControllerStateChangeEvent, ControllerGetStateAction, + StateMetadata, } from '@metamask/base-controller/next'; import { type CaipAssetType, isEvmAccountType } from '@metamask/keyring-api'; import type { @@ -157,17 +158,17 @@ export type MultichainAssetsRatesPollingInput = { accountId: string; }; -const metadata = { +const metadata: StateMetadata = { conversionRates: { includeInStateLogs: false, persist: true, - anonymous: true, + includeInDebugSnapshot: true, usedInUi: true, }, historicalPrices: { includeInStateLogs: false, persist: false, - anonymous: true, + includeInDebugSnapshot: true, usedInUi: true, }, }; diff --git a/packages/assets-controllers/src/TokenBalancesController.test.ts b/packages/assets-controllers/src/TokenBalancesController.test.ts index 07a02719910..53a016626dc 100644 --- a/packages/assets-controllers/src/TokenBalancesController.test.ts +++ b/packages/assets-controllers/src/TokenBalancesController.test.ts @@ -4121,7 +4121,7 @@ describe('TokenBalancesController', () => { deriveStateFromMetadata( controller.state, controller.metadata, - 'anonymous', + 'includeInDebugSnapshot', ), ).toMatchInlineSnapshot(`Object {}`); }); diff --git a/packages/assets-controllers/src/TokenBalancesController.ts b/packages/assets-controllers/src/TokenBalancesController.ts index db8ba047d8e..89e98b72e9f 100644 --- a/packages/assets-controllers/src/TokenBalancesController.ts +++ b/packages/assets-controllers/src/TokenBalancesController.ts @@ -6,6 +6,7 @@ import type { import type { ControllerGetStateAction, ControllerStateChangeEvent, + StateMetadata, } from '@metamask/base-controller/next'; import { BNToHex, @@ -54,11 +55,11 @@ export type ChecksumAddress = Hex; const CONTROLLER = 'TokenBalancesController' as const; const DEFAULT_INTERVAL_MS = 180_000; // 3 minutes -const metadata = { +const metadata: StateMetadata = { tokenBalances: { includeInStateLogs: false, persist: true, - anonymous: false, + includeInDebugSnapshot: false, usedInUi: true, }, }; diff --git a/packages/assets-controllers/src/TokenListController.test.ts b/packages/assets-controllers/src/TokenListController.test.ts index e4ee22a8979..84ff24accbd 100644 --- a/packages/assets-controllers/src/TokenListController.test.ts +++ b/packages/assets-controllers/src/TokenListController.test.ts @@ -1298,7 +1298,7 @@ describe('TokenListController', () => { deriveStateFromMetadata( controller.state, controller.metadata, - 'anonymous', + 'includeInDebugSnapshot', ), ).toMatchInlineSnapshot(` Object { diff --git a/packages/assets-controllers/src/TokenListController.ts b/packages/assets-controllers/src/TokenListController.ts index ffa989b3730..3b40ae7b6df 100644 --- a/packages/assets-controllers/src/TokenListController.ts +++ b/packages/assets-controllers/src/TokenListController.ts @@ -1,6 +1,7 @@ import type { ControllerGetStateAction, ControllerStateChangeEvent, + StateMetadata, } from '@metamask/base-controller/next'; import { safelyExecute } from '@metamask/controller-utils'; import type { Messenger } from '@metamask/messenger'; @@ -74,17 +75,17 @@ export type TokenListControllerMessenger = Messenger< TokenListControllerEvents | AllowedEvents >; -const metadata = { +const metadata: StateMetadata = { tokensChainsCache: { includeInStateLogs: false, persist: true, - anonymous: true, + includeInDebugSnapshot: true, usedInUi: true, }, preventPollingOnNetworkRestart: { includeInStateLogs: false, persist: true, - anonymous: true, + includeInDebugSnapshot: true, usedInUi: false, }, }; diff --git a/packages/assets-controllers/src/TokenRatesController.test.ts b/packages/assets-controllers/src/TokenRatesController.test.ts index f695ab4b633..c4b51141001 100644 --- a/packages/assets-controllers/src/TokenRatesController.test.ts +++ b/packages/assets-controllers/src/TokenRatesController.test.ts @@ -2710,7 +2710,7 @@ describe('TokenRatesController', () => { deriveStateFromMetadata( controller.state, controller.metadata, - 'anonymous', + 'includeInDebugSnapshot', ), ).toMatchInlineSnapshot(`Object {}`); }); diff --git a/packages/assets-controllers/src/TokenRatesController.ts b/packages/assets-controllers/src/TokenRatesController.ts index 587c4396be7..f5d1d382d4f 100644 --- a/packages/assets-controllers/src/TokenRatesController.ts +++ b/packages/assets-controllers/src/TokenRatesController.ts @@ -6,6 +6,7 @@ import type { import type { ControllerGetStateAction, ControllerStateChangeEvent, + StateMetadata, } from '@metamask/base-controller/next'; import { safelyExecute, @@ -200,11 +201,11 @@ async function getCurrencyConversionRate({ } } -const tokenRatesControllerMetadata = { +const tokenRatesControllerMetadata: StateMetadata = { marketData: { includeInStateLogs: false, persist: true, - anonymous: false, + includeInDebugSnapshot: false, usedInUi: true, }, }; diff --git a/packages/bridge-controller/src/bridge-controller.test.ts b/packages/bridge-controller/src/bridge-controller.test.ts index 4cd8ad60725..ea7b51d3707 100644 --- a/packages/bridge-controller/src/bridge-controller.test.ts +++ b/packages/bridge-controller/src/bridge-controller.test.ts @@ -1,7 +1,7 @@ /* eslint-disable jest/no-restricted-matchers */ /* eslint-disable jest/no-conditional-in-test */ import { Contract } from '@ethersproject/contracts'; -import { deriveStateFromMetadata } from '@metamask/base-controller'; +import { deriveStateFromMetadata } from '@metamask/base-controller/next'; import { EthAccountType, EthScope, @@ -2444,7 +2444,7 @@ describe('BridgeController', function () { deriveStateFromMetadata( bridgeController.state, bridgeController.metadata, - 'anonymous', + 'includeInDebugSnapshot', ), ).toMatchInlineSnapshot(`Object {}`); }); diff --git a/packages/bridge-controller/src/bridge-controller.ts b/packages/bridge-controller/src/bridge-controller.ts index 29df14a2491..f8fece58577 100644 --- a/packages/bridge-controller/src/bridge-controller.ts +++ b/packages/bridge-controller/src/bridge-controller.ts @@ -80,55 +80,55 @@ const metadata: StateMetadata = { quoteRequest: { includeInStateLogs: true, persist: false, - anonymous: false, + includeInDebugSnapshot: false, usedInUi: true, }, quotes: { includeInStateLogs: true, persist: false, - anonymous: false, + includeInDebugSnapshot: false, usedInUi: true, }, quotesInitialLoadTime: { includeInStateLogs: true, persist: false, - anonymous: false, + includeInDebugSnapshot: false, usedInUi: true, }, quotesLastFetched: { includeInStateLogs: true, persist: false, - anonymous: false, + includeInDebugSnapshot: false, usedInUi: true, }, quotesLoadingStatus: { includeInStateLogs: true, persist: false, - anonymous: false, + includeInDebugSnapshot: false, usedInUi: true, }, quoteFetchError: { includeInStateLogs: true, persist: false, - anonymous: false, + includeInDebugSnapshot: false, usedInUi: true, }, quotesRefreshCount: { includeInStateLogs: true, persist: false, - anonymous: false, + includeInDebugSnapshot: false, usedInUi: true, }, assetExchangeRates: { includeInStateLogs: true, persist: false, - anonymous: false, + includeInDebugSnapshot: false, usedInUi: true, }, minimumBalanceForRentExemptionInLamports: { includeInStateLogs: true, persist: false, - anonymous: false, + includeInDebugSnapshot: false, usedInUi: true, }, }; diff --git a/packages/bridge-status-controller/src/bridge-status-controller.test.ts b/packages/bridge-status-controller/src/bridge-status-controller.test.ts index 52204c4e8d3..4b1dd78e0a8 100644 --- a/packages/bridge-status-controller/src/bridge-status-controller.test.ts +++ b/packages/bridge-status-controller/src/bridge-status-controller.test.ts @@ -3708,7 +3708,7 @@ describe('BridgeStatusController', () => { deriveStateFromMetadata( controller.state, controller.metadata, - 'anonymous', + 'includeInDebugSnapshot', ), ).toMatchInlineSnapshot(`Object {}`); }); diff --git a/packages/bridge-status-controller/src/bridge-status-controller.ts b/packages/bridge-status-controller/src/bridge-status-controller.ts index ae57a883577..8bfe168c2ed 100644 --- a/packages/bridge-status-controller/src/bridge-status-controller.ts +++ b/packages/bridge-status-controller/src/bridge-status-controller.ts @@ -1,5 +1,5 @@ import type { AccountsControllerState } from '@metamask/accounts-controller'; -import type { StateMetadata } from '@metamask/base-controller'; +import type { StateMetadata } from '@metamask/base-controller/next'; import type { QuoteMetadata, RequiredEventContextFromClient, @@ -81,7 +81,7 @@ const metadata: StateMetadata = { txHistory: { includeInStateLogs: true, persist: true, - anonymous: false, + includeInDebugSnapshot: false, usedInUi: true, }, }; From 1b32baac855b944f3645575ae0efc46afec27417 Mon Sep 17 00:00:00 2001 From: Michele Esposito Date: Mon, 29 Sep 2025 10:49:55 +0200 Subject: [PATCH 44/69] migrate `MultichainBalancesController` messenger --- .../MultichainBalancesController.test.ts | 52 +++++++++++++------ .../MultichainBalancesController.ts | 50 ++++++++---------- 2 files changed, 57 insertions(+), 45 deletions(-) diff --git a/packages/assets-controllers/src/MultichainBalancesController/MultichainBalancesController.test.ts b/packages/assets-controllers/src/MultichainBalancesController/MultichainBalancesController.test.ts index 7d28fc95176..53f17015c27 100644 --- a/packages/assets-controllers/src/MultichainBalancesController/MultichainBalancesController.test.ts +++ b/packages/assets-controllers/src/MultichainBalancesController/MultichainBalancesController.test.ts @@ -1,4 +1,4 @@ -import { Messenger, deriveStateFromMetadata } from '@metamask/base-controller'; +import { deriveStateFromMetadata } from '@metamask/base-controller/next'; import type { Balance, CaipAssetType } from '@metamask/keyring-api'; import { BtcAccountType, @@ -13,6 +13,13 @@ import { } from '@metamask/keyring-api'; import { KeyringTypes } from '@metamask/keyring-controller'; import type { InternalAccount } from '@metamask/keyring-internal-api'; +import { + MOCK_ANY_NAMESPACE, + Messenger, + type MessengerActions, + type MessengerEvents, + type MockAnyNamespace, +} from '@metamask/messenger'; import { v4 as uuidv4 } from 'uuid'; import { MultichainBalancesController } from '.'; @@ -21,10 +28,6 @@ import type { MultichainBalancesControllerState, } from '.'; import { getDefaultMultichainBalancesControllerState } from './MultichainBalancesController'; -import type { - ExtractAvailableAction, - ExtractAvailableEvent, -} from '../../../base-controller/tests/helpers'; const mockBtcAccount = { address: 'bc1qssdcp5kvwh6nghzg9tuk99xsflwkdv4hgvq58q', @@ -103,21 +106,26 @@ const mockBalanceResult = { /** * The union of actions that the root messenger allows. */ -type RootAction = ExtractAvailableAction; +type RootAction = MessengerActions; /** * The union of events that the root messenger allows. */ -type RootEvent = ExtractAvailableEvent; +type RootEvent = MessengerEvents; /** - * Constructs the unrestricted messenger. This can be used to call actions and + * The root messenger type + */ +type RootMessenger = Messenger; + +/** + * Constructs the root messenger. This can be used to call actions and * publish events within the tests for this controller. * - * @returns The unrestricted messenger suited for MultichainBalancesController. + * @returns The root messenger suited for MultichainBalancesController. */ -function getRootMessenger(): Messenger { - return new Messenger(); +function getRootMessenger(): RootMessenger { + return new Messenger({ namespace: MOCK_ANY_NAMESPACE }); } /** @@ -127,23 +135,33 @@ function getRootMessenger(): Messenger { * @returns The unrestricted messenger suited for MultichainBalancesController. */ function getRestrictedMessenger( - messenger: Messenger, + messenger: RootMessenger, ): MultichainBalancesControllerMessenger { - return messenger.getRestricted({ - name: 'MultichainBalancesController', - allowedActions: [ + const multichainBalancesControllerMessenger = new Messenger< + 'MultichainBalancesController', + RootAction, + RootEvent, + RootMessenger + >({ + namespace: 'MultichainBalancesController', + parent: messenger, + }); + messenger.delegate({ + messenger: multichainBalancesControllerMessenger, + actions: [ 'SnapController:handleRequest', 'AccountsController:listMultichainAccounts', 'MultichainAssetsController:getState', 'KeyringController:getState', ], - allowedEvents: [ + events: [ 'AccountsController:accountAdded', 'AccountsController:accountRemoved', 'AccountsController:accountBalancesUpdated', 'MultichainAssetsController:accountAssetListUpdated', ], }); + return multichainBalancesControllerMessenger; } const setupController = ({ @@ -651,7 +669,7 @@ describe('MultichainBalancesController', () => { deriveStateFromMetadata( controller.state, controller.metadata, - 'anonymous', + 'includeInDebugSnapshot', ), ).toMatchInlineSnapshot(`Object {}`); }); diff --git a/packages/assets-controllers/src/MultichainBalancesController/MultichainBalancesController.ts b/packages/assets-controllers/src/MultichainBalancesController/MultichainBalancesController.ts index 1545e547b79..d547f5bc237 100644 --- a/packages/assets-controllers/src/MultichainBalancesController/MultichainBalancesController.ts +++ b/packages/assets-controllers/src/MultichainBalancesController/MultichainBalancesController.ts @@ -6,10 +6,10 @@ import type { } from '@metamask/accounts-controller'; import { BaseController, + type StateMetadata, type ControllerGetStateAction, type ControllerStateChangeEvent, - type RestrictedMessenger, -} from '@metamask/base-controller'; +} from '@metamask/base-controller/next'; import { isEvmAccountType } from '@metamask/keyring-api'; import type { Balance, @@ -19,6 +19,7 @@ import type { import type { KeyringControllerGetStateAction } from '@metamask/keyring-controller'; import type { InternalAccount } from '@metamask/keyring-internal-api'; import { KeyringClient } from '@metamask/keyring-snap-client'; +import type { Messenger } from '@metamask/messenger'; import type { HandleSnapRequest } from '@metamask/snaps-controllers'; import type { SnapId } from '@metamask/snaps-sdk'; import { HandlerType } from '@metamask/snaps-utils'; @@ -108,12 +109,10 @@ type AllowedEvents = /** * Messenger type for the MultichainBalancesController. */ -export type MultichainBalancesControllerMessenger = RestrictedMessenger< +export type MultichainBalancesControllerMessenger = Messenger< typeof controllerName, MultichainBalancesControllerActions | AllowedActions, - MultichainBalancesControllerEvents | AllowedEvents, - AllowedActions['type'], - AllowedEvents['type'] + MultichainBalancesControllerEvents | AllowedEvents >; /** @@ -123,14 +122,15 @@ export type MultichainBalancesControllerMessenger = RestrictedMessenger< * using the `persist` flag; and if they can be sent to Sentry or not, using * the `anonymous` flag. */ -const balancesControllerMetadata = { - balances: { - includeInStateLogs: false, - persist: true, - anonymous: false, - usedInUi: true, - }, -}; +const balancesControllerMetadata: StateMetadata = + { + balances: { + includeInStateLogs: false, + persist: true, + includeInDebugSnapshot: false, + usedInUi: true, + }, + }; /** * The MultichainBalancesController is responsible for fetching and caching account @@ -165,17 +165,17 @@ export class MultichainBalancesController extends BaseController< void this.updateBalance(account.id); } - this.messagingSystem.subscribe( + this.messenger.subscribe( 'AccountsController:accountRemoved', (account: string) => this.#handleOnAccountRemoved(account), ); - this.messagingSystem.subscribe( + this.messenger.subscribe( 'AccountsController:accountBalancesUpdated', (balanceUpdate: AccountBalancesUpdatedEventPayload) => this.#handleOnAccountBalancesUpdated(balanceUpdate), ); - this.messagingSystem.subscribe( + this.messenger.subscribe( 'MultichainAssetsController:accountAssetListUpdated', async ({ assets }) => { const newAccountAssets = Object.entries(assets).map( @@ -200,9 +200,7 @@ export class MultichainBalancesController extends BaseController< assets: CaipAssetType[]; }[], ): Promise { - const { isUnlocked } = this.messagingSystem.call( - 'KeyringController:getState', - ); + const { isUnlocked } = this.messenger.call('KeyringController:getState'); if (!isUnlocked) { return; @@ -256,9 +254,7 @@ export class MultichainBalancesController extends BaseController< accountId: string, assets: CaipAssetType[], ): Promise { - const { isUnlocked } = this.messagingSystem.call( - 'KeyringController:getState', - ); + const { isUnlocked } = this.messenger.call('KeyringController:getState'); if (!isUnlocked) { return; @@ -305,9 +301,7 @@ export class MultichainBalancesController extends BaseController< * @returns A list of multichain accounts. */ #listMultichainAccounts(): InternalAccount[] { - return this.messagingSystem.call( - 'AccountsController:listMultichainAccounts', - ); + return this.messenger.call('AccountsController:listMultichainAccounts'); } /** @@ -328,7 +322,7 @@ export class MultichainBalancesController extends BaseController< */ #listAccountAssets(accountId: string): CaipAssetType[] { // TODO: Add an action `MultichainAssetsController:getAccountAssets` maybe? - const assetsState = this.messagingSystem.call( + const assetsState = this.messenger.call( 'MultichainAssetsController:getState', ); @@ -427,7 +421,7 @@ export class MultichainBalancesController extends BaseController< #getClient(snapId: string): KeyringClient { return new KeyringClient({ send: async (request: JsonRpcRequest) => - (await this.messagingSystem.call('SnapController:handleRequest', { + (await this.messenger.call('SnapController:handleRequest', { snapId: snapId as SnapId, origin: 'metamask', handler: HandlerType.OnKeyringRequest, From 10916bcd7e1dffd707210a5e12c5715ee3774093 Mon Sep 17 00:00:00 2001 From: Michele Esposito Date: Mon, 29 Sep 2025 10:56:07 +0200 Subject: [PATCH 45/69] migrate `RatesController` messenger --- .../RatesController/RatesController.test.ts | 72 ++++++++++--------- .../src/RatesController/RatesController.ts | 17 +++-- .../src/RatesController/types.ts | 8 +-- 3 files changed, 52 insertions(+), 45 deletions(-) diff --git a/packages/assets-controllers/src/RatesController/RatesController.test.ts b/packages/assets-controllers/src/RatesController/RatesController.test.ts index e2b125ea4db..8ba6ccbe2b5 100644 --- a/packages/assets-controllers/src/RatesController/RatesController.test.ts +++ b/packages/assets-controllers/src/RatesController/RatesController.test.ts @@ -1,6 +1,14 @@ -import { Messenger, deriveStateFromMetadata } from '@metamask/base-controller'; +import { deriveStateFromMetadata } from '@metamask/base-controller/next'; +import { + MOCK_ANY_NAMESPACE, + Messenger, + type MessengerActions, + type MessengerEvents, + type MockAnyNamespace, +} from '@metamask/messenger'; import { useFakeTimers } from 'sinon'; +import type { RatesControllerMessenger, RatesControllerState } from './types'; import { advanceTime } from '../../../../tests/helpers'; import type { fetchMultiExchangeRate as defaultFetchExchangeRate } from '../crypto-compare-service'; import { @@ -8,12 +16,12 @@ import { RatesController, name as ratesControllerName, } from './RatesController'; -import type { - RatesControllerActions, - RatesControllerEvents, - RatesControllerMessenger, - RatesControllerState, -} from './types'; + +type AllActions = MessengerActions; + +type AllEvents = MessengerEvents; + +type RootMessenger = Messenger; const MOCK_TIMESTAMP = 1709983353; @@ -26,28 +34,26 @@ function getStubbedDate(): number { } /** - * Builds a new Messenger instance for RatesController. - * @returns A new Messenger instance. + * Builds a new root messenger instance. + * + * @returns A new root messenger instance. */ -function buildMessenger(): Messenger< - RatesControllerActions, - RatesControllerEvents -> { - return new Messenger(); +function buildRootMessenger(): RootMessenger { + return new Messenger({ namespace: MOCK_ANY_NAMESPACE }); } /** * Builds a restricted messenger for the RatesController. + * * @param messenger - The base messenger instance. * @returns A restricted messenger for the RatesController. */ function buildRatesControllerMessenger( - messenger: Messenger, + messenger: RootMessenger, ): RatesControllerMessenger { - return messenger.getRestricted({ - name: ratesControllerName, - allowedEvents: [], - allowedActions: [], + return new Messenger({ + namespace: ratesControllerName, + parent: messenger, }); } @@ -70,7 +76,7 @@ function setupRatesController({ }: { interval?: number; initialState?: Partial; - messenger: Messenger; + messenger: RootMessenger; includeUsdRate: boolean; fetchMultiExchangeRate?: typeof defaultFetchExchangeRate; }) { @@ -91,7 +97,7 @@ describe('RatesController', () => { it('constructs the RatesController with default values', () => { const ratesController = setupRatesController({ initialState: {}, - messenger: buildMessenger(), + messenger: buildRootMessenger(), includeUsdRate: false, }); const { fiatCurrency, rates, cryptocurrencies } = ratesController.state; @@ -118,7 +124,7 @@ describe('RatesController', () => { }); it('starts the polling process with default values', async () => { - const messenger = buildMessenger(); + const messenger = buildRootMessenger(); const publishActionSpy = jest.spyOn(messenger, 'publish'); jest.spyOn(global.Date, 'now').mockImplementation(() => getStubbedDate()); @@ -222,7 +228,7 @@ describe('RatesController', () => { cryptocurrencies: [Cryptocurrency.Btc], fiatCurrency: 'eur', }, - messenger: buildMessenger(), + messenger: buildRootMessenger(), includeUsdRate: true, fetchMultiExchangeRate: fetchExchangeRateStub, }); @@ -263,7 +269,7 @@ describe('RatesController', () => { }); it('stops the polling process', async () => { - const messenger = buildMessenger(); + const messenger = buildRootMessenger(); const publishActionSpy = jest.spyOn(messenger, 'publish'); const fetchExchangeRateStub = jest.fn().mockResolvedValue({}); const ratesController = setupRatesController({ @@ -318,7 +324,7 @@ describe('RatesController', () => { initialState: { cryptocurrencies: mockCryptocurrencyList, }, - messenger: buildMessenger(), + messenger: buildRootMessenger(), fetchMultiExchangeRate: fetchExchangeRateStub, includeUsdRate: false, }); @@ -335,7 +341,7 @@ describe('RatesController', () => { const ratesController = setupRatesController({ interval: 150, initialState: {}, - messenger: buildMessenger(), + messenger: buildRootMessenger(), fetchMultiExchangeRate: fetchExchangeRateStub, includeUsdRate: false, }); @@ -366,7 +372,7 @@ describe('RatesController', () => { const ratesController = setupRatesController({ interval: 150, initialState: {}, - messenger: buildMessenger(), + messenger: buildRootMessenger(), fetchMultiExchangeRate: fetchExchangeRateStub, includeUsdRate: false, }); @@ -385,7 +391,7 @@ describe('RatesController', () => { const ratesController = setupRatesController({ interval: 150, initialState: {}, - messenger: buildMessenger(), + messenger: buildRootMessenger(), fetchMultiExchangeRate: fetchExchangeRateStub, includeUsdRate: false, }); @@ -400,7 +406,7 @@ describe('RatesController', () => { it('includes expected state in debug snapshots', () => { const fetchExchangeRateStub = jest.fn().mockResolvedValue({}); const controller = setupRatesController({ - messenger: buildMessenger(), + messenger: buildRootMessenger(), fetchMultiExchangeRate: fetchExchangeRateStub, includeUsdRate: false, }); @@ -409,7 +415,7 @@ describe('RatesController', () => { deriveStateFromMetadata( controller.state, controller.metadata, - 'anonymous', + 'includeInDebugSnapshot', ), ).toMatchInlineSnapshot(` Object { @@ -435,7 +441,7 @@ describe('RatesController', () => { it('includes expected state in state logs', () => { const fetchExchangeRateStub = jest.fn().mockResolvedValue({}); const controller = setupRatesController({ - messenger: buildMessenger(), + messenger: buildRootMessenger(), fetchMultiExchangeRate: fetchExchangeRateStub, includeUsdRate: false, }); @@ -460,7 +466,7 @@ describe('RatesController', () => { it('persists expected state', () => { const fetchExchangeRateStub = jest.fn().mockResolvedValue({}); const controller = setupRatesController({ - messenger: buildMessenger(), + messenger: buildRootMessenger(), fetchMultiExchangeRate: fetchExchangeRateStub, includeUsdRate: false, }); @@ -495,7 +501,7 @@ describe('RatesController', () => { it('exposes expected state to UI', () => { const fetchExchangeRateStub = jest.fn().mockResolvedValue({}); const controller = setupRatesController({ - messenger: buildMessenger(), + messenger: buildRootMessenger(), fetchMultiExchangeRate: fetchExchangeRateStub, includeUsdRate: false, }); diff --git a/packages/assets-controllers/src/RatesController/RatesController.ts b/packages/assets-controllers/src/RatesController/RatesController.ts index 5c916a7c92a..f2d4430a89f 100644 --- a/packages/assets-controllers/src/RatesController/RatesController.ts +++ b/packages/assets-controllers/src/RatesController/RatesController.ts @@ -1,4 +1,7 @@ -import { BaseController } from '@metamask/base-controller'; +import { + BaseController, + type StateMetadata, +} from '@metamask/base-controller/next'; import { Mutex } from 'async-mutex'; import type { Draft } from 'immer'; @@ -25,23 +28,23 @@ export enum Cryptocurrency { const DEFAULT_INTERVAL = 180000; -const metadata = { +const metadata: StateMetadata = { fiatCurrency: { includeInStateLogs: true, persist: true, - anonymous: true, + includeInDebugSnapshot: true, usedInUi: true, }, rates: { includeInStateLogs: false, persist: true, - anonymous: true, + includeInDebugSnapshot: true, usedInUi: true, }, cryptocurrencies: { includeInStateLogs: true, persist: true, - anonymous: true, + includeInDebugSnapshot: true, usedInUi: false, }, }; @@ -180,7 +183,7 @@ export class RatesController extends BaseController< return; } - this.messagingSystem.publish(`${name}:pollingStarted`); + this.messenger.publish(`${name}:pollingStarted`); await this.#updateRates(); @@ -199,7 +202,7 @@ export class RatesController extends BaseController< clearInterval(this.#intervalId); this.#intervalId = undefined; - this.messagingSystem.publish(`${name}:pollingStopped`); + this.messenger.publish(`${name}:pollingStopped`); } /** diff --git a/packages/assets-controllers/src/RatesController/types.ts b/packages/assets-controllers/src/RatesController/types.ts index c26ae070075..49c5515391b 100644 --- a/packages/assets-controllers/src/RatesController/types.ts +++ b/packages/assets-controllers/src/RatesController/types.ts @@ -1,8 +1,8 @@ import type { - RestrictedMessenger, ControllerGetStateAction, ControllerStateChangeEvent, } from '@metamask/base-controller'; +import type { Messenger } from '@metamask/messenger'; import type { fetchMultiExchangeRate as defaultFetchExchangeRate } from '../crypto-compare-service'; import type { @@ -97,12 +97,10 @@ export type RatesControllerActions = RatesControllerGetStateAction; /** * Defines the actions that the RatesController can perform. */ -export type RatesControllerMessenger = RestrictedMessenger< +export type RatesControllerMessenger = Messenger< typeof ratesControllerName, RatesControllerActions, - RatesControllerEvents, - never, - never + RatesControllerEvents >; /** From 3c83baf938e0c553e9487df84c9ab34ab0827779 Mon Sep 17 00:00:00 2001 From: Michele Esposito Date: Mon, 29 Sep 2025 11:00:58 +0200 Subject: [PATCH 46/69] migrate `TokenSearchDiscoveryDataController` messenger --- ...TokenSearchDiscoveryDataController.test.ts | 39 ++++++++++++---- .../TokenSearchDiscoveryDataController.ts | 44 +++++++++---------- 2 files changed, 52 insertions(+), 31 deletions(-) diff --git a/packages/assets-controllers/src/TokenSearchDiscoveryDataController/TokenSearchDiscoveryDataController.test.ts b/packages/assets-controllers/src/TokenSearchDiscoveryDataController/TokenSearchDiscoveryDataController.test.ts index 2148acd60c2..04dad2f61bc 100644 --- a/packages/assets-controllers/src/TokenSearchDiscoveryDataController/TokenSearchDiscoveryDataController.test.ts +++ b/packages/assets-controllers/src/TokenSearchDiscoveryDataController/TokenSearchDiscoveryDataController.test.ts @@ -1,5 +1,12 @@ -import { Messenger, deriveStateFromMetadata } from '@metamask/base-controller'; +import { deriveStateFromMetadata } from '@metamask/base-controller/next'; import { ChainId } from '@metamask/controller-utils'; +import { + MOCK_ANY_NAMESPACE, + Messenger, + type MessengerActions, + type MessengerEvents, + type MockAnyNamespace, +} from '@metamask/messenger'; import type { Hex } from '@metamask/utils'; import assert from 'assert'; import { useFakeTimers } from 'sinon'; @@ -32,7 +39,11 @@ jest.mock('../token-service', () => { }; }); -type MainMessenger = Messenger; +type AllActions = MessengerActions; + +type AllEvents = MessengerEvents; + +type RootMessenger = Messenger; /** * Builds a not found token display data object. @@ -111,13 +122,21 @@ function buildFoundTokenDisplayData( * @returns The restricted messenger. */ function buildTokenSearchDiscoveryDataControllerMessenger( - messenger: MainMessenger = new Messenger(), + messenger: RootMessenger = new Messenger({ namespace: MOCK_ANY_NAMESPACE }), ): TokenSearchDiscoveryDataControllerMessenger { - return messenger.getRestricted({ - name: controllerName, - allowedActions: ['CurrencyRateController:getState'], - allowedEvents: [], + const tokenSearchDiscoveryDataControllerMessenger = new Messenger< + typeof controllerName, + AllActions, + AllEvents, + RootMessenger + >({ + namespace: controllerName, }); + messenger.delegate({ + messenger: tokenSearchDiscoveryDataControllerMessenger, + actions: ['CurrencyRateController:getState'], + }); + return tokenSearchDiscoveryDataControllerMessenger; } /** @@ -206,7 +225,9 @@ async function withController( callback = maybeCallback; } - const messenger = new Messenger(); + const messenger: RootMessenger = new Messenger({ + namespace: MOCK_ANY_NAMESPACE, + }); messenger.registerActionHandler('CurrencyRateController:getState', () => ({ currentCurrency: 'USD', @@ -899,7 +920,7 @@ describe('TokenSearchDiscoveryDataController', () => { deriveStateFromMetadata( controller.state, controller.metadata, - 'anonymous', + 'includeInDebugSnapshot', ), ).toMatchInlineSnapshot(`Object {}`); }); diff --git a/packages/assets-controllers/src/TokenSearchDiscoveryDataController/TokenSearchDiscoveryDataController.ts b/packages/assets-controllers/src/TokenSearchDiscoveryDataController/TokenSearchDiscoveryDataController.ts index dc508d7e3f7..7af8e66d20b 100644 --- a/packages/assets-controllers/src/TokenSearchDiscoveryDataController/TokenSearchDiscoveryDataController.ts +++ b/packages/assets-controllers/src/TokenSearchDiscoveryDataController/TokenSearchDiscoveryDataController.ts @@ -1,9 +1,10 @@ import { BaseController, + type StateMetadata, type ControllerGetStateAction, type ControllerStateChangeEvent, - type RestrictedMessenger, -} from '@metamask/base-controller'; +} from '@metamask/base-controller/next'; +import type { Messenger } from '@metamask/messenger'; import type { Hex } from '@metamask/utils'; import type { TokenDisplayData } from './types'; @@ -33,20 +34,21 @@ export type TokenSearchDiscoveryDataControllerState = { >; }; -const tokenSearchDiscoveryDataControllerMetadata = { - tokenDisplayData: { - includeInStateLogs: false, - persist: true, - anonymous: false, - usedInUi: true, - }, - swapsTokenAddressesByChainId: { - includeInStateLogs: false, - persist: true, - anonymous: false, - usedInUi: true, - }, -} as const; +const tokenSearchDiscoveryDataControllerMetadata: StateMetadata = + { + tokenDisplayData: { + includeInStateLogs: false, + persist: true, + includeInDebugSnapshot: false, + usedInUi: true, + }, + swapsTokenAddressesByChainId: { + includeInStateLogs: false, + persist: true, + includeInDebugSnapshot: false, + usedInUi: true, + }, + } as const; // === MESSENGER === @@ -98,12 +100,10 @@ export type AllowedEvents = never; * The messenger which is restricted to actions and events accessed by * {@link TokenSearchDiscoveryDataController}. */ -export type TokenSearchDiscoveryDataControllerMessenger = RestrictedMessenger< +export type TokenSearchDiscoveryDataControllerMessenger = Messenger< typeof controllerName, TokenSearchDiscoveryDataControllerActions | AllowedActions, - TokenSearchDiscoveryDataControllerEvents | AllowedEvents, - AllowedActions['type'], - AllowedEvents['type'] + TokenSearchDiscoveryDataControllerEvents | AllowedEvents >; /** @@ -176,7 +176,7 @@ export class TokenSearchDiscoveryDataController extends BaseController< chainId: Hex, address: string, ): Promise | null> { - const { currentCurrency } = this.messagingSystem.call( + const { currentCurrency } = this.messenger.call( 'CurrencyRateController:getState', ); @@ -251,7 +251,7 @@ export class TokenSearchDiscoveryDataController extends BaseController< } } - const { currentCurrency } = this.messagingSystem.call( + const { currentCurrency } = this.messenger.call( 'CurrencyRateController:getState', ); From f0646a779bf0a1d7f25e203a9e3eadf0f3154e11 Mon Sep 17 00:00:00 2001 From: Michele Esposito Date: Mon, 29 Sep 2025 11:09:51 +0200 Subject: [PATCH 47/69] migrate `NftDetectionController` messenger --- .../src/NftDetectionController.test.ts | 57 +++++++++++++------ .../src/NftDetectionController.ts | 30 ++++++---- 2 files changed, 59 insertions(+), 28 deletions(-) diff --git a/packages/assets-controllers/src/NftDetectionController.test.ts b/packages/assets-controllers/src/NftDetectionController.test.ts index af18eb5e175..a554b63e46c 100644 --- a/packages/assets-controllers/src/NftDetectionController.test.ts +++ b/packages/assets-controllers/src/NftDetectionController.test.ts @@ -1,10 +1,16 @@ import type { AccountsController } from '@metamask/accounts-controller'; -import { Messenger } from '@metamask/base-controller'; import { NFT_API_BASE_URL, ChainId, InfuraNetworkType, } from '@metamask/controller-utils'; +import { + MOCK_ANY_NAMESPACE, + Messenger, + type MessengerActions, + type MessengerEvents, + type MockAnyNamespace, +} from '@metamask/messenger'; import { getDefaultNetworkControllerState, NetworkClientType, @@ -42,6 +48,12 @@ import { } from './NftDetectionController'; import * as constants from './NftDetectionController'; +type AllActions = MessengerActions; + +type AllEvents = MessengerEvents; + +type RootMessenger = Messenger; + const controllerName = 'NftDetectionController' as const; const defaultSelectedAccount = createMockInternalAccount(); @@ -1914,7 +1926,9 @@ async function withController( testFunction, ] = args.length === 2 ? args : [{}, args[0]]; - const messenger = new Messenger(); + const messenger: RootMessenger = new Messenger({ + namespace: MOCK_ANY_NAMESPACE, + }); messenger.registerActionHandler( 'NetworkController:getState', @@ -1954,21 +1968,32 @@ async function withController( }), ); + const nftDetectionControllerMessenger = new Messenger< + typeof controllerName, + AllActions, + AllEvents, + RootMessenger + >({ + namespace: controllerName, + parent: messenger, + }); + messenger.delegate({ + messenger: nftDetectionControllerMessenger, + actions: [ + 'NetworkController:getState', + 'NetworkController:getNetworkClientById', + 'PreferencesController:getState', + 'AccountsController:getSelectedAccount', + 'NetworkController:findNetworkClientIdByChainId', + ], + events: [ + 'NetworkController:stateChange', + 'PreferencesController:stateChange', + ], + }); + const controller = new NftDetectionController({ - messenger: messenger.getRestricted({ - name: controllerName, - allowedActions: [ - 'NetworkController:getState', - 'NetworkController:getNetworkClientById', - 'PreferencesController:getState', - 'AccountsController:getSelectedAccount', - 'NetworkController:findNetworkClientIdByChainId', - ], - allowedEvents: [ - 'NetworkController:stateChange', - 'PreferencesController:stateChange', - ], - }), + messenger: nftDetectionControllerMessenger, disabled: true, addNft: jest.fn(), getNftState: getDefaultNftControllerState, diff --git a/packages/assets-controllers/src/NftDetectionController.ts b/packages/assets-controllers/src/NftDetectionController.ts index dd72056892c..d5a78a13b5e 100644 --- a/packages/assets-controllers/src/NftDetectionController.ts +++ b/packages/assets-controllers/src/NftDetectionController.ts @@ -1,7 +1,10 @@ import type { AccountsControllerGetSelectedAccountAction } from '@metamask/accounts-controller'; import type { AddApprovalRequest } from '@metamask/approval-controller'; -import type { RestrictedMessenger } from '@metamask/base-controller'; -import { BaseController } from '@metamask/base-controller'; +import { + BaseController, + type ControllerGetStateAction, + type ControllerStateChangeEvent, +} from '@metamask/base-controller/next'; import { toChecksumHexAddress, ChainId, @@ -13,6 +16,7 @@ import { NFT_API_TIMEOUT, toHex, } from '@metamask/controller-utils'; +import type { Messenger } from '@metamask/messenger'; import type { NetworkClient, NetworkControllerGetNetworkClientByIdAction, @@ -40,6 +44,7 @@ const controllerName = 'NftDetectionController'; export type NFTDetectionControllerState = Record; export type AllowedActions = + | ControllerGetStateAction | AddApprovalRequest | NetworkControllerGetStateAction | NetworkControllerGetNetworkClientByIdAction @@ -48,15 +53,17 @@ export type AllowedActions = | NetworkControllerFindNetworkClientIdByChainIdAction; export type AllowedEvents = + | ControllerStateChangeEvent< + typeof controllerName, + NFTDetectionControllerState + > | PreferencesControllerStateChangeEvent | NetworkControllerStateChangeEvent; -export type NftDetectionControllerMessenger = RestrictedMessenger< +export type NftDetectionControllerMessenger = Messenger< typeof controllerName, AllowedActions, - AllowedEvents, - AllowedActions['type'], - AllowedEvents['type'] + AllowedEvents >; /** @@ -503,7 +510,7 @@ export class NftDetectionController extends BaseController< this.#getNftState = getNftState; this.#addNft = addNft; - this.messagingSystem.subscribe( + this.messenger.subscribe( 'PreferencesController:stateChange', this.#onPreferencesControllerStateChange.bind(this), ); @@ -515,12 +522,12 @@ export class NftDetectionController extends BaseController< * @returns Whether current network is mainnet. */ isMainnet(): boolean { - const { selectedNetworkClientId } = this.messagingSystem.call( + const { selectedNetworkClientId } = this.messenger.call( 'NetworkController:getState', ); const { configuration: { chainId }, - } = this.messagingSystem.call( + } = this.messenger.call( 'NetworkController:getNetworkClientById', selectedNetworkClientId, ); @@ -591,8 +598,7 @@ export class NftDetectionController extends BaseController< async detectNfts(chainIds: Hex[], options?: { userAddress?: string }) { const userAddress = options?.userAddress ?? - this.messagingSystem.call('AccountsController:getSelectedAccount') - .address; + this.messenger.call('AccountsController:getSelectedAccount').address; // filter out unsupported chainIds const supportedChainIds = chainIds.filter((chainId) => @@ -796,7 +802,7 @@ export class NftDetectionController extends BaseController< collection && { collection }, chainId && { chainId }, ); - const networkClientId = this.messagingSystem.call( + const networkClientId = this.messenger.call( 'NetworkController:findNetworkClientIdByChainId', toHex(chainId), ); From a966f674e08b84a762aabcda082757c9416ff10f Mon Sep 17 00:00:00 2001 From: Michele Esposito Date: Mon, 29 Sep 2025 11:20:25 +0200 Subject: [PATCH 48/69] remove unused vars --- packages/assets-controllers/src/NftDetectionController.test.ts | 2 -- .../TokenSearchDiscoveryDataController.test.ts | 2 -- 2 files changed, 4 deletions(-) diff --git a/packages/assets-controllers/src/NftDetectionController.test.ts b/packages/assets-controllers/src/NftDetectionController.test.ts index a554b63e46c..578c7857c16 100644 --- a/packages/assets-controllers/src/NftDetectionController.test.ts +++ b/packages/assets-controllers/src/NftDetectionController.test.ts @@ -43,8 +43,6 @@ import { NftDetectionController, BlockaidResultType, MAX_GET_COLLECTION_BATCH_SIZE, - type AllowedActions, - type AllowedEvents, } from './NftDetectionController'; import * as constants from './NftDetectionController'; diff --git a/packages/assets-controllers/src/TokenSearchDiscoveryDataController/TokenSearchDiscoveryDataController.test.ts b/packages/assets-controllers/src/TokenSearchDiscoveryDataController/TokenSearchDiscoveryDataController.test.ts index 04dad2f61bc..86d1b7e01e2 100644 --- a/packages/assets-controllers/src/TokenSearchDiscoveryDataController/TokenSearchDiscoveryDataController.test.ts +++ b/packages/assets-controllers/src/TokenSearchDiscoveryDataController/TokenSearchDiscoveryDataController.test.ts @@ -16,8 +16,6 @@ import { TokenSearchDiscoveryDataController, controllerName, MAX_TOKEN_DISPLAY_DATA_LENGTH, - type AllowedActions, - type AllowedEvents, type TokenSearchDiscoveryDataControllerMessenger, type TokenSearchDiscoveryDataControllerState, } from './TokenSearchDiscoveryDataController'; From feb00b3f9c0b965f8035a4f6f4a7d1c6f223c6a0 Mon Sep 17 00:00:00 2001 From: Michele Esposito Date: Mon, 29 Sep 2025 11:20:33 +0200 Subject: [PATCH 49/69] rename leftover `messagingSystem` --- packages/assets-controllers/src/TokenBalancesController.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/assets-controllers/src/TokenBalancesController.ts b/packages/assets-controllers/src/TokenBalancesController.ts index 89e98b72e9f..47525156fac 100644 --- a/packages/assets-controllers/src/TokenBalancesController.ts +++ b/packages/assets-controllers/src/TokenBalancesController.ts @@ -836,10 +836,10 @@ export class TokenBalancesController extends StaticIntervalPollingController<{ this.#intervalPollingTimers.clear(); // Unregister action handlers - this.messagingSystem.unregisterActionHandler( + this.messenger.unregisterActionHandler( `TokenBalancesController:updateChainPollingConfigs`, ); - this.messagingSystem.unregisterActionHandler( + this.messenger.unregisterActionHandler( `TokenBalancesController:getChainPollingConfig`, ); From fa0f1965aacc7df6bae6d3d63333161b301b060c Mon Sep 17 00:00:00 2001 From: Michele Esposito Date: Mon, 29 Sep 2025 11:22:11 +0200 Subject: [PATCH 50/69] update changelog --- packages/assets-controllers/CHANGELOG.md | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/packages/assets-controllers/CHANGELOG.md b/packages/assets-controllers/CHANGELOG.md index fd4558f8455..fee29a67f9f 100644 --- a/packages/assets-controllers/CHANGELOG.md +++ b/packages/assets-controllers/CHANGELOG.md @@ -13,16 +13,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed -- **BREAKING:** Migrate the following controllers to the new `Messenger` from `@metamask/messenger` ([#6444](https://github.com/MetaMask/core/pull/6444)) - - `AccountTrackerController` - - `CurrencyRateController` - - `DeFiPositionController` - - `MultichainAssetsRatesController` - - `TokenBalancesController` - - `TokenDetectionController` - - `TokenListController` - - `TokenRatesController` -- **BREAKING:** Migrate `AssetsContractController`, `NftController`, and `TokensController` to new `Messenger` from `@metamask/messenger` ([#6386](https://github.com/MetaMask/core/pull/6386)) +- **BREAKING:** Migrate controllers to new `Messenger` from `@metamask/messenger` ([#6444](https://github.com/MetaMask/core/pull/6444), [#6386](https://github.com/MetaMask/core/pull/6386), [#6745](https://github.com/MetaMask/core/pull/6745)) - Previously, the controllers accepted a `RestrictedMessenger` instance from `@metamask/base-controller`. ## [76.0.0] From 6e80728c10a529be20c28426635fb5efbf912c30 Mon Sep 17 00:00:00 2001 From: Michele Esposito Date: Mon, 29 Sep 2025 11:31:47 +0200 Subject: [PATCH 51/69] update lint thresholds --- eslint-warning-thresholds.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/eslint-warning-thresholds.json b/eslint-warning-thresholds.json index 3815a68c937..e40228baf16 100644 --- a/eslint-warning-thresholds.json +++ b/eslint-warning-thresholds.json @@ -38,8 +38,8 @@ "jsdoc/tag-lines": 1 }, "packages/assets-controllers/src/RatesController/RatesController.test.ts": { - "import-x/order": 2, - "jsdoc/tag-lines": 4 + "import-x/order": 1, + "jsdoc/tag-lines": 2 }, "packages/assets-controllers/src/RatesController/RatesController.ts": { "@typescript-eslint/prefer-readonly": 1, @@ -70,7 +70,7 @@ }, "packages/assets-controllers/src/TokenListController.test.ts": { "import-x/namespace": 7, - "import-x/order": 3, + "import-x/order": 2, "jest/no-conditional-in-test": 2 }, "packages/assets-controllers/src/TokenRatesController.test.ts": { From 52899ba1dae36ccec64eec27363e7f198a5eadc0 Mon Sep 17 00:00:00 2001 From: Michele Esposito Date: Mon, 29 Sep 2025 11:33:08 +0200 Subject: [PATCH 52/69] fix `transaction.test.ts` --- .../bridge-status-controller/src/utils/transaction.test.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/bridge-status-controller/src/utils/transaction.test.ts b/packages/bridge-status-controller/src/utils/transaction.test.ts index b1f044da7e2..f2e51262bfa 100644 --- a/packages/bridge-status-controller/src/utils/transaction.test.ts +++ b/packages/bridge-status-controller/src/utils/transaction.test.ts @@ -1456,7 +1456,7 @@ describe('Bridge Status Controller Transaction Utils', () => { const result = await getAddTransactionBatchParams({ quoteResponse: mockQuoteResponse, - messagingSystem: mockMessagingSystem, + messenger: mockMessagingSystem, isBridgeTx: false, trade: mockQuoteResponse.trade, estimateGasFeeFn: jest.fn().mockResolvedValue({}), @@ -1473,7 +1473,7 @@ describe('Bridge Status Controller Transaction Utils', () => { const result = await getAddTransactionBatchParams({ quoteResponse: mockQuoteResponse, - messagingSystem: mockMessagingSystem, + messenger: mockMessagingSystem, isBridgeTx: false, trade: mockQuoteResponse.trade, estimateGasFeeFn: jest.fn().mockResolvedValue({}), @@ -1490,7 +1490,7 @@ describe('Bridge Status Controller Transaction Utils', () => { const result = await getAddTransactionBatchParams({ quoteResponse: mockQuoteResponse, - messagingSystem: mockMessagingSystem, + messenger: mockMessagingSystem, isBridgeTx: false, trade: mockQuoteResponse.trade, estimateGasFeeFn: jest.fn().mockResolvedValue({}), From b896289e0bcfbc92b45a08f23dc0760afe9186d6 Mon Sep 17 00:00:00 2001 From: Michele Esposito Date: Mon, 29 Sep 2025 13:14:23 +0200 Subject: [PATCH 53/69] rename leftover `messagingSystem` --- packages/assets-controllers/src/TokenBalancesController.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/assets-controllers/src/TokenBalancesController.ts b/packages/assets-controllers/src/TokenBalancesController.ts index 89e98b72e9f..47525156fac 100644 --- a/packages/assets-controllers/src/TokenBalancesController.ts +++ b/packages/assets-controllers/src/TokenBalancesController.ts @@ -836,10 +836,10 @@ export class TokenBalancesController extends StaticIntervalPollingController<{ this.#intervalPollingTimers.clear(); // Unregister action handlers - this.messagingSystem.unregisterActionHandler( + this.messenger.unregisterActionHandler( `TokenBalancesController:updateChainPollingConfigs`, ); - this.messagingSystem.unregisterActionHandler( + this.messenger.unregisterActionHandler( `TokenBalancesController:getChainPollingConfig`, ); From ab370309515017d3d9c6abd1ced8f7eaa80fa416 Mon Sep 17 00:00:00 2001 From: Michele Esposito Date: Mon, 13 Oct 2025 14:09:47 +0200 Subject: [PATCH 54/69] apply @mcmire suggestions --- .../src/ApprovalController.test.ts | 13 ++++++++----- .../base-controller/src/next/BaseController.test.ts | 10 +++++++--- .../src/TransactionControllerIntegration.test.ts | 8 ++++++-- .../src/utils/eip7702.test.ts | 6 ++++-- .../src/utils/feature-flags.test.ts | 6 ++++-- .../transaction-controller/src/utils/swaps.test.ts | 6 ++++-- 6 files changed, 33 insertions(+), 16 deletions(-) diff --git a/packages/approval-controller/src/ApprovalController.test.ts b/packages/approval-controller/src/ApprovalController.test.ts index 5afdfdf1898..652a87ba4f3 100644 --- a/packages/approval-controller/src/ApprovalController.test.ts +++ b/packages/approval-controller/src/ApprovalController.test.ts @@ -1327,7 +1327,7 @@ describe('approval controller', () => { }); it('updateRequestState', () => { - const { rootMessenger, approvalControllerMessenger } = getMessengers(); + const { approvalControllerMessenger } = getMessengers(); approvalController = new ApprovalController({ messenger: approvalControllerMessenger, @@ -1343,10 +1343,13 @@ describe('approval controller', () => { requestState: { foo: 'bar' }, }); - rootMessenger.call('ApprovalController:updateRequestState', { - id: 'foo', - requestState: { foo: 'foobar' }, - }); + approvalControllerMessenger.call( + 'ApprovalController:updateRequestState', + { + id: 'foo', + requestState: { foo: 'foobar' }, + }, + ); expect(approvalController.get('foo')?.requestState).toStrictEqual({ foo: 'foobar', diff --git a/packages/base-controller/src/next/BaseController.test.ts b/packages/base-controller/src/next/BaseController.test.ts index 7bd2339a50a..954d3277030 100644 --- a/packages/base-controller/src/next/BaseController.test.ts +++ b/packages/base-controller/src/next/BaseController.test.ts @@ -1,5 +1,9 @@ /* eslint-disable jest/no-export */ -import { Messenger } from '@metamask/messenger'; +import { + MOCK_ANY_NAMESPACE, + Messenger, + type MockAnyNamespace, +} from '@metamask/messenger'; import type { Json } from '@metamask/utils'; import type { Draft, Patch } from 'immer'; import * as sinon from 'sinon'; @@ -728,10 +732,10 @@ describe('BaseController', () => { it('should allow messaging between controllers', () => { // Construct root messenger const rootMessenger = new Messenger< - 'Root', + MockAnyNamespace, VisitorControllerActions | VisitorOverflowControllerActions, VisitorControllerEvents | VisitorOverflowControllerEvents - >({ namespace: 'Root' }); + >({ namespace: MOCK_ANY_NAMESPACE }); // Construct controller messengers, delegating to parent const visitorControllerMessenger = new Messenger< typeof visitorName, diff --git a/packages/transaction-controller/src/TransactionControllerIntegration.test.ts b/packages/transaction-controller/src/TransactionControllerIntegration.test.ts index d49269aff3f..4a4cafbfbdc 100644 --- a/packages/transaction-controller/src/TransactionControllerIntegration.test.ts +++ b/packages/transaction-controller/src/TransactionControllerIntegration.test.ts @@ -13,7 +13,9 @@ import { NetworkType, } from '@metamask/controller-utils'; import { + MOCK_ANY_NAMESPACE, Messenger, + type MockAnyNamespace, type MessengerActions, type MessengerEvents, } from '@metamask/messenger'; @@ -86,7 +88,7 @@ type AllEvents = | NetworkControllerEvents | ApprovalControllerEvents; -type RootMessenger = Messenger<'Root', AllActions, AllEvents>; +type RootMessenger = Messenger; const uuidV4Mock = jest.mocked(uuidV4); @@ -170,7 +172,9 @@ const setupController = async ( ], }); - const rootMessenger: RootMessenger = new Messenger({ namespace: 'Root' }); + const rootMessenger: RootMessenger = new Messenger({ + namespace: MOCK_ANY_NAMESPACE, + }); const networkControllerMessenger = new Messenger< 'NetworkController', diff --git a/packages/transaction-controller/src/utils/eip7702.test.ts b/packages/transaction-controller/src/utils/eip7702.test.ts index 82be470ca94..323ff64a120 100644 --- a/packages/transaction-controller/src/utils/eip7702.test.ts +++ b/packages/transaction-controller/src/utils/eip7702.test.ts @@ -2,8 +2,10 @@ import { query } from '@metamask/controller-utils'; import type EthQuery from '@metamask/eth-query'; import { Messenger, + MockAnyNamespace, type MessengerActions, type MessengerEvents, + MOCK_ANY_NAMESPACE, } from '@metamask/messenger'; import type { Hex } from '@metamask/utils'; import { remove0x } from '@metamask/utils'; @@ -77,7 +79,7 @@ const AUTHORIZATION_LIST_MOCK: AuthorizationList = [ describe('EIP-7702 Utils', () => { let rootMessenger: Messenger< - 'Root', + MockAnyNamespace, MessengerActions, MessengerEvents >; @@ -98,7 +100,7 @@ describe('EIP-7702 Utils', () => { beforeEach(() => { jest.resetAllMocks(); - rootMessenger = new Messenger({ namespace: 'Root' }); + rootMessenger = new Messenger({ namespace: MOCK_ANY_NAMESPACE }); signAuthorizationMock = jest .fn() diff --git a/packages/transaction-controller/src/utils/feature-flags.test.ts b/packages/transaction-controller/src/utils/feature-flags.test.ts index 652d3ec168e..1d1e8c91b93 100644 --- a/packages/transaction-controller/src/utils/feature-flags.test.ts +++ b/packages/transaction-controller/src/utils/feature-flags.test.ts @@ -1,5 +1,7 @@ import { + MOCK_ANY_NAMESPACE, Messenger, + type MockAnyNamespace, type MessengerActions, type MessengerEvents, } from '@metamask/messenger'; @@ -41,7 +43,7 @@ const GAS_BUFFER_5_MOCK = 1.5; describe('Feature Flags Utils', () => { let rootMessenger: Messenger< - 'Root', + MockAnyNamespace, MessengerActions, MessengerEvents >; @@ -78,7 +80,7 @@ describe('Feature Flags Utils', () => { getFeatureFlagsMock = jest.fn(); - rootMessenger = new Messenger({ namespace: 'Root' }); + rootMessenger = new Messenger({ namespace: MOCK_ANY_NAMESPACE }); remoteFeatureFlagControllerMessenger = new Messenger({ namespace: 'RemoteFeatureFlagController', diff --git a/packages/transaction-controller/src/utils/swaps.test.ts b/packages/transaction-controller/src/utils/swaps.test.ts index 9f74710da54..147d9e9174a 100644 --- a/packages/transaction-controller/src/utils/swaps.test.ts +++ b/packages/transaction-controller/src/utils/swaps.test.ts @@ -1,6 +1,8 @@ import { query } from '@metamask/controller-utils'; import { + MOCK_ANY_NAMESPACE, Messenger, + type MockAnyNamespace, type MessengerActions, type MessengerEvents, } from '@metamask/messenger'; @@ -46,11 +48,11 @@ describe('updateSwapsTransaction', () => { }, }; const rootMessenger = new Messenger< - 'Root', + MockAnyNamespace, MessengerActions, MessengerEvents >({ - namespace: 'Root', + namespace: MOCK_ANY_NAMESPACE, }); messenger = new Messenger< 'TransactionController', From ca266fd47b191cf3ae9f63f1a6337adeffbde6d4 Mon Sep 17 00:00:00 2001 From: Michele Esposito Date: Mon, 13 Oct 2025 14:42:09 +0200 Subject: [PATCH 55/69] fix: migrate leftover `messagingSystem` to `messenger` --- packages/assets-controllers/src/TokenBalancesController.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/assets-controllers/src/TokenBalancesController.ts b/packages/assets-controllers/src/TokenBalancesController.ts index 2a0c5af49be..a26bc1b64c3 100644 --- a/packages/assets-controllers/src/TokenBalancesController.ts +++ b/packages/assets-controllers/src/TokenBalancesController.ts @@ -359,13 +359,13 @@ export class TokenBalancesController extends StaticIntervalPollingController<{ ); // Subscribe to AccountActivityService balance updates for real-time updates - this.messagingSystem.subscribe( + this.messenger.subscribe( 'AccountActivityService:balanceUpdated', this.#onAccountActivityBalanceUpdate.bind(this), ); // Subscribe to AccountActivityService status changes for dynamic polling management - this.messagingSystem.subscribe( + this.messenger.subscribe( 'AccountActivityService:statusChanged', this.#onAccountActivityStatusChanged.bind(this), ); From e9a7bbd6e932a1cd760d9747d8e0471ffa69b3d9 Mon Sep 17 00:00:00 2001 From: Michele Esposito Date: Mon, 13 Oct 2025 15:05:26 +0200 Subject: [PATCH 56/69] add `BridgeControllerStateChangeEvent` to `index.ts` --- packages/bridge-controller/CHANGELOG.md | 2 +- packages/bridge-controller/src/index.ts | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/bridge-controller/CHANGELOG.md b/packages/bridge-controller/CHANGELOG.md index 4ac772396f7..340317907af 100644 --- a/packages/bridge-controller/CHANGELOG.md +++ b/packages/bridge-controller/CHANGELOG.md @@ -9,7 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added -- Add `BridgeControllerGetStateAction` type ([#6444](https://github.com/MetaMask/core/pull/6444)) +- Add `BridgeControllerGetStateAction` and `BridgeControllerStateChangeEvent` types ([#6444](https://github.com/MetaMask/core/pull/6444)) ### Changed diff --git a/packages/bridge-controller/src/index.ts b/packages/bridge-controller/src/index.ts index 3897bf9a6de..ac9fe235029 100644 --- a/packages/bridge-controller/src/index.ts +++ b/packages/bridge-controller/src/index.ts @@ -58,6 +58,7 @@ export { BridgeUserAction, BridgeBackgroundAction, type BridgeControllerGetStateAction, + type BridgeControllerStateChangeEvent, } from './types'; export { From d6a143394f748dfe7a18ae039aab0ca43b50131f Mon Sep 17 00:00:00 2001 From: Michele Esposito Date: Mon, 13 Oct 2025 15:07:58 +0200 Subject: [PATCH 57/69] fix `bridge-status-controller/CHANGELOG` --- packages/bridge-status-controller/CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/bridge-status-controller/CHANGELOG.md b/packages/bridge-status-controller/CHANGELOG.md index dde68b08b72..0380b005e08 100644 --- a/packages/bridge-status-controller/CHANGELOG.md +++ b/packages/bridge-status-controller/CHANGELOG.md @@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Changed + - **BREAKING:** Use new `Messenger` from `@metamask/messenger` ([#6444](https://github.com/MetaMask/core/pull/6444)) - Previously, `BridgeStatusController` accepted a `RestrictedMessenger` instance from `@metamask/base-controller`. From 1bc9e1fec5393c0254ccea56663153b0a939f1de Mon Sep 17 00:00:00 2001 From: Michele Esposito Date: Mon, 13 Oct 2025 15:51:33 +0200 Subject: [PATCH 58/69] remove polling-controller changelog entry --- packages/polling-controller/CHANGELOG.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/packages/polling-controller/CHANGELOG.md b/packages/polling-controller/CHANGELOG.md index 4b1f45f2ff5..bc9a31b9efd 100644 --- a/packages/polling-controller/CHANGELOG.md +++ b/packages/polling-controller/CHANGELOG.md @@ -12,10 +12,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - **BREAKING:** Use new `Messenger` from `@metamask/messenger` for `StaticIntervalPollingController` and `BlockTrackerPollingController` ([#6444](https://github.com/MetaMask/core/pull/6444)) - Previously, `StaticIntervalPollingController` and `BlockTrackerPollingController` accepted a `RestrictedMessenger` instance from `@metamask/base-controller`. -### Added - -- Add `StaticIntervalPollingControllerNext` to extend from `@metamask/base-controller/next` ([#6386](https://github.com/MetaMask/core/pull/6386)) - ## [14.0.1] ### Changed From 5cb7667c39855a86bb37ae7dd6a911ba624b997f Mon Sep 17 00:00:00 2001 From: Michele Esposito Date: Mon, 20 Oct 2025 21:02:39 +0200 Subject: [PATCH 59/69] migrate `SubscriptionController` messenger --- README.md | 1 + packages/subscription-controller/CHANGELOG.md | 5 ++ packages/subscription-controller/package.json | 1 + .../src/SubscriptionController.test.ts | 59 ++++++++++++------- .../src/SubscriptionController.ts | 38 ++++++------ .../tsconfig.build.json | 3 + .../subscription-controller/tsconfig.json | 3 + yarn.lock | 1 + 8 files changed, 70 insertions(+), 41 deletions(-) diff --git a/README.md b/README.md index 583963d2711..7aae80c22f7 100644 --- a/README.md +++ b/README.md @@ -324,6 +324,7 @@ linkStyle default opacity:0.5 signature_controller --> network_controller; subscription_controller --> base_controller; subscription_controller --> controller_utils; + subscription_controller --> messenger; subscription_controller --> polling_controller; subscription_controller --> profile_sync_controller; token_search_discovery_controller --> base_controller; diff --git a/packages/subscription-controller/CHANGELOG.md b/packages/subscription-controller/CHANGELOG.md index 99efef2c472..b59064206d3 100644 --- a/packages/subscription-controller/CHANGELOG.md +++ b/packages/subscription-controller/CHANGELOG.md @@ -7,6 +7,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Changed + +- **BREAKING:** Use new `Messenger` from `@metamask/messenger` ([#6444](https://github.com/MetaMask/core/pull/6444)) + - Previously, `SubscriptionController` accepted a `RestrictedMessenger` instance from `@metamask/base-controller`. + ## [2.0.0] ### Added diff --git a/packages/subscription-controller/package.json b/packages/subscription-controller/package.json index 451e825c92f..61bb64c57be 100644 --- a/packages/subscription-controller/package.json +++ b/packages/subscription-controller/package.json @@ -49,6 +49,7 @@ "dependencies": { "@metamask/base-controller": "^8.4.1", "@metamask/controller-utils": "^11.14.1", + "@metamask/messenger": "^0.3.0", "@metamask/polling-controller": "^14.0.1", "@metamask/utils": "^11.8.1" }, diff --git a/packages/subscription-controller/src/SubscriptionController.test.ts b/packages/subscription-controller/src/SubscriptionController.test.ts index 17dfd1e2b20..7083b9a40ab 100644 --- a/packages/subscription-controller/src/SubscriptionController.test.ts +++ b/packages/subscription-controller/src/SubscriptionController.test.ts @@ -1,4 +1,11 @@ -import { deriveStateFromMetadata, Messenger } from '@metamask/base-controller'; +import { deriveStateFromMetadata } from '@metamask/base-controller/next'; +import { + Messenger, + MOCK_ANY_NAMESPACE, + type MessengerActions, + type MessengerEvents, + type MockAnyNamespace, +} from '@metamask/messenger'; import * as sinon from 'sinon'; import { @@ -9,7 +16,6 @@ import { SubscriptionServiceError } from './errors'; import { getDefaultSubscriptionControllerState, SubscriptionController, - type AllowedActions, type AllowedEvents, type SubscriptionControllerMessenger, type SubscriptionControllerOptions, @@ -35,6 +41,12 @@ import { } from './types'; import { advanceTime } from '../../../tests/helpers'; +type AllActions = MessengerActions; + +type AllEvents = MessengerEvents; + +type RootMessenger = Messenger; + // Mock data const MOCK_SUBSCRIPTION: Subscription = { id: 'sub_123456789', @@ -113,25 +125,30 @@ const MOCK_GET_SUBSCRIPTIONS_RESPONSE = { function createCustomSubscriptionMessenger(props?: { overrideEvents?: AllowedEvents['type'][]; }) { - const baseMessenger = new Messenger(); + const rootMessenger: RootMessenger = new Messenger({ + namespace: MOCK_ANY_NAMESPACE, + }); - const messenger = baseMessenger.getRestricted< + const messenger = new Messenger< typeof controllerName, - AllowedActions['type'], - AllowedEvents['type'] + AllActions, + AllEvents, + RootMessenger >({ - name: controllerName, - allowedActions: [ + namespace: controllerName, + parent: rootMessenger, + }); + rootMessenger.delegate({ + messenger, + actions: [ 'AuthenticationController:getBearerToken', 'AuthenticationController:performSignOut', ], - allowedEvents: props?.overrideEvents ?? [ - 'AuthenticationController:stateChange', - ], + events: props?.overrideEvents ?? ['AuthenticationController:stateChange'], }); return { - baseMessenger, + rootMessenger, messenger, }; } @@ -140,25 +157,25 @@ function createCustomSubscriptionMessenger(props?: { * Jest Mock Utility to generate a mock Subscription Messenger * * @param overrideMessengers - override messengers if need to modify the underlying permissions - * @param overrideMessengers.baseMessenger - base messenger to override + * @param overrideMessengers.rootMessenger - base messenger to override * @param overrideMessengers.messenger - messenger to override * @returns series of mocks to actions that can be called */ function createMockSubscriptionMessenger(overrideMessengers?: { - baseMessenger: Messenger; + rootMessenger: RootMessenger; messenger: SubscriptionControllerMessenger; }) { - const { baseMessenger, messenger } = + const { rootMessenger, messenger } = overrideMessengers ?? createCustomSubscriptionMessenger(); const mockPerformSignOut = jest.fn(); - baseMessenger.registerActionHandler( + rootMessenger.registerActionHandler( 'AuthenticationController:performSignOut', mockPerformSignOut, ); return { - baseMessenger, + rootMessenger, messenger, mockPerformSignOut, }; @@ -216,7 +233,7 @@ type WithControllerCallback = (params: { controller: SubscriptionController; initialState: SubscriptionControllerState; messenger: SubscriptionControllerMessenger; - baseMessenger: Messenger; + rootMessenger: RootMessenger; mockService: ReturnType['mockService']; mockPerformSignOut: jest.Mock; }) => Promise | ReturnValue; @@ -237,7 +254,7 @@ async function withController( ...args: WithControllerArgs ) { const [{ ...rest }, fn] = args.length === 2 ? args : [{}, args[0]]; - const { messenger, mockPerformSignOut, baseMessenger } = + const { messenger, mockPerformSignOut, rootMessenger } = createMockSubscriptionMessenger(); const { mockService } = createMockSubscriptionService(); @@ -251,7 +268,7 @@ async function withController( controller, initialState: controller.state, messenger, - baseMessenger, + rootMessenger, mockService, mockPerformSignOut, }); @@ -1192,7 +1209,7 @@ describe('SubscriptionController', () => { deriveStateFromMetadata( controller.state, controller.metadata, - 'anonymous', + 'includeInDebugSnapshot', ), ).toMatchInlineSnapshot(` Object { diff --git a/packages/subscription-controller/src/SubscriptionController.ts b/packages/subscription-controller/src/SubscriptionController.ts index 36ba7e16035..4b2146cadb0 100644 --- a/packages/subscription-controller/src/SubscriptionController.ts +++ b/packages/subscription-controller/src/SubscriptionController.ts @@ -2,8 +2,8 @@ import { type StateMetadata, type ControllerStateChangeEvent, type ControllerGetStateAction, - type RestrictedMessenger, -} from '@metamask/base-controller'; +} from '@metamask/base-controller/next'; +import type { Messenger } from '@metamask/messenger'; import { StaticIntervalPollingController } from '@metamask/polling-controller'; import type { AuthenticationController } from '@metamask/profile-sync-controller'; @@ -110,12 +110,10 @@ export type AllowedEvents = AuthenticationController.AuthenticationControllerStateChangeEvent; // Messenger -export type SubscriptionControllerMessenger = RestrictedMessenger< +export type SubscriptionControllerMessenger = Messenger< typeof controllerName, SubscriptionControllerActions | AllowedActions, - SubscriptionControllerEvents | AllowedEvents, - AllowedActions['type'], - AllowedEvents['type'] + SubscriptionControllerEvents | AllowedEvents >; /** @@ -166,25 +164,25 @@ const subscriptionControllerMetadata: StateMetadata subscriptions: { includeInStateLogs: true, persist: true, - anonymous: false, + includeInDebugSnapshot: false, usedInUi: true, }, customerId: { includeInStateLogs: true, persist: true, - anonymous: false, + includeInDebugSnapshot: false, usedInUi: true, }, trialedProducts: { includeInStateLogs: true, persist: true, - anonymous: true, + includeInDebugSnapshot: true, usedInUi: true, }, pricing: { includeInStateLogs: true, persist: true, - anonymous: true, + includeInDebugSnapshot: true, usedInUi: true, }, }; @@ -233,47 +231,47 @@ export class SubscriptionController extends StaticIntervalPollingController()< * actions. */ #registerMessageHandlers(): void { - this.messagingSystem.registerActionHandler( + this.messenger.registerActionHandler( 'SubscriptionController:getSubscriptions', this.getSubscriptions.bind(this), ); - this.messagingSystem.registerActionHandler( + this.messenger.registerActionHandler( 'SubscriptionController:getSubscriptionByProduct', this.getSubscriptionByProduct.bind(this), ); - this.messagingSystem.registerActionHandler( + this.messenger.registerActionHandler( 'SubscriptionController:cancelSubscription', this.cancelSubscription.bind(this), ); - this.messagingSystem.registerActionHandler( + this.messenger.registerActionHandler( 'SubscriptionController:startShieldSubscriptionWithCard', this.startShieldSubscriptionWithCard.bind(this), ); - this.messagingSystem.registerActionHandler( + this.messenger.registerActionHandler( 'SubscriptionController:getPricing', this.getPricing.bind(this), ); - this.messagingSystem.registerActionHandler( + this.messenger.registerActionHandler( 'SubscriptionController:getCryptoApproveTransactionParams', this.getCryptoApproveTransactionParams.bind(this), ); - this.messagingSystem.registerActionHandler( + this.messenger.registerActionHandler( 'SubscriptionController:startSubscriptionWithCrypto', this.startSubscriptionWithCrypto.bind(this), ); - this.messagingSystem.registerActionHandler( + this.messenger.registerActionHandler( 'SubscriptionController:updatePaymentMethod', this.updatePaymentMethod.bind(this), ); - this.messagingSystem.registerActionHandler( + this.messenger.registerActionHandler( 'SubscriptionController:getBillingPortalUrl', this.getBillingPortalUrl.bind(this), ); @@ -576,7 +574,7 @@ export class SubscriptionController extends StaticIntervalPollingController()< // We perform a sign out to clear the access token from the authentication // controller. Next time the access token is requested, a new access token // will be fetched. - this.messagingSystem.call('AuthenticationController:performSignOut'); + this.messenger.call('AuthenticationController:performSignOut'); } #assertIsUserSubscribed(request: { subscriptionId: string }) { diff --git a/packages/subscription-controller/tsconfig.build.json b/packages/subscription-controller/tsconfig.build.json index affca7cb2c1..9c4e429236a 100644 --- a/packages/subscription-controller/tsconfig.build.json +++ b/packages/subscription-controller/tsconfig.build.json @@ -9,6 +9,9 @@ { "path": "../base-controller/tsconfig.build.json" }, + { + "path": "../messenger/tsconfig.build.json" + }, { "path": "../profile-sync-controller/tsconfig.build.json" }, diff --git a/packages/subscription-controller/tsconfig.json b/packages/subscription-controller/tsconfig.json index 04ea472196b..e8c3b75ae82 100644 --- a/packages/subscription-controller/tsconfig.json +++ b/packages/subscription-controller/tsconfig.json @@ -7,6 +7,9 @@ { "path": "../base-controller" }, + { + "path": "../messenger" + }, { "path": "../profile-sync-controller" }, diff --git a/yarn.lock b/yarn.lock index 07446cc02e6..1610420cc56 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4898,6 +4898,7 @@ __metadata: "@metamask/auto-changelog": "npm:^3.4.4" "@metamask/base-controller": "npm:^8.4.1" "@metamask/controller-utils": "npm:^11.14.1" + "@metamask/messenger": "npm:^0.3.0" "@metamask/polling-controller": "npm:^14.0.1" "@metamask/profile-sync-controller": "npm:^25.1.1" "@metamask/utils": "npm:^11.8.1" From b1f0c534e01b6223247dc25085eee13547a57072 Mon Sep 17 00:00:00 2001 From: Michele Esposito Date: Mon, 20 Oct 2025 21:12:41 +0200 Subject: [PATCH 60/69] migrate new `messagingSystem` call --- .../bridge-status-controller/src/bridge-status-controller.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/bridge-status-controller/src/bridge-status-controller.ts b/packages/bridge-status-controller/src/bridge-status-controller.ts index 31c313b057a..f4872cf0805 100644 --- a/packages/bridge-status-controller/src/bridge-status-controller.ts +++ b/packages/bridge-status-controller/src/bridge-status-controller.ts @@ -650,7 +650,7 @@ export class BridgeStatusController extends StaticIntervalPollingController Date: Mon, 20 Oct 2025 21:18:57 +0200 Subject: [PATCH 61/69] migrate new `messagingSystem` call --- packages/assets-controllers/src/TokenBalancesController.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/assets-controllers/src/TokenBalancesController.ts b/packages/assets-controllers/src/TokenBalancesController.ts index fe775c5f453..ca0a2e1efd0 100644 --- a/packages/assets-controllers/src/TokenBalancesController.ts +++ b/packages/assets-controllers/src/TokenBalancesController.ts @@ -1145,7 +1145,7 @@ export class TokenBalancesController extends StaticIntervalPollingController<{ // Update native balances in AccountTrackerController if (nativeBalanceUpdates.length > 0) { - this.messagingSystem.call( + this.messenger.call( 'AccountTrackerController:updateNativeBalances', nativeBalanceUpdates, ); @@ -1153,7 +1153,7 @@ export class TokenBalancesController extends StaticIntervalPollingController<{ // Import any new tokens that were discovered (balance already updated from websocket) if (newTokens.length > 0) { - await this.messagingSystem.call( + await this.messenger.call( 'TokenDetectionController:addDetectedTokensViaWs', { tokensSlice: newTokens, From a3d5fc939b729db257d5a657ffbc2d3cbf2b85a9 Mon Sep 17 00:00:00 2001 From: Michele Esposito Date: Mon, 20 Oct 2025 21:28:13 +0200 Subject: [PATCH 62/69] fix `RatesController` tests --- .../RatesController/RatesController.test.ts | 77 ++++++++++--------- 1 file changed, 40 insertions(+), 37 deletions(-) diff --git a/packages/assets-controllers/src/RatesController/RatesController.test.ts b/packages/assets-controllers/src/RatesController/RatesController.test.ts index 8ba6ccbe2b5..2fadaeda774 100644 --- a/packages/assets-controllers/src/RatesController/RatesController.test.ts +++ b/packages/assets-controllers/src/RatesController/RatesController.test.ts @@ -81,13 +81,14 @@ function setupRatesController({ fetchMultiExchangeRate?: typeof defaultFetchExchangeRate; }) { const ratesControllerMessenger = buildRatesControllerMessenger(messenger); - return new RatesController({ + const ratesController = new RatesController({ interval, messenger: ratesControllerMessenger, state: initialState, includeUsdRate, fetchMultiExchangeRate, }); + return { ratesController, ratesControllerMessenger }; } describe('RatesController', () => { @@ -95,7 +96,7 @@ describe('RatesController', () => { describe('construct', () => { it('constructs the RatesController with default values', () => { - const ratesController = setupRatesController({ + const { ratesController } = setupRatesController({ initialState: {}, messenger: buildRootMessenger(), includeUsdRate: false, @@ -125,7 +126,6 @@ describe('RatesController', () => { it('starts the polling process with default values', async () => { const messenger = buildRootMessenger(); - const publishActionSpy = jest.spyOn(messenger, 'publish'); jest.spyOn(global.Date, 'now').mockImplementation(() => getStubbedDate()); const mockBtcRateValue = 57715.42; @@ -141,15 +141,17 @@ describe('RatesController', () => { }, }); }); - const ratesController = setupRatesController({ - interval: 150, - initialState: { - fiatCurrency: 'eur', - }, - messenger, - fetchMultiExchangeRate: fetchExchangeRateStub, - includeUsdRate: false, - }); + const { ratesController, ratesControllerMessenger } = + setupRatesController({ + interval: 150, + initialState: { + fiatCurrency: 'eur', + }, + messenger, + fetchMultiExchangeRate: fetchExchangeRateStub, + includeUsdRate: false, + }); + const publishActionSpy = jest.spyOn(ratesControllerMessenger, 'publish'); const ratesPreUpdate = ratesController.state.rates; @@ -222,7 +224,7 @@ describe('RatesController', () => { }); }); - const ratesController = setupRatesController({ + const { ratesController } = setupRatesController({ interval: 150, initialState: { cryptocurrencies: [Cryptocurrency.Btc], @@ -270,15 +272,16 @@ describe('RatesController', () => { it('stops the polling process', async () => { const messenger = buildRootMessenger(); - const publishActionSpy = jest.spyOn(messenger, 'publish'); const fetchExchangeRateStub = jest.fn().mockResolvedValue({}); - const ratesController = setupRatesController({ - interval: 150, - initialState: {}, - messenger, - fetchMultiExchangeRate: fetchExchangeRateStub, - includeUsdRate: false, - }); + const { ratesController, ratesControllerMessenger } = + setupRatesController({ + interval: 150, + initialState: {}, + messenger, + fetchMultiExchangeRate: fetchExchangeRateStub, + includeUsdRate: false, + }); + const publishActionSpy = jest.spyOn(ratesControllerMessenger, 'publish'); await ratesController.start(); @@ -319,7 +322,7 @@ describe('RatesController', () => { it('returns the current cryptocurrency list', () => { const fetchExchangeRateStub = jest.fn().mockResolvedValue({}); const mockCryptocurrencyList = [Cryptocurrency.Btc]; - const ratesController = setupRatesController({ + const { ratesController } = setupRatesController({ interval: 150, initialState: { cryptocurrencies: mockCryptocurrencyList, @@ -338,7 +341,7 @@ describe('RatesController', () => { it('updates the cryptocurrency list', async () => { const fetchExchangeRateStub = jest.fn().mockResolvedValue({}); const mockCryptocurrencyList: Cryptocurrency[] = []; // Different from default list - const ratesController = setupRatesController({ + const { ratesController } = setupRatesController({ interval: 150, initialState: {}, messenger: buildRootMessenger(), @@ -369,7 +372,7 @@ describe('RatesController', () => { describe('setCurrentCurrency', () => { it('sets the currency to a new value', async () => { const fetchExchangeRateStub = jest.fn().mockResolvedValue({}); - const ratesController = setupRatesController({ + const { ratesController } = setupRatesController({ interval: 150, initialState: {}, messenger: buildRootMessenger(), @@ -388,7 +391,7 @@ describe('RatesController', () => { it('throws if input is an empty string', async () => { const fetchExchangeRateStub = jest.fn().mockResolvedValue({}); - const ratesController = setupRatesController({ + const { ratesController } = setupRatesController({ interval: 150, initialState: {}, messenger: buildRootMessenger(), @@ -405,7 +408,7 @@ describe('RatesController', () => { describe('metadata', () => { it('includes expected state in debug snapshots', () => { const fetchExchangeRateStub = jest.fn().mockResolvedValue({}); - const controller = setupRatesController({ + const { ratesController } = setupRatesController({ messenger: buildRootMessenger(), fetchMultiExchangeRate: fetchExchangeRateStub, includeUsdRate: false, @@ -413,8 +416,8 @@ describe('RatesController', () => { expect( deriveStateFromMetadata( - controller.state, - controller.metadata, + ratesController.state, + ratesController.metadata, 'includeInDebugSnapshot', ), ).toMatchInlineSnapshot(` @@ -440,7 +443,7 @@ describe('RatesController', () => { it('includes expected state in state logs', () => { const fetchExchangeRateStub = jest.fn().mockResolvedValue({}); - const controller = setupRatesController({ + const { ratesController } = setupRatesController({ messenger: buildRootMessenger(), fetchMultiExchangeRate: fetchExchangeRateStub, includeUsdRate: false, @@ -448,8 +451,8 @@ describe('RatesController', () => { expect( deriveStateFromMetadata( - controller.state, - controller.metadata, + ratesController.state, + ratesController.metadata, 'includeInStateLogs', ), ).toMatchInlineSnapshot(` @@ -465,7 +468,7 @@ describe('RatesController', () => { it('persists expected state', () => { const fetchExchangeRateStub = jest.fn().mockResolvedValue({}); - const controller = setupRatesController({ + const { ratesController } = setupRatesController({ messenger: buildRootMessenger(), fetchMultiExchangeRate: fetchExchangeRateStub, includeUsdRate: false, @@ -473,8 +476,8 @@ describe('RatesController', () => { expect( deriveStateFromMetadata( - controller.state, - controller.metadata, + ratesController.state, + ratesController.metadata, 'persist', ), ).toMatchInlineSnapshot(` @@ -500,7 +503,7 @@ describe('RatesController', () => { it('exposes expected state to UI', () => { const fetchExchangeRateStub = jest.fn().mockResolvedValue({}); - const controller = setupRatesController({ + const { ratesController } = setupRatesController({ messenger: buildRootMessenger(), fetchMultiExchangeRate: fetchExchangeRateStub, includeUsdRate: false, @@ -508,8 +511,8 @@ describe('RatesController', () => { expect( deriveStateFromMetadata( - controller.state, - controller.metadata, + ratesController.state, + ratesController.metadata, 'usedInUi', ), ).toMatchInlineSnapshot(` From bd8994754eab551d9de7ab8f3916487c1f165de1 Mon Sep 17 00:00:00 2001 From: Michele Esposito Date: Mon, 20 Oct 2025 21:30:19 +0200 Subject: [PATCH 63/69] fix `TokenBalancesController` tests --- .../src/TokenBalancesController.test.ts | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/packages/assets-controllers/src/TokenBalancesController.test.ts b/packages/assets-controllers/src/TokenBalancesController.test.ts index 6b6707eff23..a7388c9cf99 100644 --- a/packages/assets-controllers/src/TokenBalancesController.test.ts +++ b/packages/assets-controllers/src/TokenBalancesController.test.ts @@ -4383,13 +4383,14 @@ describe('TokenBalancesController', () => { const chainId = '0x1'; const account = createMockInternalAccount({ address: accountAddress }); - const { controller, messenger } = setupController({ - listAccounts: [account], - }); + const { controller, messenger, tokenBalancesControllerMessenger } = + setupController({ + listAccounts: [account], + }); // Spy on AccountTrackerController calls const updateNativeBalancesSpy = jest.fn(); - jest.spyOn(messenger, 'call').mockImplementation((( + jest.spyOn(tokenBalancesControllerMessenger, 'call').mockImplementation((( action: string, ...args: unknown[] ) => { From 5cfd25698d7ddf1bb0965dff427544841c2f44a7 Mon Sep 17 00:00:00 2001 From: Michele Esposito Date: Tue, 21 Oct 2025 14:02:22 +0200 Subject: [PATCH 64/69] lint: import `MockAnyNamespace` as type --- packages/transaction-controller/src/utils/eip7702.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/transaction-controller/src/utils/eip7702.test.ts b/packages/transaction-controller/src/utils/eip7702.test.ts index 323ff64a120..069b31f3ebc 100644 --- a/packages/transaction-controller/src/utils/eip7702.test.ts +++ b/packages/transaction-controller/src/utils/eip7702.test.ts @@ -2,7 +2,7 @@ import { query } from '@metamask/controller-utils'; import type EthQuery from '@metamask/eth-query'; import { Messenger, - MockAnyNamespace, + type MockAnyNamespace, type MessengerActions, type MessengerEvents, MOCK_ANY_NAMESPACE, From 4881477947910b49a37ce721c9eb1736a77091c6 Mon Sep 17 00:00:00 2001 From: Michele Esposito Date: Fri, 24 Oct 2025 17:07:44 +0200 Subject: [PATCH 65/69] rename `messagingSystem` to `messenger` --- packages/transaction-controller/src/TransactionController.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/transaction-controller/src/TransactionController.ts b/packages/transaction-controller/src/TransactionController.ts index 9ad06d12646..13bdd89b9e6 100644 --- a/packages/transaction-controller/src/TransactionController.ts +++ b/packages/transaction-controller/src/TransactionController.ts @@ -4467,12 +4467,12 @@ export class TransactionController extends BaseController< this.updateTransaction.bind(this), ); - this.messagingSystem.registerActionHandler( + this.messenger.registerActionHandler( `${controllerName}:emulateNewTransaction`, this.emulateNewTransaction.bind(this), ); - this.messagingSystem.registerActionHandler( + this.messenger.registerActionHandler( `${controllerName}:emulateTransactionUpdate`, this.emulateTransactionUpdate.bind(this), ); From cf3638ea23dce0a2260d17e640e4b00b146585b6 Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Fri, 24 Oct 2025 16:01:45 -0230 Subject: [PATCH 66/69] Update messagingSystem references to messenger --- .../src/TransactionController.ts | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/packages/transaction-controller/src/TransactionController.ts b/packages/transaction-controller/src/TransactionController.ts index 13bdd89b9e6..f30de01f283 100644 --- a/packages/transaction-controller/src/TransactionController.ts +++ b/packages/transaction-controller/src/TransactionController.ts @@ -2816,11 +2816,11 @@ export class TransactionController extends BaseController< } if (transactionMeta.type === TransactionType.swap) { - this.messagingSystem.publish('TransactionController:transactionNewSwap', { + this.messenger.publish('TransactionController:transactionNewSwap', { transactionMeta, }); } else if (transactionMeta.type === TransactionType.swapApproval) { - this.messagingSystem.publish( + this.messenger.publish( 'TransactionController:transactionNewSwapApproval', { transactionMeta }, ); @@ -2837,7 +2837,7 @@ export class TransactionController extends BaseController< ...transactionMeta, txParams: { ...transactionMeta.txParams, - from: this.messagingSystem.call('AccountsController:getSelectedAccount') + from: this.messenger.call('AccountsController:getSelectedAccount') .address, }, }; @@ -2857,10 +2857,9 @@ export class TransactionController extends BaseController< 'Generated from user operation', ); - this.messagingSystem.publish( - 'TransactionController:transactionStatusUpdated', - { transactionMeta: updatedTransactionMeta }, - ); + this.messenger.publish('TransactionController:transactionStatusUpdated', { + transactionMeta: updatedTransactionMeta, + }); } #addMetadata(transactionMeta: TransactionMeta) { From 998ffb96d2bfe6b386ed983ac05eb0d0a6d35023 Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Fri, 24 Oct 2025 16:07:31 -0230 Subject: [PATCH 67/69] Update changelogs following branch update --- packages/approval-controller/CHANGELOG.md | 7 +++++-- packages/assets-controllers/CHANGELOG.md | 4 ++-- packages/gas-fee-controller/CHANGELOG.md | 12 +++++++++--- packages/network-controller/CHANGELOG.md | 7 +++++-- packages/transaction-controller/CHANGELOG.md | 10 +++++----- 5 files changed, 26 insertions(+), 14 deletions(-) diff --git a/packages/approval-controller/CHANGELOG.md b/packages/approval-controller/CHANGELOG.md index a911aec0ec1..4aa56e42613 100644 --- a/packages/approval-controller/CHANGELOG.md +++ b/packages/approval-controller/CHANGELOG.md @@ -7,6 +7,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Changed + +- **BREAKING:** Use new `Messenger` from `@metamask/messenger` ([#6386](https://github.com/MetaMask/core/pull/6386)) + - Previously, `ApprovalController` accepted a `RestrictedMessenger` instance from `@metamask/base-controller`. + ## [7.2.1] ### Changed @@ -21,8 +26,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed -- **BREAKING:** Use new `Messenger` from `@metamask/messenger` ([#6386](https://github.com/MetaMask/core/pull/6386)) - - Previously, `ApprovalController` accepted a `RestrictedMessenger` instance from `@metamask/base-controller`. - Bump `@metamask/utils` from `^11.2.0` to `^11.8.1` ([#6054](https://github.com/MetaMask/core/pull/6054), [#6588](https://github.com/MetaMask/core/pull/6588), [#6708](https://github.com/MetaMask/core/pull/6708)) - Bump `@metamask/base-controller` from `^8.0.0` to `^8.4.1` ([#5722](https://github.com/MetaMask/core/pull/5722), [#6284](https://github.com/MetaMask/core/pull/6284), [#6355](https://github.com/MetaMask/core/pull/6355), [#6465](https://github.com/MetaMask/core/pull/6465), [#6632](https://github.com/MetaMask/core/pull/6632), [#6807](https://github.com/MetaMask/core/pull/6807)) diff --git a/packages/assets-controllers/CHANGELOG.md b/packages/assets-controllers/CHANGELOG.md index 4cbe20d211b..239e437d631 100644 --- a/packages/assets-controllers/CHANGELOG.md +++ b/packages/assets-controllers/CHANGELOG.md @@ -9,6 +9,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed +- **BREAKING:** Migrate `AssetsContractController`, `NftController`, and `TokensController` to new `Messenger` from `@metamask/messenger` ([#6386](https://github.com/MetaMask/core/pull/6386)) + - Previously, the controllers accepted a `RestrictedMessenger` instance from `@metamask/base-controller`. - Bump `@metamask/polling-controller` from `^14.0.1` to `^14.0.2` ([#6940](https://github.com/MetaMask/core/pull/6940)) ## [83.1.0] @@ -44,8 +46,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed -- **BREAKING:** Migrate `AssetsContractController`, `NftController`, and `TokensController` to new `Messenger` from `@metamask/messenger` ([#6386](https://github.com/MetaMask/core/pull/6386)) - - Previously, the controllers accepted a `RestrictedMessenger` instance from `@metamask/base-controller`. - Batch `OnAssetConversion` and `OnAssetsMarketData` requests to non-EVM account Snaps ([#6886](https://github.com/MetaMask/core/pull/6886)) ## [81.0.1] diff --git a/packages/gas-fee-controller/CHANGELOG.md b/packages/gas-fee-controller/CHANGELOG.md index 0b5b085c2cb..e464e82052c 100644 --- a/packages/gas-fee-controller/CHANGELOG.md +++ b/packages/gas-fee-controller/CHANGELOG.md @@ -7,6 +7,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Added + +- Export `GasFeeMessenger` type ([#6386](https://github.com/MetaMask/core/pull/6386)) + +### Changed + +- **BREAKING:** Use new `Messenger` from `@metamask/messenger` ([#6386](https://github.com/MetaMask/core/pull/6386)) + - Previously, `GasFeeController` accepted a `RestrictedMessenger` instance from `@metamask/base-controller`. + ## [24.1.1] ### Changed @@ -20,12 +29,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - Add two new controller state metadata properties: `includeInStateLogs` and `usedInUi` ([#6473](https://github.com/MetaMask/core/pull/6473)) -- Export `GasFeeMessenger` type ([#6386](https://github.com/MetaMask/core/pull/6386)) ### Changed -- **BREAKING:** Use new `Messenger` from `@metamask/messenger` ([#6386](https://github.com/MetaMask/core/pull/6386)) - - Previously, `GasFeeController` accepted a `RestrictedMessenger` instance from `@metamask/base-controller`. - Bump `@metamask/base-controller` from `^8.0.1` to `^8.4.1` ([#6284](https://github.com/MetaMask/core/pull/6284), [#6355](https://github.com/MetaMask/core/pull/6355), [#6465](https://github.com/MetaMask/core/pull/6465), [#6632](https://github.com/MetaMask/core/pull/6632), [#6807](https://github.com/MetaMask/core/pull/6807)) - Bump `@metamask/controller-utils` from `^11.10.0` to `^11.14.1` ([#6069](https://github.com/MetaMask/core/pull/6069), [#6303](https://github.com/MetaMask/core/pull/6303), [#6620](https://github.com/MetaMask/core/pull/6620), [#6629](https://github.com/MetaMask/core/pull/6629), [#6807](https://github.com/MetaMask/core/pull/6807)) - Bump `@metamask/utils` from `^11.2.0` to `^11.8.1` ([#6054](https://github.com/MetaMask/core/pull/6054), [#6588](https://github.com/MetaMask/core/pull/6588), [#6708](https://github.com/MetaMask/core/pull/6708)) diff --git a/packages/network-controller/CHANGELOG.md b/packages/network-controller/CHANGELOG.md index 1106f819698..b3dcd31dbfb 100644 --- a/packages/network-controller/CHANGELOG.md +++ b/packages/network-controller/CHANGELOG.md @@ -7,12 +7,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] -## [24.3.1] - ### Changed - **BREAKING:** Use new `Messenger` from `@metamask/messenger` ([#6386](https://github.com/MetaMask/core/pull/6386)) - Previously, `NetworkController` accepted a `RestrictedMessenger` instance from `@metamask/base-controller`. + +## [24.3.1] + +### Changed + - Bump `@metamask/base-controller` from `^8.4.1` to `^8.4.2` ([#6917](https://github.com/MetaMask/core/pull/6917)) ## [24.3.0] diff --git a/packages/transaction-controller/CHANGELOG.md b/packages/transaction-controller/CHANGELOG.md index 2c13c272f42..a16a9bf7218 100644 --- a/packages/transaction-controller/CHANGELOG.md +++ b/packages/transaction-controller/CHANGELOG.md @@ -7,6 +7,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Changed + +- **BREAKING:** Use new `Messenger` from `@metamask/messenger` ([#6386](https://github.com/MetaMask/core/pull/6386)) + - Previously, `TransactionController` accepted a `RestrictedMessenger` instance from `@metamask/base-controller`. + ## [60.10.0] ### Added @@ -48,11 +53,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Add `txMeta` property to `GetSimulationConfig` callback ([#6833](https://github.com/MetaMask/core/pull/6833)) -### Changed - -- **BREAKING:** Use new `Messenger` from `@metamask/messenger` ([#6386](https://github.com/MetaMask/core/pull/6386)) - - Previously, `TransactionController` accepted a `RestrictedMessenger` instance from `@metamask/base-controller`. - ## [60.6.1] ### Changed From ac996395bfd3997d37c6ea5ed19f1ce628770494 Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Fri, 24 Oct 2025 16:26:11 -0230 Subject: [PATCH 68/69] Fix changelog mistakes from recent merges --- packages/assets-controllers/CHANGELOG.md | 5 ++++- packages/bridge-status-controller/CHANGELOG.md | 4 ++-- packages/subscription-controller/CHANGELOG.md | 4 ++-- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/packages/assets-controllers/CHANGELOG.md b/packages/assets-controllers/CHANGELOG.md index 089ee38d9be..532159b939e 100644 --- a/packages/assets-controllers/CHANGELOG.md +++ b/packages/assets-controllers/CHANGELOG.md @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Added + +- Add export for `CurrencyRateMessenger` ([#6444](https://github.com/MetaMask/core/pull/6444)) + ### Changed - **BREAKING:** Migrate the following controllers to the new `Messenger` from `@metamask/messenger` ([#6444](https://github.com/MetaMask/core/pull/6444)) @@ -49,7 +53,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - **BREAKING:** Add new event listeners to refresh balances on `TransactionControllerUnapprovedTransactionAddedEvent` and `TransactionControllerTransactionConfirmedEvent` ([#6903](https://github.com/MetaMask/core/pull/6903)) -- Add export for `CurrencyRateMessenger` ([#6444](https://github.com/MetaMask/core/pull/6444)) - Add multicall addresses in `MULTICALL_CONTRACT_BY_CHAINID` ([#6896](https://github.com/MetaMask/core/pull/6896)) - Add multicall address for Chains: `Injective`, `Hemi`, `Plasma`, `Nonmia`, `XRPL`, `Soneium`, `Genesys`, `EDU`, `Abstract`, `Berachain`, `MegaETH Testnet`, `Apechain`, `Matchain`, `Monad Testnet`, `Monad`, `Katana`, `Lens`, `Plume`, `XDC` diff --git a/packages/bridge-status-controller/CHANGELOG.md b/packages/bridge-status-controller/CHANGELOG.md index b1f3875defa..8f3d28b229b 100644 --- a/packages/bridge-status-controller/CHANGELOG.md +++ b/packages/bridge-status-controller/CHANGELOG.md @@ -9,6 +9,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed +- **BREAKING:** Use new `Messenger` from `@metamask/messenger` ([#6444](https://github.com/MetaMask/core/pull/6444)) + - Previously, `BridgeStatusController` accepted a `RestrictedMessenger` instance from `@metamask/base-controller`. - Bump `@metamask/polling-controller` from `^14.0.1` to `^14.0.2` ([#6940](https://github.com/MetaMask/core/pull/6940)) ## [55.0.0] @@ -34,8 +36,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed -- **BREAKING:** Use new `Messenger` from `@metamask/messenger` ([#6444](https://github.com/MetaMask/core/pull/6444)) - - Previously, `BridgeStatusController` accepted a `RestrictedMessenger` instance from `@metamask/base-controller`. - Publish `destinationTransactionCompleted` event when a bridge tx completes on the destination chain ([#6900](https://github.com/MetaMask/core/pull/6900)) ## [52.0.0] diff --git a/packages/subscription-controller/CHANGELOG.md b/packages/subscription-controller/CHANGELOG.md index 528f8236b9c..30d5b1f3886 100644 --- a/packages/subscription-controller/CHANGELOG.md +++ b/packages/subscription-controller/CHANGELOG.md @@ -9,14 +9,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed +- **BREAKING:** Use new `Messenger` from `@metamask/messenger` ([#6444](https://github.com/MetaMask/core/pull/6444)) + - Previously, `SubscriptionController` accepted a `RestrictedMessenger` instance from `@metamask/base-controller`. - Bump `@metamask/polling-controller` from `^14.0.1` to `^14.0.2` ([#6940](https://github.com/MetaMask/core/pull/6940)) ## [2.1.0] ### Changed -- **BREAKING:** Use new `Messenger` from `@metamask/messenger` ([#6444](https://github.com/MetaMask/core/pull/6444)) - - Previously, `SubscriptionController` accepted a `RestrictedMessenger` instance from `@metamask/base-controller`. - Make `getCryptoApproveTransactionParams` synchronous ([#6930](https://github.com/MetaMask/core/pull/6930)) - Bump `@metamask/base-controller` from `^8.4.1` to `^8.4.2` ([#6917](https://github.com/MetaMask/core/pull/6917)) From 9660de8e9f0606d9f8d5b1655e73f71c30953159 Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Fri, 24 Oct 2025 16:32:30 -0230 Subject: [PATCH 69/69] Update ESLint warning threshold --- eslint-warning-thresholds.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eslint-warning-thresholds.json b/eslint-warning-thresholds.json index 85c35fde51b..054fae43f2f 100644 --- a/eslint-warning-thresholds.json +++ b/eslint-warning-thresholds.json @@ -56,7 +56,7 @@ }, "packages/assets-controllers/src/TokenListController.test.ts": { "import-x/namespace": 7, - "import-x/order": 3, + "import-x/order": 2, "jest/no-conditional-in-test": 2 }, "packages/assets-controllers/src/TokenRatesController.test.ts": {