@metamask/snaps-controllers 11.0.1 → 11.2.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/CHANGELOG.md +36 -1
  2. package/dist/cronjob/CronjobController.cjs +2 -2
  3. package/dist/cronjob/CronjobController.cjs.map +1 -1
  4. package/dist/cronjob/CronjobController.mjs +2 -2
  5. package/dist/cronjob/CronjobController.mjs.map +1 -1
  6. package/dist/insights/SnapInsightsController.cjs +1 -1
  7. package/dist/insights/SnapInsightsController.cjs.map +1 -1
  8. package/dist/insights/SnapInsightsController.mjs +1 -1
  9. package/dist/insights/SnapInsightsController.mjs.map +1 -1
  10. package/dist/interface/SnapInterfaceController.cjs +21 -11
  11. package/dist/interface/SnapInterfaceController.cjs.map +1 -1
  12. package/dist/interface/SnapInterfaceController.d.cts +17 -4
  13. package/dist/interface/SnapInterfaceController.d.cts.map +1 -1
  14. package/dist/interface/SnapInterfaceController.d.mts +17 -4
  15. package/dist/interface/SnapInterfaceController.d.mts.map +1 -1
  16. package/dist/interface/SnapInterfaceController.mjs +23 -13
  17. package/dist/interface/SnapInterfaceController.mjs.map +1 -1
  18. package/dist/interface/utils.cjs +124 -23
  19. package/dist/interface/utils.cjs.map +1 -1
  20. package/dist/interface/utils.d.cts +82 -2
  21. package/dist/interface/utils.d.cts.map +1 -1
  22. package/dist/interface/utils.d.mts +82 -2
  23. package/dist/interface/utils.d.mts.map +1 -1
  24. package/dist/interface/utils.mjs +120 -22
  25. package/dist/interface/utils.mjs.map +1 -1
  26. package/dist/multichain/MultichainRouter.cjs +3 -2
  27. package/dist/multichain/MultichainRouter.cjs.map +1 -1
  28. package/dist/multichain/MultichainRouter.d.cts +1 -15
  29. package/dist/multichain/MultichainRouter.d.cts.map +1 -1
  30. package/dist/multichain/MultichainRouter.d.mts +1 -15
  31. package/dist/multichain/MultichainRouter.d.mts.map +1 -1
  32. package/dist/multichain/MultichainRouter.mjs +3 -2
  33. package/dist/multichain/MultichainRouter.mjs.map +1 -1
  34. package/dist/snaps/SnapController.cjs +93 -74
  35. package/dist/snaps/SnapController.cjs.map +1 -1
  36. package/dist/snaps/SnapController.d.cts +6 -1
  37. package/dist/snaps/SnapController.d.cts.map +1 -1
  38. package/dist/snaps/SnapController.d.mts +6 -1
  39. package/dist/snaps/SnapController.d.mts.map +1 -1
  40. package/dist/snaps/SnapController.mjs +96 -77
  41. package/dist/snaps/SnapController.mjs.map +1 -1
  42. package/dist/snaps/constants.cjs +5 -1
  43. package/dist/snaps/constants.cjs.map +1 -1
  44. package/dist/snaps/constants.d.cts +4 -0
  45. package/dist/snaps/constants.d.cts.map +1 -1
  46. package/dist/snaps/constants.d.mts +4 -0
  47. package/dist/snaps/constants.d.mts.map +1 -1
  48. package/dist/snaps/constants.mjs +4 -0
  49. package/dist/snaps/constants.mjs.map +1 -1
  50. package/dist/utils.cjs +29 -1
  51. package/dist/utils.cjs.map +1 -1
  52. package/dist/utils.d.cts +20 -4
  53. package/dist/utils.d.cts.map +1 -1
  54. package/dist/utils.d.mts +20 -4
  55. package/dist/utils.d.mts.map +1 -1
  56. package/dist/utils.mjs +27 -0
  57. package/dist/utils.mjs.map +1 -1
  58. package/package.json +15 -25
@@ -10,7 +10,7 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
10
10
  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");
11
11
  return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
12
12
  };
