@metamask-previews/notification-services-controller 26.0.1-preview-6ed11f88f → 27.0.0-preview-2d576f0c9
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.
- package/CHANGELOG.md +23 -1
- package/dist/NotificationServicesController/NotificationServicesController.cjs +130 -112
- package/dist/NotificationServicesController/NotificationServicesController.cjs.map +1 -1
- package/dist/NotificationServicesController/NotificationServicesController.d.cts.map +1 -1
- package/dist/NotificationServicesController/NotificationServicesController.d.mts.map +1 -1
- package/dist/NotificationServicesController/NotificationServicesController.mjs +131 -113
- package/dist/NotificationServicesController/NotificationServicesController.mjs.map +1 -1
- package/dist/NotificationServicesController/mocks/mockResponses.cjs +9 -1
- package/dist/NotificationServicesController/mocks/mockResponses.cjs.map +1 -1
- package/dist/NotificationServicesController/mocks/mockResponses.d.cts +1 -0
- package/dist/NotificationServicesController/mocks/mockResponses.d.cts.map +1 -1
- package/dist/NotificationServicesController/mocks/mockResponses.d.mts +1 -0
- package/dist/NotificationServicesController/mocks/mockResponses.d.mts.map +1 -1
- package/dist/NotificationServicesController/mocks/mockResponses.mjs +8 -1
- package/dist/NotificationServicesController/mocks/mockResponses.mjs.map +1 -1
- package/dist/NotificationServicesController/services/api-notifications.cjs +43 -4
- package/dist/NotificationServicesController/services/api-notifications.cjs.map +1 -1
- package/dist/NotificationServicesController/services/api-notifications.d.cts +23 -2
- package/dist/NotificationServicesController/services/api-notifications.d.cts.map +1 -1
- package/dist/NotificationServicesController/services/api-notifications.d.mts +23 -2
- package/dist/NotificationServicesController/services/api-notifications.d.mts.map +1 -1
- package/dist/NotificationServicesController/services/api-notifications.mjs +40 -3
- package/dist/NotificationServicesController/services/api-notifications.mjs.map +1 -1
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -7,10 +7,31 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [27.0.0]
|
|
11
|
+
|
|
10
12
|
### Changed
|
|
11
13
|
|
|
14
|
+
- **BREAKING:** `getNotificationsApiConfigCached` now returns `null` when the Trigger API could not be read, and an empty array only when the API reported that no address is subscribed ([#9985](https://github.com/MetaMask/core/pull/9985))
|
|
15
|
+
- Previously both cases returned an empty array, so callers could not tell "the user has nothing enabled" from "we failed to ask", and acting on the guess re-subscribed or unregistered addresses behind the user.
|
|
12
16
|
- Bump `@metamask/keyring-controller` from `^27.1.0` to `^27.1.1` ([#9791](https://github.com/MetaMask/core/pull/9791))
|
|
13
17
|
- Bump `@metamask/authenticated-user-storage` from `^3.0.1` to `^3.0.2` ([#9972](https://github.com/MetaMask/core/pull/9972))
|
|
18
|
+
- Bump `@metamask/utils` from `^11.11.0` to `^11.12.0` ([#10076](https://github.com/MetaMask/core/pull/10076))
|
|
19
|
+
|
|
20
|
+
### Fixed
|
|
21
|
+
|
|
22
|
+
- **BREAKING:** Wallet-activity addresses are once again sourced from the keyring and the Trigger API instead of Authenticated User Storage, which stops users receiving notifications for addresses they do not hold ([#9985](https://github.com/MetaMask/core/pull/9985))
|
|
23
|
+
- Authenticated User Storage is keyed by canonical profile ID, which profile pairing shares across every SRP belonging to the same user, so an address list stored there pooled the addresses of unrelated SRPs and delivered each installation the union of all of them. Addresses are keyring-scoped and cannot live in profile-scoped storage.
|
|
24
|
+
- `checkAccountsPresence`, `fetchAndUpdateMetamaskNotifications` and `enablePushNotifications` now take the candidate addresses from the keyring and read the per-address enabled bit from the Trigger API. An installation can therefore only ever ask about addresses it holds.
|
|
25
|
+
- `enableAccounts` and `disableAccounts` now write subscriptions to the Trigger API. The endpoint is a per-address upsert, so two installations authenticating as the same profile no longer clobber each other's subscriptions.
|
|
26
|
+
- `createOnChainTriggers` no longer writes addresses into `walletActivity.accounts`; it writes an empty list. It subscribes the keyring's accounts only when initializing preferences for the first time and the Trigger API has no subscriptions yet, so the daily re-subscribe can no longer re-enable accounts the user turned off.
|
|
27
|
+
- The user-level `walletActivity.inAppNotificationsEnabled` and `walletActivity.pushNotificationsEnabled` toggles are still read from Authenticated User Storage. They contain no addresses, so they remain correct to share across a paired profile. An unreadable preferences blob is treated as both toggles enabled, so a storage outage no longer empties the notification list.
|
|
28
|
+
- Unregister the device from push notifications when no account has notifications enabled ([#9985](https://github.com/MetaMask/core/pull/9985))
|
|
29
|
+
- The push API rejects a registration with no addresses, and that request is what performs the delete-and-reinsert of the device's links, so the rejection left the previous links in place and push kept arriving after a user disabled every account.
|
|
30
|
+
- `enableAccounts` and `disableAccounts` now reject when the Trigger API rejects the subscription change, instead of reporting success and caching a state the server never applied ([#9985](https://github.com/MetaMask/core/pull/9985))
|
|
31
|
+
- A 4xx/5xx response was treated as success, so the settings UI showed the new toggle position and push links were added or removed for a subscription that did not change.
|
|
32
|
+
- A failed Trigger API config read no longer re-enables accounts or unregisters the device ([#9985](https://github.com/MetaMask/core/pull/9985))
|
|
33
|
+
- `createOnChainTriggers` now fails instead of reading a failed config query as "no subscriptions yet", which could subscribe every keyring account for a user who had turned them off, and it writes the preferences blob only after those subscriptions are in place so a failed run can still be retried as a first-time setup.
|
|
34
|
+
- `enablePushNotifications` leaves the device's existing push links alone rather than unregistering it, and `checkAccountsPresence` rejects rather than reporting every account as disabled.
|
|
14
35
|
|
|
15
36
|
## [26.0.1]
|
|
16
37
|
|
|
@@ -856,7 +877,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
856
877
|
|
|
857
878
|
- Initial release
|
|
858
879
|
|
|
859
|
-
[Unreleased]: https://github.com/MetaMask/core/compare/@metamask/notification-services-controller@
|
|
880
|
+
[Unreleased]: https://github.com/MetaMask/core/compare/@metamask/notification-services-controller@27.0.0...HEAD
|
|
881
|
+
[27.0.0]: https://github.com/MetaMask/core/compare/@metamask/notification-services-controller@26.0.1...@metamask/notification-services-controller@27.0.0
|
|
860
882
|
[26.0.1]: https://github.com/MetaMask/core/compare/@metamask/notification-services-controller@26.0.0...@metamask/notification-services-controller@26.0.1
|
|
861
883
|
[26.0.0]: https://github.com/MetaMask/core/compare/@metamask/notification-services-controller@25.0.0...@metamask/notification-services-controller@26.0.0
|
|
862
884
|
[25.0.0]: https://github.com/MetaMask/core/compare/@metamask/notification-services-controller@24.3.0...@metamask/notification-services-controller@25.0.0
|
|
@@ -13,7 +13,7 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
|
|
|
13
13
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
14
14
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
15
15
|
};
|
|
16
|
-
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,
|
|
16
|
+
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;
|
|
17
17
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
18
|
exports.NotificationServicesController = exports.DEFAULT_PRICE_ALERT_PREFERENCES = exports.DEFAULT_AGENTIC_CLI_PREFERENCES = exports.DEFAULT_SOCIAL_AI_PREFERENCES = exports.DEFAULT_PERPS_PREFERENCES = exports.defaultState = exports.ACCOUNTS_UPDATE_DEBOUNCE_TIME_MS = void 0;
|
|
19
19
|
const authenticated_user_storage_1 = require("@metamask/authenticated-user-storage");
|
|
@@ -129,57 +129,46 @@ var authenticated_user_storage_2 = require("@metamask/authenticated-user-storage
|
|
|
129
129
|
Object.defineProperty(exports, "DEFAULT_AGENTIC_CLI_PREFERENCES", { enumerable: true, get: function () { return authenticated_user_storage_2.DEFAULT_AGENTIC_CLI_PREFERENCES; } });
|
|
130
130
|
Object.defineProperty(exports, "DEFAULT_PRICE_ALERT_PREFERENCES", { enumerable: true, get: function () { return authenticated_user_storage_2.DEFAULT_PRICE_ALERT_PREFERENCES; } });
|
|
131
131
|
/**
|
|
132
|
-
*
|
|
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.
|
|
133
134
|
*
|
|
134
|
-
*
|
|
135
|
-
*
|
|
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.
|
|
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.
|
|
148
137
|
*
|
|
149
|
-
* @param bearerToken - JWT used to query Trigger API.
|
|
150
|
-
* @param accounts - The keyring accounts to
|
|
138
|
+
* @param bearerToken - JWT used to query the Trigger API.
|
|
139
|
+
* @param accounts - The keyring accounts to check.
|
|
151
140
|
* @param env - The environment to use for the Trigger API call.
|
|
152
|
-
* @returns
|
|
141
|
+
* @returns The enabled addresses, as returned by the Trigger API, or `null` if
|
|
142
|
+
* the Trigger API could not be read.
|
|
153
143
|
*/
|
|
154
|
-
const
|
|
144
|
+
const getEnabledAccounts = async (bearerToken, accounts, env) => {
|
|
155
145
|
const triggerConfig = await (0, api_notifications_js_1.getNotificationsApiConfigCached)(bearerToken, accounts, env);
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
address,
|
|
163
|
-
enabled: hasEnabledTriggerAccount
|
|
164
|
-
? (triggerConfigByAddress.get(address.toLowerCase()) ?? false)
|
|
165
|
-
: true,
|
|
166
|
-
}));
|
|
146
|
+
if (triggerConfig === null) {
|
|
147
|
+
return null;
|
|
148
|
+
}
|
|
149
|
+
return triggerConfig
|
|
150
|
+
.filter((addressConfig) => Boolean(addressConfig.enabled))
|
|
151
|
+
.map((addressConfig) => addressConfig.address);
|
|
167
152
|
};
|
|
168
153
|
/**
|
|
169
154
|
* Builds a fresh `NotificationPreferences` blob using hardcoded defaults for
|
|
170
|
-
* Perps, Social AI, and Agentic CLI
|
|
171
|
-
*
|
|
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.
|
|
172
162
|
*
|
|
173
|
-
* @param walletActivityAccounts - The wallet-activity account config to initialize.
|
|
174
163
|
* @param hasMarketingConsent - Whether marketing push notifications should be enabled.
|
|
175
164
|
* @param productAnnouncementEnabled - Whether marketing in-app notifications should be enabled.
|
|
176
165
|
* @returns A complete `NotificationPreferences` object.
|
|
177
166
|
*/
|
|
178
|
-
const buildFreshPreferences = (
|
|
167
|
+
const buildFreshPreferences = (hasMarketingConsent, productAnnouncementEnabled) => ({
|
|
179
168
|
walletActivity: {
|
|
180
169
|
inAppNotificationsEnabled: true,
|
|
181
170
|
pushNotificationsEnabled: true,
|
|
182
|
-
accounts:
|
|
171
|
+
accounts: [],
|
|
183
172
|
},
|
|
184
173
|
marketing: {
|
|
185
174
|
inAppNotificationsEnabled: productAnnouncementEnabled,
|
|
@@ -481,13 +470,20 @@ class NotificationServicesController extends base_controller_1.BaseController {
|
|
|
481
470
|
*/
|
|
482
471
|
async enablePushNotifications() {
|
|
483
472
|
try {
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
.map((account) => account.address);
|
|
488
|
-
if (enabledAddresses.length > 0) {
|
|
489
|
-
await __classPrivateFieldGet(this, _NotificationServicesController_pushNotifications, "f").enablePushNotifications(enabledAddresses);
|
|
473
|
+
if (!(await __classPrivateFieldGet(this, _NotificationServicesController_instances, "m", _NotificationServicesController_isWalletActivityPushEnabled).call(this))) {
|
|
474
|
+
await __classPrivateFieldGet(this, _NotificationServicesController_pushNotifications, "f").disablePushNotifications();
|
|
475
|
+
return;
|
|
490
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;
|
|
485
|
+
}
|
|
486
|
+
await __classPrivateFieldGet(this, _NotificationServicesController_instances, "m", _NotificationServicesController_registerPushNotifications).call(this, enabledAddresses);
|
|
491
487
|
}
|
|
492
488
|
catch {
|
|
493
489
|
// Do nothing, failing silently.
|
|
@@ -502,10 +498,16 @@ class NotificationServicesController extends base_controller_1.BaseController {
|
|
|
502
498
|
async checkAccountsPresence(accounts) {
|
|
503
499
|
try {
|
|
504
500
|
__classPrivateFieldGet(this, _NotificationServicesController_instances, "m", _NotificationServicesController_setIsCheckingAccountsPresence).call(this, true);
|
|
505
|
-
const
|
|
506
|
-
const
|
|
507
|
-
|
|
508
|
-
account
|
|
501
|
+
const { bearerToken } = await __classPrivateFieldGet(this, _NotificationServicesController_instances, "m", _NotificationServicesController_getBearerToken).call(this);
|
|
502
|
+
const triggerConfig = await (0, api_notifications_js_1.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),
|
|
509
511
|
]));
|
|
510
512
|
const result = {};
|
|
511
513
|
for (const address of accounts) {
|
|
@@ -564,27 +566,48 @@ class NotificationServicesController extends base_controller_1.BaseController {
|
|
|
564
566
|
__classPrivateFieldGet(this, _NotificationServicesController_instances, "m", _NotificationServicesController_setIsUpdatingMetamaskNotifications).call(this, true);
|
|
565
567
|
const { bearerToken } = await __classPrivateFieldGet(this, _NotificationServicesController_instances, "m", _NotificationServicesController_getBearerToken).call(this);
|
|
566
568
|
const { accounts } = __classPrivateFieldGet(this, _NotificationServicesController_accounts, "f").listAccounts();
|
|
567
|
-
// 1. Read existing AUS notification preferences
|
|
569
|
+
// 1. Read existing AUS notification preferences. Their absence is what
|
|
570
|
+
// marks a first-time setup, and they are initialized in step 3.
|
|
568
571
|
const preferences = await this.messenger.call('AuthenticatedUserStorageService:getNotificationPreferences');
|
|
569
572
|
const hasMarketingConsent = Boolean(opts?.hasMarketingConsent);
|
|
570
573
|
const productAnnouncementEnabled = Boolean(opts?.productAnnouncementEnabled);
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
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 (0, api_notifications_js_1.updateOnChainNotifications)(bearerToken, accounts.map((address) => ({ address, enabled: true })), __classPrivateFieldGet(this, _NotificationServicesController_env, "f"));
|
|
596
|
+
// Match the lower-case form the Trigger API echoes back, which is what
|
|
597
|
+
// every other path feeding the push API uses.
|
|
598
|
+
accountsWithNotifications = accounts.map((address) => address.toLowerCase());
|
|
575
599
|
}
|
|
576
|
-
|
|
577
|
-
|
|
600
|
+
// 3. Initialize the preferences blob, only once the subscriptions above
|
|
601
|
+
// are in place. Its existence is what makes the next run a re-subscribe
|
|
602
|
+
// rather than a first-time setup, so writing it earlier would let a
|
|
603
|
+
// failed subscribe leave the user enabled with no accounts subscribed
|
|
604
|
+
// and no second chance to seed them.
|
|
605
|
+
if (isFirstTimeSetup) {
|
|
606
|
+
await this.messenger.call('AuthenticatedUserStorageService:putNotificationPreferences', buildFreshPreferences(hasMarketingConsent, productAnnouncementEnabled), __classPrivateFieldGet(this, _NotificationServicesController_featureAnnouncementEnv, "f").platform);
|
|
578
607
|
}
|
|
579
|
-
const effectivePreferences = nextPreferences ?? preferences;
|
|
580
|
-
const accountsWithNotifications = (effectivePreferences?.walletActivity.accounts ?? [])
|
|
581
|
-
.filter((account) => account.enabled)
|
|
582
|
-
.map((account) => account.address);
|
|
583
608
|
if (opts.registerPushNotifications ?? true) {
|
|
584
609
|
// Attempt FCM/device registration only; clients must request OS permission separately.
|
|
585
|
-
__classPrivateFieldGet(this,
|
|
586
|
-
.enablePushNotifications(accountsWithNotifications)
|
|
587
|
-
.catch(() => {
|
|
610
|
+
__classPrivateFieldGet(this, _NotificationServicesController_instances, "m", _NotificationServicesController_registerPushNotifications).call(this, isPushEnabled ? accountsWithNotifications : []).catch(() => {
|
|
588
611
|
// Do Nothing
|
|
589
612
|
});
|
|
590
613
|
}
|
|
@@ -677,9 +700,8 @@ class NotificationServicesController extends base_controller_1.BaseController {
|
|
|
677
700
|
async disableAccounts(accounts) {
|
|
678
701
|
try {
|
|
679
702
|
__classPrivateFieldGet(this, _NotificationServicesController_instances, "m", _NotificationServicesController_updateUpdatingAccountsState).call(this, accounts);
|
|
680
|
-
|
|
681
|
-
await
|
|
682
|
-
await __classPrivateFieldGet(this, _NotificationServicesController_instances, "m", _NotificationServicesController_registerWalletActivityAddresses).call(this, accounts.map((address) => ({ address, enabled: false })));
|
|
703
|
+
const { bearerToken } = await __classPrivateFieldGet(this, _NotificationServicesController_instances, "m", _NotificationServicesController_getBearerToken).call(this);
|
|
704
|
+
await (0, api_notifications_js_1.updateOnChainNotifications)(bearerToken, accounts.map((address) => ({ address, enabled: false })), __classPrivateFieldGet(this, _NotificationServicesController_env, "f"));
|
|
683
705
|
await __classPrivateFieldGet(this, _NotificationServicesController_pushNotifications, "f").deletePushNotificationLinks(accounts);
|
|
684
706
|
}
|
|
685
707
|
catch {
|
|
@@ -707,9 +729,8 @@ class NotificationServicesController extends base_controller_1.BaseController {
|
|
|
707
729
|
async enableAccounts(accounts) {
|
|
708
730
|
try {
|
|
709
731
|
__classPrivateFieldGet(this, _NotificationServicesController_instances, "m", _NotificationServicesController_updateUpdatingAccountsState).call(this, accounts);
|
|
710
|
-
|
|
711
|
-
await
|
|
712
|
-
await __classPrivateFieldGet(this, _NotificationServicesController_instances, "m", _NotificationServicesController_registerWalletActivityAddresses).call(this, accounts.map((address) => ({ address, enabled: true })));
|
|
732
|
+
const { bearerToken } = await __classPrivateFieldGet(this, _NotificationServicesController_instances, "m", _NotificationServicesController_getBearerToken).call(this);
|
|
733
|
+
await (0, api_notifications_js_1.updateOnChainNotifications)(bearerToken, accounts.map((address) => ({ address, enabled: true })), __classPrivateFieldGet(this, _NotificationServicesController_env, "f"));
|
|
713
734
|
await __classPrivateFieldGet(this, _NotificationServicesController_pushNotifications, "f").addPushNotificationLinks(accounts);
|
|
714
735
|
}
|
|
715
736
|
catch (error) {
|
|
@@ -748,14 +769,20 @@ class NotificationServicesController extends base_controller_1.BaseController {
|
|
|
748
769
|
: [];
|
|
749
770
|
// Raw On Chain Notifications
|
|
750
771
|
const rawOnChainNotifications = [];
|
|
751
|
-
|
|
772
|
+
const isWalletActivityInAppEnabled = notificationPreferences?.walletActivity.inAppNotificationsEnabled ??
|
|
773
|
+
true;
|
|
774
|
+
if (isGlobalNotifsEnabled && isWalletActivityInAppEnabled) {
|
|
752
775
|
try {
|
|
753
776
|
const { bearerToken } = await __classPrivateFieldGet(this, _NotificationServicesController_instances, "m", _NotificationServicesController_getBearerToken).call(this);
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
const
|
|
758
|
-
|
|
777
|
+
// Addresses come from the keyring, so this installation can only ever
|
|
778
|
+
// ask for activity on accounts it actually holds. The Trigger API
|
|
779
|
+
// narrows that to the ones the user has enabled.
|
|
780
|
+
const { accounts } = __classPrivateFieldGet(this, _NotificationServicesController_accounts, "f").listAccounts();
|
|
781
|
+
const addressesWithNotifications = await getEnabledAccounts(bearerToken, accounts, __classPrivateFieldGet(this, _NotificationServicesController_env, "f"));
|
|
782
|
+
if (addressesWithNotifications !== null) {
|
|
783
|
+
const notifications = await (0, api_notifications_js_1.getAPINotifications)(bearerToken, addressesWithNotifications, __classPrivateFieldGet(this, _NotificationServicesController_locale, "f").call(this), __classPrivateFieldGet(this, _NotificationServicesController_featureAnnouncementEnv, "f").platform, __classPrivateFieldGet(this, _NotificationServicesController_env, "f")).catch(() => []);
|
|
784
|
+
rawOnChainNotifications.push(...notifications);
|
|
785
|
+
}
|
|
759
786
|
}
|
|
760
787
|
catch {
|
|
761
788
|
// Do nothing
|
|
@@ -979,53 +1006,44 @@ _NotificationServicesController_keyringController = new WeakMap(), _Notification
|
|
|
979
1006
|
throw new Error('Missing BearerToken');
|
|
980
1007
|
}
|
|
981
1008
|
return { bearerToken };
|
|
982
|
-
},
|
|
1009
|
+
}, _NotificationServicesController_isWalletActivityPushEnabled =
|
|
983
1010
|
/**
|
|
984
|
-
*
|
|
985
|
-
*
|
|
1011
|
+
* Reads the global wallet-activity push toggle from
|
|
1012
|
+
* {@link AuthenticatedUserStorageService}.
|
|
1013
|
+
*
|
|
1014
|
+
* Only the channel boolean is read. It is a user-level setting that contains
|
|
1015
|
+
* no addresses, so sharing it across a paired profile is correct. The address
|
|
1016
|
+
* list in the same blob is deliberately ignored — see
|
|
1017
|
+
* {@link buildFreshPreferences}.
|
|
986
1018
|
*
|
|
987
|
-
*
|
|
988
|
-
*
|
|
989
|
-
*
|
|
990
|
-
* meant to be used for incremental updates (enable/disable individual
|
|
991
|
-
* accounts) after the preferences blob has already been initialized via
|
|
992
|
-
* {@link createOnChainTriggers}; callers should not rely on it to perform
|
|
993
|
-
* first-time initialization.
|
|
1019
|
+
* A missing or unreadable blob counts as enabled, matching the API's "every
|
|
1020
|
+
* toggle is on unless stated otherwise" default, so that a storage outage does
|
|
1021
|
+
* not silently stop notifications.
|
|
994
1022
|
*
|
|
995
|
-
* @
|
|
1023
|
+
* @returns Whether wallet-activity push notifications are enabled.
|
|
996
1024
|
*/
|
|
997
|
-
async function
|
|
998
|
-
|
|
999
|
-
return;
|
|
1000
|
-
}
|
|
1001
|
-
const currentPreferences = await this.messenger
|
|
1025
|
+
async function _NotificationServicesController_isWalletActivityPushEnabled() {
|
|
1026
|
+
const preferences = await this.messenger
|
|
1002
1027
|
.call('AuthenticatedUserStorageService:getNotificationPreferences')
|
|
1003
|
-
.catch((
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1028
|
+
.catch(() => null);
|
|
1029
|
+
return preferences?.walletActivity.pushNotificationsEnabled ?? true;
|
|
1030
|
+
}, _NotificationServicesController_registerPushNotifications =
|
|
1031
|
+
/**
|
|
1032
|
+
* Registers this device for push notifications on the given addresses.
|
|
1033
|
+
*
|
|
1034
|
+
* An empty list cannot be sent: the push API rejects a registration with no
|
|
1035
|
+
* addresses, and because that request is what performs the delete-and-reinsert
|
|
1036
|
+
* of the device's links, a rejection leaves the previous links in place and
|
|
1037
|
+
* push keeps arriving. So "no addresses" has to mean unregistering the device.
|
|
1038
|
+
*
|
|
1039
|
+
* @param addresses - The addresses to receive push notifications for.
|
|
1040
|
+
*/
|
|
1041
|
+
async function _NotificationServicesController_registerPushNotifications(addresses) {
|
|
1042
|
+
if (addresses.length === 0) {
|
|
1043
|
+
await __classPrivateFieldGet(this, _NotificationServicesController_pushNotifications, "f").disablePushNotifications();
|
|
1011
1044
|
return;
|
|
1012
1045
|
}
|
|
1013
|
-
|
|
1014
|
-
account.address.toLowerCase(),
|
|
1015
|
-
{ ...account, address: account.address.toLowerCase() },
|
|
1016
|
-
]));
|
|
1017
|
-
for (const update of updates) {
|
|
1018
|
-
const address = update.address.toLowerCase();
|
|
1019
|
-
accountsByAddress.set(address, { address, enabled: update.enabled });
|
|
1020
|
-
}
|
|
1021
|
-
const nextPreferences = {
|
|
1022
|
-
...currentPreferences,
|
|
1023
|
-
walletActivity: {
|
|
1024
|
-
...currentPreferences.walletActivity,
|
|
1025
|
-
accounts: [...accountsByAddress.values()],
|
|
1026
|
-
},
|
|
1027
|
-
};
|
|
1028
|
-
await this.messenger.call('AuthenticatedUserStorageService:putNotificationPreferences', nextPreferences, __classPrivateFieldGet(this, _NotificationServicesController_featureAnnouncementEnv, "f").platform);
|
|
1046
|
+
await __classPrivateFieldGet(this, _NotificationServicesController_pushNotifications, "f").enablePushNotifications(addresses);
|
|
1029
1047
|
}, _NotificationServicesController_setIsUpdatingMetamaskNotifications = function _NotificationServicesController_setIsUpdatingMetamaskNotifications(isUpdatingMetamaskNotifications) {
|
|
1030
1048
|
this.update((state) => {
|
|
1031
1049
|
state.isUpdatingMetamaskNotifications = isUpdatingMetamaskNotifications;
|