@metamask/snaps-controllers 7.0.1 → 8.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 (153) hide show
  1. package/CHANGELOG.md +26 -1
  2. package/dist/{chunk-Q2ON6SMV.js → chunk-2UAU42DO.js} +17 -25
  3. package/dist/chunk-2UAU42DO.js.map +1 -0
  4. package/dist/{chunk-Y5KX5ICF.mjs → chunk-3Y4IJKZY.mjs} +3 -3
  5. package/dist/chunk-3Y4IJKZY.mjs.map +1 -0
  6. package/dist/{chunk-XE5IWVNV.js → chunk-4DPX4O3T.js} +17 -6
  7. package/dist/chunk-4DPX4O3T.js.map +1 -0
  8. package/dist/{chunk-YVNRYLOC.js → chunk-74GN6MIJ.js} +3 -3
  9. package/dist/{chunk-NOLPMHXS.js → chunk-BOFPNIRX.js} +21 -3
  10. package/dist/chunk-BOFPNIRX.js.map +1 -0
  11. package/dist/{chunk-3ZC4LB7T.js → chunk-E5RRFMGF.js} +3 -3
  12. package/dist/chunk-E5RRFMGF.js.map +1 -0
  13. package/dist/{chunk-WVGK5B5P.mjs → chunk-FCCGRGQS.mjs} +83 -48
  14. package/dist/chunk-FCCGRGQS.mjs.map +1 -0
  15. package/dist/{chunk-NSLYI2LS.js → chunk-FCRPOA4I.js} +12 -4
  16. package/dist/chunk-FCRPOA4I.js.map +1 -0
  17. package/dist/{chunk-63GNCRER.js → chunk-G4S6UXQ2.js} +4 -4
  18. package/dist/chunk-G4S6UXQ2.js.map +1 -0
  19. package/dist/{chunk-MYWDTEX2.js → chunk-GRBWVPLF.js} +4 -4
  20. package/dist/{chunk-36YC4Z3T.mjs → chunk-GTDDODNP.mjs} +13 -2
  21. package/dist/chunk-GTDDODNP.mjs.map +1 -0
  22. package/dist/{chunk-5MVIYRYL.mjs → chunk-IPYO7FKR.mjs} +40 -26
  23. package/dist/chunk-IPYO7FKR.mjs.map +1 -0
  24. package/dist/{chunk-75VM3O4K.mjs → chunk-P5MRZOGW.mjs} +2 -2
  25. package/dist/{chunk-Z6SOB3SY.js → chunk-PAFO2KIN.js} +3 -3
  26. package/dist/chunk-PAFO2KIN.js.map +1 -0
  27. package/dist/{chunk-25LS4KZK.mjs → chunk-PXKCSAT6.mjs} +3 -3
  28. package/dist/chunk-PXKCSAT6.mjs.map +1 -0
  29. package/dist/{chunk-BJOQRBH2.mjs → chunk-QLEQIXCE.mjs} +2 -2
  30. package/dist/chunk-QLEQIXCE.mjs.map +1 -0
  31. package/dist/{chunk-K276CM3B.mjs → chunk-QP5LV734.mjs} +20 -28
  32. package/dist/chunk-QP5LV734.mjs.map +1 -0
  33. package/dist/{chunk-SCERVW3B.mjs → chunk-RS3WN6D3.mjs} +2 -2
  34. package/dist/chunk-RS3WN6D3.mjs.map +1 -0
  35. package/dist/{chunk-54TYYPAN.js → chunk-SIW7ZXQF.js} +83 -48
  36. package/dist/chunk-SIW7ZXQF.js.map +1 -0
  37. package/dist/{chunk-Q4I5QTVC.mjs → chunk-TO6ZEBIA.mjs} +11 -3
  38. package/dist/chunk-TO6ZEBIA.mjs.map +1 -0
  39. package/dist/chunk-U4DZUKNN.js +80 -0
  40. package/dist/chunk-U4DZUKNN.js.map +1 -0
  41. package/dist/{chunk-2KCUVQFS.mjs → chunk-X5MFC3VX.mjs} +2 -2
  42. package/dist/{chunk-VOZOZKRC.mjs → chunk-XO7KDFBY.mjs} +21 -3
  43. package/dist/chunk-XO7KDFBY.mjs.map +1 -0
  44. package/dist/{chunk-ZETJVFUS.mjs → chunk-XSFI32LB.mjs} +2 -2
  45. package/dist/{chunk-WQYMF7QP.js → chunk-Y7ZOSPEN.js} +3 -3
  46. package/dist/{chunk-CJN25EXL.js → chunk-YP37KUG5.js} +46 -32
  47. package/dist/chunk-YP37KUG5.js.map +1 -0
  48. package/dist/chunk-ZQNBP53T.mjs +80 -0
  49. package/dist/chunk-ZQNBP53T.mjs.map +1 -0
  50. package/dist/{chunk-N7WIJNHY.js → chunk-ZVGZG25U.js} +4 -4
  51. package/dist/chunk-ZVGZG25U.js.map +1 -0
  52. package/dist/cronjob/CronjobController.js +12 -12
  53. package/dist/cronjob/CronjobController.mjs +11 -11
  54. package/dist/cronjob/index.js +12 -12
  55. package/dist/cronjob/index.mjs +11 -11
  56. package/dist/index.js +14 -12
  57. package/dist/index.mjs +13 -11
  58. package/dist/interface/SnapInterfaceController.js +3 -3
  59. package/dist/interface/SnapInterfaceController.mjs +2 -2
  60. package/dist/interface/index.js +3 -3
  61. package/dist/interface/index.mjs +2 -2
  62. package/dist/interface/utils.js +2 -4
  63. package/dist/interface/utils.mjs +5 -7
  64. package/dist/node.js +16 -14
  65. package/dist/node.mjs +15 -13
  66. package/dist/react-native.js +15 -13
  67. package/dist/react-native.mjs +14 -12
  68. package/dist/services/AbstractExecutionService.js +4 -4
  69. package/dist/services/AbstractExecutionService.mjs +3 -3
  70. package/dist/services/browser.js +9 -9
  71. package/dist/services/browser.mjs +8 -8
  72. package/dist/services/iframe/IframeExecutionService.js +5 -5
  73. package/dist/services/iframe/IframeExecutionService.mjs +4 -4
  74. package/dist/services/iframe/index.js +5 -5
  75. package/dist/services/iframe/index.mjs +4 -4
  76. package/dist/services/index.js +8 -8
  77. package/dist/services/index.mjs +7 -7
  78. package/dist/services/node-js/NodeProcessExecutionService.js +9 -9
  79. package/dist/services/node-js/NodeProcessExecutionService.mjs +8 -8
  80. package/dist/services/node-js/NodeThreadExecutionService.js +9 -9
  81. package/dist/services/node-js/NodeThreadExecutionService.mjs +8 -8
  82. package/dist/services/node-js/index.js +10 -10
  83. package/dist/services/node-js/index.mjs +9 -9
  84. package/dist/services/node.js +10 -10
  85. package/dist/services/node.mjs +9 -9
  86. package/dist/services/offscreen/OffscreenExecutionService.js +6 -6
  87. package/dist/services/offscreen/OffscreenExecutionService.mjs +5 -5
  88. package/dist/services/offscreen/index.js +6 -6
  89. package/dist/services/offscreen/index.mjs +5 -5
  90. package/dist/services/proxy/ProxyExecutionService.js +5 -5
  91. package/dist/services/proxy/ProxyExecutionService.mjs +4 -4
  92. package/dist/services/react-native.js +9 -9
  93. package/dist/services/react-native.mjs +8 -8
  94. package/dist/services/webview/WebViewExecutionService.js +6 -6
  95. package/dist/services/webview/WebViewExecutionService.mjs +5 -5
  96. package/dist/services/webview/index.js +6 -6
  97. package/dist/services/webview/index.mjs +5 -5
  98. package/dist/services/webworker/WebWorkerExecutionService.js +5 -5
  99. package/dist/services/webworker/WebWorkerExecutionService.mjs +4 -4
  100. package/dist/services/webworker/index.js +5 -5
  101. package/dist/services/webworker/index.mjs +4 -4
  102. package/dist/snaps/SnapController.js +4 -4
  103. package/dist/snaps/SnapController.mjs +3 -3
  104. package/dist/snaps/Timer.js +2 -2
  105. package/dist/snaps/Timer.mjs +1 -1
  106. package/dist/snaps/index.js +4 -4
  107. package/dist/snaps/index.mjs +3 -3
  108. package/dist/tsconfig.build.tsbuildinfo +1 -1
  109. package/dist/types/interface/SnapInterfaceController.d.ts +5 -4
  110. package/dist/types/interface/utils.d.ts +11 -20
  111. package/dist/types/services/AbstractExecutionService.d.ts +18 -12
  112. package/dist/types/services/ExecutionService.d.ts +1 -1
  113. package/dist/types/services/iframe/IframeExecutionService.d.ts +2 -2
  114. package/dist/types/services/node-js/NodeProcessExecutionService.d.ts +2 -2
  115. package/dist/types/services/node-js/NodeThreadExecutionService.d.ts +2 -2
  116. package/dist/types/services/proxy/ProxyExecutionService.d.ts +2 -2
  117. package/dist/types/services/webworker/WebWorkerExecutionService.d.ts +2 -2
  118. package/dist/types/snaps/SnapController.d.ts +5 -6
  119. package/dist/types/snaps/Timer.d.ts +7 -0
  120. package/dist/types/utils.d.ts +12 -0
  121. package/dist/utils.js +5 -3
  122. package/dist/utils.mjs +4 -2
  123. package/package.json +8 -7
  124. package/dist/chunk-25LS4KZK.mjs.map +0 -1
  125. package/dist/chunk-36YC4Z3T.mjs.map +0 -1
  126. package/dist/chunk-3ZC4LB7T.js.map +0 -1
  127. package/dist/chunk-54TYYPAN.js.map +0 -1
  128. package/dist/chunk-5MVIYRYL.mjs.map +0 -1
  129. package/dist/chunk-63GNCRER.js.map +0 -1
  130. package/dist/chunk-BJOQRBH2.mjs.map +0 -1
  131. package/dist/chunk-CJN25EXL.js.map +0 -1
  132. package/dist/chunk-K276CM3B.mjs.map +0 -1
  133. package/dist/chunk-KLK7ZRMH.js +0 -55
  134. package/dist/chunk-KLK7ZRMH.js.map +0 -1
  135. package/dist/chunk-N7WIJNHY.js.map +0 -1
  136. package/dist/chunk-NOLPMHXS.js.map +0 -1
  137. package/dist/chunk-NSLYI2LS.js.map +0 -1
  138. package/dist/chunk-Q2ON6SMV.js.map +0 -1
  139. package/dist/chunk-Q4I5QTVC.mjs.map +0 -1
  140. package/dist/chunk-RIU3ZIXZ.mjs +0 -55
  141. package/dist/chunk-RIU3ZIXZ.mjs.map +0 -1
  142. package/dist/chunk-SCERVW3B.mjs.map +0 -1
  143. package/dist/chunk-VOZOZKRC.mjs.map +0 -1
  144. package/dist/chunk-WVGK5B5P.mjs.map +0 -1
  145. package/dist/chunk-XE5IWVNV.js.map +0 -1
  146. package/dist/chunk-Y5KX5ICF.mjs.map +0 -1
  147. package/dist/chunk-Z6SOB3SY.js.map +0 -1
  148. /package/dist/{chunk-YVNRYLOC.js.map → chunk-74GN6MIJ.js.map} +0 -0
  149. /package/dist/{chunk-MYWDTEX2.js.map → chunk-GRBWVPLF.js.map} +0 -0
  150. /package/dist/{chunk-75VM3O4K.mjs.map → chunk-P5MRZOGW.mjs.map} +0 -0
  151. /package/dist/{chunk-2KCUVQFS.mjs.map → chunk-X5MFC3VX.mjs.map} +0 -0
  152. /package/dist/{chunk-ZETJVFUS.mjs.map → chunk-XSFI32LB.mjs.map} +0 -0
  153. /package/dist/{chunk-WQYMF7QP.js.map → chunk-Y7ZOSPEN.js.map} +0 -0