13
- var _SnapController_instances, _SnapController_closeAllConnections, _SnapController_dynamicPermissions, _SnapController_environmentEndowmentPermissions, _SnapController_excludedPermissions, _SnapController_featureFlags, _SnapController_fetchFunction, _SnapController_idleTimeCheckInterval, _SnapController_maxIdleTime, _SnapController_encryptor, _SnapController_getMnemonicSeed, _SnapController_getFeatureFlags, _SnapController_clientCryptography, _SnapController_detectSnapLocation, _SnapController_snapsRuntimeData, _SnapController_rollbackSnapshots, _SnapController_timeoutForLastRequestStatus, _SnapController_statusMachine, _SnapController_preinstalledSnaps, _SnapController_initializeStateMachine, _SnapController_registerMessageHandlers, _SnapController_handlePreinstalledSnaps, _SnapController_pollForLastRequestStatus, _SnapController_blockSnap, _SnapController_unblockSnap, _SnapController_assertIsInstallAllowed, _SnapController_assertCanInstallSnaps, _SnapController_assertCanUsePlatform, _SnapController_stopSnapsLastRequestPastMax, _SnapController_transition, _SnapController_terminateSnap, _SnapController_getSnapEncryptionKey, _SnapController_hasCachedEncryptionKey, _SnapController_decryptSnapState, _SnapController_encryptSnapState, _SnapController_getStateToPersist, _SnapController_persistSnapState, _SnapController_handleInitialConnections, _SnapController_addSnapToSubject, _SnapController_removeSnapFromSubjects, _SnapController_revokeAllSnapPermissions, _SnapController_createApproval, _SnapController_updateApproval, _SnapController_resolveAllowlistVersion, _SnapController_add, _SnapController_startSnap, _SnapController_getEndowments, _SnapController_set, _SnapController_validateSnapPermissions, _SnapController_validatePlatformVersion, _SnapController_getExecutionTimeout, _SnapController_getRpcRequestHandler, _SnapController_createInterface, _SnapController_assertInterfaceExists, _SnapController_transformSnapRpcRequestResult, _SnapController_transformOnAssetsLookupResult, _SnapController_transformOnAssetsConversionResult, _SnapController_assertSnapRpcRequestResult, _SnapController_recordSnapRpcRequestStart, _SnapController_recordSnapRpcRequestFinish, _SnapController_getRollbackSnapshot, _SnapController_createRollbackSnapshot, _SnapController_rollbackSnap, _SnapController_rollbackSnaps, _SnapController_getRuntime, _SnapController_getRuntimeExpect, _SnapController_setupRuntime, _SnapController_calculatePermissionsChange, _SnapController_isSubjectConnectedToSnap, _SnapController_calculateConnectionsChange, _SnapController_updatePermissions, _SnapController_isValidUpdate, _SnapController_callLifecycleHook, _SnapController_handleLock;
13
+ var _SnapController_instances, _SnapController_closeAllConnections, _SnapController_dynamicPermissions, _SnapController_environmentEndowmentPermissions, _SnapController_excludedPermissions, _SnapController_featureFlags, _SnapController_fetchFunction, _SnapController_idleTimeCheckInterval, _SnapController_maxIdleTime, _SnapController_encryptor, _SnapController_getMnemonicSeed, _SnapController_getFeatureFlags, _SnapController_clientCryptography, _SnapController_detectSnapLocation, _SnapController_snapsRuntimeData, _SnapController_rollbackSnapshots, _SnapController_timeoutForLastRequestStatus, _SnapController_statusMachine, _SnapController_preinstalledSnaps, _SnapController_initializeStateMachine, _SnapController_registerMessageHandlers, _SnapController_handlePreinstalledSnaps, _SnapController_pollForLastRequestStatus, _SnapController_blockSnap, _SnapController_unblockSnap, _SnapController_assertIsInstallAllowed, _SnapController_assertCanInstallSnaps, _SnapController_assertCanUsePlatform, _SnapController_stopSnapsLastRequestPastMax, _SnapController_transition, _SnapController_terminateSnap, _SnapController_hasCachedEncryptionKey, _SnapController_getSnapEncryptionKey, _SnapController_decryptSnapState, _SnapController_encryptSnapState, _SnapController_getStateToPersist, _SnapController_persistSnapState, _SnapController_handleInitialConnections, _SnapController_addSnapToSubject, _SnapController_removeSnapFromSubjects, _SnapController_revokeAllSnapPermissions, _SnapController_createApproval, _SnapController_updateApproval, _SnapController_resolveAllowlistVersion, _SnapController_add, _SnapController_startSnap, _SnapController_getEndowments, _SnapController_set, _SnapController_validateSnapPermissions, _SnapController_validatePlatformVersion, _SnapController_getExecutionTimeout, _SnapController_getRpcRequestHandler, _SnapController_createInterface, _SnapController_assertInterfaceExists, _SnapController_transformSnapRpcResponse, _SnapController_transformOnAssetsLookupResult, _SnapController_transformOnAssetsConversionResult, _SnapController_transformSnapRpcRequest, _SnapController_assertSnapRpcResponse, _SnapController_recordSnapRpcRequestStart, _SnapController_recordSnapRpcRequestFinish, _SnapController_getRollbackSnapshot, _SnapController_createRollbackSnapshot, _SnapController_rollbackSnap, _SnapController_rollbackSnaps, _SnapController_getRuntime, _SnapController_getRuntimeExpect, _SnapController_setupRuntime, _SnapController_calculatePermissionsChange, _SnapController_isSubjectConnectedToSnap, _SnapController_calculateConnectionsChange, _SnapController_updatePermissions, _SnapController_isValidUpdate, _SnapController_callLifecycleHook, _SnapController_handleLock;
14
14
  Object.defineProperty(exports, "__esModule", { value: true });
