@metamask/snaps-controllers 12.3.1 → 13.0.0

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 (88) hide show
  1. package/CHANGELOG.md +25 -1
  2. package/dist/cronjob/CronjobController.cjs +250 -276
  3. package/dist/cronjob/CronjobController.cjs.map +1 -1
  4. package/dist/cronjob/CronjobController.d.cts +61 -78
  5. package/dist/cronjob/CronjobController.d.cts.map +1 -1
  6. package/dist/cronjob/CronjobController.d.mts +61 -78
  7. package/dist/cronjob/CronjobController.d.mts.map +1 -1
  8. package/dist/cronjob/CronjobController.mjs +251 -277
  9. package/dist/cronjob/CronjobController.mjs.map +1 -1
  10. package/dist/cronjob/utils.cjs +79 -0
  11. package/dist/cronjob/utils.cjs.map +1 -0
  12. package/dist/cronjob/utils.d.cts +25 -0
  13. package/dist/cronjob/utils.d.cts.map +1 -0
  14. package/dist/cronjob/utils.d.mts +25 -0
  15. package/dist/cronjob/utils.d.mts.map +1 -0
  16. package/dist/cronjob/utils.mjs +75 -0
  17. package/dist/cronjob/utils.mjs.map +1 -0
  18. package/dist/insights/SnapInsightsController.cjs +199 -149
  19. package/dist/insights/SnapInsightsController.cjs.map +1 -1
  20. package/dist/insights/SnapInsightsController.mjs +198 -148
  21. package/dist/insights/SnapInsightsController.mjs.map +1 -1
  22. package/dist/interface/SnapInterfaceController.cjs +160 -101
  23. package/dist/interface/SnapInterfaceController.cjs.map +1 -1
  24. package/dist/interface/SnapInterfaceController.mjs +160 -101
  25. package/dist/interface/SnapInterfaceController.mjs.map +1 -1
  26. package/dist/multichain/MultichainRouter.cjs +117 -114
  27. package/dist/multichain/MultichainRouter.cjs.map +1 -1
  28. package/dist/multichain/MultichainRouter.mjs +117 -114
  29. package/dist/multichain/MultichainRouter.mjs.map +1 -1
  30. package/dist/services/AbstractExecutionService.cjs +131 -139
  31. package/dist/services/AbstractExecutionService.cjs.map +1 -1
  32. package/dist/services/AbstractExecutionService.mjs +131 -139
  33. package/dist/services/AbstractExecutionService.mjs.map +1 -1
  34. package/dist/services/ProxyPostMessageStream.cjs +19 -26
  35. package/dist/services/ProxyPostMessageStream.cjs.map +1 -1
  36. package/dist/services/ProxyPostMessageStream.mjs +19 -26
  37. package/dist/services/ProxyPostMessageStream.mjs.map +1 -1
  38. package/dist/services/iframe/IframeExecutionService.cjs +1 -0
  39. package/dist/services/iframe/IframeExecutionService.cjs.map +1 -1
  40. package/dist/services/iframe/IframeExecutionService.mjs +1 -0
  41. package/dist/services/iframe/IframeExecutionService.mjs.map +1 -1
  42. package/dist/services/offscreen/OffscreenExecutionService.cjs +3 -16
  43. package/dist/services/offscreen/OffscreenExecutionService.cjs.map +1 -1
  44. package/dist/services/offscreen/OffscreenExecutionService.mjs +3 -16
  45. package/dist/services/offscreen/OffscreenExecutionService.mjs.map +1 -1
  46. package/dist/services/proxy/ProxyExecutionService.cjs +4 -17
  47. package/dist/services/proxy/ProxyExecutionService.cjs.map +1 -1
  48. package/dist/services/proxy/ProxyExecutionService.mjs +4 -17
  49. package/dist/services/proxy/ProxyExecutionService.mjs.map +1 -1
  50. package/dist/services/webview/WebViewExecutionService.cjs +6 -19
  51. package/dist/services/webview/WebViewExecutionService.cjs.map +1 -1
  52. package/dist/services/webview/WebViewExecutionService.mjs +6 -19
  53. package/dist/services/webview/WebViewExecutionService.mjs.map +1 -1
  54. package/dist/services/webview/WebViewMessageStream.cjs +13 -26
  55. package/dist/services/webview/WebViewMessageStream.cjs.map +1 -1
  56. package/dist/services/webview/WebViewMessageStream.mjs +13 -26
  57. package/dist/services/webview/WebViewMessageStream.mjs.map +1 -1
  58. package/dist/snaps/SnapController.cjs +1370 -1161
  59. package/dist/snaps/SnapController.cjs.map +1 -1
  60. package/dist/snaps/SnapController.d.cts +4 -4
  61. package/dist/snaps/SnapController.d.cts.map +1 -1
  62. package/dist/snaps/SnapController.d.mts +4 -4
  63. package/dist/snaps/SnapController.d.mts.map +1 -1
  64. package/dist/snaps/SnapController.mjs +1370 -1161
  65. package/dist/snaps/SnapController.mjs.map +1 -1
  66. package/dist/snaps/Timer.cjs +4 -0
  67. package/dist/snaps/Timer.cjs.map +1 -1
  68. package/dist/snaps/Timer.mjs +4 -0
  69. package/dist/snaps/Timer.mjs.map +1 -1
  70. package/dist/snaps/location/http.cjs +20 -4
  71. package/dist/snaps/location/http.cjs.map +1 -1
  72. package/dist/snaps/location/http.mjs +20 -4
  73. package/dist/snaps/location/http.mjs.map +1 -1
  74. package/dist/snaps/location/local.cjs +4 -17
  75. package/dist/snaps/location/local.cjs.map +1 -1
  76. package/dist/snaps/location/local.mjs +4 -17
  77. package/dist/snaps/location/local.mjs.map +1 -1
  78. package/dist/snaps/location/npm.cjs +28 -48
  79. package/dist/snaps/location/npm.cjs.map +1 -1
  80. package/dist/snaps/location/npm.d.cts.map +1 -1
  81. package/dist/snaps/location/npm.d.mts.map +1 -1
  82. package/dist/snaps/location/npm.mjs +28 -48
  83. package/dist/snaps/location/npm.mjs.map +1 -1
  84. package/dist/snaps/registry/json.cjs +173 -166
  85. package/dist/snaps/registry/json.cjs.map +1 -1
  86. package/dist/snaps/registry/json.mjs +172 -165
  87. package/dist/snaps/registry/json.mjs.map +1 -1
  88. package/package.json +9 -9
@@ -1,10 +1,4 @@
1
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 _SnapInterfaceController_instances, _SnapInterfaceController_registerMessageHandlers, _SnapInterfaceController_validateArgs, _SnapInterfaceController_validateApproval, _SnapInterfaceController_checkPhishingList, _SnapInterfaceController_hasApprovalRequest, _SnapInterfaceController_acceptApprovalRequest, _SnapInterfaceController_getSelectedAccount, _SnapInterfaceController_listAccounts, _SnapInterfaceController_getAccountByAddress, _SnapInterfaceController_getAssetsState, _SnapInterfaceController_getSnap, _SnapInterfaceController_validateContent, _SnapInterfaceController_onNotificationsListUpdated;
8
2
  Object.defineProperty(exports, "__esModule", { value: true });
9
3
  exports.SnapInterfaceController = void 0;
10
4
  const base_controller_1 = require("@metamask/base-controller");
