@metamask-previews/notification-services-controller 10.0.0-preview-e11fb169 → 10.0.0-preview-7dcef379

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 (144) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/dist/NotificationServicesController/NotificationServicesController.cjs +76 -188
  3. package/dist/NotificationServicesController/NotificationServicesController.cjs.map +1 -1
  4. package/dist/NotificationServicesController/NotificationServicesController.d.cts +10 -16
  5. package/dist/NotificationServicesController/NotificationServicesController.d.cts.map +1 -1
  6. package/dist/NotificationServicesController/NotificationServicesController.d.mts +10 -16
  7. package/dist/NotificationServicesController/NotificationServicesController.d.mts.map +1 -1
  8. package/dist/NotificationServicesController/NotificationServicesController.mjs +77 -189
  9. package/dist/NotificationServicesController/NotificationServicesController.mjs.map +1 -1
  10. package/dist/NotificationServicesController/constants/index.cjs +0 -1
  11. package/dist/NotificationServicesController/constants/index.cjs.map +1 -1
  12. package/dist/NotificationServicesController/constants/index.d.cts +0 -1
  13. package/dist/NotificationServicesController/constants/index.d.cts.map +1 -1
  14. package/dist/NotificationServicesController/constants/index.d.mts +0 -1
  15. package/dist/NotificationServicesController/constants/index.d.mts.map +1 -1
  16. package/dist/NotificationServicesController/constants/index.mjs +0 -1
  17. package/dist/NotificationServicesController/constants/index.mjs.map +1 -1
  18. package/dist/NotificationServicesController/mocks/index.cjs +0 -2
  19. package/dist/NotificationServicesController/mocks/index.cjs.map +1 -1
  20. package/dist/NotificationServicesController/mocks/index.d.cts +0 -2
  21. package/dist/NotificationServicesController/mocks/index.d.cts.map +1 -1
  22. package/dist/NotificationServicesController/mocks/index.d.mts +0 -2
  23. package/dist/NotificationServicesController/mocks/index.d.mts.map +1 -1
  24. package/dist/NotificationServicesController/mocks/index.mjs +0 -2
  25. package/dist/NotificationServicesController/mocks/index.mjs.map +1 -1
  26. package/dist/NotificationServicesController/mocks/mockResponses.cjs +9 -9
  27. package/dist/NotificationServicesController/mocks/mockResponses.cjs.map +1 -1
  28. package/dist/NotificationServicesController/mocks/mockResponses.d.cts +7 -4
  29. package/dist/NotificationServicesController/mocks/mockResponses.d.cts.map +1 -1
  30. package/dist/NotificationServicesController/mocks/mockResponses.d.mts +7 -4
  31. package/dist/NotificationServicesController/mocks/mockResponses.d.mts.map +1 -1
  32. package/dist/NotificationServicesController/mocks/mockResponses.mjs +7 -7
  33. package/dist/NotificationServicesController/mocks/mockResponses.mjs.map +1 -1
  34. package/dist/NotificationServicesController/processors/process-notifications.cjs +4 -1
  35. package/dist/NotificationServicesController/processors/process-notifications.cjs.map +1 -1
  36. package/dist/NotificationServicesController/processors/process-notifications.d.cts +623 -0
  37. package/dist/NotificationServicesController/processors/process-notifications.d.cts.map +1 -1
  38. package/dist/NotificationServicesController/processors/process-notifications.d.mts +623 -0
  39. package/dist/NotificationServicesController/processors/process-notifications.d.mts.map +1 -1
  40. package/dist/NotificationServicesController/processors/process-notifications.mjs +2 -0
  41. package/dist/NotificationServicesController/processors/process-notifications.mjs.map +1 -1
  42. package/dist/NotificationServicesController/services/notification-config-cache.cjs +72 -0
  43. package/dist/NotificationServicesController/services/notification-config-cache.cjs.map +1 -0
  44. package/dist/NotificationServicesController/services/notification-config-cache.d.cts +19 -0
  45. package/dist/NotificationServicesController/services/notification-config-cache.d.cts.map +1 -0
  46. package/dist/NotificationServicesController/services/notification-config-cache.d.mts +19 -0
  47. package/dist/NotificationServicesController/services/notification-config-cache.d.mts.map +1 -0
  48. package/dist/NotificationServicesController/services/notification-config-cache.mjs +68 -0
  49. package/dist/NotificationServicesController/services/notification-config-cache.mjs.map +1 -0
  50. package/dist/NotificationServicesController/services/onchain-notifications.cjs +67 -140
  51. package/dist/NotificationServicesController/services/onchain-notifications.cjs.map +1 -1
  52. package/dist/NotificationServicesController/services/onchain-notifications.d.cts +25 -31
  53. package/dist/NotificationServicesController/services/onchain-notifications.d.cts.map +1 -1
  54. package/dist/NotificationServicesController/services/onchain-notifications.d.mts +25 -31
  55. package/dist/NotificationServicesController/services/onchain-notifications.d.mts.map +1 -1
  56. package/dist/NotificationServicesController/services/onchain-notifications.mjs +65 -137
  57. package/dist/NotificationServicesController/services/onchain-notifications.mjs.map +1 -1
  58. package/dist/NotificationServicesController/types/index.cjs.map +1 -1
  59. package/dist/NotificationServicesController/types/index.d.cts +0 -1
  60. package/dist/NotificationServicesController/types/index.d.cts.map +1 -1
  61. package/dist/NotificationServicesController/types/index.d.mts +0 -1
  62. package/dist/NotificationServicesController/types/index.d.mts.map +1 -1
  63. package/dist/NotificationServicesController/types/index.mjs.map +1 -1
  64. package/dist/NotificationServicesController/utils/utils.cjs +1 -350
  65. package/dist/NotificationServicesController/utils/utils.cjs.map +1 -1
  66. package/dist/NotificationServicesController/utils/utils.d.cts +0 -141
  67. package/dist/NotificationServicesController/utils/utils.d.cts.map +1 -1
  68. package/dist/NotificationServicesController/utils/utils.d.mts +0 -141
  69. package/dist/NotificationServicesController/utils/utils.d.mts.map +1 -1
  70. package/dist/NotificationServicesController/utils/utils.mjs +0 -337
  71. package/dist/NotificationServicesController/utils/utils.mjs.map +1 -1
  72. package/dist/NotificationServicesPushController/NotificationServicesPushController.cjs +22 -15
  73. package/dist/NotificationServicesPushController/NotificationServicesPushController.cjs.map +1 -1
  74. package/dist/NotificationServicesPushController/NotificationServicesPushController.d.cts +6 -5
  75. package/dist/NotificationServicesPushController/NotificationServicesPushController.d.cts.map +1 -1
  76. package/dist/NotificationServicesPushController/NotificationServicesPushController.d.mts +6 -5
  77. package/dist/NotificationServicesPushController/NotificationServicesPushController.d.mts.map +1 -1
  78. package/dist/NotificationServicesPushController/NotificationServicesPushController.mjs +23 -16
  79. package/dist/NotificationServicesPushController/NotificationServicesPushController.mjs.map +1 -1
  80. package/dist/NotificationServicesPushController/mocks/mockResponse.cjs +1 -16
  81. package/dist/NotificationServicesPushController/mocks/mockResponse.cjs.map +1 -1
  82. package/dist/NotificationServicesPushController/mocks/mockResponse.d.cts +0 -7
  83. package/dist/NotificationServicesPushController/mocks/mockResponse.d.cts.map +1 -1
  84. package/dist/NotificationServicesPushController/mocks/mockResponse.d.mts +0 -7
  85. package/dist/NotificationServicesPushController/mocks/mockResponse.d.mts.map +1 -1
  86. package/dist/NotificationServicesPushController/mocks/mockResponse.mjs +0 -14
  87. package/dist/NotificationServicesPushController/mocks/mockResponse.mjs.map +1 -1
  88. package/dist/NotificationServicesPushController/services/endpoints.cjs +1 -1
  89. package/dist/NotificationServicesPushController/services/endpoints.cjs.map +1 -1
  90. package/dist/NotificationServicesPushController/services/endpoints.d.cts +1 -1
  91. package/dist/NotificationServicesPushController/services/endpoints.d.cts.map +1 -1
  92. package/dist/NotificationServicesPushController/services/endpoints.d.mts +1 -1
  93. package/dist/NotificationServicesPushController/services/endpoints.d.mts.map +1 -1
  94. package/dist/NotificationServicesPushController/services/endpoints.mjs +1 -1
  95. package/dist/NotificationServicesPushController/services/endpoints.mjs.map +1 -1
  96. package/dist/NotificationServicesPushController/services/services.cjs +18 -41
  97. package/dist/NotificationServicesPushController/services/services.cjs.map +1 -1
  98. package/dist/NotificationServicesPushController/services/services.d.cts +19 -33
  99. package/dist/NotificationServicesPushController/services/services.d.cts.map +1 -1
  100. package/dist/NotificationServicesPushController/services/services.d.mts +19 -33
  101. package/dist/NotificationServicesPushController/services/services.d.mts.map +1 -1
  102. package/dist/NotificationServicesPushController/services/services.mjs +17 -39
  103. package/dist/NotificationServicesPushController/services/services.mjs.map +1 -1
  104. package/package.json +2 -2
  105. package/dist/NotificationServicesController/constants/constants.cjs +0 -7
  106. package/dist/NotificationServicesController/constants/constants.cjs.map +0 -1
  107. package/dist/NotificationServicesController/constants/constants.d.cts +0 -3
  108. package/dist/NotificationServicesController/constants/constants.d.cts.map +0 -1
  109. package/dist/NotificationServicesController/constants/constants.d.mts +0 -3
  110. package/dist/NotificationServicesController/constants/constants.d.mts.map +0 -1
  111. package/dist/NotificationServicesController/constants/constants.mjs +0 -4
  112. package/dist/NotificationServicesController/constants/constants.mjs.map +0 -1
  113. package/dist/NotificationServicesController/mocks/mock-notification-trigger.cjs +0 -22
  114. package/dist/NotificationServicesController/mocks/mock-notification-trigger.cjs.map +0 -1
  115. package/dist/NotificationServicesController/mocks/mock-notification-trigger.d.cts +0 -9
  116. package/dist/NotificationServicesController/mocks/mock-notification-trigger.d.cts.map +0 -1
  117. package/dist/NotificationServicesController/mocks/mock-notification-trigger.d.mts +0 -9
  118. package/dist/NotificationServicesController/mocks/mock-notification-trigger.d.mts.map +0 -1
  119. package/dist/NotificationServicesController/mocks/mock-notification-trigger.mjs +0 -18
  120. package/dist/NotificationServicesController/mocks/mock-notification-trigger.mjs.map +0 -1
  121. package/dist/NotificationServicesController/mocks/mock-notification-user-storage.cjs +0 -82
  122. package/dist/NotificationServicesController/mocks/mock-notification-user-storage.cjs.map +0 -1
  123. package/dist/NotificationServicesController/mocks/mock-notification-user-storage.d.cts +0 -35
  124. package/dist/NotificationServicesController/mocks/mock-notification-user-storage.d.cts.map +0 -1
  125. package/dist/NotificationServicesController/mocks/mock-notification-user-storage.d.mts +0 -35
  126. package/dist/NotificationServicesController/mocks/mock-notification-user-storage.d.mts.map +0 -1
  127. package/dist/NotificationServicesController/mocks/mock-notification-user-storage.mjs +0 -76
  128. package/dist/NotificationServicesController/mocks/mock-notification-user-storage.mjs.map +0 -1
  129. package/dist/NotificationServicesController/types/user-storage/index.cjs +0 -3
  130. package/dist/NotificationServicesController/types/user-storage/index.cjs.map +0 -1
  131. package/dist/NotificationServicesController/types/user-storage/index.d.cts +0 -2
  132. package/dist/NotificationServicesController/types/user-storage/index.d.cts.map +0 -1
  133. package/dist/NotificationServicesController/types/user-storage/index.d.mts +0 -2
  134. package/dist/NotificationServicesController/types/user-storage/index.d.mts.map +0 -1
  135. package/dist/NotificationServicesController/types/user-storage/index.mjs +0 -2
  136. package/dist/NotificationServicesController/types/user-storage/index.mjs.map +0 -1
  137. package/dist/NotificationServicesController/types/user-storage/user-storage.cjs +0 -3
  138. package/dist/NotificationServicesController/types/user-storage/user-storage.cjs.map +0 -1
  139. package/dist/NotificationServicesController/types/user-storage/user-storage.d.cts +0 -26
  140. package/dist/NotificationServicesController/types/user-storage/user-storage.d.cts.map +0 -1
  141. package/dist/NotificationServicesController/types/user-storage/user-storage.d.mts +0 -26
  142. package/dist/NotificationServicesController/types/user-storage/user-storage.d.mts.map +0 -1
  143. package/dist/NotificationServicesController/types/user-storage/user-storage.mjs +0 -2
  144. package/dist/NotificationServicesController/types/user-storage/user-storage.mjs.map +0 -1