package/CHANGELOG.md CHANGED
@@ -6,6 +6,29 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [8.1.0]
10
+ ### Added
11
+ - Add JSX support for custom UI ([#2258](https://github.com/MetaMask/snaps/pull/2258))
12
+
13
+ ### Changed
14
+ - Bump `@metamask/approval-controller` from `6.0.1` to `6.0.2` ([#2380](https://github.com/MetaMask/snaps/pull/2380))
15
+ - Bump `@metamask/base-controller` from `5.0.1` to `5.0.2` ([#2375](https://github.com/MetaMask/snaps/pull/2375))
16
+
17
+ ### Fixed
18
+ - Fix an issue where certain types of executors would be timed out too quickly ([#2389](https://github.com/MetaMask/snaps/pull/2389))
19
+
20
+ ## [8.0.0]
21
+ ### Changed
22
+ - **BREAKING:** Move `maxInitTime` constructor argument from `SnapController` to `ExecutionService` ([#2348](https://github.com/MetaMask/snaps/pull/2348))
23
+
24
+ ### Fixed
25
+ - Increase max UI size limit from 250 KB to 10 MB ([#2342](https://github.com/MetaMask/snaps/pull/2342))
26
+ - Consider caveats in permissions difference calculation ([#2345](https://github.com/MetaMask/snaps/pull/2345))
27
+ - This fixes a bug where certain caveats would not be correctly applied when updating Snaps.
28
+ - Gracefully handle errors for multiple simultaneous failing requests ([#2346](https://github.com/MetaMask/snaps/pull/2346))
29
+ - Properly handle termination of Snaps that are currently executing ([#2304](https://github.com/MetaMask/snaps/pull/2304))
30
+ - Properly tear down partially initialized executors and improve stability when executor initialization fails ([#2348](https://github.com/MetaMask/snaps/pull/2348))
31
+
9
32
  ## [7.0.1]
10
33
  ### Fixed
11
34
  - Fix encryption key caching issues ([#2326](https://github.com/MetaMask/snaps/pull/2326))
@@ -234,7 +257,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
234
257
  - The version of the package no longer needs to match the version of all other
235
258
  MetaMask Snaps packages.
236
259
 
237
- [Unreleased]: https://github.com/MetaMask/snaps/compare/@metamask/snaps-controllers@7.0.1...HEAD
260
+ [Unreleased]: https://github.com/MetaMask/snaps/compare/@metamask/snaps-controllers@8.1.0...HEAD
261
+ [8.1.0]: https://github.com/MetaMask/snaps/compare/@metamask/snaps-controllers@8.0.0...@metamask/snaps-controllers@8.1.0
262
+ [8.0.0]: https://github.com/MetaMask/snaps/compare/@metamask/snaps-controllers@7.0.1...@metamask/snaps-controllers@8.0.0
238
263
  [7.0.1]: https://github.com/MetaMask/snaps/compare/@metamask/snaps-controllers@7.0.0...@metamask/snaps-controllers@7.0.1
239
264
  [7.0.0]: https://github.com/MetaMask/snaps/compare/@metamask/snaps-controllers@6.0.4...@metamask/snaps-controllers@7.0.0
240
265
  [6.0.4]: https://github.com/MetaMask/snaps/compare/@metamask/snaps-controllers@6.0.3...@metamask/snaps-controllers@6.0.4
@@ -1,6 +1,7 @@
1
1
  "use strict";Object.defineProperty(exports, "__esModule", {value: true});
2
2
 
3
- var _chunkKLK7ZRMHjs = require('./chunk-KLK7ZRMH.js');
3
+
4
+ var _chunkU4DZUKNNjs = require('./chunk-U4DZUKNN.js');
4
5
 
5
6
 
6
7
 
@@ -8,14 +9,10 @@ var _chunkEXN2TFDJjs = require('./chunk-EXN2TFDJ.js');
8
9
 
9
10
  // src/interface/SnapInterfaceController.ts
10
11
  var _basecontroller = require('@metamask/base-controller');
11
-
12
-
13
-
14
12
  var _snapsutils = require('@metamask/snaps-utils');
15
13
  var _utils = require('@metamask/utils');
16
14
  var _nanoid = require('nanoid');
17
- var MAX_UI_CONTENT_SIZE = 25e4;
18
- var MAX_TEXT_LENGTH = 5e4;
15
+ var MAX_UI_CONTENT_SIZE = 1e7;
19
16
  var controllerName = "SnapInterfaceController";
20
17
  var _registerMessageHandlers, registerMessageHandlers_fn, _validateArgs, validateArgs_fn, _triggerPhishingListUpdate, triggerPhishingListUpdate_fn, _checkPhishingList, checkPhishingList_fn, _validateContent, validateContent_fn;
21
18
  var SnapInterfaceController = class extends _basecontroller.BaseController {
@@ -55,9 +52,7 @@ var SnapInterfaceController = class extends _basecontroller.BaseController {
55
52
  * Utility function to validate the components of an interface.
56
53
  * Throws if something is invalid.
57
54
  *
58
- * Right now this only checks links against the phighing list.
59
- *
60
- * @param content - The components to verify.
55
+ * @param element - The JSX element to verify.
61
56
  */
62
57
  _chunkEXN2TFDJjs.__privateAdd.call(void 0, this, _validateContent);
63
58
  _chunkEXN2TFDJjs.__privateMethod.call(void 0, this, _registerMessageHandlers, registerMessageHandlers_fn).call(this);
@@ -70,13 +65,14 @@ var SnapInterfaceController = class extends _basecontroller.BaseController {
70
65
  * @returns The newly interface id.
71
66
  */
72
67
  async createInterface(snapId, content) {
73
- await _chunkEXN2TFDJjs.__privateMethod.call(void 0, this, _validateContent, validateContent_fn).call(this, content);
68
+ const element = _chunkU4DZUKNNjs.getJsxInterface.call(void 0, content);
69
+ await _chunkEXN2TFDJjs.__privateMethod.call(void 0, this, _validateContent, validateContent_fn).call(this, element);
74
70
  const id = _nanoid.nanoid.call(void 0, );
75
- const componentState = _chunkKLK7ZRMHjs.constructState.call(void 0, {}, content);
71
+ const componentState = _chunkU4DZUKNNjs.constructState.call(void 0, {}, element);
76
72
  this.update((draftState) => {
77
73
  draftState.interfaces[id] = {
78
74
  snapId,
79
- content,
75
+ content: element,
80
76
  state: componentState
81
77
  };
82
78
  });
@@ -102,12 +98,13 @@ var SnapInterfaceController = class extends _basecontroller.BaseController {
102
98
  */
103
99
  async updateInterface(snapId, id, content) {
104
100
  _chunkEXN2TFDJjs.__privateMethod.call(void 0, this, _validateArgs, validateArgs_fn).call(this, snapId, id);
105
- await _chunkEXN2TFDJjs.__privateMethod.call(void 0, this, _validateContent, validateContent_fn).call(this, content);
101
+ const element = _chunkU4DZUKNNjs.getJsxInterface.call(void 0, content);
102
+ await _chunkEXN2TFDJjs.__privateMethod.call(void 0, this, _validateContent, validateContent_fn).call(this, element);
106
103
  const oldState = this.state.interfaces[id].state;
107
- const newState = _chunkKLK7ZRMHjs.constructState.call(void 0, oldState, content);
104
+ const newState = _chunkU4DZUKNNjs.constructState.call(void 0, oldState, element);
108
105
  this.update((draftState) => {
109
106
  draftState.interfaces[id].state = newState;
110
- draftState.interfaces[id].content = content;
107
+ draftState.interfaces[id].content = element;
111
108
  });
112
109
  }
113
110
  /**
@@ -176,22 +173,17 @@ checkPhishingList_fn = function(origin) {
176
173
  return this.messagingSystem.call("PhishingController:testOrigin", origin).result;
177
174
  };
178
175
  _validateContent = new WeakSet();
179
- validateContent_fn = async function(content) {
180
- const size = _utils.getJsonSize.call(void 0, content);
176
+ validateContent_fn = async function(element) {
177
+ const size = _snapsutils.getJsonSizeUnsafe.call(void 0, element);
181
178
  _utils.assert.call(void 0,
182
179
  size <= MAX_UI_CONTENT_SIZE,
183
- `A Snap UI may not be larger than ${MAX_UI_CONTENT_SIZE / 1e3} kB.`
184
- );
185
- const textSize = _snapsutils.getTotalTextLength.call(void 0, content);
186
- _utils.assert.call(void 0,
187
- textSize <= MAX_TEXT_LENGTH,
188
- `The text in a Snap UI may not be larger than ${MAX_TEXT_LENGTH / 1e3} kB.`
180
+ `A Snap UI may not be larger than ${MAX_UI_CONTENT_SIZE / 1e6} MB.`
189
181
  );
190
182
  await _chunkEXN2TFDJjs.__privateMethod.call(void 0, this, _triggerPhishingListUpdate, triggerPhishingListUpdate_fn).call(this);
191
- _snapsutils.validateComponentLinks.call(void 0, content, _chunkEXN2TFDJjs.__privateMethod.call(void 0, this, _checkPhishingList, checkPhishingList_fn).bind(this));
183
+ _snapsutils.validateJsxLinks.call(void 0, element, _chunkEXN2TFDJjs.__privateMethod.call(void 0, this, _checkPhishingList, checkPhishingList_fn).bind(this));
192
184
  };
193
185
 
194
186
 
195
187
 
196
188
  exports.SnapInterfaceController = SnapInterfaceController;
197
- //# sourceMappingURL=chunk-Q2ON6SMV.js.map
189
+ //# sourceMappingURL=chunk-2UAU42DO.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/interface/SnapInterfaceController.ts"],"names":[],"mappings":"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","sourcesContent":["import type { RestrictedControllerMessenger } from '@metamask/base-controller';\nimport { BaseController } from '@metamask/base-controller';\nimport type {\n MaybeUpdateState,\n TestOrigin,\n} from '@metamask/phishing-controller';\nimport type {\n InterfaceState,\n SnapId,\n ComponentOrElement,\n} from '@metamask/snaps-sdk';\nimport type { JSXElement } from '@metamask/snaps-sdk/jsx';\nimport { getJsonSizeUnsafe, validateJsxLinks } from '@metamask/snaps-utils';\nimport { assert } from '@metamask/utils';\nimport { nanoid } from 'nanoid';\n\nimport { constructState, getJsxInterface } from './utils';\n\nconst MAX_UI_CONTENT_SIZE = 10_000_000; // 10 mb\n\nconst controllerName = 'SnapInterfaceController';\n\nexport type CreateInterface = {\n type: `${typeof controllerName}:createInterface`;\n handler: SnapInterfaceController['createInterface'];\n};\n\nexport type GetInterface = {\n type: `${typeof controllerName}:getInterface`;\n handler: SnapInterfaceController['getInterface'];\n};\n\nexport type UpdateInterface = {\n type: `${typeof controllerName}:updateInterface`;\n handler: SnapInterfaceController['updateInterface'];\n};\n\nexport type DeleteInterface = {\n type: `${typeof controllerName}:deleteInterface`;\n handler: SnapInterfaceController['deleteInterface'];\n};\n\nexport type UpdateInterfaceState = {\n type: `${typeof controllerName}:updateInterfaceState`;\n handler: SnapInterfaceController['updateInterfaceState'];\n};\n\nexport type SnapInterfaceControllerAllowedActions =\n | TestOrigin\n | MaybeUpdateState;\n\nexport type SnapInterfaceControllerActions =\n | CreateInterface\n | GetInterface\n | UpdateInterface\n | DeleteInterface\n | UpdateInterfaceState;\n\nexport type SnapInterfaceControllerMessenger = RestrictedControllerMessenger<\n typeof controllerName,\n SnapInterfaceControllerActions | SnapInterfaceControllerAllowedActions,\n never,\n SnapInterfaceControllerAllowedActions['type'],\n never\n>;\n\nexport type StoredInterface = {\n snapId: SnapId;\n content: JSXElement;\n state: InterfaceState;\n};\n\nexport type SnapInterfaceControllerState = {\n interfaces: Record<string, StoredInterface>;\n};\n\nexport type SnapInterfaceControllerArgs = {\n messenger: SnapInterfaceControllerMessenger;\n state?: SnapInterfaceControllerState;\n};\n\n/**\n * Use this controller to manage snaps UI interfaces using RPC method hooks.\n */\nexport class SnapInterfaceController extends BaseController<\n typeof controllerName,\n SnapInterfaceControllerState,\n SnapInterfaceControllerMessenger\n> {\n constructor({ messenger, state }: SnapInterfaceControllerArgs) {\n super({\n messenger,\n metadata: {\n interfaces: { persist: false, anonymous: false },\n },\n name: controllerName,\n state: { interfaces: {}, ...state },\n });\n\n this.#registerMessageHandlers();\n }\n\n /**\n * Constructor helper for registering this controller's messaging system\n * actions.\n */\n #registerMessageHandlers() {\n this.messagingSystem.registerActionHandler(\n `${controllerName}:createInterface`,\n this.createInterface.bind(this),\n );\n\n this.messagingSystem.registerActionHandler(\n `${controllerName}:getInterface`,\n this.getInterface.bind(this),\n );\n\n this.messagingSystem.registerActionHandler(\n `${controllerName}:updateInterface`,\n this.updateInterface.bind(this),\n );\n\n this.messagingSystem.registerActionHandler(\n `${controllerName}:deleteInterface`,\n this.deleteInterface.bind(this),\n );\n\n this.messagingSystem.registerActionHandler(\n `${controllerName}:updateInterfaceState`,\n this.updateInterfaceState.bind(this),\n );\n }\n\n /**\n * Create an interface in the controller state with the associated data.\n *\n * @param snapId - The snap id that created the interface.\n * @param content - The interface content.\n * @returns The newly interface id.\n */\n async createInterface(snapId: SnapId, content: ComponentOrElement) {\n const element = getJsxInterface(content);\n await this.#validateContent(element);\n\n const id = nanoid();\n const componentState = constructState({}, element);\n\n this.update((draftState) => {\n // @ts-expect-error - TS2589: Type instantiation is excessively deep and\n // possibly infinite.\n draftState.interfaces[id] = {\n snapId,\n content: element,\n state: componentState,\n };\n });\n\n return id;\n }\n\n /**\n * Get the data of a given interface id.\n *\n * @param snapId - The snap id requesting the interface data.\n * @param id - The interface id.\n * @returns The interface state.\n */\n getInterface(snapId: SnapId, id: string) {\n this.#validateArgs(snapId, id);\n\n return this.state.interfaces[id];\n }\n\n /**\n * Update the interface with the given content.\n *\n * @param snapId - The snap id requesting the update.\n * @param id - The interface id.\n * @param content - The new content.\n */\n async updateInterface(\n snapId: SnapId,\n id: string,\n content: ComponentOrElement,\n ) {\n this.#validateArgs(snapId, id);\n const element = getJsxInterface(content);\n await this.#validateContent(element);\n\n const oldState = this.state.interfaces[id].state;\n const newState = constructState(oldState, element);\n\n this.update((draftState) => {\n draftState.interfaces[id].state = newState;\n draftState.interfaces[id].content = element;\n });\n }\n\n /**\n * Delete an interface from state.\n *\n * @param id - The interface id.\n */\n deleteInterface(id: string) {\n this.update((draftState) => {\n delete draftState.interfaces[id];\n });\n }\n\n /**\n * Update the interface state.\n *\n * @param id - The interface id.\n * @param state - The new state.\n */\n updateInterfaceState(id: string, state: InterfaceState) {\n this.update((draftState) => {\n draftState.interfaces[id].state = state;\n });\n }\n\n /**\n * Utility function to validate the args passed to the other methods.\n *\n * @param snapId - The snap id.\n * @param id - The interface id.\n */\n #validateArgs(snapId: SnapId, id: string) {\n const existingInterface = this.state.interfaces[id];\n\n assert(\n existingInterface !== undefined,\n `Interface with id '${id}' not found.`,\n );\n assert(\n existingInterface.snapId === snapId,\n `Interface not created by ${snapId}.`,\n );\n }\n\n /**\n * Trigger a Phishing list update if needed.\n */\n async #triggerPhishingListUpdate() {\n await this.messagingSystem.call('PhishingController:maybeUpdateState');\n }\n\n /**\n * Check an origin against the phishing list.\n *\n * @param origin - The origin to check.\n * @returns True if the origin is on the phishing list, otherwise false.\n */\n #checkPhishingList(origin: string) {\n return this.messagingSystem.call('PhishingController:testOrigin', origin)\n .result;\n }\n\n /**\n * Utility function to validate the components of an interface.\n * Throws if something is invalid.\n *\n * @param element - The JSX element to verify.\n */\n async #validateContent(element: JSXElement) {\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(element);\n assert(\n size <= MAX_UI_CONTENT_SIZE,\n `A Snap UI may not be larger than ${MAX_UI_CONTENT_SIZE / 1000000} MB.`,\n );\n\n await this.#triggerPhishingListUpdate();\n validateJsxLinks(element, this.#checkPhishingList.bind(this));\n }\n}\n"]}
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  AbstractExecutionService
3
- } from "./chunk-WVGK5B5P.mjs";
3
+ } from "./chunk-FCCGRGQS.mjs";
4
4
  import {
5
5
  __require
6
6
  } from "./chunk-YRZVIDCF.mjs";
@@ -29,11 +29,11 @@ var NodeThreadExecutionService = class extends AbstractExecutionService {
29
29
  return Promise.resolve({ worker, stream });
30
30
  }
31
31
  async terminateJob(jobWrapper) {
32
- await jobWrapper.worker.terminate();
32
+ await jobWrapper.worker?.terminate();
33
33
  }
34
34
  };
35
35
 
36
36
  export {
37
37
  NodeThreadExecutionService
38
38
  };
39
- //# sourceMappingURL=chunk-Y5KX5ICF.mjs.map
39
+ //# sourceMappingURL=chunk-3Y4IJKZY.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/services/node-js/NodeThreadExecutionService.ts"],"sourcesContent":["import type { BasePostMessageStream } from '@metamask/post-message-stream';\nimport { ThreadParentMessageStream } from '@metamask/post-message-stream';\n// eslint-disable-next-line @typescript-eslint/no-shadow\nimport { Worker } from 'worker_threads';\n\nimport type { TerminateJobArgs } from '..';\nimport { AbstractExecutionService } from '..';\n\nexport class NodeThreadExecutionService extends AbstractExecutionService<Worker> {\n protected async initEnvStream(): Promise<{\n worker: Worker;\n stream: BasePostMessageStream;\n }> {\n const worker = new Worker(\n require.resolve(\n '@metamask/snaps-execution-environments/dist/browserify/node-thread/bundle.js',\n ),\n {\n stdout: true,\n stderr: true,\n },\n );\n\n // Capturing `stdout` and `stderr` from the worker prevents the worker from\n // writing to them directly, making it easier to capture them Jest.\n worker.stdout.on('data', (data) => {\n // eslint-disable-next-line no-console\n console.log(data.toString());\n });\n\n worker.stderr.on('data', (data) => {\n // eslint-disable-next-line no-console\n console.error(data.toString());\n });\n\n const stream = new ThreadParentMessageStream({ thread: worker });\n return Promise.resolve({ worker, stream });\n }\n\n protected async terminateJob(\n jobWrapper: TerminateJobArgs<Worker>,\n ): Promise<void> {\n await jobWrapper.worker?.terminate();\n }\n}\n"],"mappings":";;;;;;;;AACA,SAAS,iCAAiC;AAE1C,SAAS,cAAc;AAKhB,IAAM,6BAAN,cAAyC,yBAAiC;AAAA,EAC/E,MAAgB,gBAGb;AACD,UAAM,SAAS,IAAI;AAAA,MACjB,UAAQ;AAAA,QACN;AAAA,MACF;AAAA,MACA;AAAA,QACE,QAAQ;AAAA,QACR,QAAQ;AAAA,MACV;AAAA,IACF;AAIA,WAAO,OAAO,GAAG,QAAQ,CAAC,SAAS;AAEjC,cAAQ,IAAI,KAAK,SAAS,CAAC;AAAA,IAC7B,CAAC;AAED,WAAO,OAAO,GAAG,QAAQ,CAAC,SAAS;AAEjC,cAAQ,MAAM,KAAK,SAAS,CAAC;AAAA,IAC/B,CAAC;AAED,UAAM,SAAS,IAAI,0BAA0B,EAAE,QAAQ,OAAO,CAAC;AAC/D,WAAO,QAAQ,QAAQ,EAAE,QAAQ,OAAO,CAAC;AAAA,EAC3C;AAAA,EAEA,MAAgB,aACd,YACe;AACf,UAAM,WAAW,QAAQ,UAAU;AAAA,EACrC;AACF;","names":[]}
@@ -1,6 +1,6 @@
1
- "use strict";Object.defineProperty(exports, "__esModule", {value: true});
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
2
2
 
3
- var _chunkNOLPMHXSjs = require('./chunk-NOLPMHXS.js');
3
+ var _chunkBOFPNIRXjs = require('./chunk-BOFPNIRX.js');
4
4
 
5
5
  // src/utils.ts
6
6
  var _snapssdk = require('@metamask/snaps-sdk');
@@ -9,6 +9,7 @@ var _snapssdk = require('@metamask/snaps-sdk');
9
9
 
10
10
 
11
11
  var _snapsutils = require('@metamask/snaps-utils');
12
+ var _fastdeepequal = require('fast-deep-equal'); var _fastdeepequal2 = _interopRequireDefault(_fastdeepequal);
12
13
  function setDiff(objectA, objectB) {
13
14
  return Object.entries(objectA).reduce(
14
15
  (acc, [key, value]) => {
@@ -20,8 +21,17 @@ function setDiff(objectA, objectB) {
20
21
  {}
21
22
  );
22
23
  }
24
+ function permissionsDiff(permissionsA, permissionsB) {
25
+ return Object.entries(permissionsA).reduce((acc, [key, value]) => {
26
+ const isIncluded = key in permissionsB;
27
+ if (!isIncluded || isIncluded && !_fastdeepequal2.default.call(void 0, value.caveats ?? [], permissionsB[key].caveats ?? [])) {
28
+ acc[key] = value;
29
+ }
30
+ return acc;
31
+ }, {});
32
+ }
23
33
  function delay(ms, result) {
24
- return delayWithTimer(new (0, _chunkNOLPMHXSjs.Timer)(ms), result);
34
+ return delayWithTimer(new (0, _chunkBOFPNIRXjs.Timer)(ms), result);
25
35
  }
26
36
  function delayWithTimer(timer, result) {
27
37
  let rejectFunc;
@@ -43,7 +53,7 @@ var hasTimedOut = Symbol(
43
53
  "Used to check if the requested promise has timeout (see withTimeout)"
44
54
  );
45
55
  async function withTimeout(promise, timerOrMs) {
46
- const timer = typeof timerOrMs === "number" ? new (0, _chunkNOLPMHXSjs.Timer)(timerOrMs) : timerOrMs;
56
+ const timer = typeof timerOrMs === "number" ? new (0, _chunkBOFPNIRXjs.Timer)(timerOrMs) : timerOrMs;
47
57
  const delayPromise = delayWithTimer(timer, hasTimedOut);
48
58
  try {
49
59
  return await Promise.race([promise, delayPromise]);
@@ -105,5 +115,6 @@ async function fetchSnap(snapId, location) {
105
115
 
106
116
 
107
117
 
108
- exports.setDiff = setDiff; exports.delay = delay; exports.delayWithTimer = delayWithTimer; exports.hasTimedOut = hasTimedOut; exports.withTimeout = withTimeout; exports.getSnapFiles = getSnapFiles; exports.fetchSnap = fetchSnap;
109
- //# sourceMappingURL=chunk-XE5IWVNV.js.map
118
+
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
@@ -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 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"]}
@@ -3,7 +3,7 @@
3
3
  var _chunkC4D6GBMYjs = require('./chunk-C4D6GBMY.js');
4
4
 
5
5
 
6
- var _chunkNSLYI2LSjs = require('./chunk-NSLYI2LS.js');
6
+ var _chunkFCRPOA4Ijs = require('./chunk-FCRPOA4I.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 _chunkNSLYI2LSjs.ProxyExecutionService {
16
+ var WebViewExecutionService = class extends _chunkFCRPOA4Ijs.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-YVNRYLOC.js.map
58
+ //# sourceMappingURL=chunk-74GN6MIJ.js.map
@@ -19,6 +19,9 @@ var Timer = class {
19
19
  get status() {
20
20
  return this.state.value;
21
21
  }
22
+ get remaining() {
23
+ return this.state.remaining;
24
+ }
22
25
  /**
23
26
  * Cancels the currently running timer and marks it finished.
24
27
  *
@@ -31,6 +34,18 @@ var Timer = class {
31
34
  );
32
35
  this.onFinish(false);
33
36
  }
37
+ /**
38
+ * Marks the timer as finished prematurely and triggers the callback.
39
+ *
40
+ * @throws {@link Error}. If it wasn't running or paused.
41
+ */
42
+ finish() {
43
+ _utils.assert.call(void 0,
44
+ this.status !== "finished",
45
+ new Error("Tried to finish a finished Timer.")
46
+ );
47
+ this.onFinish(true);
48
+ }
34
49
  /**
35
50
  * Pauses a currently running timer, allowing it to resume later.
36
51
  *
@@ -87,8 +102,11 @@ var Timer = class {
87
102
  if (this.state.value === "running" && this.state.timeout !== void 0) {
88
103
  clearTimeout(this.state.timeout);
89
104
  }
90
- const { callback } = this.state;
91
- this.state = { value: "finished" };
105
+ const { callback, remaining } = this.state;
106
+ this.state = {
107
+ value: "finished",
108
+ remaining: this.state.value === "running" ? remaining - (Date.now() - this.state.start) : remaining
109
+ };
92
110
  if (shouldCall) {
93
111
  callback();
94
112
  }
@@ -98,4 +116,4 @@ var Timer = class {
98
116
 
99
117
 
100
118
  exports.Timer = Timer;
101
- //# sourceMappingURL=chunk-NOLPMHXS.js.map
119
+ //# sourceMappingURL=chunk-BOFPNIRX.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/snaps/Timer.ts"],"names":[],"mappings":";AAAA,SAAS,cAAc;AAIhB,IAAM,QAAN,MAAY;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAwBjB,YAAY,IAAY;AACtB;AAAA,MACE,CAAC,OAAO,MAAM,EAAE;AAAA,MAChB,IAAI,UAAU,mCAAmC;AAAA,IACnD;AACA,WAAO,MAAM,GAAG,IAAI,UAAU,wCAAwC,CAAC;AACvE,SAAK,QAAQ,EAAE,OAAO,WAAW,WAAW,GAAG;AAAA,EACjD;AAAA,EAEA,IAAI,SAAsB;AACxB,WAAO,KAAK,MAAM;AAAA,EACpB;AAAA,EAEA,IAAI,YAAoB;AACtB,WAAO,KAAK,MAAM;AAAA,EACpB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,SAAS;AACP;AAAA,MACE,KAAK,WAAW,YAAY,KAAK,WAAW;AAAA,MAC5C,IAAI,MAAM,qCAAqC;AAAA,IACjD;AACA,SAAK,SAAS,KAAK;AAAA,EACrB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,SAAS;AACP;AAAA,MACE,KAAK,WAAW;AAAA,MAChB,IAAI,MAAM,mCAAmC;AAAA,IAC/C;AACA,SAAK,SAAS,IAAI;AAAA,EACpB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,QAAQ;AACN;AAAA,MACE,KAAK,MAAM,UAAU;AAAA,MACrB,IAAI,MAAM,oCAAoC;AAAA,IAChD;AAEA,UAAM,EAAE,UAAU,OAAO,SAAS,UAAU,IAAI,KAAK;AAErD,gBAAY,UAAa,aAAa,OAAc;AACpD,SAAK,QAAQ;AAAA,MACX,OAAO;AAAA,MACP;AAAA,MACA,WAAW,aAAa,KAAK,IAAI,IAAI;AAAA,IACvC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,UAAsB;AAC1B;AAAA,MACE,KAAK,MAAM,UAAU;AAAA,MACrB,IAAI,MAAM,yCAAyC;AAAA,IACrD;AAEA,UAAM,EAAE,UAAU,IAAI,KAAK;AAC3B,SAAK,QAAQ,EAAE,OAAO,UAAU,WAAW,SAAS;AACpD,SAAK,OAAO;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,SAAS;AACP;AAAA,MACE,KAAK,MAAM,UAAU;AAAA,MACrB,IAAI,MAAM,kCAAkC;AAAA,IAC9C;AACA,UAAM,EAAE,WAAW,SAAS,IAAI,KAAK;AACrC,UAAM,QAAQ,KAAK,IAAI;AAEvB,QAAI;AAEJ,QAAI,cAAc,OAAO,mBAAmB;AAC1C,gBAAU,WAAW,MAAM,KAAK,SAAS,IAAI,GAAG,SAAS;AAAA,IAC3D;AAEA,SAAK,QAAQ,EAAE,OAAO,WAAW,UAAU,WAAW,OAAO,QAAQ;AAAA,EACvE;AAAA,EAEQ,SAAS,YAAqB;AACpC,WAAO,KAAK,MAAM,UAAU,aAAa,KAAK,MAAM,UAAU,QAAQ;AAEtE,QAAI,KAAK,MAAM,UAAU,aAAa,KAAK,MAAM,YAAY,QAAW;AACtE,mBAAa,KAAK,MAAM,OAAc;AAAA,IACxC;AAEA,UAAM,EAAE,UAAU,UAAU,IAAI,KAAK;AACrC,SAAK,QAAQ;AAAA,MACX,OAAO;AAAA,MACP,WACE,KAAK,MAAM,UAAU,YACjB,aAAa,KAAK,IAAI,IAAI,KAAK,MAAM,SACrC;AAAA,IACR;AAEA,QAAI,YAAY;AACd,eAAS;AAAA,IACX;AAAA,EACF;AACF","sourcesContent":["import { assert } from '@metamask/utils';\n\nexport type TimerStatus = 'stopped' | 'paused' | 'running' | 'finished';\n\nexport class Timer {\n private state:\n | { value: 'stopped'; remaining: number }\n | {\n value: 'paused';\n remaining: number;\n callback: () => void;\n }\n | {\n value: 'running';\n remaining: number;\n callback: () => void;\n start: number;\n timeout?: unknown;\n }\n | { value: 'finished'; remaining: number };\n\n /**\n * If `ms` is smaller or equal to zero (including -Infinity), the callback is added to the event loop and executed async immediately\n * If `ms` is +Infinity the timer never finishes.\n *\n * @throws {@link TypeError}. If `ms` is NaN or negative.\n * @param ms - The number of milliseconds before the callback is called after started.\n */\n constructor(ms: number) {\n assert(\n !Number.isNaN(ms),\n new TypeError(\"Can't start a timer with NaN time\"),\n );\n assert(ms >= 0, new TypeError(\"Can't start a timer with negative time\"));\n this.state = { value: 'stopped', remaining: ms };\n }\n\n get status(): TimerStatus {\n return this.state.value;\n }\n\n get remaining(): number {\n return this.state.remaining;\n }\n\n /**\n * Cancels the currently running timer and marks it finished.\n *\n * @throws {@link Error}. If it wasn't running or paused.\n */\n cancel() {\n assert(\n this.status === 'paused' || this.status === 'running',\n new Error('Tried to cancel a not running Timer'),\n );\n this.onFinish(false);\n }\n\n /**\n * Marks the timer as finished prematurely and triggers the callback.\n *\n * @throws {@link Error}. If it wasn't running or paused.\n */\n finish() {\n assert(\n this.status !== 'finished',\n new Error('Tried to finish a finished Timer.'),\n );\n this.onFinish(true);\n }\n\n /**\n * Pauses a currently running timer, allowing it to resume later.\n *\n * @throws {@link Error}. If it wasn't running.\n */\n pause() {\n assert(\n this.state.value === 'running',\n new Error('Tried to pause a not running Timer'),\n );\n\n const { callback, start, timeout, remaining } = this.state;\n\n timeout !== undefined && clearTimeout(timeout as any);\n this.state = {\n value: 'paused',\n callback,\n remaining: remaining - (Date.now() - start),\n };\n }\n\n /**\n * Starts the timer.\n *\n * @param callback - The function that will be called after the timer finishes.\n * @throws {@link Error}. If it was already started.\n */\n start(callback: () => void) {\n assert(\n this.state.value === 'stopped',\n new Error('Tried to start an already running Timer'),\n );\n\n const { remaining } = this.state;\n this.state = { value: 'paused', remaining, callback };\n this.resume();\n }\n\n /**\n * Resumes a currently paused timer.\n *\n * @throws {@link Error}. If it wasn't paused.\n */\n resume() {\n assert(\n this.state.value === 'paused',\n new Error('Tried to resume not paused Timer'),\n );\n const { remaining, callback } = this.state;\n const start = Date.now();\n\n let timeout: unknown;\n // setTimeout returns immediately on +Infinity which we use\n if (remaining !== Number.POSITIVE_INFINITY) {\n timeout = setTimeout(() => this.onFinish(true), remaining);\n }\n\n this.state = { value: 'running', callback, remaining, start, timeout };\n }\n\n private onFinish(shouldCall: boolean) {\n assert(this.state.value === 'running' || this.state.value === 'paused');\n\n if (this.state.value === 'running' && this.state.timeout !== undefined) {\n clearTimeout(this.state.timeout as any);\n }\n\n const { callback, remaining } = this.state;\n this.state = {\n value: 'finished',\n remaining:\n this.state.value === 'running'\n ? remaining - (Date.now() - this.state.start)\n : remaining,\n };\n\n if (shouldCall) {\n callback();\n }\n }\n}\n"]}
@@ -1,6 +1,6 @@
1
1
  "use strict";Object.defineProperty(exports, "__esModule", {value: true});
2
2
 
3
- var _chunk54TYYPANjs = require('./chunk-54TYYPAN.js');
3
+ var _chunkSIW7ZXQFjs = require('./chunk-SIW7ZXQF.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 _chunk54TYYPANjs.AbstractExecutionService {
20
+ var WebWorkerExecutionService = class extends _chunkSIW7ZXQFjs.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-3ZC4LB7T.js.map
105
+ //# sourceMappingURL=chunk-E5RRFMGF.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/services/webworker/WebWorkerExecutionService.ts"],"names":[],"mappings":";;;;;;;;;;;;;AACA,SAAS,+BAA+B;AACxC,SAAS,oBAAoB;AAC7B,SAAS,cAAc;AACvB,SAAS,cAAc;AAahB,IAAM,iBAAiB;AAjB9B;AAmBO,IAAM,4BAAN,cAAwC,yBAAiC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAgB9E,YAAY;AAAA,IACV;AAAA,IACA;AAAA,IACA;AAAA,EACF,GAA6C;AAC3C,UAAM;AAAA,MACJ;AAAA,MACA;AAAA,IACF,CAAC;AAvBH;AAEA;AAuBE,uBAAK,cAAe;AAAA,EACtB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAgB,aAAa,KAA+B;AAG1D,WAAO,mBAAK,iBAAgB,iCAAiC;AAC7D,uBAAK,gBAAe,MAAM;AAAA,MACxB,OAAO,IAAI;AAAA,MACX,MAAM;AAAA,QACJ,SAAS;AAAA,QACT,QAAQ;AAAA,QACR,IAAI,OAAO;AAAA,MACb;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAgB,cAAc,OAAe;AAE3C,UAAM,KAAK,eAAe;AAG1B,WAAO,mBAAK,iBAAgB,iCAAiC;AAE7D,UAAM,SAAS,IAAI,uBAAuB;AAAA,MACxC,QAAQ,mBAAK;AAAA,MACb;AAAA,IACF,CAAC;AAED,WAAO,EAAE,QAAQ,OAAO,OAAO;AAAA,EACjC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAc,iBAAiB;AAE7B,QAAI,SAAS,eAAe,cAAc,GAAG;AAC3C;AAAA,IACF;AAEA,UAAM,SAAS,MAAM;AAAA,MACnB,mBAAK,cAAa;AAAA,MAClB;AAAA,MACA;AAAA,IACF;AAEA,uBAAK,gBAAiB,IAAI,wBAAwB;AAAA,MAChD,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,cAAc;AAAA,MACd,cAAc;AAAA,IAChB,CAAC;AAAA,EACH;AACF;AA5FE;AAEA","sourcesContent":["import type { BasePostMessageStream } from '@metamask/post-message-stream';\nimport { WindowPostMessageStream } from '@metamask/post-message-stream';\nimport { createWindow } from '@metamask/snaps-utils';\nimport { assert } from '@metamask/utils';\nimport { nanoid } from 'nanoid';\n\nimport type {\n ExecutionServiceArgs,\n TerminateJobArgs,\n} from '../AbstractExecutionService';\nimport { AbstractExecutionService } from '../AbstractExecutionService';\nimport { ProxyPostMessageStream } from '../ProxyPostMessageStream';\n\ntype WebWorkerExecutionEnvironmentServiceArgs = {\n documentUrl: URL;\n} & ExecutionServiceArgs;\n\nexport const WORKER_POOL_ID = 'snaps-worker-pool';\n\nexport class WebWorkerExecutionService extends AbstractExecutionService<string> {\n #documentUrl: URL;\n\n #runtimeStream?: BasePostMessageStream;\n\n /**\n * Create a new webworker execution service.\n *\n * @param args - The constructor arguments.\n * @param args.documentUrl - The URL of the worker pool document to use as the\n * execution environment.\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 */\n constructor({\n documentUrl,\n messenger,\n setupSnapProvider,\n }: WebWorkerExecutionEnvironmentServiceArgs) {\n super({\n messenger,\n setupSnapProvider,\n });\n\n this.#documentUrl = documentUrl;\n }\n\n /**\n * Send a termination command to the worker pool document.\n *\n * @param job - The job to terminate.\n */\n protected async terminateJob(job: TerminateJobArgs<string>) {\n // The `AbstractExecutionService` will have already closed the job stream,\n // so we write to the runtime stream directly.\n assert(this.#runtimeStream, 'Runtime stream not initialized.');\n this.#runtimeStream.write({\n jobId: job.id,\n data: {\n jsonrpc: '2.0',\n method: 'terminateJob',\n id: nanoid(),\n },\n });\n }\n\n /**\n * Create a new stream for the specified job. This wraps the runtime stream\n * in a stream specific to the job.\n *\n * @param jobId - The job ID.\n */\n protected async initEnvStream(jobId: string) {\n // Lazily create the worker pool document.\n await this.createDocument();\n\n // `createDocument` should have initialized the runtime stream.\n assert(this.#runtimeStream, 'Runtime stream not initialized.');\n\n const stream = new ProxyPostMessageStream({\n stream: this.#runtimeStream,\n jobId,\n });\n\n return { worker: jobId, stream };\n }\n\n /**\n * Creates the worker pool document to be used as the execution environment.\n *\n * If the document already exists, this does nothing.\n */\n private async createDocument() {\n // We only want to create a single pool.\n if (document.getElementById(WORKER_POOL_ID)) {\n return;\n }\n\n const window = await createWindow(\n this.#documentUrl.href,\n WORKER_POOL_ID,\n false,\n );\n\n this.#runtimeStream = new WindowPostMessageStream({\n name: 'parent',\n target: 'child',\n targetWindow: window,\n targetOrigin: '*',\n });\n }\n}\n"]}
@@ -4,7 +4,10 @@ import {
4
4
  import {
5
5
  hasTimedOut,
6
6
  withTimeout
7
- } from "./chunk-36YC4Z3T.mjs";
7
+ } from "./chunk-GTDDODNP.mjs";
8
+ import {
9
+ Timer
10
+ } from "./chunk-XO7KDFBY.mjs";
8
11
  import {
9
12
  __privateAdd,
10
13
  __privateGet,
@@ -28,13 +31,15 @@ import {
28
31
  import { nanoid } from "nanoid";
29
32
  import { pipeline } from "readable-stream";
30
33
  var controllerName = "ExecutionService";
31
- var _snapRpcHooks, _snapToJobMap, _jobToSnapMap, _messenger, _pingTimeout, _terminationTimeout, _removeSnapHooks, removeSnapHooks_fn, _createSnapHooks, createSnapHooks_fn, _mapSnapAndJob, mapSnapAndJob_fn, _removeSnapAndJobMapping, removeSnapAndJobMapping_fn;
34
+ var _snapRpcHooks, _snapToJobMap, _jobToSnapMap, _messenger, _initTimeout, _pingTimeout, _terminationTimeout, _usePing, _removeSnapHooks, removeSnapHooks_fn, _createSnapHooks, createSnapHooks_fn, _mapSnapAndJob, mapSnapAndJob_fn, _removeSnapAndJobMapping, removeSnapAndJobMapping_fn;
32
35
  var AbstractExecutionService = class {
33
36
  constructor({
34
37
  setupSnapProvider,
35
38
  messenger,
39
+ initTimeout = inMilliseconds(60, Duration.Second),
36
40
  pingTimeout = inMilliseconds(2, Duration.Second),
37
- terminationTimeout = inMilliseconds(1, Duration.Second)
41
+ terminationTimeout = inMilliseconds(1, Duration.Second),
42
+ usePing = true
38
43
  }) {
39
44
  __privateAdd(this, _removeSnapHooks);
40
45
  __privateAdd(this, _createSnapHooks);
@@ -44,16 +49,20 @@ var AbstractExecutionService = class {
44
49
  __privateAdd(this, _snapToJobMap, void 0);
45
50
  __privateAdd(this, _jobToSnapMap, void 0);
46
51
  __privateAdd(this, _messenger, void 0);
52
+ __privateAdd(this, _initTimeout, void 0);
47
53
  __privateAdd(this, _pingTimeout, void 0);
48
54
  __privateAdd(this, _terminationTimeout, void 0);
55
+ __privateAdd(this, _usePing, void 0);
49
56
  __privateSet(this, _snapRpcHooks, /* @__PURE__ */ new Map());
50
57
  this.jobs = /* @__PURE__ */ new Map();
51
58
  this.setupSnapProvider = setupSnapProvider;
52
59
  __privateSet(this, _snapToJobMap, /* @__PURE__ */ new Map());
53
60
  __privateSet(this, _jobToSnapMap, /* @__PURE__ */ new Map());
54
61
  __privateSet(this, _messenger, messenger);
62
+ __privateSet(this, _initTimeout, initTimeout);
55
63
  __privateSet(this, _pingTimeout, pingTimeout);
56
64
  __privateSet(this, _terminationTimeout, terminationTimeout);
65
+ __privateSet(this, _usePing, usePing);
57
66
  this.registerMessageHandlers();
58
67
  }
59
68
  /**
@@ -67,7 +76,7 @@ var AbstractExecutionService = class {
67
76
  );
68
77
  __privateGet(this, _messenger).registerActionHandler(
69
78
  `${controllerName}:executeSnap`,
70
- async (snapData) => this.executeSnap(snapData)
79
+ async (data) => this.executeSnap(data)
71
80
  );
72
81
  __privateGet(this, _messenger).registerActionHandler(
73
82
  `${controllerName}:terminateSnap`,
@@ -91,17 +100,20 @@ var AbstractExecutionService = class {
91
100
  if (!jobWrapper) {
92
101
  throw new Error(`Job with id "${jobId}" not found.`);
93
102
  }
94
- const result = await withTimeout(
95
- this.command(jobId, {
96
- jsonrpc: "2.0",
97
- method: "terminate",
98
- params: [],
99
- id: nanoid()
100
- }),
101
- __privateGet(this, _terminationTimeout)
102
- );
103
- if (result === hasTimedOut || result !== "OK") {
104
- logError(`Job "${jobId}" failed to terminate gracefully.`, result);
103
+ try {
104
+ const result = await withTimeout(
105
+ this.command(jobId, {
106
+ jsonrpc: "2.0",
107
+ method: "terminate",
108
+ params: [],
109
+ id: nanoid()
110
+ }),
111
+ __privateGet(this, _terminationTimeout)
112
+ );
113
+ if (result === hasTimedOut || result !== "OK") {
114
+ logError(`Job "${jobId}" failed to terminate gracefully.`, result);
115
+ }
116
+ } catch {
105
117
  }
106
118
  Object.values(jobWrapper.streams).forEach((stream) => {
107
119
  try {
@@ -112,20 +124,20 @@ var AbstractExecutionService = class {
112
124
  }
113
125
  });
114
126
  this.terminateJob(jobWrapper);
115
- __privateMethod(this, _removeSnapAndJobMapping, removeSnapAndJobMapping_fn).call(this, jobId);
116
127
  this.jobs.delete(jobId);
128
+ __privateMethod(this, _removeSnapAndJobMapping, removeSnapAndJobMapping_fn).call(this, jobId);
117
129
  log(`Job "${jobId}" terminated.`);
118
130
  }
119
131
  /**
120
132
  * Initiates a job for a snap.
121
133
  *
122
- * Depending on the execution environment, this may run forever if the Snap fails to start up properly, therefore any call to this function should be wrapped in a timeout.
123
- *
134
+ * @param jobId - The ID of the job to initiate.
135
+ * @param timer - The timer to use for timeouts.
124
136
  * @returns Information regarding the created job.
137
+ * @throws If the execution service returns an error or execution times out.
125
138
  */
126
- async initJob() {
127
- const jobId = nanoid();
128
- const { streams, worker } = await this.initStreams(jobId);
139
+ async initJob(jobId, timer) {
140
+ const { streams, worker } = await this.initStreams(jobId, timer);
129
141
  const rpcEngine = new JsonRpcEngine();
130
142
  const jsonRpcConnection = createStreamMiddleware();
131
143
  pipeline(
@@ -151,13 +163,18 @@ var AbstractExecutionService = class {
151
163
  /**
152
164
  * Sets up the streams for an initiated job.
153
165
  *
154
- * Depending on the execution environment, this may run forever if the Snap fails to start up properly, therefore any call to this function should be wrapped in a timeout.
155
- *
156
166
  * @param jobId - The id of the job.
167
+ * @param timer - The timer to use for timeouts.
157
168
  * @returns The streams to communicate with the worker and the worker itself.
169
+ * @throws If the execution service returns an error or execution times out.
158
170
  */
159
- async initStreams(jobId) {
160
- const { worker, stream: envStream } = await this.initEnvStream(jobId);
171
+ async initStreams(jobId, timer) {
172
+ const result = await withTimeout(this.initEnvStream(jobId), timer);
173
+ if (result === hasTimedOut) {
174
+ this.terminateJob({ id: jobId });
175
+ throw new Error("The Snaps execution environment failed to start.");
176
+ }
177
+ const { worker, stream: envStream } = result;
161
178
  const mux = setupMultiplex(envStream, `Job: "${jobId}"`);
162
179
  const commandStream = mux.createStream(SNAP_STREAM_NAMES.COMMAND);
163
180
  const notificationHandler = (message) => {
@@ -235,38 +252,54 @@ var AbstractExecutionService = class {
235
252
  /**
236
253
  * Initializes and executes a snap, setting up the communication channels to the snap etc.
237
254
  *
238
- * Depending on the execution environment, this may run forever if the Snap fails to start up properly, therefore any call to this function should be wrapped in a timeout.
239
- *
240
255
  * @param snapData - Data needed for Snap execution.
256
+ * @param snapData.snapId - The ID of the Snap to execute.
257
+ * @param snapData.sourceCode - The source code of the Snap to execute.
258
+ * @param snapData.endowments - The endowments available to the executing Snap.
241
259
  * @returns A string `OK` if execution succeeded.
242
- * @throws If the execution service returns an error.
260
+ * @throws If the execution service returns an error or execution times out.
243
261
  */
244
- async executeSnap(snapData) {
245
- if (__privateGet(this, _snapToJobMap).has(snapData.snapId)) {
246
- throw new Error(`Snap "${snapData.snapId}" is already being executed.`);
262
+ async executeSnap({
263
+ snapId,
264
+ sourceCode,
265
+ endowments
266
+ }) {
267
+ if (__privateGet(this, _snapToJobMap).has(snapId)) {
268
+ throw new Error(`Snap "${snapId}" is already being executed.`);
269
+ }
270
+ const jobId = nanoid();
271
+ const timer = new Timer(__privateGet(this, _initTimeout));
272
+ const job = await this.initJob(jobId, timer);
273
+ __privateMethod(this, _mapSnapAndJob, mapSnapAndJob_fn).call(this, snapId, job.id);
274
+ if (__privateGet(this, _usePing)) {
275
+ const pingResult = await withTimeout(
276
+ this.command(job.id, {
277
+ jsonrpc: "2.0",
278
+ method: "ping",
279
+ id: nanoid()
280
+ }),
281
+ __privateGet(this, _pingTimeout)
282
+ );
283
+ if (pingResult === hasTimedOut) {
284
+ throw new Error("The Snaps execution environment failed to start.");
285
+ }
247
286
  }
248
- const job = await this.initJob();
249
- __privateMethod(this, _mapSnapAndJob, mapSnapAndJob_fn).call(this, snapData.snapId, job.id);
250
- const pingResult = await withTimeout(
287
+ const rpcStream = job.streams.rpc;
288
+ this.setupSnapProvider(snapId, rpcStream);
289
+ const remainingTime = timer.remaining;
290
+ const result = await withTimeout(
251
291
  this.command(job.id, {
252
292
  jsonrpc: "2.0",
253
- method: "ping",
293
+ method: "executeSnap",
294
+ params: { snapId, sourceCode, endowments },
254
295
  id: nanoid()
255
296
  }),
256
- __privateGet(this, _pingTimeout)
297
+ remainingTime
257
298
  );
258
- if (pingResult === hasTimedOut) {
259
- throw new Error("The Snaps execution environment failed to start.");
299
+ if (result === hasTimedOut) {
300
+ throw new Error(`${snapId} failed to start.`);
260
301
  }
261
- const rpcStream = job.streams.rpc;
262
- this.setupSnapProvider(snapData.snapId, rpcStream);
263
- const result = await this.command(job.id, {
264
- jsonrpc: "2.0",
265
- method: "executeSnap",
266
- params: snapData,
267
- id: nanoid()
268
- });
269
- __privateMethod(this, _createSnapHooks, createSnapHooks_fn).call(this, snapData.snapId, job.id);
302
+ __privateMethod(this, _createSnapHooks, createSnapHooks_fn).call(this, snapId, job.id);
270
303
  return result;
271
304
  }
272
305
  // Cannot be hash private yet because of tests.
@@ -310,8 +343,10 @@ _snapRpcHooks = new WeakMap();
310
343
  _snapToJobMap = new WeakMap();
311
344
  _jobToSnapMap = new WeakMap();
312
345
  _messenger = new WeakMap();
346
+ _initTimeout = new WeakMap();
313
347
  _pingTimeout = new WeakMap();
314
348
  _terminationTimeout = new WeakMap();
349
+ _usePing = new WeakMap();
315
350
  _removeSnapHooks = new WeakSet();
316
351
  removeSnapHooks_fn = function(snapId) {
317
352
  __privateGet(this, _snapRpcHooks).delete(snapId);
@@ -362,4 +397,4 @@ export {
362
397
  AbstractExecutionService,
363
398
  setupMultiplex
364
399
  };
365
- //# sourceMappingURL=chunk-WVGK5B5P.mjs.map
400
+ //# sourceMappingURL=chunk-FCCGRGQS.mjs.map