@metamask/snaps-controllers 0.24.1 → 0.25.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 (67) hide show
  1. package/dist/cronjob/CronjobController.d.ts +3 -2
  2. package/dist/cronjob/CronjobController.js +37 -23
  3. package/dist/cronjob/CronjobController.js.map +1 -1
  4. package/dist/fsm.js +1 -1
  5. package/dist/fsm.js.map +1 -1
  6. package/dist/index.d.ts +1 -1
  7. package/dist/index.js.map +1 -1
  8. package/dist/multichain/MultiChainController.d.ts +3 -1
  9. package/dist/multichain/MultiChainController.js +8 -8
  10. package/dist/multichain/MultiChainController.js.map +1 -1
  11. package/dist/multichain/middleware.d.ts +1 -1
  12. package/dist/multichain/middleware.js +2 -2
  13. package/dist/multichain/middleware.js.map +1 -1
  14. package/dist/services/AbstractExecutionService.d.ts +3 -3
  15. package/dist/services/AbstractExecutionService.js +13 -12
  16. package/dist/services/AbstractExecutionService.js.map +1 -1
  17. package/dist/services/ExecutionService.d.ts +1 -1
  18. package/dist/services/ExecutionService.js.map +1 -1
  19. package/dist/services/iframe/IframeExecutionService.js +1 -1
  20. package/dist/services/iframe/IframeExecutionService.js.map +1 -1
  21. package/dist/services/iframe/test/server.js +6 -6
  22. package/dist/services/iframe/test/server.js.map +1 -1
  23. package/dist/services/node/NodeProcessExecutionService.d.ts +1 -1
  24. package/dist/services/node/NodeProcessExecutionService.js +2 -2
  25. package/dist/services/node/NodeProcessExecutionService.js.map +1 -1
  26. package/dist/services/node/NodeThreadExecutionService.d.ts +2 -2
  27. package/dist/services/node/NodeThreadExecutionService.js +5 -4
  28. package/dist/services/node/NodeThreadExecutionService.js.map +1 -1
  29. package/dist/snaps/SnapController.d.ts +18 -16
  30. package/dist/snaps/SnapController.js +104 -87
  31. package/dist/snaps/SnapController.js.map +1 -1
  32. package/dist/snaps/endowments/cronjob.d.ts +2 -2
  33. package/dist/snaps/endowments/cronjob.js +3 -3
  34. package/dist/snaps/endowments/cronjob.js.map +1 -1
  35. package/dist/snaps/endowments/enum.d.ts +2 -1
  36. package/dist/snaps/endowments/enum.js +1 -0
  37. package/dist/snaps/endowments/enum.js.map +1 -1
  38. package/dist/snaps/endowments/ethereum-provider.d.ts +1 -1
  39. package/dist/snaps/endowments/ethereum-provider.js +2 -2
  40. package/dist/snaps/endowments/ethereum-provider.js.map +1 -1
  41. package/dist/snaps/endowments/index.d.ts +33 -19
  42. package/dist/snaps/endowments/index.js +16 -4
  43. package/dist/snaps/endowments/index.js.map +1 -1
  44. package/dist/snaps/endowments/keyring.d.ts +1 -1
  45. package/dist/snaps/endowments/keyring.js +2 -2
  46. package/dist/snaps/endowments/keyring.js.map +1 -1
  47. package/dist/snaps/endowments/long-running.d.ts +1 -1
  48. package/dist/snaps/endowments/long-running.js +2 -2
  49. package/dist/snaps/endowments/long-running.js.map +1 -1
  50. package/dist/snaps/endowments/network-access.d.ts +1 -1
  51. package/dist/snaps/endowments/network-access.js +2 -2
  52. package/dist/snaps/endowments/network-access.js.map +1 -1
  53. package/dist/snaps/endowments/rpc.d.ts +35 -0
  54. package/dist/snaps/endowments/rpc.js +91 -0
  55. package/dist/snaps/endowments/rpc.js.map +1 -0
  56. package/dist/snaps/endowments/transaction-insight.d.ts +3 -3
  57. package/dist/snaps/endowments/transaction-insight.js +3 -3
  58. package/dist/snaps/endowments/transaction-insight.js.map +1 -1
  59. package/dist/snaps/utils/npm.d.ts +2 -2
  60. package/dist/snaps/utils/npm.js +7 -3
  61. package/dist/snaps/utils/npm.js.map +1 -1
  62. package/dist/snaps/utils/stream.d.ts +1 -1
  63. package/dist/snaps/utils/stream.js +3 -3
  64. package/dist/snaps/utils/stream.js.map +1 -1
  65. package/dist/utils.d.ts +3 -3
  66. package/dist/utils.js.map +1 -1
  67. package/package.json +25 -20
@@ -21,26 +21,25 @@ var __rest = (this && this.__rest) || function (s, e) {
21
21
  }
22
22
  return t;
23
23
  };
