@metamask/snaps-controllers 8.4.0 → 9.1.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 (77) hide show
  1. package/CHANGELOG.md +18 -1
  2. package/dist/chunk-3T6W5VI2.mjs +100 -0
  3. package/dist/chunk-3T6W5VI2.mjs.map +1 -0
  4. package/dist/{chunk-YIQM6ZKA.mjs → chunk-4M2FX2AT.mjs} +9 -2
  5. package/dist/{chunk-YIQM6ZKA.mjs.map → chunk-4M2FX2AT.mjs.map} +1 -1
  6. package/dist/chunk-6ERB63FH.js +58 -0
  7. package/dist/chunk-6ERB63FH.js.map +1 -0
  8. package/dist/{chunk-LLA2BJYO.js → chunk-BUHS4M6F.js} +7 -7
  9. package/dist/chunk-CIFVYFJW.mjs +58 -0
  10. package/dist/chunk-CIFVYFJW.mjs.map +1 -0
  11. package/dist/chunk-H7TB7I6Z.js +100 -0
  12. package/dist/chunk-H7TB7I6Z.js.map +1 -0
  13. package/dist/{chunk-5YBORD3A.js → chunk-JQ54YYLU.js} +9 -2
  14. package/dist/chunk-JQ54YYLU.js.map +1 -0
  15. package/dist/{chunk-TSPPQQHW.mjs → chunk-RVWBSSZM.mjs} +7 -4
  16. package/dist/chunk-RVWBSSZM.mjs.map +1 -0
  17. package/dist/{chunk-TMJA2PSY.mjs → chunk-WP3DAIFM.mjs} +2 -2
  18. package/dist/{chunk-IKD6PUV7.js → chunk-ZBSBCWWM.js} +7 -4
  19. package/dist/chunk-ZBSBCWWM.js.map +1 -0
  20. package/dist/cronjob/CronjobController.js +5 -5
  21. package/dist/cronjob/CronjobController.mjs +5 -5
  22. package/dist/cronjob/index.js +5 -5
  23. package/dist/cronjob/index.mjs +5 -5
  24. package/dist/index.js +6 -6
  25. package/dist/index.mjs +5 -5
  26. package/dist/interface/SnapInterfaceController.js +3 -3
  27. package/dist/interface/SnapInterfaceController.mjs +2 -2
  28. package/dist/interface/index.js +3 -3
  29. package/dist/interface/index.mjs +2 -2
  30. package/dist/interface/utils.js +2 -2
  31. package/dist/interface/utils.mjs +1 -1
  32. package/dist/node.js +6 -6
  33. package/dist/node.mjs +5 -5
  34. package/dist/react-native.js +6 -6
  35. package/dist/react-native.mjs +5 -5
  36. package/dist/services/browser.js +2 -2
  37. package/dist/services/browser.mjs +1 -1
  38. package/dist/services/index.js +2 -2
  39. package/dist/services/index.mjs +1 -1
  40. package/dist/services/node-js/NodeProcessExecutionService.js +1 -1
  41. package/dist/services/node-js/NodeProcessExecutionService.mjs +1 -1
  42. package/dist/services/node-js/NodeThreadExecutionService.js +1 -1
  43. package/dist/services/node-js/NodeThreadExecutionService.mjs +1 -1
  44. package/dist/services/node-js/index.js +1 -1
  45. package/dist/services/node-js/index.mjs +1 -1
  46. package/dist/services/node.js +2 -2
  47. package/dist/services/node.mjs +1 -1
  48. package/dist/services/offscreen/OffscreenExecutionService.js +2 -2
  49. package/dist/services/offscreen/OffscreenExecutionService.mjs +1 -1
  50. package/dist/services/offscreen/index.js +2 -2
  51. package/dist/services/offscreen/index.mjs +1 -1
  52. package/dist/services/react-native.js +2 -2
  53. package/dist/services/react-native.mjs +1 -1
  54. package/dist/snaps/SnapController.js +3 -3
  55. package/dist/snaps/SnapController.mjs +2 -2
  56. package/dist/snaps/constants.js +4 -2
  57. package/dist/snaps/constants.mjs +5 -3
  58. package/dist/snaps/index.js +3 -3
  59. package/dist/snaps/index.mjs +2 -2
  60. package/dist/tsconfig.build.tsbuildinfo +1 -1
  61. package/dist/types/interface/utils.d.ts +2 -3
  62. package/dist/types/services/offscreen/OffscreenExecutionService.d.ts +8 -9
  63. package/dist/types/snaps/constants.d.ts +6 -0
  64. package/package.json +11 -11
  65. package/dist/chunk-3OJFF5CK.mjs +0 -72
  66. package/dist/chunk-3OJFF5CK.mjs.map +0 -1
  67. package/dist/chunk-5YBORD3A.js.map +0 -1
  68. package/dist/chunk-HK4OAMJT.js +0 -72
  69. package/dist/chunk-HK4OAMJT.js.map +0 -1
  70. package/dist/chunk-IKD6PUV7.js.map +0 -1
  71. package/dist/chunk-TII2PO6O.js +0 -100
  72. package/dist/chunk-TII2PO6O.js.map +0 -1
  73. package/dist/chunk-TSPPQQHW.mjs.map +0 -1
  74. package/dist/chunk-VSDMYMJK.mjs +0 -100
  75. package/dist/chunk-VSDMYMJK.mjs.map +0 -1
  76. /package/dist/{chunk-LLA2BJYO.js.map → chunk-BUHS4M6F.js.map} +0 -0
  77. /package/dist/{chunk-TMJA2PSY.mjs.map → chunk-WP3DAIFM.mjs.map} +0 -0