@@ -0,0 +1,72 @@
1
+ "use strict";
2
+ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
3
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
4
+ 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");
5
+ return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
6
+ };
7
+ var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
8
+ if (kind === "m") throw new TypeError("Private method is not writable");
9
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
10
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
11
+ return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
12
+ };
13
+ var _OnChainNotificationsCache_instances, _OnChainNotificationsCache_cache, _OnChainNotificationsCache_TTL, _OnChainNotificationsCache_isExpired, _OnChainNotificationsCache_hasAllAddresses;
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.notificationsConfigCache = exports.OnChainNotificationsCache = exports.NotificationConfigCacheTTL = void 0;
16
+ exports.NotificationConfigCacheTTL = 1000 * 60; // 60 seconds
17
+ class OnChainNotificationsCache {
18
+ constructor() {
19
+ _OnChainNotificationsCache_instances.add(this);
20
+ _OnChainNotificationsCache_cache.set(this, null);
21
+ _OnChainNotificationsCache_TTL.set(this, exports.NotificationConfigCacheTTL);
22
+ }
23
+ get(addresses) {
24
+ if (__classPrivateFieldGet(this, _OnChainNotificationsCache_instances, "m", _OnChainNotificationsCache_isExpired).call(this) || !__classPrivateFieldGet(this, _OnChainNotificationsCache_instances, "m", _OnChainNotificationsCache_hasAllAddresses).call(this, addresses)) {
25
+ return null;
26
+ }
27
+ return addresses.map((address) => ({
28
+ address,
29
+ enabled: __classPrivateFieldGet(this, _OnChainNotificationsCache_cache, "f")?.data.get(address) ?? false,
30
+ }));
31
+ }
32
+ set(data) {
33
+ let map = new Map();
34
+ // If we have existing cache, preserve it and update with new data
35
+ if (__classPrivateFieldGet(this, _OnChainNotificationsCache_cache, "f") && !__classPrivateFieldGet(this, _OnChainNotificationsCache_instances, "m", _OnChainNotificationsCache_isExpired).call(this)) {
36
+ map = new Map(__classPrivateFieldGet(this, _OnChainNotificationsCache_cache, "f").data);
37
+ }
38
+ // Update with new data
39
+ data.forEach(({ address, enabled }) => {
40
+ map.set(address, enabled);
41
+ });
42
+ __classPrivateFieldSet(this, _OnChainNotificationsCache_cache, {
43
+ data: map,
44
+ timestamp: Date.now(),
45
+ }, "f");
46
+ }
47
+ // Full replace when updateOnChainNotifications is called
48
+ replace(data) {
49
+ const map = new Map();
50
+ data.forEach(({ address, enabled }) => {
51
+ map.set(address, enabled);
52
+ });
53
+ __classPrivateFieldSet(this, _OnChainNotificationsCache_cache, {
54
+ data: map,
55
+ timestamp: Date.now(),
56
+ }, "f");
57
+ }
58
+ clear() {
59
+ __classPrivateFieldSet(this, _OnChainNotificationsCache_cache, null, "f");
60
+ }
61
+ }
62
+ exports.OnChainNotificationsCache = OnChainNotificationsCache;
63
+ _OnChainNotificationsCache_cache = new WeakMap(), _OnChainNotificationsCache_TTL = new WeakMap(), _OnChainNotificationsCache_instances = new WeakSet(), _OnChainNotificationsCache_isExpired = function _OnChainNotificationsCache_isExpired() {
64
+ return !__classPrivateFieldGet(this, _OnChainNotificationsCache_cache, "f") || Date.now() - __classPrivateFieldGet(this, _OnChainNotificationsCache_cache, "f").timestamp > __classPrivateFieldGet(this, _OnChainNotificationsCache_TTL, "f");
65
+ }, _OnChainNotificationsCache_hasAllAddresses = function _OnChainNotificationsCache_hasAllAddresses(addresses) {
66
+ if (!__classPrivateFieldGet(this, _OnChainNotificationsCache_cache, "f")) {
67
+ return false;
68
+ }
69
+ return addresses.every((address) => __classPrivateFieldGet(this, _OnChainNotificationsCache_cache, "f")?.data.has(address));
70
+ };
71
+ exports.notificationsConfigCache = new OnChainNotificationsCache();
72
+ //# sourceMappingURL=notification-config-cache.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"notification-config-cache.cjs","sourceRoot":"","sources":["../../../src/NotificationServicesController/services/notification-config-cache.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAKa,QAAA,0BAA0B,GAAG,IAAI,GAAG,EAAE,CAAC,CAAC,aAAa;AAElE,MAAa,yBAAyB;IAAtC;;QACE,2CAAyC,IAAI,EAAC;QAErC,yCAAO,kCAA0B,EAAC;IA2D7C,CAAC;IA9CC,GAAG,CAAC,SAAmB;QACrB,IAAI,uBAAA,IAAI,kFAAW,MAAf,IAAI,CAAa,IAAI,CAAC,uBAAA,IAAI,wFAAiB,MAArB,IAAI,EAAkB,SAAS,CAAC,EAAE;YAC1D,OAAO,IAAI,CAAC;SACb;QAED,OAAO,SAAS,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;YACjC,OAAO;YACP,OAAO,EAAE,uBAAA,IAAI,wCAAO,EAAE,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,KAAK;SACjD,CAAC,CAAC,CAAC;IACN,CAAC;IAED,GAAG,CAAC,IAA6C;QAC/C,IAAI,GAAG,GAAyB,IAAI,GAAG,EAAmB,CAAC;QAE3D,kEAAkE;QAClE,IAAI,uBAAA,IAAI,wCAAO,IAAI,CAAC,uBAAA,IAAI,kFAAW,MAAf,IAAI,CAAa,EAAE;YACrC,GAAG,GAAG,IAAI,GAAG,CAAC,uBAAA,IAAI,wCAAO,CAAC,IAAI,CAAC,CAAC;SACjC;QAED,uBAAuB;QACvB,IAAI,CAAC,OAAO,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE;YACpC,GAAG,CAAC,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAC5B,CAAC,CAAC,CAAC;QAEH,uBAAA,IAAI,oCAAU;YACZ,IAAI,EAAE,GAAG;YACT,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;SACtB,MAAA,CAAC;IACJ,CAAC;IAED,yDAAyD;IACzD,OAAO,CAAC,IAA6C;QACnD,MAAM,GAAG,GAAG,IAAI,GAAG,EAAmB,CAAC;QACvC,IAAI,CAAC,OAAO,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE;YACpC,GAAG,CAAC,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAC5B,CAAC,CAAC,CAAC;QAEH,uBAAA,IAAI,oCAAU;YACZ,IAAI,EAAE,GAAG;YACT,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;SACtB,MAAA,CAAC;IACJ,CAAC;IAED,KAAK;QACH,uBAAA,IAAI,oCAAU,IAAI,MAAA,CAAC;IACrB,CAAC;CACF;AA9DD,8DA8DC;;IAxDG,OAAO,CAAC,uBAAA,IAAI,wCAAO,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,uBAAA,IAAI,wCAAO,CAAC,SAAS,GAAG,uBAAA,IAAI,sCAAK,CAAC;AACxE,CAAC,mGAEgB,SAAmB;IAClC,IAAI,CAAC,uBAAA,IAAI,wCAAO,EAAE;QAChB,OAAO,KAAK,CAAC;KACd;IACD,OAAO,SAAS,CAAC,KAAK,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,uBAAA,IAAI,wCAAO,EAAE,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC;AACtE,CAAC;AAkDU,QAAA,wBAAwB,GAAG,IAAI,yBAAyB,EAAE,CAAC","sourcesContent":["type NotificationConfigCache = {\n data: Map<string, boolean>;\n timestamp: number;\n};\n\nexport const NotificationConfigCacheTTL = 1000 * 60; // 60 seconds\n\nexport class OnChainNotificationsCache {\n #cache: NotificationConfigCache | null = null;\n\n readonly #TTL = NotificationConfigCacheTTL;\n\n #isExpired(): boolean {\n return !this.#cache || Date.now() - this.#cache.timestamp > this.#TTL;\n }\n\n #hasAllAddresses(addresses: string[]): boolean {\n if (!this.#cache) {\n return false;\n }\n return addresses.every((address) => this.#cache?.data.has(address));\n }\n\n get(addresses: string[]): { address: string; enabled: boolean }[] | null {\n if (this.#isExpired() || !this.#hasAllAddresses(addresses)) {\n return null;\n }\n\n return addresses.map((address) => ({\n address,\n enabled: this.#cache?.data.get(address) ?? false,\n }));\n }\n\n set(data: { address: string; enabled: boolean }[]): void {\n let map: Map<string, boolean> = new Map<string, boolean>();\n\n // If we have existing cache, preserve it and update with new data\n if (this.#cache && !this.#isExpired()) {\n map = new Map(this.#cache.data);\n }\n\n // Update with new data\n data.forEach(({ address, enabled }) => {\n map.set(address, enabled);\n });\n\n this.#cache = {\n data: map,\n timestamp: Date.now(),\n };\n }\n\n // Full replace when updateOnChainNotifications is called\n replace(data: { address: string; enabled: boolean }[]): void {\n const map = new Map<string, boolean>();\n data.forEach(({ address, enabled }) => {\n map.set(address, enabled);\n });\n\n this.#cache = {\n data: map,\n timestamp: Date.now(),\n };\n }\n\n clear(): void {\n this.#cache = null;\n }\n}\n\nexport const notificationsConfigCache = new OnChainNotificationsCache();\n"]}
@@ -0,0 +1,19 @@
1
+ export declare const NotificationConfigCacheTTL: number;
2
+ export declare class OnChainNotificationsCache {
3
+ #private;
4
+ get(addresses: string[]): {
5
+ address: string;
6
+ enabled: boolean;
7
+ }[] | null;
8
+ set(data: {
9
+ address: string;
10
+ enabled: boolean;
11
+ }[]): void;
12
+ replace(data: {
13
+ address: string;
14
+ enabled: boolean;
15
+ }[]): void;
16
+ clear(): void;
17
+ }
18
+ export declare const notificationsConfigCache: OnChainNotificationsCache;
19
+ //# sourceMappingURL=notification-config-cache.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"notification-config-cache.d.cts","sourceRoot":"","sources":["../../../src/NotificationServicesController/services/notification-config-cache.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,0BAA0B,QAAY,CAAC;AAEpD,qBAAa,yBAAyB;;IAgBpC,GAAG,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,OAAO,CAAA;KAAE,EAAE,GAAG,IAAI;IAWxE,GAAG,CAAC,IAAI,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,OAAO,CAAA;KAAE,EAAE,GAAG,IAAI;IAoBxD,OAAO,CAAC,IAAI,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,OAAO,CAAA;KAAE,EAAE,GAAG,IAAI;IAY5D,KAAK,IAAI,IAAI;CAGd;AAED,eAAO,MAAM,wBAAwB,2BAAkC,CAAC"}
@@ -0,0 +1,19 @@
1
+ export declare const NotificationConfigCacheTTL: number;
2
+ export declare class OnChainNotificationsCache {
3
+ #private;
4
+ get(addresses: string[]): {
5
+ address: string;
6
+ enabled: boolean;
7
+ }[] | null;
8
+ set(data: {
9
+ address: string;
10
+ enabled: boolean;
11
+ }[]): void;
12
+ replace(data: {
13
+ address: string;
14
+ enabled: boolean;
15
+ }[]): void;
16
+ clear(): void;
17
+ }
18
+ export declare const notificationsConfigCache: OnChainNotificationsCache;
19
+ //# sourceMappingURL=notification-config-cache.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"notification-config-cache.d.mts","sourceRoot":"","sources":["../../../src/NotificationServicesController/services/notification-config-cache.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,0BAA0B,QAAY,CAAC;AAEpD,qBAAa,yBAAyB;;IAgBpC,GAAG,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,OAAO,CAAA;KAAE,EAAE,GAAG,IAAI;IAWxE,GAAG,CAAC,IAAI,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,OAAO,CAAA;KAAE,EAAE,GAAG,IAAI;IAoBxD,OAAO,CAAC,IAAI,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,OAAO,CAAA;KAAE,EAAE,GAAG,IAAI;IAY5D,KAAK,IAAI,IAAI;CAGd;AAED,eAAO,MAAM,wBAAwB,2BAAkC,CAAC"}
@@ -0,0 +1,68 @@
1
+ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
2
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
3
+ 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");
4
+ return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
5
+ };
6
+ var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
7
+ if (kind === "m") throw new TypeError("Private method is not writable");
8
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
9
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
10
+ return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
11
+ };
12
+ var _OnChainNotificationsCache_instances, _OnChainNotificationsCache_cache, _OnChainNotificationsCache_TTL, _OnChainNotificationsCache_isExpired, _OnChainNotificationsCache_hasAllAddresses;
13
+ export const NotificationConfigCacheTTL = 1000 * 60; // 60 seconds
14
+ export class OnChainNotificationsCache {
15
+ constructor() {
16
+ _OnChainNotificationsCache_instances.add(this);
17
+ _OnChainNotificationsCache_cache.set(this, null);
18
+ _OnChainNotificationsCache_TTL.set(this, NotificationConfigCacheTTL);
19
+ }
20
+ get(addresses) {
21
+ if (__classPrivateFieldGet(this, _OnChainNotificationsCache_instances, "m", _OnChainNotificationsCache_isExpired).call(this) || !__classPrivateFieldGet(this, _OnChainNotificationsCache_instances, "m", _OnChainNotificationsCache_hasAllAddresses).call(this, addresses)) {
22
+ return null;
23
+ }
24
+ return addresses.map((address) => ({
25
+ address,
26
+ enabled: __classPrivateFieldGet(this, _OnChainNotificationsCache_cache, "f")?.data.get(address) ?? false,
27
+ }));
28
+ }
29
+ set(data) {
30
+ let map = new Map();
31
+ // If we have existing cache, preserve it and update with new data
32
+ if (__classPrivateFieldGet(this, _OnChainNotificationsCache_cache, "f") && !__classPrivateFieldGet(this, _OnChainNotificationsCache_instances, "m", _OnChainNotificationsCache_isExpired).call(this)) {
33
+ map = new Map(__classPrivateFieldGet(this, _OnChainNotificationsCache_cache, "f").data);
34
+ }
35
+ // Update with new data
36
+ data.forEach(({ address, enabled }) => {
37
+ map.set(address, enabled);
38
+ });
39
+ __classPrivateFieldSet(this, _OnChainNotificationsCache_cache, {
40
+ data: map,
41
+ timestamp: Date.now(),
42
+ }, "f");
43
+ }
44
+ // Full replace when updateOnChainNotifications is called
45
+ replace(data) {
46
+ const map = new Map();
47
+ data.forEach(({ address, enabled }) => {
48
+ map.set(address, enabled);
49
+ });
50
+ __classPrivateFieldSet(this, _OnChainNotificationsCache_cache, {
51
+ data: map,
52
+ timestamp: Date.now(),
53
+ }, "f");
54
+ }
55
+ clear() {
56
+ __classPrivateFieldSet(this, _OnChainNotificationsCache_cache, null, "f");
57
+ }
58
+ }
59
+ _OnChainNotificationsCache_cache = new WeakMap(), _OnChainNotificationsCache_TTL = new WeakMap(), _OnChainNotificationsCache_instances = new WeakSet(), _OnChainNotificationsCache_isExpired = function _OnChainNotificationsCache_isExpired() {
60
+ return !__classPrivateFieldGet(this, _OnChainNotificationsCache_cache, "f") || Date.now() - __classPrivateFieldGet(this, _OnChainNotificationsCache_cache, "f").timestamp > __classPrivateFieldGet(this, _OnChainNotificationsCache_TTL, "f");
61
+ }, _OnChainNotificationsCache_hasAllAddresses = function _OnChainNotificationsCache_hasAllAddresses(addresses) {
62
+ if (!__classPrivateFieldGet(this, _OnChainNotificationsCache_cache, "f")) {
63
+ return false;
64
+ }
65
+ return addresses.every((address) => __classPrivateFieldGet(this, _OnChainNotificationsCache_cache, "f")?.data.has(address));
66
+ };
67
+ export const notificationsConfigCache = new OnChainNotificationsCache();
68
+ //# sourceMappingURL=notification-config-cache.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"notification-config-cache.mjs","sourceRoot":"","sources":["../../../src/NotificationServicesController/services/notification-config-cache.ts"],"names":[],"mappings":";;;;;;;;;;;;AAKA,MAAM,CAAC,MAAM,0BAA0B,GAAG,IAAI,GAAG,EAAE,CAAC,CAAC,aAAa;AAElE,MAAM,OAAO,yBAAyB;IAAtC;;QACE,2CAAyC,IAAI,EAAC;QAErC,yCAAO,0BAA0B,EAAC;IA2D7C,CAAC;IA9CC,GAAG,CAAC,SAAmB;QACrB,IAAI,uBAAA,IAAI,kFAAW,MAAf,IAAI,CAAa,IAAI,CAAC,uBAAA,IAAI,wFAAiB,MAArB,IAAI,EAAkB,SAAS,CAAC,EAAE;YAC1D,OAAO,IAAI,CAAC;SACb;QAED,OAAO,SAAS,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;YACjC,OAAO;YACP,OAAO,EAAE,uBAAA,IAAI,wCAAO,EAAE,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,KAAK;SACjD,CAAC,CAAC,CAAC;IACN,CAAC;IAED,GAAG,CAAC,IAA6C;QAC/C,IAAI,GAAG,GAAyB,IAAI,GAAG,EAAmB,CAAC;QAE3D,kEAAkE;QAClE,IAAI,uBAAA,IAAI,wCAAO,IAAI,CAAC,uBAAA,IAAI,kFAAW,MAAf,IAAI,CAAa,EAAE;YACrC,GAAG,GAAG,IAAI,GAAG,CAAC,uBAAA,IAAI,wCAAO,CAAC,IAAI,CAAC,CAAC;SACjC;QAED,uBAAuB;QACvB,IAAI,CAAC,OAAO,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE;YACpC,GAAG,CAAC,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAC5B,CAAC,CAAC,CAAC;QAEH,uBAAA,IAAI,oCAAU;YACZ,IAAI,EAAE,GAAG;YACT,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;SACtB,MAAA,CAAC;IACJ,CAAC;IAED,yDAAyD;IACzD,OAAO,CAAC,IAA6C;QACnD,MAAM,GAAG,GAAG,IAAI,GAAG,EAAmB,CAAC;QACvC,IAAI,CAAC,OAAO,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE;YACpC,GAAG,CAAC,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAC5B,CAAC,CAAC,CAAC;QAEH,uBAAA,IAAI,oCAAU;YACZ,IAAI,EAAE,GAAG;YACT,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;SACtB,MAAA,CAAC;IACJ,CAAC;IAED,KAAK;QACH,uBAAA,IAAI,oCAAU,IAAI,MAAA,CAAC;IACrB,CAAC;CACF;;IAxDG,OAAO,CAAC,uBAAA,IAAI,wCAAO,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,uBAAA,IAAI,wCAAO,CAAC,SAAS,GAAG,uBAAA,IAAI,sCAAK,CAAC;AACxE,CAAC,mGAEgB,SAAmB;IAClC,IAAI,CAAC,uBAAA,IAAI,wCAAO,EAAE;QAChB,OAAO,KAAK,CAAC;KACd;IACD,OAAO,SAAS,CAAC,KAAK,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,uBAAA,IAAI,wCAAO,EAAE,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC;AACtE,CAAC;AAkDH,MAAM,CAAC,MAAM,wBAAwB,GAAG,IAAI,yBAAyB,EAAE,CAAC","sourcesContent":["type NotificationConfigCache = {\n data: Map<string, boolean>;\n timestamp: number;\n};\n\nexport const NotificationConfigCacheTTL = 1000 * 60; // 60 seconds\n\nexport class OnChainNotificationsCache {\n #cache: NotificationConfigCache | null = null;\n\n readonly #TTL = NotificationConfigCacheTTL;\n\n #isExpired(): boolean {\n return !this.#cache || Date.now() - this.#cache.timestamp > this.#TTL;\n }\n\n #hasAllAddresses(addresses: string[]): boolean {\n if (!this.#cache) {\n return false;\n }\n return addresses.every((address) => this.#cache?.data.has(address));\n }\n\n get(addresses: string[]): { address: string; enabled: boolean }[] | null {\n if (this.#isExpired() || !this.#hasAllAddresses(addresses)) {\n return null;\n }\n\n return addresses.map((address) => ({\n address,\n enabled: this.#cache?.data.get(address) ?? false,\n }));\n }\n\n set(data: { address: string; enabled: boolean }[]): void {\n let map: Map<string, boolean> = new Map<string, boolean>();\n\n // If we have existing cache, preserve it and update with new data\n if (this.#cache && !this.#isExpired()) {\n map = new Map(this.#cache.data);\n }\n\n // Update with new data\n data.forEach(({ address, enabled }) => {\n map.set(address, enabled);\n });\n\n this.#cache = {\n data: map,\n timestamp: Date.now(),\n };\n }\n\n // Full replace when updateOnChainNotifications is called\n replace(data: { address: string; enabled: boolean }[]): void {\n const map = new Map<string, boolean>();\n data.forEach(({ address, enabled }) => {\n map.set(address, enabled);\n });\n\n this.#cache = {\n data: map,\n timestamp: Date.now(),\n };\n }\n\n clear(): void {\n this.#cache = null;\n }\n}\n\nexport const notificationsConfigCache = new OnChainNotificationsCache();\n"]}
@@ -3,165 +3,97 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.markNotificationsAsRead = exports.getOnChainNotifications = exports.deleteOnChainTriggers = exports.createOnChainTriggers = exports.NOTIFICATION_API_MARK_ALL_AS_READ_ENDPOINT = exports.NOTIFICATION_API_LIST_ENDPOINT_PAGE_QUERY = exports.NOTIFICATION_API_LIST_ENDPOINT = exports.TRIGGER_API_BATCH_ENDPOINT = exports.NOTIFICATION_API = exports.TRIGGER_API = void 0;
7
- const profile_sync_controller_1 = require("@metamask/profile-sync-controller");
6
+ exports.markNotificationsAsRead = exports.getOnChainNotifications = exports.updateOnChainNotifications = exports.getOnChainNotificationsConfigCached = exports.NOTIFICATION_API_MARK_ALL_AS_READ_ENDPOINT = exports.NOTIFICATION_API_LIST_ENDPOINT = exports.TRIGGER_API_NOTIFICATIONS_ENDPOINT = exports.TRIGGER_API_NOTIFICATIONS_QUERY_ENDPOINT = exports.NOTIFICATION_API = exports.TRIGGER_API = void 0;
8
7
  const loglevel_1 = __importDefault(require("loglevel"));