24
- var __importDefault = (this && this.__importDefault) || function (mod) {
25
- return (mod && mod.__esModule) ? mod : { "default": mod };
26
- };
27
24
  var _SnapController_instances, _SnapController_closeAllConnections, _SnapController_environmentEndowmentPermissions, _SnapController_featureFlags, _SnapController_fetchFunction, _SnapController_idleTimeCheckInterval, _SnapController_checkSnapBlockList, _SnapController_maxIdleTime, _SnapController_npmRegistryUrl, _SnapController_getAppKey, _SnapController_timeoutForLastRequestStatus, _SnapController_statusMachine, _SnapController_initializeStateMachine, _SnapController_registerMessageHandlers, _SnapController_pollForLastRequestStatus, _SnapController_blockSnap, _SnapController_unblockSnap, _SnapController_assertIsUnblocked, _SnapController_stopSnapsLastRequestPastMax, _SnapController_transition, _SnapController_terminateSnap, _SnapController_getEncryptionKey, _SnapController_encryptSnapState, _SnapController_decryptSnapState, _SnapController_add, _SnapController_startSnap, _SnapController_getEndowments, _SnapController_set, _SnapController_fetchNpmSnap, _SnapController_fetchLocalSnap, _SnapController_processSnapPermissions, _SnapController_getRpcRequestHandler, _SnapController_executeWithTimeout, _SnapController_recordSnapRpcRequestStart, _SnapController_recordSnapRpcRequestFinish, _SnapController_getRuntime, _SnapController_getRuntimeExpect, _SnapController_setupRuntime, _SnapController_calculatePermissionsChange;
28
25
  Object.defineProperty(exports, "__esModule", { value: true });
29
26
  exports.SnapController = exports.AppKeyType = exports.SNAP_APPROVAL_UPDATE = exports.SNAP_APPROVAL_INSTALL = exports.controllerName = void 0;
30
- const browser_passworder_1 = __importDefault(require("@metamask/browser-passworder"));
31
- const controllers_1 = require("@metamask/controllers");
27
+ const base_controller_1 = require("@metamask/base-controller");
28
+ const browser_passworder_1 = require("@metamask/browser-passworder");
29
+ const rpc_methods_1 = require("@metamask/rpc-methods");
32
30
  const snaps_utils_1 = require("@metamask/snaps-utils");
31
+ const subject_metadata_controller_1 = require("@metamask/subject-metadata-controller");
33
32
  const utils_1 = require("@metamask/utils");
34
33
  const fsm_1 = require("@xstate/fsm");
35
34
  const eth_rpc_errors_1 = require("eth-rpc-errors");
36
35
  const nanoid_1 = require("nanoid");
37
- const rpc_methods_1 = require("@metamask/rpc-methods");
38
36
  const fsm_2 = require("../fsm");
39
37
  const utils_2 = require("../utils");
40
38
  const endowments_1 = require("./endowments");
39
+ const rpc_1 = require("./endowments/rpc");
41
40
  const RequestQueue_1 = require("./RequestQueue");
42
- const utils_3 = require("./utils");
43
41
  const Timer_1 = require("./Timer");
42
+ const utils_3 = require("./utils");
44
43
  exports.controllerName = 'SnapController';
45
44
  // TODO: Figure out how to name these
46
45
  exports.SNAP_APPROVAL_INSTALL = 'wallet_installSnap';
@@ -55,7 +54,7 @@ const TRUNCATED_SNAP_PROPERTIES = new Set([
55
54
  ]);
56
55
  var AppKeyType;
57
56
  (function (AppKeyType) {
58
- AppKeyType["stateEncryption"] = "stateEncryption";
57
+ AppKeyType["StateEncryption"] = "stateEncryption";
59
58
  })(AppKeyType = exports.AppKeyType || (exports.AppKeyType = {}));
