diff --git a/eslint-warning-thresholds.json b/eslint-warning-thresholds.json index 8c1926a4725..72532d38b10 100644 --- a/eslint-warning-thresholds.json +++ b/eslint-warning-thresholds.json @@ -34,8 +34,8 @@ "jsdoc/tag-lines": 1 }, "packages/assets-controllers/src/RatesController/RatesController.test.ts": { - "import-x/order": 2, - "jsdoc/tag-lines": 4 + "import-x/order": 1, + "jsdoc/tag-lines": 2 }, "packages/assets-controllers/src/RatesController/RatesController.ts": { "@typescript-eslint/prefer-readonly": 1, @@ -56,7 +56,7 @@ }, "packages/assets-controllers/src/TokenListController.test.ts": { "import-x/namespace": 7, - "import-x/order": 3, + "import-x/order": 2, "jest/no-conditional-in-test": 2 }, "packages/assets-controllers/src/TokenRatesController.test.ts": { diff --git a/packages/assets-controllers/CHANGELOG.md b/packages/assets-controllers/CHANGELOG.md index 77852259eba..bae98c18814 100644 --- a/packages/assets-controllers/CHANGELOG.md +++ b/packages/assets-controllers/CHANGELOG.md @@ -13,16 +13,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed -- **BREAKING:** Migrate the following controllers to the new `Messenger` from `@metamask/messenger` ([#6444](https://github.com/MetaMask/core/pull/6444)) - - `AccountTrackerController` - - `CurrencyRateController` - - `DeFiPositionController` - - `MultichainAssetsRatesController` - - `TokenBalancesController` - - `TokenDetectionController` - - `TokenListController` - - `TokenRatesController` -- **BREAKING:** Migrate `AssetsContractController`, `NftController`, and `TokensController` to new `Messenger` from `@metamask/messenger` ([#6386](https://github.com/MetaMask/core/pull/6386)) +- **BREAKING:** Migrate controllers to new `Messenger` from `@metamask/messenger` ([#6444](https://github.com/MetaMask/core/pull/6444), [#6386](https://github.com/MetaMask/core/pull/6386), [#6745](https://github.com/MetaMask/core/pull/6745)) - Previously, the controllers accepted a `RestrictedMessenger` instance from `@metamask/base-controller`. ## [81.0.0] diff --git a/packages/assets-controllers/src/MultichainAssetsController/MultichainAssetsController.test.ts b/packages/assets-controllers/src/MultichainAssetsController/MultichainAssetsController.test.ts index 9f07e38a6ab..1bc95642ae5 100644 --- a/packages/assets-controllers/src/MultichainAssetsController/MultichainAssetsController.test.ts +++ b/packages/assets-controllers/src/MultichainAssetsController/MultichainAssetsController.test.ts @@ -1,4 +1,4 @@ -import { deriveStateFromMetadata, Messenger } from '@metamask/base-controller'; +import { deriveStateFromMetadata } from '@metamask/base-controller/next'; import type { AccountAssetListUpdatedEventPayload, CaipAssetTypeOrId, @@ -11,6 +11,13 @@ import { } from '@metamask/keyring-api'; import { KeyringTypes } from '@metamask/keyring-controller'; import type { InternalAccount } from '@metamask/keyring-internal-api'; +import { + Messenger, + MOCK_ANY_NAMESPACE, + type MessengerActions, + type MessengerEvents, + type MockAnyNamespace, +} from '@metamask/messenger'; import type { PermissionConstraint } from '@metamask/permission-controller'; import type { SubjectPermissions } from '@metamask/permission-controller'; import type { Snap } from '@metamask/snaps-utils'; @@ -27,10 +34,6 @@ import type { MultichainAssetsControllerState, } from './MultichainAssetsController'; import { advanceTime } from '../../../../tests/helpers'; -import type { - ExtractAvailableAction, - ExtractAvailableEvent, -} from '../../../base-controller/tests/helpers'; const mockSolanaAccount: InternalAccount = { type: 'solana:data-account', @@ -216,21 +219,26 @@ const mockGetMetadataReturnValue: AssetMetadataResponse | undefined = { /** * The union of actions that the root messenger allows. */ -type RootAction = ExtractAvailableAction; +type RootAction = MessengerActions; /** * The union of events that the root messenger allows. */ -type RootEvent = ExtractAvailableEvent; +type RootEvent = MessengerEvents; + +/** + * The root messenger type. + */ +type RootMessenger = Messenger; /** - * Constructs the unrestricted messenger. This can be used to call actions and + * Constructs the root messenger. This can be used to call actions and * publish events within the tests for this controller. * - * @returns The unrestricted messenger suited for MultichainAssetsController. + * @returns The root messenger suited for MultichainAssetsController. */ -function getRootMessenger(): Messenger { - return new Messenger(); +function getRootMessenger(): RootMessenger { + return new Messenger({ namespace: MOCK_ANY_NAMESPACE }); } const setupController = ({ @@ -248,20 +256,24 @@ const setupController = ({ const messenger = getRootMessenger(); const multichainAssetsControllerMessenger: MultichainAssetsControllerMessenger = - messenger.getRestricted({ - name: 'MultichainAssetsController', - allowedActions: [ - 'AccountsController:listMultichainAccounts', - 'SnapController:handleRequest', - 'SnapController:getAll', - 'PermissionController:getPermissions', - ], - allowedEvents: [ - 'AccountsController:accountAdded', - 'AccountsController:accountRemoved', - 'AccountsController:accountAssetListUpdated', - ], + new Messenger({ + namespace: 'MultichainAssetsController', + parent: messenger, }); + messenger.delegate({ + messenger: multichainAssetsControllerMessenger, + actions: [ + 'AccountsController:listMultichainAccounts', + 'SnapController:handleRequest', + 'SnapController:getAll', + 'PermissionController:getPermissions', + ], + events: [ + 'AccountsController:accountAdded', + 'AccountsController:accountRemoved', + 'AccountsController:accountAssetListUpdated', + ], + }); const mockSnapHandleRequest = jest.fn(); messenger.registerActionHandler( @@ -827,7 +839,7 @@ describe('MultichainAssetsController', () => { deriveStateFromMetadata( controller.state, controller.metadata, - 'anonymous', + 'includeInDebugSnapshot', ), ).toMatchInlineSnapshot(`Object {}`); }); diff --git a/packages/assets-controllers/src/MultichainAssetsController/MultichainAssetsController.ts b/packages/assets-controllers/src/MultichainAssetsController/MultichainAssetsController.ts index 5b477a83c70..81358d1378a 100644 --- a/packages/assets-controllers/src/MultichainAssetsController/MultichainAssetsController.ts +++ b/packages/assets-controllers/src/MultichainAssetsController/MultichainAssetsController.ts @@ -8,8 +8,8 @@ import { BaseController, type ControllerGetStateAction, type ControllerStateChangeEvent, - type RestrictedMessenger, -} from '@metamask/base-controller'; + type StateMetadata, +} from '@metamask/base-controller/next'; import { isEvmAccountType } from '@metamask/keyring-api'; import type { AccountAssetListUpdatedEventPayload, @@ -18,6 +18,7 @@ import type { } from '@metamask/keyring-api'; import type { InternalAccount } from '@metamask/keyring-internal-api'; import { KeyringClient } from '@metamask/keyring-snap-client'; +import type { Messenger } from '@metamask/messenger'; import type { GetPermissions, PermissionConstraint, @@ -141,12 +142,10 @@ type AllowedEvents = /** * Messenger type for the MultichainAssetsController. */ -export type MultichainAssetsControllerMessenger = RestrictedMessenger< +export type MultichainAssetsControllerMessenger = Messenger< typeof controllerName, MultichainAssetsControllerActions | AllowedActions, - MultichainAssetsControllerEvents | AllowedEvents, - AllowedActions['type'], - AllowedEvents['type'] + MultichainAssetsControllerEvents | AllowedEvents >; /** @@ -156,20 +155,21 @@ export type MultichainAssetsControllerMessenger = RestrictedMessenger< * using the `persist` flag; and if they can be sent to Sentry or not, using * the `anonymous` flag. */ -const assetsControllerMetadata = { - assetsMetadata: { - includeInStateLogs: false, - persist: true, - anonymous: false, - usedInUi: true, - }, - accountsAssets: { - includeInStateLogs: false, - persist: true, - anonymous: false, - usedInUi: true, - }, -}; +const assetsControllerMetadata: StateMetadata = + { + assetsMetadata: { + includeInStateLogs: false, + persist: true, + includeInDebugSnapshot: false, + usedInUi: true, + }, + accountsAssets: { + includeInStateLogs: false, + persist: true, + includeInDebugSnapshot: false, + usedInUi: true, + }, + }; // TODO: make this controller extends StaticIntervalPollingController and update all assetsMetadata once a day. @@ -202,15 +202,15 @@ export class MultichainAssetsController extends BaseController< this.#snaps = {}; - this.messagingSystem.subscribe( + this.messenger.subscribe( 'AccountsController:accountAdded', async (account) => await this.#handleOnAccountAddedEvent(account), ); - this.messagingSystem.subscribe( + this.messenger.subscribe( 'AccountsController:accountRemoved', async (account) => await this.#handleOnAccountRemovedEvent(account), ); - this.messagingSystem.subscribe( + this.messenger.subscribe( 'AccountsController:accountAssetListUpdated', async (event) => await this.#handleAccountAssetListUpdatedEvent(event), ); @@ -237,7 +237,7 @@ export class MultichainAssetsController extends BaseController< * actions. */ #registerMessageHandlers() { - this.messagingSystem.registerActionHandler( + this.messenger.registerActionHandler( 'MultichainAssetsController:getAssetMetadata', this.getAssetMetadata.bind(this), ); @@ -323,7 +323,7 @@ export class MultichainAssetsController extends BaseController< // Trigger fetching metadata for new assets await this.#refreshAssetsMetadata(Array.from(assetsForMetadataRefresh)); - this.messagingSystem.publish(`${controllerName}:accountAssetListUpdated`, { + this.messenger.publish(`${controllerName}:accountAssetListUpdated`, { assets: accountsAndAssetsToUpdate, }); } @@ -364,17 +364,14 @@ export class MultichainAssetsController extends BaseController< this.update((state) => { state.accountsAssets[account.id] = assets; }); - this.messagingSystem.publish( - `${controllerName}:accountAssetListUpdated`, - { - assets: { - [account.id]: { - added: assets, - removed: [], - }, + this.messenger.publish(`${controllerName}:accountAssetListUpdated`, { + assets: { + [account.id]: { + added: assets, + removed: [], }, }, - ); + }); } } @@ -510,7 +507,7 @@ export class MultichainAssetsController extends BaseController< */ #getAllSnaps(): Snap[] { // TODO: Use dedicated SnapController's action once available for this: - return this.messagingSystem + return this.messenger .call('SnapController:getAll') .filter((snap) => snap.enabled && !snap.blocked); } @@ -524,7 +521,7 @@ export class MultichainAssetsController extends BaseController< #getSnapsPermissions( origin: string, ): SubjectPermissions { - return this.messagingSystem.call( + return this.messenger.call( 'PermissionController:getPermissions', origin, ) as SubjectPermissions; @@ -542,7 +539,7 @@ export class MultichainAssetsController extends BaseController< snapId: string, ): Promise { try { - return (await this.messagingSystem.call('SnapController:handleRequest', { + return (await this.messenger.call('SnapController:handleRequest', { snapId: snapId as SnapId, origin: 'metamask', handler: HandlerType.OnAssetsLookup, @@ -584,7 +581,7 @@ export class MultichainAssetsController extends BaseController< #getClient(snapId: string): KeyringClient { return new KeyringClient({ send: async (request: JsonRpcRequest) => - (await this.messagingSystem.call('SnapController:handleRequest', { + (await this.messenger.call('SnapController:handleRequest', { snapId: snapId as SnapId, origin: 'metamask', handler: HandlerType.OnKeyringRequest, diff --git a/packages/assets-controllers/src/MultichainBalancesController/MultichainBalancesController.test.ts b/packages/assets-controllers/src/MultichainBalancesController/MultichainBalancesController.test.ts index 7d28fc95176..53f17015c27 100644 --- a/packages/assets-controllers/src/MultichainBalancesController/MultichainBalancesController.test.ts +++ b/packages/assets-controllers/src/MultichainBalancesController/MultichainBalancesController.test.ts @@ -1,4 +1,4 @@ -import { Messenger, deriveStateFromMetadata } from '@metamask/base-controller'; +import { deriveStateFromMetadata } from '@metamask/base-controller/next'; import type { Balance, CaipAssetType } from '@metamask/keyring-api'; import { BtcAccountType, @@ -13,6 +13,13 @@ import { } from '@metamask/keyring-api'; import { KeyringTypes } from '@metamask/keyring-controller'; import type { InternalAccount } from '@metamask/keyring-internal-api'; +import { + MOCK_ANY_NAMESPACE, + Messenger, + type MessengerActions, + type MessengerEvents, + type MockAnyNamespace, +} from '@metamask/messenger'; import { v4 as uuidv4 } from 'uuid'; import { MultichainBalancesController } from '.'; @@ -21,10 +28,6 @@ import type { MultichainBalancesControllerState, } from '.'; import { getDefaultMultichainBalancesControllerState } from './MultichainBalancesController'; -import type { - ExtractAvailableAction, - ExtractAvailableEvent, -} from '../../../base-controller/tests/helpers'; const mockBtcAccount = { address: 'bc1qssdcp5kvwh6nghzg9tuk99xsflwkdv4hgvq58q', @@ -103,21 +106,26 @@ const mockBalanceResult = { /** * The union of actions that the root messenger allows. */ -type RootAction = ExtractAvailableAction; +type RootAction = MessengerActions; /** * The union of events that the root messenger allows. */ -type RootEvent = ExtractAvailableEvent; +type RootEvent = MessengerEvents; /** - * Constructs the unrestricted messenger. This can be used to call actions and + * The root messenger type + */ +type RootMessenger = Messenger; + +/** + * Constructs the root messenger. This can be used to call actions and * publish events within the tests for this controller. * - * @returns The unrestricted messenger suited for MultichainBalancesController. + * @returns The root messenger suited for MultichainBalancesController. */ -function getRootMessenger(): Messenger { - return new Messenger(); +function getRootMessenger(): RootMessenger { + return new Messenger({ namespace: MOCK_ANY_NAMESPACE }); } /** @@ -127,23 +135,33 @@ function getRootMessenger(): Messenger { * @returns The unrestricted messenger suited for MultichainBalancesController. */ function getRestrictedMessenger( - messenger: Messenger, + messenger: RootMessenger, ): MultichainBalancesControllerMessenger { - return messenger.getRestricted({ - name: 'MultichainBalancesController', - allowedActions: [ + const multichainBalancesControllerMessenger = new Messenger< + 'MultichainBalancesController', + RootAction, + RootEvent, + RootMessenger + >({ + namespace: 'MultichainBalancesController', + parent: messenger, + }); + messenger.delegate({ + messenger: multichainBalancesControllerMessenger, + actions: [ 'SnapController:handleRequest', 'AccountsController:listMultichainAccounts', 'MultichainAssetsController:getState', 'KeyringController:getState', ], - allowedEvents: [ + events: [ 'AccountsController:accountAdded', 'AccountsController:accountRemoved', 'AccountsController:accountBalancesUpdated', 'MultichainAssetsController:accountAssetListUpdated', ], }); + return multichainBalancesControllerMessenger; } const setupController = ({ @@ -651,7 +669,7 @@ describe('MultichainBalancesController', () => { deriveStateFromMetadata( controller.state, controller.metadata, - 'anonymous', + 'includeInDebugSnapshot', ), ).toMatchInlineSnapshot(`Object {}`); }); diff --git a/packages/assets-controllers/src/MultichainBalancesController/MultichainBalancesController.ts b/packages/assets-controllers/src/MultichainBalancesController/MultichainBalancesController.ts index 1545e547b79..d547f5bc237 100644 --- a/packages/assets-controllers/src/MultichainBalancesController/MultichainBalancesController.ts +++ b/packages/assets-controllers/src/MultichainBalancesController/MultichainBalancesController.ts @@ -6,10 +6,10 @@ import type { } from '@metamask/accounts-controller'; import { BaseController, + type StateMetadata, type ControllerGetStateAction, type ControllerStateChangeEvent, - type RestrictedMessenger, -} from '@metamask/base-controller'; +} from '@metamask/base-controller/next'; import { isEvmAccountType } from '@metamask/keyring-api'; import type { Balance, @@ -19,6 +19,7 @@ import type { import type { KeyringControllerGetStateAction } from '@metamask/keyring-controller'; import type { InternalAccount } from '@metamask/keyring-internal-api'; import { KeyringClient } from '@metamask/keyring-snap-client'; +import type { Messenger } from '@metamask/messenger'; import type { HandleSnapRequest } from '@metamask/snaps-controllers'; import type { SnapId } from '@metamask/snaps-sdk'; import { HandlerType } from '@metamask/snaps-utils'; @@ -108,12 +109,10 @@ type AllowedEvents = /** * Messenger type for the MultichainBalancesController. */ -export type MultichainBalancesControllerMessenger = RestrictedMessenger< +export type MultichainBalancesControllerMessenger = Messenger< typeof controllerName, MultichainBalancesControllerActions | AllowedActions, - MultichainBalancesControllerEvents | AllowedEvents, - AllowedActions['type'], - AllowedEvents['type'] + MultichainBalancesControllerEvents | AllowedEvents >; /** @@ -123,14 +122,15 @@ export type MultichainBalancesControllerMessenger = RestrictedMessenger< * using the `persist` flag; and if they can be sent to Sentry or not, using * the `anonymous` flag. */ -const balancesControllerMetadata = { - balances: { - includeInStateLogs: false, - persist: true, - anonymous: false, - usedInUi: true, - }, -}; +const balancesControllerMetadata: StateMetadata = + { + balances: { + includeInStateLogs: false, + persist: true, + includeInDebugSnapshot: false, + usedInUi: true, + }, + }; /** * The MultichainBalancesController is responsible for fetching and caching account @@ -165,17 +165,17 @@ export class MultichainBalancesController extends BaseController< void this.updateBalance(account.id); } - this.messagingSystem.subscribe( + this.messenger.subscribe( 'AccountsController:accountRemoved', (account: string) => this.#handleOnAccountRemoved(account), ); - this.messagingSystem.subscribe( + this.messenger.subscribe( 'AccountsController:accountBalancesUpdated', (balanceUpdate: AccountBalancesUpdatedEventPayload) => this.#handleOnAccountBalancesUpdated(balanceUpdate), ); - this.messagingSystem.subscribe( + this.messenger.subscribe( 'MultichainAssetsController:accountAssetListUpdated', async ({ assets }) => { const newAccountAssets = Object.entries(assets).map( @@ -200,9 +200,7 @@ export class MultichainBalancesController extends BaseController< assets: CaipAssetType[]; }[], ): Promise { - const { isUnlocked } = this.messagingSystem.call( - 'KeyringController:getState', - ); + const { isUnlocked } = this.messenger.call('KeyringController:getState'); if (!isUnlocked) { return; @@ -256,9 +254,7 @@ export class MultichainBalancesController extends BaseController< accountId: string, assets: CaipAssetType[], ): Promise { - const { isUnlocked } = this.messagingSystem.call( - 'KeyringController:getState', - ); + const { isUnlocked } = this.messenger.call('KeyringController:getState'); if (!isUnlocked) { return; @@ -305,9 +301,7 @@ export class MultichainBalancesController extends BaseController< * @returns A list of multichain accounts. */ #listMultichainAccounts(): InternalAccount[] { - return this.messagingSystem.call( - 'AccountsController:listMultichainAccounts', - ); + return this.messenger.call('AccountsController:listMultichainAccounts'); } /** @@ -328,7 +322,7 @@ export class MultichainBalancesController extends BaseController< */ #listAccountAssets(accountId: string): CaipAssetType[] { // TODO: Add an action `MultichainAssetsController:getAccountAssets` maybe? - const assetsState = this.messagingSystem.call( + const assetsState = this.messenger.call( 'MultichainAssetsController:getState', ); @@ -427,7 +421,7 @@ export class MultichainBalancesController extends BaseController< #getClient(snapId: string): KeyringClient { return new KeyringClient({ send: async (request: JsonRpcRequest) => - (await this.messagingSystem.call('SnapController:handleRequest', { + (await this.messenger.call('SnapController:handleRequest', { snapId: snapId as SnapId, origin: 'metamask', handler: HandlerType.OnKeyringRequest, diff --git a/packages/assets-controllers/src/NftDetectionController.test.ts b/packages/assets-controllers/src/NftDetectionController.test.ts index 98d4e9b58b7..5cb89d7549e 100644 --- a/packages/assets-controllers/src/NftDetectionController.test.ts +++ b/packages/assets-controllers/src/NftDetectionController.test.ts @@ -1,10 +1,16 @@ import type { AccountsController } from '@metamask/accounts-controller'; -import { Messenger } from '@metamask/base-controller'; import { NFT_API_BASE_URL, ChainId, InfuraNetworkType, } from '@metamask/controller-utils'; +import { + MOCK_ANY_NAMESPACE, + Messenger, + type MessengerActions, + type MessengerEvents, + type MockAnyNamespace, +} from '@metamask/messenger'; import { getDefaultNetworkControllerState, NetworkClientType, @@ -36,10 +42,15 @@ import { getDefaultNftControllerState } from './NftController'; import { NftDetectionController, BlockaidResultType, - type AllowedActions, - type AllowedEvents, + type NftDetectionControllerMessenger, } from './NftDetectionController'; +type AllActions = MessengerActions; + +type AllEvents = MessengerEvents; + +type RootMessenger = Messenger; + const controllerName = 'NftDetectionController' as const; const defaultSelectedAccount = createMockInternalAccount(); @@ -1069,7 +1080,9 @@ async function withController( testFunction, ] = args.length === 2 ? args : [{}, args[0]]; - const messenger = new Messenger(); + const messenger: RootMessenger = new Messenger({ + namespace: MOCK_ANY_NAMESPACE, + }); messenger.registerActionHandler( 'NetworkController:getState', @@ -1109,21 +1122,32 @@ async function withController( }), ); + const nftDetectionControllerMessenger = new Messenger< + typeof controllerName, + AllActions, + AllEvents, + RootMessenger + >({ + namespace: controllerName, + parent: messenger, + }); + messenger.delegate({ + messenger: nftDetectionControllerMessenger, + actions: [ + 'NetworkController:getState', + 'NetworkController:getNetworkClientById', + 'PreferencesController:getState', + 'AccountsController:getSelectedAccount', + 'NetworkController:findNetworkClientIdByChainId', + ], + events: [ + 'NetworkController:stateChange', + 'PreferencesController:stateChange', + ], + }); + const controller = new NftDetectionController({ - messenger: messenger.getRestricted({ - name: controllerName, - allowedActions: [ - 'NetworkController:getState', - 'NetworkController:getNetworkClientById', - 'PreferencesController:getState', - 'AccountsController:getSelectedAccount', - 'NetworkController:findNetworkClientIdByChainId', - ], - allowedEvents: [ - 'NetworkController:stateChange', - 'PreferencesController:stateChange', - ], - }), + messenger: nftDetectionControllerMessenger, disabled: true, addNft: jest.fn(), getNftState: getDefaultNftControllerState, diff --git a/packages/assets-controllers/src/NftDetectionController.ts b/packages/assets-controllers/src/NftDetectionController.ts index 219ca024f92..3f6845a7a30 100644 --- a/packages/assets-controllers/src/NftDetectionController.ts +++ b/packages/assets-controllers/src/NftDetectionController.ts @@ -1,7 +1,10 @@ import type { AccountsControllerGetSelectedAccountAction } from '@metamask/accounts-controller'; import type { AddApprovalRequest } from '@metamask/approval-controller'; -import type { RestrictedMessenger } from '@metamask/base-controller'; -import { BaseController } from '@metamask/base-controller'; +import { + BaseController, + type ControllerGetStateAction, + type ControllerStateChangeEvent, +} from '@metamask/base-controller/next'; import { toChecksumHexAddress, ChainId, @@ -11,6 +14,7 @@ import { handleFetch, toHex, } from '@metamask/controller-utils'; +import type { Messenger } from '@metamask/messenger'; import type { NetworkClient, NetworkControllerGetNetworkClientByIdAction, @@ -37,6 +41,7 @@ const controllerName = 'NftDetectionController'; export type NFTDetectionControllerState = Record; export type AllowedActions = + | ControllerGetStateAction | AddApprovalRequest | NetworkControllerGetStateAction | NetworkControllerGetNetworkClientByIdAction @@ -45,15 +50,17 @@ export type AllowedActions = | NetworkControllerFindNetworkClientIdByChainIdAction; export type AllowedEvents = + | ControllerStateChangeEvent< + typeof controllerName, + NFTDetectionControllerState + > | PreferencesControllerStateChangeEvent | NetworkControllerStateChangeEvent; -export type NftDetectionControllerMessenger = RestrictedMessenger< +export type NftDetectionControllerMessenger = Messenger< typeof controllerName, AllowedActions, - AllowedEvents, - AllowedActions['type'], - AllowedEvents['type'] + AllowedEvents >; /** @@ -498,7 +505,7 @@ export class NftDetectionController extends BaseController< this.#getNftState = getNftState; this.#addNft = addNft; - this.messagingSystem.subscribe( + this.messenger.subscribe( 'PreferencesController:stateChange', this.#onPreferencesControllerStateChange.bind(this), ); @@ -510,12 +517,12 @@ export class NftDetectionController extends BaseController< * @returns Whether current network is mainnet. */ isMainnet(): boolean { - const { selectedNetworkClientId } = this.messagingSystem.call( + const { selectedNetworkClientId } = this.messenger.call( 'NetworkController:getState', ); const { configuration: { chainId }, - } = this.messagingSystem.call( + } = this.messenger.call( 'NetworkController:getNetworkClientById', selectedNetworkClientId, ); @@ -586,8 +593,7 @@ export class NftDetectionController extends BaseController< async detectNfts(chainIds: Hex[], options?: { userAddress?: string }) { const userAddress = options?.userAddress ?? - this.messagingSystem.call('AccountsController:getSelectedAccount') - .address; + this.messenger.call('AccountsController:getSelectedAccount').address; // filter out unsupported chainIds const supportedChainIds = chainIds.filter((chainId) => @@ -693,7 +699,7 @@ export class NftDetectionController extends BaseController< collection && { collection }, chainId && { chainId }, ); - const networkClientId = this.messagingSystem.call( + const networkClientId = this.messenger.call( 'NetworkController:findNetworkClientIdByChainId', toHex(chainId), ); diff --git a/packages/assets-controllers/src/RatesController/RatesController.test.ts b/packages/assets-controllers/src/RatesController/RatesController.test.ts index e2b125ea4db..8ba6ccbe2b5 100644 --- a/packages/assets-controllers/src/RatesController/RatesController.test.ts +++ b/packages/assets-controllers/src/RatesController/RatesController.test.ts @@ -1,6 +1,14 @@ -import { Messenger, deriveStateFromMetadata } from '@metamask/base-controller'; +import { deriveStateFromMetadata } from '@metamask/base-controller/next'; +import { + MOCK_ANY_NAMESPACE, + Messenger, + type MessengerActions, + type MessengerEvents, + type MockAnyNamespace, +} from '@metamask/messenger'; import { useFakeTimers } from 'sinon'; +import type { RatesControllerMessenger, RatesControllerState } from './types'; import { advanceTime } from '../../../../tests/helpers'; import type { fetchMultiExchangeRate as defaultFetchExchangeRate } from '../crypto-compare-service'; import { @@ -8,12 +16,12 @@ import { RatesController, name as ratesControllerName, } from './RatesController'; -import type { - RatesControllerActions, - RatesControllerEvents, - RatesControllerMessenger, - RatesControllerState, -} from './types'; + +type AllActions = MessengerActions; + +type AllEvents = MessengerEvents; + +type RootMessenger = Messenger; const MOCK_TIMESTAMP = 1709983353; @@ -26,28 +34,26 @@ function getStubbedDate(): number { } /** - * Builds a new Messenger instance for RatesController. - * @returns A new Messenger instance. + * Builds a new root messenger instance. + * + * @returns A new root messenger instance. */ -function buildMessenger(): Messenger< - RatesControllerActions, - RatesControllerEvents -> { - return new Messenger(); +function buildRootMessenger(): RootMessenger { + return new Messenger({ namespace: MOCK_ANY_NAMESPACE }); } /** * Builds a restricted messenger for the RatesController. + * * @param messenger - The base messenger instance. * @returns A restricted messenger for the RatesController. */ function buildRatesControllerMessenger( - messenger: Messenger, + messenger: RootMessenger, ): RatesControllerMessenger { - return messenger.getRestricted({ - name: ratesControllerName, - allowedEvents: [], - allowedActions: [], + return new Messenger({ + namespace: ratesControllerName, + parent: messenger, }); } @@ -70,7 +76,7 @@ function setupRatesController({ }: { interval?: number; initialState?: Partial; - messenger: Messenger; + messenger: RootMessenger; includeUsdRate: boolean; fetchMultiExchangeRate?: typeof defaultFetchExchangeRate; }) { @@ -91,7 +97,7 @@ describe('RatesController', () => { it('constructs the RatesController with default values', () => { const ratesController = setupRatesController({ initialState: {}, - messenger: buildMessenger(), + messenger: buildRootMessenger(), includeUsdRate: false, }); const { fiatCurrency, rates, cryptocurrencies } = ratesController.state; @@ -118,7 +124,7 @@ describe('RatesController', () => { }); it('starts the polling process with default values', async () => { - const messenger = buildMessenger(); + const messenger = buildRootMessenger(); const publishActionSpy = jest.spyOn(messenger, 'publish'); jest.spyOn(global.Date, 'now').mockImplementation(() => getStubbedDate()); @@ -222,7 +228,7 @@ describe('RatesController', () => { cryptocurrencies: [Cryptocurrency.Btc], fiatCurrency: 'eur', }, - messenger: buildMessenger(), + messenger: buildRootMessenger(), includeUsdRate: true, fetchMultiExchangeRate: fetchExchangeRateStub, }); @@ -263,7 +269,7 @@ describe('RatesController', () => { }); it('stops the polling process', async () => { - const messenger = buildMessenger(); + const messenger = buildRootMessenger(); const publishActionSpy = jest.spyOn(messenger, 'publish'); const fetchExchangeRateStub = jest.fn().mockResolvedValue({}); const ratesController = setupRatesController({ @@ -318,7 +324,7 @@ describe('RatesController', () => { initialState: { cryptocurrencies: mockCryptocurrencyList, }, - messenger: buildMessenger(), + messenger: buildRootMessenger(), fetchMultiExchangeRate: fetchExchangeRateStub, includeUsdRate: false, }); @@ -335,7 +341,7 @@ describe('RatesController', () => { const ratesController = setupRatesController({ interval: 150, initialState: {}, - messenger: buildMessenger(), + messenger: buildRootMessenger(), fetchMultiExchangeRate: fetchExchangeRateStub, includeUsdRate: false, }); @@ -366,7 +372,7 @@ describe('RatesController', () => { const ratesController = setupRatesController({ interval: 150, initialState: {}, - messenger: buildMessenger(), + messenger: buildRootMessenger(), fetchMultiExchangeRate: fetchExchangeRateStub, includeUsdRate: false, }); @@ -385,7 +391,7 @@ describe('RatesController', () => { const ratesController = setupRatesController({ interval: 150, initialState: {}, - messenger: buildMessenger(), + messenger: buildRootMessenger(), fetchMultiExchangeRate: fetchExchangeRateStub, includeUsdRate: false, }); @@ -400,7 +406,7 @@ describe('RatesController', () => { it('includes expected state in debug snapshots', () => { const fetchExchangeRateStub = jest.fn().mockResolvedValue({}); const controller = setupRatesController({ - messenger: buildMessenger(), + messenger: buildRootMessenger(), fetchMultiExchangeRate: fetchExchangeRateStub, includeUsdRate: false, }); @@ -409,7 +415,7 @@ describe('RatesController', () => { deriveStateFromMetadata( controller.state, controller.metadata, - 'anonymous', + 'includeInDebugSnapshot', ), ).toMatchInlineSnapshot(` Object { @@ -435,7 +441,7 @@ describe('RatesController', () => { it('includes expected state in state logs', () => { const fetchExchangeRateStub = jest.fn().mockResolvedValue({}); const controller = setupRatesController({ - messenger: buildMessenger(), + messenger: buildRootMessenger(), fetchMultiExchangeRate: fetchExchangeRateStub, includeUsdRate: false, }); @@ -460,7 +466,7 @@ describe('RatesController', () => { it('persists expected state', () => { const fetchExchangeRateStub = jest.fn().mockResolvedValue({}); const controller = setupRatesController({ - messenger: buildMessenger(), + messenger: buildRootMessenger(), fetchMultiExchangeRate: fetchExchangeRateStub, includeUsdRate: false, }); @@ -495,7 +501,7 @@ describe('RatesController', () => { it('exposes expected state to UI', () => { const fetchExchangeRateStub = jest.fn().mockResolvedValue({}); const controller = setupRatesController({ - messenger: buildMessenger(), + messenger: buildRootMessenger(), fetchMultiExchangeRate: fetchExchangeRateStub, includeUsdRate: false, }); diff --git a/packages/assets-controllers/src/RatesController/RatesController.ts b/packages/assets-controllers/src/RatesController/RatesController.ts index 5c916a7c92a..f2d4430a89f 100644 --- a/packages/assets-controllers/src/RatesController/RatesController.ts +++ b/packages/assets-controllers/src/RatesController/RatesController.ts @@ -1,4 +1,7 @@ -import { BaseController } from '@metamask/base-controller'; +import { + BaseController, + type StateMetadata, +} from '@metamask/base-controller/next'; import { Mutex } from 'async-mutex'; import type { Draft } from 'immer'; @@ -25,23 +28,23 @@ export enum Cryptocurrency { const DEFAULT_INTERVAL = 180000; -const metadata = { +const metadata: StateMetadata = { fiatCurrency: { includeInStateLogs: true, persist: true, - anonymous: true, + includeInDebugSnapshot: true, usedInUi: true, }, rates: { includeInStateLogs: false, persist: true, - anonymous: true, + includeInDebugSnapshot: true, usedInUi: true, }, cryptocurrencies: { includeInStateLogs: true, persist: true, - anonymous: true, + includeInDebugSnapshot: true, usedInUi: false, }, }; @@ -180,7 +183,7 @@ export class RatesController extends BaseController< return; } - this.messagingSystem.publish(`${name}:pollingStarted`); + this.messenger.publish(`${name}:pollingStarted`); await this.#updateRates(); @@ -199,7 +202,7 @@ export class RatesController extends BaseController< clearInterval(this.#intervalId); this.#intervalId = undefined; - this.messagingSystem.publish(`${name}:pollingStopped`); + this.messenger.publish(`${name}:pollingStopped`); } /** diff --git a/packages/assets-controllers/src/RatesController/types.ts b/packages/assets-controllers/src/RatesController/types.ts index c26ae070075..49c5515391b 100644 --- a/packages/assets-controllers/src/RatesController/types.ts +++ b/packages/assets-controllers/src/RatesController/types.ts @@ -1,8 +1,8 @@ import type { - RestrictedMessenger, ControllerGetStateAction, ControllerStateChangeEvent, } from '@metamask/base-controller'; +import type { Messenger } from '@metamask/messenger'; import type { fetchMultiExchangeRate as defaultFetchExchangeRate } from '../crypto-compare-service'; import type { @@ -97,12 +97,10 @@ export type RatesControllerActions = RatesControllerGetStateAction; /** * Defines the actions that the RatesController can perform. */ -export type RatesControllerMessenger = RestrictedMessenger< +export type RatesControllerMessenger = Messenger< typeof ratesControllerName, RatesControllerActions, - RatesControllerEvents, - never, - never + RatesControllerEvents >; /** diff --git a/packages/assets-controllers/src/TokenSearchDiscoveryDataController/TokenSearchDiscoveryDataController.test.ts b/packages/assets-controllers/src/TokenSearchDiscoveryDataController/TokenSearchDiscoveryDataController.test.ts index 2148acd60c2..86d1b7e01e2 100644 --- a/packages/assets-controllers/src/TokenSearchDiscoveryDataController/TokenSearchDiscoveryDataController.test.ts +++ b/packages/assets-controllers/src/TokenSearchDiscoveryDataController/TokenSearchDiscoveryDataController.test.ts @@ -1,5 +1,12 @@ -import { Messenger, deriveStateFromMetadata } from '@metamask/base-controller'; +import { deriveStateFromMetadata } from '@metamask/base-controller/next'; import { ChainId } from '@metamask/controller-utils'; +import { + MOCK_ANY_NAMESPACE, + Messenger, + type MessengerActions, + type MessengerEvents, + type MockAnyNamespace, +} from '@metamask/messenger'; import type { Hex } from '@metamask/utils'; import assert from 'assert'; import { useFakeTimers } from 'sinon'; @@ -9,8 +16,6 @@ import { TokenSearchDiscoveryDataController, controllerName, MAX_TOKEN_DISPLAY_DATA_LENGTH, - type AllowedActions, - type AllowedEvents, type TokenSearchDiscoveryDataControllerMessenger, type TokenSearchDiscoveryDataControllerState, } from './TokenSearchDiscoveryDataController'; @@ -32,7 +37,11 @@ jest.mock('../token-service', () => { }; }); -type MainMessenger = Messenger; +type AllActions = MessengerActions; + +type AllEvents = MessengerEvents; + +type RootMessenger = Messenger; /** * Builds a not found token display data object. @@ -111,13 +120,21 @@ function buildFoundTokenDisplayData( * @returns The restricted messenger. */ function buildTokenSearchDiscoveryDataControllerMessenger( - messenger: MainMessenger = new Messenger(), + messenger: RootMessenger = new Messenger({ namespace: MOCK_ANY_NAMESPACE }), ): TokenSearchDiscoveryDataControllerMessenger { - return messenger.getRestricted({ - name: controllerName, - allowedActions: ['CurrencyRateController:getState'], - allowedEvents: [], + const tokenSearchDiscoveryDataControllerMessenger = new Messenger< + typeof controllerName, + AllActions, + AllEvents, + RootMessenger + >({ + namespace: controllerName, }); + messenger.delegate({ + messenger: tokenSearchDiscoveryDataControllerMessenger, + actions: ['CurrencyRateController:getState'], + }); + return tokenSearchDiscoveryDataControllerMessenger; } /** @@ -206,7 +223,9 @@ async function withController( callback = maybeCallback; } - const messenger = new Messenger(); + const messenger: RootMessenger = new Messenger({ + namespace: MOCK_ANY_NAMESPACE, + }); messenger.registerActionHandler('CurrencyRateController:getState', () => ({ currentCurrency: 'USD', @@ -899,7 +918,7 @@ describe('TokenSearchDiscoveryDataController', () => { deriveStateFromMetadata( controller.state, controller.metadata, - 'anonymous', + 'includeInDebugSnapshot', ), ).toMatchInlineSnapshot(`Object {}`); }); diff --git a/packages/assets-controllers/src/TokenSearchDiscoveryDataController/TokenSearchDiscoveryDataController.ts b/packages/assets-controllers/src/TokenSearchDiscoveryDataController/TokenSearchDiscoveryDataController.ts index dc508d7e3f7..7af8e66d20b 100644 --- a/packages/assets-controllers/src/TokenSearchDiscoveryDataController/TokenSearchDiscoveryDataController.ts +++ b/packages/assets-controllers/src/TokenSearchDiscoveryDataController/TokenSearchDiscoveryDataController.ts @@ -1,9 +1,10 @@ import { BaseController, + type StateMetadata, type ControllerGetStateAction, type ControllerStateChangeEvent, - type RestrictedMessenger, -} from '@metamask/base-controller'; +} from '@metamask/base-controller/next'; +import type { Messenger } from '@metamask/messenger'; import type { Hex } from '@metamask/utils'; import type { TokenDisplayData } from './types'; @@ -33,20 +34,21 @@ export type TokenSearchDiscoveryDataControllerState = { >; }; -const tokenSearchDiscoveryDataControllerMetadata = { - tokenDisplayData: { - includeInStateLogs: false, - persist: true, - anonymous: false, - usedInUi: true, - }, - swapsTokenAddressesByChainId: { - includeInStateLogs: false, - persist: true, - anonymous: false, - usedInUi: true, - }, -} as const; +const tokenSearchDiscoveryDataControllerMetadata: StateMetadata = + { + tokenDisplayData: { + includeInStateLogs: false, + persist: true, + includeInDebugSnapshot: false, + usedInUi: true, + }, + swapsTokenAddressesByChainId: { + includeInStateLogs: false, + persist: true, + includeInDebugSnapshot: false, + usedInUi: true, + }, + } as const; // === MESSENGER === @@ -98,12 +100,10 @@ export type AllowedEvents = never; * The messenger which is restricted to actions and events accessed by * {@link TokenSearchDiscoveryDataController}. */ -export type TokenSearchDiscoveryDataControllerMessenger = RestrictedMessenger< +export type TokenSearchDiscoveryDataControllerMessenger = Messenger< typeof controllerName, TokenSearchDiscoveryDataControllerActions | AllowedActions, - TokenSearchDiscoveryDataControllerEvents | AllowedEvents, - AllowedActions['type'], - AllowedEvents['type'] + TokenSearchDiscoveryDataControllerEvents | AllowedEvents >; /** @@ -176,7 +176,7 @@ export class TokenSearchDiscoveryDataController extends BaseController< chainId: Hex, address: string, ): Promise | null> { - const { currentCurrency } = this.messagingSystem.call( + const { currentCurrency } = this.messenger.call( 'CurrencyRateController:getState', ); @@ -251,7 +251,7 @@ export class TokenSearchDiscoveryDataController extends BaseController< } } - const { currentCurrency } = this.messagingSystem.call( + const { currentCurrency } = this.messenger.call( 'CurrencyRateController:getState', );