@metamask/snaps-controllers 0.27.1 → 0.29.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 (58) hide show
  1. package/dist/cronjob/CronjobController.js +3 -3
  2. package/dist/cronjob/CronjobController.js.map +1 -1
  3. package/dist/logging.d.ts +8 -0
  4. package/dist/logging.js +13 -0
  5. package/dist/logging.js.map +1 -0
  6. package/dist/multichain/MultiChainController.js +11 -12
  7. package/dist/multichain/MultiChainController.js.map +1 -1
  8. package/dist/services/AbstractExecutionService.js +10 -9
  9. package/dist/services/AbstractExecutionService.js.map +1 -1
  10. package/dist/services/browser.d.ts +1 -0
  11. package/dist/services/browser.js +1 -0
  12. package/dist/services/browser.js.map +1 -1
  13. package/dist/services/iframe/IframeExecutionService.d.ts +0 -10
  14. package/dist/services/iframe/IframeExecutionService.js +2 -53
  15. package/dist/services/iframe/IframeExecutionService.js.map +1 -1
  16. package/dist/services/iframe/test/fixJSDOMPostMessageEventSource.js +0 -40
  17. package/dist/services/iframe/test/fixJSDOMPostMessageEventSource.js.map +1 -1
  18. package/dist/services/index.d.ts +1 -0
  19. package/dist/services/index.js +1 -0
  20. package/dist/services/index.js.map +1 -1
  21. package/dist/services/offscreen/OffscreenExecutionService.d.ts +49 -0
  22. package/dist/services/offscreen/OffscreenExecutionService.js +100 -0
  23. package/dist/services/offscreen/OffscreenExecutionService.js.map +1 -0
  24. package/dist/services/offscreen/OffscreenPostMessageStream.d.ts +35 -0
  25. package/dist/services/offscreen/OffscreenPostMessageStream.js +66 -0
  26. package/dist/services/offscreen/OffscreenPostMessageStream.js.map +1 -0
  27. package/dist/services/offscreen/index.d.ts +2 -0
  28. package/dist/services/offscreen/index.js +19 -0
  29. package/dist/services/offscreen/index.js.map +1 -0
  30. package/dist/snaps/SnapController.d.ts +30 -35
  31. package/dist/snaps/SnapController.js +109 -87
  32. package/dist/snaps/SnapController.js.map +1 -1
  33. package/dist/snaps/endowments/index.d.ts +1 -1
  34. package/dist/snaps/endowments/network-access.d.ts +1 -1
  35. package/dist/snaps/endowments/network-access.js +1 -1
  36. package/dist/snaps/endowments/network-access.js.map +1 -1
  37. package/dist/snaps/index.d.ts +1 -0
  38. package/dist/snaps/index.js +1 -0
  39. package/dist/snaps/index.js.map +1 -1
  40. package/dist/snaps/location/location.d.ts +4 -0
  41. package/dist/snaps/location/location.js +3 -1
  42. package/dist/snaps/location/location.js.map +1 -1
  43. package/dist/snaps/location/npm.d.ts +2 -1
  44. package/dist/snaps/location/npm.js +30 -12
  45. package/dist/snaps/location/npm.js.map +1 -1
  46. package/dist/snaps/registry/index.d.ts +2 -0
  47. package/dist/snaps/registry/index.js +19 -0
  48. package/dist/snaps/registry/index.js.map +1 -0
  49. package/dist/snaps/registry/json.d.ts +20 -0
  50. package/dist/snaps/registry/json.js +95 -0
  51. package/dist/snaps/registry/json.js.map +1 -0
  52. package/dist/snaps/registry/registry.d.ts +29 -0
  53. package/dist/snaps/registry/registry.js +11 -0
  54. package/dist/snaps/registry/registry.js.map +1 -0
  55. package/package.json +10 -9
  56. package/dist/services/iframe/test/server.d.ts +0 -11
  57. package/dist/services/iframe/test/server.js +0 -71
  58. package/dist/services/iframe/test/server.js.map +0 -1
@@ -21,7 +21,7 @@ var __rest = (this && this.__rest) || function (s, e) {
21
21
  }
22
22
  return t;
23
23
  };
