Skip to content

Commit a0a3194

Browse files
authored
refactor: migrate AccountTreeController to @metamask/messenger (#6380)
## Explanation <!-- Thanks for your contribution! Take a moment to answer these questions so that reviewers have the information they need to properly understand your changes: * What is the current state of things and why does it need to change? * What is the solution your changes offer and how does it work? * Are there any changes whose purpose might not obvious to those unfamiliar with the domain? * If your primary goal was to update one package but you found you had to update another one along the way, why did you do so? * If you had to upgrade a dependency, why did you do so? --> This PR migrates the `AccountTreeController` class to the new `@metamask/messenger` comm system, as opposed to the one exported from `@metamask/base-controller`. ## References <!-- Are there any issues that this pull request is tied to? Are there other links that reviewers should consult to understand these changes better? Are there client or consumer pull requests to adopt any breaking changes? For example: * Fixes #12345 * Related to #67890 --> * Related to #5626 ## 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](https://github.com/MetaMask/core/tree/main/docs/contributing.md#updating-changelogs), highlighting breaking changes as necessary - [ ] I've prepared draft pull requests for clients and consumer packages to resolve any breaking changes
1 parent c69c677 commit a0a3194

File tree

14 files changed

+263
-405
lines changed

14 files changed

+263
-405
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,7 @@ linkStyle default opacity:0.5
148148
transaction_controller(["@metamask/transaction-controller"]);
149149
user_operation_controller(["@metamask/user-operation-controller"]);
150150
account_tree_controller --> base_controller;
151+
account_tree_controller --> messenger;
151152
account_tree_controller --> accounts_controller;
152153
account_tree_controller --> keyring_controller;
153154
account_tree_controller --> multichain_account_service;
@@ -216,6 +217,7 @@ linkStyle default opacity:0.5
216217
earn_controller --> transaction_controller;
217218
eip_5792_middleware --> transaction_controller;
218219
eip_5792_middleware --> keyring_controller;
220+
eip_7702_internal_rpc_middleware --> controller_utils;
219221
eip1193_permission_middleware --> chain_agnostic_permission;
220222
eip1193_permission_middleware --> controller_utils;
221223
eip1193_permission_middleware --> json_rpc_engine;

packages/account-tree-controller/CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
### Changed
11+
12+
- **BREAKING:** Use new `Messenger` from `@metamask/messenger` ([#6380](https://github.com/MetaMask/core/pull/6380))
13+
- Previously, `AccountTreeController` accepted a `RestrictedMessenger` instance from `@metamask/base-controller`.
14+
1015
## [1.6.0]
1116

1217
### Changed

packages/account-tree-controller/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
},
4949
"dependencies": {
5050
"@metamask/base-controller": "^8.4.2",
51+
"@metamask/messenger": "^0.3.0",
5152
"@metamask/snaps-sdk": "^9.0.0",
5253
"@metamask/snaps-utils": "^11.0.0",
5354
"@metamask/superstruct": "^3.1.0",

packages/account-tree-controller/src/AccountTreeController.test.ts

Lines changed: 37 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import {
99
type AccountGroupId,
1010
} from '@metamask/account-api';
1111
import type { AccountId } from '@metamask/accounts-controller';
12-
import { Messenger, deriveStateFromMetadata } from '@metamask/base-controller';
12+
import { deriveStateFromMetadata } from '@metamask/base-controller/next';
1313
import {
1414
BtcAccountType,
1515
EthAccountType,
@@ -36,14 +36,11 @@ import type { BackupAndSyncAnalyticsEventPayload } from './backup-and-sync/analy
3636
import { BackupAndSyncService } from './backup-and-sync/service';
3737
import { isAccountGroupNameUnique } from './group';
3838
import { getAccountWalletNameFromKeyringType } from './rules/keyring';
39+
import { type AccountTreeControllerState } from './types';
3940
import {
40-
type AccountTreeControllerMessenger,
41-
type AccountTreeControllerActions,
42-
type AccountTreeControllerEvents,
43-
type AccountTreeControllerState,
44-
type AllowedActions,
45-
type AllowedEvents,
46-
} from './types';
41+
getAccountTreeControllerMessenger,
42+
getRootMessenger,
43+
} from '../tests/mockMessenger';
4744

4845
// Local mock of EMPTY_ACCOUNT to avoid circular dependency
4946
const EMPTY_ACCOUNT_MOCK: InternalAccount = {
@@ -233,53 +230,7 @@ const MOCK_HARDWARE_ACCOUNT_1: InternalAccount = {
233230
},
234231
};
235232

236-
/**
237-
* Creates a new root messenger instance for testing.
238-
*
239-
* @returns A new Messenger instance.
240-
*/
241-
function getRootMessenger() {
242-
return new Messenger<
243-
AccountTreeControllerActions | AllowedActions,
244-
AccountTreeControllerEvents | AllowedEvents
245-
>();
246-
}
247-
248-
/**
249-
* Retrieves a restricted messenger for the AccountTreeController.
250-
*
251-
* @param messenger - The root messenger instance. Defaults to a new Messenger created by getRootMessenger().
252-
* @returns The restricted messenger for the AccountTreeController.
253-
*/
254-
function getAccountTreeControllerMessenger(
255-
messenger = getRootMessenger(),
256-
): AccountTreeControllerMessenger {
257-
return messenger.getRestricted({
258-
name: 'AccountTreeController',
259-
allowedEvents: [
260-
'AccountsController:accountAdded',
261-
'AccountsController:accountRemoved',
262-
'AccountsController:selectedAccountChange',
263-
'UserStorageController:stateChange',
264-
'MultichainAccountService:walletStatusChange',
265-
],
266-
allowedActions: [
267-
'AccountsController:listMultichainAccounts',
268-
'AccountsController:getAccount',
269-
'AccountsController:getSelectedMultichainAccount',
270-
'AccountsController:setSelectedAccount',
271-
'UserStorageController:getState',
272-
'UserStorageController:performGetStorage',
273-
'UserStorageController:performGetStorageAllFeatureEntries',
274-
'UserStorageController:performSetStorage',
275-
'UserStorageController:performBatchSetStorage',
276-
'AuthenticationController:getSessionProfile',
277-
'MultichainAccountService:createMultichainAccountGroup',
278-
'KeyringController:getState',
279-
'SnapController:get',
280-
],
281-
});
282-
}
233+
const mockGetSelectedMultichainAccountActionHandler = jest.fn();
283234

284235
/**
285236
* Sets up the AccountTreeController for testing.
@@ -317,10 +268,7 @@ function setup({
317268
},
318269
}: {
319270
state?: Partial<AccountTreeControllerState>;
320-
messenger?: Messenger<
321-
AccountTreeControllerActions | AllowedActions,
322-
AccountTreeControllerEvents | AllowedEvents
323-
>;
271+
messenger?: ReturnType<typeof getRootMessenger>;
324272
accounts?: InternalAccount[];
325273
keyrings?: KeyringObject[];
326274
config?: {
@@ -338,9 +286,9 @@ function setup({
338286
};
339287
} = {}): {
340288
controller: AccountTreeController;
341-
messenger: Messenger<
342-
AccountTreeControllerActions | AllowedActions,
343-
AccountTreeControllerEvents | AllowedEvents
289+
messenger: ReturnType<typeof getRootMessenger>;
290+
accountTreeControllerMessenger: ReturnType<
291+
typeof getAccountTreeControllerMessenger
344292
>;
345293
spies: {
346294
consoleWarn: jest.SpyInstance;
@@ -401,6 +349,7 @@ function setup({
401349
mocks.AccountsController.listMultichainAccounts.mockImplementation(
402350
() => mocks.AccountsController.accounts,
403351
);
352+
404353
messenger.registerActionHandler(
405354
'AccountsController:listMultichainAccounts',
406355
mocks.AccountsController.listMultichainAccounts,
@@ -474,8 +423,10 @@ function setup({
474423
);
475424
}
476425

426+
const accountTreeControllerMessenger =
427+
getAccountTreeControllerMessenger(messenger);
477428
const controller = new AccountTreeController({
478-
messenger: getAccountTreeControllerMessenger(messenger),
429+
messenger: accountTreeControllerMessenger,
479430
state,
480431
...(config && { config }),
481432
});
@@ -487,6 +438,7 @@ function setup({
487438
return {
488439
controller,
489440
messenger,
441+
accountTreeControllerMessenger,
490442
spies: { consoleWarn: consoleWarnSpy },
491443
mocks,
492444
};
@@ -1802,12 +1754,15 @@ describe('AccountTreeController', () => {
18021754
});
18031755

18041756
it('updates AccountsController selected account (with EVM account) when selectedAccountGroup changes', () => {
1805-
const { controller, messenger } = setup({
1757+
const { controller, accountTreeControllerMessenger } = setup({
18061758
accounts: [MOCK_HD_ACCOUNT_1, MOCK_HD_ACCOUNT_2],
18071759
keyrings: [MOCK_HD_KEYRING_1, MOCK_HD_KEYRING_2],
18081760
});
18091761

1810-
const setSelectedAccountSpy = jest.spyOn(messenger, 'call');
1762+
const setSelectedAccountSpy = jest.spyOn(
1763+
accountTreeControllerMessenger,
1764+
'call',
1765+
);
18111766

18121767
controller.init();
18131768

@@ -1839,15 +1794,18 @@ describe('AccountTreeController', () => {
18391794
},
18401795
},
18411796
} as const;
1842-
const { controller, messenger } = setup({
1797+
const { controller, accountTreeControllerMessenger } = setup({
18431798
accounts: [
18441799
MOCK_HD_ACCOUNT_1,
18451800
nonEvmAccount2, // Wallet 2 > Account 1.
18461801
],
18471802
keyrings: [MOCK_HD_KEYRING_1, MOCK_HD_KEYRING_2],
18481803
});
18491804

1850-
const setSelectedAccountSpy = jest.spyOn(messenger, 'call');
1805+
const setSelectedAccountSpy = jest.spyOn(
1806+
accountTreeControllerMessenger,
1807+
'call',
1808+
);
18511809

18521810
controller.init();
18531811

@@ -1969,18 +1927,14 @@ describe('AccountTreeController', () => {
19691927
});
19701928

19711929
it('falls back to first wallet first group when AccountsController returns EMPTY_ACCOUNT', () => {
1972-
const { controller, messenger } = setup({
1930+
const { controller } = setup({
19731931
accounts: [MOCK_HD_ACCOUNT_1, MOCK_HD_ACCOUNT_2],
19741932
keyrings: [MOCK_HD_KEYRING_1, MOCK_HD_KEYRING_2],
19751933
});
19761934

1977-
// Unregister existing handler and register new one BEFORE init
1978-
messenger.unregisterActionHandler(
1979-
'AccountsController:getSelectedMultichainAccount',
1980-
);
1981-
messenger.registerActionHandler(
1982-
'AccountsController:getSelectedMultichainAccount',
1983-
() => EMPTY_ACCOUNT_MOCK,
1935+
// Mock action handler BEFORE init
1936+
mockGetSelectedMultichainAccountActionHandler.mockReturnValue(
1937+
EMPTY_ACCOUNT_MOCK,
19841938
);
19851939

19861940
controller.init();
@@ -1998,7 +1952,7 @@ describe('AccountTreeController', () => {
19981952
});
19991953

20001954
it('falls back to first wallet first group when selected account is not in tree', () => {
2001-
const { controller, messenger } = setup({
1955+
const { controller } = setup({
20021956
accounts: [MOCK_HD_ACCOUNT_1, MOCK_HD_ACCOUNT_2],
20031957
keyrings: [MOCK_HD_KEYRING_1, MOCK_HD_KEYRING_2],
20041958
});
@@ -2009,12 +1963,8 @@ describe('AccountTreeController', () => {
20091963
id: 'unknown-account-id',
20101964
};
20111965

2012-
messenger.unregisterActionHandler(
2013-
'AccountsController:getSelectedMultichainAccount',
2014-
);
2015-
messenger.registerActionHandler(
2016-
'AccountsController:getSelectedMultichainAccount',
2017-
() => unknownAccount,
1966+
mockGetSelectedMultichainAccountActionHandler.mockReturnValue(
1967+
unknownAccount,
20181968
);
20191969

20201970
controller.init();
@@ -2032,18 +1982,14 @@ describe('AccountTreeController', () => {
20321982
});
20331983

20341984
it('returns empty string when no wallets exist and getSelectedMultichainAccount returns EMPTY_ACCOUNT', () => {
2035-
const { controller, messenger } = setup({
1985+
const { controller } = setup({
20361986
accounts: [],
20371987
keyrings: [],
20381988
});
20391989

2040-
// Mock getSelectedMultichainAccount to return EMPTY_ACCOUNT_MOCK (id is '') BEFORE init
2041-
messenger.unregisterActionHandler(
2042-
'AccountsController:getSelectedMultichainAccount',
2043-
);
2044-
messenger.registerActionHandler(
2045-
'AccountsController:getSelectedMultichainAccount',
2046-
() => EMPTY_ACCOUNT_MOCK,
1990+
// Mock getSelectedAccount to return EMPTY_ACCOUNT_MOCK (id is '') BEFORE init
1991+
mockGetSelectedMultichainAccountActionHandler.mockReturnValue(
1992+
EMPTY_ACCOUNT_MOCK,
20471993
);
20481994

20491995
controller.init();
@@ -4328,7 +4274,7 @@ describe('AccountTreeController', () => {
43284274
deriveStateFromMetadata(
43294275
controller.state,
43304276
controller.metadata,
4331-
'anonymous',
4277+
'includeInDebugSnapshot',
43324278
),
43334279
).toMatchInlineSnapshot(`Object {}`);
43344280
});

0 commit comments

Comments
 (0)