Skip to content

Commit 827f7f5

Browse files
committed
refactor: migrate {AccountActivity,BackendWebSocket}Service to @metamask/messenger
1 parent 73a5aad commit 827f7f5

File tree

10 files changed

+160
-101
lines changed

10 files changed

+160
-101
lines changed

packages/core-backend/CHANGELOG.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,18 @@ 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` ([#6821](https://github.com/MetaMask/core/pull/6821))
13+
- Previously, `AccountActivityService` and `BackendWebSocketService` accepted a `RestrictedMessenger` instance from `@metamask/base-controller`.
14+
15+
### Removed
16+
17+
- **BREAKING:** Remove exported type aliases and constants that were specific to controller messenger integration ([#6821](https://github.com/MetaMask/core/pull/6821))
18+
- Removed type exports: `BackendWebSocketServiceAllowedActions`, `BackendWebSocketServiceAllowedEvents`, `AccountActivityServiceAllowedActions`, `AccountActivityServiceAllowedEvents`
19+
- Removed constant exports: `ACCOUNT_ACTIVITY_SERVICE_ALLOWED_ACTIONS`, `ACCOUNT_ACTIVITY_SERVICE_ALLOWED_EVENTS`
20+
- These types and constants were internal implementation details that should not have been exposed. Consumers should use the service-specific messenger types directly.
21+
1022
## [1.0.1]
1123

1224
### Changed

packages/core-backend/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,8 @@
4747
"test:watch": "NODE_OPTIONS=--experimental-vm-modules jest --watch"
4848
},
4949
"dependencies": {
50-
"@metamask/base-controller": "^8.4.1",
5150
"@metamask/controller-utils": "^11.14.1",
51+
"@metamask/messenger": "^0.3.0",
5252
"@metamask/profile-sync-controller": "^25.1.1",
5353
"@metamask/utils": "^11.8.1",
5454
"uuid": "^8.3.2"

packages/core-backend/src/AccountActivityService.test.ts

Lines changed: 82 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,37 @@
1-
import { Messenger } from '@metamask/base-controller';
21
import type { InternalAccount } from '@metamask/keyring-internal-api';
2+
import {
3+
Messenger,
4+
MOCK_ANY_NAMESPACE,
5+
type MessengerActions,
6+
type MessengerEvents,
7+
type MockAnyNamespace,
8+
} from '@metamask/messenger';
39
import type { Hex } from '@metamask/utils';
410
import nock, { isDone } from 'nock';
511

6-
import type {
7-
AccountActivityServiceAllowedEvents,
8-
AccountActivityServiceAllowedActions,
9-
} from './AccountActivityService';
1012
import {
1113
AccountActivityService,
1214
type AccountActivityServiceMessenger,
1315
type SubscriptionOptions,
14-
ACCOUNT_ACTIVITY_SERVICE_ALLOWED_ACTIONS,
15-
ACCOUNT_ACTIVITY_SERVICE_ALLOWED_EVENTS,
1616
} from './AccountActivityService';
1717
import type { ServerNotificationMessage } from './BackendWebSocketService';
1818
import { WebSocketState } from './BackendWebSocketService';
1919
import type { Transaction, BalanceUpdate } from './types';
2020
import type { AccountActivityMessage } from './types';
2121
import { flushPromises } from '../../../tests/helpers';
2222

23+
type AllAccountActivityServiceActions =
24+
MessengerActions<AccountActivityServiceMessenger>;
25+
26+
type AllAccountActivityServiceEvents =
27+
MessengerEvents<AccountActivityServiceMessenger>;
28+
29+
type RootMessenger = Messenger<
30+
MockAnyNamespace,
31+
AllAccountActivityServiceActions,
32+
AllAccountActivityServiceEvents
33+
>;
34+
2335
// Helper function for completing async operations
2436
const completeAsyncOperations = async (timeoutMs = 0) => {
2537
await flushPromises();
@@ -49,25 +61,70 @@ const createMockInternalAccount = (options: {
4961
scopes: ['eip155:1'], // Required scopes property
5062
});
5163

64+
/**
65+
* Creates and returns a root messenger for testing
66+
*
67+
* @returns A messenger instance
68+
*/
69+
function getRootMessenger(): RootMessenger {
70+
return new Messenger({
71+
namespace: MOCK_ANY_NAMESPACE,
72+
});
73+
}
74+
5275
/**
5376
* Creates a real messenger with registered mock actions for testing
5477
* Each call creates a completely independent messenger to ensure test isolation
5578
*
5679
* @returns Object containing the messenger and mock action functions
5780
*/
58-
const getMessenger = () => {
81+
const getMessenger = (): {
82+
rootMessenger: RootMessenger;
83+
messenger: AccountActivityServiceMessenger;
84+
mocks: {
85+
getSelectedAccount: jest.Mock;
86+
connect: jest.Mock;
87+
disconnect: jest.Mock;
88+
subscribe: jest.Mock;
89+
channelHasSubscription: jest.Mock;
90+
getSubscriptionsByChannel: jest.Mock;
91+
findSubscriptionsByChannelPrefix: jest.Mock;
92+
addChannelCallback: jest.Mock;
93+
removeChannelCallback: jest.Mock;
94+
};
95+
} => {
5996
// Use any types for the root messenger to avoid complex type constraints in tests
6097
// Create a unique root messenger for each test
61-
const rootMessenger = new Messenger<
62-
AccountActivityServiceAllowedActions,
63-
AccountActivityServiceAllowedEvents
64-
>();
65-
const messenger: AccountActivityServiceMessenger =
66-
rootMessenger.getRestricted({
67-
name: 'AccountActivityService',
68-
allowedActions: [...ACCOUNT_ACTIVITY_SERVICE_ALLOWED_ACTIONS],
69-
allowedEvents: [...ACCOUNT_ACTIVITY_SERVICE_ALLOWED_EVENTS],
70-
});
98+
const rootMessenger = getRootMessenger();
99+
const messenger: AccountActivityServiceMessenger = new Messenger<
100+
'AccountActivityService',
101+
AllAccountActivityServiceActions,
102+
AllAccountActivityServiceEvents,
103+
RootMessenger
104+
>({
105+
namespace: 'AccountActivityService',
106+
parent: rootMessenger,
107+
});
108+
109+
rootMessenger.delegate({
110+
actions: [
111+
'AccountsController:getSelectedAccount',
112+
'BackendWebSocketService:connect',
113+
'BackendWebSocketService:disconnect',
114+
'BackendWebSocketService:subscribe',
115+
'BackendWebSocketService:getConnectionInfo',
116+
'BackendWebSocketService:channelHasSubscription',
117+
'BackendWebSocketService:getSubscriptionsByChannel',
118+
'BackendWebSocketService:findSubscriptionsByChannelPrefix',
119+
'BackendWebSocketService:addChannelCallback',
120+
'BackendWebSocketService:removeChannelCallback',
121+
],
122+
events: [
123+
'AccountsController:selectedAccountChange',
124+
'BackendWebSocketService:connectionStateChanged',
125+
],
126+
messenger,
127+
});
71128

72129
// Create mock action handlers
73130
const mockGetSelectedAccount = jest.fn();
@@ -216,10 +273,7 @@ type WithServiceOptions = {
216273
type WithServiceCallback<ReturnValue> = (payload: {
217274
service: AccountActivityService;
218275
messenger: AccountActivityServiceMessenger;
219-
rootMessenger: Messenger<
220-
AccountActivityServiceAllowedActions,
221-
AccountActivityServiceAllowedEvents
222-
>;
276+
rootMessenger: RootMessenger;
223277
mocks: {
224278
getSelectedAccount: jest.Mock;
225279
connect: jest.Mock;
@@ -633,7 +687,7 @@ describe('AccountActivityService', () => {
633687
});
634688

635689
// Publish WebSocket ERROR state event - will be picked up by controller subscription
636-
await rootMessenger.publish(
690+
rootMessenger.publish(
637691
'BackendWebSocketService:connectionStateChanged',
638692
{
639693
state: WebSocketState.ERROR,
@@ -686,7 +740,7 @@ describe('AccountActivityService', () => {
686740
});
687741

688742
// Publish account change event - will be picked up by controller subscription
689-
await rootMessenger.publish(
743+
rootMessenger.publish(
690744
'AccountsController:selectedAccountChange',
691745
solanaAccount,
692746
);
@@ -716,7 +770,7 @@ describe('AccountActivityService', () => {
716770
});
717771

718772
// Publish account change event - will be picked up by controller subscription
719-
await rootMessenger.publish(
773+
rootMessenger.publish(
720774
'AccountsController:selectedAccountChange',
721775
unknownAccount,
722776
);
@@ -738,7 +792,7 @@ describe('AccountActivityService', () => {
738792
mocks.getSelectedAccount.mockReturnValue(null);
739793

740794
// Publish WebSocket connection event - will be picked up by controller subscription
741-
await rootMessenger.publish(
795+
rootMessenger.publish(
742796
'BackendWebSocketService:connectionStateChanged',
743797
{
744798
state: WebSocketState.CONNECTED,
@@ -805,7 +859,7 @@ describe('AccountActivityService', () => {
805859
});
806860

807861
// Publish account change event on root messenger
808-
await rootMessenger.publish(
862+
rootMessenger.publish(
809863
'AccountsController:selectedAccountChange',
810864
newAccount,
811865
);
@@ -843,7 +897,7 @@ describe('AccountActivityService', () => {
843897
});
844898

845899
// Publish account change event on root messenger
846-
await rootMessenger.publish(
900+
rootMessenger.publish(
847901
'AccountsController:selectedAccountChange',
848902
newAccount,
849903
);

packages/core-backend/src/AccountActivityService.ts

Lines changed: 6 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ import type {
99
AccountsControllerGetSelectedAccountAction,
1010
AccountsControllerSelectedAccountChangeEvent,
1111
} from '@metamask/accounts-controller';
12-
import type { RestrictedMessenger } from '@metamask/base-controller';
1312
import type { InternalAccount } from '@metamask/keyring-internal-api';
13+
import type { Messenger } from '@metamask/messenger';
1414

1515
import type { AccountActivityServiceMethodActions } from './AccountActivityService-method-action-types';
1616
import type {
@@ -119,27 +119,7 @@ export type AccountActivityServiceOptions = {
119119
// Action types for the messaging system - using generated method actions
120120
export type AccountActivityServiceActions = AccountActivityServiceMethodActions;
121121

122-
// Allowed actions that AccountActivityService can call on other controllers
123-
export const ACCOUNT_ACTIVITY_SERVICE_ALLOWED_ACTIONS = [
124-
'AccountsController:getSelectedAccount',
125-
'BackendWebSocketService:connect',
126-
'BackendWebSocketService:disconnect',
127-
'BackendWebSocketService:subscribe',
128-
'BackendWebSocketService:getConnectionInfo',
129-
'BackendWebSocketService:channelHasSubscription',
130-
'BackendWebSocketService:getSubscriptionsByChannel',
131-
'BackendWebSocketService:findSubscriptionsByChannelPrefix',
132-
'BackendWebSocketService:addChannelCallback',
133-
'BackendWebSocketService:removeChannelCallback',
134-
] as const;
135-
136-
// Allowed events that AccountActivityService can listen to
137-
export const ACCOUNT_ACTIVITY_SERVICE_ALLOWED_EVENTS = [
138-
'AccountsController:selectedAccountChange',
139-
'BackendWebSocketService:connectionStateChanged',
140-
] as const;
141-
142-
export type AccountActivityServiceAllowedActions =
122+
type AllowedActions =
143123
| AccountsControllerGetSelectedAccountAction
144124
| BackendWebSocketServiceMethodActions;
145125

@@ -176,16 +156,14 @@ export type AccountActivityServiceEvents =
176156
| AccountActivityServiceSubscriptionErrorEvent
177157
| AccountActivityServiceStatusChangedEvent;
178158

179-
export type AccountActivityServiceAllowedEvents =
159+
export type AllowedEvents =
180160
| AccountsControllerSelectedAccountChangeEvent
181161
| BackendWebSocketServiceConnectionStateChangedEvent;
182162

183-
export type AccountActivityServiceMessenger = RestrictedMessenger<
163+
export type AccountActivityServiceMessenger = Messenger<
184164
typeof SERVICE_NAME,
185-
AccountActivityServiceActions | AccountActivityServiceAllowedActions,
186-
AccountActivityServiceEvents | AccountActivityServiceAllowedEvents,
187-
AccountActivityServiceAllowedActions['type'],
188-
AccountActivityServiceAllowedEvents['type']
165+
AccountActivityServiceActions | AllowedActions,
166+
AccountActivityServiceEvents | AllowedEvents
189167
>;
190168

191169
// =============================================================================

packages/core-backend/src/BackendWebSocketService.test.ts

Lines changed: 47 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,17 @@
1-
import { Messenger } from '@metamask/base-controller';
1+
import {
2+
Messenger,
3+
MOCK_ANY_NAMESPACE,
4+
type MessengerActions,
5+
type MessengerEvents,
6+
type MockAnyNamespace,
7+
} from '@metamask/messenger';
28

39
import {
410
BackendWebSocketService,
511
getCloseReason,
612
WebSocketState,
713
type BackendWebSocketServiceOptions,
814
type BackendWebSocketServiceMessenger,
9-
type BackendWebSocketServiceAllowedActions,
10-
type BackendWebSocketServiceAllowedEvents,
1115
} from './BackendWebSocketService';
1216
import { flushPromises } from '../../../tests/helpers';
1317

@@ -18,6 +22,18 @@ import { flushPromises } from '../../../tests/helpers';
1822
// Type for global object with WebSocket mock
1923
type GlobalWithWebSocket = typeof global & { lastWebSocket: MockWebSocket };
2024

25+
type AllBackendWebSocketServiceActions =
26+
MessengerActions<BackendWebSocketServiceMessenger>;
27+
28+
type AllBackendWebSocketServiceEvents =
29+
MessengerEvents<BackendWebSocketServiceMessenger>;
30+
31+
type RootMessenger = Messenger<
32+
MockAnyNamespace,
33+
AllBackendWebSocketServiceActions,
34+
AllBackendWebSocketServiceEvents
35+
>;
36+
2137
// =====================================================
2238
// MOCK WEBSOCKET CLASS
2339
// =====================================================
@@ -149,6 +165,17 @@ class MockWebSocket extends EventTarget {
149165
// TEST UTILITIES & MOCKS
150166
// =====================================================
151167

168+
/**
169+
* Creates and returns a root messenger for testing
170+
*
171+
* @returns A messenger instance
172+
*/
173+
function getRootMessenger(): RootMessenger {
174+
return new Messenger({
175+
namespace: MOCK_ANY_NAMESPACE,
176+
});
177+
}
178+
152179
/**
153180
* Creates a real messenger with registered mock actions for testing
154181
* Each call creates a completely independent messenger to ensure test isolation
@@ -157,15 +184,21 @@ class MockWebSocket extends EventTarget {
157184
*/
158185
const getMessenger = () => {
159186
// Create a unique root messenger for each test
160-
const rootMessenger = new Messenger<
161-
BackendWebSocketServiceAllowedActions,
162-
BackendWebSocketServiceAllowedEvents
163-
>();
164-
const messenger = rootMessenger.getRestricted({
165-
name: 'BackendWebSocketService',
166-
allowedActions: ['AuthenticationController:getBearerToken'],
167-
allowedEvents: ['AuthenticationController:stateChange'],
168-
}) as unknown as BackendWebSocketServiceMessenger;
187+
const rootMessenger = getRootMessenger();
188+
const messenger = new Messenger<
189+
'BackendWebSocketService',
190+
AllBackendWebSocketServiceActions,
191+
AllBackendWebSocketServiceEvents,
192+
RootMessenger
193+
>({
194+
namespace: 'BackendWebSocketService',
195+
parent: rootMessenger,
196+
});
197+
rootMessenger.delegate({
198+
actions: ['AuthenticationController:getBearerToken'],
199+
events: ['AuthenticationController:stateChange'],
200+
messenger,
201+
});
169202

170203
// Create mock action handlers
171204
const mockGetBearerToken = jest.fn().mockResolvedValue('valid-default-token');
@@ -234,10 +267,7 @@ type TestSetupOptions = {
234267
type TestSetup = {
235268
service: BackendWebSocketService;
236269
messenger: BackendWebSocketServiceMessenger;
237-
rootMessenger: Messenger<
238-
BackendWebSocketServiceAllowedActions,
239-
BackendWebSocketServiceAllowedEvents
240-
>;
270+
rootMessenger: RootMessenger;
241271
mocks: {
242272
getBearerToken: jest.Mock;
243273
};
@@ -256,10 +286,7 @@ type TestSetup = {
256286
type WithServiceCallback<ReturnValue> = (payload: {
257287
service: BackendWebSocketService;
258288
messenger: BackendWebSocketServiceMessenger;
259-
rootMessenger: Messenger<
260-
BackendWebSocketServiceAllowedActions,
261-
BackendWebSocketServiceAllowedEvents
262-
>;
289+
rootMessenger: RootMessenger;
263290
mocks: {
264291
getBearerToken: jest.Mock;
265292
};

0 commit comments

Comments
 (0)