24
- var _SnapController_instances, _SnapController_closeAllConnections, _SnapController_environmentEndowmentPermissions, _SnapController_featureFlags, _SnapController_fetchFunction, _SnapController_idleTimeCheckInterval, _SnapController_checkSnapBlockList, _SnapController_maxIdleTime, _SnapController_detectSnapLocation, _SnapController_rollbackSnapshots, _SnapController_timeoutForLastRequestStatus, _SnapController_statusMachine, _SnapController_initializeStateMachine, _SnapController_registerMessageHandlers, _SnapController_pollForLastRequestStatus, _SnapController_blockSnap, _SnapController_unblockSnap, _SnapController_assertIsUnblocked, _SnapController_stopSnapsLastRequestPastMax, _SnapController_transition, _SnapController_terminateSnap, _SnapController_add, _SnapController_startSnap, _SnapController_getEndowments, _SnapController_set, _SnapController_fetchSnap, _SnapController_processSnapPermissions, _SnapController_getRpcRequestHandler, _SnapController_executeWithTimeout, _SnapController_recordSnapRpcRequestStart, _SnapController_recordSnapRpcRequestFinish, _SnapController_getRollbackSnapshot, _SnapController_createRollbackSnapshot, _SnapController_rollbackSnap, _SnapController_rollbackSnaps, _SnapController_getRuntime, _SnapController_getRuntimeExpect, _SnapController_setupRuntime, _SnapController_calculatePermissionsChange, _SnapController_isValidUpdate;
24
+ var _SnapController_instances, _SnapController_closeAllConnections, _SnapController_environmentEndowmentPermissions, _SnapController_excludedPermissions, _SnapController_featureFlags, _SnapController_fetchFunction, _SnapController_idleTimeCheckInterval, _SnapController_registry, _SnapController_maxIdleTime, _SnapController_detectSnapLocation, _SnapController_rollbackSnapshots, _SnapController_timeoutForLastRequestStatus, _SnapController_statusMachine, _SnapController_initializeStateMachine, _SnapController_registerMessageHandlers, _SnapController_pollForLastRequestStatus, _SnapController_blockSnap, _SnapController_unblockSnap, _SnapController_assertIsInstallAllowed, _SnapController_stopSnapsLastRequestPastMax, _SnapController_transition, _SnapController_terminateSnap, _SnapController_removeSnapFromSubjects, _SnapController_add, _SnapController_startSnap, _SnapController_getEndowments, _SnapController_set, _SnapController_fetchSnap, _SnapController_processSnapPermissions, _SnapController_getRpcRequestHandler, _SnapController_executeWithTimeout, _SnapController_recordSnapRpcRequestStart, _SnapController_recordSnapRpcRequestFinish, _SnapController_getRollbackSnapshot, _SnapController_createRollbackSnapshot, _SnapController_rollbackSnap, _SnapController_rollbackSnaps, _SnapController_getRuntime, _SnapController_getRuntimeExpect, _SnapController_setupRuntime, _SnapController_calculatePermissionsChange, _SnapController_isValidUpdate;
25
25
  Object.defineProperty(exports, "__esModule", { value: true });
26
26
  exports.SnapController = exports.SNAP_APPROVAL_UPDATE = exports.SNAP_APPROVAL_INSTALL = exports.controllerName = void 0;
27
27
  const base_controller_1 = require("@metamask/base-controller");
@@ -33,10 +33,12 @@ const fsm_1 = require("@xstate/fsm");
33
33
  const eth_rpc_errors_1 = require("eth-rpc-errors");
34
34
  const nanoid_1 = require("nanoid");
35
35
  const fsm_2 = require("../fsm");
36
+ const logging_1 = require("../logging");
36
37
  const utils_2 = require("../utils");
37
38
  const endowments_1 = require("./endowments");
38
39
  const rpc_1 = require("./endowments/rpc");
39
40
  const location_1 = require("./location");
41
+ const registry_1 = require("./registry");
40
42
  const RequestQueue_1 = require("./RequestQueue");
41
43
  const Timer_1 = require("./Timer");
42
44
  exports.controllerName = 'SnapController';
