Skip to content

Comments

feat!: Expose Accounts-owned controller/service methods through messenger#7976

Open
GuillaumeRx wants to merge 23 commits intomainfrom
gr/expose-accounts-methods-messenger
Open

feat!: Expose Accounts-owned controller/service methods through messenger#7976
GuillaumeRx wants to merge 23 commits intomainfrom
gr/expose-accounts-methods-messenger

Conversation

@GuillaumeRx
Copy link
Contributor

@GuillaumeRx GuillaumeRx commented Feb 18, 2026

Explanation

Exposes all the public methods other than init or any internally used methods of the accounts-owned controllers/services throught the messenger.

This also refactors how actions are defined and bound to the messenger using registerMethodActionHandlers and MESSENGER_EXPOSED_METHODS.

The generate-method-action-type script was used to generate the action types.

This is a breaking change in the profile-sync-controller package as some of the action type names changed but none of the underlying signatures changed.

References

Checklist

  • I've updated the test suite for new or updated code as appropriate
  • I've updated documentation (JSDoc, Markdown, etc.) for new or updated code as appropriate
  • I've communicated my changes to consumers by updating changelogs for packages I've changed
  • I've introduced breaking changes in this PR and have prepared draft pull requests for clients and consumer packages to resolve them

Note

Medium Risk
Wide cross-package refactor of messenger action registration and exported action type names; risk is mainly integration breakage for consumers relying on old action types or missing exposed methods, rather than new business logic.

Overview
Refactors AccountsController, AccountTreeController, MultichainAccountService, and profile-sync-controller (AuthenticationController, UserStorageController) to expose public APIs through the messenger via registerMethodActionHandlers and per-module MESSENGER_EXPOSED_METHODS, replacing manual registerActionHandler wiring.

Introduces auto-generated *-method-action-types.ts files (and new generate-method-action-types scripts using tsx) and updates package exports/types and cross-package AllowedActions references to the new ...Action type names (notably a breaking rename in profile-sync-controller). Tests were adjusted for the new action names and a couple of behaviors (e.g., selected-account missing ID now throws; account-group name conflict resolution is exercised via public setters).

Written by Cursor Bugbot for commit 7ec9ffb. This will update automatically on new commits. Configure here.

@GuillaumeRx GuillaumeRx requested a review from a team as a code owner February 18, 2026 11:14
@GuillaumeRx GuillaumeRx force-pushed the gr/expose-accounts-methods-messenger branch from 7de355d to 0e42ff2 Compare February 18, 2026 11:15
Comment on lines +4578 to +4589
controller.setAccountGroupName(groupId, 'Suffix Test', true);

// Test with no conflicts: should return "Unique Name (2)"
const uniqueName = controller.resolveNameConflict(
wallet,
groupId,
'Unique Name',
);
expect(uniqueName).toBe('Unique Name (2)');
const collidingGroupObject = controller.getAccountGroupObject(groupId);

expect(collidingGroupObject?.metadata.name).toBe('Suffix Test (3)');

// Test with no conflicts: should return "Unique Name"
controller.setAccountGroupName(groupId, 'Unique Name', true);

const uniqueGroupObject = controller.getAccountGroupObject(groupId);

expect(uniqueGroupObject?.metadata.name).toBe('Unique Name');
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

resolveNameConflict is only internally used. It doesn't make sense to have it publicly only to test its behavior in unit tests. We can do that via the public methods that uses it

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can confirm this is not used in either extension and mobile.

Comment on lines +4578 to +4589
controller.setAccountGroupName(groupId, 'Suffix Test', true);

// Test with no conflicts: should return "Unique Name (2)"
const uniqueName = controller.resolveNameConflict(
wallet,
groupId,
'Unique Name',
);
expect(uniqueName).toBe('Unique Name (2)');
const collidingGroupObject = controller.getAccountGroupObject(groupId);

expect(collidingGroupObject?.metadata.name).toBe('Suffix Test (3)');

// Test with no conflicts: should return "Unique Name"
controller.setAccountGroupName(groupId, 'Unique Name', true);

const uniqueGroupObject = controller.getAccountGroupObject(groupId);

expect(uniqueGroupObject?.metadata.name).toBe('Unique Name');
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This assertion was very misleading by the way. If there's no conflict the method shouldn't be called therefore no suffix should be added.