@@ -42,9 +36,20 @@ class SnapInterfaceController extends base_controller_1.BaseController {
42
36
  name: controllerName,
43
37
  state: { interfaces: {}, ...state },
44
38
  });
45
- _SnapInterfaceController_instances.add(this);
46
- this.messagingSystem.subscribe('NotificationServicesController:notificationsListUpdated', __classPrivateFieldGet(this, _SnapInterfaceController_instances, "m", _SnapInterfaceController_onNotificationsListUpdated).bind(this));
47
- __classPrivateFieldGet(this, _SnapInterfaceController_instances, "m", _SnapInterfaceController_registerMessageHandlers).call(this);
39
+ this.messagingSystem.subscribe('NotificationServicesController:notificationsListUpdated', this.#onNotificationsListUpdated.bind(this));
40
+ this.#registerMessageHandlers();
41
+ }
42
+ /**
43
+ * Constructor helper for registering this controller's messaging system
44
+ * actions.
45
+ */
46
+ #registerMessageHandlers() {
47
+ this.messagingSystem.registerActionHandler(`${controllerName}:createInterface`, this.createInterface.bind(this));
48
+ this.messagingSystem.registerActionHandler(`${controllerName}:getInterface`, this.getInterface.bind(this));
49
+ this.messagingSystem.registerActionHandler(`${controllerName}:updateInterface`, this.updateInterface.bind(this));
50
+ this.messagingSystem.registerActionHandler(`${controllerName}:deleteInterface`, this.deleteInterface.bind(this));
51
+ this.messagingSystem.registerActionHandler(`${controllerName}:updateInterfaceState`, this.updateInterfaceState.bind(this));
52
+ this.messagingSystem.registerActionHandler(`${controllerName}:resolveInterface`, this.resolveInterface.bind(this));
48
53
  }
49
54
  /**
50
55
  * Create an interface in the controller state with the associated data.
@@ -57,14 +62,14 @@ class SnapInterfaceController extends base_controller_1.BaseController {
57
62
  */
58
63
  async createInterface(snapId, content, context, contentType) {
59
64
  const element = (0, utils_2.getJsxInterface)(content);
60
- await __classPrivateFieldGet(this, _SnapInterfaceController_instances, "m", _SnapInterfaceController_validateContent).call(this, element);
65
+ await this.#validateContent(element);
61
66
  (0, utils_2.validateInterfaceContext)(context);
62
67
  const id = (0, nanoid_1.nanoid)();
63
68
  const componentState = (0, utils_2.constructState)({}, element, {
64
- getAssetsState: __classPrivateFieldGet(this, _SnapInterfaceController_instances, "m", _SnapInterfaceController_getAssetsState).bind(this),
65
- getAccountByAddress: __classPrivateFieldGet(this, _SnapInterfaceController_instances, "m", _SnapInterfaceController_getAccountByAddress).bind(this),
66
- getSelectedAccount: __classPrivateFieldGet(this, _SnapInterfaceController_instances, "m", _SnapInterfaceController_getSelectedAccount).bind(this),
67
- listAccounts: __classPrivateFieldGet(this, _SnapInterfaceController_instances, "m", _SnapInterfaceController_listAccounts).bind(this),
69
+ getAssetsState: this.#getAssetsState.bind(this),
70
+ getAccountByAddress: this.#getAccountByAddress.bind(this),
71
+ getSelectedAccount: this.#getSelectedAccount.bind(this),
72
+ listAccounts: this.#listAccounts.bind(this),
68
73
  snapOwnsAccount: (account) => (0, snaps_utils_1.snapOwnsAccount)(snapId, account),
69
74
  });
70
75
  this.update((draftState) => {
@@ -88,7 +93,7 @@ class SnapInterfaceController extends base_controller_1.BaseController {
88
93
  * @returns The interface state.
89
94
  */
90
95
  getInterface(snapId, id) {
91
- __classPrivateFieldGet(this, _SnapInterfaceController_instances, "m", _SnapInterfaceController_validateArgs).call(this, snapId, id);
96
+ this.#validateArgs(snapId, id);
92
97
  return this.state.interfaces[id];
93
98
  }
94
99
  /**
@@ -100,16 +105,16 @@ class SnapInterfaceController extends base_controller_1.BaseController {
100
105
  * @param context - An optional interface context object.
101
106
  */
102
107
  async updateInterface(snapId, id, content, context) {
103
- __classPrivateFieldGet(this, _SnapInterfaceController_instances, "m", _SnapInterfaceController_validateArgs).call(this, snapId, id);
108
+ this.#validateArgs(snapId, id);
104
109
  const element = (0, utils_2.getJsxInterface)(content);
105
- await __classPrivateFieldGet(this, _SnapInterfaceController_instances, "m", _SnapInterfaceController_validateContent).call(this, element);
110
+ await this.#validateContent(element);
106
111
  (0, utils_2.validateInterfaceContext)(context);
107
112
  const oldState = this.state.interfaces[id].state;
108
113
  const newState = (0, utils_2.constructState)(oldState, element, {
109
- getAssetsState: __classPrivateFieldGet(this, _SnapInterfaceController_instances, "m", _SnapInterfaceController_getAssetsState).bind(this),
110
- getAccountByAddress: __classPrivateFieldGet(this, _SnapInterfaceController_instances, "m", _SnapInterfaceController_getAccountByAddress).bind(this),
111
- getSelectedAccount: __classPrivateFieldGet(this, _SnapInterfaceController_instances, "m", _SnapInterfaceController_getSelectedAccount).bind(this),
112
- listAccounts: __classPrivateFieldGet(this, _SnapInterfaceController_instances, "m", _SnapInterfaceController_listAccounts).bind(this),
114
+ getAssetsState: this.#getAssetsState.bind(this),
115
+ getAccountByAddress: this.#getAccountByAddress.bind(this),
116
+ getSelectedAccount: this.#getSelectedAccount.bind(this),
117
+ listAccounts: this.#listAccounts.bind(this),
113
118
  snapOwnsAccount: (account) => (0, snaps_utils_1.snapOwnsAccount)(snapId, account),
114
119
  });
115
120
  this.update((draftState) => {
@@ -150,88 +155,142 @@ class SnapInterfaceController extends base_controller_1.BaseController {
150
155
  * @param value - The value to resolve the promise with.
151
156
  */
152
157
  async resolveInterface(snapId, id, value) {
153
- __classPrivateFieldGet(this, _SnapInterfaceController_instances, "m", _SnapInterfaceController_validateArgs).call(this, snapId, id);
154
- __classPrivateFieldGet(this, _SnapInterfaceController_instances, "m", _SnapInterfaceController_validateApproval).call(this, id);
155
- await __classPrivateFieldGet(this, _SnapInterfaceController_instances, "m", _SnapInterfaceController_acceptApprovalRequest).call(this, id, value);
158
+ this.#validateArgs(snapId, id);
159
+ this.#validateApproval(id);
160
+ await this.#acceptApprovalRequest(id, value);
156
161
  this.deleteInterface(id);
157
162
  }
163
+ /**
164
+ * Utility function to validate the args passed to the other methods.
165
+ *
166
+ * @param snapId - The snap id.
167
+ * @param id - The interface id.
168
+ */
169
+ #validateArgs(snapId, id) {
170
+ const existingInterface = this.state.interfaces[id];
171
+ (0, utils_1.assert)(existingInterface !== undefined, `Interface with id '${id}' not found.`);
172
+ (0, utils_1.assert)(existingInterface.snapId === snapId, `Interface not created by ${snapId}.`);
173
+ }
174
+ /**
175
+ * Utility function to validate that the approval request exists.
176
+ *
177
+ * @param id - The interface id.
178
+ */
179
+ #validateApproval(id) {
180
+ (0, utils_1.assert)(this.#hasApprovalRequest(id), `Approval request with id '${id}' not found.`);
181
+ }
182
+ /**
183
+ * Check an origin against the phishing list.
184
+ *
185
+ * @param origin - The origin to check.
186
+ * @returns True if the origin is on the phishing list, otherwise false.
187
+ */
188
+ #checkPhishingList(origin) {
189
+ return this.messagingSystem.call('PhishingController:testOrigin', origin)
190
+ .result;
191
+ }
192
+ /**
193
+ * Check if an approval request exists for a given interface by looking up
194
+ * if the ApprovalController has a request with the given interface ID.
195
+ *
196
+ * @param id - The interface id.
197
+ * @returns True if an approval request exists, otherwise false.
198
+ */
199
+ #hasApprovalRequest(id) {
200
+ return this.messagingSystem.call('ApprovalController:hasRequest', {
201
+ id,
202
+ });
203
+ }
204
+ /**
205
+ * Accept an approval request for a given interface.
206
+ *
207
+ * @param id - The interface id.
208
+ * @param value - The value to resolve the promise with.
209
+ */
210
+ async #acceptApprovalRequest(id, value) {
211
+ await this.messagingSystem.call('ApprovalController:acceptRequest', id, value);
212
+ }
213
+ /**
214
+ * Get the selected account in the client.
215
+ *
216
+ * @returns The selected account.
217
+ */
218
+ #getSelectedAccount() {
219
+ return this.messagingSystem.call('AccountsController:getSelectedMultichainAccount');
220
+ }
221
+ /**
222
+ * Get a list of accounts for the given chain IDs.
223
+ *
224
+ * @param chainIds - The chain IDs to get the accounts for.
225
+ * @returns The list of accounts.
226
+ */
227
+ #listAccounts(chainIds) {
228
+ const accounts = this.messagingSystem.call('AccountsController:listMultichainAccounts');
229
+ if (!chainIds || chainIds.length === 0) {
230
+ return accounts;
231
+ }
232
+ return accounts.filter((account) => account.scopes.some((scope) => (0, utils_2.isMatchingChainId)(scope, chainIds)));
233
+ }
234
+ /**
235
+ * Get an account by its address.
236
+ *
237
+ * @param address - The account address.
238
+ * @returns The account or undefined if not found.
239
+ */
240
+ #getAccountByAddress(address) {
241
+ const { address: parsedAddress } = (0, utils_1.parseCaipAccountId)(address);
242
+ return this.messagingSystem.call('AccountsController:getAccountByAddress', parsedAddress);
243
+ }
244
+ /**
245
+ * Get the MultichainAssetsController state.
246
+ *
247
+ * @returns The MultichainAssetsController state.
248
+ */
249
+ #getAssetsState() {
250
+ return this.messagingSystem.call('MultichainAssetsController:getState');
251
+ }
252
+ /**
253
+ * Get a snap by its id.
254
+ *
255
+ * @param id - The snap id.
256
+ * @returns The snap.
257
+ */
258
+ #getSnap(id) {
259
+ return this.messagingSystem.call('SnapController:get', id);
260
+ }
261
+ /**
262
+ * Utility function to validate the components of an interface.
263
+ * Throws if something is invalid.
264
+ *
265
+ * @param element - The JSX element to verify.
266
+ */
267
+ async #validateContent(element) {
268
+ // We assume the validity of this JSON to be validated by the caller.
269
+ // E.g., in the RPC method implementation.
270
+ const size = (0, snaps_utils_1.getJsonSizeUnsafe)(element);
271
+ (0, utils_1.assert)(size <= MAX_UI_CONTENT_SIZE, `A Snap UI may not be larger than ${MAX_UI_CONTENT_SIZE / 1000000} MB.`);
272
+ (0, snaps_utils_1.validateJsxElements)(element, {
273
+ isOnPhishingList: this.#checkPhishingList.bind(this),
274
+ getSnap: this.#getSnap.bind(this),
275
+ getAccountByAddress: this.#getAccountByAddress.bind(this),
276
+ });
277
+ }
278
+ #onNotificationsListUpdated(notificationsList) {
279
+ const snapNotificationsWithInterface = notificationsList.filter((notification) => {
280
+ return (notification.type === 'snap' &&
281
+ (0, utils_1.hasProperty)(notification.data, 'detailedView'));
282
+ });
283
+ const interfaceIdSet = new Set(snapNotificationsWithInterface.map((notification) => notification
284
+ .data.detailedView.interfaceId));
285
+ this.update((state) => {
286
+ Object.entries(state.interfaces).forEach(([id, snapInterface]) => {
287
+ if (snapInterface.contentType === snaps_sdk_1.ContentType.Notification &&
288
+ !interfaceIdSet.has(id)) {
289
+ delete state.interfaces[id];
290
+ }
291
+ });
292
+ });
293
+ }
158
294
  }