15
15
  exports.SnapController = exports.SNAP_APPROVAL_RESULT = exports.SNAP_APPROVAL_UPDATE = exports.SNAP_APPROVAL_INSTALL = exports.controllerName = void 0;
16
16
  const base_controller_1 = require("@metamask/base-controller");
@@ -130,6 +130,35 @@ class SnapController extends base_controller_1.BaseController {
130
130
  _SnapController_timeoutForLastRequestStatus.set(this, void 0);
131
131
  _SnapController_statusMachine.set(this, void 0);
132
132
  _SnapController_preinstalledSnaps.set(this, void 0);
133
+ /**
134
+ * Persist the state of a Snap.
135
+ *
136
+ * This function is debounced per Snap, meaning that multiple calls to this
137
+ * function for the same Snap will only result in one state update. It also
138
+ * uses a mutex to ensure that only one state update per Snap is processed at
139
+ * a time, avoiding possible race conditions.
140
+ *
141
+ * @param snapId - The Snap ID.
142
+ * @param newSnapState - The new state of the Snap.
143
+ * @param encrypted - A flag to indicate whether to use encrypted storage or
144
+ * not.
145
+ */
146
+ _SnapController_persistSnapState.set(this, (0, utils_2.debouncePersistState)((snapId, newSnapState, encrypted) => {
147
+ const runtime = __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_getRuntimeExpect).call(this, snapId);
148
+ runtime.stateMutex
149
+ .runExclusive(async () => {
150
+ const newState = await __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_getStateToPersist).call(this, snapId, newSnapState, encrypted);
151
+ if (encrypted) {
152
+ return this.update((state) => {
153
+ state.snapStates[snapId] = newState;
154
+ });
155
+ }
156
+ return this.update((state) => {
157
+ state.unencryptedSnapStates[snapId] = newState;
158
+ });
159
+ })
160
+ .catch(snaps_utils_1.logError);
161
+ }, constants_1.STATE_DEBOUNCE_TIMEOUT));
133
162
  __classPrivateFieldSet(this, _SnapController_closeAllConnections, closeAllConnections, "f");
134
163
  __classPrivateFieldSet(this, _SnapController_dynamicPermissions, dynamicPermissions, "f");
135
164
  __classPrivateFieldSet(this, _SnapController_environmentEndowmentPermissions, environmentEndowmentPermissions, "f");
@@ -406,11 +435,7 @@ class SnapController extends base_controller_1.BaseController {
406
435
  else {
407
436
  runtime.unencryptedState = newSnapState;
408
437
  }
409
- // This is intentionally run asynchronously to avoid blocking the main
410
- // thread.
411
- __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_persistSnapState).call(this, snapId, newSnapState, encrypted).catch((error) => {
412
- (0, snaps_utils_1.logError)(error);
413
- });
438
+ __classPrivateFieldGet(this, _SnapController_persistSnapState, "f").call(this, snapId, newSnapState, encrypted);
414
439
  }
