diff --git a/README.md b/README.md index 0b377cff988..dba9c2e9c6c 100644 --- a/README.md +++ b/README.md @@ -216,6 +216,7 @@ linkStyle default opacity:0.5 earn_controller --> transaction_controller; eip_5792_middleware --> transaction_controller; eip_5792_middleware --> keyring_controller; + eip_7702_internal_rpc_middleware --> controller_utils; eip1193_permission_middleware --> chain_agnostic_permission; eip1193_permission_middleware --> controller_utils; eip1193_permission_middleware --> json_rpc_engine; @@ -301,6 +302,7 @@ linkStyle default opacity:0.5 remote_feature_flag_controller --> base_controller; remote_feature_flag_controller --> controller_utils; sample_controllers --> base_controller; + sample_controllers --> messenger; sample_controllers --> controller_utils; sample_controllers --> network_controller; seedless_onboarding_controller --> base_controller; diff --git a/docs/controller-guidelines.md b/docs/controller-guidelines.md index fdf1a32cac6..f4db78d4580 100644 --- a/docs/controller-guidelines.md +++ b/docs/controller-guidelines.md @@ -14,7 +14,7 @@ Controllers are foundational pieces within MetaMask's architecture: All controllers should inherit from `BaseController` from the `@metamask/base-controller` package. This provides a few benefits: - It defines a standard interface for all controllers. -- It introduces the messenger system, which is useful for interacting with other controllers without requiring direct access to them. +- It introduces the messenger, which is useful for interacting with other parts of the application without requiring a direct reference. - It enforces that `update` is the only way to modify the state of the controller and provides a way to listen for state updates via the messenger. - It simplifies initialization by consolidating constructor arguments into one options object. @@ -22,7 +22,7 @@ All controllers should inherit from `BaseController` from the `@metamask/base-co One of the uniquely identifying features of a controller is the ability to manage state. -If you have a class that does not capture any data in state, then your class does not need to inherit from `BaseController` (even if it uses the messaging system). +If you have a class that does not capture any data in state, then your class does not need to inherit from `BaseController` (even if it uses a messenger). ## Maintain a clear and concise API @@ -108,22 +108,24 @@ export { FooController, getDefaultFooControllerState } from './FooController'; Each property in state has two pieces of metadata that must be specified. This instructs the client how to treat that property: +- `includeInDebugSnapshot` - Informs the client whether to include the property in debug state logs attached to Sentry events (`true`) or not (`false`). We must exclude any data that could potentially be personally identifying here, and we often also exclude data that is large and/or unhelpful for debugging. +- `includeInStateLogs` - Informs the client whether to include the property in state logs downloaded by users (`true`) or not (`false`). We must exclude any sensitive data that we don't want our support team to have access to (such as private keys). We include personally-identifiable data related to on-chain state here (we never collect this data, and we have a disclaimer about this in the UI when users download state logs), but other types of personally identifiable information must still be excluded. - `persist` — Informs the client whether the property should be placed in persistent storage (`true`) or not (`false`). Opting out is useful if you want to have a property in state for convenience reasons but you know that property is ephemeral and can be easily reconstructed. -- `anonymous` — Informs the client whether the property is free of personally identifiable information (`true`) or not (`false`) and can therefore safely be included and sent to error reporting services such as Sentry. When in doubt, use `false`. +- `usedInUi` - Informs the client whether the property is used in the UI (`true`) or not (`false`). This is used to filter the state we send to the UI to improve performance. A variable named `${controllerName}Metadata` should be defined (there is no need to export it) and passed as the `metadata` argument in the constructor to `BaseController`. ```typescript const keyringControllerMetadata = { vault: { + // This property can be used to identify a user, so we want to make sure we + // do not include it in Sentry. + includeInDebugSnapshot: false, // We don't want to include this in state logs because it contains sensitive key material. includeInStateLogs: false, // We want to persist this property so it's restored automatically, as we // cannot reconstruct it otherwise. persist: true, - // This property can be used to identify a user, so we want to make sure we - // do not include it in Sentry. - anonymous: false, // This property is only used in the controller, not in the UI. usedInUi: false, }, @@ -193,7 +195,7 @@ class FooController extends BaseController { } ``` -## Use the messaging system instead of callbacks +## Use the messenger instead of callbacks Prior to BaseController v2, it was common for a controller to respond to an event occurring within another controller (such a state change) by receiving an event listener callback which the client would bind ahead of time: @@ -222,7 +224,7 @@ const fooController = new FooController({ }); ``` -If the recipient controller supports the messaging system, however, the callback pattern is unnecessary. Using the messenger not only aligns the controller with `BaseController`, but also reduces the number of options that consumers need to remember in order to use the controller: +If the recipient controller uses a messenger, however, the callback pattern is unnecessary. Using the messenger not only aligns the controller with `BaseController`, but also reduces the number of options that consumers need to remember in order to use the controller: ✅ **The constructor subscribes to the `BarController:stateChange` event** @@ -231,12 +233,10 @@ If the recipient controller supports the messaging system, however, the callback const name = 'FooController'; -type FooControllerMessenger = RestrictedMessenger< +type FooControllerMessenger = Messenger< typeof name, - never, - never, - never, - never + FooControllerActions, + FooControllerEvents >; class FooController extends BaseController< @@ -255,22 +255,40 @@ class FooController extends BaseController< // === Client repo === -const rootMessenger = new Messenger<'BarController:stateChange', never>(); -const barControllerMessenger = rootMessenger.getRestricted({ - name: 'BarController', +const rootMessenger = new Messenger<'Root', RootActions, RootEvents>({ + namespace: 'Root', +}); +const barControllerMessenger = new Messenger< + 'BarController', + BarControllerActions, + BarControllerEvents, + typeof rootMessenger +>({ + namespace: 'BarController', + parent: rootMessenger, }); const barController = new BarController({ messenger: barControllerMessenger, }); -const fooControllerMessenger = rootMessenger.getRestricted({ - name: 'FooController', +const fooControllerMessenger = new Messenger< + 'FooController', + FooControllerActions, + FooControllerEvents | BarControllerStateChange, + typeof rootMessenger +>({ + namespace: 'FooController', + parent: rootMessenger, +}); +rootMessenger.delegate({ + events: ['BarController:stateChange'], + messenger: fooControllerMessenger, }); const fooController = new FooController({ messenger: fooControllerMessenger, }); ``` -## Use the messaging system instead of event emitters +## Use the messenger instead of event emitters Some controllers expose an EventEmitter object so that other parts of the system can listen to them: @@ -312,12 +330,10 @@ However, this pattern can be replaced with the use of the messenger: const name = 'FooController'; -type FooControllerMessenger = RestrictedMessenger< +type FooControllerMessenger = Messenger< typeof name, - never, - never, - never, - never + FooControllerActions, + FooControllerEvents >; class FooController extends BaseController< @@ -330,15 +346,23 @@ class FooController extends BaseController< } doSomething() { - this.messagingSystem.publish('FooController:someEvent'); + this.messenger.publish('FooController:someEvent'); } } // === Client repo === -const rootMessenger = new Messenger<'FooController:someEvent', never>(); -const fooControllerMessenger = rootMessenger.getRestricted({ - name: 'FooController', +const rootMessenger = new Messenger<'Root', RootActions, RootEvents>({ + namespace: 'Root', +}); +const fooControllerMessenger = new Messenger< + 'FooController', + FooControllerActions, + FooControllerEvents, + typeof rootMessenger +>({ + namespace: 'FooController', + parent: rootMessenger, }); const fooController = new FooController({ messenger: fooControllerMessenger, @@ -507,37 +531,19 @@ A controller should define and export a type union that holds all of its actions The name of this type should be `${ControllerName}Actions`. -This type should be only passed to `RestrictedMessenger` as the 2nd type parameter. It should _not_ be included in its 4th type parameter, as that is is used for external actions. - -🚫 **`FooController['type']` is passed as the 4th type parameter** - -```typescript -export type FooControllerActions = - | FooControllerUpdateCurrencyAction - | FooControllerUpdateRatesAction; - -export type FooControllerMessenger = RestrictedMessenger< - 'FooController', - FooControllerActions, - never, - FooControllerActions['type'], - never ->; -``` +This type should be passed to `Messenger` as the 2nd type parameter. It should _not_ include external actions. -✅ **`never` is passed as the 4th type parameter (assuming no external actions)** +✅ **`FooControllerActions` is passed as the 2nd type parameter (assuming no external actions)** ```typescript export type FooControllerActions = | FooControllerUpdateCurrencyAction | FooControllerUpdateRatesAction; -export type FooControllerMessenger = RestrictedMessenger< +export type FooControllerMessenger = Messenger< 'FooController', FooControllerActions, - never, - never, - never + FooControllerEvents >; ``` @@ -547,189 +553,178 @@ A controller should define and export a type union that holds all of its events. The name of this type should be `${ControllerName}Events`. -This type should be only passed to `RestrictedMessenger` as the 3rd type parameter. It should _not_ be included in its 5th type parameter, as that is is used for external events. +This type should be passed to `Messenger` as the 3rd type parameter. It should _not_ include external events. -🚫 **`FooControllerEvents['type']` is passed as the 5th type parameter** +✅ **`FooControllerEvents` is passed as the 3rd type parameter (assuming no external events)** ```typescript export type FooControllerEvents = | FooControllerMessageReceivedEvent | FooControllerNotificationAddedEvent; -export type FooControllerMessenger = RestrictedMessenger< +export type FooControllerMessenger = Messenger< 'FooController', - never, - FooControllerEvents, - never, - FooControllerEvents['type'] ->; -``` - -✅ **`never` is passed as the 5th type parameter (assuming no external events)** - -```typescript -export type FooControllerEvents = - | FooControllerMessageReceivedEvent - | FooControllerNotificationAddedEvent; - -export type FooControllerMessenger = RestrictedMessenger< - 'FooController', - never, - FooControllerEvents, - never, - never + FooControllerActions, + FooControllerEvents >; ``` ## Define, but do not export, a type union for external action types -A controller may wish to call actions defined by other controllers, and therefore will need to define them in the messenger's allowlist. +A controller may wish to call actions defined by other controllers, and therefore will need to include them in the controller messenger's type definition. -In this case, the controller should group these types into a type union so that they can be easily passed to the `RestrictedMessenger` type. However, it should not export this type, as it would then be re-exporting types that another package has already exported. +In this case, the controller should group these types into a type union so that they can be easily passed to the `Messenger` type. However, it should not export this type, as it would then be re-exporting types that another package has already exported. The name of this type should be `AllowedActions`. -This type should not only be passed to `RestrictedMessenger` as the 2nd type parameter, but should also be included in its 4th type parameter. +This type should be passed to `Messenger` as part of the 2nd type parameter, in a type union with internal actions. -🚫 **`never` is passed as the 4th type parameter** +🚫 **`AllowedActions` is included in the actions type union and _is_ exported** ```typescript +/* === packages/foo-controller/src/FooController.ts === */ + +export type FooControllerActions = + | FooControllerUpdateCurrencyAction + | FooControllerUpdateRatesAction; + export type AllowedActions = | BarControllerDoSomethingAction | BarControllerDoSomethingElseAction; -export type FooControllerMessenger = RestrictedMessenger< +export type FooControllerMessenger = Messenger< 'FooController', - AllowedActions, - never, - never, - never + FooControllerActions | AllowedActions, + FooControllerEvents >; + +/* === packages/foo-controller/src/index.ts === */ + +export type { AllowedActions } from '@metamask/foo-controller'; ``` -🚫 **`AllowedActions['type']` is passed as the 4th type parameter, but `AllowedActions` is exported** +🚫 **External actions are included in controller action type** ```typescript -/* === packages/foo-controller/src/FooController.ts === */ - -export type AllowedActions = +export type FooControllerActions = + | FooControllerUpdateCurrencyAction + | FooControllerUpdateRatesAction | BarControllerDoSomethingAction | BarControllerDoSomethingElseAction; -export type FooControllerMessenger = RestrictedMessenger< +export type FooControllerMessenger = Messenger< 'FooController', - AllowedActions, - never, - AllowedActions['type'], - never + FooControllerActions, + FooControllerEvents >; - -/* === packages/foo-controller/src/index.ts === */ - -export type { AllowedActions } from '@metamask/foo-controller'; ``` -✅ **`AllowedActions['type']` is passed as the 4th type parameter, and `AllowedActions` is _not_ exported** +✅ **`AllowedActions` is included in the actions type union but is _not_ exported** ```typescript +export type FooControllerActions = + | FooControllerUpdateCurrencyAction + | FooControllerUpdateRatesAction; + type AllowedActions = | BarControllerDoSomethingAction | BarControllerDoSomethingElseAction; -export type FooControllerMessenger = RestrictedMessenger< +export type FooControllerMessenger = Messenger< 'FooController', - AllowedActions, - never, - AllowedActions['type'], - never + FooControllerActions | AllowedActions, + FooControllerEvents >; ``` -If, in a test, you need to access all of the actions included in a controller's messenger allowlist, use the [`ExtractAvailableAction` utility type](../packages/base-controller/tests/helpers.ts): +If, in a test, you need to access all of the actions supported by a messenger, use the [`MessengerActions` utility type](../packages/messenger/src/Messenger.ts): ```typescript -// NOTE: You may need to adjust the path depending on where you are -import { ExtractAvailableAction } from '../../base-controller/tests/helpers'; +import type { MessengerActions, MessengerEvents } from '@metamask/messenger'; const messenger = new Messenger< - ExtractAvailableAction, - never + controllerName, + MessengerActions, + MessengerEvents >(); ``` ## Define, but do not export, a type union for external event types -A controller may wish to subscribe to events defined by other controllers, and therefore will need to define them in the messenger's allowlist. +A controller may wish to subscribe to events defined by other controllers, and therefore will need to include them in the controller messenger's type definition. -In this case, the controller should group these types into a type union so that they can be easily passed to the `RestrictedMessenger` type. However, it should not export this type, as it would then be re-exporting types that another package has already exported. +In this case, the controller should group these types into a type union so that they can be easily passed to the `Messenger` type. However, it should not export this type, as it would then be re-exporting types that another package has already exported. The name of this type should be `AllowedEvents`. -This type should not only be passed to `RestrictedMessenger` as the 3rd type parameter, but should also be included in its 5th type parameter. +This type should be passed to `Messenger` as part of the 3rd type parameter, in a type union with internal events. -🚫 **`never` is passed as the 5th type parameter** +🚫 **`AllowedEvents` is included in the actions type union and _is_ exported** ```typescript +/* === packages/foo-controller/src/FooController.ts === */ +export type FooControllerEvents = + | FooControllerMessageReceivedEvent + | FooControllerNotificationAddedEvent; + export type AllowedEvents = | BarControllerSomethingHappenedEvent | BarControllerSomethingElseHappenedEvent; -export type FooControllerMessenger = RestrictedMessenger< +export type FooControllerMessenger = Messenger< 'FooController', - never, - AllowedEvents, - never, - never + FooControllerActions, + FooControllerEvents | AllowedEvents >; + +/* === packages/foo-controller/src/index.ts === */ + +export type { AllowedEvents } from '@metamask/foo-controller'; ``` -🚫 **`AllowedEvents['type']` is passed as the 5th type parameter, but `AllowedEvents` is exported** +🚫 **External events are included in controller event type** ```typescript -/* === packages/foo-controller/src/FooController.ts === */ - -export type AllowedEvents = +export type FooControllerEvents = + | FooControllerMessageReceivedEvent + | FooControllerNotificationAddedEvent | BarControllerSomethingHappenedEvent | BarControllerSomethingElseHappenedEvent; -export type FooControllerMessenger = RestrictedMessenger< +export type FooControllerMessenger = Messenger< 'FooController', - never, - AllowedEvents, - never, - AllowedEvents['type'] + FooControllerActions, + FooControllerEvents >; - -/* === packages/foo-controller/src/index.ts === */ - -export type { AllowedEvents } from '@metamask/foo-controller'; ``` -✅ **`AllowedEvents['type']` is passed as the 5th type parameter, and `AllowedEvents` is _not_ exported** +✅ **`AllowedEvents` is included in the events type union but is _not_ exported** ```typescript +export type FooControllerEvents = + | FooControllerMessageReceivedEvent + | FooControllerNotificationAddedEvent; + type AllowedEvents = | BarControllerSomethingHappenedEvent | BarControllerSomethingElseHappenedEvent; -export type FooControllerMessenger = RestrictedMessenger< +export type FooControllerMessenger = Messenger< 'FooController', - never, - AllowedEvents, - never, - AllowedEvents['type'] + FooControllerActions, + FooControllerEvents | AllowedEvents >; ``` -If, in a test, you need to access all of the events included in a controller's messenger allowlist, use the [`ExtractAvailableEvent` utility type](../packages/base-controller/tests/helpers.ts): +If, in a test, you need to access all of the events supported by a messenger, use the [`MessengerEvents` utility type](../packages/messenger/src/Messenger.ts): ```typescript -// NOTE: You may need to adjust the path depending on where you are -import { ExtractAvailableEvent } from '../../base-controller/tests/helpers'; +import type { MessengerActions, MessengerEvents } from '@metamask/messenger'; const messenger = new Messenger< - never, - ExtractAvailableEvent + controllerName, + MessengerActions, + MessengerEvents >(); ``` @@ -792,25 +787,17 @@ export type AllowedEvents = | ApprovalControllerApprovalRequestApprovedEvent | ApprovalControllerApprovalRequestRejectedEvent; -export type SwapsControllerMessenger = RestrictedMessenger< +export type SwapsControllerMessenger = Messenger< 'SwapsController', SwapsControllerActions | AllowedActions, - SwapsControllerEvents | AllowedEvents, - AllowedActions['type'], - AllowedEvents['type'] + SwapsControllerEvents | AllowedEvents >; ``` A messenger that allows no actions or events (whether internal or external) looks like this: ```typescript -export type SwapsControllerMessenger = RestrictedMessenger< - 'SwapsController', - never, - never, - never, - never ->; +export type FooServiceMessenger = Messenger<'FooService', never, never>; ``` ## Define and export a type for the controller's state @@ -1175,14 +1162,14 @@ class AccountsController extends BaseController< import { AccountsControllerGetStateAction } from '@metamask/accounts-controller'; +// Other type definitions + type AllowedActions = AccountsControllerGetStateAction; -type PreferencesControllerMessenger = RestrictedMessenger< +type PreferencesControllerMessenger = Messenger< 'PreferencesController', - AllowedActions, - never, - AllowedActions['type'], - never + PreferencesControllerActions | AllowedActions, + PreferencesControllerEvents >; class PreferencesController extends BaseController< @@ -1216,7 +1203,7 @@ class PreferencesController extends BaseController< ## Expose derived state using selectors instead of getters -Sometimes, for convenience, consumers want access to a higher-level representation of a controller's state. It is tempting to add a method to the controller which provides this representation, but this means that a consumer would need an entire instance of the controller on hand to use this method. Using the messaging system mitigates this problem, but then the consumer would need access to a messenger as well, which may be impossible in places like Redux selector functions. +Sometimes, for convenience, consumers want access to a higher-level representation of a controller's state. It is tempting to add a method to the controller which provides this representation, but this means that a consumer would need an entire instance of the controller on hand to use this method. Using the messenger mitigates this problem, but then the consumer would need access to a messenger as well, which may be impossible in places like Redux selector functions. To make it easier to share such representations across disparate parts of the codebase in a flexible fashion, you can define and export selector functions from your controller file instead. They should be placed under a `${controllerName}Selectors` object and then exported. @@ -1256,7 +1243,7 @@ class TokensController extends BaseController { } ``` -🚫 **Methods exposed via the messaging system** +🚫 **Methods exposed via the messenger** ```typescript /* === This repo: packages/accounts-controller/src/AccountsController.ts === */ @@ -1271,16 +1258,15 @@ export type AccountsControllerGetInactiveAccountsAction = { handler: AccountsController['getInactiveAccounts']; }; -type AccountsControllerActions = +export type AccountsControllerActions = + /// Other actions | AccountsControllerGetActiveAccountAction | AccountsControllerGetInactiveAccountsAction; -export type AccountsControllerMessenger = RestrictedMessenger< +export type AccountsControllerMessenger = Messenger< 'AccountsController', AccountsControllerActions, - never, - never, - never + AccountsControllerEvents >; class AccountsController extends BaseController { @@ -1304,12 +1290,10 @@ type AllowedActions = | AccountsControllerGetActiveAccountsAction | AccountsControllerGetInactiveAccountsAction; -export type TokensControllerMessenger = RestrictedMessenger< +export type TokensControllerMessenger = Messenger< 'TokensController', - AllowedActions, - never, - AllowedActions['type'], - never + TokensControllerActions | AllowedActions, + TokensControllerEvents >; class TokensController extends BaseController { @@ -1327,7 +1311,7 @@ class TokensController extends BaseController { // Now TokensController no longer needs an instance of AccountsController to // access the list of active accounts, which is good... const tokens = getTokens( - this.messagingSystem.call('AccountsController:getActiveAccounts'), + this.messenger.call('AccountsController:getActiveAccounts'), ); // ... do something with tokens ... } @@ -1385,12 +1369,10 @@ export type AccountsControllerGetStateAction = ControllerGetStateAction< type AccountsControllerActions = AccountsControllerGetStateAccountAction; -export type AccountsControllerMessenger = RestrictedMessenger< +export type AccountsControllerMessenger = Messenger< 'AccountsController', AccountsControllerActions, - never, - never, - never + AccountsControllerEvents, >; /* === This repo: packages/tokens-controller/src/TokensController.ts === */ @@ -1402,12 +1384,10 @@ import { accountsControllerSelectors } from '@metamask/accounts-controller'; type AllowedActions = AccountsControllerGetStateAction; -export type TokensControllerMessenger = RestrictedMessenger< +export type TokensControllerMessenger = Messenger< 'TokensController', - AllowedActions, - never, - AllowedActions['type'], - never + TokensControllerActions | AllowedActions, + TokensControllerEvents >; class TokensController extends BaseController { @@ -1423,7 +1403,7 @@ class TokensController extends BaseController { fetchTokens() { // Now TokensController can use the selector in combination with the state - const tokensControllerState = this.messagingSystem.call( + const tokensControllerState = this.messenger.call( 'AccountsController:getState', ); const accounts = accountsControllerSelectors.selectActiveAccounts( diff --git a/docs/data-services.md b/docs/data-services.md index 57d79671c0b..cfd3967d3dc 100644 --- a/docs/data-services.md +++ b/docs/data-services.md @@ -2,14 +2,14 @@ ## What is a data service? -A **data service** is a pattern for making interactions with an external API (fetching token prices, storing accounts, etc.). It is implemented as a plain TypeScript class with methods that are exposed through the messaging system. +A **data service** is a pattern for making interactions with an external API (fetching token prices, storing accounts, etc.). It is implemented as a plain TypeScript class with methods that are exposed through a messenger. ## Why use this pattern? If you want to talk to an API, it might be tempting to define a method in the controller or a function in a separate file. However, implementing the data service pattern is advantageous for the following reasons: 1. The pattern provides an abstraction that allows for implementing and reusing strategies that are common when working with external APIs, such as batching, automatic retries with exponential backoff, etc. -2. By integrating with the messaging system, other parts of the application can make use of the data service without needing to go through the controller, or in fact, without needing a reference to the data service at all. +2. By integrating with a messenger, other parts of the application can make use of the data service without needing to go through the controller, or in fact, without needing a reference to the data service at all. ## How to create a data service @@ -78,7 +78,7 @@ Next we'll define the messenger. We give the messenger a namespace, and we expos ```typescript // (top of file) -import type { RestrictedMessenger } from '@metamask/base-controller'; +import type { Messenger } from '@metamask/messenger'; const SERVICE_NAME = 'GasPricesService'; @@ -95,21 +95,19 @@ export type GasPricesServiceEvents = never; type AllowedEvents = never; -export type GasPricesServiceMessenger = RestrictedMessenger< +export type GasPricesServiceMessenger = Messenger< typeof SERVICE_NAME, GasPricesServiceActions | AllowedActions, - GasPricesServiceEvents | AllowedEvents, - AllowedActions['type'], - AllowedEvents['type'] + GasPricesServiceEvents | AllowedEvents >; // ... ``` -Note that we need to add `@metamask/base-controller` as a direct dependency of the package to bring in the `RestrictedMessenger` type (here we assume that our package is called `@metamask/gas-prices-controller`): +Note that we need to add `@metamask/messenger` as a direct dependency of the package to bring in the `Messenger` type (here we assume that our package is called `@metamask/gas-prices-controller`): ```shell -yarn workspace @metamask/gas-prices-controller add @metamask/base-controller +yarn workspace @metamask/gas-prices-controller add @metamask/messenger ``` Finally we will register the method as an action handler on the messenger: @@ -145,7 +143,7 @@ export class GasPricesService {
View whole file
```typescript -import type { RestrictedMessenger } from '@metamask/base-controller'; +import type { Messenger } from '@metamask/messenger'; const SERVICE_NAME = 'GasPricesService'; @@ -162,12 +160,10 @@ export type GasPricesServiceEvents = never; type AllowedEvents = never; -export type GasPricesServiceMessenger = RestrictedMessenger< +export type GasPricesServiceMessenger = Messenger< typeof SERVICE_NAME, GasPricesServiceActions | AllowedActions, - GasPricesServiceEvents | AllowedEvents, - AllowedActions['type'], - AllowedEvents['type'] + GasPricesServiceEvents | AllowedEvents >; type GasPricesResponse = { @@ -272,10 +268,12 @@ import { Messenger } from '@metamask/base-controller'; // ... function buildMessenger(): GasPricesServiceMessenger { - return new Messenger().getRestricted({ - name: 'GasPricesService', - allowedActions: [], - allowedEvents: [], + return new Messenger< + 'GasPricesService', + GasPricesServiceActions, + GasPricesServiceEvents + >({ + namespace: 'GasPricesService', }); } ``` @@ -321,7 +319,11 @@ describe('GasPricesService', () => { ```typescript import nock from 'nock'; -import type { GasPricesServiceMessenger } from './gas-prices-service'; +import type { + GasPricesServiceMessenger, + GasPricesServiceActions, + GasPricesServiceEvents, +} from './gas-prices-service'; import { GasPricesService } from './gas-prices-service'; describe('GasPricesService', () => { @@ -375,10 +377,12 @@ describe('GasPricesService', () => { }); function buildMessenger(): GasPricesServiceMessenger { - return new Messenger().getRestricted({ - name: 'GasPricesService', - allowedActions: [], - allowedEvents: [], + return new Messenger< + 'GasPricesService', + GasPricesServiceActions, + GasPricesServiceEvents + >({ + namespace: 'GasPricesService', }); } ``` @@ -387,7 +391,7 @@ function buildMessenger(): GasPricesServiceMessenger { ## How to use a data service -Let's say that we wanted to use our data service that we built above. To do this, we will instantiate the messenger for the data service — which itself relies on a global messenger — and then the data service itself. +Let's say that we wanted to use our data service that we built above. To do this, we will instantiate the messenger for the data service — which itself relies on a root messenger — and then the data service itself. First we need to import the data service: @@ -395,22 +399,29 @@ First we need to import the data service: import { GasPricesService } from '@metamask/gas-prices-service'; ``` -Then we create a global messenger: +Then we create a root messenger: ```typescript -const globalMessenger = new Messenger(); +const rootMessenger = new Messenger<'Root', AllActions, AllEvents>({ + namespace: 'Root', +}); ``` Then we create a messenger for the GasPricesService: ```typescript -const gasPricesServiceMessenger = globalMessenger.getRestricted({ - allowedActions: [], - allowedEvents: [], +const gasPricesServiceMessenger = new Messenger< + 'GasPricesService', + GasPricesServiceActions, + GasPricesServiceEvents, + typeof rootMessenger +>({ + namespace: 'GasPricesService', + parent: rootMessenger, }); ``` -Now we instantiate the data service to register the action handler on the global messenger. We assume we have a global `fetch` function available: +Now we instantiate the data service to register the action handler on the root messenger. We assume we have a global `fetch` function available: ```typescript const gasPricesService = new GasPricesService({ @@ -421,7 +432,7 @@ const gasPricesService = new GasPricesService({ Great! Now that we've set up the data service and its messenger action, we can use it somewhere else. -Let's say we wanted to use it in a controller. We'd just need to allow that controller's messenger access to `GasPricesService:fetchGasPrices` by passing it via the `allowedActions` option. +Let's say we wanted to use `GasPricesService:fetchGasPrices` in a controller. First, that controller's messenger would need to include `GasPricesService:fetchGasPrices` in its type defintion. This code would probably be in the controller package itself. For instance, if we had a file `packages/send-controller/send-controller.ts`, we might have: @@ -436,15 +447,22 @@ type SendControllerEvents = ...; type AllowedEvents = ...; -type SendControllerMessenger = RestrictedMessenger< +type SendControllerMessenger = Messenger< 'SendController', SendControllerActions | AllowedActions, SendControllerEvents | AllowedEvents, - AllowedActions['type'], - AllowedEvents['type'] >; ``` +Then we'll need to allow that controller's messenger access to `GasPricesService:fetchGasPrices` by delegating it from the root messenger: + +```typescript +rootMessenger.delegate({ + actions: ['GasPricesService:fetchGasPrices'], + messenger: sendControllerMessenger, +}); +``` + Then, later on in our controller, we could say: ```typescript @@ -452,7 +470,7 @@ class SendController extends BaseController { // ... await someMethodThatUsesGasPrices() { - const gasPrices = await this.#messagingSystem.call( + const gasPrices = await this.messenger.call( 'GasPricesService:fetchGasPrices', ); // ... use gasPrices somehow ... diff --git a/packages/sample-controllers/CHANGELOG.md b/packages/sample-controllers/CHANGELOG.md index 546c70743a0..94d347cbf17 100644 --- a/packages/sample-controllers/CHANGELOG.md +++ b/packages/sample-controllers/CHANGELOG.md @@ -7,6 +7,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Changed + +- **BREAKING:** Migrate to new `Messenger` class ([#6335](https://github.com/MetaMask/core/pull/6335)) +- **BREAKING:** Rename metadata property `anonymous` to `includeInDebugSnapshot` ([#6335](https://github.com/MetaMask/core/pull/6335)) + ## [2.0.2] ### Changed diff --git a/packages/sample-controllers/package.json b/packages/sample-controllers/package.json index c72a9978e13..bf1c0e193e2 100644 --- a/packages/sample-controllers/package.json +++ b/packages/sample-controllers/package.json @@ -48,6 +48,7 @@ }, "dependencies": { "@metamask/base-controller": "^8.4.2", + "@metamask/messenger": "^0.3.0", "@metamask/utils": "^11.8.1" }, "devDependencies": { diff --git a/packages/sample-controllers/src/sample-gas-prices-controller.test.ts b/packages/sample-controllers/src/sample-gas-prices-controller.test.ts index 6159414c133..b61edf5c6c4 100644 --- a/packages/sample-controllers/src/sample-gas-prices-controller.test.ts +++ b/packages/sample-controllers/src/sample-gas-prices-controller.test.ts @@ -1,12 +1,15 @@ -import { Messenger, deriveStateFromMetadata } from '@metamask/base-controller'; +import { deriveStateFromMetadata } from '@metamask/base-controller/next'; +import { + Messenger, + MOCK_ANY_NAMESPACE, + type MockAnyNamespace, + type MessengerActions, + type MessengerEvents, +} from '@metamask/messenger'; import { SampleGasPricesController } from '@metamask/sample-controllers'; import type { SampleGasPricesControllerMessenger } from '@metamask/sample-controllers'; import { flushPromises } from '../../../tests/helpers'; -import type { - ExtractAvailableAction, - ExtractAvailableEvent, -} from '../../base-controller/tests/helpers'; import { buildMockGetNetworkClientById } from '../../network-controller/tests/helpers'; describe('SampleGasPricesController', () => { @@ -301,7 +304,7 @@ describe('SampleGasPricesController', () => { deriveStateFromMetadata( controller.state, controller.metadata, - 'anonymous', + 'includeInDebugSnapshot', ), ).toMatchInlineSnapshot(`Object {}`); }); @@ -362,8 +365,9 @@ describe('SampleGasPricesController', () => { * required by the controller under test. */ type RootMessenger = Messenger< - ExtractAvailableAction, - ExtractAvailableEvent + MockAnyNamespace, + MessengerActions, + MessengerEvents >; /** @@ -389,7 +393,7 @@ type WithControllerOptions = { * @returns The root messenger. */ function getRootMessenger(): RootMessenger { - return new Messenger(); + return new Messenger({ namespace: MOCK_ANY_NAMESPACE }); } /** @@ -402,14 +406,19 @@ function getRootMessenger(): RootMessenger { function getMessenger( rootMessenger: RootMessenger, ): SampleGasPricesControllerMessenger { - return rootMessenger.getRestricted({ - name: 'SampleGasPricesController', - allowedActions: [ - 'SampleGasPricesService:fetchGasPrices', + const messenger: SampleGasPricesControllerMessenger = new Messenger({ + namespace: 'SampleGasPricesController', + parent: rootMessenger, + }); + rootMessenger.delegate({ + actions: [ 'NetworkController:getNetworkClientById', + 'SampleGasPricesService:fetchGasPrices', ], - allowedEvents: ['NetworkController:stateChange'], + events: ['NetworkController:stateChange'], + messenger, }); + return messenger; } /** diff --git a/packages/sample-controllers/src/sample-gas-prices-controller.ts b/packages/sample-controllers/src/sample-gas-prices-controller.ts index c6db87b3f32..8bcec969f01 100644 --- a/packages/sample-controllers/src/sample-gas-prices-controller.ts +++ b/packages/sample-controllers/src/sample-gas-prices-controller.ts @@ -1,10 +1,10 @@ import type { ControllerGetStateAction, ControllerStateChangeEvent, - RestrictedMessenger, StateMetadata, -} from '@metamask/base-controller'; -import { BaseController } from '@metamask/base-controller'; +} from '@metamask/base-controller/next'; +import { BaseController } from '@metamask/base-controller/next'; +import type { Messenger } from '@metamask/messenger'; import type { NetworkClientId, NetworkControllerGetNetworkClientByIdAction, @@ -65,9 +65,9 @@ export type SampleGasPricesControllerState = { */ const gasPricesControllerMetadata = { gasPricesByChainId: { + includeInDebugSnapshot: false, includeInStateLogs: true, persist: true, - anonymous: false, usedInUi: true, }, } satisfies StateMetadata; @@ -137,12 +137,10 @@ type AllowedEvents = NetworkControllerStateChangeEvent; * The messenger restricted to actions and events accessed by * {@link SampleGasPricesController}. */ -export type SampleGasPricesControllerMessenger = RestrictedMessenger< +export type SampleGasPricesControllerMessenger = Messenger< typeof controllerName, SampleGasPricesControllerActions | AllowedActions, - SampleGasPricesControllerEvents | AllowedEvents, - AllowedActions['type'], - AllowedEvents['type'] + SampleGasPricesControllerEvents | AllowedEvents >; // === CONTROLLER DEFINITION === @@ -153,7 +151,7 @@ export type SampleGasPricesControllerMessenger = RestrictedMessenger< * @example * * ``` ts - * import { Messenger } from '@metamask/base-controller'; + * import { Messenger } from '@metamask/messenger'; * import type { * NetworkControllerActions, * NetworkControllerEvents, @@ -170,18 +168,23 @@ export type SampleGasPricesControllerMessenger = RestrictedMessenger< * selectGasPrices, * } from '@metamask/sample-controllers'; * - * const globalMessenger = new Messenger< + * const rootMessenger = new Messenger< + * 'Root', * SampleGasPricesServiceActions * | SampleGasPricesControllerActions * | NetworkControllerActions, * SampleGasPricesServiceEvents * | SampleGasPricesControllerEvents * | NetworkControllerEvents - * >(); - * const gasPricesServiceMessenger = globalMessenger.getRestricted({ - * name: 'SampleGasPricesService', - * allowedActions: [], - * allowedEvents: [], + * >({ namespace: 'Root' }); + * const gasPricesServiceMessenger = new Messenger< + * 'SampleGasPricesService', + * SampleGasPricesServiceActions, + * SampleGasPricesServiceEvents, + * typeof rootMessenger, + * >({ + * namespace: 'SampleGasPricesService', + * parent: rootMessenger, * }); * // Instantiate the service to register its actions on the messenger * new SampleGasPricesService({ @@ -189,10 +192,14 @@ export type SampleGasPricesControllerMessenger = RestrictedMessenger< * // We assume you're using this in the browser. * fetch, * }); - * const gasPricesControllerMessenger = globalMessenger.getRestricted({ - * name: 'SampleGasPricesController', - * allowedActions: ['NetworkController:getNetworkClientById'], - * allowedEvents: ['NetworkController:stateChange'], + * const gasPricesControllerMessenger = new Messenger< + * 'SampleGasPricesController', + * SampleGasPricesControllerActions | NetworkControllerGetNetworkClientByIdAction, + * SampleGasPricesControllerEvents | NetworkControllerStateChangeEvent, + * typeof rootMessenger, + * >({ + * namespace: 'SampleGasPricesController', + * parent: rootMessenger, * }); * // Instantiate the controller to register its actions on the messenger * new SampleGasPricesController({ @@ -200,11 +207,11 @@ export type SampleGasPricesControllerMessenger = RestrictedMessenger< * }); * * // Later... - * await globalMessenger.call( + * await rootMessenger.call( * 'SampleGasPricesController:updateGasPrices', * { chainId: '0x42' }, * ); - * const gasPricesControllerState = await globalMessenger.call( + * const gasPricesControllerState = await rootMessenger.call( * 'SampleGasPricesController:getState', * ); * gasPricesControllerState.gasPricesByChainId @@ -246,12 +253,12 @@ export class SampleGasPricesController extends BaseController< }, }); - this.messagingSystem.registerMethodActionHandlers( + this.messenger.registerMethodActionHandlers( this, MESSENGER_EXPOSED_METHODS, ); - this.messagingSystem.subscribe( + this.messenger.subscribe( 'NetworkController:stateChange', this.#onSelectedNetworkClientIdChange.bind(this), (networkControllerState) => @@ -267,7 +274,7 @@ export class SampleGasPricesController extends BaseController< * @param args.chainId - The chain ID for which to fetch gas prices. */ async updateGasPrices({ chainId }: { chainId: Hex }) { - const gasPricesResponse = await this.messagingSystem.call( + const gasPricesResponse = await this.messenger.call( 'SampleGasPricesService:fetchGasPrices', chainId, ); @@ -291,7 +298,7 @@ export class SampleGasPricesController extends BaseController< ) { const { configuration: { chainId }, - } = this.messagingSystem.call( + } = this.messenger.call( 'NetworkController:getNetworkClientById', selectedNetworkClientId, ); diff --git a/packages/sample-controllers/src/sample-gas-prices-service/sample-gas-prices-service.test.ts b/packages/sample-controllers/src/sample-gas-prices-service/sample-gas-prices-service.test.ts index d7628dc190c..2c82b73f7c6 100644 --- a/packages/sample-controllers/src/sample-gas-prices-service/sample-gas-prices-service.test.ts +++ b/packages/sample-controllers/src/sample-gas-prices-service/sample-gas-prices-service.test.ts @@ -1,15 +1,17 @@ -import { Messenger } from '@metamask/base-controller'; import { HttpError } from '@metamask/controller-utils'; +import { + Messenger, + MOCK_ANY_NAMESPACE, + type MockAnyNamespace, + type MessengerActions, + type MessengerEvents, +} from '@metamask/messenger'; import nock from 'nock'; import { useFakeTimers } from 'sinon'; import type { SinonFakeTimers } from 'sinon'; import type { SampleGasPricesServiceMessenger } from './sample-gas-prices-service'; import { SampleGasPricesService } from './sample-gas-prices-service'; -import type { - ExtractAvailableAction, - ExtractAvailableEvent, -} from '../../../base-controller/tests/helpers'; describe('SampleGasPricesService', () => { let clock: SinonFakeTimers; @@ -293,8 +295,11 @@ describe('SampleGasPricesService', () => { * required by the service under test. */ type RootMessenger = Messenger< - ExtractAvailableAction, - ExtractAvailableEvent + MockAnyNamespace, + MessengerActions, + // TODO: Disable this lint rule + // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-arguments + MessengerEvents >; /** @@ -304,7 +309,7 @@ type RootMessenger = Messenger< * @returns The root messenger. */ function getRootMessenger(): RootMessenger { - return new Messenger(); + return new Messenger({ namespace: MOCK_ANY_NAMESPACE }); } /** @@ -317,10 +322,9 @@ function getRootMessenger(): RootMessenger { function getMessenger( rootMessenger: RootMessenger, ): SampleGasPricesServiceMessenger { - return rootMessenger.getRestricted({ - name: 'SampleGasPricesService', - allowedActions: [], - allowedEvents: [], + return new Messenger({ + namespace: 'SampleGasPricesService', + parent: rootMessenger, }); } diff --git a/packages/sample-controllers/src/sample-gas-prices-service/sample-gas-prices-service.ts b/packages/sample-controllers/src/sample-gas-prices-service/sample-gas-prices-service.ts index 5117114bc7c..5eacf5d7a79 100644 --- a/packages/sample-controllers/src/sample-gas-prices-service/sample-gas-prices-service.ts +++ b/packages/sample-controllers/src/sample-gas-prices-service/sample-gas-prices-service.ts @@ -1,4 +1,3 @@ -import type { RestrictedMessenger } from '@metamask/base-controller'; import type { CreateServicePolicyOptions, ServicePolicy, @@ -8,6 +7,7 @@ import { fromHex, HttpError, } from '@metamask/controller-utils'; +import type { Messenger } from '@metamask/messenger'; import { hasProperty, isPlainObject, type Hex } from '@metamask/utils'; import type { SampleGasPricesServiceMethodActions } from './sample-gas-prices-service-method-action-types'; @@ -49,12 +49,12 @@ type AllowedEvents = never; * The messenger which is restricted to actions and events accessed by * {@link SampleGasPricesService}. */ -export type SampleGasPricesServiceMessenger = RestrictedMessenger< +export type SampleGasPricesServiceMessenger = Messenger< typeof serviceName, SampleGasPricesServiceActions | AllowedActions, - SampleGasPricesServiceEvents | AllowedEvents, - AllowedActions['type'], - AllowedEvents['type'] + // TODO: Disable this lint rule + // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-arguments + SampleGasPricesServiceEvents | AllowedEvents >; // === SERVICE DEFINITION === @@ -76,20 +76,25 @@ type GasPricesResponse = { * @example * * ``` ts - * import { Messenger } from '@metamask/base-controller'; + * import { Messenger } from '@metamask/messenger'; * import type { * SampleGasPricesServiceActions, * SampleGasPricesServiceEvents, * } from '@metamask/sample-controllers'; * - * const globalMessenger = new Messenger< - * SampleGasPricesServiceActions, + * const rootMessenger = new Messenger< + * 'Root', + * SampleGasPricesServiceActions * SampleGasPricesServiceEvents - * >(); - * const gasPricesServiceMessenger = globalMessenger.getRestricted({ - * name: 'SampleGasPricesService', - * allowedActions: [], - * allowedEvents: [], + * >({ namespace: 'Root' }); + * const gasPricesServiceMessenger = new Messenger< + * 'SampleGasPricesService', + * SampleGasPricesServiceActions, + * SampleGasPricesServiceEvents, + * typeof rootMessenger, + * >({ + * namespace: 'SampleGasPricesService', + * parent: rootMessenger, * }); * // Instantiate the service to register its actions on the messenger * new SampleGasPricesService({ @@ -99,7 +104,7 @@ type GasPricesResponse = { * * // Later... * // Fetch gas prices for Mainnet - * const gasPrices = await globalMessenger.call( + * const gasPrices = await rootMessenger.call( * 'SampleGasPricesService:fetchGasPrices', * '0x1', * ); diff --git a/packages/sample-controllers/src/sample-petnames-controller.test.ts b/packages/sample-controllers/src/sample-petnames-controller.test.ts index 40163b21703..0d7d67159f7 100644 --- a/packages/sample-controllers/src/sample-petnames-controller.test.ts +++ b/packages/sample-controllers/src/sample-petnames-controller.test.ts @@ -1,11 +1,14 @@ -import { Messenger, deriveStateFromMetadata } from '@metamask/base-controller'; +import { deriveStateFromMetadata } from '@metamask/base-controller/next'; +import { + Messenger, + MOCK_ANY_NAMESPACE, + type MockAnyNamespace, + type MessengerActions, + type MessengerEvents, +} from '@metamask/messenger'; import type { SamplePetnamesControllerMessenger } from './sample-petnames-controller'; import { SamplePetnamesController } from './sample-petnames-controller'; -import type { - ExtractAvailableAction, - ExtractAvailableEvent, -} from '../../base-controller/tests/helpers'; import { PROTOTYPE_POLLUTION_BLOCKLIST } from '../../controller-utils/src/util'; describe('SamplePetnamesController', () => { @@ -197,7 +200,7 @@ describe('SamplePetnamesController', () => { deriveStateFromMetadata( controller.state, controller.metadata, - 'anonymous', + 'includeInDebugSnapshot', ), ).toMatchInlineSnapshot(`Object {}`); }); @@ -258,8 +261,9 @@ describe('SamplePetnamesController', () => { * required by the controller under test. */ type RootMessenger = Messenger< - ExtractAvailableAction, - ExtractAvailableEvent + MockAnyNamespace, + MessengerActions, + MessengerEvents >; /** @@ -285,7 +289,7 @@ type WithControllerOptions = { * @returns The root messenger. */ function getRootMessenger(): RootMessenger { - return new Messenger(); + return new Messenger({ namespace: MOCK_ANY_NAMESPACE }); } /** @@ -298,10 +302,9 @@ function getRootMessenger(): RootMessenger { function getMessenger( rootMessenger: RootMessenger, ): SamplePetnamesControllerMessenger { - return rootMessenger.getRestricted({ - name: 'SamplePetnamesController', - allowedActions: [], - allowedEvents: [], + return new Messenger({ + namespace: 'SamplePetnamesController', + parent: rootMessenger, }); } diff --git a/packages/sample-controllers/src/sample-petnames-controller.ts b/packages/sample-controllers/src/sample-petnames-controller.ts index cf7a4a70784..bf0e7499441 100644 --- a/packages/sample-controllers/src/sample-petnames-controller.ts +++ b/packages/sample-controllers/src/sample-petnames-controller.ts @@ -1,11 +1,11 @@ import type { ControllerGetStateAction, ControllerStateChangeEvent, - RestrictedMessenger, StateMetadata, -} from '@metamask/base-controller'; -import { BaseController } from '@metamask/base-controller'; +} from '@metamask/base-controller/next'; +import { BaseController } from '@metamask/base-controller/next'; import { isSafeDynamicKey } from '@metamask/controller-utils'; +import type { Messenger } from '@metamask/messenger'; import type { Hex } from '@metamask/utils'; import type { SamplePetnamesControllerMethodActions } from './sample-petnames-controller-method-action-types'; @@ -41,9 +41,9 @@ export type SamplePetnamesControllerState = { */ const samplePetnamesControllerMetadata = { namesByChainIdAndAddress: { + includeInDebugSnapshot: false, includeInStateLogs: true, persist: true, - anonymous: false, usedInUi: true, }, } satisfies StateMetadata; @@ -111,12 +111,10 @@ type AllowedEvents = never; * The messenger restricted to actions and events accessed by * {@link SamplePetnamesController}. */ -export type SamplePetnamesControllerMessenger = RestrictedMessenger< +export type SamplePetnamesControllerMessenger = Messenger< typeof controllerName, SamplePetnamesControllerActions | AllowedActions, - SamplePetnamesControllerEvents | AllowedEvents, - AllowedActions['type'], - AllowedEvents['type'] + SamplePetnamesControllerEvents | AllowedEvents >; // === CONTROLLER DEFINITION === @@ -128,27 +126,32 @@ export type SamplePetnamesControllerMessenger = RestrictedMessenger< * @example * * ``` ts - * import { Messenger } from '@metamask/base-controller'; + * import { Messenger } from '@metamask/messenger'; * import type { * SamplePetnamesControllerActions, * SamplePetnamesControllerEvents, * } from '@metamask/sample-controllers'; * - * const globalMessenger = new Messenger< + * const rootMessenger = new Messenger< + * 'Root', * SamplePetnamesControllerActions, * SamplePetnamesControllerEvents - * >(); - * const samplePetnamesMessenger = globalMessenger.getRestricted({ - * name: 'SamplePetnamesController', - * allowedActions: [], - * allowedEvents: [], + * >({ namespace: 'Root' }); + * const samplePetnamesMessenger = new Messenger< + * 'SamplePetnamesController', + * SamplePetnamesControllerActions, + * SamplePetnamesControllerEvents, + * typeof rootMessenger, + * >({ + * namespace: 'SamplePetnamesController', + * parent: rootMessenger, * }); * // Instantiate the controller to register its actions on the messenger * new SamplePetnamesController({ * messenger: samplePetnamesMessenger, * }); * - * globalMessenger.call( + * rootMessenger.call( * 'SamplePetnamesController:assignPetname', * [ * '0x1', @@ -156,7 +159,7 @@ export type SamplePetnamesControllerMessenger = RestrictedMessenger< * 'Primary Account', * ], * ); - * const samplePetnamesControllerState = await globalMessenger.call( + * const samplePetnamesControllerState = await rootMessenger.call( * 'SamplePetnamesController:getState', * ); * samplePetnamesControllerState.namesByChainIdAndAddress @@ -193,7 +196,7 @@ export class SamplePetnamesController extends BaseController< }, }); - this.messagingSystem.registerMethodActionHandlers( + this.messenger.registerMethodActionHandlers( this, MESSENGER_EXPOSED_METHODS, ); diff --git a/packages/sample-controllers/tsconfig.build.json b/packages/sample-controllers/tsconfig.build.json index 37e83ff4f7f..d71ced03932 100644 --- a/packages/sample-controllers/tsconfig.build.json +++ b/packages/sample-controllers/tsconfig.build.json @@ -7,6 +7,7 @@ }, "references": [ { "path": "../../packages/base-controller/tsconfig.build.json" }, + { "path": "../../packages/messenger/tsconfig.build.json" }, { "path": "../../packages/network-controller/tsconfig.build.json" } ], "include": ["../../types", "./src"] diff --git a/packages/sample-controllers/tsconfig.json b/packages/sample-controllers/tsconfig.json index 42ff3e1c18a..65b458897f2 100644 --- a/packages/sample-controllers/tsconfig.json +++ b/packages/sample-controllers/tsconfig.json @@ -6,6 +6,7 @@ "references": [ { "path": "../../packages/base-controller" }, { "path": "../../packages/controller-utils" }, + { "path": "../../packages/messenger" }, { "path": "../../packages/network-controller" } ], "include": ["../../types", "./src"], diff --git a/yarn.lock b/yarn.lock index f67c9bc6cb0..e94fd0e13e1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4631,6 +4631,7 @@ __metadata: "@metamask/auto-changelog": "npm:^3.4.4" "@metamask/base-controller": "npm:^8.4.2" "@metamask/controller-utils": "npm:^11.14.1" + "@metamask/messenger": "npm:^0.3.0" "@metamask/network-controller": "npm:^24.3.1" "@metamask/utils": "npm:^11.8.1" "@types/jest": "npm:^27.4.1"