* @throws An error if the account ID is not found.
*/
getAccountExpect(accountId: string): InternalAccount {
#getAccountExpect(accountId: string): InternalAccount {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't need this method to be public, it's only used internally.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense!

@GuillaumeRx GuillaumeRx force-pushed the gr/expose-accounts-methods-messenger branch from 0e42ff2 to 6ea2c28 Compare February 19, 2026 15:10
@GuillaumeRx GuillaumeRx requested review from a team as code owners February 19, 2026 15:10
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know what's going on here with the imports, I just made sure that the original export behavior was respected.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This certainly seems cleaner :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know what's going on here with the imports, I just made sure that the original export behavior was respected.

@GuillaumeRx GuillaumeRx requested review from a team as code owners February 19, 2026 15:30
@GuillaumeRx GuillaumeRx changed the title chore: Expose Accounts-owned controller/service methods through messenger feat!: Expose Accounts-owned controller/service methods through messenger Feb 20, 2026
@GuillaumeRx GuillaumeRx requested a review from a team as a code owner February 20, 2026 10:44
@GuillaumeRx GuillaumeRx force-pushed the gr/expose-accounts-methods-messenger branch 2 times, most recently from be1d092 to 405c239 Compare February 20, 2026 11:19
Comment on lines +850 to +857
const { messenger, mocks } = await setup({
accounts: [MOCK_HD_ACCOUNT_1],
});

const resyncAccountsSpy = jest.spyOn(service, 'resyncAccounts');
await messenger.call('MultichainAccountService:resyncAccounts');
expect(resyncAccountsSpy).toHaveBeenCalled();

expect(mocks.EvmAccountProvider.resyncAccounts).toHaveBeenCalled();
expect(mocks.SolAccountProvider.resyncAccounts).toHaveBeenCalled();
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we can't spy resyncAccounts at this step since registeMethodActionHandlers will register the original method not the spied one

Comment on lines -882 to -887
const ensureCanUseSnapPlatformSpy = jest.spyOn(
service,
'ensureCanUseSnapPlatform',
await rootMessenger.call(
'MultichainAccountService:ensureCanUseSnapPlatform',
);
await messenger.call('MultichainAccountService:ensureCanUseSnapPlatform');
expect(ensureCanUseSnapPlatformSpy).toHaveBeenCalled();
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we can't spy ensureCanUseSnapPlatform at this step since registeMethodActionHandlers will register the original method not the spied one

@GuillaumeRx GuillaumeRx force-pushed the gr/expose-accounts-methods-messenger branch from 31e2baa to 6867941 Compare February 20, 2026 13:04
Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Copy link
Contributor

@mcmire mcmire left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice! The code changes themselves look good, but I had some suggestions on changelogs. (You may need to add the no-changelog label to this PR to suppress the changelog checker.)

Comment on lines +4578 to +4589
controller.setAccountGroupName(groupId, 'Suffix Test', true);

// Test with no conflicts: should return "Unique Name (2)"
const uniqueName = controller.resolveNameConflict(
wallet,
groupId,
'Unique Name',
);
expect(uniqueName).toBe('Unique Name (2)');
const collidingGroupObject = controller.getAccountGroupObject(groupId);

expect(collidingGroupObject?.metadata.name).toBe('Suffix Test (3)');

// Test with no conflicts: should return "Unique Name"
controller.setAccountGroupName(groupId, 'Unique Name', true);

const uniqueGroupObject = controller.getAccountGroupObject(groupId);

expect(uniqueGroupObject?.metadata.name).toBe('Unique Name');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can confirm this is not used in either extension and mobile.

- The controller's methods are now exposed to the messenger through `registerMethodActionHandlers` and `MESSENGER_EXPOSED_METHODS`.
- The action types are now generated using `generate-method-action-types`.
- Exposes the missing public methods in the messenger.
- Update `UserStorageController` and `AuthenticationController` actions to their new names ([#7976](https://github.com/MetaMask/core/pull/7976))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are these public-facing changes? It looks like we are using new names for the types in the union, but neither the names of the action type strings nor the signatures of the action handlers themselves have changed. So consumers should not need to adjust how they construct the AccountTreeController messenger. Is this true?

Suggested change
- Update `UserStorageController` and `AuthenticationController` actions to their new names ([#7976](https://github.com/MetaMask/core/pull/7976))

* @throws An error if the account ID is not found.
*/
getAccountExpect(accountId: string): InternalAccount {
#getAccountExpect(accountId: string): InternalAccount {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense!

- The action types are now generated using `generate-method-action-types`.
- Exposes the missing public methods in the messenger.
- Update `UserStorageController` and `AuthenticationController` actions to their new names ([#7976](https://github.com/MetaMask/core/pull/7976))
- Bump `@metamask/accounts-controller` from `^36.0.0` to `^36.0.1` ([#7996](https://github.com/MetaMask/core/pull/7996))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we mention that we effectively removed resolveNameConflict?

Suggested change
- Bump `@metamask/accounts-controller` from `^36.0.0` to `^36.0.1` ([#7996](https://github.com/MetaMask/core/pull/7996))
### Removed
- **BREAKING:** Remove `resolveNameConflict` from `AccountTreeController` ([#7976](https://github.com/MetaMask/core/pull/7976))
- This method was only used internally.

Comment on lines 10 to +15
### Changed

- Refactor the controller's messenger action registration ([#7976](https://github.com/MetaMask/core/pull/7976/))
- The controller's methods are now exposed to the messenger through `registerMethodActionHandlers` and `MESSENGER_EXPOSED_METHODS`.
- The action types are now generated using `generate-method-action-types`.
- Exposes the missing public methods in the messenger.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We've been keeping changelog entries focused on public changes to the API only.
Curious if instead of highlighting that we refactored the messenger action registration, we should instead call out which methods are now available through the messenger? Also should this be in "Added" since we are adding new things that consumers can use?

Suggested change
### Changed
- Refactor the controller's messenger action registration ([#7976](https://github.com/MetaMask/core/pull/7976/))
- The controller's methods are now exposed to the messenger through `registerMethodActionHandlers` and `MESSENGER_EXPOSED_METHODS`.
- The action types are now generated using `generate-method-action-types`.
- Exposes the missing public methods in the messenger.
### Added
- Expose missing public `AccountTreeController` methods through its messenger ([#7976](https://github.com/MetaMask/core/pull/7976/))
- The following actions are now available:
- `AccountTreeController:getAccountWalletObject`
- `AccountTreeController:getAccountWalletObjects`
- `AccountTreeController:getAccountGroupObject`
- `AccountTreeController:clearState`
- `AccountTreeController:syncWithUserStorage`
- `AccountTreeController:syncWithUserStorageAtLeastOnce`
- Corresponding action types (e.g. `AccountTreeControllerGetAccountWalletObjectAction`) are available as well.


### Changed

- Refactor the controller's messenger action registration ([#7976](https://github.com/MetaMask/core/pull/7976/))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(Similar as for the changelogs above)

- Debounce `KeyringController:stateChange` handler to reduce redundant notification subscription calls during rapid account syncing ([#7980](https://github.com/MetaMask/core/pull/7980))
- Filter out Product Account announcements notifications older than 3 months ([#7884](https://github.com/MetaMask/core/pull/7884))
- Bump `@metamask/controller-utils` from `^11.18.0` to `^11.19.0` ([#7995](https://github.com/MetaMask/core/pull/7995))
- Update `AuthenticationController` actions to their new names ([#7976](https://github.com/MetaMask/core/pull/7976))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
- Update `AuthenticationController` actions to their new names ([#7976](https://github.com/MetaMask/core/pull/7976))


### Changed

- Update `AuthenticationController` action to its new name ([#7976](https://github.com/MetaMask/core/pull/7976))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
- Update `AuthenticationController` action to its new name ([#7976](https://github.com/MetaMask/core/pull/7976))

- **BREAKING:** Refactor the controller's messenger action registration ([#7976](https://github.com/MetaMask/core/pull/7976/))
- The controller's methods are now exposed to the messenger through `registerMethodActionHandlers` and `MESSENGER_EXPOSED_METHODS`.
- The action types are now generated using `generate-method-action-types`.
- Exposes the missing public methods in the messenger.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a bit different from other changelogs since we have some breaking changes. Currently it's not clear what exactly is breaking. Should we highlight that better specifically? Maybe something like:

Suggested change
- Exposes the missing public methods in the messenger.
### Added
- Expose missing public `UserStorageController` methods through its messenger ([#7976](https://github.com/MetaMask/core/pull/7976/))
- The following actions are now available:
- `UserStorageController:performDeleteStorageAllFeatureEntries`
- `UserStorageController:listEntropySources`
- `UserStorageController:setIsBackupAndSyncFeatureEnabled`
- `UserStorageController:setIsContactSyncingInProgress`
- `UserStorageController:syncContactsWithUserStorage`
- Corresponding action types (e.g. `UserStorageControllerPerformDeleteStorageAllFeatureEntriesAction`) are available as well.
### Changed
- **BREAKING:** Standardize names of `AuthenticationController` and `UserStorageController` messenger action types ([#7976](https://github.com/MetaMask/core/pull/7976/))
- All existing types for messenger actions have been renamed so they end in `Action` (e.g. `AuthenticationControllerPerformSignIn` -> `AuthenticationControllerPerformSignInAction`). You will need to update imports appropriately.
- This change only affects the types. The action type strings themselves have not changed, so you do not need to update the list of actions you pass when initializing `AuthenticationController` and `UserStorageController` messengers.

- Bump `@metamask/transaction-controller` from `^62.16.0` to `^62.18.0` ([#7897](https://github.com/MetaMask/core/pull/7897), [#7996](https://github.com/MetaMask/core/pull/7996), [#8005](https://github.com/MetaMask/core/pull/8005))
- Bump `@metamask/polling-controller` from `^16.0.2` to `^16.0.3` ([#7996](https://github.com/MetaMask/core/pull/7996))
- Bump `@metamask/controller-utils` from `^11.18.0` to `^11.19.0` ([#7995](https://github.com/MetaMask/core/pull/7995))
- Update `AuthenticationController` actions to their new names ([#7976](https://github.com/MetaMask/core/pull/7976))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
- Update `AuthenticationController` actions to their new names ([#7976](https://github.com/MetaMask/core/pull/7976))

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants