diff --git a/eslint-suppressions.json b/eslint-suppressions.json index 4646a9b2a21..b7493f59e9a 100644 --- a/eslint-suppressions.json +++ b/eslint-suppressions.json @@ -1560,33 +1560,6 @@ "count": 3 } }, - "packages/notification-services-controller/src/NotificationServicesController/NotificationServicesController.test.ts": { - "@typescript-eslint/explicit-function-return-type": { - "count": 23 - }, - "id-length": { - "count": 7 - } - }, - "packages/notification-services-controller/src/NotificationServicesController/NotificationServicesController.ts": { - "@typescript-eslint/explicit-function-return-type": { - "count": 31 - }, - "@typescript-eslint/no-misused-promises": { - "count": 1 - }, - "id-denylist": { - "count": 5 - }, - "id-length": { - "count": 8 - } - }, - "packages/notification-services-controller/src/NotificationServicesController/__fixtures__/mockServices.ts": { - "@typescript-eslint/explicit-function-return-type": { - "count": 6 - } - }, "packages/notification-services-controller/src/NotificationServicesController/constants/notification-schema.ts": { "@typescript-eslint/naming-convention": { "count": 18 diff --git a/packages/notification-services-controller/src/NotificationServicesController/NotificationServicesController.test.ts b/packages/notification-services-controller/src/NotificationServicesController/NotificationServicesController.test.ts index 1870ac086d8..01620f2c603 100644 --- a/packages/notification-services-controller/src/NotificationServicesController/NotificationServicesController.test.ts +++ b/packages/notification-services-controller/src/NotificationServicesController/NotificationServicesController.test.ts @@ -61,12 +61,13 @@ const featureAnnouncementsEnv = { }; // Testing util to clean up verbose logs when testing errors -const mockErrorLog = () => +const mockErrorLog = (): jest.SpyInstance => jest.spyOn(log, 'error').mockImplementation(jest.fn()); -const mockWarnLog = () => jest.spyOn(log, 'warn').mockImplementation(jest.fn()); +const mockWarnLog = (): jest.SpyInstance => + jest.spyOn(log, 'warn').mockImplementation(jest.fn()); // Removing caches to avoid interference -const clearAPICache = () => { +const clearAPICache = (): void => { notificationsConfigCache.clear(); }; @@ -94,11 +95,11 @@ describe('NotificationServicesController', () => { }); describe('init', () => { - const arrangeMocks = () => { + const arrangeMocks = (): ReturnType => { const messengerMocks = mockNotificationMessenger(); jest .spyOn(ControllerUtils, 'toChecksumHexAddress') - .mockImplementation((x) => x); + .mockImplementation((address) => address); return messengerMocks; }; @@ -107,7 +108,7 @@ describe('NotificationServicesController', () => { // eslint-disable-next-line @typescript-eslint/no-explicit-any messenger: any, accounts: string[] = ['0x111', '0x222'], - ) => { + ): Promise => { messenger.publish( 'KeyringController:stateChange', { @@ -119,7 +120,11 @@ describe('NotificationServicesController', () => { const arrangeActAssertKeyringTest = async ( controllerState?: Partial, - ) => { + ): Promise<{ + act: (addresses: string[], assertion: () => void) => Promise; + mockEnable: jest.SpyInstance; + mockDisable: jest.SpyInstance; + }> => { const mocks = arrangeMocks(); const { messenger, globalMessenger, mockKeyringControllerGetState } = mocks; @@ -155,7 +160,10 @@ describe('NotificationServicesController', () => { .spyOn(controller, 'disableAccounts') .mockResolvedValue(); - const act = async (addresses: string[], assertion: () => void) => { + const act = async ( + addresses: string[], + assertion: () => void, + ): Promise => { mockKeyringControllerGetState.mockReturnValue({ isUnlocked: true, keyrings: [ @@ -246,7 +254,9 @@ describe('NotificationServicesController', () => { const arrangeActInitialisePushNotifications = ( modifications?: (mocks: ReturnType) => void, - ) => { + ): ReturnType & { + mockAPIGetNotificationConfig: nock.Scope; + } => { // Arrange const mockAPIGetNotificationConfig = mockGetOnChainNotificationsConfig(); const mocks = arrangeMocks(); @@ -378,7 +388,12 @@ describe('NotificationServicesController', () => { }); describe('createOnChainTriggers', () => { - const arrangeMocks = (overrides?: { mockGetConfig: () => nock.Scope }) => { + const arrangeMocks = (overrides?: { + mockGetConfig: () => nock.Scope; + }): ReturnType & { + mockGetConfig: nock.Scope; + mockUpdateNotifications: nock.Scope; + } => { const messengerMocks = mockNotificationMessenger(); const mockGetConfig = overrides?.mockGetConfig() ?? mockGetOnChainNotificationsConfig(); @@ -532,7 +547,9 @@ describe('NotificationServicesController', () => { }); describe('disableAccounts', () => { - const arrangeMocks = () => { + const arrangeMocks = (): ReturnType & { + mockUpdateNotifications: nock.Scope; + } => { const messengerMocks = mockNotificationMessenger(); const mockUpdateNotifications = mockUpdateOnChainNotifications(); return { ...messengerMocks, mockUpdateNotifications }; @@ -572,7 +589,9 @@ describe('NotificationServicesController', () => { }); describe('enableAccounts', () => { - const arrangeMocks = () => { + const arrangeMocks = (): ReturnType & { + mockUpdateNotifications: nock.Scope; + } => { const messengerMocks = mockNotificationMessenger(); const mockUpdateNotifications = mockUpdateOnChainNotifications(); return { ...messengerMocks, mockUpdateNotifications }; @@ -612,7 +631,17 @@ describe('NotificationServicesController', () => { }); describe('fetchAndUpdateMetamaskNotifications', () => { - const arrangeMocks = () => { + const arrangeMocks = (): ReturnType & { + mockNotificationConfigAPI: nock.Scope; + mockFeatureAnnouncementAPIResult: ReturnType< + typeof createMockFeatureAnnouncementAPIResult + >; + mockFeatureAnnouncementsAPI: nock.Scope; + mockOnChainNotificationsAPIResult: ReturnType< + typeof createMockNotificationEthSent + >[]; + mockOnChainNotificationsAPI: nock.Scope; + } => { const messengerMocks = mockNotificationMessenger(); const mockFeatureAnnouncementAPIResult = @@ -646,7 +675,7 @@ describe('NotificationServicesController', () => { const arrangeController = ( messenger: NotificationServicesControllerMessenger, overrideState?: Partial, - ) => { + ): NotificationServicesController => { const controller = new NotificationServicesController({ messenger, env: { featureAnnouncements: featureAnnouncementsEnv }, @@ -677,18 +706,25 @@ describe('NotificationServicesController', () => { // Should have 1 feature announcement expect( - result.filter((n) => n.type === TRIGGER_TYPES.FEATURES_ANNOUNCEMENT), + result.filter( + (notification) => + notification.type === TRIGGER_TYPES.FEATURES_ANNOUNCEMENT, + ), ).toHaveLength(1); // Should have 1 Wallet Notification expect( - result.filter((n) => n.type === TRIGGER_TYPES.ETH_SENT), + result.filter( + (notification) => notification.type === TRIGGER_TYPES.ETH_SENT, + ), ).toHaveLength(1); // Should have 1 Snap Notification - expect(result.filter((n) => n.type === TRIGGER_TYPES.SNAP)).toHaveLength( - 1, - ); + expect( + result.filter( + (notification) => notification.type === TRIGGER_TYPES.SNAP, + ), + ).toHaveLength(1); // Total notification length = 3 expect(result).toHaveLength(3); @@ -708,9 +744,11 @@ describe('NotificationServicesController', () => { // Should only contain snap notification // As this is not controlled by the global notification switch expect(result).toHaveLength(1); - expect(result.filter((n) => n.type === TRIGGER_TYPES.SNAP)).toHaveLength( - 1, - ); + expect( + result.filter( + (notification) => notification.type === TRIGGER_TYPES.SNAP, + ), + ).toHaveLength(1); // APIs should not have been called expect(mocks.mockFeatureAnnouncementsAPI.isDone()).toBe(false); @@ -727,7 +765,10 @@ describe('NotificationServicesController', () => { // Should not have any feature announcements expect( - result.filter((n) => n.type === TRIGGER_TYPES.FEATURES_ANNOUNCEMENT), + result.filter( + (notification) => + notification.type === TRIGGER_TYPES.FEATURES_ANNOUNCEMENT, + ), ).toHaveLength(0); // Should not have called feature announcement API @@ -895,7 +936,11 @@ describe('NotificationServicesController', () => { }); describe('markMetamaskNotificationsAsRead', () => { - const arrangeMocks = (options?: { onChainMarkAsReadFails: boolean }) => { + const arrangeMocks = (options?: { + onChainMarkAsReadFails: boolean; + }): ReturnType & { + mockMarkAsReadAPI: nock.Scope; + } => { const messengerMocks = mockNotificationMessenger(); const mockMarkAsReadAPI = mockMarkNotificationsAsRead({ @@ -977,7 +1022,12 @@ describe('NotificationServicesController', () => { }); describe('enableMetamaskNotifications', () => { - const arrangeMocks = (overrides?: { mockGetConfig: () => nock.Scope }) => { + const arrangeMocks = (overrides?: { + mockGetConfig: () => nock.Scope; + }): ReturnType & { + mockGetConfig: nock.Scope; + mockUpdateNotifications: nock.Scope; + } => { const messengerMocks = mockNotificationMessenger(); const mockGetConfig = overrides?.mockGetConfig() ?? mockGetOnChainNotificationsConfig(); @@ -1143,7 +1193,9 @@ describe('NotificationServicesController', () => { }); describe('enablePushNotifications', () => { - const arrangeMocks = () => { + const arrangeMocks = (): ReturnType & { + mockGetConfig: nock.Scope; + } => { const messengerMocks = mockNotificationMessenger(); const mockGetConfig = mockGetOnChainNotificationsConfig({ status: 200, @@ -1214,7 +1266,9 @@ describe('NotificationServicesController', () => { }); describe('sendPerpPlaceOrderNotification', () => { - const arrangeMocks = () => { + const arrangeMocks = (): ReturnType & { + mockCreatePerpAPI: nock.Scope; + } => { const messengerMocks = mockNotificationMessenger(); const mockCreatePerpAPI = mockCreatePerpNotification({ status: 200, @@ -1396,8 +1450,10 @@ describe('NotificationServicesController', () => { // Thus this `AnyFunc` can be used to help constrain the generic parameters correctly // eslint-disable-next-line @typescript-eslint/no-explicit-any type AnyFunc = (...args: any[]) => any; -const typedMockAction = () => - jest.fn, Parameters>(); +const typedMockAction = (): jest.Mock< + ReturnType, + Parameters +> => jest.fn, Parameters>(); const controllerName = 'NotificationServicesController'; @@ -1429,7 +1485,17 @@ function getRootMessenger(): RootMessenger { * * @returns mock notification messenger and other messenger mocks */ -function mockNotificationMessenger() { +function mockNotificationMessenger(): { + globalMessenger: RootMessenger; + messenger: NotificationServicesControllerMessenger; + mockGetBearerToken: jest.Mock; + mockIsSignedIn: jest.Mock; + mockAuthPerformSignIn: jest.Mock; + mockDisablePushNotifications: jest.Mock; + mockEnablePushNotifications: jest.Mock; + mockSubscribeToPushNotifications: jest.Mock; + mockKeyringControllerGetState: jest.Mock; +} { const globalMessenger = getRootMessenger(); const messenger = new Messenger< @@ -1568,15 +1634,19 @@ function mockNotificationMessenger() { */ function arrangeFailureAuthAssertions( mocks: ReturnType, -) { +): { + notLoggedIn: () => jest.Mock; + noBearerToken: () => jest.Mock; + rejectedBearerToken: () => jest.Mock; +} { const testScenarios = { - NotLoggedIn: () => mocks.mockIsSignedIn.mockReturnValue(false), + notLoggedIn: (): jest.Mock => mocks.mockIsSignedIn.mockReturnValue(false), // unlikely, but in case it returns null - NoBearerToken: () => + noBearerToken: (): jest.Mock => mocks.mockGetBearerToken.mockResolvedValueOnce(null as unknown as string), - RejectedBearerToken: () => + rejectedBearerToken: (): jest.Mock => mocks.mockGetBearerToken.mockRejectedValueOnce( new Error('MOCK - no bearer token'), ), diff --git a/packages/notification-services-controller/src/NotificationServicesController/NotificationServicesController.ts b/packages/notification-services-controller/src/NotificationServicesController/NotificationServicesController.ts index ed8ad1a41e5..80659ed91f9 100644 --- a/packages/notification-services-controller/src/NotificationServicesController/NotificationServicesController.ts +++ b/packages/notification-services-controller/src/NotificationServicesController/NotificationServicesController.ts @@ -291,11 +291,11 @@ export default class NotificationServicesController extends BaseController< readonly #keyringController = { isUnlocked: false, - setupLockedStateSubscriptions: (onUnlock: () => Promise) => { + setupLockedStateSubscriptions: (onUnlock: () => Promise): void => { const { isUnlocked } = this.messenger.call('KeyringController:getState'); this.#keyringController.isUnlocked = isUnlocked; - this.messenger.subscribe('KeyringController:unlock', () => { + this.messenger.subscribe('KeyringController:unlock', (): void => { this.#keyringController.isUnlocked = true; // messaging system cannot await promises // we don't need to wait for a result on this. @@ -303,22 +303,22 @@ export default class NotificationServicesController extends BaseController< onUnlock(); }); - this.messenger.subscribe('KeyringController:lock', () => { + this.messenger.subscribe('KeyringController:lock', (): void => { this.#keyringController.isUnlocked = false; }); }, }; readonly #auth = { - getBearerToken: async () => { + getBearerToken: async (): Promise => { return await this.messenger.call( 'AuthenticationController:getBearerToken', ); }, - isSignedIn: () => { + isSignedIn: (): boolean => { return this.messenger.call('AuthenticationController:isSignedIn'); }, - signIn: async () => { + signIn: async (): Promise => { return await this.messenger.call( 'AuthenticationController:performSignIn', ); @@ -331,40 +331,40 @@ export default class NotificationServicesController extends BaseController< // To ensure we subscribe to the most up-to-date notifications isSetup: false, - subscribeToPushNotifications: async () => { + subscribeToPushNotifications: async (): Promise => { await this.messenger.call( 'NotificationServicesPushController:subscribeToPushNotifications', ); }, - enablePushNotifications: async (addresses: string[]) => { + enablePushNotifications: async (addresses: string[]): Promise => { try { await this.messenger.call( 'NotificationServicesPushController:enablePushNotifications', addresses, ); - } catch (e) { - log.error('Silently failed to enable push notifications', e); + } catch (error) { + log.error('Silently failed to enable push notifications', error); } }, - disablePushNotifications: async () => { + disablePushNotifications: async (): Promise => { try { await this.messenger.call( 'NotificationServicesPushController:disablePushNotifications', ); - } catch (e) { - log.error('Silently failed to disable push notifications', e); + } catch (error) { + log.error('Silently failed to disable push notifications', error); } }, - subscribe: () => { + subscribe: (): void => { this.messenger.subscribe( 'NotificationServicesPushController:onNewNotifications', - (notification) => { + (notification): void => { // eslint-disable-next-line @typescript-eslint/no-floating-promises this.updateMetamaskNotificationsList(notification); }, ); }, - initializePushNotifications: async () => { + initializePushNotifications: async (): Promise => { if (!this.state.isNotificationServicesEnabled) { return; } @@ -394,10 +394,10 @@ export default class NotificationServicesController extends BaseController< // Flag to ensure we only setup once isNotificationAccountsSetup: false, - getNotificationAccounts: () => { + getNotificationAccounts: (): string[] | null => { const { keyrings } = this.messenger.call('KeyringController:getState'); const firstHDKeyring = keyrings.find( - (k) => k.type === KeyringTypes.hd.toString(), + (keyring) => keyring.type === KeyringTypes.hd.toString(), ); const keyringAccounts = firstHDKeyring?.accounts ?? null; return keyringAccounts; @@ -408,7 +408,11 @@ export default class NotificationServicesController extends BaseController< * * @returns addresses removed, added, and latest list of addresses */ - listAccounts: () => { + listAccounts: (): { + accountsAdded: string[]; + accountsRemoved: string[]; + accounts: string[]; + } => { // Get previous and current account sets const nonChecksumAccounts = this.#accounts.getNotificationAccounts(); if (!nonChecksumAccounts) { @@ -420,8 +424,8 @@ export default class NotificationServicesController extends BaseController< } const accounts = nonChecksumAccounts - .map((a) => toChecksumHexAddress(a)) - .filter((a) => isValidHexAddress(a)); + .map((address) => toChecksumHexAddress(address)) + .filter((address) => isValidHexAddress(address)); const currentAccountsSet = new Set(accounts); const prevAccountsSet = new Set(this.state.subscriptionAccountsSeen); @@ -436,9 +440,11 @@ export default class NotificationServicesController extends BaseController< } // Calculate added and removed addresses - const accountsAdded = accounts.filter((a) => !prevAccountsSet.has(a)); + const accountsAdded = accounts.filter( + (account) => !prevAccountsSet.has(account), + ); const accountsRemoved = [...prevAccountsSet.values()].filter( - (a) => !currentAccountsSet.has(a), + (account) => !currentAccountsSet.has(account), ); // Update accounts seen @@ -471,11 +477,12 @@ export default class NotificationServicesController extends BaseController< * We can call the `listAccounts` defined above to find out about any accounts added, removed * And call effects to subscribe/unsubscribe to notifications. */ - subscribe: () => { + subscribe: (): void => { this.messenger.subscribe( 'KeyringController:stateChange', - - async (totalAccounts, prevTotalAccounts) => { + // Using void return for async callback - result is intentionally ignored + // eslint-disable-next-line @typescript-eslint/no-misused-promises + async (totalAccounts, prevTotalAccounts): Promise => { const hasTotalAccountsChanged = totalAccounts !== prevTotalAccounts; if ( !this.state.isNotificationServicesEnabled || @@ -544,17 +551,19 @@ export default class NotificationServicesController extends BaseController< }); this.#featureAnnouncementEnv = env.featureAnnouncements; - this.#locale = env.locale ?? (() => 'en'); + this.#locale = env.locale ?? ((): string => 'en'); this.#env = env.env ?? 'prd'; this.#registerMessageHandlers(); this.#clearLoadingStates(); } - init() { - this.#keyringController.setupLockedStateSubscriptions(async () => { - this.#accounts.initialize(); - await this.#pushNotifications.initializePushNotifications(); - }); + init(): void { + this.#keyringController.setupLockedStateSubscriptions( + async (): Promise => { + this.#accounts.initialize(); + await this.#pushNotifications.initializePushNotifications(); + }, + ); this.#accounts.initialize(); // eslint-disable-next-line @typescript-eslint/no-floating-promises @@ -594,7 +603,7 @@ export default class NotificationServicesController extends BaseController< }); } - #assertAuthEnabled() { + #assertAuthEnabled(): void { if (!this.#auth.isSignedIn()) { this.update((state) => { state.isNotificationServicesEnabled = false; @@ -603,14 +612,14 @@ export default class NotificationServicesController extends BaseController< } } - async #enableAuth() { + async #enableAuth(): Promise { const isSignedIn = this.#auth.isSignedIn(); if (!isSignedIn) { await this.#auth.signIn(); } } - async #getBearerToken() { + async #getBearerToken(): Promise<{ bearerToken: string }> { this.#assertAuthEnabled(); const bearerToken = await this.#auth.getBearerToken(); @@ -634,7 +643,7 @@ export default class NotificationServicesController extends BaseController< */ #setIsUpdatingMetamaskNotifications( isUpdatingMetamaskNotifications: boolean, - ) { + ): void { this.update((state) => { state.isUpdatingMetamaskNotifications = isUpdatingMetamaskNotifications; }); @@ -650,7 +659,7 @@ export default class NotificationServicesController extends BaseController< */ #setIsFetchingMetamaskNotifications( isFetchingMetamaskNotifications: boolean, - ) { + ): void { this.update((state) => { state.isFetchingMetamaskNotifications = isFetchingMetamaskNotifications; }); @@ -665,7 +674,7 @@ export default class NotificationServicesController extends BaseController< * * @param isCheckingAccountsPresence - A boolean value indicating whether the account presence check is currently active. */ - #setIsCheckingAccountsPresence(isCheckingAccountsPresence: boolean) { + #setIsCheckingAccountsPresence(isCheckingAccountsPresence: boolean): void { this.update((state) => { state.isCheckingAccountsPresence = isCheckingAccountsPresence; }); @@ -677,7 +686,7 @@ export default class NotificationServicesController extends BaseController< * * @param accounts - The accounts being updated. */ - #updateUpdatingAccountsState(accounts: string[]) { + #updateUpdatingAccountsState(accounts: string[]): void { this.update((state) => { const uniqueAccounts = new Set([ ...state.isUpdatingMetamaskNotificationsAccount, @@ -692,7 +701,7 @@ export default class NotificationServicesController extends BaseController< * * @param accounts - The accounts that have finished updating. */ - #clearUpdatingAccountsState(accounts: string[]) { + #clearUpdatingAccountsState(accounts: string[]): void { this.update((state) => { state.isUpdatingMetamaskNotificationsAccount = state.isUpdatingMetamaskNotificationsAccount.filter( @@ -704,7 +713,7 @@ export default class NotificationServicesController extends BaseController< /** * Public method to expose enabling push notifications */ - public async enablePushNotifications() { + public async enablePushNotifications(): Promise { try { const { bearerToken } = await this.#getBearerToken(); const { accounts } = this.#accounts.listAccounts(); @@ -714,20 +723,20 @@ export default class NotificationServicesController extends BaseController< this.#env, ); const addresses = addressesWithNotifications - .filter((a) => Boolean(a.enabled)) - .map((a) => a.address); + .filter((addressConfig) => Boolean(addressConfig.enabled)) + .map((addressConfig) => addressConfig.address); if (addresses.length > 0) { await this.#pushNotifications.enablePushNotifications(addresses); } - } catch (e) { - log.error('Failed to enable push notifications', e); + } catch (error) { + log.error('Failed to enable push notifications', error); } } /** * Public method to expose disabling push notifications */ - public async disablePushNotifications() { + public async disablePushNotifications(): Promise { await this.#pushNotifications.disablePushNotifications(); } @@ -769,13 +778,13 @@ export default class NotificationServicesController extends BaseController< */ public async setFeatureAnnouncementsEnabled( featureAnnouncementsEnabled: boolean, - ) { + ): Promise { try { - this.update((s) => { - s.isFeatureAnnouncementsEnabled = featureAnnouncementsEnabled; + this.update((state) => { + state.isFeatureAnnouncementsEnabled = featureAnnouncementsEnabled; }); - } catch (e) { - log.error('Unable to toggle feature announcements', e); + } catch (error) { + log.error('Unable to toggle feature announcements', error); throw new Error('Unable to toggle feature announcements'); } } @@ -811,8 +820,8 @@ export default class NotificationServicesController extends BaseController< // Notifications API can return array with addresses set to false // So assert that at least one address is enabled let accountsWithNotifications = addressesWithNotifications - .filter((a) => Boolean(a.enabled)) - .map((a) => a.address); + .filter((addressConfig) => Boolean(addressConfig.enabled)) + .map((addressConfig) => addressConfig.address); // 2. Enable Notifications (if no accounts subscribed or we are resetting) if (accountsWithNotifications.length === 0 || opts?.resetNotifications) { @@ -844,8 +853,8 @@ export default class NotificationServicesController extends BaseController< state.isMetamaskNotificationsFeatureSeen = true; } }); - } catch (err) { - log.error('Failed to create On Chain triggers', err); + } catch (error) { + log.error('Failed to create On Chain triggers', error); throw new Error('Failed to create On Chain triggers'); } finally { this.#setIsUpdatingMetamaskNotifications(false); @@ -858,13 +867,13 @@ export default class NotificationServicesController extends BaseController< * * @throws {Error} If there is an error during the process of enabling notifications. */ - public async enableMetamaskNotifications() { + public async enableMetamaskNotifications(): Promise { try { this.#setIsUpdatingMetamaskNotifications(true); await this.#enableAuth(); await this.createOnChainTriggers(); - } catch (e) { - log.error('Unable to enable notifications', e); + } catch (error) { + log.error('Unable to enable notifications', error); throw new Error('Unable to enable notifications'); } finally { this.#setIsUpdatingMetamaskNotifications(false); @@ -879,7 +888,7 @@ export default class NotificationServicesController extends BaseController< * * @throws {Error} If the user is not authenticated or if there is an error during the process. */ - public async disableNotificationServices() { + public async disableNotificationServices(): Promise { this.#setIsUpdatingMetamaskNotifications(true); // Attempt Disable Push Notifications @@ -930,8 +939,8 @@ export default class NotificationServicesController extends BaseController< accounts.map((address) => ({ address, enabled: false })), this.#env, ); - } catch (err) { - log.error('Failed to delete OnChain triggers', err); + } catch (error) { + log.error('Failed to delete OnChain triggers', error); throw new Error('Failed to delete OnChain triggers'); } finally { this.#clearUpdatingAccountsState(accounts); @@ -963,8 +972,8 @@ export default class NotificationServicesController extends BaseController< accounts.map((address) => ({ address, enabled: true })), this.#env, ); - } catch (err) { - log.error('Failed to update OnChain triggers', err); + } catch (error) { + log.error('Failed to update OnChain triggers', error); throw new Error('Failed to update OnChain triggers'); } finally { this.#clearUpdatingAccountsState(accounts); @@ -1013,8 +1022,8 @@ export default class NotificationServicesController extends BaseController< this.#env, ) ) - .filter((a) => Boolean(a.enabled)) - .map((a) => a.address); + .filter((addressConfig) => Boolean(addressConfig.enabled)) + .map((addressConfig) => addressConfig.address); const notifications = await getAPINotifications( bearerToken, addressesWithNotifications, @@ -1045,8 +1054,9 @@ export default class NotificationServicesController extends BaseController< // Sort Notifications metamaskNotifications.sort( - (a, b) => - new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime(), + (notificationA, notificationB) => + new Date(notificationB.createdAt).getTime() - + new Date(notificationA.createdAt).getTime(), ); // Update State @@ -1061,9 +1071,9 @@ export default class NotificationServicesController extends BaseController< this.#setIsFetchingMetamaskNotifications(false); return metamaskNotifications; - } catch (err) { + } catch (error) { this.#setIsFetchingMetamaskNotifications(false); - log.error('Failed to fetch notifications', err); + log.error('Failed to fetch notifications', error); throw new Error('Failed to fetch notifications'); } } @@ -1075,7 +1085,7 @@ export default class NotificationServicesController extends BaseController< * @returns An array of notifications of the passed in type. * @throws Throws an error if an invalid trigger type is passed. */ - public getNotificationsByType(type: TRIGGER_TYPES) { + public getNotificationsByType(type: TRIGGER_TYPES): INotification[] { assert( Object.values(TRIGGER_TYPES).includes(type), 'Invalid trigger type.', @@ -1093,7 +1103,7 @@ export default class NotificationServicesController extends BaseController< * * @param id - The id of the notification to delete. */ - public async deleteNotificationById(id: string) { + public async deleteNotificationById(id: string): Promise { const fetchedNotification = this.state.metamaskNotificationsList.find( (notification) => notification.id === id, ); @@ -1130,7 +1140,7 @@ export default class NotificationServicesController extends BaseController< * * @param ids - The ids of the notifications to delete. */ - public async deleteNotificationsById(ids: string[]) { + public async deleteNotificationsById(ids: string[]): Promise { for (const id of ids) { await this.deleteNotificationById(id); } @@ -1216,8 +1226,8 @@ export default class NotificationServicesController extends BaseController< (notification) => notification.id, ); } - } catch (err) { - log.warn('Something failed when marking notifications as read', err); + } catch (error) { + log.warn('Something failed when marking notifications as read', error); } // Update the state (state is also used on counter & badge) @@ -1268,7 +1278,9 @@ export default class NotificationServicesController extends BaseController< notification: INotification, ): Promise { if ( - this.state.metamaskNotificationsList.some((n) => n.id === notification.id) + this.state.metamaskNotificationsList.some( + (existingNotification) => existingNotification.id === notification.id, + ) ) { return; } @@ -1278,7 +1290,9 @@ export default class NotificationServicesController extends BaseController< if (processedNotification) { this.update((state) => { const existingNotificationIds = new Set( - state.metamaskNotificationsList.map((n) => n.id), + state.metamaskNotificationsList.map( + (existingNotification) => existingNotification.id, + ), ); // Add the new notification only if its ID is not already present in the list if (!existingNotificationIds.has(processedNotification.id)) { @@ -1302,7 +1316,9 @@ export default class NotificationServicesController extends BaseController< * * @param input perp input */ - public async sendPerpPlaceOrderNotification(input: OrderInput) { + public async sendPerpPlaceOrderNotification( + input: OrderInput, + ): Promise { try { const { bearerToken } = await this.#getBearerToken(); await createPerpOrderNotification(bearerToken, input); diff --git a/packages/notification-services-controller/src/NotificationServicesController/__fixtures__/mockServices.ts b/packages/notification-services-controller/src/NotificationServicesController/__fixtures__/mockServices.ts index 206b6bb5e97..44ac409c51b 100644 --- a/packages/notification-services-controller/src/NotificationServicesController/__fixtures__/mockServices.ts +++ b/packages/notification-services-controller/src/NotificationServicesController/__fixtures__/mockServices.ts @@ -16,7 +16,7 @@ type MockReply = { export const mockFetchFeatureAnnouncementNotifications = ( mockReply?: MockReply, -) => { +): nock.Scope => { const mockResponse = getMockFeatureAnnouncementResponse(); const reply = mockReply ?? { status: 200, body: mockResponse.response }; const mockEndpoint = nock(mockResponse.url) @@ -27,7 +27,9 @@ export const mockFetchFeatureAnnouncementNotifications = ( return mockEndpoint; }; -export const mockUpdateOnChainNotifications = (mockReply?: MockReply) => { +export const mockUpdateOnChainNotifications = ( + mockReply?: MockReply, +): nock.Scope => { const mockResponse = getMockUpdateOnChainNotifications(); const reply = mockReply ?? { status: 204 }; @@ -38,7 +40,9 @@ export const mockUpdateOnChainNotifications = (mockReply?: MockReply) => { return mockEndpoint; }; -export const mockGetOnChainNotificationsConfig = (mockReply?: MockReply) => { +export const mockGetOnChainNotificationsConfig = ( + mockReply?: MockReply, +): nock.Scope => { const mockResponse = getMockOnChainNotificationsConfig(); const reply = mockReply ?? { status: 200, body: mockResponse.response }; @@ -49,7 +53,7 @@ export const mockGetOnChainNotificationsConfig = (mockReply?: MockReply) => { return mockEndpoint; }; -export const mockGetAPINotifications = (mockReply?: MockReply) => { +export const mockGetAPINotifications = (mockReply?: MockReply): nock.Scope => { const mockResponse = getMockListNotificationsResponse(); const reply = mockReply ?? { status: 200, body: mockResponse.response }; @@ -61,7 +65,9 @@ export const mockGetAPINotifications = (mockReply?: MockReply) => { return mockEndpoint; }; -export const mockMarkNotificationsAsRead = (mockReply?: MockReply) => { +export const mockMarkNotificationsAsRead = ( + mockReply?: MockReply, +): nock.Scope => { const mockResponse = getMockMarkNotificationsAsReadResponse(); const reply = mockReply ?? { status: 200 }; @@ -72,7 +78,9 @@ export const mockMarkNotificationsAsRead = (mockReply?: MockReply) => { return mockEndpoint; }; -export const mockCreatePerpNotification = (mockReply?: MockReply) => { +export const mockCreatePerpNotification = ( + mockReply?: MockReply, +): nock.Scope => { const mockResponse = getMockCreatePerpOrderNotification(); const reply = mockReply ?? { status: 201 }; const mockEndpoint = nock(mockResponse.url)