8
+ const notification_config_cache_1 = require("./notification-config-cache.cjs");
9
9
  const to_raw_notification_1 = require("../../shared/to-raw-notification.cjs");
10
10
  const utils_1 = require("../utils/utils.cjs");
11
11
  exports.TRIGGER_API = 'https://trigger.api.cx.metamask.io';
12
12
  exports.NOTIFICATION_API = 'https://notification.api.cx.metamask.io';
13
- exports.TRIGGER_API_BATCH_ENDPOINT = `${exports.TRIGGER_API}/api/v1/triggers/batch`;
14
- exports.NOTIFICATION_API_LIST_ENDPOINT = `${exports.NOTIFICATION_API}/api/v1/notifications`;
15
- const NOTIFICATION_API_LIST_ENDPOINT_PAGE_QUERY = (page) => `${exports.NOTIFICATION_API_LIST_ENDPOINT}?page=${page}&per_page=100`;
16
- exports.NOTIFICATION_API_LIST_ENDPOINT_PAGE_QUERY = NOTIFICATION_API_LIST_ENDPOINT_PAGE_QUERY;
17
- exports.NOTIFICATION_API_MARK_ALL_AS_READ_ENDPOINT = `${exports.NOTIFICATION_API}/api/v1/notifications/mark-as-read`;
13
+ // Gets notification settings for each account provided
14
+ exports.TRIGGER_API_NOTIFICATIONS_QUERY_ENDPOINT = `${exports.TRIGGER_API}/api/v2/notifications/query`;
15
+ // Used to create/update account notifications for each account provided
16
+ exports.TRIGGER_API_NOTIFICATIONS_ENDPOINT = `${exports.TRIGGER_API}/api/v2/notifications`;
17
+ // Lists notifications for each account provided
18
+ exports.NOTIFICATION_API_LIST_ENDPOINT = `${exports.NOTIFICATION_API}/api/v2/notifications`;
19
+ // Makrs notifications as read
20
+ exports.NOTIFICATION_API_MARK_ALL_AS_READ_ENDPOINT = `${exports.NOTIFICATION_API}/api/v2/notifications/mark-as-read`;
18
21
  /**
19
- * Creates on-chain triggers based on the provided notification triggers.
20
- * This method generates a unique token for each trigger using the trigger ID and storage key,
21
- * proving ownership of the trigger being updated. It then makes an API call to create these triggers.
22
- * Upon successful creation, it updates the userStorage to reflect the new trigger status.
22
+ * fetches notification config (accounts enabled vs disabled)
23
23
  *
24
- * @param userStorage - The user's storage object where triggers and their statuses are stored.
25
- * @param storageKey - A key used along with the trigger ID to generate a unique token for each trigger.
26
- * @param bearerToken - The JSON Web Token used for authentication in the API call.
27
- * @param triggers - An array of notification triggers to be created. Each trigger includes an ID, chain ID, kind, and address.
28
- * @returns A promise that resolves to void. Throws an error if the API call fails or if there's an issue creating the triggers.
24
+ * @param bearerToken - jwt
25
+ * @param addresses - list of addresses to check
26
+ * NOTE the API will return addresses config with false if they have not been created before.
27
+ * NOTE this is cached for 1s to prevent multiple update calls
28
+ * @returns object of notification config, or null if missing
29
29
  */