60
59
  const defaultState = {
61
60
  snapErrors: {},
@@ -69,12 +68,14 @@ const defaultState = {
69
68
  * @returns Object with serializable snap properties.
70
69
  */
71
70
  function truncateSnap(snap) {
72
- return Object.keys(snap).reduce((serialized, key) => {
71
+ const truncatedSnap = Object.keys(snap).reduce((serialized, key) => {
73
72
  if (TRUNCATED_SNAP_PROPERTIES.has(key)) {
74
73
  serialized[key] = snap[key];
75
74
  }
76
75
  return serialized;
77
76
  }, {});
77
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
78
+ return truncatedSnap;
78
79
  }
79
80
  const name = 'SnapController';
80
81
  /*
@@ -83,7 +84,7 @@ const name = 'SnapController';
83
84
  * - Authorize: Requests the snap's required permissions from the user.
84
85
  * - Start: Initializes the snap in its SES realm with the authorized permissions.
85
86
  */
86
- class SnapController extends controllers_1.BaseControllerV2 {
87
+ class SnapController extends base_controller_1.BaseControllerV2 {
87
88
  constructor({ closeAllConnections, messenger, state, getAppKey, environmentEndowmentPermissions = [], npmRegistryUrl, idleTimeCheckInterval = (0, utils_1.inMilliseconds)(5, utils_1.Duration.Second), checkBlockList, maxIdleTime = (0, utils_1.inMilliseconds)(30, utils_1.Duration.Second), maxRequestTime = (0, utils_1.inMilliseconds)(60, utils_1.Duration.Second), fetchFunction = globalThis.fetch.bind(globalThis), featureFlags = {}, }) {
88
89
  var _a, _b;
89
90
  super({
@@ -153,9 +154,11 @@ class SnapController extends controllers_1.BaseControllerV2 {
153
154
  this._onOutboundResponse = this._onOutboundResponse.bind(this);
154
155
  this.snapsRuntimeData = new Map();
155
156
  __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_pollForLastRequestStatus).call(this);
157
+ /* eslint-disable @typescript-eslint/unbound-method */
156
158
  this.messagingSystem.subscribe('ExecutionService:unhandledError', this._onUnhandledSnapError);
157
159
  this.messagingSystem.subscribe('ExecutionService:outboundRequest', this._onOutboundRequest);
158
160
  this.messagingSystem.subscribe('ExecutionService:outboundResponse', this._onOutboundResponse);
161
+ /* eslint-enable @typescript-eslint/unbound-method */
159
162
  __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_initializeStateMachine).call(this);
160
163
  __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_registerMessageHandlers).call(this);
161
164
  Object.values((_b = state === null || state === void 0 ? void 0 : state.snaps) !== null && _b !== void 0 ? _b : {}).forEach((snap) => {
@@ -179,7 +182,7 @@ class SnapController extends controllers_1.BaseControllerV2 {
179
182
  };
180
183
  return blockListArg;
181
184
  }, {}));
182
- await Promise.all(Object.entries(blockedSnaps).map((_a) => {
185
+ await Promise.all(Object.entries(blockedSnaps).map(async (_a) => {
183
186
  var [snapId, _b] = _a, { blocked } = _b, blockData = __rest(_b, ["blocked"]);
184
187
  if (blocked) {
185
188
  return __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_blockSnap).call(this, snapId, blockData);
@@ -200,11 +203,15 @@ class SnapController extends controllers_1.BaseControllerV2 {
200
203
  });
201
204
  return result[snapId].blocked;
202
205
  }
203
- async _onUnhandledSnapError(snapId, error) {
204
- await this.stopSnap(snapId, snaps_utils_1.SnapStatusEvents.Crash);
205
- this.addSnapError(error);
206
+ _onUnhandledSnapError(snapId, error) {
207
+ this.stopSnap(snapId, snaps_utils_1.SnapStatusEvents.Crash)
208
+ .then(() => this.addSnapError(error))
209
+ .catch((stopSnapError) => {
210
+ // TODO: Decide how to handle errors.
211
+ console.error(stopSnapError);
212
+ });
206
213
  }
207
- async _onOutboundRequest(snapId) {
214
+ _onOutboundRequest(snapId) {
208
215
  const runtime = __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_getRuntimeExpect).call(this, snapId);
209
216
  // Ideally we would only pause the pending request that is making the outbound request
210
217
  // but right now we don't have a way to know which request initiated the outbound request
@@ -213,7 +220,7 @@ class SnapController extends controllers_1.BaseControllerV2 {
213
220
  .forEach((pendingRequest) => pendingRequest.timer.pause());
214
221
  runtime.pendingOutboundRequests += 1;
215
222
  }
216
- async _onOutboundResponse(snapId) {
223
+ _onOutboundResponse(snapId) {
217
224
  const runtime = __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_getRuntimeExpect).call(this, snapId);
218
225
  runtime.pendingOutboundRequests -= 1;
219
226
  if (runtime.pendingOutboundRequests === 0) {
@@ -260,7 +267,7 @@ class SnapController extends controllers_1.BaseControllerV2 {
260
267
  * @param snapId - The id of the Snap to disable.
261
268
  * @returns A promise that resolves once the snap has been disabled.
262
269
  */
263
- disableSnap(snapId) {
270
+ async disableSnap(snapId) {
264
271
  if (!this.has(snapId)) {
265
272
  throw new Error(`Snap "${snapId}" not found.`);
266
273
  }
@@ -386,7 +393,7 @@ class SnapController extends controllers_1.BaseControllerV2 {
386
393
  *
387
394
  * @param snapId - The id of the Snap whose state should be cleared.
388
395
  */
389
- async clearSnapState(snapId) {
396
+ clearSnapState(snapId) {
390
397
  const runtime = __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_getRuntimeExpect).call(this, snapId);
391
398
  runtime.state = null;
392
399
  }
@@ -402,20 +409,19 @@ class SnapController extends controllers_1.BaseControllerV2 {
402
409
  });
403
410
  }
404
411
  /**
405
- * Removes an error by internalID from a the SnapControllers state.
412
+ * Removes an error by internalID from the SnapControllers state.
406
413
  *
407
414
  * @param internalID - The internal error ID to remove on the SnapController.
408
415
  */
409
- async removeSnapError(internalID) {
416
+ removeSnapError(internalID) {
410
417
  this.update((state) => {
411
418
  delete state.snapErrors[internalID];
412
419
  });
413
420
  }
414
421
  /**
415
422
  * Clears all errors from the SnapControllers state.
416
- *
417
423
  */
418
- async clearSnapErrors() {
424
+ clearSnapErrors() {
419
425
  this.update((state) => {
420
426
  state.snapErrors = {};
421
427
  });
@@ -436,13 +442,13 @@ class SnapController extends controllers_1.BaseControllerV2 {
436
442
  * Completely clear the controller's state: delete all associated data,
437
443
  * handlers, event listeners, and permissions; tear down all snap providers.
438
444
  */
439
- clearState() {
445
+ async clearState() {
440
446
  const snapIds = Object.keys(this.state.snaps);
441
447
  snapIds.forEach((snapId) => {
442
448
  __classPrivateFieldGet(this, _SnapController_closeAllConnections, "f").call(this, snapId);
443
449
  });
444
- this.messagingSystem.call('ExecutionService:terminateAllSnaps');
445
- snapIds.forEach(this.revokeAllSnapPermissions);
450
+ await this.messagingSystem.call('ExecutionService:terminateAllSnaps');
451
+ snapIds.forEach((snapId) => this.revokeAllSnapPermissions(snapId));
446
452
  this.update((state) => {
447
453
  state.snaps = {};
448
454
  state.snapStates = {};
@@ -491,8 +497,8 @@ class SnapController extends controllers_1.BaseControllerV2 {
491
497
  *
492
498
  * @param snapId - The snap ID.
493
499
  */
494
- async revokeAllSnapPermissions(snapId) {
495
- if (await this.messagingSystem.call('PermissionController:hasPermissions', snapId)) {
500
+ revokeAllSnapPermissions(snapId) {
501
+ if (this.messagingSystem.call('PermissionController:hasPermissions', snapId)) {
496
502
  this.messagingSystem.call('PermissionController:revokeAllPermissions', snapId);
497
503
  }
498
504
  }
@@ -529,9 +535,9 @@ class SnapController extends controllers_1.BaseControllerV2 {
529
535
  * @param origin - The origin whose permitted snaps to retrieve.
530
536
  * @returns The serialized permitted snaps for the origin.
531
537
  */
532
- async getPermittedSnaps(origin) {
538
+ getPermittedSnaps(origin) {
533
539
  var _a;
534
- return Object.values((_a = (await this.messagingSystem.call('PermissionController:getPermissions', origin))) !== null && _a !== void 0 ? _a : {}).reduce((permittedSnaps, perm) => {
540
+ return Object.values((_a = this.messagingSystem.call('PermissionController:getPermissions', origin)) !== null && _a !== void 0 ? _a : {}).reduce((permittedSnaps, perm) => {
535
541
  if (perm.parentCapability.startsWith(snaps_utils_1.SNAP_PREFIX)) {
536
542
  const snapId = perm.parentCapability.replace(snaps_utils_1.SNAP_PREFIX_REGEX, '');
537
543
  const snap = this.get(snapId);
@@ -556,15 +562,15 @@ class SnapController extends controllers_1.BaseControllerV2 {
556
562
  async installSnaps(origin, requestedSnaps) {
557
563
  const result = {};
558
564
  await Promise.all(Object.entries(requestedSnaps).map(async ([snapId, { version: rawVersion }]) => {
559
- const version = (0, snaps_utils_1.resolveVersion)(rawVersion);
560
- const permissionName = (0, snaps_utils_1.getSnapPermissionName)(snapId);
561
- if (!(0, snaps_utils_1.isValidSnapVersionRange)(version)) {
565
+ const [error, version] = (0, snaps_utils_1.resolveVersionRange)(rawVersion);
566
+ if (error) {
562
567
  result[snapId] = {
563
568
  error: eth_rpc_errors_1.ethErrors.rpc.invalidParams(`The "version" field must be a valid SemVer version range if specified. Received: "${version}".`),
564
569
  };
565
570
  return;
566
571
  }
567
- if (await this.messagingSystem.call('PermissionController:hasPermission', origin, permissionName)) {
572
+ const permissionName = (0, snaps_utils_1.getSnapPermissionName)(snapId);
573
+ if (this.messagingSystem.call('PermissionController:hasPermission', origin, permissionName)) {
568
574
  // Attempt to install and run the snap, storing any errors that
569
575
  // occur during the process.
570
576
  result[snapId] = Object.assign({}, (await this.processRequestedSnap(origin, snapId, version)));
@@ -591,7 +597,7 @@ class SnapController extends controllers_1.BaseControllerV2 {
591
597
  try {
592
598
  (0, snaps_utils_1.validateSnapId)(snapId);
593
599
  }
594
- catch (err) {
600
+ catch (error) {
595
601
  return {
596
602
  error: eth_rpc_errors_1.ethErrors.rpc.invalidParams(`"${snapId}" is not a valid snap id.`),
597
603
  };
@@ -612,8 +618,8 @@ class SnapController extends controllers_1.BaseControllerV2 {
612
618
  }
613
619
  return updateResult;
614
620
  }
615
- catch (err) {
616
- return { error: (0, eth_rpc_errors_1.serializeError)(err) };
621
+ catch (error) {
622
+ return { error: (0, eth_rpc_errors_1.serializeError)(error) };
617
623
  }
618
624
  }
619
625
  else {
@@ -641,12 +647,12 @@ class SnapController extends controllers_1.BaseControllerV2 {
641
647
  this.messagingSystem.publish(`SnapController:snapInstalled`, truncated);
642
648
  return truncated;
643
649
  }
644
- catch (err) {
645
- console.error(`Error when adding snap.`, err);
650
+ catch (error) {
651
+ console.error(`Error when adding snap.`, error);
646
652
  if (this.has(snapId)) {
647
- this.removeSnap(snapId);
653
+ await this.removeSnap(snapId);
648
654
  }
649
- return { error: (0, eth_rpc_errors_1.serializeError)(err) };
655
+ return { error: (0, eth_rpc_errors_1.serializeError)(error) };
650
656
  }
651
657
  }
652
658
  /**
@@ -668,7 +674,7 @@ class SnapController extends controllers_1.BaseControllerV2 {
668
674
  */
669
675
  async updateSnap(origin, snapId, newVersionRange = snaps_utils_1.DEFAULT_REQUESTED_SNAP_VERSION) {
670
676
  const snap = this.getExpect(snapId);
671
- if (!(0, snaps_utils_1.isValidSnapVersionRange)(newVersionRange)) {
677
+ if (!(0, snaps_utils_1.isValidSemVerRange)(newVersionRange)) {
672
678
  throw new Error(`Received invalid snap version range: "${newVersionRange}".`);
673
679
  }
674
680
  const newSnap = await this.fetchSnap(snapId, newVersionRange);
@@ -682,7 +688,7 @@ class SnapController extends controllers_1.BaseControllerV2 {
682
688
  shasum: newSnap.manifest.source.shasum,
683
689
  });
684
690
  const processedPermissions = __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_processSnapPermissions).call(this, newSnap.manifest.initialPermissions);
685
- const { newPermissions, unusedPermissions, approvedPermissions } = await __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_calculatePermissionsChange).call(this, snapId, processedPermissions);
691
+ const { newPermissions, unusedPermissions, approvedPermissions } = __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_calculatePermissionsChange).call(this, snapId, processedPermissions);
686
692
  const id = (0, nanoid_1.nanoid)();
687
693
  const _a = (await this.messagingSystem.call('ApprovalController:addRequest', {
688
694
  origin,
@@ -712,12 +718,12 @@ class SnapController extends controllers_1.BaseControllerV2 {
712
718
  });
713
719
  const unusedPermissionsKeys = Object.keys(unusedPermissions);
714
720
  if ((0, utils_1.isNonEmptyArray)(unusedPermissionsKeys)) {
715
- await this.messagingSystem.call('PermissionController:revokePermissions', {
721
+ this.messagingSystem.call('PermissionController:revokePermissions', {
716
722
  [snapId]: unusedPermissionsKeys,
717
723
  });
718
724
  }
719
725
  if ((0, utils_1.isNonEmptyArray)(Object.keys(approvedNewPermissions))) {
720
- await this.messagingSystem.call('PermissionController:grantPermissions', {
726
+ this.messagingSystem.call('PermissionController:grantPermissions', {
721
727
  approvedPermissions: approvedNewPermissions,
722
728
  subject: { origin: snapId },
723
729
  requestData,
@@ -785,7 +791,7 @@ class SnapController extends controllers_1.BaseControllerV2 {
785
791
  },
786
792
  }, true)), { permissions: approvedPermissions } = _a, requestData = __rest(_a, ["permissions"]);
787
793
  if ((0, utils_1.isNonEmptyArray)(Object.keys(approvedPermissions))) {
788
- await this.messagingSystem.call('PermissionController:grantPermissions', {
794
+ this.messagingSystem.call('PermissionController:grantPermissions', {
789
795
  approvedPermissions,
790
796
  subject: { origin: snapId },
791
797
  requestData,
@@ -802,9 +808,11 @@ class SnapController extends controllers_1.BaseControllerV2 {
802
808
  if (__classPrivateFieldGet(this, _SnapController_timeoutForLastRequestStatus, "f")) {
803
809
  clearTimeout(__classPrivateFieldGet(this, _SnapController_timeoutForLastRequestStatus, "f"));
804
810
  }
811
+ /* eslint-disable @typescript-eslint/unbound-method */
805
812
  this.messagingSystem.unsubscribe('ExecutionService:unhandledError', this._onUnhandledSnapError);
806
813
  this.messagingSystem.unsubscribe('ExecutionService:outboundRequest', this._onOutboundRequest);
807
814
  this.messagingSystem.unsubscribe('ExecutionService:outboundResponse', this._onOutboundResponse);
815
+ /* eslint-enable @typescript-eslint/unbound-method */
808
816
  }
809
817
  /**
810
818
  * Passes a JSON-RPC request object to the RPC handler function of a snap.
@@ -817,6 +825,23 @@ class SnapController extends controllers_1.BaseControllerV2 {
817
825
  * @returns The result of the JSON-RPC request.
818
826
  */
819
827
  async handleRequest({ snapId, origin, handler: handlerType, request, }) {
828
+ const permissionName = endowments_1.handlerEndowments[handlerType];
829
+ const hasPermission = this.messagingSystem.call('PermissionController:hasPermission', snapId, permissionName);
830
+ if (!hasPermission) {
831
+ throw new Error(`Snap "${snapId}" is not permitted to use "${permissionName}".`);
832
+ }
833
+ if (permissionName === endowments_1.SnapEndowments.Rpc) {
834
+ const subject = this.messagingSystem.call('SubjectMetadataController:getSubjectMetadata', origin);
835
+ const isSnap = (subject === null || subject === void 0 ? void 0 : subject.subjectType) === subject_metadata_controller_1.SubjectType.Snap;
836
+ const permissions = this.messagingSystem.call('PermissionController:getPermissions', snapId);
837
+ const rpcPermission = permissions === null || permissions === void 0 ? void 0 : permissions[endowments_1.SnapEndowments.Rpc];
838
+ (0, utils_1.assert)(rpcPermission);
839
+ const origins = (0, rpc_1.getRpcCaveatOrigins)(rpcPermission);
840
+ (0, utils_1.assert)(origins);
841
+ if ((isSnap && !origins.snaps) || (!isSnap && !origins.dapps)) {
842
+ throw new Error(`Snap "${snapId}" is not permitted to handle JSON-RPC requests from "${origin}".`);
843
+ }
844
+ }
820
845
  const handler = await __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_getRpcRequestHandler).call(this, snapId);
821
846
  if (!handler) {
822
847
  throw new Error(`Snap RPC message handler not found for snap "${snapId}".`);
@@ -878,23 +903,26 @@ _SnapController_closeAllConnections = new WeakMap(), _SnapController_environment
878
903
  }, _SnapController_registerMessageHandlers = function _SnapController_registerMessageHandlers() {
879
904
  this.messagingSystem.registerActionHandler(`${exports.controllerName}:clearSnapState`, (...args) => this.clearSnapState(...args));
880
905
  this.messagingSystem.registerActionHandler(`${exports.controllerName}:get`, (...args) => this.get(...args));
881
- this.messagingSystem.registerActionHandler(`${exports.controllerName}:getSnapState`, (...args) => this.getSnapState(...args));
882
- this.messagingSystem.registerActionHandler(`${exports.controllerName}:handleRequest`, (...args) => this.handleRequest(...args));
906
+ this.messagingSystem.registerActionHandler(`${exports.controllerName}:getSnapState`, async (...args) => this.getSnapState(...args));
907
+ this.messagingSystem.registerActionHandler(`${exports.controllerName}:handleRequest`, async (...args) => this.handleRequest(...args));
883
908
  this.messagingSystem.registerActionHandler(`${exports.controllerName}:has`, (...args) => this.has(...args));
884
- this.messagingSystem.registerActionHandler(`${exports.controllerName}:updateBlockedSnaps`, () => this.updateBlockedSnaps());
885
- this.messagingSystem.registerActionHandler(`${exports.controllerName}:updateSnapState`, (...args) => this.updateSnapState(...args));
909
+ this.messagingSystem.registerActionHandler(`${exports.controllerName}:updateBlockedSnaps`, async () => this.updateBlockedSnaps());
910
+ this.messagingSystem.registerActionHandler(`${exports.controllerName}:updateSnapState`, async (...args) => this.updateSnapState(...args));
886
911
  this.messagingSystem.registerActionHandler(`${exports.controllerName}:enable`, (...args) => this.enableSnap(...args));
887
- this.messagingSystem.registerActionHandler(`${exports.controllerName}:disable`, (...args) => this.disableSnap(...args));
888
- this.messagingSystem.registerActionHandler(`${exports.controllerName}:remove`, (...args) => this.removeSnap(...args));
912
+ this.messagingSystem.registerActionHandler(`${exports.controllerName}:disable`, async (...args) => this.disableSnap(...args));
913
+ this.messagingSystem.registerActionHandler(`${exports.controllerName}:remove`, async (...args) => this.removeSnap(...args));
889
914
  this.messagingSystem.registerActionHandler(`${exports.controllerName}:getPermitted`, (...args) => this.getPermittedSnaps(...args));
890
- this.messagingSystem.registerActionHandler(`${exports.controllerName}:install`, (...args) => this.installSnaps(...args));
915
+ this.messagingSystem.registerActionHandler(`${exports.controllerName}:install`, async (...args) => this.installSnaps(...args));
891
916
  this.messagingSystem.registerActionHandler(`${exports.controllerName}:removeSnapError`, (...args) => this.removeSnapError(...args));
892
917
  this.messagingSystem.registerActionHandler(`${exports.controllerName}:getAll`, (...args) => this.getAllSnaps(...args));
893
918
  this.messagingSystem.registerActionHandler(`${exports.controllerName}:incrementActiveReferences`, (...args) => this.incrementActiveReferences(...args));
894
919
  this.messagingSystem.registerActionHandler(`${exports.controllerName}:decrementActiveReferences`, (...args) => this.decrementActiveReferences(...args));
895
920
  }, _SnapController_pollForLastRequestStatus = function _SnapController_pollForLastRequestStatus() {
896
- __classPrivateFieldSet(this, _SnapController_timeoutForLastRequestStatus, setTimeout(async () => {
897
- await __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_stopSnapsLastRequestPastMax).call(this);
921
+ __classPrivateFieldSet(this, _SnapController_timeoutForLastRequestStatus, setTimeout(() => {
922
+ __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_stopSnapsLastRequestPastMax).call(this).catch((error) => {
923
+ // TODO: Decide how to handle errors.
924
+ console.error(error);
925
+ });
898
926
  __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_pollForLastRequestStatus).call(this);
899
927
  }, __classPrivateFieldGet(this, _SnapController_idleTimeCheckInterval, "f")), "f");
900
928
  }, _SnapController_blockSnap =
@@ -920,15 +948,7 @@ async function _SnapController_blockSnap(snapId, blockedSnapInfo) {
920
948
  console.error(`Encountered error when stopping blocked snap "${snapId}".`, error);
921
949
  }
922
950
  this.messagingSystem.publish(`${exports.controllerName}:snapBlocked`, snapId, blockedSnapInfo);
923
- }, _SnapController_unblockSnap =
924
- /**
925
- * Unblocks a snap so that it can be enabled and started again. Emits
926
- * {@link SnapUnblocked}. Does nothing if the snap is not installed or already
927
- * unblocked.
928
- *
929
- * @param snapId - The id of the snap to unblock.
930
- */
931
- async function _SnapController_unblockSnap(snapId) {
951
+ }, _SnapController_unblockSnap = function _SnapController_unblockSnap(snapId) {
932
952
  if (!this.has(snapId) || !this.state.snaps[snapId].blocked) {
933
953
  return;
934
954
  }
@@ -958,7 +978,7 @@ async function _SnapController_assertIsUnblocked(snapId, snapInfo) {
958
978
  runtime.lastRequest &&
959
979
  __classPrivateFieldGet(this, _SnapController_maxIdleTime, "f") &&
960
980
  (0, utils_1.timeSince)(runtime.lastRequest) > __classPrivateFieldGet(this, _SnapController_maxIdleTime, "f"))
961
- .map(([snapId]) => this.stopSnap(snapId, snaps_utils_1.SnapStatusEvents.Stop)));
981
+ .map(async ([snapId]) => this.stopSnap(snapId, snaps_utils_1.SnapStatusEvents.Stop)));
962
982
  }, _SnapController_transition = function _SnapController_transition(snapId, event) {
963
983
  const { interpreter } = __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_getRuntimeExpect).call(this, snapId);
964
984
  interpreter.send(event);
@@ -975,16 +995,18 @@ async function _SnapController_terminateSnap(snapId) {
975
995
  await this.messagingSystem.call('ExecutionService:terminateSnap', snapId);
976
996
  this.messagingSystem.publish('SnapController:snapTerminated', this.getTruncatedExpect(snapId));
977
997
  }, _SnapController_getEncryptionKey = async function _SnapController_getEncryptionKey(snapId) {
978
- return __classPrivateFieldGet(this, _SnapController_getAppKey, "f").call(this, snapId, AppKeyType.stateEncryption);
998
+ return __classPrivateFieldGet(this, _SnapController_getAppKey, "f").call(this, snapId, AppKeyType.StateEncryption);
979
999
  }, _SnapController_encryptSnapState = async function _SnapController_encryptSnapState(snapId, state) {
980
1000
  const appKey = await __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_getEncryptionKey).call(this, snapId);
981
- return browser_passworder_1.default.encrypt(appKey, state);
1001
+ return (0, browser_passworder_1.encrypt)(appKey, state);
982
1002
  }, _SnapController_decryptSnapState = async function _SnapController_decryptSnapState(snapId, encrypted) {
983
1003
  const appKey = await __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_getEncryptionKey).call(this, snapId);
984
1004
  try {
985
- return await browser_passworder_1.default.decrypt(appKey, encrypted);
1005
+ const value = await (0, browser_passworder_1.decrypt)(appKey, encrypted);
1006
+ (0, utils_1.assert)((0, utils_1.isValidJson)(value));
1007
+ return value;
986
1008
  }
987
- catch (err) {
1009
+ catch (error) {
988
1010
  throw new Error('Failed to decrypt snap state, the state must be corrupted.');
989
1011
  }
990
1012
  }, _SnapController_add =
@@ -1044,9 +1066,9 @@ async function _SnapController_add(args) {
1044
1066
  __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_transition).call(this, snapId, snaps_utils_1.SnapStatusEvents.Start);
1045
1067
  return result;
1046
1068
  }
1047
- catch (err) {
1069
+ catch (error) {
1048
1070
  await __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_terminateSnap).call(this, snapId);
1049
- throw err;
1071
+ throw error;
1050
1072
  }
1051
1073
  }, _SnapController_getEndowments =
1052
1074
  /**
@@ -1063,7 +1085,7 @@ async function _SnapController_add(args) {
1063
1085
  async function _SnapController_getEndowments(snapId) {
1064
1086
  let allEndowments = [];
1065
1087
  for (const permissionName of __classPrivateFieldGet(this, _SnapController_environmentEndowmentPermissions, "f")) {
1066
- if (await this.messagingSystem.call('PermissionController:hasPermission', snapId, permissionName)) {
1088
+ if (this.messagingSystem.call('PermissionController:hasPermission', snapId, permissionName)) {
1067
1089
  const endowments = await this.messagingSystem.call('PermissionController:getEndowments', snapId, permissionName);
1068
1090
  if (endowments) {
1069
1091
  // We don't have any guarantees about the type of the endowments
@@ -1080,6 +1102,8 @@ async function _SnapController_getEndowments(snapId) {
1080
1102
  ...new Set([...snaps_utils_1.DEFAULT_ENDOWMENTS, ...allEndowments]),
1081
1103
  ];
1082
1104
  if (dedupedEndowments.length <
1105
+ // This is a bug in TypeScript: https://github.com/microsoft/TypeScript/issues/48313
1106
+ // eslint-disable-next-line @typescript-eslint/restrict-plus-operands
1083
1107
  snaps_utils_1.DEFAULT_ENDOWMENTS.length + allEndowments.length) {
1084
1108
  console.error('Duplicate endowments found. Default endowments should not be requested.', allEndowments);
1085
1109
  }
@@ -1131,7 +1155,7 @@ async function _SnapController_getEndowments(snapId) {
1131
1155
  this.messagingSystem.publish(`SnapController:snapAdded`, snap, svgIcon);
1132
1156
  return Object.assign(Object.assign({}, snap), { sourceCode });
1133
1157
  }, _SnapController_fetchNpmSnap = async function _SnapController_fetchNpmSnap(packageName, versionRange) {
1134
- if (!(0, snaps_utils_1.isValidSnapVersionRange)(versionRange)) {
1158
+ if (!(0, snaps_utils_1.isValidSemVerRange)(versionRange)) {
1135
1159
  throw new Error(`Received invalid Snap version range: "${versionRange}".`);
1136
1160
  }
1137
1161
  const { manifest, sourceCode, svgIcon } = await (0, utils_3.fetchNpmSnap)(packageName, versionRange, __classPrivateFieldGet(this, _SnapController_npmRegistryUrl, "f"), __classPrivateFieldGet(this, _SnapController_fetchFunction, "f"));
@@ -1177,14 +1201,7 @@ async function _SnapController_fetchLocalSnap(localhostUrl) {
1177
1201
  (0, utils_1.assert)(Object.keys(value).length === 0);
1178
1202
  return [initialPermission, {}];
1179
1203
  }));
1180
- }, _SnapController_getRpcRequestHandler =
1181
- /**
1182
- * Gets the RPC message handler for the given snap.
1183
- *
1184
- * @param snapId - The id of the Snap whose message handler to get.
1185
- * @returns The RPC handler for the given snap.
1186
- */
1187
- async function _SnapController_getRpcRequestHandler(snapId) {
1204
+ }, _SnapController_getRpcRequestHandler = function _SnapController_getRpcRequestHandler(snapId) {
1188
1205
  const runtime = __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_getRuntimeExpect).call(this, snapId);
1189
1206
  const existingHandler = runtime.rpcHandler;
1190
1207
  if (existingHandler) {
@@ -1201,7 +1218,7 @@ async function _SnapController_getRpcRequestHandler(snapId) {
1201
1218
  if (this.state.snaps[snapId].status === snaps_utils_1.SnapStatus.Installing) {
1202
1219
  throw new Error(`Snap "${snapId}" is currently being installed. Please try again later.`);
1203
1220
  }
1204
- if (this.isRunning(snapId) === false) {
1221
+ if (!this.isRunning(snapId)) {
1205
1222
  let localStartPromise = startPromises.get(snapId);
1206
1223
  if (!localStartPromise) {
1207
1224
  localStartPromise = this.startSnap(snapId);
@@ -1241,9 +1258,9 @@ async function _SnapController_getRpcRequestHandler(snapId) {
1241
1258
  __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_recordSnapRpcRequestFinish).call(this, snapId, request.id);
1242
1259
  return result;
1243
1260
  }
1244
- catch (err) {
1261
+ catch (error) {
1245
1262
  await this.stopSnap(snapId, snaps_utils_1.SnapStatusEvents.Crash);
1246
- throw err;
1263
+ throw error;
1247
1264
  }
1248
1265
  };
1249
1266
  runtime.rpcHandler = rpcHandler;
@@ -1260,7 +1277,7 @@ async function _SnapController_getRpcRequestHandler(snapId) {
1260
1277
  * @template PromiseValue - The value of the Promise.
1261
1278
  */
1262
1279
  async function _SnapController_executeWithTimeout(snapId, promise, timer) {
1263
- const isLongRunning = await this.messagingSystem.call('PermissionController:hasPermission', snapId, endowments_1.SnapEndowments.LongRunning);
1280
+ const isLongRunning = this.messagingSystem.call('PermissionController:hasPermission', snapId, endowments_1.SnapEndowments.LongRunning);
1264
1281
  // Long running snaps have timeouts disabled
1265
1282
  if (isLongRunning) {
1266
1283
  return promise;
@@ -1276,7 +1293,7 @@ async function _SnapController_executeWithTimeout(snapId, promise, timer) {
1276
1293
  runtime.lastRequest = null;
1277
1294
  }, _SnapController_recordSnapRpcRequestFinish = function _SnapController_recordSnapRpcRequestFinish(snapId, requestId) {
1278
1295
  const runtime = __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_getRuntimeExpect).call(this, snapId);
1279
- runtime.pendingInboundRequests = runtime.pendingInboundRequests.filter((r) => r.requestId !== requestId);
1296
+ runtime.pendingInboundRequests = runtime.pendingInboundRequests.filter((request) => request.requestId !== requestId);
1280
1297
  if (runtime.pendingInboundRequests.length === 0) {
1281
1298
  runtime.lastRequest = Date.now();
1282
1299
  }
@@ -1299,9 +1316,9 @@ async function _SnapController_executeWithTimeout(snapId, promise, timer) {
1299
1316
  });
1300
1317
  (0, fsm_2.forceStrict)(interpreter);
1301
1318
  this.snapsRuntimeData.set(snapId, Object.assign({ lastRequest: null, rpcHandler: null, installPromise: null, activeReferences: 0, pendingInboundRequests: [], pendingOutboundRequests: 0, interpreter }, data));
1302
- }, _SnapController_calculatePermissionsChange = async function _SnapController_calculatePermissionsChange(snapId, desiredPermissionsSet) {
1319
+ }, _SnapController_calculatePermissionsChange = function _SnapController_calculatePermissionsChange(snapId, desiredPermissionsSet) {
1303
1320
  var _a;
1304
- const oldPermissions = (_a = (await this.messagingSystem.call('PermissionController:getPermissions', snapId))) !== null && _a !== void 0 ? _a : {};
1321
+ const oldPermissions = (_a = this.messagingSystem.call('PermissionController:getPermissions', snapId)) !== null && _a !== void 0 ? _a : {};
1305
1322
  const newPermissions = (0, utils_2.setDiff)(desiredPermissionsSet, oldPermissions);
1306
1323
  // TODO(ritave): The assumption that these are unused only holds so long as we do not
1307
1324
  // permit dynamic permission requests.