@metamask-previews/notification-services-controller 26.0.1-preview-acb2929f3 → 26.0.1-preview-e3275932a

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (24) hide show
  1. package/CHANGELOG.md +0 -18
  2. package/dist/NotificationServicesController/NotificationServicesController.cjs +112 -128
  3. package/dist/NotificationServicesController/NotificationServicesController.cjs.map +1 -1
  4. package/dist/NotificationServicesController/NotificationServicesController.d.cts.map +1 -1
  5. package/dist/NotificationServicesController/NotificationServicesController.d.mts.map +1 -1
  6. package/dist/NotificationServicesController/NotificationServicesController.mjs +113 -129
  7. package/dist/NotificationServicesController/NotificationServicesController.mjs.map +1 -1
  8. package/dist/NotificationServicesController/mocks/mockResponses.cjs +1 -9
  9. package/dist/NotificationServicesController/mocks/mockResponses.cjs.map +1 -1
  10. package/dist/NotificationServicesController/mocks/mockResponses.d.cts +0 -1
  11. package/dist/NotificationServicesController/mocks/mockResponses.d.cts.map +1 -1
  12. package/dist/NotificationServicesController/mocks/mockResponses.d.mts +0 -1
  13. package/dist/NotificationServicesController/mocks/mockResponses.d.mts.map +1 -1
  14. package/dist/NotificationServicesController/mocks/mockResponses.mjs +1 -8
  15. package/dist/NotificationServicesController/mocks/mockResponses.mjs.map +1 -1
  16. package/dist/NotificationServicesController/services/api-notifications.cjs +4 -43
  17. package/dist/NotificationServicesController/services/api-notifications.cjs.map +1 -1
  18. package/dist/NotificationServicesController/services/api-notifications.d.cts +2 -23
  19. package/dist/NotificationServicesController/services/api-notifications.d.cts.map +1 -1
  20. package/dist/NotificationServicesController/services/api-notifications.d.mts +2 -23
  21. package/dist/NotificationServicesController/services/api-notifications.d.mts.map +1 -1
  22. package/dist/NotificationServicesController/services/api-notifications.mjs +3 -40
  23. package/dist/NotificationServicesController/services/api-notifications.mjs.map +1 -1
  24. package/package.json +1 -1
@@ -9,7 +9,7 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
9
9
  if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
10
10
  return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
11
11
  };
