@metamask/snaps-controllers 8.1.1 → 8.3.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 (119) hide show
  1. package/CHANGELOG.md +19 -1
  2. package/dist/{chunk-TO6ZEBIA.mjs → chunk-3A72M4GC.mjs} +2 -2
  3. package/dist/{chunk-ZVGZG25U.js → chunk-3AANDIXT.js} +3 -3
  4. package/dist/{chunk-X5MFC3VX.mjs → chunk-3OJFF5CK.mjs} +2 -2
  5. package/dist/{chunk-GTDDODNP.mjs → chunk-567BFPSL.mjs} +9 -2
  6. package/dist/chunk-567BFPSL.mjs.map +1 -0
  7. package/dist/{chunk-RS3WN6D3.mjs → chunk-7IJQGFT5.mjs} +2 -2
  8. package/dist/{chunk-U4DZUKNN.js → chunk-7TYZZFHZ.js} +16 -3
  9. package/dist/chunk-7TYZZFHZ.js.map +1 -0
  10. package/dist/{chunk-4DPX4O3T.js → chunk-CDTGUNSA.js} +9 -2
  11. package/dist/chunk-CDTGUNSA.js.map +1 -0
  12. package/dist/{chunk-74GN6MIJ.js → chunk-FPGAQ6MT.js} +3 -3
  13. package/dist/{chunk-Y7ZOSPEN.js → chunk-HK4OAMJT.js} +3 -3
  14. package/dist/{chunk-E5RRFMGF.js → chunk-HQ6HMINL.js} +3 -3
  15. package/dist/{chunk-WMT2TIOI.mjs → chunk-JCQR3I2Q.mjs} +64 -24
  16. package/dist/chunk-JCQR3I2Q.mjs.map +1 -0
  17. package/dist/{chunk-FCRPOA4I.js → chunk-KH72WRHR.js} +3 -3
  18. package/dist/{chunk-QLEQIXCE.mjs → chunk-LRVK45HN.mjs} +2 -2
  19. package/dist/{chunk-A6RUJL4K.js → chunk-NRZEYYBQ.js} +72 -32
  20. package/dist/chunk-NRZEYYBQ.js.map +1 -0
  21. package/dist/{chunk-2UAU42DO.js → chunk-PIQFC66N.js} +12 -8
  22. package/dist/chunk-PIQFC66N.js.map +1 -0
  23. package/dist/{chunk-PXKCSAT6.mjs → chunk-PMZXFAQI.mjs} +2 -2
  24. package/dist/{chunk-FCCGRGQS.mjs → chunk-QLFH3MC6.mjs} +2 -2
  25. package/dist/{chunk-QP5LV734.mjs → chunk-QLWR3M4Q.mjs} +9 -5
  26. package/dist/chunk-QLWR3M4Q.mjs.map +1 -0
  27. package/dist/{chunk-G4S6UXQ2.js → chunk-RW7AYHRG.js} +3 -3
  28. package/dist/{chunk-SIW7ZXQF.js → chunk-S775IABY.js} +10 -10
  29. package/dist/{chunk-P5MRZOGW.mjs → chunk-SAAURQ5A.mjs} +2 -2
  30. package/dist/{chunk-ZQNBP53T.mjs → chunk-UJJCRV7W.mjs} +16 -3
  31. package/dist/chunk-UJJCRV7W.mjs.map +1 -0
  32. package/dist/{chunk-3Y4IJKZY.mjs → chunk-YUWYMNIX.mjs} +2 -2
  33. package/dist/{chunk-PAFO2KIN.js → chunk-ZRC46TUF.js} +3 -3
  34. package/dist/cronjob/CronjobController.js +9 -9
  35. package/dist/cronjob/CronjobController.mjs +9 -9
  36. package/dist/cronjob/index.js +9 -9
  37. package/dist/cronjob/index.mjs +9 -9
  38. package/dist/index.js +12 -10
  39. package/dist/index.mjs +11 -9
  40. package/dist/interface/SnapInterfaceController.js +3 -3
  41. package/dist/interface/SnapInterfaceController.mjs +2 -2
  42. package/dist/interface/index.js +3 -3
  43. package/dist/interface/index.mjs +2 -2
  44. package/dist/interface/utils.js +4 -2
  45. package/dist/interface/utils.mjs +5 -3
  46. package/dist/node.js +14 -12
  47. package/dist/node.mjs +13 -11
  48. package/dist/react-native.js +13 -11
  49. package/dist/react-native.mjs +12 -10
  50. package/dist/services/AbstractExecutionService.js +3 -3
  51. package/dist/services/AbstractExecutionService.mjs +2 -2
  52. package/dist/services/browser.js +8 -8
  53. package/dist/services/browser.mjs +7 -7
  54. package/dist/services/iframe/IframeExecutionService.js +4 -4
  55. package/dist/services/iframe/IframeExecutionService.mjs +3 -3
  56. package/dist/services/iframe/index.js +4 -4
  57. package/dist/services/iframe/index.mjs +3 -3
  58. package/dist/services/index.js +7 -7
  59. package/dist/services/index.mjs +6 -6
  60. package/dist/services/node-js/NodeProcessExecutionService.js +8 -8
  61. package/dist/services/node-js/NodeProcessExecutionService.mjs +7 -7
  62. package/dist/services/node-js/NodeThreadExecutionService.js +8 -8
  63. package/dist/services/node-js/NodeThreadExecutionService.mjs +7 -7
  64. package/dist/services/node-js/index.js +9 -9
  65. package/dist/services/node-js/index.mjs +8 -8
  66. package/dist/services/node.js +9 -9
  67. package/dist/services/node.mjs +8 -8
  68. package/dist/services/offscreen/OffscreenExecutionService.js +5 -5
  69. package/dist/services/offscreen/OffscreenExecutionService.mjs +4 -4
  70. package/dist/services/offscreen/index.js +5 -5
  71. package/dist/services/offscreen/index.mjs +4 -4
  72. package/dist/services/proxy/ProxyExecutionService.js +4 -4
  73. package/dist/services/proxy/ProxyExecutionService.mjs +3 -3
  74. package/dist/services/react-native.js +8 -8
  75. package/dist/services/react-native.mjs +7 -7
  76. package/dist/services/webview/WebViewExecutionService.js +5 -5
  77. package/dist/services/webview/WebViewExecutionService.mjs +4 -4
  78. package/dist/services/webview/index.js +5 -5
  79. package/dist/services/webview/index.mjs +4 -4
  80. package/dist/services/webworker/WebWorkerExecutionService.js +4 -4
  81. package/dist/services/webworker/WebWorkerExecutionService.mjs +3 -3
  82. package/dist/services/webworker/index.js +4 -4
  83. package/dist/services/webworker/index.mjs +3 -3
  84. package/dist/snaps/SnapController.js +3 -3
  85. package/dist/snaps/SnapController.mjs +2 -2
  86. package/dist/snaps/index.js +3 -3
  87. package/dist/snaps/index.mjs +2 -2
  88. package/dist/tsconfig.build.tsbuildinfo +1 -1
  89. package/dist/types/interface/SnapInterfaceController.d.ts +4 -2
  90. package/dist/types/interface/utils.d.ts +8 -1
  91. package/dist/types/snaps/SnapController.d.ts +10 -1
  92. package/dist/types/utils.d.ts +13 -0
  93. package/dist/utils.js +4 -2
  94. package/dist/utils.mjs +3 -1
  95. package/package.json +7 -7
  96. package/dist/chunk-2UAU42DO.js.map +0 -1
  97. package/dist/chunk-4DPX4O3T.js.map +0 -1
  98. package/dist/chunk-A6RUJL4K.js.map +0 -1
  99. package/dist/chunk-GTDDODNP.mjs.map +0 -1
  100. package/dist/chunk-QP5LV734.mjs.map +0 -1
  101. package/dist/chunk-U4DZUKNN.js.map +0 -1
  102. package/dist/chunk-WMT2TIOI.mjs.map +0 -1
  103. package/dist/chunk-ZQNBP53T.mjs.map +0 -1
  104. /package/dist/{chunk-TO6ZEBIA.mjs.map → chunk-3A72M4GC.mjs.map} +0 -0
  105. /package/dist/{chunk-ZVGZG25U.js.map → chunk-3AANDIXT.js.map} +0 -0
  106. /package/dist/{chunk-X5MFC3VX.mjs.map → chunk-3OJFF5CK.mjs.map} +0 -0
  107. /package/dist/{chunk-RS3WN6D3.mjs.map → chunk-7IJQGFT5.mjs.map} +0 -0
  108. /package/dist/{chunk-74GN6MIJ.js.map → chunk-FPGAQ6MT.js.map} +0 -0
  109. /package/dist/{chunk-Y7ZOSPEN.js.map → chunk-HK4OAMJT.js.map} +0 -0
  110. /package/dist/{chunk-E5RRFMGF.js.map → chunk-HQ6HMINL.js.map} +0 -0
  111. /package/dist/{chunk-FCRPOA4I.js.map → chunk-KH72WRHR.js.map} +0 -0
  112. /package/dist/{chunk-QLEQIXCE.mjs.map → chunk-LRVK45HN.mjs.map} +0 -0
  113. /package/dist/{chunk-PXKCSAT6.mjs.map → chunk-PMZXFAQI.mjs.map} +0 -0
  114. /package/dist/{chunk-FCCGRGQS.mjs.map → chunk-QLFH3MC6.mjs.map} +0 -0
  115. /package/dist/{chunk-G4S6UXQ2.js.map → chunk-RW7AYHRG.js.map} +0 -0
  116. /package/dist/{chunk-SIW7ZXQF.js.map → chunk-S775IABY.js.map} +0 -0
  117. /package/dist/{chunk-P5MRZOGW.mjs.map → chunk-SAAURQ5A.mjs.map} +0 -0
  118. /package/dist/{chunk-3Y4IJKZY.mjs.map → chunk-YUWYMNIX.mjs.map} +0 -0
  119. /package/dist/{chunk-PAFO2KIN.js.map → chunk-ZRC46TUF.js.map} +0 -0