159
295
  exports.SnapInterfaceController = SnapInterfaceController;
160
- _SnapInterfaceController_instances = new WeakSet(), _SnapInterfaceController_registerMessageHandlers = function _SnapInterfaceController_registerMessageHandlers() {
161
- this.messagingSystem.registerActionHandler(`${controllerName}:createInterface`, this.createInterface.bind(this));
162
- this.messagingSystem.registerActionHandler(`${controllerName}:getInterface`, this.getInterface.bind(this));
163
- this.messagingSystem.registerActionHandler(`${controllerName}:updateInterface`, this.updateInterface.bind(this));
164
- this.messagingSystem.registerActionHandler(`${controllerName}:deleteInterface`, this.deleteInterface.bind(this));
165
- this.messagingSystem.registerActionHandler(`${controllerName}:updateInterfaceState`, this.updateInterfaceState.bind(this));
166
- this.messagingSystem.registerActionHandler(`${controllerName}:resolveInterface`, this.resolveInterface.bind(this));
167
- }, _SnapInterfaceController_validateArgs = function _SnapInterfaceController_validateArgs(snapId, id) {
168
- const existingInterface = this.state.interfaces[id];
169
- (0, utils_1.assert)(existingInterface !== undefined, `Interface with id '${id}' not found.`);
170
- (0, utils_1.assert)(existingInterface.snapId === snapId, `Interface not created by ${snapId}.`);
171
- }, _SnapInterfaceController_validateApproval = function _SnapInterfaceController_validateApproval(id) {
172
- (0, utils_1.assert)(__classPrivateFieldGet(this, _SnapInterfaceController_instances, "m", _SnapInterfaceController_hasApprovalRequest).call(this, id), `Approval request with id '${id}' not found.`);
173
- }, _SnapInterfaceController_checkPhishingList = function _SnapInterfaceController_checkPhishingList(origin) {
174
- return this.messagingSystem.call('PhishingController:testOrigin', origin)
175
- .result;
176
- }, _SnapInterfaceController_hasApprovalRequest = function _SnapInterfaceController_hasApprovalRequest(id) {
177
- return this.messagingSystem.call('ApprovalController:hasRequest', {
178
- id,
179
- });
180
- }, _SnapInterfaceController_acceptApprovalRequest =
181
- /**
182
- * Accept an approval request for a given interface.
183
- *
184
- * @param id - The interface id.
185
- * @param value - The value to resolve the promise with.
186
- */
187
- async function _SnapInterfaceController_acceptApprovalRequest(id, value) {
188
- await this.messagingSystem.call('ApprovalController:acceptRequest', id, value);
189
- }, _SnapInterfaceController_getSelectedAccount = function _SnapInterfaceController_getSelectedAccount() {
190
- return this.messagingSystem.call('AccountsController:getSelectedMultichainAccount');
191
- }, _SnapInterfaceController_listAccounts = function _SnapInterfaceController_listAccounts(chainIds) {
192
- const accounts = this.messagingSystem.call('AccountsController:listMultichainAccounts');
193
- if (!chainIds || chainIds.length === 0) {
194
- return accounts;
195
- }
196
- return accounts.filter((account) => account.scopes.some((scope) => (0, utils_2.isMatchingChainId)(scope, chainIds)));
197
- }, _SnapInterfaceController_getAccountByAddress = function _SnapInterfaceController_getAccountByAddress(address) {
198
- const { address: parsedAddress } = (0, utils_1.parseCaipAccountId)(address);
199
- return this.messagingSystem.call('AccountsController:getAccountByAddress', parsedAddress);
200
- }, _SnapInterfaceController_getAssetsState = function _SnapInterfaceController_getAssetsState() {
201
- return this.messagingSystem.call('MultichainAssetsController:getState');
202
- }, _SnapInterfaceController_getSnap = function _SnapInterfaceController_getSnap(id) {
203
- return this.messagingSystem.call('SnapController:get', id);
204
- }, _SnapInterfaceController_validateContent =
205
- /**
206
- * Utility function to validate the components of an interface.
207
- * Throws if something is invalid.
208
- *
209
- * @param element - The JSX element to verify.
210
- */
211
- async function _SnapInterfaceController_validateContent(element) {
212
- // We assume the validity of this JSON to be validated by the caller.
213
- // E.g., in the RPC method implementation.
214
- const size = (0, snaps_utils_1.getJsonSizeUnsafe)(element);
215
- (0, utils_1.assert)(size <= MAX_UI_CONTENT_SIZE, `A Snap UI may not be larger than ${MAX_UI_CONTENT_SIZE / 1000000} MB.`);
216
- (0, snaps_utils_1.validateJsxElements)(element, {
217
- isOnPhishingList: __classPrivateFieldGet(this, _SnapInterfaceController_instances, "m", _SnapInterfaceController_checkPhishingList).bind(this),
218
- getSnap: __classPrivateFieldGet(this, _SnapInterfaceController_instances, "m", _SnapInterfaceController_getSnap).bind(this),
219
- getAccountByAddress: __classPrivateFieldGet(this, _SnapInterfaceController_instances, "m", _SnapInterfaceController_getAccountByAddress).bind(this),
220
- });
221
- }, _SnapInterfaceController_onNotificationsListUpdated = function _SnapInterfaceController_onNotificationsListUpdated(notificationsList) {
222
- const snapNotificationsWithInterface = notificationsList.filter((notification) => {
223
- return (notification.type === 'snap' &&
224
- (0, utils_1.hasProperty)(notification.data, 'detailedView'));
225
- });
226
- const interfaceIdSet = new Set(snapNotificationsWithInterface.map((notification) => notification
227
- .data.detailedView.interfaceId));
228
- this.update((state) => {
229
- Object.entries(state.interfaces).forEach(([id, snapInterface]) => {
230
- if (snapInterface.contentType === snaps_sdk_1.ContentType.Notification &&
231
- !interfaceIdSet.has(id)) {
232
- delete state.interfaces[id];
233
- }
234
- });
235
- });
236
- };
237
296
  //# sourceMappingURL=SnapInterfaceController.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"SnapInterfaceController.cjs","sourceRoot":"","sources":["../../src/interface/SnapInterfaceController.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n AcceptRequest,\n HasApprovalRequest,\n} from '@metamask/approval-controller';\nimport type {\n RestrictedMessenger,\n ControllerGetStateAction,\n ControllerStateChangeEvent,\n} from '@metamask/base-controller';\nimport { BaseController } from '@metamask/base-controller';\nimport type { TestOrigin } from '@metamask/phishing-controller';\nimport type {\n InterfaceState,\n SnapId,\n ComponentOrElement,\n InterfaceContext,\n FungibleAssetMetadata,\n} from '@metamask/snaps-sdk';\nimport { ContentType } from '@metamask/snaps-sdk';\nimport type { JSXElement } from '@metamask/snaps-sdk/jsx';\nimport type { InternalAccount } from '@metamask/snaps-utils';\nimport {\n getJsonSizeUnsafe,\n snapOwnsAccount,\n validateJsxElements,\n} from '@metamask/snaps-utils';\nimport type {\n CaipAccountId,\n CaipAssetType,\n CaipChainId,\n Json,\n} from '@metamask/utils';\nimport { assert, hasProperty, parseCaipAccountId } from '@metamask/utils';\nimport { castDraft } from 'immer';\nimport { nanoid } from 'nanoid';\n\nimport {\n constructState,\n getJsxInterface,\n isMatchingChainId,\n validateInterfaceContext,\n} from './utils';\nimport type { GetSnap } from '../snaps';\n\nconst MAX_UI_CONTENT_SIZE = 10_000_000; // 10 mb\n\nconst controllerName = 'SnapInterfaceController';\n\nexport type CreateInterface = {\n type: `${typeof controllerName}:createInterface`;\n handler: SnapInterfaceController['createInterface'];\n};\n\nexport type GetInterface = {\n type: `${typeof controllerName}:getInterface`;\n handler: SnapInterfaceController['getInterface'];\n};\n\nexport type UpdateInterface = {\n type: `${typeof controllerName}:updateInterface`;\n handler: SnapInterfaceController['updateInterface'];\n};\n\nexport type DeleteInterface = {\n type: `${typeof controllerName}:deleteInterface`;\n handler: SnapInterfaceController['deleteInterface'];\n};\n\nexport type UpdateInterfaceState = {\n type: `${typeof controllerName}:updateInterfaceState`;\n handler: SnapInterfaceController['updateInterfaceState'];\n};\n\nexport type ResolveInterface = {\n type: `${typeof controllerName}:resolveInterface`;\n handler: SnapInterfaceController['resolveInterface'];\n};\n\ntype AccountsControllerGetAccountByAddressAction = {\n type: `AccountsController:getAccountByAddress`;\n handler: (address: string) => InternalAccount | undefined;\n};\n\ntype AccountsControllerGetSelectedMultichainAccountAction = {\n type: `AccountsController:getSelectedMultichainAccount`;\n handler: () => InternalAccount;\n};\n\ntype AccountsControllerListMultichainAccountsAction = {\n type: `AccountsController:listMultichainAccounts`;\n handler: (chainId?: CaipChainId) => InternalAccount[];\n};\n\nexport type SnapInterfaceControllerGetStateAction = ControllerGetStateAction<\n typeof controllerName,\n SnapInterfaceControllerState\n>;\n\ntype MultichainAssetsControllerGetStateAction = ControllerGetStateAction<\n 'MultichainAssetsController',\n {\n assetsMetadata: {\n [asset: CaipAssetType]: FungibleAssetMetadata;\n };\n accountsAssets: { [account: string]: CaipAssetType[] };\n }\n>;\n\nexport type SnapInterfaceControllerAllowedActions =\n | TestOrigin\n | HasApprovalRequest\n | AcceptRequest\n | GetSnap\n | MultichainAssetsControllerGetStateAction\n | AccountsControllerGetSelectedMultichainAccountAction\n | AccountsControllerGetAccountByAddressAction\n | AccountsControllerListMultichainAccountsAction;\n\nexport type SnapInterfaceControllerActions =\n | CreateInterface\n | GetInterface\n | UpdateInterface\n | DeleteInterface\n | UpdateInterfaceState\n | ResolveInterface\n | SnapInterfaceControllerGetStateAction;\n\nexport type SnapInterfaceControllerStateChangeEvent =\n ControllerStateChangeEvent<\n typeof controllerName,\n SnapInterfaceControllerState\n >;\n\ntype OtherNotification = { type: string; [key: string]: unknown };\n\nexport type ExpandedView = {\n title: string;\n interfaceId: string;\n footerLink?: { href: string; text: string };\n};\n\ntype NormalSnapNotificationData = { message: string; origin: string };\n\ntype ExpandedSnapNotificationData = {\n message: string;\n origin: string;\n detailedView: ExpandedView;\n};\n\ntype SnapNotification = {\n type: 'snap';\n data: NormalSnapNotificationData | ExpandedSnapNotificationData;\n readDate: string | null;\n};\n\ntype Notification = OtherNotification | SnapNotification;\n\ntype NotificationListUpdatedEvent = {\n type: 'NotificationServicesController:notificationsListUpdated';\n payload: [Notification[]];\n};\n\nexport type SnapInterfaceControllerEvents =\n | SnapInterfaceControllerStateChangeEvent\n | NotificationListUpdatedEvent;\n\nexport type SnapInterfaceControllerMessenger = RestrictedMessenger<\n typeof controllerName,\n SnapInterfaceControllerActions | SnapInterfaceControllerAllowedActions,\n SnapInterfaceControllerEvents,\n SnapInterfaceControllerAllowedActions['type'],\n SnapInterfaceControllerEvents['type']\n>;\n\nexport type StoredInterface = {\n snapId: SnapId;\n content: JSXElement;\n state: InterfaceState;\n context: InterfaceContext | null;\n contentType: ContentType | null;\n};\n\nexport type SnapInterfaceControllerState = {\n interfaces: Record<string, StoredInterface>;\n};\n\nexport type SnapInterfaceControllerArgs = {\n messenger: SnapInterfaceControllerMessenger;\n state?: SnapInterfaceControllerState;\n};\n\n/**\n * Use this controller to manage snaps UI interfaces using RPC method hooks.\n */\nexport class SnapInterfaceController extends BaseController<\n typeof controllerName,\n SnapInterfaceControllerState,\n SnapInterfaceControllerMessenger\n> {\n constructor({ messenger, state }: SnapInterfaceControllerArgs) {\n super({\n messenger,\n metadata: {\n interfaces: {\n persist: (interfaces: Record<string, StoredInterface>) => {\n return Object.entries(interfaces).reduce<\n Record<string, StoredInterface>\n >((persistedInterfaces, [id, snapInterface]) => {\n switch (snapInterface.contentType) {\n case ContentType.Notification:\n persistedInterfaces[id] = snapInterface;\n return persistedInterfaces;\n default:\n return persistedInterfaces;\n }\n }, {});\n },\n anonymous: false,\n },\n },\n name: controllerName,\n state: { interfaces: {}, ...state },\n });\n\n this.messagingSystem.subscribe(\n 'NotificationServicesController:notificationsListUpdated',\n this.#onNotificationsListUpdated.bind(this),\n );\n\n this.#registerMessageHandlers();\n }\n\n /**\n * Constructor helper for registering this controller's messaging system\n * actions.\n */\n #registerMessageHandlers() {\n this.messagingSystem.registerActionHandler(\n `${controllerName}:createInterface`,\n this.createInterface.bind(this),\n );\n\n this.messagingSystem.registerActionHandler(\n `${controllerName}:getInterface`,\n this.getInterface.bind(this),\n );\n\n this.messagingSystem.registerActionHandler(\n `${controllerName}:updateInterface`,\n this.updateInterface.bind(this),\n );\n\n this.messagingSystem.registerActionHandler(\n `${controllerName}:deleteInterface`,\n this.deleteInterface.bind(this),\n );\n\n this.messagingSystem.registerActionHandler(\n `${controllerName}:updateInterfaceState`,\n this.updateInterfaceState.bind(this),\n );\n\n this.messagingSystem.registerActionHandler(\n `${controllerName}:resolveInterface`,\n this.resolveInterface.bind(this),\n );\n }\n\n /**\n * Create an interface in the controller state with the associated data.\n *\n * @param snapId - The snap id that created the interface.\n * @param content - The interface content.\n * @param context - An optional interface context object.\n * @param contentType - The type of content.\n * @returns The newly interface id.\n */\n async createInterface(\n snapId: SnapId,\n content: ComponentOrElement,\n context?: InterfaceContext,\n contentType?: ContentType,\n ) {\n const element = getJsxInterface(content);\n await this.#validateContent(element);\n validateInterfaceContext(context);\n\n const id = nanoid();\n const componentState = constructState({}, element, {\n getAssetsState: this.#getAssetsState.bind(this),\n getAccountByAddress: this.#getAccountByAddress.bind(this),\n getSelectedAccount: this.#getSelectedAccount.bind(this),\n listAccounts: this.#listAccounts.bind(this),\n snapOwnsAccount: (account: InternalAccount) =>\n snapOwnsAccount(snapId, account),\n });\n\n this.update((draftState) => {\n // @ts-expect-error - TS2589: Type instantiation is excessively deep and\n // possibly infinite.\n draftState.interfaces[id] = {\n snapId,\n content: castDraft(element),\n state: componentState,\n context: context ?? null,\n contentType: contentType ?? null,\n };\n });\n\n return id;\n }\n\n /**\n * Get the data of a given interface id.\n *\n * @param snapId - The snap id requesting the interface data.\n * @param id - The interface id.\n * @returns The interface state.\n */\n getInterface(snapId: SnapId, id: string) {\n this.#validateArgs(snapId, id);\n\n return this.state.interfaces[id];\n }\n\n /**\n * Update the interface with the given content.\n *\n * @param snapId - The snap id requesting the update.\n * @param id - The interface id.\n * @param content - The new content.\n * @param context - An optional interface context object.\n */\n async updateInterface(\n snapId: SnapId,\n id: string,\n content: ComponentOrElement,\n context?: InterfaceContext,\n ) {\n this.#validateArgs(snapId, id);\n const element = getJsxInterface(content);\n await this.#validateContent(element);\n validateInterfaceContext(context);\n\n const oldState = this.state.interfaces[id].state;\n const newState = constructState(oldState, element, {\n getAssetsState: this.#getAssetsState.bind(this),\n getAccountByAddress: this.#getAccountByAddress.bind(this),\n getSelectedAccount: this.#getSelectedAccount.bind(this),\n listAccounts: this.#listAccounts.bind(this),\n snapOwnsAccount: (account: InternalAccount) =>\n snapOwnsAccount(snapId, account),\n });\n\n this.update((draftState) => {\n draftState.interfaces[id].state = newState;\n draftState.interfaces[id].content = castDraft(element);\n if (context) {\n draftState.interfaces[id].context = context;\n }\n });\n }\n\n /**\n * Delete an interface from state.\n *\n * @param id - The interface id.\n */\n deleteInterface(id: string) {\n this.update((draftState) => {\n delete draftState.interfaces[id];\n });\n }\n\n /**\n * Update the interface state.\n *\n * @param id - The interface id.\n * @param state - The new state.\n */\n updateInterfaceState(id: string, state: InterfaceState) {\n this.update((draftState) => {\n draftState.interfaces[id].state = state;\n });\n }\n\n /**\n * Resolve the promise of a given interface approval request.\n * The approval needs to have the same ID as the interface.\n *\n * @param snapId - The snap id.\n * @param id - The interface id.\n * @param value - The value to resolve the promise with.\n */\n async resolveInterface(snapId: SnapId, id: string, value: Json) {\n this.#validateArgs(snapId, id);\n this.#validateApproval(id);\n\n await this.#acceptApprovalRequest(id, value);\n\n this.deleteInterface(id);\n }\n\n /**\n * Utility function to validate the args passed to the other methods.\n *\n * @param snapId - The snap id.\n * @param id - The interface id.\n */\n #validateArgs(snapId: SnapId, id: string) {\n const existingInterface = this.state.interfaces[id];\n\n assert(\n existingInterface !== undefined,\n `Interface with id '${id}' not found.`,\n );\n assert(\n existingInterface.snapId === snapId,\n `Interface not created by ${snapId}.`,\n );\n }\n\n /**\n * Utility function to validate that the approval request exists.\n *\n * @param id - The interface id.\n */\n #validateApproval(id: string) {\n assert(\n this.#hasApprovalRequest(id),\n `Approval request with id '${id}' not found.`,\n );\n }\n\n /**\n * Check an origin against the phishing list.\n *\n * @param origin - The origin to check.\n * @returns True if the origin is on the phishing list, otherwise false.\n */\n #checkPhishingList(origin: string) {\n return this.messagingSystem.call('PhishingController:testOrigin', origin)\n .result;\n }\n\n /**\n * Check if an approval request exists for a given interface by looking up\n * if the ApprovalController has a request with the given interface ID.\n *\n * @param id - The interface id.\n * @returns True if an approval request exists, otherwise false.\n */\n #hasApprovalRequest(id: string) {\n return this.messagingSystem.call('ApprovalController:hasRequest', {\n id,\n });\n }\n\n /**\n * Accept an approval request for a given interface.\n *\n * @param id - The interface id.\n * @param value - The value to resolve the promise with.\n */\n async #acceptApprovalRequest(id: string, value: Json) {\n await this.messagingSystem.call(\n 'ApprovalController:acceptRequest',\n id,\n value,\n );\n }\n\n /**\n * Get the selected account in the client.\n *\n * @returns The selected account.\n */\n #getSelectedAccount() {\n return this.messagingSystem.call(\n 'AccountsController:getSelectedMultichainAccount',\n );\n }\n\n /**\n * Get a list of accounts for the given chain IDs.\n *\n * @param chainIds - The chain IDs to get the accounts for.\n * @returns The list of accounts.\n */\n #listAccounts(chainIds?: CaipChainId[]) {\n const accounts = this.messagingSystem.call(\n 'AccountsController:listMultichainAccounts',\n );\n\n if (!chainIds || chainIds.length === 0) {\n return accounts;\n }\n\n return accounts.filter((account) =>\n account.scopes.some((scope) => isMatchingChainId(scope, chainIds)),\n );\n }\n\n /**\n * Get an account by its address.\n *\n * @param address - The account address.\n * @returns The account or undefined if not found.\n */\n #getAccountByAddress(address: CaipAccountId) {\n const { address: parsedAddress } = parseCaipAccountId(address);\n\n return this.messagingSystem.call(\n 'AccountsController:getAccountByAddress',\n parsedAddress,\n );\n }\n\n /**\n * Get the MultichainAssetsController state.\n *\n * @returns The MultichainAssetsController state.\n */\n #getAssetsState() {\n return this.messagingSystem.call('MultichainAssetsController:getState');\n }\n\n /**\n * Get a snap by its id.\n *\n * @param id - The snap id.\n * @returns The snap.\n */\n #getSnap(id: string) {\n return this.messagingSystem.call('SnapController:get', id);\n }\n\n /**\n * Utility function to validate the components of an interface.\n * Throws if something is invalid.\n *\n * @param element - The JSX element to verify.\n */\n async #validateContent(element: JSXElement) {\n // We assume the validity of this JSON to be validated by the caller.\n // E.g., in the RPC method implementation.\n const size = getJsonSizeUnsafe(element);\n assert(\n size <= MAX_UI_CONTENT_SIZE,\n `A Snap UI may not be larger than ${MAX_UI_CONTENT_SIZE / 1000000} MB.`,\n );\n\n validateJsxElements(element, {\n isOnPhishingList: this.#checkPhishingList.bind(this),\n getSnap: this.#getSnap.bind(this),\n getAccountByAddress: this.#getAccountByAddress.bind(this),\n });\n }\n\n #onNotificationsListUpdated(notificationsList: Notification[]) {\n const snapNotificationsWithInterface = notificationsList.filter(\n (notification) => {\n return (\n notification.type === 'snap' &&\n hasProperty((notification as SnapNotification).data, 'detailedView')\n );\n },\n );\n\n const interfaceIdSet = new Set(\n snapNotificationsWithInterface.map(\n (notification) =>\n (\n (notification as SnapNotification)\n .data as ExpandedSnapNotificationData\n ).detailedView.interfaceId,\n ),\n );\n\n this.update((state) => {\n Object.entries(state.interfaces).forEach(([id, snapInterface]) => {\n if (\n snapInterface.contentType === ContentType.Notification &&\n !interfaceIdSet.has(id)\n ) {\n delete state.interfaces[id];\n }\n });\n });\n }\n}\n"]}