415
440
  /**
416
441
  * Clears the state of the snap with the given id.
@@ -427,11 +452,7 @@ class SnapController extends base_controller_1.BaseController {
427
452
  else {
428
453
  runtime.unencryptedState = null;
429
454
  }
430
- // This is intentionally run asynchronously to avoid blocking the main
431
- // thread.
432
- __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_persistSnapState).call(this, snapId, null, encrypted).catch((error) => {
433
- (0, snaps_utils_1.logError)(error);
434
- });
455
+ __classPrivateFieldGet(this, _SnapController_persistSnapState, "f").call(this, snapId, null, encrypted);
435
456
  }
436
457
  /**
437
458
  * Gets the own state of the snap with the given id.
@@ -443,26 +464,29 @@ class SnapController extends base_controller_1.BaseController {
443
464
  */
444
465
  async getSnapState(snapId, encrypted) {
445
466
  const runtime = __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_getRuntimeExpect).call(this, snapId);
446
- const cachedState = encrypted ? runtime.state : runtime.unencryptedState;
447
- if (cachedState !== undefined) {
448
- return cachedState;
449
- }
450
- const state = encrypted
451
- ? this.state.snapStates[snapId]
452
- : this.state.unencryptedSnapStates[snapId];
453
- if (state === null || state === undefined) {
454
- return null;
455
- }
456
- if (!encrypted) {
457
- // For performance reasons, we do not validate that the state is JSON,
458
- // since we control serialization.
459
- const json = JSON.parse(state);
460
- runtime.unencryptedState = json;
461
- return json;
462
- }
463
- const decrypted = await __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_decryptSnapState).call(this, snapId, state);
464
- runtime.state = decrypted;
465
- return decrypted;
467
+ return await runtime.getStateMutex.runExclusive(async () => {
468
+ const cachedState = encrypted ? runtime.state : runtime.unencryptedState;
469
+ if (cachedState !== undefined) {
470
+ return cachedState;
471
+ }
472
+ const state = encrypted
473
+ ? this.state.snapStates[snapId]
474
+ : this.state.unencryptedSnapStates[snapId];
475
+ if (state === null || state === undefined) {
476
+ return null;
477
+ }
478
+ if (!encrypted) {
479
+ // For performance reasons, we do not validate that the state is JSON,
480
+ // since we control serialization.
481
+ const json = JSON.parse(state);
482
+ runtime.unencryptedState = json;
483
+ return json;
484
+ }
485
+ const decrypted = await __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_decryptSnapState).call(this, snapId, state);
486
+ // eslint-disable-next-line require-atomic-updates
487
+ runtime.state = decrypted;
488
+ return decrypted;
489
+ });
466
490
  }
467
491
  /**
468
492
  * Gets a static auxiliary snap file in a chosen file encoding.
@@ -997,6 +1021,7 @@ class SnapController extends base_controller_1.BaseController {
997
1021
  */
998
1022
  async handleRequest({ snapId, origin, handler: handlerType, request: rawRequest, }) {
999
1023
  __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_assertCanUsePlatform).call(this);
1024
+ (0, utils_1.assert)(origin === 'metamask' || (0, snaps_utils_1.isValidUrl)(origin), "'origin' must be a valid URL or 'metamask'.");
1000
1025
  const request = {
1001
1026
  jsonrpc: '2.0',
1002
1027
  id: (0, nanoid_1.nanoid)(),
@@ -1035,7 +1060,7 @@ class SnapController extends base_controller_1.BaseController {
1035
1060
  }
1036
1061
  }
1037
1062
  exports.SnapController = SnapController;