package/CHANGELOG.md CHANGED
@@ -6,6 +6,22 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [8.3.0]
10
+ ### Added
11
+ - Add origin to lifecycle hooks ([#2441](https://github.com/MetaMask/snaps/pull/2441))
12
+ - Lifecycle hooks can now use the `origin` parameter to determine the origin
13
+ of the installation or update.
14
+
15
+ ## [8.2.0]
16
+ ### Added
17
+ - Add `context` field to `snap_createInterface` ([#2413](https://github.com/MetaMask/snaps/pull/2413))
18
+ - Add feature flag to disable platform ([#2434](https://github.com/MetaMask/snaps/pull/2434))
19
+ - Add support for `Dropdown` component ([#2420](https://github.com/MetaMask/snaps/pull/2420))
20
+ - Add `initialConnections` diff calculations needed for Snap update ([#2424](https://github.com/MetaMask/snaps/pull/2424))
21
+
22
+ ### Fixed
23
+ - Correctly merge caveats when using initial connections ([#2419](https://github.com/MetaMask/snaps/pull/2419))
24
+
9
25
  ## [8.1.1]
10
26
  ### Fixed
11
27
  - Re-instantiate preinstalled Snaps after clearing state ([#2393](https://github.com/MetaMask/snaps/pull/2393))
@@ -261,7 +277,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
261
277
  - The version of the package no longer needs to match the version of all other
262
278
  MetaMask Snaps packages.
263
279
 
264
- [Unreleased]: https://github.com/MetaMask/snaps/compare/@metamask/snaps-controllers@8.1.1...HEAD
280
+ [Unreleased]: https://github.com/MetaMask/snaps/compare/@metamask/snaps-controllers@8.3.0...HEAD
281
+ [8.3.0]: https://github.com/MetaMask/snaps/compare/@metamask/snaps-controllers@8.2.0...@metamask/snaps-controllers@8.3.0
282
+ [8.2.0]: https://github.com/MetaMask/snaps/compare/@metamask/snaps-controllers@8.1.1...@metamask/snaps-controllers@8.2.0
265
283
  [8.1.1]: https://github.com/MetaMask/snaps/compare/@metamask/snaps-controllers@8.1.0...@metamask/snaps-controllers@8.1.1
266
284
  [8.1.0]: https://github.com/MetaMask/snaps/compare/@metamask/snaps-controllers@8.0.0...@metamask/snaps-controllers@8.1.0
267
285
  [8.0.0]: https://github.com/MetaMask/snaps/compare/@metamask/snaps-controllers@7.0.1...@metamask/snaps-controllers@8.0.0
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  AbstractExecutionService
3
- } from "./chunk-FCCGRGQS.mjs";
3
+ } from "./chunk-QLFH3MC6.mjs";
4
4
  import {
5
5
  ProxyPostMessageStream
6
6
  } from "./chunk-ZVOYOZFT.mjs";
@@ -79,4 +79,4 @@ _stream = new WeakMap();
79
79
  export {
80
80
  ProxyExecutionService
81
81
  };
82
- //# sourceMappingURL=chunk-TO6ZEBIA.mjs.map
82
+ //# sourceMappingURL=chunk-3A72M4GC.mjs.map
@@ -1,6 +1,6 @@
1
1
  "use strict";Object.defineProperty(exports, "__esModule", {value: true});
2
2
 
3
- var _chunkSIW7ZXQFjs = require('./chunk-SIW7ZXQF.js');
3
+ var _chunkS775IABYjs = require('./chunk-S775IABY.js');
4
4
 
5
5
 
6
6
  var _chunkEXN2TFDJjs = require('./chunk-EXN2TFDJ.js');
@@ -8,7 +8,7 @@ var _chunkEXN2TFDJjs = require('./chunk-EXN2TFDJ.js');
8
8
  // src/services/node-js/NodeProcessExecutionService.ts
9
9
  var _postmessagestream = require('@metamask/post-message-stream');
10
10
  var _child_process = require('child_process');
11
- var NodeProcessExecutionService = class extends _chunkSIW7ZXQFjs.AbstractExecutionService {
11
+ var NodeProcessExecutionService = class extends _chunkS775IABYjs.AbstractExecutionService {
12
12
  async initEnvStream() {
13
13
  const worker = _child_process.fork.call(void 0,
14
14
  _chunkEXN2TFDJjs.__require.resolve(
@@ -35,4 +35,4 @@ var NodeProcessExecutionService = class extends _chunkSIW7ZXQFjs.AbstractExecuti
35
35
 
36
36
 
37
37
  exports.NodeProcessExecutionService = NodeProcessExecutionService;
38
- //# sourceMappingURL=chunk-ZVGZG25U.js.map
38
+ //# sourceMappingURL=chunk-3AANDIXT.js.map
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  ProxyExecutionService
3
- } from "./chunk-TO6ZEBIA.mjs";
3
+ } from "./chunk-3A72M4GC.mjs";
4
4
  import {
5
5
  __privateAdd,
6
6
  __privateMethod
@@ -69,4 +69,4 @@ createDocument_fn = async function() {
69
69
  export {
70
70
  OffscreenExecutionService
71
71
  };
72
- //# sourceMappingURL=chunk-X5MFC3VX.mjs.map
72
+ //# sourceMappingURL=chunk-3OJFF5CK.mjs.map
@@ -106,6 +106,12 @@ async function fetchSnap(snapId, location) {
106
106
  );
107
107
  }
108
108
  }
109
+ function calculateConnectionsChange(oldConnectionsSet, desiredConnectionsSet) {
110
+ const newConnections = setDiff(desiredConnectionsSet, oldConnectionsSet);
111
+ const unusedConnections = setDiff(oldConnectionsSet, desiredConnectionsSet);
112
+ const approvedConnections = setDiff(oldConnectionsSet, unusedConnections);
113
+ return { newConnections, unusedConnections, approvedConnections };
114
+ }
109
115
 
110
116
  export {
111
117
  setDiff,
@@ -115,6 +121,7 @@ export {
115
121
  hasTimedOut,
116
122
  withTimeout,
117
123
  getSnapFiles,
118
- fetchSnap
124
+ fetchSnap,
125
+ calculateConnectionsChange
119
126
  };
120
- //# sourceMappingURL=chunk-GTDDODNP.mjs.map
127
+ //# sourceMappingURL=chunk-567BFPSL.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/utils.ts"],"sourcesContent":["import type { PermissionConstraint } from '@metamask/permission-controller';\nimport type { SnapId } from '@metamask/snaps-sdk';\nimport { getErrorMessage } from '@metamask/snaps-sdk';\nimport {\n encodeBase64,\n getValidatedLocalizationFiles,\n validateFetchedSnap,\n} from '@metamask/snaps-utils';\nimport type { Json } from '@metamask/utils';\nimport deepEqual from 'fast-deep-equal';\n\nimport type { SnapLocation } from './snaps';\nimport { Timer } from './snaps/Timer';\n\n/**\n * Takes two objects and does a Set Difference of them.\n * Set Difference is generally defined as follows:\n * ```\n * 𝑥 ∈ A ∖ B ⟺ 𝑥 ∈ A ∧ 𝑥 ∉ B\n * ```\n * Meaning that the returned object contains all properties of A expect those that also\n * appear in B. Notice that properties that appear in B, but not in A, have no effect.\n *\n * @see [Set Difference]{@link https://proofwiki.org/wiki/Definition:Set_Difference}\n * @param objectA - The object on which the difference is being calculated.\n * @param objectB - The object whose properties will be removed from objectA.\n * @returns The objectA without properties from objectB.\n */\nexport function setDiff<\n ObjectA extends Record<any, unknown>,\n ObjectB extends Record<any, unknown>,\n>(objectA: ObjectA, objectB: ObjectB): Diff<ObjectA, ObjectB> {\n return Object.entries(objectA).reduce<Record<any, unknown>>(\n (acc, [key, value]) => {\n if (!(key in objectB)) {\n acc[key] = value;\n }\n return acc;\n },\n {},\n ) as Diff<ObjectA, ObjectB>;\n}\n\n/**\n * Calculate a difference between two permissions objects.\n *\n * Similar to `setDiff` except for one additional condition:\n * Permissions in B should be removed from A if they exist in both and have differing caveats.\n *\n * @param permissionsA - An object containing one or more partial permissions.\n * @param permissionsB - An object containing one or more partial permissions to be subtracted from A.\n * @returns The permissions set A without properties from B.\n */\nexport function permissionsDiff<\n PermissionsA extends Record<string, Pick<PermissionConstraint, 'caveats'>>,\n PermissionsB extends Record<string, Pick<PermissionConstraint, 'caveats'>>,\n>(\n permissionsA: PermissionsA,\n permissionsB: PermissionsB,\n): Diff<PermissionsA, PermissionsB> {\n return Object.entries(permissionsA).reduce<\n Record<string, Pick<PermissionConstraint, 'caveats'>>\n >((acc, [key, value]) => {\n const isIncluded = key in permissionsB;\n if (\n !isIncluded ||\n (isIncluded &&\n !deepEqual(value.caveats ?? [], permissionsB[key].caveats ?? []))\n ) {\n acc[key] = value;\n }\n return acc;\n }, {}) as Diff<PermissionsA, PermissionsB>;\n}\n\n/**\n * A Promise that delays its return for a given amount of milliseconds.\n *\n * @param ms - Milliseconds to delay the execution for.\n * @param result - The result to return from the Promise after delay.\n * @returns A promise that is void if no result provided, result otherwise.\n * @template Result - The `result`.\n */\nexport function delay<Result = void>(\n ms: number,\n result?: Result,\n): Promise<Result> & { cancel: () => void } {\n return delayWithTimer(new Timer(ms), result);\n}\n\n/**\n * A Promise that delays it's return by using a pausable Timer.\n *\n * @param timer - Timer used to control the delay.\n * @param result - The result to return from the Promise after delay.\n * @returns A promise that is void if no result provided, result otherwise.\n * @template Result - The `result`.\n */\nexport function delayWithTimer<Result = void>(\n timer: Timer,\n result?: Result,\n): Promise<Result> & { cancel: () => void } {\n let rejectFunc: (reason: Error) => void;\n const promise: any = new Promise<Result>((resolve: any, reject) => {\n timer.start(() => {\n result === undefined ? resolve() : resolve(result);\n });\n rejectFunc = reject;\n });\n\n promise.cancel = () => {\n if (timer.status !== 'finished') {\n timer.cancel();\n rejectFunc(new Error('The delay has been canceled.'));\n }\n };\n return promise;\n}\n\n/*\n * We use a Symbol instead of rejecting the promise so that Errors thrown\n * by the main promise will propagate.\n */\nexport const hasTimedOut = Symbol(\n 'Used to check if the requested promise has timeout (see withTimeout)',\n);\n\n/**\n * Executes the given Promise, if the Timer expires before the Promise settles, we return earlier.\n *\n * NOTE:** The given Promise is not cancelled or interrupted, and will continue to execute uninterrupted. We will just discard its result if it does not complete before the timeout.\n *\n * @param promise - The promise that you want to execute.\n * @param timerOrMs - The timer controlling the timeout or a ms value.\n * @returns The resolved `PromiseValue`, or the hasTimedOut symbol if\n * returning early.\n * @template PromiseValue - The value of the Promise.\n */\nexport async function withTimeout<PromiseValue = void>(\n promise: Promise<PromiseValue>,\n timerOrMs: Timer | number,\n): Promise<PromiseValue | typeof hasTimedOut> {\n const timer =\n typeof timerOrMs === 'number' ? new Timer(timerOrMs) : timerOrMs;\n const delayPromise = delayWithTimer(timer, hasTimedOut);\n try {\n return await Promise.race([promise, delayPromise]);\n } finally {\n delayPromise.cancel();\n }\n}\n\n/**\n * Checks whether the type is composed of literal types\n *\n * @returns @type {true} if whole type is composed of literals, @type {false} if whole type is not literals, @type {boolean} if mixed\n * @example\n * ```\n * type t1 = IsLiteral<1 | 2 | \"asd\" | true>;\n * // t1 = true\n *\n * type t2 = IsLiteral<number | string>;\n * // t2 = false\n *\n * type t3 = IsLiteral<1 | string>;\n * // t3 = boolean\n *\n * const s = Symbol();\n * type t4 = IsLiteral<typeof s>;\n * // t4 = true\n *\n * type t5 = IsLiteral<symbol>\n * // t5 = false;\n * ```\n */\ntype IsLiteral<Type> = Type extends string | number | boolean | symbol\n ? Extract<string | number | boolean | symbol, Type> extends never\n ? true\n : false\n : false;\n\n/**\n * Returns all keys of an object, that are literal, as an union\n *\n * @example\n * ```\n * type t1 = _LiteralKeys<{a: number, b: 0, c: 'foo', d: string}>\n * // t1 = 'b' | 'c'\n * ```\n * @see [Literal types]{@link https://www.typescriptlang.org/docs/handbook/literal-types.html}\n */\ntype LiteralKeys<Type> = NonNullable<\n {\n [Key in keyof Type]: IsLiteral<Key> extends true ? Key : never;\n }[keyof Type]\n>;\n\n/**\n * Returns all keys of an object, that are not literal, as an union\n *\n * @example\n * ```\n * type t1 = _NonLiteralKeys<{a: number, b: 0, c: 'foo', d: string}>\n * // t1 = 'a' | 'd'\n * ```\n * @see [Literal types]{@link https://www.typescriptlang.org/docs/handbook/literal-types.html}\n */\ntype NonLiteralKeys<Type> = NonNullable<\n {\n [Key in keyof Type]: IsLiteral<Key> extends false ? Key : never;\n }[keyof Type]\n>;\n\n/**\n * A set difference of two objects based on their keys\n *\n * @example\n * ```\n * type t1 = Diff<{a: string, b: string}, {a: number}>\n * // t1 = {b: string};\n * type t2 = Diff<{a: string, 0: string}, Record<string, unknown>>;\n * // t2 = { a?: string, 0: string};\n * type t3 = Diff<{a: string, 0: string, 1: string}, Record<1 | string, unknown>>;\n * // t3 = {a?: string, 0: string}\n * ```\n * @see {@link setDiff} for the main use-case\n */\nexport type Diff<First, Second> = Omit<First, LiteralKeys<Second>> &\n Partial<Pick<First, Extract<keyof First, NonLiteralKeys<Second>>>>;\n\n/**\n * Makes every specified property of the specified object type mutable.\n *\n * @template Type - The object whose readonly properties to make mutable.\n * @template TargetKey - The property key(s) to make mutable.\n */\nexport type Mutable<\n Type extends Record<string, unknown>,\n TargetKey extends string,\n> = {\n -readonly [Key in keyof Pick<Type, TargetKey>]: Type[Key];\n} & {\n [Key in keyof Omit<Type, TargetKey>]: Type[Key];\n};\n\n/**\n * Get all files in a Snap from an array of file paths.\n *\n * @param location - The location of the Snap.\n * @param files - The array of file paths.\n * @returns The array of files as {@link VirtualFile}s.\n */\nexport async function getSnapFiles(\n location: SnapLocation,\n files?: string[] | undefined,\n) {\n if (!files || files.length === 0) {\n return [];\n }\n\n return await Promise.all(\n files.map(async (filePath) => location.fetch(filePath)),\n );\n}\n\n/**\n * Fetch the Snap manifest, source code, and any other files from the given\n * location.\n *\n * @param snapId - The ID of the Snap to fetch.\n * @param location - The location of the Snap.\n * @returns The Snap files and location.\n * @throws If the Snap files are invalid, or if the Snap could not be fetched.\n */\nexport async function fetchSnap(snapId: SnapId, location: SnapLocation) {\n try {\n const manifest = await location.manifest();\n const sourceCode = await location.fetch(\n manifest.result.source.location.npm.filePath,\n );\n const { iconPath } = manifest.result.source.location.npm;\n const svgIcon = iconPath ? await location.fetch(iconPath) : undefined;\n\n const auxiliaryFiles = await getSnapFiles(\n location,\n manifest.result.source.files,\n );\n\n await Promise.all(\n auxiliaryFiles.map(async (file) => {\n // This should still be safe\n // eslint-disable-next-line require-atomic-updates\n file.data.base64 = await encodeBase64(file);\n }),\n );\n\n const localizationFiles = await getSnapFiles(\n location,\n manifest.result.source.locales,\n );\n\n const validatedLocalizationFiles =\n getValidatedLocalizationFiles(localizationFiles);\n\n const files = {\n manifest,\n sourceCode,\n svgIcon,\n auxiliaryFiles,\n localizationFiles: validatedLocalizationFiles,\n };\n\n await validateFetchedSnap(files);\n\n return files;\n } catch (error) {\n throw new Error(\n `Failed to fetch snap \"${snapId}\": ${getErrorMessage(error)}.`,\n );\n }\n}\n\n/**\n * Calculate change of initialConnections.\n *\n * @param oldConnectionsSet - Previously approved connections.\n * @param desiredConnectionsSet - New connections.\n * @returns Object containing newConnections, unusedConnections and approvedConnections.\n */\nexport function calculateConnectionsChange(\n oldConnectionsSet: Record<string, Json>,\n desiredConnectionsSet: Record<string, Json>,\n): {\n newConnections: Record<string, Json>;\n unusedConnections: Record<string, Json>;\n approvedConnections: Record<string, Json>;\n} {\n const newConnections = setDiff(desiredConnectionsSet, oldConnectionsSet);\n\n const unusedConnections = setDiff(oldConnectionsSet, desiredConnectionsSet);\n\n // It's a Set Intersection of oldConnections and desiredConnectionsSet\n // oldConnections ∖ (oldConnections ∖ desiredConnectionsSet) ⟺ oldConnections ∩ desiredConnectionsSet\n const approvedConnections = setDiff(oldConnectionsSet, unusedConnections);\n\n return { newConnections, unusedConnections, approvedConnections };\n}\n"],"mappings":"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","names":[]}
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  AbstractExecutionService
3
- } from "./chunk-FCCGRGQS.mjs";
3
+ } from "./chunk-QLFH3MC6.mjs";
4
4
  import {
5
5
  ProxyPostMessageStream
6
6
  } from "./chunk-ZVOYOZFT.mjs";
@@ -102,4 +102,4 @@ export {
102
102
  WORKER_POOL_ID,
103
103
  WebWorkerExecutionService
104
104
  };
105
- //# sourceMappingURL=chunk-RS3WN6D3.mjs.map
105
+ //# sourceMappingURL=chunk-7IJQGFT5.mjs.map
@@ -4,6 +4,7 @@ var _jsx = require('@metamask/snaps-sdk/jsx');
4
4
 
5
5
 
6
6
 
7
+
7
8
  var _snapsutils = require('@metamask/snaps-utils');
8
9
  function getJsxInterface(component) {
9
10
  if (_jsx.isJSXElementUnsafe.call(void 0, component)) {
@@ -65,16 +66,28 @@ function constructState(oldState, component, newState = {}) {
65
66
  );
66
67
  return newState;
67
68
  }
68
- if (component.type === "Input") {
69
+ if (component.type === "Input" || component.type === "Dropdown") {
69
70
  assertNameIsUnique(newState, component.props.name);
70
71
  newState[component.props.name] = constructInputState(oldState, component);
71
72
  }
72
73
  return newState;
73
74
  }
75
+ var MAX_CONTEXT_SIZE = 1e6;
76
+ function validateInterfaceContext(context) {
77
+ if (!context) {
78
+ return;
79
+ }
80
+ const size = _snapsutils.getJsonSizeUnsafe.call(void 0, context);
81
+ _snapssdk.assert.call(void 0,
82
+ size <= MAX_CONTEXT_SIZE,
83
+ `A Snap interface context may not be larger than ${MAX_CONTEXT_SIZE / 1e6} MB.`
84
+ );
85
+ }
86
+
74
87
 
75
88
 
76
89
 
77
90
 
78
91
 
79
- exports.getJsxInterface = getJsxInterface; exports.assertNameIsUnique = assertNameIsUnique; exports.constructState = constructState;
80
- //# sourceMappingURL=chunk-U4DZUKNN.js.map
92
+ exports.getJsxInterface = getJsxInterface; exports.assertNameIsUnique = assertNameIsUnique; exports.constructState = constructState; exports.validateInterfaceContext = validateInterfaceContext;
93
+ //# sourceMappingURL=chunk-7TYZZFHZ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/interface/utils.ts"],"names":[],"mappings":";AAAA,SAAS,cAAc;AAcvB,SAAS,0BAA0B;AACnC;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAUA,SAAS,gBAAgB,WAA2C;AACzE,MAAI,mBAAmB,SAAS,GAAG;AACjC,WAAO;AAAA,EACT;AAEA,SAAO,2BAA2B,SAAS;AAC7C;AAQO,SAAS,mBAAmB,OAAuB,MAAc;AACtE;AAAA,IACE,MAAM,IAAI,MAAM;AAAA,IAChB,4EAA4E,IAAI;AAAA,EAClF;AACF;AASA,SAAS,oBACP,UACA,SACA;AACA,SAAO,QAAQ,MAAM,SAAS,SAAS,QAAQ,MAAM,IAAI,KAAK;AAChE;AAUA,SAAS,wBACP,UACA,WACA,MACA;AACA,QAAM,eAAe,SAAS,IAAI;AAClC,QAAM,gBAAgB,eAAe,UAAU,MAAM,IAAI;AACzD,SAAO,UAAU,MAAM,SAAS,iBAAiB;AACnD;AAQA,SAAS,cAAc,SAAuB;AAC5C,MAAI,MAAM,QAAQ,QAAQ,MAAM,QAAQ,GAAG;AACzC,WAAO,QAAQ,MAAM,SAAS,CAAC;AAAA,EACjC;AAEA,SAAO,QAAQ,MAAM;AACvB;AAWA,SAAS,mBACP,UACA,WACA,MACA,UACW;AACX,MAAI,UAAU,SAAS,UAAU;AAC/B,WAAO;AAAA,EACT;AAEA,QAAM,QAAQ,cAAc,SAAS;AACrC,qBAAmB,UAAU,MAAM,MAAM,IAAI;AAE7C,WAAS,MAAM,MAAM,IAAI,IAAI,wBAAwB,UAAU,OAAO,IAAI;AAE1E,SAAO;AACT;AAUO,SAAS,eACd,UACA,WACA,WAA2B,CAAC,GACZ;AAChB,MAAI,UAAU,SAAS,OAAO;AAC5B,UAAM,WAAW,eAAe,SAAS;AACzC,WAAO,SAAS;AAAA,MACd,CAAC,aAAa,SACZ,eAAe,UAAU,MAAoB,WAAW;AAAA,MAC1D;AAAA,IACF;AAAA,EACF;AAEA,MAAI,UAAU,SAAS,QAAQ;AAC7B,uBAAmB,UAAU,UAAU,MAAM,IAAI;AAEjD,UAAM,WAAW,eAAe,SAAS;AACzC,aAAS,UAAU,MAAM,IAAI,IAAI,SAAS;AAAA,MACxC,CAAC,aAAa,SAAS;AACrB,eAAO;AAAA,UACL;AAAA;AAAA,UAEA;AAAA,UACA,UAAU,MAAM;AAAA,UAChB;AAAA,QACF;AAAA,MACF;AAAA,MACA,CAAC;AAAA,IACH;AAEA,WAAO;AAAA,EACT;AAEA,MAAI,UAAU,SAAS,WAAW,UAAU,SAAS,YAAY;AAC/D,uBAAmB,UAAU,UAAU,MAAM,IAAI;AACjD,aAAS,UAAU,MAAM,IAAI,IAAI,oBAAoB,UAAU,SAAS;AAAA,EAC1E;AAEA,SAAO;AACT;AAEA,IAAM,mBAAmB;AAQlB,SAAS,yBAAyB,SAA4B;AACnE,MAAI,CAAC,SAAS;AACZ;AAAA,EACF;AAIA,QAAM,OAAO,kBAAkB,OAAO;AACtC;AAAA,IACE,QAAQ;AAAA,IACR,mDACE,mBAAmB,GACrB;AAAA,EACF;AACF","sourcesContent":["import { assert } from '@metamask/snaps-sdk';\nimport type {\n FormState,\n InterfaceState,\n ComponentOrElement,\n InterfaceContext,\n} from '@metamask/snaps-sdk';\nimport type {\n ButtonElement,\n DropdownElement,\n FieldElement,\n InputElement,\n JSXElement,\n} from '@metamask/snaps-sdk/jsx';\nimport { isJSXElementUnsafe } from '@metamask/snaps-sdk/jsx';\nimport {\n getJsonSizeUnsafe,\n getJsxChildren,\n getJsxElementFromComponent,\n} from '@metamask/snaps-utils';\n\n/**\n * Get a JSX element from a component or JSX element. If the component is a\n * JSX element, it is returned as is. Otherwise, the component is converted to\n * a JSX element.\n *\n * @param component - The component to convert.\n * @returns The JSX element.\n */\nexport function getJsxInterface(component: ComponentOrElement): JSXElement {\n if (isJSXElementUnsafe(component)) {\n return component;\n }\n\n return getJsxElementFromComponent(component);\n}\n\n/**\n * Assert that the component name is unique in state.\n *\n * @param state - The interface state to verify against.\n * @param name - The component name to verify.\n */\nexport function assertNameIsUnique(state: InterfaceState, name: string) {\n assert(\n state[name] === undefined,\n `Duplicate component names are not allowed, found multiple instances of: \"${name}\".`,\n );\n}\n\n/**\n * Construct the state for an input field.\n *\n * @param oldState - The previous state.\n * @param element - The input element.\n * @returns The input state.\n */\nfunction constructInputState(\n oldState: InterfaceState,\n element: InputElement | DropdownElement,\n) {\n return element.props.value ?? oldState[element.props.name] ?? null;\n}\n\n/**\n * Construct the state for a form input.\n *\n * @param oldState - The previous state.\n * @param component - The input element.\n * @param form - The parent form name of the input.\n * @returns The input state.\n */\nfunction constructFormInputState(\n oldState: InterfaceState,\n component: InputElement | DropdownElement,\n form: string,\n) {\n const oldFormState = oldState[form] as FormState;\n const oldInputState = oldFormState?.[component.props.name];\n return component.props.value ?? oldInputState ?? null;\n}\n\n/**\n * Get the input field from a field element.\n *\n * @param element - The field element.\n * @returns The input element.\n */\nfunction getFieldInput(element: FieldElement) {\n if (Array.isArray(element.props.children)) {\n return element.props.children[0];\n }\n\n return element.props.children;\n}\n\n/**\n * Construct the state for a form input.\n *\n * @param oldState - The previous state.\n * @param component - The field element.\n * @param form - The parent form name of the input.\n * @param newState - The new state.\n * @returns The input state.\n */\nfunction constructFormState(\n oldState: InterfaceState,\n component: FieldElement | ButtonElement,\n form: string,\n newState: FormState,\n): FormState {\n if (component.type === 'Button') {\n return newState;\n }\n\n const input = getFieldInput(component);\n assertNameIsUnique(newState, input.props.name);\n\n newState[input.props.name] = constructFormInputState(oldState, input, form);\n\n return newState;\n}\n\n/**\n * Construct the interface state for a given component tree.\n *\n * @param oldState - The previous state.\n * @param component - The UI component to construct state from.\n * @param newState - The state that is being constructed.\n * @returns The interface state of the passed component.\n */\nexport function constructState(\n oldState: InterfaceState,\n component: JSXElement,\n newState: InterfaceState = {},\n): InterfaceState {\n if (component.type === 'Box') {\n const children = getJsxChildren(component);\n return children.reduce(\n (accumulator, node) =>\n constructState(oldState, node as JSXElement, accumulator),\n newState,\n );\n }\n\n if (component.type === 'Form') {\n assertNameIsUnique(newState, component.props.name);\n\n const children = getJsxChildren(component);\n newState[component.props.name] = children.reduce<FormState>(\n (accumulator, node) => {\n return constructFormState(\n oldState,\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion\n node as FieldElement | ButtonElement,\n component.props.name,\n accumulator,\n );\n },\n {},\n );\n\n return newState;\n }\n\n if (component.type === 'Input' || component.type === 'Dropdown') {\n assertNameIsUnique(newState, component.props.name);\n newState[component.props.name] = constructInputState(oldState, component);\n }\n\n return newState;\n}\n\nconst MAX_CONTEXT_SIZE = 1_000_000; // 1 mb\n\n/**\n * Validate a JSON blob to be used as the interface context.\n *\n * @param context - The JSON blob.\n * @throws If the JSON blob is too large.\n */\nexport function validateInterfaceContext(context?: InterfaceContext) {\n if (!context) {\n return;\n }\n\n // We assume the validity of this JSON to be validated by the caller.\n // E.g., in the RPC method implementation.\n const size = getJsonSizeUnsafe(context);\n assert(\n size <= MAX_CONTEXT_SIZE,\n `A Snap interface context may not be larger than ${\n MAX_CONTEXT_SIZE / 1000000\n } MB.`,\n );\n}\n"]}
@@ -106,6 +106,13 @@ async function fetchSnap(snapId, location) {
106
106
  );
107
107
  }
108
108
  }
109
+ function calculateConnectionsChange(oldConnectionsSet, desiredConnectionsSet) {
110
+ const newConnections = setDiff(desiredConnectionsSet, oldConnectionsSet);
111
+ const unusedConnections = setDiff(oldConnectionsSet, desiredConnectionsSet);
112
+ const approvedConnections = setDiff(oldConnectionsSet, unusedConnections);
113
+ return { newConnections, unusedConnections, approvedConnections };
114
+ }
115
+
109
116
 
110
117
 
111
118
 
@@ -116,5 +123,5 @@ async function fetchSnap(snapId, location) {
116
123
 
117
124
 
118
125
 
119
- exports.setDiff = setDiff; exports.permissionsDiff = permissionsDiff; exports.delay = delay; exports.delayWithTimer = delayWithTimer; exports.hasTimedOut = hasTimedOut; exports.withTimeout = withTimeout; exports.getSnapFiles = getSnapFiles; exports.fetchSnap = fetchSnap;
120
- //# sourceMappingURL=chunk-4DPX4O3T.js.map
126
+ exports.setDiff = setDiff; exports.permissionsDiff = permissionsDiff; exports.delay = delay; exports.delayWithTimer = delayWithTimer; exports.hasTimedOut = hasTimedOut; exports.withTimeout = withTimeout; exports.getSnapFiles = getSnapFiles; exports.fetchSnap = fetchSnap; exports.calculateConnectionsChange = calculateConnectionsChange;
127
+ //# sourceMappingURL=chunk-CDTGUNSA.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/utils.ts"],"names":[],"mappings":"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","sourcesContent":["import type { PermissionConstraint } from '@metamask/permission-controller';\nimport type { SnapId } from '@metamask/snaps-sdk';\nimport { getErrorMessage } from '@metamask/snaps-sdk';\nimport {\n encodeBase64,\n getValidatedLocalizationFiles,\n validateFetchedSnap,\n} from '@metamask/snaps-utils';\nimport type { Json } from '@metamask/utils';\nimport deepEqual from 'fast-deep-equal';\n\nimport type { SnapLocation } from './snaps';\nimport { Timer } from './snaps/Timer';\n\n/**\n * Takes two objects and does a Set Difference of them.\n * Set Difference is generally defined as follows:\n * ```\n * 𝑥 ∈ A ∖ B ⟺ 𝑥 ∈ A ∧ 𝑥 ∉ B\n * ```\n * Meaning that the returned object contains all properties of A expect those that also\n * appear in B. Notice that properties that appear in B, but not in A, have no effect.\n *\n * @see [Set Difference]{@link https://proofwiki.org/wiki/Definition:Set_Difference}\n * @param objectA - The object on which the difference is being calculated.\n * @param objectB - The object whose properties will be removed from objectA.\n * @returns The objectA without properties from objectB.\n */\nexport function setDiff<\n ObjectA extends Record<any, unknown>,\n ObjectB extends Record<any, unknown>,\n>(objectA: ObjectA, objectB: ObjectB): Diff<ObjectA, ObjectB> {\n return Object.entries(objectA).reduce<Record<any, unknown>>(\n (acc, [key, value]) => {\n if (!(key in objectB)) {\n acc[key] = value;\n }\n return acc;\n },\n {},\n ) as Diff<ObjectA, ObjectB>;\n}\n\n/**\n * Calculate a difference between two permissions objects.\n *\n * Similar to `setDiff` except for one additional condition:\n * Permissions in B should be removed from A if they exist in both and have differing caveats.\n *\n * @param permissionsA - An object containing one or more partial permissions.\n * @param permissionsB - An object containing one or more partial permissions to be subtracted from A.\n * @returns The permissions set A without properties from B.\n */\nexport function permissionsDiff<\n PermissionsA extends Record<string, Pick<PermissionConstraint, 'caveats'>>,\n PermissionsB extends Record<string, Pick<PermissionConstraint, 'caveats'>>,\n>(\n permissionsA: PermissionsA,\n permissionsB: PermissionsB,\n): Diff<PermissionsA, PermissionsB> {\n return Object.entries(permissionsA).reduce<\n Record<string, Pick<PermissionConstraint, 'caveats'>>\n >((acc, [key, value]) => {\n const isIncluded = key in permissionsB;\n if (\n !isIncluded ||\n (isIncluded &&\n !deepEqual(value.caveats ?? [], permissionsB[key].caveats ?? []))\n ) {\n acc[key] = value;\n }\n return acc;\n }, {}) as Diff<PermissionsA, PermissionsB>;\n}\n\n/**\n * A Promise that delays its return for a given amount of milliseconds.\n *\n * @param ms - Milliseconds to delay the execution for.\n * @param result - The result to return from the Promise after delay.\n * @returns A promise that is void if no result provided, result otherwise.\n * @template Result - The `result`.\n */\nexport function delay<Result = void>(\n ms: number,\n result?: Result,\n): Promise<Result> & { cancel: () => void } {\n return delayWithTimer(new Timer(ms), result);\n}\n\n/**\n * A Promise that delays it's return by using a pausable Timer.\n *\n * @param timer - Timer used to control the delay.\n * @param result - The result to return from the Promise after delay.\n * @returns A promise that is void if no result provided, result otherwise.\n * @template Result - The `result`.\n */\nexport function delayWithTimer<Result = void>(\n timer: Timer,\n result?: Result,\n): Promise<Result> & { cancel: () => void } {\n let rejectFunc: (reason: Error) => void;\n const promise: any = new Promise<Result>((resolve: any, reject) => {\n timer.start(() => {\n result === undefined ? resolve() : resolve(result);\n });\n rejectFunc = reject;\n });\n\n promise.cancel = () => {\n if (timer.status !== 'finished') {\n timer.cancel();\n rejectFunc(new Error('The delay has been canceled.'));\n }\n };\n return promise;\n}\n\n/*\n * We use a Symbol instead of rejecting the promise so that Errors thrown\n * by the main promise will propagate.\n */\nexport const hasTimedOut = Symbol(\n 'Used to check if the requested promise has timeout (see withTimeout)',\n);\n\n/**\n * Executes the given Promise, if the Timer expires before the Promise settles, we return earlier.\n *\n * NOTE:** The given Promise is not cancelled or interrupted, and will continue to execute uninterrupted. We will just discard its result if it does not complete before the timeout.\n *\n * @param promise - The promise that you want to execute.\n * @param timerOrMs - The timer controlling the timeout or a ms value.\n * @returns The resolved `PromiseValue`, or the hasTimedOut symbol if\n * returning early.\n * @template PromiseValue - The value of the Promise.\n */\nexport async function withTimeout<PromiseValue = void>(\n promise: Promise<PromiseValue>,\n timerOrMs: Timer | number,\n): Promise<PromiseValue | typeof hasTimedOut> {\n const timer =\n typeof timerOrMs === 'number' ? new Timer(timerOrMs) : timerOrMs;\n const delayPromise = delayWithTimer(timer, hasTimedOut);\n try {\n return await Promise.race([promise, delayPromise]);\n } finally {\n delayPromise.cancel();\n }\n}\n\n/**\n * Checks whether the type is composed of literal types\n *\n * @returns @type {true} if whole type is composed of literals, @type {false} if whole type is not literals, @type {boolean} if mixed\n * @example\n * ```\n * type t1 = IsLiteral<1 | 2 | \"asd\" | true>;\n * // t1 = true\n *\n * type t2 = IsLiteral<number | string>;\n * // t2 = false\n *\n * type t3 = IsLiteral<1 | string>;\n * // t3 = boolean\n *\n * const s = Symbol();\n * type t4 = IsLiteral<typeof s>;\n * // t4 = true\n *\n * type t5 = IsLiteral<symbol>\n * // t5 = false;\n * ```\n */\ntype IsLiteral<Type> = Type extends string | number | boolean | symbol\n ? Extract<string | number | boolean | symbol, Type> extends never\n ? true\n : false\n : false;\n\n/**\n * Returns all keys of an object, that are literal, as an union\n *\n * @example\n * ```\n * type t1 = _LiteralKeys<{a: number, b: 0, c: 'foo', d: string}>\n * // t1 = 'b' | 'c'\n * ```\n * @see [Literal types]{@link https://www.typescriptlang.org/docs/handbook/literal-types.html}\n */\ntype LiteralKeys<Type> = NonNullable<\n {\n [Key in keyof Type]: IsLiteral<Key> extends true ? Key : never;\n }[keyof Type]\n>;\n\n/**\n * Returns all keys of an object, that are not literal, as an union\n *\n * @example\n * ```\n * type t1 = _NonLiteralKeys<{a: number, b: 0, c: 'foo', d: string}>\n * // t1 = 'a' | 'd'\n * ```\n * @see [Literal types]{@link https://www.typescriptlang.org/docs/handbook/literal-types.html}\n */\ntype NonLiteralKeys<Type> = NonNullable<\n {\n [Key in keyof Type]: IsLiteral<Key> extends false ? Key : never;\n }[keyof Type]\n>;\n\n/**\n * A set difference of two objects based on their keys\n *\n * @example\n * ```\n * type t1 = Diff<{a: string, b: string}, {a: number}>\n * // t1 = {b: string};\n * type t2 = Diff<{a: string, 0: string}, Record<string, unknown>>;\n * // t2 = { a?: string, 0: string};\n * type t3 = Diff<{a: string, 0: string, 1: string}, Record<1 | string, unknown>>;\n * // t3 = {a?: string, 0: string}\n * ```\n * @see {@link setDiff} for the main use-case\n */\nexport type Diff<First, Second> = Omit<First, LiteralKeys<Second>> &\n Partial<Pick<First, Extract<keyof First, NonLiteralKeys<Second>>>>;\n\n/**\n * Makes every specified property of the specified object type mutable.\n *\n * @template Type - The object whose readonly properties to make mutable.\n * @template TargetKey - The property key(s) to make mutable.\n */\nexport type Mutable<\n Type extends Record<string, unknown>,\n TargetKey extends string,\n> = {\n -readonly [Key in keyof Pick<Type, TargetKey>]: Type[Key];\n} & {\n [Key in keyof Omit<Type, TargetKey>]: Type[Key];\n};\n\n/**\n * Get all files in a Snap from an array of file paths.\n *\n * @param location - The location of the Snap.\n * @param files - The array of file paths.\n * @returns The array of files as {@link VirtualFile}s.\n */\nexport async function getSnapFiles(\n location: SnapLocation,\n files?: string[] | undefined,\n) {\n if (!files || files.length === 0) {\n return [];\n }\n\n return await Promise.all(\n files.map(async (filePath) => location.fetch(filePath)),\n );\n}\n\n/**\n * Fetch the Snap manifest, source code, and any other files from the given\n * location.\n *\n * @param snapId - The ID of the Snap to fetch.\n * @param location - The location of the Snap.\n * @returns The Snap files and location.\n * @throws If the Snap files are invalid, or if the Snap could not be fetched.\n */\nexport async function fetchSnap(snapId: SnapId, location: SnapLocation) {\n try {\n const manifest = await location.manifest();\n const sourceCode = await location.fetch(\n manifest.result.source.location.npm.filePath,\n );\n const { iconPath } = manifest.result.source.location.npm;\n const svgIcon = iconPath ? await location.fetch(iconPath) : undefined;\n\n const auxiliaryFiles = await getSnapFiles(\n location,\n manifest.result.source.files,\n );\n\n await Promise.all(\n auxiliaryFiles.map(async (file) => {\n // This should still be safe\n // eslint-disable-next-line require-atomic-updates\n file.data.base64 = await encodeBase64(file);\n }),\n );\n\n const localizationFiles = await getSnapFiles(\n location,\n manifest.result.source.locales,\n );\n\n const validatedLocalizationFiles =\n getValidatedLocalizationFiles(localizationFiles);\n\n const files = {\n manifest,\n sourceCode,\n svgIcon,\n auxiliaryFiles,\n localizationFiles: validatedLocalizationFiles,\n };\n\n await validateFetchedSnap(files);\n\n return files;\n } catch (error) {\n throw new Error(\n `Failed to fetch snap \"${snapId}\": ${getErrorMessage(error)}.`,\n );\n }\n}\n\n/**\n * Calculate change of initialConnections.\n *\n * @param oldConnectionsSet - Previously approved connections.\n * @param desiredConnectionsSet - New connections.\n * @returns Object containing newConnections, unusedConnections and approvedConnections.\n */\nexport function calculateConnectionsChange(\n oldConnectionsSet: Record<string, Json>,\n desiredConnectionsSet: Record<string, Json>,\n): {\n newConnections: Record<string, Json>;\n unusedConnections: Record<string, Json>;\n approvedConnections: Record<string, Json>;\n} {\n const newConnections = setDiff(desiredConnectionsSet, oldConnectionsSet);\n\n const unusedConnections = setDiff(oldConnectionsSet, desiredConnectionsSet);\n\n // It's a Set Intersection of oldConnections and desiredConnectionsSet\n // oldConnections ∖ (oldConnections ∖ desiredConnectionsSet) ⟺ oldConnections ∩ desiredConnectionsSet\n const approvedConnections = setDiff(oldConnectionsSet, unusedConnections);\n\n return { newConnections, unusedConnections, approvedConnections };\n}\n"]}
@@ -3,7 +3,7 @@
3
3
  var _chunkC4D6GBMYjs = require('./chunk-C4D6GBMY.js');
4
4
 
5
5
 
6
- var _chunkFCRPOA4Ijs = require('./chunk-FCRPOA4I.js');
6
+ var _chunkKH72WRHRjs = require('./chunk-KH72WRHR.js');
7
7
 
8
8
 
9
9
 
@@ -13,7 +13,7 @@ var _chunkEXN2TFDJjs = require('./chunk-EXN2TFDJ.js');
13
13
 
14
14
  // src/services/webview/WebViewExecutionService.ts
15
15
  var _getWebView, _ensureWebViewLoaded, ensureWebViewLoaded_fn;
16
- var WebViewExecutionService = class extends _chunkFCRPOA4Ijs.ProxyExecutionService {
16
+ var WebViewExecutionService = class extends _chunkKH72WRHRjs.ProxyExecutionService {
17
17
  constructor({
18
18
  messenger,
19
19
  setupSnapProvider,
@@ -55,4 +55,4 @@ ensureWebViewLoaded_fn = async function() {
55
55
 
56
56
 
57
57
  exports.WebViewExecutionService = WebViewExecutionService;
58
- //# sourceMappingURL=chunk-74GN6MIJ.js.map
58
+ //# sourceMappingURL=chunk-FPGAQ6MT.js.map
@@ -1,6 +1,6 @@
1
1
  "use strict";Object.defineProperty(exports, "__esModule", {value: true});
2
2
 
3
- var _chunkFCRPOA4Ijs = require('./chunk-FCRPOA4I.js');
3
+ var _chunkKH72WRHRjs = require('./chunk-KH72WRHR.js');
4
4
 
5
5
 
6
6
 
@@ -9,7 +9,7 @@ var _chunkEXN2TFDJjs = require('./chunk-EXN2TFDJ.js');
9
9
  // src/services/offscreen/OffscreenExecutionService.ts
10
10
  var _postmessagestream = require('@metamask/post-message-stream');
11
11
  var _createDocument, createDocument_fn;
12
- var OffscreenExecutionService = class extends _chunkFCRPOA4Ijs.ProxyExecutionService {
12
+ var OffscreenExecutionService = class extends _chunkKH72WRHRjs.ProxyExecutionService {
13
13
  /**
14
14
  * Create a new offscreen execution service.
15
15
  *
@@ -69,4 +69,4 @@ createDocument_fn = async function() {
69
69
 
70
70
 
71
71
  exports.OffscreenExecutionService = OffscreenExecutionService;
72
- //# sourceMappingURL=chunk-Y7ZOSPEN.js.map
72
+ //# sourceMappingURL=chunk-HK4OAMJT.js.map
@@ -1,6 +1,6 @@
1
1
  "use strict";Object.defineProperty(exports, "__esModule", {value: true});
2
2
 
3
- var _chunkSIW7ZXQFjs = require('./chunk-SIW7ZXQF.js');
3
+ var _chunkS775IABYjs = require('./chunk-S775IABY.js');
4
4
 
5
5
 
6
6
  var _chunk7Y6P5FRNjs = require('./chunk-7Y6P5FRN.js');
@@ -17,7 +17,7 @@ var _utils = require('@metamask/utils');
17
17
  var _nanoid = require('nanoid');
18
18
  var WORKER_POOL_ID = "snaps-worker-pool";
19
19
  var _documentUrl, _runtimeStream;
20
- var WebWorkerExecutionService = class extends _chunkSIW7ZXQFjs.AbstractExecutionService {
20
+ var WebWorkerExecutionService = class extends _chunkS775IABYjs.AbstractExecutionService {
21
21
  /**
22
22
  * Create a new webworker execution service.
23
23
  *
@@ -102,4 +102,4 @@ _runtimeStream = new WeakMap();
102
102
 
103
103
 
104
104
  exports.WORKER_POOL_ID = WORKER_POOL_ID; exports.WebWorkerExecutionService = WebWorkerExecutionService;
105
- //# sourceMappingURL=chunk-E5RRFMGF.js.map
105
+ //# sourceMappingURL=chunk-HQ6HMINL.js.map
@@ -15,12 +15,13 @@ import {
15
15
  log
16
16
  } from "./chunk-4HVWEABQ.mjs";
17
17
  import {
18
+ calculateConnectionsChange,
18
19
  fetchSnap,
19
20
  hasTimedOut,
20
21
  permissionsDiff,
21
22
  setDiff,
22
23
  withTimeout
23
- } from "./chunk-GTDDODNP.mjs";
24
+ } from "./chunk-567BFPSL.mjs";
24
25
  import {
25
26
  Timer
26
27
  } from "./chunk-XO7KDFBY.mjs";
@@ -117,7 +118,7 @@ function truncateSnap(snap) {
117
118
  return truncatedSnap;
118
119
  }
119
120
  var name = "SnapController";
120
- var _closeAllConnections, _dynamicPermissions, _environmentEndowmentPermissions, _excludedPermissions, _featureFlags, _fetchFunction, _idleTimeCheckInterval, _maxIdleTime, _encryptor, _getMnemonic, _detectSnapLocation, _snapsRuntimeData, _rollbackSnapshots, _timeoutForLastRequestStatus, _statusMachine, _preinstalledSnaps, _initializeStateMachine, initializeStateMachine_fn, _registerMessageHandlers, registerMessageHandlers_fn, _handlePreinstalledSnaps, handlePreinstalledSnaps_fn, _pollForLastRequestStatus, pollForLastRequestStatus_fn, _blockSnap, blockSnap_fn, _unblockSnap, unblockSnap_fn, _assertIsInstallAllowed, assertIsInstallAllowed_fn, _stopSnapsLastRequestPastMax, stopSnapsLastRequestPastMax_fn, _transition, transition_fn, _terminateSnap, terminateSnap_fn, _getSnapEncryptionKey, getSnapEncryptionKey_fn, _decryptSnapState, decryptSnapState_fn, _encryptSnapState, encryptSnapState_fn, _handleInitialConnections, handleInitialConnections_fn, _addSnapToSubject, addSnapToSubject_fn, _removeSnapFromSubjects, removeSnapFromSubjects_fn, _revokeAllSnapPermissions, revokeAllSnapPermissions_fn, _createApproval, createApproval_fn, _updateApproval, updateApproval_fn, _resolveAllowlistVersion, resolveAllowlistVersion_fn, _add, add_fn, _startSnap, startSnap_fn, _getEndowments, getEndowments_fn, _set, set_fn, _validateSnapPermissions, validateSnapPermissions_fn, _getExecutionTimeout, getExecutionTimeout_fn, _getRpcRequestHandler, getRpcRequestHandler_fn, _createInterface, createInterface_fn, _assertInterfaceExists, assertInterfaceExists_fn, _transformSnapRpcRequestResult, transformSnapRpcRequestResult_fn, _assertSnapRpcRequestResult, assertSnapRpcRequestResult_fn, _recordSnapRpcRequestStart, recordSnapRpcRequestStart_fn, _recordSnapRpcRequestFinish, recordSnapRpcRequestFinish_fn, _getRollbackSnapshot, getRollbackSnapshot_fn, _createRollbackSnapshot, createRollbackSnapshot_fn, _rollbackSnap, rollbackSnap_fn, _rollbackSnaps, rollbackSnaps_fn, _getRuntime, getRuntime_fn, _getRuntimeExpect, getRuntimeExpect_fn, _setupRuntime, setupRuntime_fn, _calculatePermissionsChange, calculatePermissionsChange_fn, _updatePermissions, updatePermissions_fn, _isValidUpdate, isValidUpdate_fn, _callLifecycleHook, callLifecycleHook_fn;
121
+ var _closeAllConnections, _dynamicPermissions, _environmentEndowmentPermissions, _excludedPermissions, _featureFlags, _fetchFunction, _idleTimeCheckInterval, _maxIdleTime, _encryptor, _getMnemonic, _getFeatureFlags, _detectSnapLocation, _snapsRuntimeData, _rollbackSnapshots, _timeoutForLastRequestStatus, _statusMachine, _preinstalledSnaps, _initializeStateMachine, initializeStateMachine_fn, _registerMessageHandlers, registerMessageHandlers_fn, _handlePreinstalledSnaps, handlePreinstalledSnaps_fn, _pollForLastRequestStatus, pollForLastRequestStatus_fn, _blockSnap, blockSnap_fn, _unblockSnap, unblockSnap_fn, _assertIsInstallAllowed, assertIsInstallAllowed_fn, _assertCanUsePlatform, assertCanUsePlatform_fn, _stopSnapsLastRequestPastMax, stopSnapsLastRequestPastMax_fn, _transition, transition_fn, _terminateSnap, terminateSnap_fn, _getSnapEncryptionKey, getSnapEncryptionKey_fn, _decryptSnapState, decryptSnapState_fn, _encryptSnapState, encryptSnapState_fn, _handleInitialConnections, handleInitialConnections_fn, _addSnapToSubject, addSnapToSubject_fn, _removeSnapFromSubjects, removeSnapFromSubjects_fn, _revokeAllSnapPermissions, revokeAllSnapPermissions_fn, _createApproval, createApproval_fn, _updateApproval, updateApproval_fn, _resolveAllowlistVersion, resolveAllowlistVersion_fn, _add, add_fn, _startSnap, startSnap_fn, _getEndowments, getEndowments_fn, _set, set_fn, _validateSnapPermissions, validateSnapPermissions_fn, _getExecutionTimeout, getExecutionTimeout_fn, _getRpcRequestHandler, getRpcRequestHandler_fn, _createInterface, createInterface_fn, _assertInterfaceExists, assertInterfaceExists_fn, _transformSnapRpcRequestResult, transformSnapRpcRequestResult_fn, _assertSnapRpcRequestResult, assertSnapRpcRequestResult_fn, _recordSnapRpcRequestStart, recordSnapRpcRequestStart_fn, _recordSnapRpcRequestFinish, recordSnapRpcRequestFinish_fn, _getRollbackSnapshot, getRollbackSnapshot_fn, _createRollbackSnapshot, createRollbackSnapshot_fn, _rollbackSnap, rollbackSnap_fn, _rollbackSnaps, rollbackSnaps_fn, _getRuntime, getRuntime_fn, _getRuntimeExpect, getRuntimeExpect_fn, _setupRuntime, setupRuntime_fn, _calculatePermissionsChange, calculatePermissionsChange_fn, _updatePermissions, updatePermissions_fn, _isValidUpdate, isValidUpdate_fn, _callLifecycleHook, callLifecycleHook_fn;
121
122
  var SnapController = class extends BaseController {
122
123
  constructor({
123
124
  closeAllConnections,
@@ -134,7 +135,8 @@ var SnapController = class extends BaseController {
134
135
  detectSnapLocation: detectSnapLocationFunction = detectSnapLocation,
135
136
  preinstalledSnaps = null,
136
137
  encryptor,
137
- getMnemonic
138
+ getMnemonic,
139
+ getFeatureFlags = () => ({})
138
140
  }) {
139
141
  super({
140
142
  messenger,
@@ -203,6 +205,10 @@ var SnapController = class extends BaseController {
203
205
  */
204
206
  __privateAdd(this, _unblockSnap);
205
207
  __privateAdd(this, _assertIsInstallAllowed);
208
+ /**
209
+ * Asserts whether the Snaps platform is allowed to run.
210
+ */
211
+ __privateAdd(this, _assertCanUsePlatform);
206
212
  __privateAdd(this, _stopSnapsLastRequestPastMax);
207
213
  /**
208
214
  * Transitions between states using `snapStatusStateMachineConfig` as the template to figure out
@@ -427,6 +433,7 @@ var SnapController = class extends BaseController {
427
433
  * `endowment:lifecycle-hooks` permission. If the snap does not have the
428
434
  * permission, nothing happens.
429
435
  *
436
+ * @param origin - The origin.
430
437
  * @param snapId - The snap ID.
431
438
  * @param handler - The lifecycle hook to call. This should be one of the
432
439
  * supported lifecycle hooks.
@@ -443,6 +450,7 @@ var SnapController = class extends BaseController {
443
450
  __privateAdd(this, _maxIdleTime, void 0);
444
451
  __privateAdd(this, _encryptor, void 0);
445
452
  __privateAdd(this, _getMnemonic, void 0);
453
+ __privateAdd(this, _getFeatureFlags, void 0);
446
454
  __privateAdd(this, _detectSnapLocation, void 0);
447
455
  __privateAdd(this, _snapsRuntimeData, void 0);
448
456
  __privateAdd(this, _rollbackSnapshots, void 0);
@@ -461,6 +469,7 @@ var SnapController = class extends BaseController {
461
469
  __privateSet(this, _detectSnapLocation, detectSnapLocationFunction);
462
470
  __privateSet(this, _encryptor, encryptor);
463
471
  __privateSet(this, _getMnemonic, getMnemonic);
472
+ __privateSet(this, _getFeatureFlags, getFeatureFlags);
464
473
  __privateSet(this, _preinstalledSnaps, preinstalledSnaps);
465
474
  this._onUnhandledSnapError = this._onUnhandledSnapError.bind(this);
466
475
  this._onOutboundRequest = this._onOutboundRequest.bind(this);
@@ -480,24 +489,34 @@ var SnapController = class extends BaseController {
480
489
  "ExecutionService:outboundResponse",
481
490
  this._onOutboundResponse
482
491
  );
483
- this.messagingSystem.subscribe("SnapController:snapInstalled", ({ id }) => {
484
- __privateMethod(this, _callLifecycleHook, callLifecycleHook_fn).call(this, id, HandlerType.OnInstall).catch((error) => {
485
- logError(
486
- `Error when calling \`onInstall\` lifecycle hook for snap "${id}": ${getErrorMessage(
487
- error
488
- )}`
492
+ this.messagingSystem.subscribe(
493
+ "SnapController:snapInstalled",
494
+ ({ id }, origin) => {
495
+ __privateMethod(this, _callLifecycleHook, callLifecycleHook_fn).call(this, origin, id, HandlerType.OnInstall).catch(
496
+ (error) => {
497
+ logError(
498
+ `Error when calling \`onInstall\` lifecycle hook for snap "${id}": ${getErrorMessage(
499
+ error
500
+ )}`
501
+ );
502
+ }
489
503
  );
490
- });
491
- });
492
- this.messagingSystem.subscribe("SnapController:snapUpdated", ({ id }) => {
493
- __privateMethod(this, _callLifecycleHook, callLifecycleHook_fn).call(this, id, HandlerType.OnUpdate).catch((error) => {
494
- logError(
495
- `Error when calling \`onUpdate\` lifecycle hook for snap "${id}": ${getErrorMessage(
496
- error
497
- )}`
504
+ }
505
+ );
506
+ this.messagingSystem.subscribe(
507
+ "SnapController:snapUpdated",
508
+ ({ id }, _oldVersion, origin) => {
509
+ __privateMethod(this, _callLifecycleHook, callLifecycleHook_fn).call(this, origin, id, HandlerType.OnUpdate).catch(
510
+ (error) => {
511
+ logError(
512
+ `Error when calling \`onUpdate\` lifecycle hook for snap "${id}": ${getErrorMessage(
513
+ error
514
+ )}`
515
+ );
516
+ }
498
517
  );
499
- });
500
- });
518
+ }
519
+ );
501
520
  __privateMethod(this, _initializeStateMachine, initializeStateMachine_fn).call(this);
502
521
  __privateMethod(this, _registerMessageHandlers, registerMessageHandlers_fn).call(this);
503
522
  if (__privateGet(this, _preinstalledSnaps)) {
@@ -513,6 +532,7 @@ var SnapController = class extends BaseController {
513
532
  * for more information.
514
533
  */
515
534
  async updateBlockedSnaps() {
535
+ __privateMethod(this, _assertCanUsePlatform, assertCanUsePlatform_fn).call(this);
516
536
  await this.messagingSystem.call("SnapsRegistry:update");
517
537
  const blockedSnaps = await this.messagingSystem.call(
518
538
  "SnapsRegistry:get",
@@ -562,6 +582,7 @@ var SnapController = class extends BaseController {
562
582
  * @param snapId - The id of the Snap to start.
563
583
  */
564
584
  async startSnap(snapId) {
585
+ __privateMethod(this, _assertCanUsePlatform, assertCanUsePlatform_fn).call(this);
565
586
  const snap = this.state.snaps[snapId];
566
587
  if (snap.enabled === false) {
567
588
  throw new Error(`Snap "${snapId}" is disabled.`);
@@ -980,6 +1001,7 @@ var SnapController = class extends BaseController {
980
1001
  * snap couldn't be installed.
981
1002
  */
982
1003
  async installSnaps(origin, requestedSnaps) {
1004
+ __privateMethod(this, _assertCanUsePlatform, assertCanUsePlatform_fn).call(this);
983
1005
  const result = {};
984
1006
  const snapIds = Object.keys(requestedSnaps);
985
1007
  const pendingUpdates = [];
@@ -1155,6 +1177,7 @@ var SnapController = class extends BaseController {
1155
1177
  * @returns The snap metadata if updated, `null` otherwise.
1156
1178
  */
1157
1179
  async updateSnap(origin, snapId, location, newVersionRange = DEFAULT_REQUESTED_SNAP_VERSION, emitEvent = true) {
1180
+ __privateMethod(this, _assertCanUsePlatform, assertCanUsePlatform_fn).call(this);
1158
1181
  if (!isValidSemVerRange(newVersionRange)) {
1159
1182
  throw new Error(
1160
1183
  `Received invalid snap version range: "${newVersionRange}".`
@@ -1198,13 +1221,19 @@ var SnapController = class extends BaseController {
1198
1221
  );
1199
1222
  __privateMethod(this, _validateSnapPermissions, validateSnapPermissions_fn).call(this, processedPermissions);
1200
1223
  const { newPermissions, unusedPermissions, approvedPermissions } = __privateMethod(this, _calculatePermissionsChange, calculatePermissionsChange_fn).call(this, snapId, processedPermissions);
1224
+ const { newConnections, unusedConnections, approvedConnections } = calculateConnectionsChange(
1225
+ oldManifest.initialConnections ?? {},
1226
+ manifest.initialConnections ?? {}
1227
+ );
1201
1228
  __privateMethod(this, _updateApproval, updateApproval_fn).call(this, pendingApproval.id, {
1202
- connections: manifest.initialConnections ?? {},
1203
1229
  permissions: newPermissions,
1204
1230
  newVersion: manifest.version,
1205
1231
  newPermissions,
1206
1232
  approvedPermissions,
1207
1233
  unusedPermissions,
1234
+ newConnections,
1235
+ unusedConnections,
1236
+ approvedConnections,
1208
1237
  loading: false
1209
1238
  });
1210
1239
  const { permissions: approvedNewPermissions, ...requestData } = await pendingApproval.promise;
@@ -1288,6 +1317,7 @@ var SnapController = class extends BaseController {
1288
1317
  * verified.
1289
1318
  */
1290
1319
  async getRegistryMetadata(snapId) {
1320
+ __privateMethod(this, _assertCanUsePlatform, assertCanUsePlatform_fn).call(this);
1291
1321
  return await this.messagingSystem.call("SnapsRegistry:getMetadata", snapId);
1292
1322
  }
1293
1323
  /**
@@ -1365,6 +1395,7 @@ var SnapController = class extends BaseController {
1365
1395
  handler: handlerType,
1366
1396
  request: rawRequest
1367
1397
  }) {
1398
+ __privateMethod(this, _assertCanUsePlatform, assertCanUsePlatform_fn).call(this);
1368
1399
  const request = {
1369
1400
  jsonrpc: "2.0",
1370
1401
  id: nanoid(),
@@ -1424,6 +1455,7 @@ _idleTimeCheckInterval = new WeakMap();
1424
1455
  _maxIdleTime = new WeakMap();
1425
1456
  _encryptor = new WeakMap();
1426
1457
  _getMnemonic = new WeakMap();
1458
+ _getFeatureFlags = new WeakMap();
1427
1459
  _detectSnapLocation = new WeakMap();
1428
1460
  _snapsRuntimeData = new WeakMap();
1429
1461
  _rollbackSnapshots = new WeakMap();
@@ -1690,6 +1722,14 @@ assertIsInstallAllowed_fn = async function(snapId, snapInfo) {
1690
1722
  );
1691
1723
  }
1692
1724
  };
1725
+ _assertCanUsePlatform = new WeakSet();
1726
+ assertCanUsePlatform_fn = function() {
1727
+ const flags = __privateGet(this, _getFeatureFlags).call(this);
1728
+ assert(
1729
+ flags.disableSnaps !== true,
1730
+ "The Snaps platform requires basic functionality to be used. Enable basic functionality in the settings to use the Snaps platform."
1731
+ );
1732
+ };
1693
1733
  _stopSnapsLastRequestPastMax = new WeakSet();
1694
1734
  stopSnapsLastRequestPastMax_fn = async function() {
1695
1735
  const entries = [...__privateGet(this, _snapsRuntimeData).entries()];
@@ -1814,7 +1854,7 @@ addSnapToSubject_fn = function(origin, snapId) {
1814
1854
  origin,
1815
1855
  WALLET_SNAP_PERMISSION_KEY,
1816
1856
  SnapCaveatType.SnapIds,
1817
- { ...existingCaveat, [snapId]: {} }
1857
+ { ...existingCaveat.value, [snapId]: {} }
1818
1858
  );
1819
1859
  return;
1820
1860
  }
@@ -2415,7 +2455,7 @@ isValidUpdate_fn = function(snapId, newVersionRange) {
2415
2455
  return true;
2416
2456
  };
2417
2457
  _callLifecycleHook = new WeakSet();
2418
- callLifecycleHook_fn = async function(snapId, handler) {
2458
+ callLifecycleHook_fn = async function(origin, snapId, handler) {
2419
2459
  const permissionName = handlerEndowments[handler];
2420
2460
  assert(permissionName, "Lifecycle hook must have an endowment.");
2421
2461
  const hasPermission = this.messagingSystem.call(
@@ -2429,7 +2469,7 @@ callLifecycleHook_fn = async function(snapId, handler) {
2429
2469
  await this.handleRequest({
2430
2470
  snapId,
2431
2471
  handler,
2432
- origin: "",
2472
+ origin,
2433
2473
  request: {
2434
2474
  jsonrpc: "2.0",
2435
2475
  method: handler
@@ -2444,4 +2484,4 @@ export {
2444
2484
  SNAP_APPROVAL_RESULT,
2445
2485
  SnapController
2446
2486
  };
2447
- //# sourceMappingURL=chunk-WMT2TIOI.mjs.map
2487
+ //# sourceMappingURL=chunk-JCQR3I2Q.mjs.map