package/CHANGELOG.md CHANGED
@@ -6,6 +6,21 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [9.1.0]
10
+ ### Added
11
+ - Add `Checkbox` component ([#2501](https://github.com/MetaMask/snaps/pull/2501))
12
+ - Add `FileInput` component ([#2469](https://github.com/MetaMask/snaps/pull/2469))
13
+ - Support additional components inside forms ([#2497](https://github.com/MetaMask/snaps/pull/2497))
14
+
15
+ ## [9.0.0]
16
+ ### Changed
17
+ - **BREAKING:** Defer creation of offscreen document in `OffscreenExecutionService` ([#2473](https://github.com/MetaMask/snaps/pull/2473))
18
+ - Update `onNameLookup` response to include `domainName` ([#2484](https://github.com/MetaMask/snaps/pull/2484))
19
+ - Bump MetaMask dependencies ([#2460](https://github.com/MetaMask/snaps/pull/2460))
20
+
21
+ ### Fixed
22
+ - Properly decrypt legacy state blobs ([#2472](https://github.com/MetaMask/snaps/pull/2472))
23
+
9
24
  ## [8.4.0]
10
25
  ### Added
11
26
  - Add `hidden` flag for preinstalled Snaps ([#2463](https://github.com/MetaMask/snaps/pull/2463))
@@ -288,7 +303,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
288
303
  - The version of the package no longer needs to match the version of all other
289
304
  MetaMask Snaps packages.
290
305
 
291
- [Unreleased]: https://github.com/MetaMask/snaps/compare/@metamask/snaps-controllers@8.4.0...HEAD
306
+ [Unreleased]: https://github.com/MetaMask/snaps/compare/@metamask/snaps-controllers@9.1.0...HEAD
307
+ [9.1.0]: https://github.com/MetaMask/snaps/compare/@metamask/snaps-controllers@9.0.0...@metamask/snaps-controllers@9.1.0
308
+ [9.0.0]: https://github.com/MetaMask/snaps/compare/@metamask/snaps-controllers@8.4.0...@metamask/snaps-controllers@9.0.0
292
309
  [8.4.0]: https://github.com/MetaMask/snaps/compare/@metamask/snaps-controllers@8.3.1...@metamask/snaps-controllers@8.4.0
293
310
  [8.3.1]: https://github.com/MetaMask/snaps/compare/@metamask/snaps-controllers@8.3.0...@metamask/snaps-controllers@8.3.1
294
311
  [8.3.0]: https://github.com/MetaMask/snaps/compare/@metamask/snaps-controllers@8.2.0...@metamask/snaps-controllers@8.3.0
@@ -0,0 +1,100 @@
1
+ // src/interface/utils.ts
2
+ import { assert } from "@metamask/snaps-sdk";
3
+ import { isJSXElementUnsafe } from "@metamask/snaps-sdk/jsx";
4
+ import {
5
+ getJsonSizeUnsafe,
6
+ getJsxChildren,
7
+ getJsxElementFromComponent,
8
+ walkJsx
9
+ } from "@metamask/snaps-utils";
10
+ function getJsxInterface(component) {
11
+ if (isJSXElementUnsafe(component)) {
12
+ return component;
13
+ }
14
+ return getJsxElementFromComponent(component);
15
+ }
16
+ function assertNameIsUnique(state, name) {
17
+ assert(
18
+ state[name] === void 0,
19
+ `Duplicate component names are not allowed, found multiple instances of: "${name}".`
20
+ );
21
+ }
22
+ function constructComponentSpecificDefaultState(element) {
23
+ switch (element.type) {
24
+ case "Dropdown": {
25
+ const children = getJsxChildren(element);
26
+ return children[0]?.props.value;
27
+ }
28
+ case "Checkbox":
29
+ return false;
30
+ default:
31
+ return null;
32
+ }
33
+ }
34
+ function getComponentStateValue(element) {
35
+ switch (element.type) {
36
+ case "Checkbox":
37
+ return element.props.checked;
38
+ default:
39
+ return element.props.value;
40
+ }
41
+ }
42
+ function constructInputState(oldState, element, form) {
43
+ const oldStateUnwrapped = form ? oldState[form] : oldState;
44
+ const oldInputState = oldStateUnwrapped?.[element.props.name];
45
+ if (element.type === "FileInput") {
46
+ return oldInputState ?? null;
47
+ }
48
+ return getComponentStateValue(element) ?? oldInputState ?? constructComponentSpecificDefaultState(element) ?? null;
49
+ }
50
+ function constructState(oldState, rootComponent) {
51
+ const newState = {};
52
+ const formStack = [];
53
+ walkJsx(rootComponent, (component, depth) => {
54
+ let currentForm = formStack[formStack.length - 1];
55
+ if (currentForm && depth <= currentForm.depth) {
56
+ formStack.pop();
57
+ currentForm = formStack[formStack.length - 1];
58
+ }
59
+ if (component.type === "Form") {
60
+ assertNameIsUnique(newState, component.props.name);
61
+ formStack.push({ name: component.props.name, depth });
62
+ newState[component.props.name] = {};
63
+ return;
64
+ }
65
+ if (currentForm && (component.type === "Input" || component.type === "Dropdown" || component.type === "FileInput" || component.type === "Checkbox")) {
66
+ const formState = newState[currentForm.name];
67
+ assertNameIsUnique(formState, component.props.name);
68
+ formState[component.props.name] = constructInputState(
69
+ oldState,
70
+ component,
71
+ currentForm.name
72
+ );
73
+ return;
74
+ }
75
+ if (component.type === "Input" || component.type === "Dropdown" || component.type === "FileInput" || component.type === "Checkbox") {
76
+ assertNameIsUnique(newState, component.props.name);
77
+ newState[component.props.name] = constructInputState(oldState, component);
78
+ }
79
+ });
80
+ return newState;
81
+ }
82
+ var MAX_CONTEXT_SIZE = 1e6;
83
+ function validateInterfaceContext(context) {
84
+ if (!context) {
85
+ return;
86
+ }
87
+ const size = getJsonSizeUnsafe(context);
88
+ assert(
89
+ size <= MAX_CONTEXT_SIZE,
90
+ `A Snap interface context may not be larger than ${MAX_CONTEXT_SIZE / 1e6} MB.`
91
+ );
92
+ }
93
+
94
+ export {
95
+ getJsxInterface,
96
+ assertNameIsUnique,
97
+ constructState,
98
+ validateInterfaceContext
99
+ };
100
+ //# sourceMappingURL=chunk-3T6W5VI2.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/interface/utils.ts"],"sourcesContent":["import { assert } from '@metamask/snaps-sdk';\nimport type {\n FormState,\n InterfaceState,\n ComponentOrElement,\n InterfaceContext,\n State,\n} from '@metamask/snaps-sdk';\nimport type {\n DropdownElement,\n InputElement,\n JSXElement,\n OptionElement,\n FileInputElement,\n CheckboxElement,\n} from '@metamask/snaps-sdk/jsx';\nimport { isJSXElementUnsafe } from '@metamask/snaps-sdk/jsx';\nimport {\n getJsonSizeUnsafe,\n getJsxChildren,\n getJsxElementFromComponent,\n walkJsx,\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 default state for a component.\n *\n * This function is meant to be used inside constructInputState to account\n * for component specific defaults and will not override the component value or existing form state.\n *\n * @param element - The input element.\n * @returns The default state for the specific component, if any.\n */\nfunction constructComponentSpecificDefaultState(\n element: InputElement | DropdownElement | CheckboxElement,\n) {\n switch (element.type) {\n case 'Dropdown': {\n const children = getJsxChildren(element) as OptionElement[];\n return children[0]?.props.value;\n }\n\n case 'Checkbox':\n return false;\n\n default:\n return null;\n }\n}\n\n/**\n * Get the state value for a stateful component.\n *\n * Most components store the state value as a `value` prop.\n * This function exists to account for components where that isn't the case.\n *\n * @param element - The input element.\n * @returns The state value for a given component.\n */\nfunction getComponentStateValue(\n element: InputElement | DropdownElement | CheckboxElement,\n) {\n switch (element.type) {\n case 'Checkbox':\n return element.props.checked;\n\n default:\n return element.props.value;\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 * @param form - An optional form that the input is enclosed in.\n * @returns The input state.\n */\nfunction constructInputState(\n oldState: InterfaceState,\n element: InputElement | DropdownElement | FileInputElement | CheckboxElement,\n form?: string,\n) {\n const oldStateUnwrapped = form ? (oldState[form] as FormState) : oldState;\n const oldInputState = oldStateUnwrapped?.[element.props.name] as State;\n\n if (element.type === 'FileInput') {\n return oldInputState ?? null;\n }\n\n return (\n getComponentStateValue(element) ??\n oldInputState ??\n constructComponentSpecificDefaultState(element) ??\n null\n );\n}\n\n/**\n * Construct the interface state for a given component tree.\n *\n * @param oldState - The previous state.\n * @param rootComponent - The UI component to construct state from.\n * @returns The interface state of the passed component.\n */\nexport function constructState(\n oldState: InterfaceState,\n rootComponent: JSXElement,\n): InterfaceState {\n const newState: InterfaceState = {};\n\n // Stack containing the forms we have visited and at which depth\n const formStack: { name: string; depth: number }[] = [];\n\n walkJsx(rootComponent, (component, depth) => {\n let currentForm = formStack[formStack.length - 1];\n\n // Pop the current form of the stack once we leave its depth.\n if (currentForm && depth <= currentForm.depth) {\n formStack.pop();\n currentForm = formStack[formStack.length - 1];\n }\n\n if (component.type === 'Form') {\n assertNameIsUnique(newState, component.props.name);\n formStack.push({ name: component.props.name, depth });\n newState[component.props.name] = {};\n return;\n }\n\n // Stateful components inside a form\n if (\n currentForm &&\n (component.type === 'Input' ||\n component.type === 'Dropdown' ||\n component.type === 'FileInput' ||\n component.type === 'Checkbox')\n ) {\n const formState = newState[currentForm.name] as FormState;\n assertNameIsUnique(formState, component.props.name);\n formState[component.props.name] = constructInputState(\n oldState,\n component,\n currentForm.name,\n );\n return;\n }\n\n // Stateful components outside a form\n if (\n component.type === 'Input' ||\n component.type === 'Dropdown' ||\n component.type === 'FileInput' ||\n component.type === 'Checkbox'\n ) {\n assertNameIsUnique(newState, component.props.name);\n newState[component.props.name] = constructInputState(oldState, component);\n }\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"],"mappings":";AAAA,SAAS,cAAc;AAgBvB,SAAS,0BAA0B;AACnC;AAAA,EACE;AAAA,EACA;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;AAWA,SAAS,uCACP,SACA;AACA,UAAQ,QAAQ,MAAM;AAAA,IACpB,KAAK,YAAY;AACf,YAAM,WAAW,eAAe,OAAO;AACvC,aAAO,SAAS,CAAC,GAAG,MAAM;AAAA,IAC5B;AAAA,IAEA,KAAK;AACH,aAAO;AAAA,IAET;AACE,aAAO;AAAA,EACX;AACF;AAWA,SAAS,uBACP,SACA;AACA,UAAQ,QAAQ,MAAM;AAAA,IACpB,KAAK;AACH,aAAO,QAAQ,MAAM;AAAA,IAEvB;AACE,aAAO,QAAQ,MAAM;AAAA,EACzB;AACF;AAUA,SAAS,oBACP,UACA,SACA,MACA;AACA,QAAM,oBAAoB,OAAQ,SAAS,IAAI,IAAkB;AACjE,QAAM,gBAAgB,oBAAoB,QAAQ,MAAM,IAAI;AAE5D,MAAI,QAAQ,SAAS,aAAa;AAChC,WAAO,iBAAiB;AAAA,EAC1B;AAEA,SACE,uBAAuB,OAAO,KAC9B,iBACA,uCAAuC,OAAO,KAC9C;AAEJ;AASO,SAAS,eACd,UACA,eACgB;AAChB,QAAM,WAA2B,CAAC;AAGlC,QAAM,YAA+C,CAAC;AAEtD,UAAQ,eAAe,CAAC,WAAW,UAAU;AAC3C,QAAI,cAAc,UAAU,UAAU,SAAS,CAAC;AAGhD,QAAI,eAAe,SAAS,YAAY,OAAO;AAC7C,gBAAU,IAAI;AACd,oBAAc,UAAU,UAAU,SAAS,CAAC;AAAA,IAC9C;AAEA,QAAI,UAAU,SAAS,QAAQ;AAC7B,yBAAmB,UAAU,UAAU,MAAM,IAAI;AACjD,gBAAU,KAAK,EAAE,MAAM,UAAU,MAAM,MAAM,MAAM,CAAC;AACpD,eAAS,UAAU,MAAM,IAAI,IAAI,CAAC;AAClC;AAAA,IACF;AAGA,QACE,gBACC,UAAU,SAAS,WAClB,UAAU,SAAS,cACnB,UAAU,SAAS,eACnB,UAAU,SAAS,aACrB;AACA,YAAM,YAAY,SAAS,YAAY,IAAI;AAC3C,yBAAmB,WAAW,UAAU,MAAM,IAAI;AAClD,gBAAU,UAAU,MAAM,IAAI,IAAI;AAAA,QAChC;AAAA,QACA;AAAA,QACA,YAAY;AAAA,MACd;AACA;AAAA,IACF;AAGA,QACE,UAAU,SAAS,WACnB,UAAU,SAAS,cACnB,UAAU,SAAS,eACnB,UAAU,SAAS,YACnB;AACA,yBAAmB,UAAU,UAAU,MAAM,IAAI;AACjD,eAAS,UAAU,MAAM,IAAI,IAAI,oBAAoB,UAAU,SAAS;AAAA,IAC1E;AAAA,EACF,CAAC;AAED,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;","names":[]}
@@ -12,8 +12,15 @@ var ALLOWED_PERMISSIONS = Object.freeze([
12
12
  SnapEndowments.TransactionInsight,
13
13
  SnapEndowments.SignatureInsight
14
14
  ]);
15
+ var LEGACY_ENCRYPTION_KEY_DERIVATION_OPTIONS = {
16
+ algorithm: "PBKDF2",
17
+ params: {
18
+ iterations: 1e4
19
+ }
20
+ };
15
21
 
16
22
  export {
17
- ALLOWED_PERMISSIONS
23
+ ALLOWED_PERMISSIONS,
24
+ LEGACY_ENCRYPTION_KEY_DERIVATION_OPTIONS
18
25
  };
19
- //# sourceMappingURL=chunk-YIQM6ZKA.mjs.map
26
+ //# sourceMappingURL=chunk-4M2FX2AT.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/snaps/constants.ts"],"sourcesContent":["import { SnapEndowments } from '@metamask/snaps-rpc-methods';\n\n// These permissions are allowed without being on the allowlist.\nexport const ALLOWED_PERMISSIONS = Object.freeze([\n 'snap_dialog',\n 'snap_manageState',\n 'snap_notify',\n 'snap_getLocale',\n SnapEndowments.Cronjob,\n SnapEndowments.HomePage,\n SnapEndowments.LifecycleHooks,\n SnapEndowments.EthereumProvider,\n SnapEndowments.TransactionInsight,\n SnapEndowments.SignatureInsight,\n]);\n"],"mappings":";AAAA,SAAS,sBAAsB;AAGxB,IAAM,sBAAsB,OAAO,OAAO;AAAA,EAC/C;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,eAAe;AAAA,EACf,eAAe;AAAA,EACf,eAAe;AAAA,EACf,eAAe;AAAA,EACf,eAAe;AAAA,EACf,eAAe;AACjB,CAAC;","names":[]}
1
+ {"version":3,"sources":["../src/snaps/constants.ts"],"sourcesContent":["import { SnapEndowments } from '@metamask/snaps-rpc-methods';\n\n// These permissions are allowed without being on the allowlist.\nexport const ALLOWED_PERMISSIONS = Object.freeze([\n 'snap_dialog',\n 'snap_manageState',\n 'snap_notify',\n 'snap_getLocale',\n SnapEndowments.Cronjob,\n SnapEndowments.HomePage,\n SnapEndowments.LifecycleHooks,\n SnapEndowments.EthereumProvider,\n SnapEndowments.TransactionInsight,\n SnapEndowments.SignatureInsight,\n]);\n\nexport const LEGACY_ENCRYPTION_KEY_DERIVATION_OPTIONS = {\n algorithm: 'PBKDF2' as const,\n params: {\n iterations: 10_000,\n },\n};\n"],"mappings":";AAAA,SAAS,sBAAsB;AAGxB,IAAM,sBAAsB,OAAO,OAAO;AAAA,EAC/C;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,eAAe;AAAA,EACf,eAAe;AAAA,EACf,eAAe;AAAA,EACf,eAAe;AAAA,EACf,eAAe;AAAA,EACf,eAAe;AACjB,CAAC;AAEM,IAAM,2CAA2C;AAAA,EACtD,WAAW;AAAA,EACX,QAAQ;AAAA,IACN,YAAY;AAAA,EACd;AACF;","names":[]}
@@ -0,0 +1,58 @@
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true});
2
+
3
+ var _chunkKH72WRHRjs = require('./chunk-KH72WRHR.js');
4
+
5
+
6
+
7
+
8
+ var _chunkEXN2TFDJjs = require('./chunk-EXN2TFDJ.js');
9
+
10
+ // src/services/offscreen/OffscreenExecutionService.ts
11
+ var _postmessagestream = require('@metamask/post-message-stream');
12
+ var _offscreenPromise;
13
+ var OffscreenExecutionService = class extends _chunkKH72WRHRjs.ProxyExecutionService {
14
+ /**
15
+ * Create a new offscreen execution service.
16
+ *
17
+ * @param args - The constructor arguments.
18
+ * @param args.messenger - The messenger to use for communication with the
19
+ * `SnapController`.
20
+ * @param args.setupSnapProvider - The function to use to set up the snap
21
+ * provider.
22
+ * @param args.offscreenPromise - A promise that resolves when the offscreen
23
+ * environment is ready.
24
+ */
25
+ constructor({
26
+ messenger,
27
+ setupSnapProvider,
28
+ offscreenPromise
29
+ }) {
30
+ super({
31
+ messenger,
32
+ setupSnapProvider,
33
+ stream: new (0, _postmessagestream.BrowserRuntimePostMessageStream)({
34
+ name: "parent",
35
+ target: "child"
36
+ })
37
+ });
38
+ _chunkEXN2TFDJjs.__privateAdd.call(void 0, this, _offscreenPromise, void 0);
39
+ _chunkEXN2TFDJjs.__privateSet.call(void 0, this, _offscreenPromise, offscreenPromise);
40
+ }
41
+ /**
42
+ * Create a new stream for the given job ID. This will wait for the offscreen
43
+ * environment to be ready before creating the stream.
44
+ *
45
+ * @param jobId - The job ID to create a stream for.
46
+ * @returns The stream for the given job ID.
47
+ */
48
+ async initEnvStream(jobId) {
49
+ await _chunkEXN2TFDJjs.__privateGet.call(void 0, this, _offscreenPromise);
50
+ return await super.initEnvStream(jobId);
51
+ }
52
+ };
53
+ _offscreenPromise = new WeakMap();
54
+
55
+
56
+
57
+ exports.OffscreenExecutionService = OffscreenExecutionService;
58
+ //# sourceMappingURL=chunk-6ERB63FH.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/services/offscreen/OffscreenExecutionService.ts"],"names":[],"mappings":";;;;;;;;;;AAAA,SAAS,uCAAuC;AAAhD;AASO,IAAM,4BAAN,cAAwC,sBAAsB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcnE,YAAY;AAAA,IACV;AAAA,IACA;AAAA,IACA;AAAA,EACF,GAA6C;AAC3C,UAAM;AAAA,MACJ;AAAA,MACA;AAAA,MACA,QAAQ,IAAI,gCAAgC;AAAA,QAC1C,MAAM;AAAA,QACN,QAAQ;AAAA,MACV,CAAC;AAAA,IACH,CAAC;AAzBH,uBAAS,mBAAT;AA2BE,uBAAK,mBAAoB;AAAA,EAC3B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAgB,cAAc,OAAe;AAC3C,UAAM,mBAAK;AAEX,WAAO,MAAM,MAAM,cAAc,KAAK;AAAA,EACxC;AACF;AA1CW","sourcesContent":["import { BrowserRuntimePostMessageStream } from '@metamask/post-message-stream';\n\nimport type { ExecutionServiceArgs } from '../AbstractExecutionService';\nimport { ProxyExecutionService } from '../proxy/ProxyExecutionService';\n\ntype OffscreenExecutionEnvironmentServiceArgs = {\n offscreenPromise: Promise<unknown>;\n} & ExecutionServiceArgs;\n\nexport class OffscreenExecutionService extends ProxyExecutionService {\n readonly #offscreenPromise: Promise<unknown>;\n\n /**\n * Create a new offscreen execution service.\n *\n * @param args - The constructor arguments.\n * @param args.messenger - The messenger to use for communication with the\n * `SnapController`.\n * @param args.setupSnapProvider - The function to use to set up the snap\n * provider.\n * @param args.offscreenPromise - A promise that resolves when the offscreen\n * environment is ready.\n */\n constructor({\n messenger,\n setupSnapProvider,\n offscreenPromise,\n }: OffscreenExecutionEnvironmentServiceArgs) {\n super({\n messenger,\n setupSnapProvider,\n stream: new BrowserRuntimePostMessageStream({\n name: 'parent',\n target: 'child',\n }),\n });\n\n this.#offscreenPromise = offscreenPromise;\n }\n\n /**\n * Create a new stream for the given job ID. This will wait for the offscreen\n * environment to be ready before creating the stream.\n *\n * @param jobId - The job ID to create a stream for.\n * @returns The stream for the given job ID.\n */\n protected async initEnvStream(jobId: string) {\n await this.#offscreenPromise;\n\n return await super.initEnvStream(jobId);\n }\n}\n"]}
@@ -2,7 +2,7 @@
2
2
 
3
3
 
4
4
 
5
- var _chunkTII2PO6Ojs = require('./chunk-TII2PO6O.js');
5
+ var _chunkH7TB7I6Zjs = require('./chunk-H7TB7I6Z.js');
6
6
 
7
7
 
8
8
 
@@ -67,11 +67,11 @@ var SnapInterfaceController = class extends _basecontroller.BaseController {
67
67
  * @returns The newly interface id.
68
68
  */
69
69
  async createInterface(snapId, content, context) {
70
- const element = _chunkTII2PO6Ojs.getJsxInterface.call(void 0, content);
70
+ const element = _chunkH7TB7I6Zjs.getJsxInterface.call(void 0, content);
71
71
  await _chunkEXN2TFDJjs.__privateMethod.call(void 0, this, _validateContent, validateContent_fn).call(this, element);
72
- _chunkTII2PO6Ojs.validateInterfaceContext.call(void 0, context);
72
+ _chunkH7TB7I6Zjs.validateInterfaceContext.call(void 0, context);
73
73
  const id = _nanoid.nanoid.call(void 0, );
74
- const componentState = _chunkTII2PO6Ojs.constructState.call(void 0, {}, element);
74
+ const componentState = _chunkH7TB7I6Zjs.constructState.call(void 0, {}, element);
75
75
  this.update((draftState) => {
76
76
  draftState.interfaces[id] = {
77
77
  snapId,
@@ -102,10 +102,10 @@ var SnapInterfaceController = class extends _basecontroller.BaseController {
102
102
  */
103
103
  async updateInterface(snapId, id, content) {
104
104
  _chunkEXN2TFDJjs.__privateMethod.call(void 0, this, _validateArgs, validateArgs_fn).call(this, snapId, id);
105
- const element = _chunkTII2PO6Ojs.getJsxInterface.call(void 0, content);
105
+ const element = _chunkH7TB7I6Zjs.getJsxInterface.call(void 0, content);
106
106
  await _chunkEXN2TFDJjs.__privateMethod.call(void 0, this, _validateContent, validateContent_fn).call(this, element);
107
107
  const oldState = this.state.interfaces[id].state;
108
- const newState = _chunkTII2PO6Ojs.constructState.call(void 0, oldState, element);
108
+ const newState = _chunkH7TB7I6Zjs.constructState.call(void 0, oldState, element);
109
109
  this.update((draftState) => {
110
110
  draftState.interfaces[id].state = newState;
111
111
  draftState.interfaces[id].content = element;
@@ -190,4 +190,4 @@ validateContent_fn = async function(element) {
190
190
 
191
191
 
192
192
  exports.SnapInterfaceController = SnapInterfaceController;
193
- //# sourceMappingURL=chunk-LLA2BJYO.js.map
193
+ //# sourceMappingURL=chunk-BUHS4M6F.js.map
@@ -0,0 +1,58 @@
1
+ import {
2
+ ProxyExecutionService
3
+ } from "./chunk-3A72M4GC.mjs";
4
+ import {
5
+ __privateAdd,
6
+ __privateGet,
7
+ __privateSet
8
+ } from "./chunk-YRZVIDCF.mjs";
9
+
10
+ // src/services/offscreen/OffscreenExecutionService.ts
11
+ import { BrowserRuntimePostMessageStream } from "@metamask/post-message-stream";
12
+ var _offscreenPromise;
13
+ var OffscreenExecutionService = class extends ProxyExecutionService {
14
+ /**
15
+ * Create a new offscreen execution service.
16
+ *
17
+ * @param args - The constructor arguments.
18
+ * @param args.messenger - The messenger to use for communication with the
19
+ * `SnapController`.
20
+ * @param args.setupSnapProvider - The function to use to set up the snap
21
+ * provider.
22
+ * @param args.offscreenPromise - A promise that resolves when the offscreen
23
+ * environment is ready.
24
+ */
25
+ constructor({
26
+ messenger,
27
+ setupSnapProvider,
28
+ offscreenPromise
29
+ }) {
30
+ super({
31
+ messenger,
32
+ setupSnapProvider,
33
+ stream: new BrowserRuntimePostMessageStream({
34
+ name: "parent",
35
+ target: "child"
36
+ })
37
+ });
38
+ __privateAdd(this, _offscreenPromise, void 0);
39
+ __privateSet(this, _offscreenPromise, offscreenPromise);
40
+ }
41
+ /**
42
+ * Create a new stream for the given job ID. This will wait for the offscreen
43
+ * environment to be ready before creating the stream.
44
+ *
45
+ * @param jobId - The job ID to create a stream for.
46
+ * @returns The stream for the given job ID.
47
+ */
48
+ async initEnvStream(jobId) {
49
+ await __privateGet(this, _offscreenPromise);
50
+ return await super.initEnvStream(jobId);
51
+ }
52
+ };
53
+ _offscreenPromise = new WeakMap();
54
+
55
+ export {
56
+ OffscreenExecutionService
57
+ };
58
+ //# sourceMappingURL=chunk-CIFVYFJW.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/services/offscreen/OffscreenExecutionService.ts"],"sourcesContent":["import { BrowserRuntimePostMessageStream } from '@metamask/post-message-stream';\n\nimport type { ExecutionServiceArgs } from '../AbstractExecutionService';\nimport { ProxyExecutionService } from '../proxy/ProxyExecutionService';\n\ntype OffscreenExecutionEnvironmentServiceArgs = {\n offscreenPromise: Promise<unknown>;\n} & ExecutionServiceArgs;\n\nexport class OffscreenExecutionService extends ProxyExecutionService {\n readonly #offscreenPromise: Promise<unknown>;\n\n /**\n * Create a new offscreen execution service.\n *\n * @param args - The constructor arguments.\n * @param args.messenger - The messenger to use for communication with the\n * `SnapController`.\n * @param args.setupSnapProvider - The function to use to set up the snap\n * provider.\n * @param args.offscreenPromise - A promise that resolves when the offscreen\n * environment is ready.\n */\n constructor({\n messenger,\n setupSnapProvider,\n offscreenPromise,\n }: OffscreenExecutionEnvironmentServiceArgs) {\n super({\n messenger,\n setupSnapProvider,\n stream: new BrowserRuntimePostMessageStream({\n name: 'parent',\n target: 'child',\n }),\n });\n\n this.#offscreenPromise = offscreenPromise;\n }\n\n /**\n * Create a new stream for the given job ID. This will wait for the offscreen\n * environment to be ready before creating the stream.\n *\n * @param jobId - The job ID to create a stream for.\n * @returns The stream for the given job ID.\n */\n protected async initEnvStream(jobId: string) {\n await this.#offscreenPromise;\n\n return await super.initEnvStream(jobId);\n }\n}\n"],"mappings":";;;;;;;;;;AAAA,SAAS,uCAAuC;AAAhD;AASO,IAAM,4BAAN,cAAwC,sBAAsB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcnE,YAAY;AAAA,IACV;AAAA,IACA;AAAA,IACA;AAAA,EACF,GAA6C;AAC3C,UAAM;AAAA,MACJ;AAAA,MACA;AAAA,MACA,QAAQ,IAAI,gCAAgC;AAAA,QAC1C,MAAM;AAAA,QACN,QAAQ;AAAA,MACV,CAAC;AAAA,IACH,CAAC;AAzBH,uBAAS,mBAAT;AA2BE,uBAAK,mBAAoB;AAAA,EAC3B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAgB,cAAc,OAAe;AAC3C,UAAM,mBAAK;AAEX,WAAO,MAAM,MAAM,cAAc,KAAK;AAAA,EACxC;AACF;AA1CW;","names":[]}
@@ -0,0 +1,100 @@
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true});// src/interface/utils.ts
2
+ var _snapssdk = require('@metamask/snaps-sdk');
3
+ var _jsx = require('@metamask/snaps-sdk/jsx');
4
+
5
+
6
+
7
+
8
+
9
+ var _snapsutils = require('@metamask/snaps-utils');
10
+ function getJsxInterface(component) {
11
+ if (_jsx.isJSXElementUnsafe.call(void 0, component)) {
12
+ return component;
13
+ }
14
+ return _snapsutils.getJsxElementFromComponent.call(void 0, component);
15
+ }
16
+ function assertNameIsUnique(state, name) {
17
+ _snapssdk.assert.call(void 0,
18
+ state[name] === void 0,
19
+ `Duplicate component names are not allowed, found multiple instances of: "${name}".`
20
+ );
21
+ }
22
+ function constructComponentSpecificDefaultState(element) {
23
+ switch (element.type) {
24
+ case "Dropdown": {
25
+ const children = _snapsutils.getJsxChildren.call(void 0, element);
26
+ return children[0]?.props.value;
27
+ }
28
+ case "Checkbox":
29
+ return false;
30
+ default:
31
+ return null;
32
+ }
33
+ }
34
+ function getComponentStateValue(element) {
35
+ switch (element.type) {
36
+ case "Checkbox":
37
+ return element.props.checked;
38
+ default:
39
+ return element.props.value;
40
+ }
41
+ }
42
+ function constructInputState(oldState, element, form) {
43
+ const oldStateUnwrapped = form ? oldState[form] : oldState;
44
+ const oldInputState = oldStateUnwrapped?.[element.props.name];
45
+ if (element.type === "FileInput") {
46
+ return oldInputState ?? null;
47
+ }
48
+ return getComponentStateValue(element) ?? oldInputState ?? constructComponentSpecificDefaultState(element) ?? null;
49
+ }
50
+ function constructState(oldState, rootComponent) {
51
+ const newState = {};
52
+ const formStack = [];
53
+ _snapsutils.walkJsx.call(void 0, rootComponent, (component, depth) => {
54
+ let currentForm = formStack[formStack.length - 1];
55
+ if (currentForm && depth <= currentForm.depth) {
56
+ formStack.pop();
57
+ currentForm = formStack[formStack.length - 1];
58
+ }
59
+ if (component.type === "Form") {
60
+ assertNameIsUnique(newState, component.props.name);
61
+ formStack.push({ name: component.props.name, depth });
62
+ newState[component.props.name] = {};
63
+ return;
64
+ }
65
+ if (currentForm && (component.type === "Input" || component.type === "Dropdown" || component.type === "FileInput" || component.type === "Checkbox")) {
66
+ const formState = newState[currentForm.name];
67
+ assertNameIsUnique(formState, component.props.name);
68
+ formState[component.props.name] = constructInputState(
69
+ oldState,
70
+ component,
71
+ currentForm.name
72
+ );
73
+ return;
74
+ }
75
+ if (component.type === "Input" || component.type === "Dropdown" || component.type === "FileInput" || component.type === "Checkbox") {
76
+ assertNameIsUnique(newState, component.props.name);
77
+ newState[component.props.name] = constructInputState(oldState, component);
78
+ }
79
+ });
80
+ return newState;
81
+ }
82
+ var MAX_CONTEXT_SIZE = 1e6;
83
+ function validateInterfaceContext(context) {
84
+ if (!context) {
85
+ return;
86
+ }
87
+ const size = _snapsutils.getJsonSizeUnsafe.call(void 0, context);
88
+ _snapssdk.assert.call(void 0,
89
+ size <= MAX_CONTEXT_SIZE,
90
+ `A Snap interface context may not be larger than ${MAX_CONTEXT_SIZE / 1e6} MB.`
91
+ );
92
+ }
93
+
94
+
95
+
96
+
97
+
98
+
99
+ exports.getJsxInterface = getJsxInterface; exports.assertNameIsUnique = assertNameIsUnique; exports.constructState = constructState; exports.validateInterfaceContext = validateInterfaceContext;
100
+ //# sourceMappingURL=chunk-H7TB7I6Z.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/interface/utils.ts"],"names":[],"mappings":";AAAA,SAAS,cAAc;AAgBvB,SAAS,0BAA0B;AACnC;AAAA,EACE;AAAA,EACA;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;AAWA,SAAS,uCACP,SACA;AACA,UAAQ,QAAQ,MAAM;AAAA,IACpB,KAAK,YAAY;AACf,YAAM,WAAW,eAAe,OAAO;AACvC,aAAO,SAAS,CAAC,GAAG,MAAM;AAAA,IAC5B;AAAA,IAEA,KAAK;AACH,aAAO;AAAA,IAET;AACE,aAAO;AAAA,EACX;AACF;AAWA,SAAS,uBACP,SACA;AACA,UAAQ,QAAQ,MAAM;AAAA,IACpB,KAAK;AACH,aAAO,QAAQ,MAAM;AAAA,IAEvB;AACE,aAAO,QAAQ,MAAM;AAAA,EACzB;AACF;AAUA,SAAS,oBACP,UACA,SACA,MACA;AACA,QAAM,oBAAoB,OAAQ,SAAS,IAAI,IAAkB;AACjE,QAAM,gBAAgB,oBAAoB,QAAQ,MAAM,IAAI;AAE5D,MAAI,QAAQ,SAAS,aAAa;AAChC,WAAO,iBAAiB;AAAA,EAC1B;AAEA,SACE,uBAAuB,OAAO,KAC9B,iBACA,uCAAuC,OAAO,KAC9C;AAEJ;AASO,SAAS,eACd,UACA,eACgB;AAChB,QAAM,WAA2B,CAAC;AAGlC,QAAM,YAA+C,CAAC;AAEtD,UAAQ,eAAe,CAAC,WAAW,UAAU;AAC3C,QAAI,cAAc,UAAU,UAAU,SAAS,CAAC;AAGhD,QAAI,eAAe,SAAS,YAAY,OAAO;AAC7C,gBAAU,IAAI;AACd,oBAAc,UAAU,UAAU,SAAS,CAAC;AAAA,IAC9C;AAEA,QAAI,UAAU,SAAS,QAAQ;AAC7B,yBAAmB,UAAU,UAAU,MAAM,IAAI;AACjD,gBAAU,KAAK,EAAE,MAAM,UAAU,MAAM,MAAM,MAAM,CAAC;AACpD,eAAS,UAAU,MAAM,IAAI,IAAI,CAAC;AAClC;AAAA,IACF;AAGA,QACE,gBACC,UAAU,SAAS,WAClB,UAAU,SAAS,cACnB,UAAU,SAAS,eACnB,UAAU,SAAS,aACrB;AACA,YAAM,YAAY,SAAS,YAAY,IAAI;AAC3C,yBAAmB,WAAW,UAAU,MAAM,IAAI;AAClD,gBAAU,UAAU,MAAM,IAAI,IAAI;AAAA,QAChC;AAAA,QACA;AAAA,QACA,YAAY;AAAA,MACd;AACA;AAAA,IACF;AAGA,QACE,UAAU,SAAS,WACnB,UAAU,SAAS,cACnB,UAAU,SAAS,eACnB,UAAU,SAAS,YACnB;AACA,yBAAmB,UAAU,UAAU,MAAM,IAAI;AACjD,eAAS,UAAU,MAAM,IAAI,IAAI,oBAAoB,UAAU,SAAS;AAAA,IAC1E;AAAA,EACF,CAAC;AAED,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 State,\n} from '@metamask/snaps-sdk';\nimport type {\n DropdownElement,\n InputElement,\n JSXElement,\n OptionElement,\n FileInputElement,\n CheckboxElement,\n} from '@metamask/snaps-sdk/jsx';\nimport { isJSXElementUnsafe } from '@metamask/snaps-sdk/jsx';\nimport {\n getJsonSizeUnsafe,\n getJsxChildren,\n getJsxElementFromComponent,\n walkJsx,\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 default state for a component.\n *\n * This function is meant to be used inside constructInputState to account\n * for component specific defaults and will not override the component value or existing form state.\n *\n * @param element - The input element.\n * @returns The default state for the specific component, if any.\n */\nfunction constructComponentSpecificDefaultState(\n element: InputElement | DropdownElement | CheckboxElement,\n) {\n switch (element.type) {\n case 'Dropdown': {\n const children = getJsxChildren(element) as OptionElement[];\n return children[0]?.props.value;\n }\n\n case 'Checkbox':\n return false;\n\n default:\n return null;\n }\n}\n\n/**\n * Get the state value for a stateful component.\n *\n * Most components store the state value as a `value` prop.\n * This function exists to account for components where that isn't the case.\n *\n * @param element - The input element.\n * @returns The state value for a given component.\n */\nfunction getComponentStateValue(\n element: InputElement | DropdownElement | CheckboxElement,\n) {\n switch (element.type) {\n case 'Checkbox':\n return element.props.checked;\n\n default:\n return element.props.value;\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 * @param form - An optional form that the input is enclosed in.\n * @returns The input state.\n */\nfunction constructInputState(\n oldState: InterfaceState,\n element: InputElement | DropdownElement | FileInputElement | CheckboxElement,\n form?: string,\n) {\n const oldStateUnwrapped = form ? (oldState[form] as FormState) : oldState;\n const oldInputState = oldStateUnwrapped?.[element.props.name] as State;\n\n if (element.type === 'FileInput') {\n return oldInputState ?? null;\n }\n\n return (\n getComponentStateValue(element) ??\n oldInputState ??\n constructComponentSpecificDefaultState(element) ??\n null\n );\n}\n\n/**\n * Construct the interface state for a given component tree.\n *\n * @param oldState - The previous state.\n * @param rootComponent - The UI component to construct state from.\n * @returns The interface state of the passed component.\n */\nexport function constructState(\n oldState: InterfaceState,\n rootComponent: JSXElement,\n): InterfaceState {\n const newState: InterfaceState = {};\n\n // Stack containing the forms we have visited and at which depth\n const formStack: { name: string; depth: number }[] = [];\n\n walkJsx(rootComponent, (component, depth) => {\n let currentForm = formStack[formStack.length - 1];\n\n // Pop the current form of the stack once we leave its depth.\n if (currentForm && depth <= currentForm.depth) {\n formStack.pop();\n currentForm = formStack[formStack.length - 1];\n }\n\n if (component.type === 'Form') {\n assertNameIsUnique(newState, component.props.name);\n formStack.push({ name: component.props.name, depth });\n newState[component.props.name] = {};\n return;\n }\n\n // Stateful components inside a form\n if (\n currentForm &&\n (component.type === 'Input' ||\n component.type === 'Dropdown' ||\n component.type === 'FileInput' ||\n component.type === 'Checkbox')\n ) {\n const formState = newState[currentForm.name] as FormState;\n assertNameIsUnique(formState, component.props.name);\n formState[component.props.name] = constructInputState(\n oldState,\n component,\n currentForm.name,\n );\n return;\n }\n\n // Stateful components outside a form\n if (\n component.type === 'Input' ||\n component.type === 'Dropdown' ||\n component.type === 'FileInput' ||\n component.type === 'Checkbox'\n ) {\n assertNameIsUnique(newState, component.props.name);\n newState[component.props.name] = constructInputState(oldState, component);\n }\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"]}
@@ -12,8 +12,15 @@ var ALLOWED_PERMISSIONS = Object.freeze([
12
12
  _snapsrpcmethods.SnapEndowments.TransactionInsight,
13
13
  _snapsrpcmethods.SnapEndowments.SignatureInsight
14
14
  ]);
15
+ var LEGACY_ENCRYPTION_KEY_DERIVATION_OPTIONS = {
16
+ algorithm: "PBKDF2",
17
+ params: {
18
+ iterations: 1e4
19
+ }
20
+ };
15
21
 
16
22
 
17
23
 
18
- exports.ALLOWED_PERMISSIONS = ALLOWED_PERMISSIONS;
19
- //# sourceMappingURL=chunk-5YBORD3A.js.map
24
+
25
+ exports.ALLOWED_PERMISSIONS = ALLOWED_PERMISSIONS; exports.LEGACY_ENCRYPTION_KEY_DERIVATION_OPTIONS = LEGACY_ENCRYPTION_KEY_DERIVATION_OPTIONS;
26
+ //# sourceMappingURL=chunk-JQ54YYLU.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/snaps/constants.ts"],"names":[],"mappings":";AAAA,SAAS,sBAAsB;AAGxB,IAAM,sBAAsB,OAAO,OAAO;AAAA,EAC/C;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,eAAe;AAAA,EACf,eAAe;AAAA,EACf,eAAe;AAAA,EACf,eAAe;AAAA,EACf,eAAe;AAAA,EACf,eAAe;AACjB,CAAC;AAEM,IAAM,2CAA2C;AAAA,EACtD,WAAW;AAAA,EACX,QAAQ;AAAA,IACN,YAAY;AAAA,EACd;AACF","sourcesContent":["import { SnapEndowments } from '@metamask/snaps-rpc-methods';\n\n// These permissions are allowed without being on the allowlist.\nexport const ALLOWED_PERMISSIONS = Object.freeze([\n 'snap_dialog',\n 'snap_manageState',\n 'snap_notify',\n 'snap_getLocale',\n SnapEndowments.Cronjob,\n SnapEndowments.HomePage,\n SnapEndowments.LifecycleHooks,\n SnapEndowments.EthereumProvider,\n SnapEndowments.TransactionInsight,\n SnapEndowments.SignatureInsight,\n]);\n\nexport const LEGACY_ENCRYPTION_KEY_DERIVATION_OPTIONS = {\n algorithm: 'PBKDF2' as const,\n params: {\n iterations: 10_000,\n },\n};\n"]}
@@ -5,8 +5,9 @@ import {
5
5
  RequestQueue
6
6
  } from "./chunk-NC5PBDKD.mjs";
7
7
  import {
8
- ALLOWED_PERMISSIONS
9
- } from "./chunk-YIQM6ZKA.mjs";
8
+ ALLOWED_PERMISSIONS,
9
+ LEGACY_ENCRYPTION_KEY_DERIVATION_OPTIONS
10
+ } from "./chunk-4M2FX2AT.mjs";
10
11
  import {
11
12
  forceStrict,
12
13
  validateMachine
@@ -1806,7 +1807,9 @@ decryptSnapState_fn = async function(snapId, state) {
1806
1807
  snapId,
1807
1808
  salt,
1808
1809
  useCache,
1809
- keyMetadata
1810
+ // When decrypting state we expect key metadata to be present.
1811
+ // If it isn't present, we assume that the Snap state we are decrypting is old enough to use the legacy encryption params.
1812
+ keyMetadata: keyMetadata ?? LEGACY_ENCRYPTION_KEY_DERIVATION_OPTIONS
1810
1813
  });
1811
1814
  const decryptedState = await __privateGet(this, _encryptor).decryptWithKey(key, parsed);
1812
1815
  assert(isValidJson(decryptedState));
@@ -2493,4 +2496,4 @@ export {
2493
2496
  SNAP_APPROVAL_RESULT,
2494
2497
  SnapController
2495
2498
  };
2496
- //# sourceMappingURL=chunk-TSPPQQHW.mjs.map
2499
+ //# sourceMappingURL=chunk-RVWBSSZM.mjs.map