1038
- _SnapController_closeAllConnections = new WeakMap(), _SnapController_dynamicPermissions = new WeakMap(), _SnapController_environmentEndowmentPermissions = new WeakMap(), _SnapController_excludedPermissions = new WeakMap(), _SnapController_featureFlags = new WeakMap(), _SnapController_fetchFunction = new WeakMap(), _SnapController_idleTimeCheckInterval = new WeakMap(), _SnapController_maxIdleTime = new WeakMap(), _SnapController_encryptor = new WeakMap(), _SnapController_getMnemonicSeed = new WeakMap(), _SnapController_getFeatureFlags = new WeakMap(), _SnapController_clientCryptography = new WeakMap(), _SnapController_detectSnapLocation = new WeakMap(), _SnapController_snapsRuntimeData = new WeakMap(), _SnapController_rollbackSnapshots = new WeakMap(), _SnapController_timeoutForLastRequestStatus = new WeakMap(), _SnapController_statusMachine = new WeakMap(), _SnapController_preinstalledSnaps = new WeakMap(), _SnapController_instances = new WeakSet(), _SnapController_initializeStateMachine = function _SnapController_initializeStateMachine() {
1063
+ _SnapController_closeAllConnections = new WeakMap(), _SnapController_dynamicPermissions = new WeakMap(), _SnapController_environmentEndowmentPermissions = new WeakMap(), _SnapController_excludedPermissions = new WeakMap(), _SnapController_featureFlags = new WeakMap(), _SnapController_fetchFunction = new WeakMap(), _SnapController_idleTimeCheckInterval = new WeakMap(), _SnapController_maxIdleTime = new WeakMap(), _SnapController_encryptor = new WeakMap(), _SnapController_getMnemonicSeed = new WeakMap(), _SnapController_getFeatureFlags = new WeakMap(), _SnapController_clientCryptography = new WeakMap(), _SnapController_detectSnapLocation = new WeakMap(), _SnapController_snapsRuntimeData = new WeakMap(), _SnapController_rollbackSnapshots = new WeakMap(), _SnapController_timeoutForLastRequestStatus = new WeakMap(), _SnapController_statusMachine = new WeakMap(), _SnapController_preinstalledSnaps = new WeakMap(), _SnapController_persistSnapState = new WeakMap(), _SnapController_instances = new WeakSet(), _SnapController_initializeStateMachine = function _SnapController_initializeStateMachine() {
1039
1064
  const disableGuard = ({ snapId }) => {
1040
1065
  return this.getExpect(snapId).enabled;
1041
1066
  };
@@ -1268,6 +1293,8 @@ async function _SnapController_terminateSnap(snapId) {
1268
1293
  // Hack to give up execution for a bit to let timed out requests return.
1269
1294
  await new Promise((resolve) => setTimeout(resolve, 1));
1270
1295
  this.messagingSystem.publish('SnapController:snapTerminated', this.getTruncatedExpect(snapId));
1296
+ }, _SnapController_hasCachedEncryptionKey = function _SnapController_hasCachedEncryptionKey(snapId, runtime = __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_getRuntimeExpect).call(this, snapId)) {
1297
+ return runtime.encryptionKey !== null && runtime.encryptionSalt !== null;
1271
1298
  }, _SnapController_getSnapEncryptionKey =
1272
1299
  /**
1273
1300
  * Generate an encryption key to be used for state encryption for a given Snap.
@@ -1281,7 +1308,7 @@ async function _SnapController_terminateSnap(snapId) {
1281
1308
  */
1282
1309
  async function _SnapController_getSnapEncryptionKey({ snapId, salt: passedSalt, useCache, keyMetadata, }) {
1283
1310
  const runtime = __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_getRuntimeExpect).call(this, snapId);
1284
- if (runtime.encryptionKey && runtime.encryptionSalt && useCache) {
1311
+ if (__classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_hasCachedEncryptionKey).call(this, snapId, runtime) && useCache) {
1285
1312
  return {
1286
1313
  key: await __classPrivateFieldGet(this, _SnapController_encryptor, "f").importKey(runtime.encryptionKey),
1287
1314
  salt: runtime.encryptionSalt,
@@ -1302,9 +1329,6 @@ async function _SnapController_getSnapEncryptionKey({ snapId, salt: passedSalt,
1302
1329
  runtime.encryptionSalt = salt;
1303
1330
  }
1304
1331
  return { key: encryptionKey, salt };
1305
- }, _SnapController_hasCachedEncryptionKey = function _SnapController_hasCachedEncryptionKey(snapId) {
1306
- const runtime = __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_getRuntimeExpect).call(this, snapId);
1307
- return runtime.encryptionKey !== null && runtime.encryptionSalt !== null;
1308
1332
  }, _SnapController_decryptSnapState =
1309
1333
  /**
1310
1334
  * Decrypt the encrypted state for a given Snap.
@@ -1383,31 +1407,6 @@ async function _SnapController_getStateToPersist(snapId, state, encrypted) {
1383
1407
  return await __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_encryptSnapState).call(this, snapId, state);
1384
1408
  }
1385
1409
  return JSON.stringify(state);
1386
- }, _SnapController_persistSnapState =
1387
- /**
1388
- * Persist the state of a Snap.
1389
- *
1390
- * This is run with a mutex to ensure that only one state update per Snap is
1391
- * processed at a time, avoiding possible race conditions.
1392
- *
1393
- * @param snapId - The Snap ID.
1394
- * @param newSnapState - The new state of the Snap.
1395
- * @param encrypted - A flag to indicate whether to use encrypted storage or
1396
- * not.
1397
- */
1398
- async function _SnapController_persistSnapState(snapId, newSnapState, encrypted) {
1399
- const runtime = __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_getRuntimeExpect).call(this, snapId);
1400
- await runtime.stateMutex.runExclusive(async () => {
1401
- const newState = await __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_getStateToPersist).call(this, snapId, newSnapState, encrypted);
1402
- if (encrypted) {
1403
- return this.update((state) => {
1404
- state.snapStates[snapId] = newState;
1405
- });
1406
- }
1407
- return this.update((state) => {
1408
- state.unencryptedSnapStates[snapId] = newState;
1409
- });
1410
- });
1411
1410
  }, _SnapController_handleInitialConnections = function _SnapController_handleInitialConnections(snapId, previousInitialConnections, initialConnections) {
1412
1411
  if (previousInitialConnections) {
1413
1412
  const revokedInitialConnections = (0, utils_2.setDiff)(previousInitialConnections, initialConnections);
@@ -1723,23 +1722,24 @@ async function _SnapController_getEndowments(snapId) {
1723
1722
  }
1724
1723
  }
1725
1724
  }