12
- var _NotificationServicesController_instances, _NotificationServicesController_keyringController, _NotificationServicesController_auth, _NotificationServicesController_pushNotifications, _NotificationServicesController_accounts, _NotificationServicesController_locale, _NotificationServicesController_featureAnnouncementEnv, _NotificationServicesController_env, _NotificationServicesController_clearLoadingStates, _NotificationServicesController_assertAuthEnabled, _NotificationServicesController_enableAuth, _NotificationServicesController_getBearerToken, _NotificationServicesController_isWalletActivityPushEnabled, _NotificationServicesController_registerPushNotifications, _NotificationServicesController_setIsUpdatingMetamaskNotifications, _NotificationServicesController_setIsFetchingMetamaskNotifications, _NotificationServicesController_setIsCheckingAccountsPresence, _NotificationServicesController_updateUpdatingAccountsState, _NotificationServicesController_clearUpdatingAccountsState;
12
+ var _NotificationServicesController_instances, _NotificationServicesController_keyringController, _NotificationServicesController_auth, _NotificationServicesController_pushNotifications, _NotificationServicesController_accounts, _NotificationServicesController_locale, _NotificationServicesController_featureAnnouncementEnv, _NotificationServicesController_env, _NotificationServicesController_clearLoadingStates, _NotificationServicesController_assertAuthEnabled, _NotificationServicesController_enableAuth, _NotificationServicesController_getBearerToken, _NotificationServicesController_registerWalletActivityAddresses, _NotificationServicesController_setIsUpdatingMetamaskNotifications, _NotificationServicesController_setIsFetchingMetamaskNotifications, _NotificationServicesController_setIsCheckingAccountsPresence, _NotificationServicesController_updateUpdatingAccountsState, _NotificationServicesController_clearUpdatingAccountsState;
13
13
  function $importDefault(module) {
14
14
  if (module?.__esModule) {
15
15
  return module.default;
@@ -26,7 +26,7 @@ import $log from "loglevel";
26
26
  const log = $importDefault($log);
27
27
  import { TRIGGER_TYPES } from "./constants/notification-schema.mjs";
28
28
  import { processAndFilterNotifications, safeProcessNotification } from "./processors/process-notifications.mjs";
29
- import { getAPINotifications, getNotificationsApiConfigCached, markNotificationsAsRead, updateOnChainNotifications } from "./services/api-notifications.mjs";
29
+ import { getAPINotifications, getNotificationsApiConfigCached, markNotificationsAsRead } from "./services/api-notifications.mjs";
30
30
  import { getFeatureAnnouncementNotifications } from "./services/feature-announcements.mjs";
31
31
  import { createPerpOrderNotification } from "./services/perp-notifications.mjs";
32
32
  // Unique name for the controller
@@ -129,46 +129,57 @@ export const DEFAULT_SOCIAL_AI_PREFERENCES = {
129
129
  };
130
130
  export { DEFAULT_AGENTIC_CLI_PREFERENCES, DEFAULT_PRICE_ALERT_PREFERENCES } from "@metamask/authenticated-user-storage";
131
131
  /**
132
- * Returns the subset of `accounts` that has a wallet-activity subscription in
133
- * the Trigger API, which is the source of truth for the per-address enabled bit.
132
+ * Builds wallet-activity preferences from the keyring's current accounts.
134
133
  *
135
- * The address universe is always supplied by the caller from the keyring, so the
136
- * result cannot contain an address this installation does not hold.
134
+ * @param accounts - The keyring accounts to build wallet-activity entries for.
135
+ * @returns An array of wallet-activity account entries (lower-cased addresses).
136
+ */
137
+ const buildWalletActivityAccounts = (accounts) => accounts.map(({ address, enabled }) => {
138
+ const lowercased = address.toLowerCase();
139
+ return {
140
+ address: lowercased,
141
+ enabled,
142
+ };
143
+ });
144
+ /**
145
+ * Builds wallet-activity initialization from the Trigger API. If Trigger has no
146
+ * enabled entries for the current keyring accounts, this is a first-time
147
+ * notification setup and all current accounts should start enabled.
137
148
  *
138
- * @param bearerToken - JWT used to query the Trigger API.
139
- * @param accounts - The keyring accounts to check.
149
+ * @param bearerToken - JWT used to query Trigger API.
150
+ * @param accounts - The keyring accounts to initialize.
140
151
  * @param env - The environment to use for the Trigger API call.
141
- * @returns The enabled addresses, as returned by the Trigger API, or `null` if
142
- * the Trigger API could not be read.
152
+ * @returns Wallet-activity account initialization entries.
143
153
  */
144
- const getEnabledAccounts = async (bearerToken, accounts, env) => {
154
+ const buildWalletActivityAccountsFromTriggerConfig = async (bearerToken, accounts, env) => {
145
155
  const triggerConfig = await getNotificationsApiConfigCached(bearerToken, accounts, env);
146
- if (triggerConfig === null) {
147
- return null;
148
- }
149
- return triggerConfig
150
- .filter((addressConfig) => Boolean(addressConfig.enabled))
151
- .map((addressConfig) => addressConfig.address);
156
+ const triggerConfigByAddress = new Map(triggerConfig.map(({ address, enabled }) => [
157
+ address.toLowerCase(),
158
+ enabled,
159
+ ]));
160
+ const hasEnabledTriggerAccount = accounts.some((address) => triggerConfigByAddress.get(address.toLowerCase()) === true);
161
+ return accounts.map((address) => ({
162
+ address,
163
+ enabled: hasEnabledTriggerAccount
164
+ ? (triggerConfigByAddress.get(address.toLowerCase()) ?? false)
165
+ : true,
166
+ }));
152
167
  };
153
168
  /**
154
169
  * Builds a fresh `NotificationPreferences` blob using hardcoded defaults for
155
- * Perps, Social AI, and Agentic CLI and the user's marketing/product-announcement
156
- * flags.
157
- *
158
- * `walletActivity.accounts` is deliberately left empty. Addresses are scoped to a
159
- * keyring, but this blob is keyed by canonical profile ID, which pairing shares
160
- * across every SRP belonging to the same user — so storing them here pools the
161
- * addresses of unrelated SRPs. Subscriptions live in the Trigger API instead.
170
+ * Perps, Social AI, and Agentic CLI, the supplied wallet-activity accounts and
171
+ * the user's marketing/product-announcement flags.
162
172
  *
173
+ * @param walletActivityAccounts - The wallet-activity account config to initialize.
163
174
  * @param hasMarketingConsent - Whether marketing push notifications should be enabled.
164
175
  * @param productAnnouncementEnabled - Whether marketing in-app notifications should be enabled.
165
176
  * @returns A complete `NotificationPreferences` object.
166
177
  */
167
- const buildFreshPreferences = (hasMarketingConsent, productAnnouncementEnabled) => ({
178
+ const buildFreshPreferences = (walletActivityAccounts, hasMarketingConsent, productAnnouncementEnabled) => ({
168
179
  walletActivity: {
169
180
  inAppNotificationsEnabled: true,
170
181
  pushNotificationsEnabled: true,
171
- accounts: [],
182
+ accounts: buildWalletActivityAccounts(walletActivityAccounts),
172
183
  },
173
184
  marketing: {
174
185
  inAppNotificationsEnabled: productAnnouncementEnabled,
@@ -470,20 +481,13 @@ export class NotificationServicesController extends BaseController {
470
481
  */
471
482
  async enablePushNotifications() {
472
483
  try {
473
- if (!(await __classPrivateFieldGet(this, _NotificationServicesController_instances, "m", _NotificationServicesController_isWalletActivityPushEnabled).call(this))) {
474
- await __classPrivateFieldGet(this, _NotificationServicesController_pushNotifications, "f").disablePushNotifications();
475
- return;
476
- }
477
- const { bearerToken } = await __classPrivateFieldGet(this, _NotificationServicesController_instances, "m", _NotificationServicesController_getBearerToken).call(this);
478
- const { accounts } = __classPrivateFieldGet(this, _NotificationServicesController_accounts, "f").listAccounts();
479
- const enabledAddresses = await getEnabledAccounts(bearerToken, accounts, __classPrivateFieldGet(this, _NotificationServicesController_env, "f"));
480
- if (enabledAddresses === null) {
481
- // "No addresses" unregisters the device, so an unreadable subscription
482
- // list must not be treated as an empty one: leave the existing links
483
- // alone until we can read the real state.
484
- return;
484
+ const preferences = await this.messenger.call('AuthenticatedUserStorageService:getNotificationPreferences');
485
+ const enabledAddresses = (preferences?.walletActivity.accounts ?? [])
486
+ .filter((account) => account.enabled)
487
+ .map((account) => account.address);
488
+ if (enabledAddresses.length > 0) {
489
+ await __classPrivateFieldGet(this, _NotificationServicesController_pushNotifications, "f").enablePushNotifications(enabledAddresses);
485
490
  }
486
- await __classPrivateFieldGet(this, _NotificationServicesController_instances, "m", _NotificationServicesController_registerPushNotifications).call(this, enabledAddresses);
487
491
  }
488
492
  catch {
489
493
  // Do nothing, failing silently.
@@ -498,16 +502,10 @@ export class NotificationServicesController extends BaseController {
498
502
  async checkAccountsPresence(accounts) {
499
503
  try {
500
504
  __classPrivateFieldGet(this, _NotificationServicesController_instances, "m", _NotificationServicesController_setIsCheckingAccountsPresence).call(this, true);
501
- const { bearerToken } = await __classPrivateFieldGet(this, _NotificationServicesController_instances, "m", _NotificationServicesController_getBearerToken).call(this);
502
- const triggerConfig = await getNotificationsApiConfigCached(bearerToken, accounts, __classPrivateFieldGet(this, _NotificationServicesController_env, "f"));
503
- if (triggerConfig === null) {
504
- // Reporting every account as disabled would misrepresent the user's
505
- // settings, so surface the failure instead.
506
- throw new Error('Failed to read wallet-activity subscriptions');
507
- }
508
- const enabledByAddress = new Map(triggerConfig.map((addressConfig) => [
509
- addressConfig.address.toLowerCase(),
510
- Boolean(addressConfig.enabled),
505
+ const preferences = await this.messenger.call('AuthenticatedUserStorageService:getNotificationPreferences');
506
+ const enabledByAddress = new Map((preferences?.walletActivity.accounts ?? []).map((account) => [
507
+ account.address.toLowerCase(),
508
+ account.enabled,
511
509
  ]));
512
510
  const result = {};
513
511
  for (const address of accounts) {
@@ -566,46 +564,27 @@ export class NotificationServicesController extends BaseController {
566
564
  __classPrivateFieldGet(this, _NotificationServicesController_instances, "m", _NotificationServicesController_setIsUpdatingMetamaskNotifications).call(this, true);
567
565
  const { bearerToken } = await __classPrivateFieldGet(this, _NotificationServicesController_instances, "m", _NotificationServicesController_getBearerToken).call(this);
568
566
  const { accounts } = __classPrivateFieldGet(this, _NotificationServicesController_accounts, "f").listAccounts();
569
- // 1. Read existing AUS notification preferences. Their absence is what
570
- // marks a first-time setup, and they are initialized in step 3.
567
+ // 1. Read existing AUS notification preferences and initialize only if absent.
571
568
  const preferences = await this.messenger.call('AuthenticatedUserStorageService:getNotificationPreferences');
572
569
  const hasMarketingConsent = Boolean(opts?.hasMarketingConsent);
573
570
  const productAnnouncementEnabled = Boolean(opts?.productAnnouncementEnabled);
574
- const isFirstTimeSetup = preferences === null;
575
- const isPushEnabled = preferences?.walletActivity.pushNotificationsEnabled ?? true;
576
- // 2. Subscribe the keyring's accounts on first-time setup only.
577
- //
578
- // This method also runs on the daily re-subscribe, so the absence of a
579
- // preferences blob — not the absence of subscriptions — is what marks a
580
- // genuine first-time setup. Keying off "no subscriptions" would re-enable
581
- // every account daily for a user who had turned them all off.
582
- //
583
- // Even at first-time setup, existing subscriptions win: a user upgrading
584
- // from a client that never wrote a preferences blob keeps whichever
585
- // accounts they had already disabled.
586
- let accountsWithNotifications = await getEnabledAccounts(bearerToken, accounts, __classPrivateFieldGet(this, _NotificationServicesController_env, "f"));
587
- if (accountsWithNotifications === null) {
588
- // An unreadable subscription list is not an empty one. Subscribing
589
- // every account here would re-enable ones the user had turned off, and
590
- // registering push for that guessed list would send activity for them,
591
- // so fail and let the caller retry.
592
- throw new Error('Failed to read wallet-activity subscriptions');
593
- }
594
- if (isFirstTimeSetup && accountsWithNotifications.length === 0) {
595
- await updateOnChainNotifications(bearerToken, accounts.map((address) => ({ address, enabled: true })), __classPrivateFieldGet(this, _NotificationServicesController_env, "f"));
596
- accountsWithNotifications = accounts;
571
+ let nextPreferences;
572
+ if (preferences === null) {
573
+ const walletActivityAccounts = await buildWalletActivityAccountsFromTriggerConfig(bearerToken, accounts, __classPrivateFieldGet(this, _NotificationServicesController_env, "f"));
574
+ nextPreferences = buildFreshPreferences(walletActivityAccounts, hasMarketingConsent, productAnnouncementEnabled);
597
575
  }
598
- // 3. Initialize the preferences blob, only once the subscriptions above
599
- // are in place. Its existence is what makes the next run a re-subscribe
600
- // rather than a first-time setup, so writing it earlier would let a
601
- // failed subscribe leave the user enabled with no accounts subscribed
602
- // and no second chance to seed them.
603
- if (isFirstTimeSetup) {
604
- await this.messenger.call('AuthenticatedUserStorageService:putNotificationPreferences', buildFreshPreferences(hasMarketingConsent, productAnnouncementEnabled), __classPrivateFieldGet(this, _NotificationServicesController_featureAnnouncementEnv, "f").platform);
576
+ if (nextPreferences) {
577
+ await this.messenger.call('AuthenticatedUserStorageService:putNotificationPreferences', nextPreferences, __classPrivateFieldGet(this, _NotificationServicesController_featureAnnouncementEnv, "f").platform);
605
578
  }
579
+ const effectivePreferences = nextPreferences ?? preferences;
580
+ const accountsWithNotifications = (effectivePreferences?.walletActivity.accounts ?? [])
581
+ .filter((account) => account.enabled)
582
+ .map((account) => account.address);
606
583
  if (opts.registerPushNotifications ?? true) {
607
584
  // Attempt FCM/device registration only; clients must request OS permission separately.
608
- __classPrivateFieldGet(this, _NotificationServicesController_instances, "m", _NotificationServicesController_registerPushNotifications).call(this, isPushEnabled ? accountsWithNotifications : []).catch(() => {
585
+ __classPrivateFieldGet(this, _NotificationServicesController_pushNotifications, "f")
586
+ .enablePushNotifications(accountsWithNotifications)
587
+ .catch(() => {
609
588
  // Do Nothing
610
589
  });
611
590
  }
@@ -698,8 +677,9 @@ export class NotificationServicesController extends BaseController {
698
677
  async disableAccounts(accounts) {
699
678
  try {
700
679
  __classPrivateFieldGet(this, _NotificationServicesController_instances, "m", _NotificationServicesController_updateUpdatingAccountsState).call(this, accounts);
701
- const { bearerToken } = await __classPrivateFieldGet(this, _NotificationServicesController_instances, "m", _NotificationServicesController_getBearerToken).call(this);
702
- await updateOnChainNotifications(bearerToken, accounts.map((address) => ({ address, enabled: false })), __classPrivateFieldGet(this, _NotificationServicesController_env, "f"));
680
+ // Sign-in gate.
681
+ await __classPrivateFieldGet(this, _NotificationServicesController_instances, "m", _NotificationServicesController_getBearerToken).call(this);
682
+ await __classPrivateFieldGet(this, _NotificationServicesController_instances, "m", _NotificationServicesController_registerWalletActivityAddresses).call(this, accounts.map((address) => ({ address, enabled: false })));
703
683
  await __classPrivateFieldGet(this, _NotificationServicesController_pushNotifications, "f").deletePushNotificationLinks(accounts);
704
684
  }
705
685
  catch {
@@ -727,8 +707,9 @@ export class NotificationServicesController extends BaseController {
727
707
  async enableAccounts(accounts) {
728
708
  try {
729
709
  __classPrivateFieldGet(this, _NotificationServicesController_instances, "m", _NotificationServicesController_updateUpdatingAccountsState).call(this, accounts);
730
- const { bearerToken } = await __classPrivateFieldGet(this, _NotificationServicesController_instances, "m", _NotificationServicesController_getBearerToken).call(this);
731
- await updateOnChainNotifications(bearerToken, accounts.map((address) => ({ address, enabled: true })), __classPrivateFieldGet(this, _NotificationServicesController_env, "f"));
710
+ // Sign-in gate.
711
+ await __classPrivateFieldGet(this, _NotificationServicesController_instances, "m", _NotificationServicesController_getBearerToken).call(this);
712
+ await __classPrivateFieldGet(this, _NotificationServicesController_instances, "m", _NotificationServicesController_registerWalletActivityAddresses).call(this, accounts.map((address) => ({ address, enabled: true })));
732
713
  await __classPrivateFieldGet(this, _NotificationServicesController_pushNotifications, "f").addPushNotificationLinks(accounts);
733
714
  }
734
715
  catch (error) {
@@ -767,20 +748,14 @@ export class NotificationServicesController extends BaseController {
767
748
  : [];
768
749
  // Raw On Chain Notifications
769
750
  const rawOnChainNotifications = [];
770
- const isWalletActivityInAppEnabled = notificationPreferences?.walletActivity.inAppNotificationsEnabled ??
771
- true;
772
- if (isGlobalNotifsEnabled && isWalletActivityInAppEnabled) {
751
+ if (isGlobalNotifsEnabled) {
773
752
  try {
774
753
  const { bearerToken } = await __classPrivateFieldGet(this, _NotificationServicesController_instances, "m", _NotificationServicesController_getBearerToken).call(this);
775
- // Addresses come from the keyring, so this installation can only ever
776
- // ask for activity on accounts it actually holds. The Trigger API
777
- // narrows that to the ones the user has enabled.
778
- const { accounts } = __classPrivateFieldGet(this, _NotificationServicesController_accounts, "f").listAccounts();
779
- const addressesWithNotifications = await getEnabledAccounts(bearerToken, accounts, __classPrivateFieldGet(this, _NotificationServicesController_env, "f"));
780
- if (addressesWithNotifications !== null) {
781
- const notifications = await getAPINotifications(bearerToken, addressesWithNotifications, __classPrivateFieldGet(this, _NotificationServicesController_locale, "f").call(this), __classPrivateFieldGet(this, _NotificationServicesController_featureAnnouncementEnv, "f").platform, __classPrivateFieldGet(this, _NotificationServicesController_env, "f")).catch(() => []);
782
- rawOnChainNotifications.push(...notifications);
783
- }
754
+ const addressesWithNotifications = (notificationPreferences?.walletActivity.accounts ?? [])
755
+ .filter((account) => account.enabled)
756
+ .map((account) => account.address);
757
+ const notifications = await getAPINotifications(bearerToken, addressesWithNotifications, __classPrivateFieldGet(this, _NotificationServicesController_locale, "f").call(this), __classPrivateFieldGet(this, _NotificationServicesController_featureAnnouncementEnv, "f").platform, __classPrivateFieldGet(this, _NotificationServicesController_env, "f")).catch(() => []);
758
+ rawOnChainNotifications.push(...notifications);
784
759
  }
785
760
  catch {
786
761
  // Do nothing
@@ -1003,44 +978,53 @@ _NotificationServicesController_keyringController = new WeakMap(), _Notification
1003
978
  throw new Error('Missing BearerToken');
1004
979
  }
1005
980
  return { bearerToken };
1006
- }, _NotificationServicesController_isWalletActivityPushEnabled =
981
+ }, _NotificationServicesController_registerWalletActivityAddresses =
1007
982
  /**
1008
- * Reads the global wallet-activity push toggle from
1009
- * {@link AuthenticatedUserStorageService}.
1010
- *
1011
- * Only the channel boolean is read. It is a user-level setting that contains
1012
- * no addresses, so sharing it across a paired profile is correct. The address
1013
- * list in the same blob is deliberately ignored — see
1014
- * {@link buildFreshPreferences}.
983
+ * Updates the `walletActivity.accounts` entries in the user's
984
+ * notification-preferences blob in {@link AuthenticatedUserStorageService}.
1015
985
  *
1016
- * A missing or unreadable blob counts as enabled, matching the API's "every
1017
- * toggle is on unless stated otherwise" default, so that a storage outage does
1018
- * not silently stop notifications.
986
+ * `putNotificationPreferences` replaces the entire blob, so we read the
987
+ * current preferences, merge the supplied updates into
988
+ * `walletActivity.accounts`, and write the result back. This helper is only
989
+ * meant to be used for incremental updates (enable/disable individual
990
+ * accounts) after the preferences blob has already been initialized via
991
+ * {@link createOnChainTriggers}; callers should not rely on it to perform
992
+ * first-time initialization.
1019
993
  *
1020
- * @returns Whether wallet-activity push notifications are enabled.
994
+ * @param updates - Addresses to register, each with the desired `enabled` flag
1021
995
  */
1022
- async function _NotificationServicesController_isWalletActivityPushEnabled() {
1023
- const preferences = await this.messenger
996
+ async function _NotificationServicesController_registerWalletActivityAddresses(updates) {
997
+ if (updates.length === 0) {
998
+ return;
999
+ }
1000
+ const currentPreferences = await this.messenger
1024
1001
  .call('AuthenticatedUserStorageService:getNotificationPreferences')
1025
- .catch(() => null);
1026
- return preferences?.walletActivity.pushNotificationsEnabled ?? true;
1027
- }, _NotificationServicesController_registerPushNotifications =
1028
- /**
1029
- * Registers this device for push notifications on the given addresses.
1030
- *
1031
- * An empty list cannot be sent: the push API rejects a registration with no
1032
- * addresses, and because that request is what performs the delete-and-reinsert
1033
- * of the device's links, a rejection leaves the previous links in place and
1034
- * push keeps arriving. So "no addresses" has to mean unregistering the device.
1035
- *
1036
- * @param addresses - The addresses to receive push notifications for.
1037
- */
1038
- async function _NotificationServicesController_registerPushNotifications(addresses) {
1039
- if (addresses.length === 0) {
1040
- await __classPrivateFieldGet(this, _NotificationServicesController_pushNotifications, "f").disablePushNotifications();
1002
+ .catch((error) => {
1003
+ log.error('Failed to get notification preferences. Re-initializing them instead.', error);
1004
+ // TODO: return null once validation error captured
1005
+ // return null;
1006
+ throw error;
1007
+ });
1008
+ if (!currentPreferences) {
1009
+ log.warn('Preferences blob not yet initialized; run `createOnChainTriggers` first.');
1041
1010
  return;
1042
1011
  }
1043
- await __classPrivateFieldGet(this, _NotificationServicesController_pushNotifications, "f").enablePushNotifications(addresses);
1012
+ const accountsByAddress = new Map(currentPreferences.walletActivity.accounts.map((account) => [
1013
+ account.address.toLowerCase(),
1014
+ { ...account, address: account.address.toLowerCase() },
1015
+ ]));
1016
+ for (const update of updates) {
1017
+ const address = update.address.toLowerCase();
1018
+ accountsByAddress.set(address, { address, enabled: update.enabled });
1019
+ }
1020
+ const nextPreferences = {
1021
+ ...currentPreferences,
1022
+ walletActivity: {
1023
+ ...currentPreferences.walletActivity,
1024
+ accounts: [...accountsByAddress.values()],
1025
+ },
1026
+ };
1027
+ await this.messenger.call('AuthenticatedUserStorageService:putNotificationPreferences', nextPreferences, __classPrivateFieldGet(this, _NotificationServicesController_featureAnnouncementEnv, "f").platform);
1044
1028
  }, _NotificationServicesController_setIsUpdatingMetamaskNotifications = function _NotificationServicesController_setIsUpdatingMetamaskNotifications(isUpdatingMetamaskNotifications) {
1045
1029
  this.update((state) => {
1046
1030
  state.isUpdatingMetamaskNotifications = isUpdatingMetamaskNotifications;