Skip to content

Commit de05bad

Browse files
authored
Merge branch 'main' into cryptodev2s/docs/add-interactive-release-mode
2 parents c9823c1 + 94d55d8 commit de05bad

File tree

2 files changed

+83
-57
lines changed

2 files changed

+83
-57
lines changed

packages/notification-services-controller/src/NotificationServicesController/NotificationServicesController.test.ts

Lines changed: 55 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -69,26 +69,6 @@ const mockErrorLog = () =>
6969
const mockWarnLog = () => jest.spyOn(log, 'warn').mockImplementation(jest.fn());
7070

7171
describe('metamask-notifications - constructor()', () => {
72-
const arrangeMocks = () => {
73-
const messengerMocks = mockNotificationMessenger();
74-
jest
75-
.spyOn(ControllerUtils, 'toChecksumHexAddress')
76-
.mockImplementation((x) => x);
77-
78-
return messengerMocks;
79-
};
80-
81-
const actPublishKeyringStateChange = async (
82-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
83-
messenger: any,
84-
) => {
85-
messenger.publish(
86-
'KeyringController:stateChange',
87-
{} as KeyringControllerState,
88-
[],
89-
);
90-
};
91-
9272
it('initializes state & override state', () => {
9373
const controller1 = new NotificationServicesController({
9474
messenger: mockNotificationMessenger().messenger,
@@ -108,16 +88,39 @@ describe('metamask-notifications - constructor()', () => {
10888
expect(controller2.state.isFeatureAnnouncementsEnabled).toBe(true);
10989
expect(controller2.state.isNotificationServicesEnabled).toBe(true);
11090
});
91+
});
92+
93+
describe('metamask-notifications - init()', () => {
94+
const arrangeMocks = () => {
95+
const messengerMocks = mockNotificationMessenger();
96+
jest
97+
.spyOn(ControllerUtils, 'toChecksumHexAddress')
98+
.mockImplementation((x) => x);
99+
100+
return messengerMocks;
101+
};
102+
103+
const actPublishKeyringStateChange = async (
104+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
105+
messenger: any,
106+
) => {
107+
messenger.publish(
108+
'KeyringController:stateChange',
109+
{} as KeyringControllerState,
110+
[],
111+
);
112+
};
111113

112114
it('keyring Change Event but feature not enabled will not add or remove triggers', async () => {
113-
const { messenger, globalMessenger, mockListAccounts } = arrangeMocks();
115+
const { messenger, globalMessenger, mockWithKeyring } = arrangeMocks();
114116

115117
// initialize controller with 1 address
116-
mockListAccounts.mockResolvedValueOnce([ADDRESS_1]);
118+
mockWithKeyring.mockResolvedValueOnce([ADDRESS_1]);
117119
const controller = new NotificationServicesController({
118120
messenger,
119121
env: { featureAnnouncements: featureAnnouncementsEnv },
120122
});
123+
controller.init();
121124

122125
const mockUpdate = jest
123126
.spyOn(controller, 'updateOnChainTriggersByAccount')
@@ -127,15 +130,15 @@ describe('metamask-notifications - constructor()', () => {
127130
.mockResolvedValue({} as UserStorage);
128131

129132
// listAccounts has a new address
130-
mockListAccounts.mockResolvedValueOnce([ADDRESS_1, ADDRESS_2]);
133+
mockWithKeyring.mockResolvedValueOnce([ADDRESS_1, ADDRESS_2]);
131134
await actPublishKeyringStateChange(globalMessenger);
132135

133136
expect(mockUpdate).not.toHaveBeenCalled();
134137
expect(mockDelete).not.toHaveBeenCalled();
135138
});
136139

137140
it('keyring Change Event with new triggers will update triggers correctly', async () => {
138-
const { messenger, globalMessenger, mockListAccounts } = arrangeMocks();
141+
const { messenger, globalMessenger, mockWithKeyring } = arrangeMocks();
139142

140143
// initialize controller with 1 address
141144
const controller = new NotificationServicesController({
@@ -146,6 +149,7 @@ describe('metamask-notifications - constructor()', () => {
146149
subscriptionAccountsSeen: [ADDRESS_1],
147150
},
148151
});
152+
controller.init();
149153

150154
const mockUpdate = jest
151155
.spyOn(controller, 'updateOnChainTriggersByAccount')
@@ -155,7 +159,7 @@ describe('metamask-notifications - constructor()', () => {
155159
.mockResolvedValue({} as UserStorage);
156160

157161
const act = async (addresses: string[], assertion: () => void) => {
158-
mockListAccounts.mockResolvedValueOnce(addresses);
162+
mockWithKeyring.mockResolvedValueOnce(addresses);
159163
await actPublishKeyringStateChange(globalMessenger);
160164
await waitFor(() => {
161165
assertion();
@@ -184,9 +188,9 @@ describe('metamask-notifications - constructor()', () => {
184188
expect(mockDelete).toHaveBeenCalled();
185189
});
186190

187-
// If the address is added back to the list, because it is seen we won't update
191+
// If the address is added back to the list, we will perform an update
188192
await act([ADDRESS_1, ADDRESS_2], () => {
189-
expect(mockUpdate).not.toHaveBeenCalled();
193+
expect(mockUpdate).toHaveBeenCalled();
190194
expect(mockDelete).not.toHaveBeenCalled();
191195
});
192196
});
@@ -199,12 +203,14 @@ describe('metamask-notifications - constructor()', () => {
199203
modifications?.(mocks);
200204

201205
// Act
202-
new NotificationServicesController({
206+
const controller = new NotificationServicesController({
203207
messenger: mocks.messenger,
204208
env: { featureAnnouncements: featureAnnouncementsEnv },
205209
state: { isNotificationServicesEnabled: true },
206210
});
207211

212+
controller.init();
213+
208214
return mocks;
209215
};
210216

@@ -287,7 +293,7 @@ describe('metamask-notifications - constructor()', () => {
287293
modifications?.(mocks);
288294

289295
// Act
290-
new NotificationServicesController({
296+
const controller = new NotificationServicesController({
291297
messenger: mocks.messenger,
292298
env: {
293299
featureAnnouncements: featureAnnouncementsEnv,
@@ -296,46 +302,49 @@ describe('metamask-notifications - constructor()', () => {
296302
state: { isNotificationServicesEnabled: true },
297303
});
298304

305+
controller.init();
306+
299307
return mocks;
300308
};
301309

302310
it('should initialse accounts to track notifications on', async () => {
303-
const { mockListAccounts } =
311+
const { mockWithKeyring } =
304312
arrangeActInitialiseNotificationAccountTracking();
305313
await waitFor(() => {
306-
expect(mockListAccounts).toHaveBeenCalled();
314+
expect(mockWithKeyring).toHaveBeenCalled();
307315
});
308316
});
309317

310318
it('should not initialise accounts if wallet is locked', async () => {
311-
const { mockListAccounts } =
312-
arrangeActInitialiseNotificationAccountTracking((mocks) => {
319+
const { mockWithKeyring } = arrangeActInitialiseNotificationAccountTracking(
320+
(mocks) => {
313321
mocks.mockKeyringControllerGetState.mockReturnValue({
314322
isUnlocked: false,
315323
} as MockVar);
316-
});
324+
},
325+
);
317326
await waitFor(() => {
318-
expect(mockListAccounts).not.toHaveBeenCalled();
327+
expect(mockWithKeyring).not.toHaveBeenCalled();
319328
});
320329
});
321330

322331
it('should re-initialise if the wallet was locked, and then unlocked', async () => {
323332
// Test Wallet Locked
324-
const { globalMessenger, mockListAccounts } =
333+
const { globalMessenger, mockWithKeyring } =
325334
arrangeActInitialiseNotificationAccountTracking((mocks) => {
326335
mocks.mockKeyringControllerGetState.mockReturnValue({
327336
isUnlocked: false,
328337
} as MockVar);
329338
});
330339
await waitFor(() => {
331-
expect(mockListAccounts).not.toHaveBeenCalled();
340+
expect(mockWithKeyring).not.toHaveBeenCalled();
332341
});
333342

334343
// Test Wallet Unlock
335344
jest.clearAllMocks();
336345
globalMessenger.publish('KeyringController:unlock');
337346
await waitFor(() => {
338-
expect(mockListAccounts).toHaveBeenCalled();
347+
expect(mockWithKeyring).toHaveBeenCalled();
339348
});
340349
});
341350
});
@@ -927,7 +936,7 @@ describe('metamask-notifications - enableMetamaskNotifications()', () => {
927936

928937
it('should sign a user in if not already signed in', async () => {
929938
const mocks = arrangeMocks();
930-
mocks.mockListAccounts.mockResolvedValue([ADDRESS_1]);
939+
mocks.mockWithKeyring.mockResolvedValue([ADDRESS_1]);
931940
mocks.mockIsSignedIn.mockReturnValue(false); // mock that auth is not enabled
932941
const controller = new NotificationServicesController({
933942
messenger: mocks.messenger,
@@ -943,7 +952,7 @@ describe('metamask-notifications - enableMetamaskNotifications()', () => {
943952

944953
it('create new notifications when switched on and no new notifications', async () => {
945954
const mocks = arrangeMocks();
946-
mocks.mockListAccounts.mockResolvedValue([ADDRESS_1]);
955+
mocks.mockWithKeyring.mockResolvedValue([ADDRESS_1]);
947956
const controller = new NotificationServicesController({
948957
messenger: mocks.messenger,
949958
env: { featureAnnouncements: featureAnnouncementsEnv },
@@ -966,7 +975,7 @@ describe('metamask-notifications - enableMetamaskNotifications()', () => {
966975

967976
it('not create new notifications when enabling an account already in storage', async () => {
968977
const mocks = arrangeMocks();
969-
mocks.mockListAccounts.mockResolvedValue([ADDRESS_1]);
978+
mocks.mockWithKeyring.mockResolvedValue([ADDRESS_1]);
970979
const userStorage = createMockFullUserStorage({ address: ADDRESS_1 });
971980
mocks.mockPerformGetStorage.mockResolvedValue(JSON.stringify(userStorage));
972981
const controller = new NotificationServicesController({
@@ -1153,7 +1162,7 @@ function mockNotificationMessenger() {
11531162
const messenger = globalMessenger.getRestricted({
11541163
name: 'NotificationServicesController',
11551164
allowedActions: [
1156-
'KeyringController:getAccounts',
1165+
'KeyringController:withKeyring',
11571166
'KeyringController:getState',
11581167
'AuthenticationController:getBearerToken',
11591168
'AuthenticationController:isSignedIn',
@@ -1175,7 +1184,7 @@ function mockNotificationMessenger() {
11751184
],
11761185
});
11771186

1178-
const mockListAccounts =
1187+
const mockWithKeyring =
11791188
typedMockAction<KeyringControllerGetAccountsAction>().mockResolvedValue([]);
11801189

11811190
const mockGetBearerToken =
@@ -1230,8 +1239,8 @@ function mockNotificationMessenger() {
12301239
// eslint-disable-next-line @typescript-eslint/no-explicit-any
12311240
const [, ...params]: any[] = args;
12321241

1233-
if (actionType === 'KeyringController:getAccounts') {
1234-
return mockListAccounts();
1242+
if (actionType === 'KeyringController:withKeyring') {
1243+
return mockWithKeyring();
12351244
}
12361245

12371246
if (actionType === 'KeyringController:getState') {
@@ -1299,7 +1308,7 @@ function mockNotificationMessenger() {
12991308
return {
13001309
globalMessenger,
13011310
messenger,
1302-
mockListAccounts,
1311+
mockWithKeyring,
13031312
mockGetBearerToken,
13041313
mockIsSignedIn,
13051314
mockAuthPerformSignIn,

packages/notification-services-controller/src/NotificationServicesController/NotificationServicesController.ts

Lines changed: 28 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,13 @@ import {
99
isValidHexAddress,
1010
toChecksumHexAddress,
1111
} from '@metamask/controller-utils';
12-
import type {
13-
KeyringControllerGetAccountsAction,
14-
KeyringControllerStateChangeEvent,
15-
KeyringControllerGetStateAction,
16-
KeyringControllerLockEvent,
17-
KeyringControllerUnlockEvent,
12+
import {
13+
type KeyringControllerStateChangeEvent,
14+
type KeyringControllerGetStateAction,
15+
type KeyringControllerLockEvent,
16+
type KeyringControllerUnlockEvent,
17+
type KeyringControllerWithKeyringAction,
18+
KeyringTypes,
1819
} from '@metamask/keyring-controller';
1920
import type {
2021
AuthenticationController,
@@ -199,7 +200,7 @@ export type Actions =
199200
// Allowed Actions
200201
export type AllowedActions =
201202
// Keyring Controller Requests
202-
| KeyringControllerGetAccountsAction
203+
| KeyringControllerWithKeyringAction
203204
| KeyringControllerGetStateAction
204205
// Auth Controller Requests
205206
| AuthenticationController.AuthenticationControllerGetBearerToken
@@ -408,16 +409,30 @@ export default class NotificationServicesController extends BaseController<
408409
// Flag to ensure we only setup once
409410
isNotificationAccountsSetup: false,
410411

412+
getNotificationAccounts: async () => {
413+
const mainHDWalletAccounts = (await this.messagingSystem.call(
414+
'KeyringController:withKeyring',
415+
{
416+
type: KeyringTypes.hd,
417+
index: 0,
418+
},
419+
async ({ keyring }): Promise<string[]> => {
420+
return await keyring.getAccounts();
421+
},
422+
)) as string[];
423+
424+
return mainHDWalletAccounts;
425+
},
426+
411427
/**
412428
* Used to get list of addresses from keyring (wallet addresses)
413429
*
414430
* @returns addresses removed, added, and latest list of addresses
415431
*/
416432
listAccounts: async () => {
417433
// Get previous and current account sets
418-
const nonChecksumAccounts = await this.messagingSystem.call(
419-
'KeyringController:getAccounts',
420-
);
434+
const nonChecksumAccounts =
435+
await this.#accounts.getNotificationAccounts();
421436
const accounts = nonChecksumAccounts
422437
.map((a) => toChecksumHexAddress(a))
423438
.filter((a) => isValidHexAddress(a));
@@ -442,7 +457,7 @@ export default class NotificationServicesController extends BaseController<
442457

443458
// Update accounts seen
444459
this.update((state) => {
445-
state.subscriptionAccountsSeen = [...prevAccountsSet, ...accountsAdded];
460+
state.subscriptionAccountsSeen = [...currentAccountsSet];
446461
});
447462

448463
return {
@@ -530,7 +545,9 @@ export default class NotificationServicesController extends BaseController<
530545
this.#featureAnnouncementEnv = env.featureAnnouncements;
531546
this.#registerMessageHandlers();
532547
this.#clearLoadingStates();
548+
}
533549

550+
init() {
534551
this.#keyringController.setupLockedStateSubscriptions(async () => {
535552
await this.#accounts.initialize();
536553
await this.#pushNotifications.initializePushNotifications();

0 commit comments

Comments
 (0)