Skip to content

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

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

chore: Expose Accounts-owned controller/service methods through messenger#7976
GuillaumeRx wants to merge 3 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.

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
Changes the cross-controller messaging surface and registration mechanism; misconfiguration of the exposed-method allowlists could break runtime message calls despite minimal business-logic changes.

Overview
Standardizes messenger wiring across accounts-owned packages by replacing per-action registerActionHandler blocks with registerMethodActionHandlers + centralized MESSENGER_EXPOSED_METHODS allowlists in AccountTreeController, AccountsController, MultichainAccountService, AuthenticationController, and UserStorageController.

Expands the messenger-exposed surface area for account tree operations (e.g., getters for wallet/group objects, clearState, and user-storage sync entrypoints) and for AccountsController adds loadBackup to the action types; internal-only helpers like resolveNameConflict and getAccountExpect are made private, with tests updated accordingly (switching to getAccount() and exercising conflict handling via public APIs).

Written by Cursor Bugbot for commit 0e42ff2. 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

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

@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.

ActionsObj['performBatchDeleteStorage'];
export type UserStorageControllerGetStorageKey = ActionsObj['getStorageKey'];
export type UserStoragePerformDeleteStorageAllFeatureEntries =
ActionsObj['performDeleteStorageAllFeatureEntries'];
Copy link

Choose a reason for hiding this comment

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

Inconsistent type name missing "Controller" prefix

Low Severity

The newly exported type UserStoragePerformDeleteStorageAllFeatureEntries is missing "Controller" in its name. Every other exported type alias in this file follows the UserStorageController* naming convention (e.g., UserStorageControllerPerformDeleteStorage, UserStorageControllerListEntropySources). This inconsistency makes the type harder to discover for consumers who follow the established naming pattern.

Fix in Cursor Fix in Web

Copy link
Contributor

@mcmire mcmire Feb 18, 2026

Choose a reason for hiding this comment

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

This is true. These types are incorrectly named. But fixing this is out of scope for this PR.

ActionsObj['performBatchDeleteStorage'];
export type UserStorageControllerGetStorageKey = ActionsObj['getStorageKey'];
export type UserStoragePerformDeleteStorageAllFeatureEntries =
ActionsObj['performDeleteStorageAllFeatureEntries'];
Copy link
Contributor

Choose a reason for hiding this comment

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

This wasn't exposed before, why's it added?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The idea is to have everything called externally being called via the messenger. This is a preliminary step to ensure that we expose all public methods through 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.

Gotcha, thanks

handler: AccountTreeController['setAccountGroupPinned'];
};

export type AccountTreeControllerGetAccountWalletObjectAction = {
Copy link
Contributor

Choose a reason for hiding this comment

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

What are your thoughts on using yarn generate-action-method-types to automatically generate these types? Essentially what this does is generate a file (in this case called AccountsController-method-action-types.ts) which will hold the types for all actions you've added to MESSENGER_EXPOSED_METHODS. The file exports the types it generates as well as a union called AccountsControllerMethodActionTypes.

Using this script has the advantage that if the methods are JSDoc'd, then the doc blocks will be copied over to the types. You can see how we typically plug in the *MethodActionTypes type here:

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 wasn't aware of yarn generate-action-method-types and it seems relevant to use this tool here.

| 'getUserProfileLineage'
| 'isSignedIn'
>;
type ActionsObj = CreateActionsObj<(typeof MESSENGER_EXPOSED_METHODS)[number]>;
Copy link
Contributor

Choose a reason for hiding this comment

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

Similar for this. The generate-method-action-types package script will give us an AuthenticationControllerMethodActions type that replaces this one, and we should be able to use it within the Actions type.

| 'performBatchDeleteStorage'
| 'getStorageKey'
>;
type ActionsObj = CreateActionsObj<(typeof MESSENGER_EXPOSED_METHODS)[number]>;
Copy link
Contributor

Choose a reason for hiding this comment

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

Same for this one.

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