Skip to content

Commit b4c76ed

Browse files
refactor: migrate MultichainAccountService to @metamask/messenger (#6544)
## 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 `MultichainAccountService` to the new `@metamask/messenger` message bus, 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 <!-- CURSOR_SUMMARY --> --- > [!NOTE] > Migrate `MultichainAccountService` and tests from `@metamask/base-controller` messenger to the new `@metamask/messenger`, updating types, helpers, configs, and dependencies. > > - **Multichain Account Service (BREAKING)** > - Replace `RestrictedMessenger` from `@metamask/base-controller` with new `Messenger` from `@metamask/messenger` in `src/types.ts` and all usages. > - Add `RootMessenger` test helper and implement delegation-based `getMultichainAccountServiceMessenger` in `src/tests/messenger.ts`. > - Update tests to use `rootMessenger` for `registerActionHandler`/`publish` and pass restricted messenger to providers/service. > - **Dependencies/Config** > - Add dependency `@metamask/messenger` to `packages/multichain-account-service/package.json` and reference it in `tsconfig*.json`. > - Update README dependency graph to include `multichain_account_service --> messenger`. > - **Changelog** > - Document breaking change: service now uses `@metamask/messenger` and expects its `Messenger` type. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit b90d0ca. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY --> --------- Co-authored-by: Michele Esposito <michele@esposito.codes>
1 parent 5f863de commit b4c76ed

15 files changed

+132
-166
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,7 @@ linkStyle default opacity:0.5
262262
message_manager --> controller_utils;
263263
message_manager --> messenger;
264264
multichain_account_service --> base_controller;
265+
multichain_account_service --> messenger;
265266
multichain_account_service --> accounts_controller;
266267
multichain_account_service --> keyring_controller;
267268
multichain_api_middleware --> chain_agnostic_permission;

packages/multichain-account-service/CHANGELOG.md

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

1010
### Changed
1111

12+
- **BREAKING:** Use new `Messenger` from `@metamask/messenger` ([#6544](https://github.com/MetaMask/core/pull/6544))
13+
- Previously, `MultichainAccountService` accepted a `RestrictedMessenger` instance from `@metamask/base-controller`.
1214
- Bump `@metamask/eth-snap-keyring` from `^17.0.0` to `^18.0.0` ([#6951](https://github.com/MetaMask/core/pull/6951))
1315

1416
## [1.6.2]

packages/multichain-account-service/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
"@metamask/keyring-internal-api": "^9.0.0",
5656
"@metamask/keyring-snap-client": "^8.0.0",
5757
"@metamask/keyring-utils": "^3.1.0",
58+
"@metamask/messenger": "^0.3.0",
5859
"@metamask/snaps-sdk": "^9.0.0",
5960
"@metamask/snaps-utils": "^11.0.0",
6061
"@metamask/superstruct": "^3.1.0",

packages/multichain-account-service/src/MultichainAccountGroup.test.ts

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import {
55
toMultichainAccountGroupId,
66
toMultichainAccountWalletId,
77
} from '@metamask/account-api';
8-
import type { Messenger } from '@metamask/base-controller';
98
import { EthScope, SolScope } from '@metamask/keyring-api';
109
import type { InternalAccount } from '@metamask/keyring-internal-api';
1110

@@ -22,13 +21,8 @@ import {
2221
setupNamedAccountProvider,
2322
getMultichainAccountServiceMessenger,
2423
getRootMessenger,
24+
type RootMessenger,
2525
} from './tests';
26-
import type {
27-
AllowedActions,
28-
AllowedEvents,
29-
MultichainAccountServiceActions,
30-
MultichainAccountServiceEvents,
31-
} from './types';
3226

3327
function setup({
3428
groupIndex = 0,
@@ -44,10 +38,7 @@ function setup({
4438
],
4539
}: {
4640
groupIndex?: number;
47-
messenger?: Messenger<
48-
MultichainAccountServiceActions | AllowedActions,
49-
MultichainAccountServiceEvents | AllowedEvents
50-
>;
41+
messenger?: RootMessenger;
5142
accounts?: InternalAccount[][];
5243
} = {}): {
5344
wallet: MultichainAccountWallet<Bip44Account<InternalAccount>>;

packages/multichain-account-service/src/MultichainAccountService.test.ts

Lines changed: 55 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
/* eslint-disable jsdoc/require-jsdoc */
22

3-
import type { Messenger } from '@metamask/base-controller';
43
import { mnemonicPhraseToBytes } from '@metamask/key-tree';
54
import type { KeyringAccount } from '@metamask/keyring-api';
65
import { EthAccountType, SolAccountType } from '@metamask/keyring-api';
@@ -37,14 +36,9 @@ import {
3736
makeMockAccountProvider,
3837
mockAsInternalAccount,
3938
setupNamedAccountProvider,
39+
type RootMessenger,
4040
} from './tests';
41-
import type {
42-
AllowedActions,
43-
AllowedEvents,
44-
MultichainAccountServiceActions,
45-
MultichainAccountServiceEvents,
46-
MultichainAccountServiceMessenger,
47-
} from './types';
41+
import type { MultichainAccountServiceMessenger } from './types';
4842

4943
// Mock providers.
5044
jest.mock('./providers/EvmAccountProvider', () => {
@@ -93,25 +87,19 @@ function mockAccountProvider<Provider extends NamedAccountProvider>(
9387
}
9488

9589
function setup({
96-
messenger = getRootMessenger(),
90+
rootMessenger = getRootMessenger(),
9791
keyrings = [MOCK_HD_KEYRING_1, MOCK_HD_KEYRING_2],
9892
accounts,
9993
providerConfigs,
10094
}: {
101-
messenger?: Messenger<
102-
MultichainAccountServiceActions | AllowedActions,
103-
MultichainAccountServiceEvents | AllowedEvents
104-
>;
95+
rootMessenger?: RootMessenger;
10596
keyrings?: KeyringObject[];
10697
accounts?: KeyringAccount[];
10798
providerConfigs?: MultichainAccountServiceOptions['providerConfigs'];
10899
} = {}): {
109100
service: MultichainAccountService;
110-
serviceMessenger: MultichainAccountServiceMessenger;
111-
messenger: Messenger<
112-
MultichainAccountServiceActions | AllowedActions,
113-
MultichainAccountServiceEvents | AllowedEvents
114-
>;
101+
rootMessenger: RootMessenger;
102+
messenger: MultichainAccountServiceMessenger;
115103
mocks: Mocks;
116104
} {
117105
const mocks: Mocks = {
@@ -136,17 +124,17 @@ function setup({
136124
keyrings: mocks.KeyringController.keyrings,
137125
}));
138126

139-
messenger.registerActionHandler(
127+
rootMessenger.registerActionHandler(
140128
'KeyringController:getState',
141129
mocks.KeyringController.getState,
142130
);
143131

144-
messenger.registerActionHandler(
132+
rootMessenger.registerActionHandler(
145133
'KeyringController:getKeyringsByType',
146134
mocks.KeyringController.getKeyringsByType,
147135
);
148136

149-
messenger.registerActionHandler(
137+
rootMessenger.registerActionHandler(
150138
'KeyringController:addNewKeyring',
151139
mocks.KeyringController.addNewKeyring,
152140
);
@@ -156,7 +144,7 @@ function setup({
156144
() => accounts,
157145
);
158146

159-
messenger.registerActionHandler(
147+
rootMessenger.registerActionHandler(
160148
'AccountsController:listMultichainAccounts',
161149
mocks.AccountsController.listMultichainAccounts,
162150
);
@@ -180,14 +168,21 @@ function setup({
180168
);
181169
}
182170

183-
const serviceMessenger = getMultichainAccountServiceMessenger(messenger);
171+
const messenger = getMultichainAccountServiceMessenger(rootMessenger);
172+
184173
const service = new MultichainAccountService({
185-
messenger: serviceMessenger,
174+
messenger,
186175
providerConfigs,
187176
});
177+
188178
service.init();
189179

190-
return { service, serviceMessenger, messenger, mocks };
180+
return {
181+
service,
182+
rootMessenger,
183+
messenger,
184+
mocks,
185+
};
191186
}
192187

193188
describe('MultichainAccountService', () => {
@@ -216,17 +211,17 @@ describe('MultichainAccountService', () => {
216211
},
217212
};
218213

219-
const { mocks, serviceMessenger } = setup({
214+
const { mocks, messenger } = setup({
220215
accounts: [MOCK_HD_ACCOUNT_1, MOCK_SOL_ACCOUNT_1],
221216
providerConfigs,
222217
});
223218

224219
expect(mocks.EvmAccountProvider.constructor).toHaveBeenCalledWith(
225-
serviceMessenger,
220+
messenger,
226221
providerConfigs[EvmAccountProvider.NAME],
227222
);
228223
expect(mocks.SolAccountProvider.constructor).toHaveBeenCalledWith(
229-
serviceMessenger,
224+
messenger,
230225
providerConfigs[SolAccountProvider.NAME],
231226
);
232227
});
@@ -249,17 +244,17 @@ describe('MultichainAccountService', () => {
249244
// No `EVM_ACCOUNT_PROVIDER_NAME`, cause it's optional in this test.
250245
};
251246

252-
const { mocks, serviceMessenger } = setup({
247+
const { mocks, messenger } = setup({
253248
accounts: [MOCK_HD_ACCOUNT_1, MOCK_SOL_ACCOUNT_1],
254249
providerConfigs,
255250
});
256251

257252
expect(mocks.EvmAccountProvider.constructor).toHaveBeenCalledWith(
258-
serviceMessenger,
253+
messenger,
259254
undefined,
260255
);
261256
expect(mocks.SolAccountProvider.constructor).toHaveBeenCalledWith(
262-
serviceMessenger,
257+
messenger,
263258
providerConfigs[SolAccountProvider.NAME],
264259
);
265260
});
@@ -474,7 +469,7 @@ describe('MultichainAccountService', () => {
474469

475470
it('syncs the appropriate wallet and update reverse mapping on AccountsController:accountAdded', () => {
476471
const accounts = [account1, account3]; // No `account2` for now.
477-
const { service, messenger, mocks } = setup({ accounts, keyrings });
472+
const { service, rootMessenger, mocks } = setup({ accounts, keyrings });
478473

479474
const wallet1 = service.getMultichainAccountWallet({
480475
entropySource: entropy1,
@@ -483,7 +478,7 @@ describe('MultichainAccountService', () => {
483478

484479
// Now we're adding `account2`.
485480
mocks.EvmAccountProvider.accounts = [account1, account2];
486-
messenger.publish(
481+
rootMessenger.publish(
487482
'AccountsController:accountAdded',
488483
mockAsInternalAccount(account2),
489484
);
@@ -514,7 +509,7 @@ describe('MultichainAccountService', () => {
514509
.get();
515510

516511
const accounts = [account1]; // No `otherAccount1` for now.
517-
const { service, messenger, mocks } = setup({ accounts, keyrings });
512+
const { service, rootMessenger, mocks } = setup({ accounts, keyrings });
518513

519514
const wallet1 = service.getMultichainAccountWallet({
520515
entropySource: entropy1,
@@ -523,7 +518,7 @@ describe('MultichainAccountService', () => {
523518

524519
// Now we're adding `account2`.
525520
mocks.EvmAccountProvider.accounts = [account1, otherAccount1];
526-
messenger.publish(
521+
rootMessenger.publish(
527522
'AccountsController:accountAdded',
528523
mockAsInternalAccount(otherAccount1),
529524
);
@@ -555,12 +550,12 @@ describe('MultichainAccountService', () => {
555550
.get();
556551

557552
const accounts = [account1]; // No `otherAccount1` for now.
558-
const { messenger, mocks } = setup({ accounts, keyrings });
553+
const { rootMessenger, messenger, mocks } = setup({ accounts, keyrings });
559554
const publishSpy = jest.spyOn(messenger, 'publish');
560555

561556
// Now we're adding `otherAccount1` to an existing group.
562557
mocks.EvmAccountProvider.accounts = [account1, otherAccount1];
563-
messenger.publish(
558+
rootMessenger.publish(
564559
'AccountsController:accountAdded',
565560
mockAsInternalAccount(otherAccount1),
566561
);
@@ -574,7 +569,7 @@ describe('MultichainAccountService', () => {
574569

575570
it('creates new detected wallets and update reverse mapping on AccountsController:accountAdded', () => {
576571
const accounts = [account1, account2]; // No `account3` for now (associated with "Wallet 2").
577-
const { service, messenger, mocks } = setup({
572+
const { service, rootMessenger, mocks } = setup({
578573
accounts,
579574
keyrings: [keyring1],
580575
});
@@ -592,7 +587,7 @@ describe('MultichainAccountService', () => {
592587
// Now we're adding `account3`.
593588
mocks.KeyringController.keyrings = [keyring1, keyring2];
594589
mocks.EvmAccountProvider.accounts = [account1, account2, account3];
595-
messenger.publish(
590+
rootMessenger.publish(
596591
'AccountsController:accountAdded',
597592
mockAsInternalAccount(account3),
598593
);
@@ -616,7 +611,10 @@ describe('MultichainAccountService', () => {
616611

617612
it('ignores non-BIP-44 accounts on AccountsController:accountAdded', () => {
618613
const accounts = [account1];
619-
const { service, messenger } = setup({ accounts, keyrings });
614+
const { service, rootMessenger } = setup({
615+
accounts,
616+
keyrings,
617+
});
620618

621619
const wallet1 = service.getMultichainAccountWallet({
622620
entropySource: entropy1,
@@ -626,7 +624,7 @@ describe('MultichainAccountService', () => {
626624
expect(oldMultichainAccounts[0].getAccounts()).toHaveLength(1);
627625

628626
// Now we're publishing a new account that is not BIP-44 compatible.
629-
messenger.publish(
627+
rootMessenger.publish(
630628
'AccountsController:accountAdded',
631629
mockAsInternalAccount(MOCK_SNAP_ACCOUNT_2),
632630
);
@@ -638,7 +636,7 @@ describe('MultichainAccountService', () => {
638636

639637
it('syncs the appropriate wallet and update reverse mapping on AccountsController:accountRemoved', () => {
640638
const accounts = [account1, account2];
641-
const { service, messenger, mocks } = setup({ accounts, keyrings });
639+
const { service, rootMessenger, mocks } = setup({ accounts, keyrings });
642640

643641
const wallet1 = service.getMultichainAccountWallet({
644642
entropySource: entropy1,
@@ -647,7 +645,7 @@ describe('MultichainAccountService', () => {
647645

648646
// Now we're removing `account2`.
649647
mocks.EvmAccountProvider.accounts = [account1];
650-
messenger.publish('AccountsController:accountRemoved', account2.id);
648+
rootMessenger.publish('AccountsController:accountRemoved', account2.id);
651649
expect(wallet1.getMultichainAccountGroups()).toHaveLength(1);
652650

653651
const walletAndMultichainAccount2 = service.getAccountContext(
@@ -681,7 +679,9 @@ describe('MultichainAccountService', () => {
681679
.withGroupIndex(0)
682680
.get();
683681

684-
const { service, messenger } = setup({ accounts: [mockEvmAccount] });
682+
const { service, messenger } = setup({
683+
accounts: [mockEvmAccount],
684+
});
685685
const publishSpy = jest.spyOn(messenger, 'publish');
686686

687687
const nextGroup = await service.createNextMultichainAccountGroup({
@@ -735,7 +735,9 @@ describe('MultichainAccountService', () => {
735735
.withGroupIndex(0)
736736
.get();
737737

738-
const { service, messenger } = setup({ accounts: [mockEvmAccount] });
738+
const { service, messenger } = setup({
739+
accounts: [mockEvmAccount],
740+
});
739741
const publishSpy = jest.spyOn(messenger, 'publish');
740742

741743
const group = await service.createMultichainAccountGroup({
@@ -926,7 +928,9 @@ describe('MultichainAccountService', () => {
926928
});
927929

928930
it('sets basic functionality with MultichainAccountService:setBasicFunctionality', async () => {
929-
const { messenger } = setup({ accounts: [MOCK_HD_ACCOUNT_1] });
931+
const { messenger } = setup({
932+
accounts: [MOCK_HD_ACCOUNT_1],
933+
});
930934

931935
// This tests the action handler registration
932936
expect(
@@ -986,11 +990,13 @@ describe('MultichainAccountService', () => {
986990
let solProvider: SolAccountProvider;
987991

988992
beforeEach(() => {
989-
const { messenger } = setup({ accounts: [MOCK_HD_ACCOUNT_1] });
993+
const { rootMessenger } = setup({
994+
accounts: [MOCK_HD_ACCOUNT_1],
995+
});
990996

991997
// Create actual SolAccountProvider instance for wrapping
992998
solProvider = new SolAccountProvider(
993-
getMultichainAccountServiceMessenger(messenger),
999+
getMultichainAccountServiceMessenger(rootMessenger),
9941000
);
9951001

9961002
// Spy on the provider methods
@@ -1001,7 +1007,7 @@ describe('MultichainAccountService', () => {
10011007
jest.spyOn(solProvider, 'isAccountCompatible');
10021008

10031009
wrapper = new AccountProviderWrapper(
1004-
getMultichainAccountServiceMessenger(messenger),
1010+
getMultichainAccountServiceMessenger(rootMessenger),
10051011
solProvider,
10061012
);
10071013
});

0 commit comments

Comments
 (0)