@@ -46,7 +48,6 @@ exports.SNAP_APPROVAL_UPDATE = 'wallet_updateSnap';
46
48
  const TRUNCATED_SNAP_PROPERTIES = new Set([
47
49
  'initialPermissions',
48
50
  'id',
49
- 'permissionName',
50
51
  'version',
51
52
  'enabled',
52
53
  'blocked',
@@ -80,7 +81,7 @@ const name = 'SnapController';
80
81
  * - Start: Initializes the snap in its SES realm with the authorized permissions.
81
82
  */
82
83
  class SnapController extends base_controller_1.BaseControllerV2 {
83
- constructor({ closeAllConnections, messenger, state, environmentEndowmentPermissions = [], 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 = {}, detectSnapLocation: detectSnapLocationFunction = location_1.detectSnapLocation, }) {
84
+ constructor({ closeAllConnections, messenger, state, environmentEndowmentPermissions = [], excludedPermissions = {}, idleTimeCheckInterval = (0, utils_1.inMilliseconds)(5, utils_1.Duration.Second), registry = new registry_1.JsonSnapsRegistry(), 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 = {}, detectSnapLocation: detectSnapLocationFunction = location_1.detectSnapLocation, }) {
84
85
  var _a, _b;
85
86
  super({
86
87
  messenger,
@@ -125,10 +126,11 @@ class SnapController extends base_controller_1.BaseControllerV2 {
125
126
  _SnapController_instances.add(this);
126
127
  _SnapController_closeAllConnections.set(this, void 0);
127
128
  _SnapController_environmentEndowmentPermissions.set(this, void 0);
129
+ _SnapController_excludedPermissions.set(this, void 0);
128
130
  _SnapController_featureFlags.set(this, void 0);
129
131
  _SnapController_fetchFunction.set(this, void 0);
130
132
  _SnapController_idleTimeCheckInterval.set(this, void 0);
131
- _SnapController_checkSnapBlockList.set(this, void 0);
133
+ _SnapController_registry.set(this, void 0);
132
134
  _SnapController_maxIdleTime.set(this, void 0);
133
135
  _SnapController_detectSnapLocation.set(this, void 0);
134
136
  _SnapController_rollbackSnapshots.set(this, void 0);
@@ -136,10 +138,11 @@ class SnapController extends base_controller_1.BaseControllerV2 {
136
138
  _SnapController_statusMachine.set(this, void 0);
137
139
  __classPrivateFieldSet(this, _SnapController_closeAllConnections, closeAllConnections, "f");
138
140
  __classPrivateFieldSet(this, _SnapController_environmentEndowmentPermissions, environmentEndowmentPermissions, "f");
141
+ __classPrivateFieldSet(this, _SnapController_excludedPermissions, excludedPermissions, "f");
139
142
  __classPrivateFieldSet(this, _SnapController_featureFlags, featureFlags, "f");
140
143
  __classPrivateFieldSet(this, _SnapController_fetchFunction, fetchFunction, "f");
141
144
  __classPrivateFieldSet(this, _SnapController_idleTimeCheckInterval, idleTimeCheckInterval, "f");
142
- __classPrivateFieldSet(this, _SnapController_checkSnapBlockList, checkBlockList, "f");
145
+ __classPrivateFieldSet(this, _SnapController_registry, registry, "f");
143
146
  __classPrivateFieldSet(this, _SnapController_maxIdleTime, maxIdleTime, "f");
144
147
  this.maxRequestTime = maxRequestTime;
145
148
  __classPrivateFieldSet(this, _SnapController_detectSnapLocation, detectSnapLocationFunction, "f");
@@ -170,40 +173,26 @@ class SnapController extends base_controller_1.BaseControllerV2 {
170
173
  * for more information.
171
174
  */
172
175
  async updateBlockedSnaps() {
173
- const blockedSnaps = await __classPrivateFieldGet(this, _SnapController_checkSnapBlockList, "f").call(this, Object.values(this.state.snaps).reduce((blockListArg, snap) => {
176
+ const blockedSnaps = await __classPrivateFieldGet(this, _SnapController_registry, "f").get(Object.values(this.state.snaps).reduce((blockListArg, snap) => {
174
177
  blockListArg[snap.id] = {
175
178
  version: snap.version,
176
- shasum: snap.manifest.source.shasum,
179
+ checksum: snap.manifest.source.shasum,
177
180
  };
178
181
  return blockListArg;
179
182
  }, {}));
180
- await Promise.all(Object.entries(blockedSnaps).map(async (_a) => {
181
- var [snapId, _b] = _a, { blocked } = _b, blockData = __rest(_b, ["blocked"]);
182
- if (blocked) {
183
- return __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_blockSnap).call(this, snapId, blockData);
183
+ await Promise.all(Object.entries(blockedSnaps).map(async ([snapId, { status, reason }]) => {
184
+ if (status === registry_1.SnapsRegistryStatus.Blocked) {
185
+ return __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_blockSnap).call(this, snapId, reason);
184
186
  }
185
187
  return __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_unblockSnap).call(this, snapId);
186
188
  }));
187
189
  }
188
- /**
189
- * Checks the block list to determine whether a version of a snap is blocked.
190
- *
191
- * @param snapId - The snap id to check.
192
- * @param snapInfo - Snap information containing version and shasum.
193
- * @returns Whether the version of the snap is blocked or not.
194
- */
195
- async isBlocked(snapId, snapInfo) {
196
- const result = await __classPrivateFieldGet(this, _SnapController_checkSnapBlockList, "f").call(this, {
197
- [snapId]: snapInfo,
198
- });
199
- return result[snapId].blocked;
200
- }
201
190
  _onUnhandledSnapError(snapId, error) {
202
191
  this.stopSnap(snapId, snaps_utils_1.SnapStatusEvents.Crash)
203
192
  .then(() => this.addSnapError(error))
204
193
  .catch((stopSnapError) => {
205
194
  // TODO: Decide how to handle errors.
206
- console.error(stopSnapError);
195
+ (0, snaps_utils_1.logError)(stopSnapError);
207
196
  });
208
197
  }
209
198
  _onOutboundRequest(snapId) {
@@ -475,9 +464,7 @@ class SnapController extends base_controller_1.BaseControllerV2 {
475
464
  // affect the host environment while we are deleting it.
476
465
  await this.disableSnap(snapId);
477
466
  this.revokeAllSnapPermissions(snapId);
478
- const permissionName = (0, snaps_utils_1.getSnapPermissionName)(snapId);
479
- // Revoke all subjects access to the snap
480
- this.messagingSystem.call('PermissionController:revokePermissionForAllSubjects', permissionName);
467
+ __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_removeSnapFromSubjects).call(this, snapId);
481
468
  this.snapsRuntimeData.delete(snapId);
482
469
  this.update((state) => {
483
470
  delete state.snaps[snapId];
@@ -530,15 +517,14 @@ class SnapController extends base_controller_1.BaseControllerV2 {
530
517
  * @returns The serialized permitted snaps for the origin.
531
518
  */
532
519
  getPermittedSnaps(origin) {
533
- var _a;
534
- return Object.values((_a = this.messagingSystem.call('PermissionController:getPermissions', origin)) !== null && _a !== void 0 ? _a : {}).reduce((permittedSnaps, perm) => {
535
- if (perm.parentCapability.startsWith(snaps_utils_1.SNAP_PREFIX)) {
536
- const snapId = perm.parentCapability.replace(snaps_utils_1.SNAP_PREFIX_REGEX, '');
537
- const snap = this.get(snapId);
538
- const truncatedSnap = this.getTruncated(snapId);
539
- if (truncatedSnap && (snap === null || snap === void 0 ? void 0 : snap.status) !== snaps_utils_1.SnapStatus.Installing) {
540
- permittedSnaps[snapId] = truncatedSnap;
541
- }
520
+ var _a, _b, _c, _d, _e;
521
+ const permissions = (_a = this.messagingSystem.call('PermissionController:getPermissions', origin)) !== null && _a !== void 0 ? _a : {};
522
+ const snaps = (_e = (_d = (_c = (_b = permissions[rpc_methods_1.WALLET_SNAP_PERMISSION_KEY]) === null || _b === void 0 ? void 0 : _b.caveats) === null || _c === void 0 ? void 0 : _c.find((caveat) => caveat.type === snaps_utils_1.SnapCaveatType.SnapIds)) === null || _d === void 0 ? void 0 : _d.value) !== null && _e !== void 0 ? _e : {};
523
+ return Object.keys(snaps).reduce((permittedSnaps, snapId) => {
524
+ const snap = this.get(snapId);
525
+ const truncatedSnap = this.getTruncated(snapId);
526
+ if (truncatedSnap && (snap === null || snap === void 0 ? void 0 : snap.status) !== snaps_utils_1.SnapStatus.Installing) {
527
+ permittedSnaps[snapId] = truncatedSnap;
542
528
  }
543
529
  return permittedSnaps;
544
530
  }, {});
@@ -566,8 +552,8 @@ class SnapController extends base_controller_1.BaseControllerV2 {
566
552
  if (error) {
567
553
  throw eth_rpc_errors_1.ethErrors.rpc.invalidParams(`The "version" field must be a valid SemVer version range if specified. Received: "${rawVersion}".`);
568
554
  }
569
- const permissionName = (0, snaps_utils_1.getSnapPermissionName)(snapId);
570
- if (!this.messagingSystem.call('PermissionController:hasPermission', origin, permissionName)) {
555
+ const permissions = this.messagingSystem.call('PermissionController:getPermissions', origin);
556
+ if (!(0, snaps_utils_1.isSnapPermitted)(permissions, snapId)) {
571
557
  throw eth_rpc_errors_1.ethErrors.provider.unauthorized(`Not authorized to install snap "${snapId}". Request the permission for the snap before attempting to install it.`);
572
558
  }
573
559
  const isUpdate = pendingUpdates.includes(snapId);
@@ -611,15 +597,16 @@ class SnapController extends base_controller_1.BaseControllerV2 {
611
597
  const location = __classPrivateFieldGet(this, _SnapController_detectSnapLocation, "f").call(this, snapId, {
612
598
  versionRange,
613
599
  fetch: __classPrivateFieldGet(this, _SnapController_fetchFunction, "f"),
600
+ allowLocal: __classPrivateFieldGet(this, _SnapController_featureFlags, "f").allowLocalSnaps,
614
601
  });
615
602
  const existingSnap = this.getTruncated(snapId);
616
603
  // For devX we always re-install local snaps.
617
604
  if (existingSnap && !location.shouldAlwaysReload) {
618
- if ((0, snaps_utils_1.satisfiesVersionRange)(existingSnap.version, versionRange)) {
605
+ if ((0, utils_1.satisfiesVersionRange)(existingSnap.version, versionRange)) {
619
606
  return existingSnap;
620
607
  }
621
608
  if (__classPrivateFieldGet(this, _SnapController_featureFlags, "f").dappsCanUpdateSnaps === true) {
622
- const updateResult = await this.updateSnap(origin, snapId, versionRange, location);
609
+ const updateResult = await this.updateSnap(origin, snapId, location, versionRange);
623
610
  if (updateResult === null) {
624
611
  throw eth_rpc_errors_1.ethErrors.rpc.invalidParams(`Snap "${snapId}@${existingSnap.version}" is already installed. Couldn't update to a version inside requested "${versionRange}" range.`);
625
612
  }
@@ -647,7 +634,7 @@ class SnapController extends base_controller_1.BaseControllerV2 {
647
634
  return truncated;
648
635
  }
649
636
  catch (error) {
650
- console.error(`Error when adding snap.`, error);
637
+ (0, snaps_utils_1.logError)(`Error when adding snap.`, error);
651
638
  throw error;
652
639
  }
653
640
  }
@@ -665,25 +652,25 @@ class SnapController extends base_controller_1.BaseControllerV2 {
665
652
  *
666
653
  * @param origin - The origin requesting the snap update.
667
654
  * @param snapId - The id of the Snap to be updated.
668
- * @param newVersionRange - A semver version range in which the maximum version will be chosen.
669
655
  * @param location - Optional location that was already used during installation flow.
656
+ * @param newVersionRange - A semver version range in which the maximum version will be chosen.
670
657
  * @returns The snap metadata if updated, `null` otherwise.
671
658
  */
672
- async updateSnap(origin, snapId, newVersionRange = snaps_utils_1.DEFAULT_REQUESTED_SNAP_VERSION, location) {
659
+ async updateSnap(origin, snapId, location, newVersionRange = snaps_utils_1.DEFAULT_REQUESTED_SNAP_VERSION) {
673
660
  var _a;
674
661
  const snap = this.getExpect(snapId);
675
- if (!(0, snaps_utils_1.isValidSemVerRange)(newVersionRange)) {
662
+ if (!(0, utils_1.isValidSemVerRange)(newVersionRange)) {
676
663
  throw new Error(`Received invalid snap version range: "${newVersionRange}".`);
677
664
  }
678
- const newSnap = await __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_fetchSnap).call(this, snapId, location !== null && location !== void 0 ? location : __classPrivateFieldGet(this, _SnapController_detectSnapLocation, "f").call(this, snapId, { versionRange: newVersionRange }));
665
+ const newSnap = await __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_fetchSnap).call(this, snapId, location);
679
666
  const newVersion = newSnap.manifest.result.version;
680
- if (!(0, snaps_utils_1.gtVersion)(newVersion, snap.version)) {
681
- console.warn(`Tried updating snap "${snapId}" within "${newVersionRange}" version range, but newer version "${snap.version}" is already installed`);
667
+ if (!(0, utils_1.gtVersion)(newVersion, snap.version)) {
668
+ (0, snaps_utils_1.logWarning)(`Tried updating snap "${snapId}" within "${newVersionRange}" version range, but newer version "${snap.version}" is already installed`);
682
669
  return null;
683
670
  }
684
- await __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_assertIsUnblocked).call(this, snapId, {
671
+ await __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_assertIsInstallAllowed).call(this, snapId, {
685
672
  version: newVersion,
686
- shasum: newSnap.manifest.result.source.shasum,
673
+ checksum: newSnap.manifest.result.source.shasum,
687
674
  });
688
675
  const processedPermissions = __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_processSnapPermissions).call(this, newSnap.manifest.result.initialPermissions);
689
676
  const { newPermissions, unusedPermissions, approvedPermissions } = __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_calculatePermissionsChange).call(this, snapId, processedPermissions);
@@ -734,9 +721,10 @@ class SnapController extends base_controller_1.BaseControllerV2 {
734
721
  rollbackSnapshot.permissions.granted = Object.keys(approvedNewPermissions);
735
722
  rollbackSnapshot.permissions.requestData = requestData;
736
723
  }
724
+ const normalizedSourcePath = (0, snaps_utils_1.normalizeRelative)(newSnap.manifest.result.source.location.npm.filePath);
737
725
  const sourceCode = (_a = newSnap.files
738
- .find((file) => file.path === newSnap.manifest.result.source.location.npm.filePath)) === null || _a === void 0 ? void 0 : _a.toString();
739
- (0, utils_1.assert)(sourceCode !== undefined);
726
+ .find((file) => file.path === normalizedSourcePath)) === null || _a === void 0 ? void 0 : _a.toString();
727
+ (0, utils_1.assert)(typeof sourceCode === 'string' && sourceCode.length > 0, `Invalid source code for snap "${snapId}".`);
740
728
  try {
741
729
  await __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_startSnap).call(this, { snapId, sourceCode });
742
730
  }
@@ -747,6 +735,16 @@ class SnapController extends base_controller_1.BaseControllerV2 {
747
735
  this.messagingSystem.publish('SnapController:snapUpdated', truncatedSnap, snap.version);
748
736
  return truncatedSnap;
749
737
  }
738
+ /**
739
+ * Get metadata for the given snap ID.
740
+ *
741
+ * @param snapId - The ID of the snap to get metadata for.
742
+ * @returns The metadata for the given snap ID, or `null` if the snap is not
743
+ * verified.
744
+ */
745
+ async getRegistryMetadata(snapId) {
746
+ return await __classPrivateFieldGet(this, _SnapController_registry, "f").getMetadata(snapId);
747
+ }
750
748
  /**
751
749
  * Initiates a request for the given snap's initial permissions.
752
750
  * Must be called in order. See processRequestedSnap.
@@ -758,12 +756,19 @@ class SnapController extends base_controller_1.BaseControllerV2 {
758
756
  * @returns The snap's approvedPermissions.
759
757
  */
760
758
  async authorize(origin, snapId) {
761
- console.info(`Authorizing snap: ${snapId}`);
759
+ (0, logging_1.log)(`Authorizing snap: ${snapId}`);
762
760
  const snapsState = this.state.snaps;
763
761
  const snap = snapsState[snapId];
764
762
  const { initialPermissions } = snap;
765
763
  try {
766
764
  const processedPermissions = __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_processSnapPermissions).call(this, initialPermissions);
765
+ const excludedPermissionErrors = Object.keys(processedPermissions).reduce((errors, permission) => {
766
+ if ((0, utils_1.hasProperty)(__classPrivateFieldGet(this, _SnapController_excludedPermissions, "f"), permission)) {
767
+ errors.push(__classPrivateFieldGet(this, _SnapController_excludedPermissions, "f")[permission]);
768
+ }
769
+ return errors;
770
+ }, []);
771
+ (0, utils_1.assert)(excludedPermissionErrors.length === 0, `One or more permissions are not allowed:\n${excludedPermissionErrors.join('\n')}`);
767
772
  const id = (0, nanoid_1.nanoid)();
768
773
  const _a = (await this.messagingSystem.call('ApprovalController:addRequest', {
769
774
  origin,
@@ -836,7 +841,7 @@ class SnapController extends base_controller_1.BaseControllerV2 {
836
841
  }
837
842
  }
838
843
  exports.SnapController = SnapController;
839
- _SnapController_closeAllConnections = new WeakMap(), _SnapController_environmentEndowmentPermissions = new WeakMap(), _SnapController_featureFlags = new WeakMap(), _SnapController_fetchFunction = new WeakMap(), _SnapController_idleTimeCheckInterval = new WeakMap(), _SnapController_checkSnapBlockList = new WeakMap(), _SnapController_maxIdleTime = new WeakMap(), _SnapController_detectSnapLocation = new WeakMap(), _SnapController_rollbackSnapshots = new WeakMap(), _SnapController_timeoutForLastRequestStatus = new WeakMap(), _SnapController_statusMachine = new WeakMap(), _SnapController_instances = new WeakSet(), _SnapController_initializeStateMachine = function _SnapController_initializeStateMachine() {
844
+ _SnapController_closeAllConnections = new WeakMap(), _SnapController_environmentEndowmentPermissions = new WeakMap(), _SnapController_excludedPermissions = new WeakMap(), _SnapController_featureFlags = new WeakMap(), _SnapController_fetchFunction = new WeakMap(), _SnapController_idleTimeCheckInterval = new WeakMap(), _SnapController_registry = new WeakMap(), _SnapController_maxIdleTime = new WeakMap(), _SnapController_detectSnapLocation = new WeakMap(), _SnapController_rollbackSnapshots = new WeakMap(), _SnapController_timeoutForLastRequestStatus = new WeakMap(), _SnapController_statusMachine = new WeakMap(), _SnapController_instances = new WeakSet(), _SnapController_initializeStateMachine = function _SnapController_initializeStateMachine() {
840
845
  const disableGuard = ({ snapId }) => {
841
846
  return this.getExpect(snapId).enabled;
842
847
  };
@@ -880,6 +885,7 @@ _SnapController_closeAllConnections = new WeakMap(), _SnapController_environment
880
885
  target: snaps_utils_1.SnapStatus.Running,
881
886
  cond: disableGuard,
882
887
  },
888
+ [snaps_utils_1.SnapStatusEvents.Update]: snaps_utils_1.SnapStatus.Updating,
883
889
  },
884
890
  },
885
891
  },
@@ -903,11 +909,12 @@ _SnapController_closeAllConnections = new WeakMap(), _SnapController_environment
903
909
  this.messagingSystem.registerActionHandler(`${exports.controllerName}:getAll`, (...args) => this.getAllSnaps(...args));
904
910
  this.messagingSystem.registerActionHandler(`${exports.controllerName}:incrementActiveReferences`, (...args) => this.incrementActiveReferences(...args));
905
911
  this.messagingSystem.registerActionHandler(`${exports.controllerName}:decrementActiveReferences`, (...args) => this.decrementActiveReferences(...args));
912
+ this.messagingSystem.registerActionHandler(`${exports.controllerName}:getRegistryMetadata`, async (...args) => this.getRegistryMetadata(...args));
906
913
  }, _SnapController_pollForLastRequestStatus = function _SnapController_pollForLastRequestStatus() {
907
914
  __classPrivateFieldSet(this, _SnapController_timeoutForLastRequestStatus, setTimeout(() => {
908
915
  __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_stopSnapsLastRequestPastMax).call(this).catch((error) => {
909
916
  // TODO: Decide how to handle errors.
910
- console.error(error);
917
+ (0, snaps_utils_1.logError)(error);
911
918
  });
912
919
  __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_pollForLastRequestStatus).call(this);
913
920
  }, __classPrivateFieldGet(this, _SnapController_idleTimeCheckInterval, "f")), "f");
@@ -931,7 +938,7 @@ async function _SnapController_blockSnap(snapId, blockedSnapInfo) {
931
938
  await this.disableSnap(snapId);
932
939
  }
933
940
  catch (error) {
934
- console.error(`Encountered error when stopping blocked snap "${snapId}".`, error);
941
+ (0, snaps_utils_1.logError)(`Encountered error when stopping blocked snap "${snapId}".`, error);
935
942
  }
936
943
  this.messagingSystem.publish(`${exports.controllerName}:snapBlocked`, snapId, blockedSnapInfo);
937
944
  }, _SnapController_unblockSnap = function _SnapController_unblockSnap(snapId) {
@@ -943,17 +950,18 @@ async function _SnapController_blockSnap(snapId, blockedSnapInfo) {
943
950
  delete state.snaps[snapId].blockInformation;
944
951
  });
945
952
  this.messagingSystem.publish(`${exports.controllerName}:snapUnblocked`, snapId);
946
- }, _SnapController_assertIsUnblocked =
947
- /**
948
- * Asserts that a version of a snap is not blocked. Succeeds automatically
949
- * if {@link SnapController._checkSnapBlockList} is undefined.
950
- *
951
- * @param snapId - The id of the snap to check.
952
- * @param snapInfo - Snap information containing version and shasum.
953
- */
954
- async function _SnapController_assertIsUnblocked(snapId, snapInfo) {
955
- if (await this.isBlocked(snapId, snapInfo)) {
956
- throw new Error(`Cannot install version "${snapInfo.version}" of snap "${snapId}": the version is blocked.`);
953
+ }, _SnapController_assertIsInstallAllowed = async function _SnapController_assertIsInstallAllowed(snapId, snapInfo) {
954
+ var _a, _b;
955
+ const results = await __classPrivateFieldGet(this, _SnapController_registry, "f").get({
956
+ [snapId]: snapInfo,
957
+ });
958
+ const result = results[snapId];
959
+ if (result.status === registry_1.SnapsRegistryStatus.Blocked) {
960
+ throw new Error(`Cannot install version "${snapInfo.version}" of snap "${snapId}": The version is blocked. ${(_b = (_a = result.reason) === null || _a === void 0 ? void 0 : _a.explanation) !== null && _b !== void 0 ? _b : ''}`);
961
+ }
962
+ else if (__classPrivateFieldGet(this, _SnapController_featureFlags, "f").requireAllowlist &&
963
+ result.status !== registry_1.SnapsRegistryStatus.Verified) {
964
+ throw new Error(`Cannot install version "${snapInfo.version}" of snap "${snapId}": The snap is not on the allow list.`);
957
965
  }
958
966
  }, _SnapController_stopSnapsLastRequestPastMax = async function _SnapController_stopSnapsLastRequestPastMax() {
959
967
  const entries = [...this.snapsRuntimeData.entries()];
@@ -980,6 +988,19 @@ async function _SnapController_assertIsUnblocked(snapId, snapInfo) {
980
988
  async function _SnapController_terminateSnap(snapId) {
981
989
  await this.messagingSystem.call('ExecutionService:terminateSnap', snapId);
982
990
  this.messagingSystem.publish('SnapController:snapTerminated', this.getTruncatedExpect(snapId));
991
+ }, _SnapController_removeSnapFromSubjects = function _SnapController_removeSnapFromSubjects(snapId) {
992
+ var _a, _b, _c, _d;
993
+ const subjects = this.messagingSystem.call('PermissionController:getSubjectNames');
994
+ for (const subject of subjects) {
995
+ const subjectPermissions = this.messagingSystem.call('PermissionController:getPermissions', subject);
996
+ const snapIdsCaveat = ((_c = (_b = (_a = subjectPermissions === null || subjectPermissions === void 0 ? void 0 : subjectPermissions[rpc_methods_1.WALLET_SNAP_PERMISSION_KEY]) === null || _a === void 0 ? void 0 : _a.caveats) === null || _b === void 0 ? void 0 : _b.find((caveat) => caveat.type === snaps_utils_1.SnapCaveatType.SnapIds)) !== null && _c !== void 0 ? _c : {});
997
+ const caveatHasSnap = Boolean((_d = snapIdsCaveat.value) === null || _d === void 0 ? void 0 : _d[snapId]);
998
+ if (caveatHasSnap) {
999
+ const newCaveatValue = Object.assign({}, snapIdsCaveat.value);
1000
+ delete newCaveatValue[snapId];
1001
+ this.messagingSystem.call('PermissionController:updateCaveat', subject, rpc_methods_1.WALLET_SNAP_PERMISSION_KEY, snaps_utils_1.SnapCaveatType.SnapIds, newCaveatValue);
1002
+ }
1003
+ }
983
1004
  }, _SnapController_add =
984
1005
  /**
985
1006
  * Returns a promise representing the complete installation of the requested snap.
@@ -996,14 +1017,14 @@ async function _SnapController_add(args) {
996
1017
  __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_setupRuntime).call(this, snapId, { sourceCode: null, state: null });
997
1018
  const runtime = __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_getRuntimeExpect).call(this, snapId);
998
1019
  if (!runtime.installPromise) {
999
- console.info(`Adding snap: ${snapId}`);
1020
+ (0, logging_1.log)(`Adding snap: ${snapId}`);
1000
1021
  // If fetching and setting the snap succeeds, this property will be set
1001
1022
  // to null in the authorize() method.
1002
1023
  runtime.installPromise = (async () => {
1003
1024
  const fetchedSnap = await __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_fetchSnap).call(this, snapId, location);
1004
- await __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_assertIsUnblocked).call(this, snapId, {
1025
+ await __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_assertIsInstallAllowed).call(this, snapId, {
1005
1026
  version: fetchedSnap.manifest.result.version,
1006
- shasum: fetchedSnap.manifest.result.source.shasum,
1027
+ checksum: fetchedSnap.manifest.result.source.shasum,
1007
1028
  });
1008
1029
  return __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_set).call(this, Object.assign(Object.assign(Object.assign({}, args), fetchedSnap), { id: snapId }));
1009
1030
  })();
@@ -1066,7 +1087,7 @@ async function _SnapController_getEndowments(snapId) {
1066
1087
  // This is a bug in TypeScript: https://github.com/microsoft/TypeScript/issues/48313
1067
1088
  // eslint-disable-next-line @typescript-eslint/restrict-plus-operands
1068
1089
  snaps_utils_1.DEFAULT_ENDOWMENTS.length + allEndowments.length) {
1069
- console.error('Duplicate endowments found. Default endowments should not be requested.', allEndowments);
1090
+ (0, snaps_utils_1.logError)('Duplicate endowments found. Default endowments should not be requested.', allEndowments);
1070
1091
  }
1071
1092
  return dedupedEndowments;
1072
1093
  }, _SnapController_set = function _SnapController_set(args) {
@@ -1074,17 +1095,18 @@ async function _SnapController_getEndowments(snapId) {
1074
1095
  const { id: snapId, origin, manifest, files, versionRange = snaps_utils_1.DEFAULT_REQUESTED_SNAP_VERSION, isUpdate = false, } = args;
1075
1096
  (0, snaps_utils_1.assertIsSnapManifest)(manifest.result);
1076
1097
  const { version } = manifest.result;
1077
- if (!(0, snaps_utils_1.satisfiesVersionRange)(version, versionRange)) {
1098
+ if (!(0, utils_1.satisfiesVersionRange)(version, versionRange)) {
1078
1099
  throw new Error(`Version mismatch. Manifest for "${snapId}" specifies version "${version}" which doesn't satisfy requested version range "${versionRange}"`);
1079
1100
  }
1101
+ const normalizedSourcePath = (0, snaps_utils_1.normalizeRelative)(manifest.result.source.location.npm.filePath);
1102
+ const { iconPath } = manifest.result.source.location.npm;
1103
+ const normalizedIconPath = iconPath && (0, snaps_utils_1.normalizeRelative)(iconPath);
1080
1104
  const sourceCode = (_a = files
1081
- .find((file) => file.path === manifest.result.source.location.npm.filePath)) === null || _a === void 0 ? void 0 : _a.toString();
1082
- const svgIcon = files.find((file) => manifest.result.source.location.npm.iconPath !== undefined &&
1083
- file.path === manifest.result.source.location.npm.iconPath);
1084
- (0, utils_1.assert)(sourceCode !== undefined);
1085
- if (typeof sourceCode !== 'string' || sourceCode.length === 0) {
1086
- throw new Error(`Invalid source code for snap "${snapId}".`);
1087
- }
1105
+ .find((file) => file.path === normalizedSourcePath)) === null || _a === void 0 ? void 0 : _a.toString();
1106
+ const svgIcon = normalizedIconPath
1107
+ ? files.find((file) => file.path === normalizedIconPath)
1108
+ : undefined;
1109
+ (0, utils_1.assert)(typeof sourceCode === 'string' && sourceCode.length > 0, `Invalid source code for snap "${snapId}".`);
1088
1110
  const snapsState = this.state.snaps;
1089
1111
  const existingSnap = snapsState[snapId];
1090
1112
  const previousVersionHistory = (_b = existingSnap === null || existingSnap === void 0 ? void 0 : existingSnap.versionHistory) !== null && _b !== void 0 ? _b : [];
@@ -1099,9 +1121,7 @@ async function _SnapController_getEndowments(snapId) {
1099
1121
  const snap = Object.assign(Object.assign({}, existingSnap), {
1100
1122
  // Note that the snap will be unblocked and enabled, regardless of its
1101
1123
  // previous state.
1102
- blocked: false, enabled: true,
1103
- // So we can easily correlate the snap with its permission
1104
- permissionName: (0, snaps_utils_1.getSnapPermissionName)(snapId), id: snapId, initialPermissions: manifest.result.initialPermissions, manifest: manifest.result, status: __classPrivateFieldGet(this, _SnapController_statusMachine, "f").config.initial, version,
1124
+ blocked: false, enabled: true, id: snapId, initialPermissions: manifest.result.initialPermissions, manifest: manifest.result, status: __classPrivateFieldGet(this, _SnapController_statusMachine, "f").config.initial, version,
1105
1125
  versionHistory });
1106
1126
  // If the snap was blocked, it isn't any longer
1107
1127
  delete snap.blockInformation;
@@ -1135,12 +1155,13 @@ async function _SnapController_fetchSnap(snapId, location) {
1135
1155
  try {
1136
1156
  const manifest = await location.manifest();
1137
1157
  const sourceCode = await location.fetch(manifest.result.source.location.npm.filePath);
1138
- (0, snaps_utils_1.validateSnapShasum)(manifest.result, sourceCode.toString());
1139
1158
  const { iconPath } = manifest.result.source.location.npm;
1159
+ const svgIcon = iconPath ? await location.fetch(iconPath) : undefined;
1140
1160
  const files = [sourceCode];
1141
- if (iconPath) {
1142
- files.push(await location.fetch(iconPath));
1161
+ if (svgIcon) {
1162
+ files.push(svgIcon);
1143
1163
  }
1164
+ (0, snaps_utils_1.validateSnapShasum)({ manifest, sourceCode, svgIcon });
1144
1165
  return { manifest, files, location };
1145
1166
  }
1146
1167
  catch (error) {
@@ -1245,6 +1266,7 @@ async function _SnapController_executeWithTimeout(snapId, promise, timer) {
1245
1266
  const isLongRunning = this.messagingSystem.call('PermissionController:hasPermission', snapId, endowments_1.SnapEndowments.LongRunning);
1246
1267
  // Long running snaps have timeouts disabled
1247
1268
  if (isLongRunning) {
1269
+ (0, snaps_utils_1.logWarning)(`${endowments_1.SnapEndowments.LongRunning} will soon be deprecated. For more information please see https://github.com/MetaMask/snaps-monorepo/issues/945.`);
1248
1270
  return promise;
1249
1271
  }
1250
1272
  const result = await (0, utils_2.withTimeout)(promise, timer !== null && timer !== void 0 ? timer : this.maxRequestTime);
@@ -1360,10 +1382,10 @@ async function _SnapController_rollbackSnaps(snapIds) {
1360
1382
  return { newPermissions, unusedPermissions, approvedPermissions };
1361
1383
  }, _SnapController_isValidUpdate = function _SnapController_isValidUpdate(snapId, newVersionRange) {
1362
1384
  const existingSnap = this.getExpect(snapId);
1363
- if ((0, snaps_utils_1.satisfiesVersionRange)(existingSnap.version, newVersionRange)) {
1385
+ if ((0, utils_1.satisfiesVersionRange)(existingSnap.version, newVersionRange)) {
1364
1386
  return false;
1365
1387
  }
1366
- if ((0, snaps_utils_1.gtRange)(existingSnap.version, newVersionRange)) {
1388
+ if ((0, utils_1.gtRange)(existingSnap.version, newVersionRange)) {
1367
1389
  return false;
1368
1390
  }
1369
1391
  return true;