30
- async function createOnChainTriggers(userStorage, storageKey, bearerToken, triggers) {
31
- const triggersToCreate = triggers.map((t) => ({
32
- id: t.id,
33
- token: profile_sync_controller_1.UserStorageController.createSHA256Hash(t.id + storageKey),
34
- config: {
35
- kind: t.kind,
36
- chain_id: Number(t.chainId),
37
- address: t.address,
38
- },
39
- }));
40
- if (triggersToCreate.length === 0) {
41
- return;
30
+ async function getOnChainNotificationsConfigCached(bearerToken, addresses) {
31
+ if (addresses.length === 0) {
32
+ return [];
42
33
  }
43
- const response = await (0, utils_1.makeApiCall)(bearerToken, exports.TRIGGER_API_BATCH_ENDPOINT, 'POST', triggersToCreate);
44
- if (!response.ok) {
45
- const errorData = await response.json().catch(() => undefined);
46
- loglevel_1.default.error('Error creating triggers:', errorData);
47
- throw new Error('OnChain Notifications - unable to create triggers');
34
+ addresses = addresses.map((a) => a.toLowerCase());
35
+ const cached = notification_config_cache_1.notificationsConfigCache.get(addresses);
36
+ if (cached) {
37
+ return cached;
48
38
  }
49
- // If the trigger creation was fine
50
- // then update the userStorage
51
- for (const trigger of triggersToCreate) {
52
- (0, utils_1.toggleUserStorageTriggerStatus)(userStorage, trigger.config.address, String(trigger.config.chain_id), trigger.id, true);
39
+ const body = addresses.map((address) => ({ address }));
40
+ const data = await (0, utils_1.makeApiCall)(bearerToken, exports.TRIGGER_API_NOTIFICATIONS_QUERY_ENDPOINT, 'POST', body)
41
+ .then((r) => (r.ok ? r.json() : null))
42
+ .catch(() => null);
43
+ const result = data ?? [];
44
+ if (result.length > 0) {
45
+ notification_config_cache_1.notificationsConfigCache.set(result);
53
46
  }
54
- (0, utils_1.cleanUserStorage)(userStorage);
47
+ return result;
55
48
  }
56
- exports.createOnChainTriggers = createOnChainTriggers;
49
+ exports.getOnChainNotificationsConfigCached = getOnChainNotificationsConfigCached;
57
50
  /**
58
- * Deletes on-chain triggers based on the provided UUIDs.
59
- * This method generates a unique token for each trigger using the UUID and storage key,
60
- * proving ownership of the trigger being deleted. It then makes an API call to delete these triggers.
61
- * Upon successful deletion, it updates the userStorage to remove the deleted trigger statuses.
51
+ * updates notifications for a given addresses
62
52
  *
63
- * @param userStorage - The user's storage object where triggers and their statuses are stored.
64
- * @param storageKey - A key used along with the UUID to generate a unique token for each trigger.
65
- * @param bearerToken - The JSON Web Token used for authentication in the API call.
66
- * @param uuids - An array of UUIDs representing the triggers to be deleted.
67
- * @returns A promise that resolves to the updated UserStorage object. Throws an error if the API call fails or if there's an issue deleting the triggers.
53
+ * @param bearerToken - jwt
54
+ * @param addresses - list of addresses to check
55
+ * @returns void
68
56
  */
69
- async function deleteOnChainTriggers(userStorage, storageKey, bearerToken, uuids) {
70
- const triggersToDelete = uuids.map((uuid) => ({
71
- id: uuid,
72
- token: profile_sync_controller_1.UserStorageController.createSHA256Hash(uuid + storageKey),
73
- }));
74
- try {
75
- const response = await (0, utils_1.makeApiCall)(bearerToken, exports.TRIGGER_API_BATCH_ENDPOINT, 'DELETE', triggersToDelete);
76
- if (!response.ok) {
77
- throw new Error(`Failed to delete on-chain notifications for uuids ${uuids.join(', ')}`);
78
- }
79
- // Update the state of the deleted trigger to false
80
- for (const uuid of uuids) {
81
- for (const address in userStorage) {
82
- if (address in userStorage) {
83
- for (const chainId in userStorage[address]) {
84
- if (userStorage?.[address]?.[chainId]?.[uuid]) {
85
- delete userStorage[address][chainId][uuid];
86
- }
87
- }
88
- }
89
- }
90
- }
91
- // Follow-up cleanup, if an address had no triggers whatsoever, then we can delete the address
92
- const isEmpty = (obj = {}) => Object.keys(obj).length === 0;
93
- for (const address in userStorage) {
94
- if (address in userStorage) {
95
- for (const chainId in userStorage[address]) {
96
- // Chain isEmpty Check
97
- if (isEmpty(userStorage?.[address]?.[chainId])) {
98
- delete userStorage[address][chainId];
99
- }
100
- }
101
- // Address isEmpty Check
102
- if (isEmpty(userStorage?.[address])) {
103
- delete userStorage[address];
104
- }
105
- }
106
- }
107
- }
108
- catch (err) {
109
- loglevel_1.default.error(`Error deleting on-chain notifications for uuids ${uuids.join(', ')}:`, err);
110
- throw err;
57
+ async function updateOnChainNotifications(bearerToken, addresses) {
58
+ if (addresses.length === 0) {
59
+ return;
111
60
  }
112
- return userStorage;
61
+ addresses = addresses.map((a) => {
62
+ a.address = a.address.toLowerCase();
63
+ return a;
64
+ });
65
+ const body = addresses;
66
+ await (0, utils_1.makeApiCall)(bearerToken, exports.TRIGGER_API_NOTIFICATIONS_ENDPOINT, 'POST', body)
67
+ .then(() => notification_config_cache_1.notificationsConfigCache.replace(addresses))
68
+ .catch(() => null);
113
69
  }
114
- exports.deleteOnChainTriggers = deleteOnChainTriggers;
70
+ exports.updateOnChainNotifications = updateOnChainNotifications;
115
71
  /**
116
- * Fetches on-chain notifications for the given user storage and BearerToken.
117
- * This method iterates through the userStorage to find enabled triggers and fetches notifications for those triggers.
118
- * It makes paginated API calls to the notifications service, transforming and aggregating the notifications into a single array.
119
- * The process stops either when all pages have been fetched or when a page has less than 100 notifications, indicating the end of the data.
72
+ * Fetches on-chain notifications for the given addresses
120
73
  *
121
- * @param userStorage - The user's storage object containing trigger information.
122
74
  * @param bearerToken - The JSON Web Token used for authentication in the API call.
75
+ * @param addresses - List of addresses
123
76
  * @returns A promise that resolves to an array of OnChainRawNotification objects. If no triggers are enabled or an error occurs, it may return an empty array.
124
77
  */
125
- async function getOnChainNotifications(userStorage, bearerToken) {
126
- const triggerIds = (0, utils_1.traverseUserStorageTriggers)(userStorage, {
127
- mapTrigger: (t) => {
128
- if (!t.enabled) {
129
- return undefined;
130
- }
131
- return t.id;
132
- },
133
- });
134
- if (triggerIds.length === 0) {
78
+ async function getOnChainNotifications(bearerToken, addresses) {
79
+ if (addresses.length === 0) {
135
80
  return [];
136
81
  }
137
- const onChainNotifications = [];
138
- const PAGE_LIMIT = 2;
139
- for (let page = 1; page <= PAGE_LIMIT; page++) {
140
- try {
141
- const response = await (0, utils_1.makeApiCall)(bearerToken, (0, exports.NOTIFICATION_API_LIST_ENDPOINT_PAGE_QUERY)(page), 'POST', { trigger_ids: triggerIds });
142
- const notifications = (await response.json());
143
- // Transform and sort notifications
144
- const transformedNotifications = notifications
145
- .map((n) => {
146
- if (!n.data?.kind) {
147
- return undefined;
148
- }
149
- return (0, to_raw_notification_1.toRawOnChainNotification)(n);
150
- })
151
- .filter((n) => Boolean(n));
152
- onChainNotifications.push(...transformedNotifications);
153
- // if less than 100 notifications on page, then means we reached end
154
- if (notifications.length < 100) {
155
- page = PAGE_LIMIT + 1;
156
- break;
157
- }
158
- }
159
- catch (err) {
160
- loglevel_1.default.error(`Error fetching on-chain notifications for trigger IDs ${triggerIds.join(', ')}:`, err);
161
- // do nothing
82
+ addresses = addresses.map((a) => a.toLowerCase());
83
+ const body = addresses.map((address) => ({ address }));
84
+ const notifications = await (0, utils_1.makeApiCall)(bearerToken, exports.NOTIFICATION_API_LIST_ENDPOINT, 'POST', body)
85
+ .then((r) => r.ok ? r.json() : null)
86
+ .catch(() => null);
87
+ // Transform and sort notifications
88
+ const transformedNotifications = notifications
89
+ ?.map((n) => {
90
+ if (!n.data?.kind) {
91
+ return undefined;
162
92
  }
163
- }
164
- return onChainNotifications;
93
+ return (0, to_raw_notification_1.toRawOnChainNotification)(n);
94
+ })
95
+ .filter((n) => Boolean(n));
96
+ return transformedNotifications ?? [];
165
97
  }
166
98
  exports.getOnChainNotifications = getOnChainNotifications;
167
99
  /**
@@ -178,15 +110,10 @@ async function markNotificationsAsRead(bearerToken, notificationIds) {
178
110
  return;
179
111
  }
180
112
  try {
181
- const response = await (0, utils_1.makeApiCall)(bearerToken, exports.NOTIFICATION_API_MARK_ALL_AS_READ_ENDPOINT, 'POST', { ids: notificationIds });
182
- if (response.status !== 200) {
183
- const errorData = await response.json().catch(() => undefined);
184
- throw new Error(`Error marking notifications as read: ${errorData?.message}`);
185
- }
113
+ await (0, utils_1.makeApiCall)(bearerToken, exports.NOTIFICATION_API_MARK_ALL_AS_READ_ENDPOINT, 'POST', { ids: notificationIds });
186
114
  }
187
115
  catch (err) {
188
116
  loglevel_1.default.error('Error marking notifications as read:', err);
189
- throw err;
190
117
  }
191
118
  }
192
119
  exports.markNotificationsAsRead = markNotificationsAsRead;
@@ -1 +1 @@
1
- {"version":3,"file":"onchain-notifications.cjs","sourceRoot":"","sources":["../../../src/NotificationServicesController/services/onchain-notifications.ts"],"names":[],"mappings":"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","sourcesContent":["import { UserStorageController } from '@metamask/profile-sync-controller';\nimport log from 'loglevel';\n\nimport { toRawOnChainNotification } from '../../shared/to-raw-notification';\nimport type {\n OnChainRawNotification,\n UnprocessedOnChainRawNotification,\n} from '../types/on-chain-notification/on-chain-notification';\nimport type { UserStorage } from '../types/user-storage/user-storage';\nimport {\n cleanUserStorage,\n makeApiCall,\n toggleUserStorageTriggerStatus,\n traverseUserStorageTriggers,\n} from '../utils/utils';\n\nexport type NotificationTrigger = {\n id: string;\n chainId: string;\n kind: string;\n address: string;\n};\n\nexport const TRIGGER_API = 'https://trigger.api.cx.metamask.io';\nexport const NOTIFICATION_API = 'https://notification.api.cx.metamask.io';\nexport const TRIGGER_API_BATCH_ENDPOINT = `${TRIGGER_API}/api/v1/triggers/batch`;\nexport const NOTIFICATION_API_LIST_ENDPOINT = `${NOTIFICATION_API}/api/v1/notifications`;\nexport const NOTIFICATION_API_LIST_ENDPOINT_PAGE_QUERY = (page: number) =>\n `${NOTIFICATION_API_LIST_ENDPOINT}?page=${page}&per_page=100`;\nexport const NOTIFICATION_API_MARK_ALL_AS_READ_ENDPOINT = `${NOTIFICATION_API}/api/v1/notifications/mark-as-read`;\n\n/**\n * Creates on-chain triggers based on the provided notification triggers.\n * This method generates a unique token for each trigger using the trigger ID and storage key,\n * proving ownership of the trigger being updated. It then makes an API call to create these triggers.\n * Upon successful creation, it updates the userStorage to reflect the new trigger status.\n *\n * @param userStorage - The user's storage object where triggers and their statuses are stored.\n * @param storageKey - A key used along with the trigger ID to generate a unique token for each trigger.\n * @param bearerToken - The JSON Web Token used for authentication in the API call.\n * @param triggers - An array of notification triggers to be created. Each trigger includes an ID, chain ID, kind, and address.\n * @returns A promise that resolves to void. Throws an error if the API call fails or if there's an issue creating the triggers.\n */\nexport async function createOnChainTriggers(\n userStorage: UserStorage,\n storageKey: string,\n bearerToken: string,\n triggers: NotificationTrigger[],\n): Promise<void> {\n type RequestPayloadTrigger = {\n id: string;\n // this is the trigger token, generated by using the uuid + storage key. It proves you own the trigger you are updating\n token: string;\n config: {\n kind: string;\n chain_id: number;\n address: string;\n };\n };\n const triggersToCreate: RequestPayloadTrigger[] = triggers.map((t) => ({\n id: t.id,\n token: UserStorageController.createSHA256Hash(t.id + storageKey),\n config: {\n kind: t.kind,\n chain_id: Number(t.chainId),\n address: t.address,\n },\n }));\n\n if (triggersToCreate.length === 0) {\n return;\n }\n\n const response = await makeApiCall(\n bearerToken,\n TRIGGER_API_BATCH_ENDPOINT,\n 'POST',\n triggersToCreate,\n );\n\n if (!response.ok) {\n const errorData = await response.json().catch(() => undefined);\n log.error('Error creating triggers:', errorData);\n throw new Error('OnChain Notifications - unable to create triggers');\n }\n\n // If the trigger creation was fine\n // then update the userStorage\n for (const trigger of triggersToCreate) {\n toggleUserStorageTriggerStatus(\n userStorage,\n trigger.config.address,\n String(trigger.config.chain_id),\n trigger.id,\n true,\n );\n }\n\n cleanUserStorage(userStorage);\n}\n\n/**\n * Deletes on-chain triggers based on the provided UUIDs.\n * This method generates a unique token for each trigger using the UUID and storage key,\n * proving ownership of the trigger being deleted. It then makes an API call to delete these triggers.\n * Upon successful deletion, it updates the userStorage to remove the deleted trigger statuses.\n *\n * @param userStorage - The user's storage object where triggers and their statuses are stored.\n * @param storageKey - A key used along with the UUID to generate a unique token for each trigger.\n * @param bearerToken - The JSON Web Token used for authentication in the API call.\n * @param uuids - An array of UUIDs representing the triggers to be deleted.\n * @returns A promise that resolves to the updated UserStorage object. Throws an error if the API call fails or if there's an issue deleting the triggers.\n */\nexport async function deleteOnChainTriggers(\n userStorage: UserStorage,\n storageKey: string,\n bearerToken: string,\n uuids: string[],\n): Promise<UserStorage> {\n const triggersToDelete = uuids.map((uuid) => ({\n id: uuid,\n token: UserStorageController.createSHA256Hash(uuid + storageKey),\n }));\n\n try {\n const response = await makeApiCall(\n bearerToken,\n TRIGGER_API_BATCH_ENDPOINT,\n 'DELETE',\n triggersToDelete,\n );\n\n if (!response.ok) {\n throw new Error(\n `Failed to delete on-chain notifications for uuids ${uuids.join(', ')}`,\n );\n }\n\n // Update the state of the deleted trigger to false\n for (const uuid of uuids) {\n for (const address in userStorage) {\n if (address in userStorage) {\n for (const chainId in userStorage[address]) {\n if (userStorage?.[address]?.[chainId]?.[uuid]) {\n delete userStorage[address][chainId][uuid];\n }\n }\n }\n }\n }\n\n // Follow-up cleanup, if an address had no triggers whatsoever, then we can delete the address\n const isEmpty = (obj = {}) => Object.keys(obj).length === 0;\n for (const address in userStorage) {\n if (address in userStorage) {\n for (const chainId in userStorage[address]) {\n // Chain isEmpty Check\n if (isEmpty(userStorage?.[address]?.[chainId])) {\n delete userStorage[address][chainId];\n }\n }\n\n // Address isEmpty Check\n if (isEmpty(userStorage?.[address])) {\n delete userStorage[address];\n }\n }\n }\n } catch (err) {\n log.error(\n `Error deleting on-chain notifications for uuids ${uuids.join(', ')}:`,\n err,\n );\n throw err;\n }\n\n return userStorage;\n}\n\n/**\n * Fetches on-chain notifications for the given user storage and BearerToken.\n * This method iterates through the userStorage to find enabled triggers and fetches notifications for those triggers.\n * It makes paginated API calls to the notifications service, transforming and aggregating the notifications into a single array.\n * The process stops either when all pages have been fetched or when a page has less than 100 notifications, indicating the end of the data.\n *\n * @param userStorage - The user's storage object containing trigger information.\n * @param bearerToken - The JSON Web Token used for authentication in the API call.\n * @returns A promise that resolves to an array of OnChainRawNotification objects. If no triggers are enabled or an error occurs, it may return an empty array.\n */\nexport async function getOnChainNotifications(\n userStorage: UserStorage,\n bearerToken: string,\n): Promise<OnChainRawNotification[]> {\n const triggerIds = traverseUserStorageTriggers(userStorage, {\n mapTrigger: (t) => {\n if (!t.enabled) {\n return undefined;\n }\n return t.id;\n },\n });\n\n if (triggerIds.length === 0) {\n return [];\n }\n\n const onChainNotifications: OnChainRawNotification[] = [];\n const PAGE_LIMIT = 2;\n for (let page = 1; page <= PAGE_LIMIT; page++) {\n try {\n const response = await makeApiCall(\n bearerToken,\n NOTIFICATION_API_LIST_ENDPOINT_PAGE_QUERY(page),\n 'POST',\n { trigger_ids: triggerIds },\n );\n\n const notifications =\n (await response.json()) as UnprocessedOnChainRawNotification[];\n\n // Transform and sort notifications\n const transformedNotifications = notifications\n .map((n): OnChainRawNotification | undefined => {\n if (!n.data?.kind) {\n return undefined;\n }\n\n return toRawOnChainNotification(n);\n })\n .filter((n): n is OnChainRawNotification => Boolean(n));\n\n onChainNotifications.push(...transformedNotifications);\n\n // if less than 100 notifications on page, then means we reached end\n if (notifications.length < 100) {\n page = PAGE_LIMIT + 1;\n break;\n }\n } catch (err) {\n log.error(\n `Error fetching on-chain notifications for trigger IDs ${triggerIds.join(\n ', ',\n )}:`,\n err,\n );\n // do nothing\n }\n }\n\n return onChainNotifications;\n}\n\n/**\n * Marks the specified notifications as read.\n * This method sends a POST request to the notifications service to mark the provided notification IDs as read.\n * If the operation is successful, it completes without error. If the operation fails, it throws an error with details.\n *\n * @param bearerToken - The JSON Web Token used for authentication in the API call.\n * @param notificationIds - An array of notification IDs to be marked as read.\n * @returns A promise that resolves to void. The promise will reject if there's an error during the API call or if the response status is not 200.\n */\nexport async function markNotificationsAsRead(\n bearerToken: string,\n notificationIds: string[],\n): Promise<void> {\n if (notificationIds.length === 0) {\n return;\n }\n\n try {\n const response = await makeApiCall(\n bearerToken,\n NOTIFICATION_API_MARK_ALL_AS_READ_ENDPOINT,\n 'POST',\n { ids: notificationIds },\n );\n\n if (response.status !== 200) {\n const errorData = await response.json().catch(() => undefined);\n throw new Error(\n `Error marking notifications as read: ${errorData?.message as string}`,\n );\n }\n } catch (err) {\n log.error('Error marking notifications as read:', err);\n throw err;\n }\n}\n"]}
1
+ {"version":3,"file":"onchain-notifications.cjs","sourceRoot":"","sources":["../../../src/NotificationServicesController/services/onchain-notifications.ts"],"names":[],"mappings":"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","sourcesContent":["import log from 'loglevel';\n\nimport { notificationsConfigCache } from './notification-config-cache';\nimport { toRawOnChainNotification } from '../../shared/to-raw-notification';\nimport type {\n OnChainRawNotification,\n UnprocessedOnChainRawNotification,\n} from '../types/on-chain-notification/on-chain-notification';\nimport { makeApiCall } from '../utils/utils';\n\nexport type NotificationTrigger = {\n id: string;\n chainId: string;\n kind: string;\n address: string;\n};\n\nexport const TRIGGER_API = 'https://trigger.api.cx.metamask.io';\nexport const NOTIFICATION_API = 'https://notification.api.cx.metamask.io';\n\n// Gets notification settings for each account provided\nexport const TRIGGER_API_NOTIFICATIONS_QUERY_ENDPOINT = `${TRIGGER_API}/api/v2/notifications/query`;\n\n// Used to create/update account notifications for each account provided\nexport const TRIGGER_API_NOTIFICATIONS_ENDPOINT = `${TRIGGER_API}/api/v2/notifications`;\n\n// Lists notifications for each account provided\nexport const NOTIFICATION_API_LIST_ENDPOINT = `${NOTIFICATION_API}/api/v2/notifications`;\n\n// Makrs notifications as read\nexport const NOTIFICATION_API_MARK_ALL_AS_READ_ENDPOINT = `${NOTIFICATION_API}/api/v2/notifications/mark-as-read`;\n\n/**\n * fetches notification config (accounts enabled vs disabled)\n *\n * @param bearerToken - jwt\n * @param addresses - list of addresses to check\n * NOTE the API will return addresses config with false if they have not been created before.\n * NOTE this is cached for 1s to prevent multiple update calls\n * @returns object of notification config, or null if missing\n */\nexport async function getOnChainNotificationsConfigCached(\n bearerToken: string,\n addresses: string[],\n) {\n if (addresses.length === 0) {\n return [];\n }\n\n addresses = addresses.map((a) => a.toLowerCase());\n\n const cached = notificationsConfigCache.get(addresses);\n if (cached) {\n return cached;\n }\n\n type RequestBody = { address: string }[];\n type Response = { address: string; enabled: boolean }[];\n const body: RequestBody = addresses.map((address) => ({ address }));\n const data = await makeApiCall(\n bearerToken,\n TRIGGER_API_NOTIFICATIONS_QUERY_ENDPOINT,\n 'POST',\n body,\n )\n .then<Response | null>((r) => (r.ok ? r.json() : null))\n .catch(() => null);\n\n const result = data ?? [];\n\n if (result.length > 0) {\n notificationsConfigCache.set(result);\n }\n\n return result;\n}\n\n/**\n * updates notifications for a given addresses\n *\n * @param bearerToken - jwt\n * @param addresses - list of addresses to check\n * @returns void\n */\nexport async function updateOnChainNotifications(\n bearerToken: string,\n addresses: { address: string; enabled: boolean }[],\n) {\n if (addresses.length === 0) {\n return;\n }\n\n addresses = addresses.map((a) => {\n a.address = a.address.toLowerCase();\n return a;\n });\n\n type RequestBody = { address: string; enabled: boolean }[];\n const body: RequestBody = addresses;\n await makeApiCall(\n bearerToken,\n TRIGGER_API_NOTIFICATIONS_ENDPOINT,\n 'POST',\n body,\n )\n .then(() => notificationsConfigCache.replace(addresses))\n .catch(() => null);\n}\n\n/**\n * Fetches on-chain notifications for the given addresses\n *\n * @param bearerToken - The JSON Web Token used for authentication in the API call.\n * @param addresses - List of addresses\n * @returns A promise that resolves to an array of OnChainRawNotification objects. If no triggers are enabled or an error occurs, it may return an empty array.\n */\nexport async function getOnChainNotifications(\n bearerToken: string,\n addresses: string[],\n): Promise<OnChainRawNotification[]> {\n if (addresses.length === 0) {\n return [];\n }\n\n addresses = addresses.map((a) => a.toLowerCase());\n\n type RequestBody = { address: string }[];\n const body: RequestBody = addresses.map((address) => ({ address }));\n const notifications = await makeApiCall(\n bearerToken,\n NOTIFICATION_API_LIST_ENDPOINT,\n 'POST',\n body,\n )\n .then<UnprocessedOnChainRawNotification[] | null>((r) =>\n r.ok ? r.json() : null,\n )\n .catch(() => null);\n\n // Transform and sort notifications\n const transformedNotifications = notifications\n ?.map((n): OnChainRawNotification | undefined => {\n if (!n.data?.kind) {\n return undefined;\n }\n\n return toRawOnChainNotification(n);\n })\n .filter((n): n is OnChainRawNotification => Boolean(n));\n\n return transformedNotifications ?? [];\n}\n\n/**\n * Marks the specified notifications as read.\n * This method sends a POST request to the notifications service to mark the provided notification IDs as read.\n * If the operation is successful, it completes without error. If the operation fails, it throws an error with details.\n *\n * @param bearerToken - The JSON Web Token used for authentication in the API call.\n * @param notificationIds - An array of notification IDs to be marked as read.\n * @returns A promise that resolves to void. The promise will reject if there's an error during the API call or if the response status is not 200.\n */\nexport async function markNotificationsAsRead(\n bearerToken: string,\n notificationIds: string[],\n): Promise<void> {\n if (notificationIds.length === 0) {\n return;\n }\n\n try {\n await makeApiCall(\n bearerToken,\n NOTIFICATION_API_MARK_ALL_AS_READ_ENDPOINT,\n 'POST',\n { ids: notificationIds },\n );\n } catch (err) {\n log.error('Error marking notifications as read:', err);\n }\n}\n"]}
@@ -1,5 +1,4 @@
1
1
  import type { OnChainRawNotification } from "../types/on-chain-notification/on-chain-notification.cjs";
2
- import type { UserStorage } from "../types/user-storage/user-storage.cjs";
3
2
  export type NotificationTrigger = {
4
3
  id: string;
5
4
  chainId: string;
@@ -8,47 +7,42 @@ export type NotificationTrigger = {
8
7
  };
9
8
  export declare const TRIGGER_API = "https://trigger.api.cx.metamask.io";
10
9
  export declare const NOTIFICATION_API = "https://notification.api.cx.metamask.io";
11
- export declare const TRIGGER_API_BATCH_ENDPOINT = "https://trigger.api.cx.metamask.io/api/v1/triggers/batch";
12
- export declare const NOTIFICATION_API_LIST_ENDPOINT = "https://notification.api.cx.metamask.io/api/v1/notifications";
13
- export declare const NOTIFICATION_API_LIST_ENDPOINT_PAGE_QUERY: (page: number) => string;
14
- export declare const NOTIFICATION_API_MARK_ALL_AS_READ_ENDPOINT = "https://notification.api.cx.metamask.io/api/v1/notifications/mark-as-read";
10
+ export declare const TRIGGER_API_NOTIFICATIONS_QUERY_ENDPOINT = "https://trigger.api.cx.metamask.io/api/v2/notifications/query";
11
+ export declare const TRIGGER_API_NOTIFICATIONS_ENDPOINT = "https://trigger.api.cx.metamask.io/api/v2/notifications";
12
+ export declare const NOTIFICATION_API_LIST_ENDPOINT = "https://notification.api.cx.metamask.io/api/v2/notifications";
13
+ export declare const NOTIFICATION_API_MARK_ALL_AS_READ_ENDPOINT = "https://notification.api.cx.metamask.io/api/v2/notifications/mark-as-read";
15
14
  /**
16
- * Creates on-chain triggers based on the provided notification triggers.
17
- * This method generates a unique token for each trigger using the trigger ID and storage key,
18
- * proving ownership of the trigger being updated. It then makes an API call to create these triggers.
19
- * Upon successful creation, it updates the userStorage to reflect the new trigger status.
15
+ * fetches notification config (accounts enabled vs disabled)
20
16
  *
21
- * @param userStorage - The user's storage object where triggers and their statuses are stored.
22
- * @param storageKey - A key used along with the trigger ID to generate a unique token for each trigger.
23
- * @param bearerToken - The JSON Web Token used for authentication in the API call.
24
- * @param triggers - An array of notification triggers to be created. Each trigger includes an ID, chain ID, kind, and address.
25
- * @returns A promise that resolves to void. Throws an error if the API call fails or if there's an issue creating the triggers.
17
+ * @param bearerToken - jwt
18
+ * @param addresses - list of addresses to check
19
+ * NOTE the API will return addresses config with false if they have not been created before.
20
+ * NOTE this is cached for 1s to prevent multiple update calls
21
+ * @returns object of notification config, or null if missing
26
22
  */
27
- export declare function createOnChainTriggers(userStorage: UserStorage, storageKey: string, bearerToken: string, triggers: NotificationTrigger[]): Promise<void>;
23
+ export declare function getOnChainNotificationsConfigCached(bearerToken: string, addresses: string[]): Promise<{
24
+ address: string;
25
+ enabled: boolean;
26
+ }[]>;
28
27
  /**
29
- * Deletes on-chain triggers based on the provided UUIDs.
30
- * This method generates a unique token for each trigger using the UUID and storage key,
31
- * proving ownership of the trigger being deleted. It then makes an API call to delete these triggers.
32
- * Upon successful deletion, it updates the userStorage to remove the deleted trigger statuses.
28
+ * updates notifications for a given addresses
33
29
  *
34
- * @param userStorage - The user's storage object where triggers and their statuses are stored.
35
- * @param storageKey - A key used along with the UUID to generate a unique token for each trigger.
36
- * @param bearerToken - The JSON Web Token used for authentication in the API call.
37
- * @param uuids - An array of UUIDs representing the triggers to be deleted.
38
- * @returns A promise that resolves to the updated UserStorage object. Throws an error if the API call fails or if there's an issue deleting the triggers.
30
+ * @param bearerToken - jwt
31
+ * @param addresses - list of addresses to check
32
+ * @returns void
39
33
  */
40
- export declare function deleteOnChainTriggers(userStorage: UserStorage, storageKey: string, bearerToken: string, uuids: string[]): Promise<UserStorage>;
34
+ export declare function updateOnChainNotifications(bearerToken: string, addresses: {
35
+ address: string;
36
+ enabled: boolean;
37
+ }[]): Promise<void>;
41
38
  /**
42
- * Fetches on-chain notifications for the given user storage and BearerToken.
43
- * This method iterates through the userStorage to find enabled triggers and fetches notifications for those triggers.
44
- * It makes paginated API calls to the notifications service, transforming and aggregating the notifications into a single array.
45
- * The process stops either when all pages have been fetched or when a page has less than 100 notifications, indicating the end of the data.
39
+ * Fetches on-chain notifications for the given addresses
46
40
  *
47
- * @param userStorage - The user's storage object containing trigger information.
48
41
  * @param bearerToken - The JSON Web Token used for authentication in the API call.
42
+ * @param addresses - List of addresses
49
43
  * @returns A promise that resolves to an array of OnChainRawNotification objects. If no triggers are enabled or an error occurs, it may return an empty array.
50
44
  */
51
- export declare function getOnChainNotifications(userStorage: UserStorage, bearerToken: string): Promise<OnChainRawNotification[]>;
45
+ export declare function getOnChainNotifications(bearerToken: string, addresses: string[]): Promise<OnChainRawNotification[]>;
52
46
  /**
53
47
  * Marks the specified notifications as read.
54
48
  * This method sends a POST request to the notifications service to mark the provided notification IDs as read.
@@ -1 +1 @@
1
- {"version":3,"file":"onchain-notifications.d.cts","sourceRoot":"","sources":["../../../src/NotificationServicesController/services/onchain-notifications.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACV,sBAAsB,EAEvB,iEAA6D;AAC9D,OAAO,KAAK,EAAE,WAAW,EAAE,+CAA2C;AAQtE,MAAM,MAAM,mBAAmB,GAAG;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,eAAO,MAAM,WAAW,uCAAuC,CAAC;AAChE,eAAO,MAAM,gBAAgB,4CAA4C,CAAC;AAC1E,eAAO,MAAM,0BAA0B,6DAAyC,CAAC;AACjF,eAAO,MAAM,8BAA8B,iEAA6C,CAAC;AACzF,eAAO,MAAM,yCAAyC,SAAU,MAAM,WACP,CAAC;AAChE,eAAO,MAAM,0CAA0C,8EAA0D,CAAC;AAElH;;;;;;;;;;;GAWG;AACH,wBAAsB,qBAAqB,CACzC,WAAW,EAAE,WAAW,EACxB,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,mBAAmB,EAAE,GAC9B,OAAO,CAAC,IAAI,CAAC,CAmDf;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,qBAAqB,CACzC,WAAW,EAAE,WAAW,EACxB,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,MAAM,EAAE,GACd,OAAO,CAAC,WAAW,CAAC,CA2DtB;AAED;;;;;;;;;GASG;AACH,wBAAsB,uBAAuB,CAC3C,WAAW,EAAE,WAAW,EACxB,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,sBAAsB,EAAE,CAAC,CA0DnC;AAED;;;;;;;;GAQG;AACH,wBAAsB,uBAAuB,CAC3C,WAAW,EAAE,MAAM,EACnB,eAAe,EAAE,MAAM,EAAE,GACxB,OAAO,CAAC,IAAI,CAAC,CAuBf"}
1
+ {"version":3,"file":"onchain-notifications.d.cts","sourceRoot":"","sources":["../../../src/NotificationServicesController/services/onchain-notifications.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACV,sBAAsB,EAEvB,iEAA6D;AAG9D,MAAM,MAAM,mBAAmB,GAAG;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,eAAO,MAAM,WAAW,uCAAuC,CAAC;AAChE,eAAO,MAAM,gBAAgB,4CAA4C,CAAC;AAG1E,eAAO,MAAM,wCAAwC,kEAA8C,CAAC;AAGpG,eAAO,MAAM,kCAAkC,4DAAwC,CAAC;AAGxF,eAAO,MAAM,8BAA8B,iEAA6C,CAAC;AAGzF,eAAO,MAAM,0CAA0C,8EAA0D,CAAC;AAElH;;;;;;;;GAQG;AACH,wBAAsB,mCAAmC,CACvD,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,EAAE;;;KAgCpB;AAED;;;;;;GAMG;AACH,wBAAsB,0BAA0B,CAC9C,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,EAAE,iBAqBnD;AAED;;;;;;GAMG;AACH,wBAAsB,uBAAuB,CAC3C,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,EAAE,GAClB,OAAO,CAAC,sBAAsB,EAAE,CAAC,CAgCnC;AAED;;;;;;;;GAQG;AACH,wBAAsB,uBAAuB,CAC3C,WAAW,EAAE,MAAM,EACnB,eAAe,EAAE,MAAM,EAAE,GACxB,OAAO,CAAC,IAAI,CAAC,CAef"}