1725
+ const transformedRequest = __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_transformSnapRpcRequest).call(this, snapId, handlerType, request);
1726
1726
  const timer = new Timer_1.Timer(timeout);
1727
- __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_recordSnapRpcRequestStart).call(this, snapId, request.id, timer);
1728
- const handleRpcRequestPromise = this.messagingSystem.call('ExecutionService:handleRpcRequest', snapId, { origin, handler: handlerType, request });
1727
+ __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_recordSnapRpcRequestStart).call(this, snapId, transformedRequest.id, timer);
1728
+ const handleRpcRequestPromise = this.messagingSystem.call('ExecutionService:handleRpcRequest', snapId, { origin, handler: handlerType, request: transformedRequest });
1729
1729
  // This will either get the result or reject due to the timeout.
1730
1730
  try {
1731
1731
  const result = await (0, utils_2.withTimeout)(handleRpcRequestPromise, timer);
1732
1732
  if (result === utils_2.hasTimedOut) {
1733
1733
  throw new Error(`${snapId} failed to respond to the request in time.`);
1734
1734
  }
1735
- await __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_assertSnapRpcRequestResult).call(this, snapId, handlerType, result);
1736
- const transformedResult = await __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_transformSnapRpcRequestResult).call(this, snapId, handlerType, request, result);
1737
- __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_recordSnapRpcRequestFinish).call(this, snapId, request.id);
1735
+ await __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_assertSnapRpcResponse).call(this, snapId, handlerType, result);
1736
+ const transformedResult = await __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_transformSnapRpcResponse).call(this, snapId, handlerType, transformedRequest, result);
1737
+ __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_recordSnapRpcRequestFinish).call(this, snapId, transformedRequest.id);
1738
1738
  return transformedResult;
1739
1739
  }
1740
1740
  catch (error) {
1741
1741
  // We flag the RPC request as finished early since termination may affect pending requests
1742
- __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_recordSnapRpcRequestFinish).call(this, snapId, request.id);
1742
+ __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_recordSnapRpcRequestFinish).call(this, snapId, transformedRequest.id);
1743
1743
  const [jsonRpcError, handled] = (0, snaps_utils_1.unwrapError)(error);
1744
1744
  if (!handled) {
1745
1745
  await this.stopSnap(snapId, snaps_utils_1.SnapStatusEvents.Crash);
@@ -1763,17 +1763,17 @@ async function _SnapController_createInterface(snapId, content, contentType) {
1763
1763
  }, _SnapController_assertInterfaceExists = function _SnapController_assertInterfaceExists(snapId, id) {
1764
1764
  // This will throw if the interface isn't accessible, but we assert nevertheless.
1765
1765
  (0, utils_1.assert)(this.messagingSystem.call('SnapInterfaceController:getInterface', snapId, id));
1766
- }, _SnapController_transformSnapRpcRequestResult =
1766
+ }, _SnapController_transformSnapRpcResponse =
1767
1767
  /**
1768
- * Transform a RPC request result if necessary.
1768
+ * Transform a RPC response if necessary.
1769
1769
  *
1770
1770
  * @param snapId - The snap ID of the snap that produced the result.
1771
1771
  * @param handlerType - The handler type that produced the result.
1772
1772
  * @param request - The request that returned the result.
1773
- * @param result - The result.
1773
+ * @param result - The response.
1774
1774
  * @returns The transformed result if applicable, otherwise the original result.
1775
1775
  */