1
+ {"version":3,"file":"SnapInterfaceController.cjs","sourceRoot":"","sources":["../../src/interface/SnapInterfaceController.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n AcceptRequest,\n HasApprovalRequest,\n} from '@metamask/approval-controller';\nimport type {\n RestrictedMessenger,\n ControllerGetStateAction,\n ControllerStateChangeEvent,\n} from '@metamask/base-controller';\nimport { BaseController } from '@metamask/base-controller';\nimport type { TestOrigin } from '@metamask/phishing-controller';\nimport type {\n InterfaceState,\n SnapId,\n ComponentOrElement,\n InterfaceContext,\n FungibleAssetMetadata,\n} from '@metamask/snaps-sdk';\nimport { ContentType } from '@metamask/snaps-sdk';\nimport type { JSXElement } from '@metamask/snaps-sdk/jsx';\nimport type { InternalAccount } from '@metamask/snaps-utils';\nimport {\n getJsonSizeUnsafe,\n snapOwnsAccount,\n validateJsxElements,\n} from '@metamask/snaps-utils';\nimport type {\n CaipAccountId,\n CaipAssetType,\n CaipChainId,\n Json,\n} from '@metamask/utils';\nimport { assert, hasProperty, parseCaipAccountId } from '@metamask/utils';\nimport { castDraft } from 'immer';\nimport { nanoid } from 'nanoid';\n\nimport {\n constructState,\n getJsxInterface,\n isMatchingChainId,\n validateInterfaceContext,\n} from './utils';\nimport type { GetSnap } from '../snaps';\n\nconst MAX_UI_CONTENT_SIZE = 10_000_000; // 10 mb\n\nconst controllerName = 'SnapInterfaceController';\n\nexport type CreateInterface = {\n type: `${typeof controllerName}:createInterface`;\n handler: SnapInterfaceController['createInterface'];\n};\n\nexport type GetInterface = {\n type: `${typeof controllerName}:getInterface`;\n handler: SnapInterfaceController['getInterface'];\n};\n\nexport type UpdateInterface = {\n type: `${typeof controllerName}:updateInterface`;\n handler: SnapInterfaceController['updateInterface'];\n};\n\nexport type DeleteInterface = {\n type: `${typeof controllerName}:deleteInterface`;\n handler: SnapInterfaceController['deleteInterface'];\n};\n\nexport type UpdateInterfaceState = {\n type: `${typeof controllerName}:updateInterfaceState`;\n handler: SnapInterfaceController['updateInterfaceState'];\n};\n\nexport type ResolveInterface = {\n type: `${typeof controllerName}:resolveInterface`;\n handler: SnapInterfaceController['resolveInterface'];\n};\n\ntype AccountsControllerGetAccountByAddressAction = {\n type: `AccountsController:getAccountByAddress`;\n handler: (address: string) => InternalAccount | undefined;\n};\n\ntype AccountsControllerGetSelectedMultichainAccountAction = {\n type: `AccountsController:getSelectedMultichainAccount`;\n handler: () => InternalAccount;\n};\n\ntype AccountsControllerListMultichainAccountsAction = {\n type: `AccountsController:listMultichainAccounts`;\n handler: (chainId?: CaipChainId) => InternalAccount[];\n};\n\nexport type SnapInterfaceControllerGetStateAction = ControllerGetStateAction<\n typeof controllerName,\n SnapInterfaceControllerState\n>;\n\ntype MultichainAssetsControllerGetStateAction = ControllerGetStateAction<\n 'MultichainAssetsController',\n {\n assetsMetadata: {\n [asset: CaipAssetType]: FungibleAssetMetadata;\n };\n accountsAssets: { [account: string]: CaipAssetType[] };\n }\n>;\n\nexport type SnapInterfaceControllerAllowedActions =\n | TestOrigin\n | HasApprovalRequest\n | AcceptRequest\n | GetSnap\n | MultichainAssetsControllerGetStateAction\n | AccountsControllerGetSelectedMultichainAccountAction\n | AccountsControllerGetAccountByAddressAction\n | AccountsControllerListMultichainAccountsAction;\n\nexport type SnapInterfaceControllerActions =\n | CreateInterface\n | GetInterface\n | UpdateInterface\n | DeleteInterface\n | UpdateInterfaceState\n | ResolveInterface\n | SnapInterfaceControllerGetStateAction;\n\nexport type SnapInterfaceControllerStateChangeEvent =\n ControllerStateChangeEvent<\n typeof controllerName,\n SnapInterfaceControllerState\n >;\n\ntype OtherNotification = { type: string; [key: string]: unknown };\n\nexport type ExpandedView = {\n title: string;\n interfaceId: string;\n footerLink?: { href: string; text: string };\n};\n\ntype NormalSnapNotificationData = { message: string; origin: string };\n\ntype ExpandedSnapNotificationData = {\n message: string;\n origin: string;\n detailedView: ExpandedView;\n};\n\ntype SnapNotification = {\n type: 'snap';\n data: NormalSnapNotificationData | ExpandedSnapNotificationData;\n readDate: string | null;\n};\n\ntype Notification = OtherNotification | SnapNotification;\n\ntype NotificationListUpdatedEvent = {\n type: 'NotificationServicesController:notificationsListUpdated';\n payload: [Notification[]];\n};\n\nexport type SnapInterfaceControllerEvents =\n | SnapInterfaceControllerStateChangeEvent\n | NotificationListUpdatedEvent;\n\nexport type SnapInterfaceControllerMessenger = RestrictedMessenger<\n typeof controllerName,\n SnapInterfaceControllerActions | SnapInterfaceControllerAllowedActions,\n SnapInterfaceControllerEvents,\n SnapInterfaceControllerAllowedActions['type'],\n SnapInterfaceControllerEvents['type']\n>;\n\nexport type StoredInterface = {\n snapId: SnapId;\n content: JSXElement;\n state: InterfaceState;\n context: InterfaceContext | null;\n contentType: ContentType | null;\n};\n\nexport type SnapInterfaceControllerState = {\n interfaces: Record<string, StoredInterface>;\n};\n\nexport type SnapInterfaceControllerArgs = {\n messenger: SnapInterfaceControllerMessenger;\n state?: SnapInterfaceControllerState;\n};\n\n/**\n * Use this controller to manage snaps UI interfaces using RPC method hooks.\n */\nexport class SnapInterfaceController extends BaseController<\n typeof controllerName,\n SnapInterfaceControllerState,\n SnapInterfaceControllerMessenger\n> {\n constructor({ messenger, state }: SnapInterfaceControllerArgs) {\n super({\n messenger,\n metadata: {\n interfaces: {\n persist: (interfaces: Record<string, StoredInterface>) => {\n return Object.entries(interfaces).reduce<\n Record<string, StoredInterface>\n >((persistedInterfaces, [id, snapInterface]) => {\n switch (snapInterface.contentType) {\n case ContentType.Notification:\n persistedInterfaces[id] = snapInterface;\n return persistedInterfaces;\n default:\n return persistedInterfaces;\n }\n }, {});\n },\n anonymous: false,\n },\n },\n name: controllerName,\n state: { interfaces: {}, ...state },\n });\n\n this.messagingSystem.subscribe(\n 'NotificationServicesController:notificationsListUpdated',\n this.#onNotificationsListUpdated.bind(this),\n );\n\n this.#registerMessageHandlers();\n }\n\n /**\n * Constructor helper for registering this controller's messaging system\n * actions.\n */\n #registerMessageHandlers() {\n this.messagingSystem.registerActionHandler(\n `${controllerName}:createInterface`,\n this.createInterface.bind(this),\n );\n\n this.messagingSystem.registerActionHandler(\n `${controllerName}:getInterface`,\n this.getInterface.bind(this),\n );\n\n this.messagingSystem.registerActionHandler(\n `${controllerName}:updateInterface`,\n this.updateInterface.bind(this),\n );\n\n this.messagingSystem.registerActionHandler(\n `${controllerName}:deleteInterface`,\n this.deleteInterface.bind(this),\n );\n\n this.messagingSystem.registerActionHandler(\n `${controllerName}:updateInterfaceState`,\n this.updateInterfaceState.bind(this),\n );\n\n this.messagingSystem.registerActionHandler(\n `${controllerName}:resolveInterface`,\n this.resolveInterface.bind(this),\n );\n }\n\n /**\n * Create an interface in the controller state with the associated data.\n *\n * @param snapId - The snap id that created the interface.\n * @param content - The interface content.\n * @param context - An optional interface context object.\n * @param contentType - The type of content.\n * @returns The newly interface id.\n */\n async createInterface(\n snapId: SnapId,\n content: ComponentOrElement,\n context?: InterfaceContext,\n contentType?: ContentType,\n ) {\n const element = getJsxInterface(content);\n await this.#validateContent(element);\n validateInterfaceContext(context);\n\n const id = nanoid();\n const componentState = constructState({}, element, {\n getAssetsState: this.#getAssetsState.bind(this),\n getAccountByAddress: this.#getAccountByAddress.bind(this),\n getSelectedAccount: this.#getSelectedAccount.bind(this),\n listAccounts: this.#listAccounts.bind(this),\n snapOwnsAccount: (account: InternalAccount) =>\n snapOwnsAccount(snapId, account),\n });\n\n this.update((draftState) => {\n // @ts-expect-error - TS2589: Type instantiation is excessively deep and\n // possibly infinite.\n draftState.interfaces[id] = {\n snapId,\n content: castDraft(element),\n state: componentState,\n context: context ?? null,\n contentType: contentType ?? null,\n };\n });\n\n return id;\n }\n\n /**\n * Get the data of a given interface id.\n *\n * @param snapId - The snap id requesting the interface data.\n * @param id - The interface id.\n * @returns The interface state.\n */\n getInterface(snapId: SnapId, id: string) {\n this.#validateArgs(snapId, id);\n\n return this.state.interfaces[id];\n }\n\n /**\n * Update the interface with the given content.\n *\n * @param snapId - The snap id requesting the update.\n * @param id - The interface id.\n * @param content - The new content.\n * @param context - An optional interface context object.\n */\n async updateInterface(\n snapId: SnapId,\n id: string,\n content: ComponentOrElement,\n context?: InterfaceContext,\n ) {\n this.#validateArgs(snapId, id);\n const element = getJsxInterface(content);\n await this.#validateContent(element);\n validateInterfaceContext(context);\n\n const oldState = this.state.interfaces[id].state;\n const newState = constructState(oldState, element, {\n getAssetsState: this.#getAssetsState.bind(this),\n getAccountByAddress: this.#getAccountByAddress.bind(this),\n getSelectedAccount: this.#getSelectedAccount.bind(this),\n listAccounts: this.#listAccounts.bind(this),\n snapOwnsAccount: (account: InternalAccount) =>\n snapOwnsAccount(snapId, account),\n });\n\n this.update((draftState) => {\n draftState.interfaces[id].state = newState;\n draftState.interfaces[id].content = castDraft(element);\n if (context) {\n draftState.interfaces[id].context = context;\n }\n });\n }\n\n /**\n * Delete an interface from state.\n *\n * @param id - The interface id.\n */\n deleteInterface(id: string) {\n this.update((draftState) => {\n delete draftState.interfaces[id];\n });\n }\n\n /**\n * Update the interface state.\n *\n * @param id - The interface id.\n * @param state - The new state.\n */\n updateInterfaceState(id: string, state: InterfaceState) {\n this.update((draftState) => {\n draftState.interfaces[id].state = state;\n });\n }\n\n /**\n * Resolve the promise of a given interface approval request.\n * The approval needs to have the same ID as the interface.\n *\n * @param snapId - The snap id.\n * @param id - The interface id.\n * @param value - The value to resolve the promise with.\n */\n async resolveInterface(snapId: SnapId, id: string, value: Json) {\n this.#validateArgs(snapId, id);\n this.#validateApproval(id);\n\n await this.#acceptApprovalRequest(id, value);\n\n this.deleteInterface(id);\n }\n\n /**\n * Utility function to validate the args passed to the other methods.\n *\n * @param snapId - The snap id.\n * @param id - The interface id.\n */\n #validateArgs(snapId: SnapId, id: string) {\n const existingInterface = this.state.interfaces[id];\n\n assert(\n existingInterface !== undefined,\n `Interface with id '${id}' not found.`,\n );\n assert(\n existingInterface.snapId === snapId,\n `Interface not created by ${snapId}.`,\n );\n }\n\n /**\n * Utility function to validate that the approval request exists.\n *\n * @param id - The interface id.\n */\n #validateApproval(id: string) {\n assert(\n this.#hasApprovalRequest(id),\n `Approval request with id '${id}' not found.`,\n );\n }\n\n /**\n * Check an origin against the phishing list.\n *\n * @param origin - The origin to check.\n * @returns True if the origin is on the phishing list, otherwise false.\n */\n #checkPhishingList(origin: string) {\n return this.messagingSystem.call('PhishingController:testOrigin', origin)\n .result;\n }\n\n /**\n * Check if an approval request exists for a given interface by looking up\n * if the ApprovalController has a request with the given interface ID.\n *\n * @param id - The interface id.\n * @returns True if an approval request exists, otherwise false.\n */\n #hasApprovalRequest(id: string) {\n return this.messagingSystem.call('ApprovalController:hasRequest', {\n id,\n });\n }\n\n /**\n * Accept an approval request for a given interface.\n *\n * @param id - The interface id.\n * @param value - The value to resolve the promise with.\n */\n async #acceptApprovalRequest(id: string, value: Json) {\n await this.messagingSystem.call(\n 'ApprovalController:acceptRequest',\n id,\n value,\n );\n }\n\n /**\n * Get the selected account in the client.\n *\n * @returns The selected account.\n */\n #getSelectedAccount() {\n return this.messagingSystem.call(\n 'AccountsController:getSelectedMultichainAccount',\n );\n }\n\n /**\n * Get a list of accounts for the given chain IDs.\n *\n * @param chainIds - The chain IDs to get the accounts for.\n * @returns The list of accounts.\n */\n #listAccounts(chainIds?: CaipChainId[]) {\n const accounts = this.messagingSystem.call(\n 'AccountsController:listMultichainAccounts',\n );\n\n if (!chainIds || chainIds.length === 0) {\n return accounts;\n }\n\n return accounts.filter((account) =>\n account.scopes.some((scope) => isMatchingChainId(scope, chainIds)),\n );\n }\n\n /**\n * Get an account by its address.\n *\n * @param address - The account address.\n * @returns The account or undefined if not found.\n */\n #getAccountByAddress(address: CaipAccountId) {\n const { address: parsedAddress } = parseCaipAccountId(address);\n\n return this.messagingSystem.call(\n 'AccountsController:getAccountByAddress',\n parsedAddress,\n );\n }\n\n /**\n * Get the MultichainAssetsController state.\n *\n * @returns The MultichainAssetsController state.\n */\n #getAssetsState() {\n return this.messagingSystem.call('MultichainAssetsController:getState');\n }\n\n /**\n * Get a snap by its id.\n *\n * @param id - The snap id.\n * @returns The snap.\n */\n #getSnap(id: string) {\n return this.messagingSystem.call('SnapController:get', id);\n }\n\n /**\n * Utility function to validate the components of an interface.\n * Throws if something is invalid.\n *\n * @param element - The JSX element to verify.\n */\n async #validateContent(element: JSXElement) {\n // We assume the validity of this JSON to be validated by the caller.\n // E.g., in the RPC method implementation.\n const size = getJsonSizeUnsafe(element);\n assert(\n size <= MAX_UI_CONTENT_SIZE,\n `A Snap UI may not be larger than ${MAX_UI_CONTENT_SIZE / 1000000} MB.`,\n );\n\n validateJsxElements(element, {\n isOnPhishingList: this.#checkPhishingList.bind(this),\n getSnap: this.#getSnap.bind(this),\n getAccountByAddress: this.#getAccountByAddress.bind(this),\n });\n }\n\n #onNotificationsListUpdated(notificationsList: Notification[]) {\n const snapNotificationsWithInterface = notificationsList.filter(\n (notification) => {\n return (\n notification.type === 'snap' &&\n hasProperty((notification as SnapNotification).data, 'detailedView')\n );\n },\n );\n\n const interfaceIdSet = new Set(\n snapNotificationsWithInterface.map(\n (notification) =>\n (\n (notification as SnapNotification)\n .data as ExpandedSnapNotificationData\n ).detailedView.interfaceId,\n ),\n );\n\n this.update((state) => {\n Object.entries(state.interfaces).forEach(([id, snapInterface]) => {\n if (\n snapInterface.contentType === ContentType.Notification &&\n !interfaceIdSet.has(id)\n ) {\n delete state.interfaces[id];\n }\n });\n });\n }\n}\n"]}