diff --git a/README.md b/README.md index 75517b4265e..faacafc4f03 100644 --- a/README.md +++ b/README.md @@ -166,8 +166,10 @@ linkStyle default opacity:0.5 app_metadata_controller --> base_controller; app_metadata_controller --> messenger; 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; @@ -275,6 +277,7 @@ linkStyle default opacity:0.5 network_controller --> eth_json_rpc_middleware; 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; @@ -333,6 +336,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_block_tracker; diff --git a/eslint-warning-thresholds.json b/eslint-warning-thresholds.json index f5a52c63e63..85c35fde51b 100644 --- a/eslint-warning-thresholds.json +++ b/eslint-warning-thresholds.json @@ -68,7 +68,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": { diff --git a/packages/approval-controller/CHANGELOG.md b/packages/approval-controller/CHANGELOG.md index 1ded7e4bc93..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 diff --git a/packages/approval-controller/package.json b/packages/approval-controller/package.json index cf16f60c99d..a22204434a3 100644 --- a/packages/approval-controller/package.json +++ b/packages/approval-controller/package.json @@ -48,6 +48,7 @@ }, "dependencies": { "@metamask/base-controller": "^8.4.2", + "@metamask/messenger": "^0.3.0", "@metamask/rpc-errors": "^7.0.2", "@metamask/utils": "^11.8.1", "nanoid": "^3.3.8" diff --git a/packages/approval-controller/src/ApprovalController.test.ts b/packages/approval-controller/src/ApprovalController.test.ts index e817a38ed56..652a87ba4f3 100644 --- a/packages/approval-controller/src/ApprovalController.test.ts +++ b/packages/approval-controller/src/ApprovalController.test.ts @@ -1,6 +1,13 @@ /* eslint-disable jest/expect-expect */ -import { deriveStateFromMetadata, Messenger } 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 { errorCodes, JsonRpcError } from '@metamask/rpc-errors'; import { nanoid } from 'nanoid'; @@ -9,6 +16,7 @@ import type { AddApprovalOptions, ApprovalControllerActions, ApprovalControllerEvents, + ApprovalControllerMessenger, ErrorOptions, StartFlowOptions, SuccessOptions, @@ -28,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'; @@ -223,20 +237,26 @@ 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< - ApprovalControllerActions, - ApprovalControllerEvents - >(); - return messenger.getRestricted({ - name: 'ApprovalController', - allowedActions: [], - allowedEvents: [], +function getMessengers() { + const rootMessenger: RootMessenger = new Messenger({ + namespace: MOCK_ANY_NAMESPACE, }); + return { + rootMessenger, + approvalControllerMessenger: new Messenger< + typeof controllerName, + ApprovalControllerActions, + ApprovalControllerEvents, + typeof rootMessenger + >({ + namespace: controllerName, + parent: rootMessenger, + }), + }; } describe('approval controller', () => { @@ -250,7 +270,7 @@ describe('approval controller', () => { showApprovalRequest = jest.fn(); approvalController = new ApprovalController({ - messenger: getRestrictedMessenger(), + messenger: getMessengers().approvalControllerMessenger, showApprovalRequest, }); }); @@ -445,7 +465,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 +658,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 +698,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 +1289,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 +1308,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 +1327,10 @@ describe('approval controller', () => { }); it('updateRequestState', () => { - const messenger = new Messenger< - ApprovalControllerActions, - ApprovalControllerEvents - >(); + const { approvalControllerMessenger } = getMessengers(); approvalController = new ApprovalController({ - messenger: messenger.getRestricted({ - name: controllerName, - allowedActions: [], - allowedEvents: [], - }), + messenger: approvalControllerMessenger, showApprovalRequest, }); @@ -1344,10 +1343,13 @@ describe('approval controller', () => { requestState: { foo: 'bar' }, }); - messenger.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', @@ -1719,7 +1721,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 9f577677cf5..f2e7efe13c3 100644 --- a/packages/approval-controller/src/ApprovalController.ts +++ b/packages/approval-controller/src/ApprovalController.ts @@ -1,9 +1,12 @@ -import type { ControllerGetStateAction } from '@metamask/base-controller'; +import type { + ControllerGetStateAction, + StateMetadata, +} from '@metamask/base-controller/next'; 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'; @@ -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, }, }; @@ -134,12 +137,10 @@ export type ApprovalControllerState = { approvalFlows: ApprovalFlowState[]; }; -export type ApprovalControllerMessenger = RestrictedMessenger< +export type ApprovalControllerMessenger = Messenger< typeof controllerName, ApprovalControllerActions, - ApprovalControllerEvents, - never, - never + ApprovalControllerEvents >; // Option Types @@ -413,12 +414,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) { @@ -428,47 +429,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/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/CHANGELOG.md b/packages/assets-controllers/CHANGELOG.md index 6b4d6e6f690..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] diff --git a/packages/assets-controllers/package.json b/packages/assets-controllers/package.json index 07de6f4f141..0b332da6f79 100644 --- a/packages/assets-controllers/package.json +++ b/packages/assets-controllers/package.json @@ -59,6 +59,7 @@ "@metamask/controller-utils": "^11.14.1", "@metamask/eth-query": "^4.0.0", "@metamask/keyring-api": "^21.0.0", + "@metamask/messenger": "^0.3.0", "@metamask/metamask-eth-abis": "^3.1.1", "@metamask/polling-controller": "^14.0.2", "@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 a3d69a8670c..1313cd75ea6 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/packages/assets-controllers/src/NftController.test.ts b/packages/assets-controllers/src/NftController.test.ts index 1f8a75e2f6e..6a8eecb93ba 100644 --- a/packages/assets-controllers/src/NftController.test.ts +++ b/packages/assets-controllers/src/NftController.test.ts @@ -6,7 +6,7 @@ import type { } from '@metamask/accounts-controller'; import type { ApprovalControllerMessenger } from '@metamask/approval-controller'; import { ApprovalController } from '@metamask/approval-controller'; -import { Messenger, deriveStateFromMetadata } from '@metamask/base-controller'; +import { deriveStateFromMetadata } from '@metamask/base-controller/next'; import { IPFS_DEFAULT_GATEWAY_URL, ERC1155, @@ -22,14 +22,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 +59,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'; @@ -226,15 +235,9 @@ function setupController({ mockGetNetworkClientIdByChainId?: Record; displayNftMedia?: boolean; } = {}) { - const messenger = new Messenger< - | ExtractAvailableAction - | NftControllerAllowedActions - | ExtractAvailableAction, - | ExtractAvailableEvent - | NftControllerAllowedEvents - | ExtractAvailableEvent - | AccountsControllerSelectedAccountChangeEvent - >(); + const messenger: RootMessenger = new Messenger({ + namespace: MOCK_ANY_NAMESPACE, + }); const getNetworkClientById = buildMockGetNetworkClientById( mockNetworkClientConfigurationsByNetworkClientId, @@ -331,10 +334,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({ @@ -350,14 +357,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', @@ -371,7 +382,7 @@ function setupController({ 'NetworkController:findNetworkClientIdByChainId', 'PhishingController:bulkScanUrls', ], - allowedEvents: [ + events: [ 'AccountsController:selectedEvmAccountChange', 'PreferencesController:stateChange', ], @@ -379,7 +390,7 @@ function setupController({ const nftController = new NftController({ onNftAdded: jest.fn(), - messenger: nftControllerMessenger as NftControllerMessenger, + messenger: nftControllerMessenger, ...options, }); @@ -408,6 +419,7 @@ function setupController({ return { nftController, messenger, + nftControllerMessenger, approvalController, triggerPreferencesStateChange, triggerSelectedAccountChange, @@ -645,11 +657,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( @@ -684,11 +696,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( @@ -719,7 +731,7 @@ describe('NftController', () => { ); const { nftController, - messenger, + nftControllerMessenger, triggerPreferencesStateChange, triggerSelectedAccountChange, } = setupController({ @@ -746,7 +758,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` @@ -846,7 +858,7 @@ describe('NftController', () => { ); const { nftController, - messenger, + nftControllerMessenger, triggerPreferencesStateChange, triggerSelectedAccountChange, } = setupController({ @@ -872,7 +884,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` @@ -972,7 +984,7 @@ describe('NftController', () => { ); const { nftController, - messenger, + nftControllerMessenger, triggerPreferencesStateChange, triggerSelectedAccountChange, } = setupController({ @@ -998,7 +1010,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` @@ -1098,7 +1110,7 @@ describe('NftController', () => { ); const { nftController, - messenger, + nftControllerMessenger, triggerPreferencesStateChange, triggerSelectedAccountChange, } = setupController({ @@ -1125,7 +1137,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` @@ -1226,7 +1238,7 @@ describe('NftController', () => { const { nftController, - messenger, + nftControllerMessenger, triggerPreferencesStateChange, triggerSelectedAccountChange, } = setupController({ @@ -1256,7 +1268,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` @@ -1359,20 +1371,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, @@ -1385,7 +1400,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` @@ -5951,7 +5966,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 adbe53087c4..1027997d7f1 100644 --- a/packages/assets-controllers/src/NftController.ts +++ b/packages/assets-controllers/src/NftController.ts @@ -5,14 +5,12 @@ 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'; + type StateMetadata, +} from '@metamask/base-controller/next'; import { safelyExecute, handleFetch, @@ -29,6 +27,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, @@ -238,23 +237,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, }, }; @@ -309,12 +308,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 => ({ @@ -399,7 +396,7 @@ export class NftController extends BaseController< }, }); - this.#selectedAccountId = this.messagingSystem.call( + this.#selectedAccountId = this.messenger.call( 'AccountsController:getSelectedAccount', ).id; this.#ipfsGateway = ipfsGateway; @@ -408,12 +405,12 @@ export class NftController extends BaseController< this.#isIpfsGatewayEnabled = isIpfsGatewayEnabled; this.#onNftAdded = onNftAdded; - this.messagingSystem.subscribe( + this.messenger.subscribe( 'PreferencesController:stateChange', this.#onPreferencesControllerStateChange.bind(this), ); - this.messagingSystem.subscribe( + this.messenger.subscribe( 'AccountsController:selectedEvmAccountChange', this.#onSelectedAccountChange.bind(this), ); @@ -441,7 +438,7 @@ export class NftController extends BaseController< displayNftMedia?: boolean; openSeaEnabled?: boolean; }) { - const selectedAccount = this.messagingSystem.call( + const selectedAccount = this.messenger.call( 'AccountsController:getSelectedAccount', ); this.#selectedAccountId = selectedAccount.id; @@ -748,7 +745,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, @@ -761,7 +758,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, @@ -804,7 +801,7 @@ export class NftController extends BaseController< ): Promise { const { configuration: { chainId }, - } = this.messagingSystem.call( + } = this.messenger.call( 'NetworkController:getNetworkClientById', networkClientId, ); @@ -853,12 +850,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, @@ -1055,7 +1052,7 @@ export class NftController extends BaseController< const { allNftContracts } = this.state; const { configuration: { chainId }, - } = this.messagingSystem.call( + } = this.messenger.call( 'NetworkController:getNetworkClientById', networkClientId as NetworkClientId, ); @@ -1388,7 +1385,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, @@ -1401,7 +1398,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, @@ -1520,7 +1517,7 @@ export class NftController extends BaseController< ); const { configuration: { chainId }, - } = this.messagingSystem.call( + } = this.messenger.call( 'NetworkController:getNetworkClientById', networkClientId, ); @@ -1574,7 +1571,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), ); @@ -1679,7 +1676,7 @@ export class NftController extends BaseController< const { configuration: { chainId }, - } = this.messagingSystem.call( + } = this.messenger.call( 'NetworkController:getNetworkClientById', networkClientId as NetworkClientId, ); @@ -1721,7 +1718,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, ); @@ -1772,7 +1769,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, ); @@ -1848,7 +1845,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, ); @@ -1899,7 +1896,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, ); @@ -2070,7 +2067,7 @@ export class NftController extends BaseController< } async _requestApproval(suggestedNftMeta: SuggestedNftMeta) { - return this.messagingSystem.call( + return this.messenger.call( 'ApprovalController:addRequest', { id: suggestedNftMeta.id, @@ -2099,7 +2096,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, ); @@ -2212,7 +2209,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, ); diff --git a/packages/assets-controllers/src/TokensController.test.ts b/packages/assets-controllers/src/TokensController.test.ts index 5bfd1fedd6a..b84f5a901b5 100644 --- a/packages/assets-controllers/src/TokensController.test.ts +++ b/packages/assets-controllers/src/TokensController.test.ts @@ -1,10 +1,10 @@ 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 { deriveStateFromMetadata, Messenger } from '@metamask/base-controller'; +import { deriveStateFromMetadata } from '@metamask/base-controller/next'; import contractMaps from '@metamask/contract-metadata'; import { ApprovalType, @@ -14,6 +14,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 +34,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 +44,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 +56,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); @@ -3477,7 +3483,7 @@ describe('TokensController', () => { deriveStateFromMetadata( controller.state, controller.metadata, - 'anonymous', + 'includeInDebugSnapshot', ), ).toMatchInlineSnapshot(`Object {}`); }); @@ -3545,7 +3551,7 @@ type WithControllerCallback = ({ changeNetwork: (networkControllerState: { selectedNetworkClientId: NetworkClientId; }) => void; - messenger: UnrestrictedMessenger; + messenger: RootMessenger; approvalController: ApprovalController; triggerSelectedAccountChange: (internalAccount: InternalAccount) => void; triggerAccountRemoved: (accountAddress: string) => void; @@ -3603,12 +3609,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, @@ -3616,16 +3628,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', @@ -3663,7 +3684,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 571e28188de..8a45509a468 100644 --- a/packages/assets-controllers/src/TokensController.ts +++ b/packages/assets-controllers/src/TokensController.ts @@ -8,11 +8,11 @@ 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'; + StateMetadata, +} from '@metamask/base-controller/next'; +import { BaseController } from '@metamask/base-controller/next'; import contractsMap from '@metamask/contract-metadata'; import { toChecksumHexAddress, @@ -27,6 +27,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, @@ -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, }, }; @@ -158,12 +159,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 => { @@ -224,32 +223,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; @@ -419,7 +418,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; @@ -505,7 +504,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; @@ -581,7 +580,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; @@ -739,7 +738,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; @@ -798,7 +797,7 @@ export class TokensController extends BaseController< #getProvider(networkClientId?: NetworkClientId): Web3Provider { return new Web3Provider( networkClientId - ? this.messagingSystem.call( + ? this.messenger.call( 'NetworkController:getNetworkClientById', networkClientId, ).provider @@ -1082,7 +1081,7 @@ export class TokensController extends BaseController< } async #requestApproval(suggestedAssetMeta: SuggestedAssetMeta) { - return this.messagingSystem.call( + return this.messenger.call( 'ApprovalController:addRequest', { id: suggestedAssetMeta.id, @@ -1104,12 +1103,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, ); diff --git a/packages/assets-controllers/tsconfig.build.json b/packages/assets-controllers/tsconfig.build.json index 629b833e22a..5ef0e52c3b8 100644 --- a/packages/assets-controllers/tsconfig.build.json +++ b/packages/assets-controllers/tsconfig.build.json @@ -14,6 +14,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 ae60fdfc0d7..a537b98ca39 100644 --- a/packages/assets-controllers/tsconfig.json +++ b/packages/assets-controllers/tsconfig.json @@ -13,6 +13,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/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/gas-fee-controller/CHANGELOG.md b/packages/gas-fee-controller/CHANGELOG.md index d5853050c10..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 diff --git a/packages/gas-fee-controller/src/GasFeeController.test.ts b/packages/gas-fee-controller/src/GasFeeController.test.ts index 4153f3829b2..9e736d00018 100644 --- a/packages/gas-fee-controller/src/GasFeeController.test.ts +++ b/packages/gas-fee-controller/src/GasFeeController.test.ts @@ -1,16 +1,20 @@ -import { deriveStateFromMetadata, Messenger } from '@metamask/base-controller'; +import { deriveStateFromMetadata } from '@metamask/base-controller/next'; 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 +34,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 +51,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 +127,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 +302,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, @@ -1277,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 6a50f0cfbdf..be6fe7b3fb0 100644 --- a/packages/gas-fee-controller/src/GasFeeController.ts +++ b/packages/gas-fee-controller/src/GasFeeController.ts @@ -1,14 +1,15 @@ import type { ControllerGetStateAction, ControllerStateChangeEvent, - RestrictedMessenger, -} from '@metamask/base-controller'; + StateMetadata, +} 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 +19,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'; @@ -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, }, }; @@ -262,12 +263,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 = { @@ -286,7 +285,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 @@ -398,14 +397,14 @@ export class GasFeeController extends StaticIntervalPollingController; /** @@ -1202,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, }, }, @@ -1235,7 +1233,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`, @@ -1244,80 +1242,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`, @@ -1541,15 +1539,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(); } @@ -1768,7 +1760,7 @@ export class NetworkController extends BaseController< const listener = () => { networkChanged = true; try { - this.messagingSystem.unsubscribe( + this.messenger.unsubscribe( 'NetworkController:networkDidChange', listener, ); @@ -1792,10 +1784,7 @@ export class NetworkController extends BaseController< } } }; - this.messagingSystem.subscribe( - 'NetworkController:networkDidChange', - listener, - ); + this.messenger.subscribe('NetworkController:networkDidChange', listener); const { isInfura, networkStatus, isEIP1559Compatible } = await this.#determineNetworkMetadata(this.state.selectedNetworkClientId); @@ -1807,7 +1796,7 @@ export class NetworkController extends BaseController< } try { - this.messagingSystem.unsubscribe( + this.messenger.unsubscribe( 'NetworkController:networkDidChange', listener, ); @@ -1829,15 +1818,15 @@ export class NetworkController extends BaseController< if (isInfura) { if (networkStatus === NetworkStatus.Available) { - this.messagingSystem.publish('NetworkController:infuraIsUnblocked'); + this.messenger.publish('NetworkController:infuraIsUnblocked'); } else if (networkStatus === 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'); } } @@ -2108,7 +2097,7 @@ export class NetworkController extends BaseController< }); }); - this.messagingSystem.publish( + this.messenger.publish( `${controllerName}:networkAdded`, newNetworkConfiguration, ); @@ -2445,7 +2434,7 @@ export class NetworkController extends BaseController< }); }); - this.messagingSystem.publish( + this.messenger.publish( 'NetworkController:networkRemoved', existingNetworkConfiguration, ); @@ -2849,7 +2838,7 @@ export class NetworkController extends BaseController< }, getRpcServiceOptions: this.#getRpcServiceOptions, getBlockTrackerOptions: this.#getBlockTrackerOptions, - messenger: this.messagingSystem, + messenger: this.messenger, isRpcFailoverEnabled: this.#isRpcFailoverEnabled, logger: this.#log, }); @@ -2866,7 +2855,7 @@ export class NetworkController extends BaseController< }, getRpcServiceOptions: this.#getRpcServiceOptions, getBlockTrackerOptions: this.#getBlockTrackerOptions, - messenger: this.messagingSystem, + messenger: this.messenger, isRpcFailoverEnabled: this.#isRpcFailoverEnabled, logger: this.#log, }); @@ -3029,7 +3018,7 @@ export class NetworkController extends BaseController< }, getRpcServiceOptions: this.#getRpcServiceOptions, getBlockTrackerOptions: this.#getBlockTrackerOptions, - messenger: this.messagingSystem, + messenger: this.messenger, isRpcFailoverEnabled: this.#isRpcFailoverEnabled, logger: this.#log, }), @@ -3047,7 +3036,7 @@ export class NetworkController extends BaseController< }, getRpcServiceOptions: this.#getRpcServiceOptions, getBlockTrackerOptions: this.#getBlockTrackerOptions, - messenger: this.messagingSystem, + messenger: this.messenger, isRpcFailoverEnabled: this.#isRpcFailoverEnabled, logger: this.#log, }), 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 358fbb79e2d..4841f92b647 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, @@ -166,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: {}, }, @@ -187,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({ @@ -213,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({ @@ -246,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({ @@ -278,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({ @@ -310,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({ @@ -357,9 +357,9 @@ describe('NetworkController', () => { 'ErrorReportingService:captureException', jest.fn(), ); - const restrictedMessenger = buildNetworkControllerMessenger(messenger); + const controllerMessenger = buildNetworkControllerMessenger(messenger); const controller = new NetworkController({ - messenger: restrictedMessenger, + messenger: controllerMessenger, state: { selectedNetworkClientId: 'nonexistent', networkConfigurationsByChainId: { @@ -398,10 +398,10 @@ describe('NetworkController', () => { 'ErrorReportingService:captureException', captureExceptionMock, ); - const restrictedMessenger = buildNetworkControllerMessenger(messenger); + const controllerMessenger = buildNetworkControllerMessenger(messenger); new NetworkController({ - messenger: restrictedMessenger, + messenger: controllerMessenger, state: { selectedNetworkClientId: 'nonexistent', networkConfigurationsByChainId: { @@ -442,11 +442,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, @@ -2385,7 +2385,7 @@ describe('NetworkController', () => { }, infuraProjectId, }, - async ({ controller, messenger }) => { + async ({ controller, networkControllerMessenger }) => { const fakeProvider = buildFakeProvider([ // Called during provider initialization { @@ -2409,7 +2409,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 @@ -2896,7 +2896,7 @@ describe('NetworkController', () => { }, infuraProjectId, }, - async ({ controller, messenger }) => { + async ({ controller, networkControllerMessenger }) => { const fakeProvider = buildFakeProvider([ // Called during provider initialization { @@ -2920,7 +2920,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 @@ -14507,7 +14507,7 @@ describe('NetworkController', () => { deriveStateFromMetadata( controller.state, controller.metadata, - 'anonymous', + 'includeInDebugSnapshot', ), ).toMatchInlineSnapshot(`Object {}`); }); diff --git a/packages/network-controller/tests/helpers.ts b/packages/network-controller/tests/helpers.ts index 77d6100549b..bff0d7f5010 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,13 @@ import { NetworksTicker, toHex, } 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'; @@ -13,10 +19,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 +44,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 + MockAnyNamespace, + AllNetworkControllerActions, + AllNetworkControllerEvents >; /** @@ -76,23 +85,32 @@ export const TESTNET = { * @returns The messenger. */ export function buildRootMessenger(): RootMessenger { - return new Messenger(); + return new Messenger({ namespace: MOCK_ANY_NAMESPACE }); } /** - * 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; } /** diff --git a/packages/network-controller/tsconfig.build.json b/packages/network-controller/tsconfig.build.json index 0cbfa18f6af..3aa1aa62e0f 100644 --- a/packages/network-controller/tsconfig.build.json +++ b/packages/network-controller/tsconfig.build.json @@ -12,7 +12,8 @@ { "path": "../eth-json-rpc-middleware/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 7a59daff571..9f1911d6466 100644 --- a/packages/network-controller/tsconfig.json +++ b/packages/network-controller/tsconfig.json @@ -11,7 +11,8 @@ { "path": "../eth-json-rpc-middleware" }, { "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/polling-controller/CHANGELOG.md b/packages/polling-controller/CHANGELOG.md index 8d6f8b906d6..60ff27b48bd 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)) + ## [14.0.2] ### Changed diff --git a/packages/polling-controller/src/StaticIntervalPollingController.ts b/packages/polling-controller/src/StaticIntervalPollingController.ts index 5076dfcffdf..34f130ff96f 100644 --- a/packages/polling-controller/src/StaticIntervalPollingController.ts +++ b/packages/polling-controller/src/StaticIntervalPollingController.ts @@ -1,4 +1,5 @@ import { BaseController } from '@metamask/base-controller'; +import { BaseController as BaseControllerNext } from '@metamask/base-controller/next'; import type { Json } from '@metamask/utils'; import { @@ -89,3 +90,10 @@ 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 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'; diff --git a/packages/transaction-controller/CHANGELOG.md b/packages/transaction-controller/CHANGELOG.md index ad53ec10f6b..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 diff --git a/packages/transaction-controller/package.json b/packages/transaction-controller/package.json index 3b68d910323..7aa0dfc821e 100644 --- a/packages/transaction-controller/package.json +++ b/packages/transaction-controller/package.json @@ -57,6 +57,7 @@ "@metamask/base-controller": "^8.4.2", "@metamask/controller-utils": "^11.14.1", "@metamask/eth-query": "^4.0.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/packages/transaction-controller/src/TransactionController.test.ts b/packages/transaction-controller/src/TransactionController.test.ts index 44ed9a2ca41..f59aac432ca 100644 --- a/packages/transaction-controller/src/TransactionController.test.ts +++ b/packages/transaction-controller/src/TransactionController.test.ts @@ -4,7 +4,7 @@ import type { AddApprovalRequest, AddResult, } from '@metamask/approval-controller'; -import { Messenger, deriveStateFromMetadata } from '@metamask/base-controller'; +import { deriveStateFromMetadata } from '@metamask/base-controller/next'; import { ChainId, NetworkType, @@ -15,6 +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, + type MockAnyNamespace, + type MessengerActions, + type MessengerEvents, + MOCK_ANY_NAMESPACE, +} from '@metamask/messenger'; import type { BlockTracker, NetworkClientConfiguration, @@ -50,11 +57,8 @@ 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'; import { TransactionController } from './TransactionController'; @@ -111,9 +115,16 @@ import { buildMockGetNetworkClientById, } from '../../network-controller/tests/helpers'; -type UnrestrictedMessenger = Messenger< - TransactionControllerActions | AllowedActions, - TransactionControllerEvents | AllowedEvents +type AllTransactionControllerActions = + MessengerActions; + +type AllTransactionControllerEvents = + MessengerEvents; + +type RootMessenger = Messenger< + MockAnyNamespace, + AllTransactionControllerActions, + AllTransactionControllerEvents >; const MOCK_V1_UUID = '9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d'; @@ -329,10 +340,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 @@ -662,11 +670,13 @@ describe('TransactionController', () => { listener(networkState); }); }; - const unrestrictedMessenger: UnrestrictedMessenger = new Messenger(); + const rootMessenger: RootMessenger = new Messenger({ + namespace: MOCK_ANY_NAMESPACE, + }); const getNetworkClientById = buildMockGetNetworkClientById( mockNetworkClientConfigurationsByNetworkClientId, ); - unrestrictedMessenger.registerActionHandler( + rootMessenger.registerActionHandler( 'NetworkController:getNetworkClientById', getNetworkClientById, ); @@ -674,7 +684,7 @@ describe('TransactionController', () => { const { addTransactionApprovalRequest = { state: 'pending' } } = messengerOptions; const mockTransactionApprovalRequest = mockAddTransactionApprovalRequest( - unrestrictedMessenger, + rootMessenger, addTransactionApprovalRequest, ); @@ -699,28 +709,31 @@ 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 mockGetSelectedAccount = jest.fn().mockReturnValue(selectedAccount); - unrestrictedMessenger.registerActionHandler( + rootMessenger.registerActionHandler( 'AccountsController:getSelectedAccount', mockGetSelectedAccount, ); - unrestrictedMessenger.registerActionHandler( + rootMessenger.registerActionHandler( 'AccountsController:getState', () => ({}) as never, ); @@ -729,14 +742,14 @@ describe('TransactionController', () => { featureFlags: {}, }); - unrestrictedMessenger.registerActionHandler( + rootMessenger.registerActionHandler( 'RemoteFeatureFlagController:getState', remoteFeatureFlagControllerGetStateMock, ); const controller = new TransactionController({ ...otherOptions, - messenger: restrictedMessenger, + messenger: transactionControllerMessenger, } as TransactionControllerOptions); const state = givenOptions?.state; @@ -759,7 +772,8 @@ describe('TransactionController', () => { return { controller, - messenger: unrestrictedMessenger, + messenger: transactionControllerMessenger, + rootMessenger, mockTransactionApprovalRequest, mockGetSelectedAccount, changeNetwork, @@ -788,7 +802,7 @@ describe('TransactionController', () => { * finally the mocked version of the action handler itself. */ function mockAddTransactionApprovalRequest( - messenger: UnrestrictedMessenger, + messenger: RootMessenger, options: | { state: 'approved'; @@ -6044,8 +6058,8 @@ describe('TransactionController', () => { }); it('uses the nonceTracker for the networkClientId matching the chainId', async () => { - const { controller, messenger } = setupController(); - messenger.registerActionHandler( + const { controller, rootMessenger } = setupController(); + rootMessenger.registerActionHandler( 'NetworkController:findNetworkClientIdByChainId', () => 'sepolia', ); @@ -8234,7 +8248,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 705f33f6b48..f30de01f283 100644 --- a/packages/transaction-controller/src/TransactionController.ts +++ b/packages/transaction-controller/src/TransactionController.ts @@ -11,9 +11,9 @@ import type { import type { ControllerGetStateAction, ControllerStateChangeEvent, - RestrictedMessenger, -} from '@metamask/base-controller'; -import { BaseController } from '@metamask/base-controller'; + StateMetadata, +} from '@metamask/base-controller/next'; +import { BaseController } from '@metamask/base-controller/next'; import { query, ApprovalType, @@ -27,6 +27,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, @@ -177,35 +178,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, }, }; @@ -758,12 +759,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 >; /** @@ -955,7 +954,7 @@ export class TransactionController extends BaseController< }, }); - this.messagingSystem = messenger; + this.messenger = messenger; this.#afterAdd = hooks?.afterAdd ?? (() => Promise.resolve({})); this.#afterSign = hooks?.afterSign ?? (() => true); @@ -1003,7 +1002,7 @@ export class TransactionController extends BaseController< this.#transactionHistoryLimit = transactionHistoryLimit; const findNetworkClientIdByChainId = (chainId: Hex) => { - return this.messagingSystem.call( + return this.messenger.call( `NetworkController:findNetworkClientIdByChainId`, chainId, ); @@ -1012,7 +1011,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, ); @@ -1024,10 +1023,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); }, }); @@ -1043,12 +1039,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); }, }); @@ -1083,7 +1076,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, @@ -1095,7 +1088,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, ); @@ -1103,7 +1096,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, @@ -1147,7 +1140,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, ); @@ -1170,7 +1163,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: ( @@ -1196,7 +1189,7 @@ export class TransactionController extends BaseController< return isAtomicBatchSupported({ ...request, getEthQuery: (chainId) => this.#getEthQuery({ chainId }), - messenger: this.messagingSystem, + messenger: this.messenger, publicKeyEIP7702: this.#publicKeyEIP7702, }); } @@ -1384,7 +1377,7 @@ export class TransactionController extends BaseController< { isSwapsDisabled: this.#isSwapsDisabled, cancelTransaction: this.#rejectTransaction.bind(this), - messenger: this.messagingSystem, + messenger: this.messenger, }, ); @@ -1416,7 +1409,7 @@ export class TransactionController extends BaseController< ); } - this.messagingSystem.publish( + this.messenger.publish( `${controllerName}:unapprovedTransactionAdded`, addedTransactionMeta, ); @@ -1484,7 +1477,7 @@ export class TransactionController extends BaseController< txParams.value = '0x0'; }, afterSubmit: (newTransactionMeta) => { - this.messagingSystem.publish( + this.messenger.publish( `${controllerName}:transactionFinished`, newTransactionMeta, ); @@ -1523,7 +1516,7 @@ export class TransactionController extends BaseController< transactionId, transactionType: TransactionType.retry, afterSubmit: (newTransactionMeta) => { - this.messagingSystem.publish( + this.messenger.publish( `${controllerName}:speedupTransactionAdded`, newTransactionMeta, ); @@ -1639,12 +1632,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, }); @@ -1680,7 +1673,7 @@ export class TransactionController extends BaseController< ignoreDelegationSignatures, isSimulationEnabled: this.#isSimulationEnabled(), getSimulationConfig: this.#getSimulationConfig, - messenger: this.messagingSystem, + messenger: this.messenger, txParams: transaction, }); @@ -1709,7 +1702,7 @@ export class TransactionController extends BaseController< ethQuery, isSimulationEnabled: this.#isSimulationEnabled(), getSimulationConfig: this.#getSimulationConfig, - messenger: this.messagingSystem, + messenger: this.messenger, txParams: transaction, }); @@ -1856,7 +1849,7 @@ export class TransactionController extends BaseController< throw error; }); - this.messagingSystem.publish( + this.messenger.publish( `${controllerName}:transactionConfirmed`, updatedTransactionMeta, ); @@ -2200,7 +2193,7 @@ export class TransactionController extends BaseController< await updateTransactionLayer1GasFee({ layer1GasFeeFlows: this.#layer1GasFeeFlows, - messenger: this.messagingSystem, + messenger: this.messenger, provider, transactionMeta: updatedTransaction, }); @@ -2394,7 +2387,7 @@ export class TransactionController extends BaseController< status as TransactionStatus, ) ) { - this.messagingSystem.publish( + this.messenger.publish( `${controllerName}:transactionFinished`, updatedTransactionMeta, ); @@ -2528,7 +2521,7 @@ export class TransactionController extends BaseController< const gasFeeFlow = getGasFeeFlow( transactionMeta, this.#gasFeeFlows, - this.messagingSystem, + this.messenger, ) as GasFeeFlow; const ethQuery = new EthQuery(provider); @@ -2540,7 +2533,7 @@ export class TransactionController extends BaseController< return gasFeeFlow.getGasFees({ ethQuery, gasFeeControllerData, - messenger: this.messagingSystem, + messenger: this.messenger, transactionMeta, }); } @@ -2570,7 +2563,7 @@ export class TransactionController extends BaseController< return await getTransactionLayer1GasFee({ layer1GasFeeFlows: this.#layer1GasFeeFlows, - messenger: this.messagingSystem, + messenger: this.messenger, provider, transactionMeta: { txParams: transactionParams, @@ -2823,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 }, ); @@ -2844,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, }, }; @@ -2864,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) { @@ -2908,7 +2900,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, }), ); @@ -2918,7 +2910,7 @@ export class TransactionController extends BaseController< async () => await updateTransactionLayer1GasFee({ layer1GasFeeFlows: this.#layer1GasFeeFlows, - messenger: this.messagingSystem, + messenger: this.messenger, provider, transactionMeta, }), @@ -3025,13 +3017,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 }; @@ -3163,7 +3152,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, ); @@ -3233,11 +3222,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, ); @@ -3295,7 +3284,7 @@ export class TransactionController extends BaseController< error: normalizeTxError(error ?? providerErrors.userRejectedRequest()), }; - this.messagingSystem.publish( + this.messenger.publish( `${controllerName}:transactionFinished`, updatedTransactionMeta, ); @@ -3305,7 +3294,7 @@ export class TransactionController extends BaseController< updatedTransactionMeta, ); - this.messagingSystem.publish(`${controllerName}:transactionRejected`, { + this.messenger.publish(`${controllerName}:transactionRejected`, { transactionMeta: updatedTransactionMeta, actionId, }); @@ -3407,7 +3396,7 @@ export class TransactionController extends BaseController< parentContext: traceContext, }); - return (await this.messagingSystem.call( + return (await this.messenger.call( 'ApprovalController:addRequest', { id, @@ -3543,7 +3532,7 @@ export class TransactionController extends BaseController< ); }); - this.messagingSystem.publish( + this.messenger.publish( `${controllerName}:incomingTransactionsReceived`, finalTransactions, ); @@ -3692,7 +3681,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( @@ -3782,7 +3771,7 @@ export class TransactionController extends BaseController< const signedAuthorizationList = await signAuthorizationList({ authorizationList, - messenger: this.messagingSystem, + messenger: this.messenger, transactionMeta, }); @@ -3874,7 +3863,7 @@ export class TransactionController extends BaseController< } #onTransactionStatusChange(transactionMeta: TransactionMeta) { - this.messagingSystem.publish(`${controllerName}:transactionStatusUpdated`, { + this.messenger.publish(`${controllerName}:transactionStatusUpdated`, { transactionMeta, }); } @@ -3897,7 +3886,7 @@ export class TransactionController extends BaseController< this.#markNonceDuplicatesDropped(transactionMeta.id); - this.messagingSystem.publish( + this.messenger.publish( `${controllerName}:transactionConfirmed`, transactionMeta, ); @@ -3928,7 +3917,7 @@ export class TransactionController extends BaseController< updateTransaction: this.updateTransaction.bind(this), }); - this.messagingSystem.publish( + this.messenger.publish( `${controllerName}:postTransactionBalanceUpdated`, { transactionMeta: updatedTransactionMeta, @@ -3992,7 +3981,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, @@ -4268,7 +4257,7 @@ export class TransactionController extends BaseController< chainId, getSimulationConfig: this.#getSimulationConfig, isEIP7702GasFeeTokensEnabled: this.#isEIP7702GasFeeTokensEnabled, - messenger: this.messagingSystem, + messenger: this.messenger, publicKeyEIP7702: this.#publicKeyEIP7702, transactionMeta, }); @@ -4367,11 +4356,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') @@ -4431,58 +4420,58 @@ 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}:addTransaction`, this.addTransaction.bind(this), ); - this.messagingSystem.registerActionHandler( + this.messenger.registerActionHandler( `${controllerName}:addTransactionBatch`, this.addTransactionBatch.bind(this), ); - this.messagingSystem.registerActionHandler( + this.messenger.registerActionHandler( `${controllerName}:confirmExternalTransaction`, this.confirmExternalTransaction.bind(this), ); - this.messagingSystem.registerActionHandler( + this.messenger.registerActionHandler( `${controllerName}:estimateGas`, this.estimateGas.bind(this), ); - this.messagingSystem.registerActionHandler( + this.messenger.registerActionHandler( `${controllerName}:getNonceLock`, this.getNonceLock.bind(this), ); - this.messagingSystem.registerActionHandler( + this.messenger.registerActionHandler( `${controllerName}:getTransactions`, this.getTransactions.bind(this), ); - this.messagingSystem.registerActionHandler( + this.messenger.registerActionHandler( `${controllerName}:updateCustodialTransaction`, this.updateCustodialTransaction.bind(this), ); - this.messagingSystem.registerActionHandler( + this.messenger.registerActionHandler( `${controllerName}:updateTransaction`, 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), ); @@ -4556,7 +4545,7 @@ export class TransactionController extends BaseController< }; } - this.messagingSystem.publish(`${controllerName}:transactionFailed`, { + this.messenger.publish(`${controllerName}:transactionFailed`, { actionId, error: error.message, transactionMeta: newTransactionMeta, @@ -4564,7 +4553,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/TransactionControllerIntegration.test.ts b/packages/transaction-controller/src/TransactionControllerIntegration.test.ts index b1713b98523..48e94d4e685 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,13 @@ import { InfuraNetworkType, NetworkType, } from '@metamask/controller-utils'; +import { + MOCK_ANY_NAMESPACE, + Messenger, + type MockAnyNamespace, + type MessengerActions, + type MessengerEvents, +} from '@metamask/messenger'; import { NetworkController, NetworkClientType, @@ -30,8 +36,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 +70,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; const uuidV4Mock = jest.mocked(uuidV4); @@ -158,13 +172,21 @@ const setupController = async ( ], }); - const unrestrictedMessenger: UnrestrictedMessenger = new Messenger(); + const rootMessenger: RootMessenger = new Messenger({ + namespace: MOCK_ANY_NAMESPACE, + }); + + 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 +199,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 +233,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: {} }), ); diff --git a/packages/transaction-controller/src/utils/eip7702.test.ts b/packages/transaction-controller/src/utils/eip7702.test.ts index 1b70fa09db1..069b31f3ebc 100644 --- a/packages/transaction-controller/src/utils/eip7702.test.ts +++ b/packages/transaction-controller/src/utils/eip7702.test.ts @@ -1,6 +1,12 @@ import { query } from '@metamask/controller-utils'; import type EthQuery from '@metamask/eth-query'; -import type { RemoteFeatureFlagControllerGetStateAction } from '@metamask/remote-feature-flag-controller'; +import { + Messenger, + type MockAnyNamespace, + type MessengerActions, + type MessengerEvents, + MOCK_ANY_NAMESPACE, +} from '@metamask/messenger'; import type { Hex } from '@metamask/utils'; import { remove0x } from '@metamask/utils'; @@ -16,7 +22,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 +78,10 @@ const AUTHORIZATION_LIST_MOCK: AuthorizationList = [ ]; describe('EIP-7702 Utils', () => { - let baseMessenger: Messenger< - | KeyringControllerSignEip7702AuthorizationAction - | RemoteFeatureFlagControllerGetStateAction, - never + let rootMessenger: Messenger< + MockAnyNamespace, + MessengerActions, + MessengerEvents >; const getCodeMock = jest.mocked(query); @@ -95,21 +100,33 @@ describe('EIP-7702 Utils', () => { beforeEach(() => { jest.resetAllMocks(); - baseMessenger = new Messenger(); + rootMessenger = new Messenger({ namespace: MOCK_ANY_NAMESPACE }); 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..1d1e8c91b93 100644 --- a/packages/transaction-controller/src/utils/feature-flags.test.ts +++ b/packages/transaction-controller/src/utils/feature-flags.test.ts @@ -1,4 +1,10 @@ -import { Messenger } from '@metamask/base-controller'; +import { + MOCK_ANY_NAMESPACE, + Messenger, + type MockAnyNamespace, + type MessengerActions, + type MessengerEvents, +} from '@metamask/messenger'; import type { RemoteFeatureFlagControllerGetStateAction } from '@metamask/remote-feature-flag-controller'; import type { Hex } from '@metamask/utils'; @@ -36,13 +42,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< + MockAnyNamespace, + MessengerActions, + MessengerEvents >; let controllerMessenger: TransactionControllerMessenger; + let remoteFeatureFlagControllerMessenger: Messenger< + 'RemoteFeatureFlagController', + RemoteFeatureFlagControllerGetStateAction, + never, + typeof rootMessenger + >; + let getFeatureFlagsMock: jest.MockedFn< RemoteFeatureFlagControllerGetStateAction['handler'] >; @@ -66,17 +80,25 @@ describe('Feature Flags Utils', () => { getFeatureFlagsMock = jest.fn(); - baseMessenger = new Messenger(); + rootMessenger = new Messenger({ namespace: MOCK_ANY_NAMESPACE }); + + 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..147d9e9174a 100644 --- a/packages/transaction-controller/src/utils/swaps.test.ts +++ b/packages/transaction-controller/src/utils/swaps.test.ts @@ -1,5 +1,11 @@ -import { Messenger } from '@metamask/base-controller'; import { query } from '@metamask/controller-utils'; +import { + MOCK_ANY_NAMESPACE, + Messenger, + type MockAnyNamespace, + type MessengerActions, + type MessengerEvents, +} from '@metamask/messenger'; import { updateSwapsTransaction, @@ -9,13 +15,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 +47,29 @@ describe('updateSwapsTransaction', () => { destinationTokenSymbol: 'DAI', }, }; + const rootMessenger = new Messenger< + MockAnyNamespace, + MessengerActions, + MessengerEvents + >({ + namespace: MOCK_ANY_NAMESPACE, + }); 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/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"] diff --git a/yarn.lock b/yarn.lock index 1305279b509..2fa22b1aace 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2728,6 +2728,7 @@ __metadata: dependencies: "@metamask/auto-changelog": "npm:^3.4.4" "@metamask/base-controller": "npm:^8.4.2" + "@metamask/messenger": "npm:^0.3.0" "@metamask/rpc-errors": "npm:^7.0.2" "@metamask/utils": "npm:^11.8.1" "@types/jest": "npm:^27.4.1" @@ -2769,6 +2770,7 @@ __metadata: "@metamask/keyring-controller": "npm:^23.2.0" "@metamask/keyring-internal-api": "npm:^9.0.0" "@metamask/keyring-snap-client": "npm:^8.0.0" + "@metamask/messenger": "npm:^0.3.0" "@metamask/metamask-eth-abis": "npm:^3.1.1" "@metamask/multichain-account-service": "npm:^1.6.2" "@metamask/network-controller": "npm:^24.3.1" @@ -4237,6 +4239,7 @@ __metadata: "@metamask/eth-json-rpc-provider": "npm:^5.0.1" "@metamask/eth-query": "npm:^4.0.0" "@metamask/json-rpc-engine": "npm:^10.1.1" + "@metamask/messenger": "npm:^0.3.0" "@metamask/rpc-errors": "npm:^7.0.2" "@metamask/swappable-obj-proxy": "npm:^2.3.0" "@metamask/utils": "npm:^11.8.1" @@ -5009,6 +5012,7 @@ __metadata: "@metamask/eth-query": "npm:^4.0.0" "@metamask/ethjs-provider-http": "npm:^0.3.0" "@metamask/gas-fee-controller": "npm:^24.1.1" + "@metamask/messenger": "npm:^0.3.0" "@metamask/metamask-eth-abis": "npm:^3.1.1" "@metamask/network-controller": "npm:^24.3.1" "@metamask/nonce-tracker": "npm:^6.0.0"