1776
- async function _SnapController_transformSnapRpcRequestResult(snapId, handlerType, request, result) {
1776
+ async function _SnapController_transformSnapRpcResponse(snapId, handlerType, request, result) {
1777
1777
  switch (handlerType) {
1778
1778
  case snaps_utils_1.HandlerType.OnTransaction:
1779
1779
  case snaps_utils_1.HandlerType.OnSignature:
@@ -1830,7 +1830,22 @@ async function _SnapController_transformSnapRpcRequestResult(snapId, handlerType
1830
1830
  return accumulator;
1831
1831
  }, {});
1832
1832
  return { conversionRates: filteredConversionRates };
1833
- }, _SnapController_assertSnapRpcRequestResult =
1833
+ }, _SnapController_transformSnapRpcRequest = function _SnapController_transformSnapRpcRequest(snapId, handlerType, request) {
1834
+ switch (handlerType) {
1835
+ // For onUserInput we inject context, so the client doesn't have to worry about keeping it in sync.
1836
+ case snaps_utils_1.HandlerType.OnUserInput: {
1837
+ (0, utils_1.assert)(request.params && (0, utils_1.hasProperty)(request.params, 'id'));
1838
+ const interfaceId = request.params.id;
1839
+ const { context } = this.messagingSystem.call('SnapInterfaceController:getInterface', snapId, interfaceId);
1840
+ return {
1841
+ ...request,
1842
+ params: { ...request.params, context },
1843
+ };
1844
+ }
1845
+ default:
1846
+ return request;
1847
+ }
1848
+ }, _SnapController_assertSnapRpcResponse =
1834
1849
  /**
1835
1850
  * Assert that the returned result of a Snap RPC call is the expected shape.
1836
1851
  *
@@ -1838,7 +1853,7 @@ async function _SnapController_transformSnapRpcRequestResult(snapId, handlerType
1838
1853
  * @param handlerType - The handler type of the RPC Request.
1839
1854
  * @param result - The result of the RPC request.
1840
1855
  */
1841
- async function _SnapController_assertSnapRpcRequestResult(snapId, handlerType, result) {
1856
+ async function _SnapController_assertSnapRpcResponse(snapId, handlerType, result) {
1842
1857
  switch (handlerType) {
1843
1858
  case snaps_utils_1.HandlerType.OnTransaction: {
1844
1859
  (0, utils_1.assertStruct)(result, snaps_utils_1.OnTransactionResponseStruct);
@@ -1875,7 +1890,10 @@ async function _SnapController_assertSnapRpcRequestResult(snapId, handlerType, r
1875
1890
  (0, utils_1.assertStruct)(result, snaps_sdk_1.OnAssetsLookupResponseStruct);
1876
1891
  break;
1877
1892
  case snaps_utils_1.HandlerType.OnAssetsConversion:
1878
- (0, utils_1.assertStruct)(result, snaps_sdk_1.OnAssetsConversionResponseStruct);
1893
+ (0, utils_1.assertStruct)(result, snaps_utils_1.OnAssetsConversionResponseStruct);
1894
+ break;
1895
+ case snaps_utils_1.HandlerType.OnAssetHistoricalPrice:
1896
+ (0, utils_1.assertStruct)(result, snaps_utils_1.OnAssetHistoricalPriceResponseStruct);
1879
1897
  break;
1880
1898
  default:
1881
1899
  break;
@@ -1985,6 +2003,7 @@ async function _SnapController_rollbackSnaps(snapIds) {
1985
2003
  interpreter,
1986
2004
  stopping: false,
1987
2005
  stateMutex: new async_mutex_1.Mutex(),
2006
+ getStateMutex: new async_mutex_1.Mutex(),
1988
2007
  });
1989
2008
  }, _SnapController_calculatePermissionsChange = function _SnapController_calculatePermissionsChange(snapId, desiredPermissionsSet) {
1990
2009
  const oldPermissions = this.messagingSystem.call('PermissionController:getPermissions', snapId) ?? {};