@metamask/snaps-execution-environments 10.4.0 → 11.0.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 (54) hide show
  1. package/CHANGELOG.md +16 -1
  2. package/dist/common/BaseSnapExecutor.cjs +130 -189
  3. package/dist/common/BaseSnapExecutor.cjs.map +1 -1
  4. package/dist/common/BaseSnapExecutor.d.cts +0 -57
  5. package/dist/common/BaseSnapExecutor.d.cts.map +1 -1
  6. package/dist/common/BaseSnapExecutor.d.mts +0 -57
  7. package/dist/common/BaseSnapExecutor.d.mts.map +1 -1
  8. package/dist/common/BaseSnapExecutor.mjs +135 -194
  9. package/dist/common/BaseSnapExecutor.mjs.map +1 -1
  10. package/dist/common/commands.cjs +23 -29
  11. package/dist/common/commands.cjs.map +1 -1
  12. package/dist/common/commands.d.cts +12 -20
  13. package/dist/common/commands.d.cts.map +1 -1
  14. package/dist/common/commands.d.mts +12 -20
  15. package/dist/common/commands.d.mts.map +1 -1
  16. package/dist/common/commands.mjs +21 -27
  17. package/dist/common/commands.mjs.map +1 -1
  18. package/dist/common/utils.cjs +41 -1
  19. package/dist/common/utils.cjs.map +1 -1
  20. package/dist/common/utils.d.cts +7 -0
  21. package/dist/common/utils.d.cts.map +1 -1
  22. package/dist/common/utils.d.mts +7 -0
  23. package/dist/common/utils.d.mts.map +1 -1
  24. package/dist/common/utils.mjs +39 -0
  25. package/dist/common/utils.mjs.map +1 -1
  26. package/dist/common/validation.cjs +13 -25
  27. package/dist/common/validation.cjs.map +1 -1
  28. package/dist/common/validation.d.cts +69 -42
  29. package/dist/common/validation.d.cts.map +1 -1
  30. package/dist/common/validation.d.mts +69 -42
  31. package/dist/common/validation.d.mts.map +1 -1
  32. package/dist/common/validation.mjs +15 -27
  33. package/dist/common/validation.mjs.map +1 -1
  34. package/dist/webpack/iframe/bundle.js +1 -1
  35. package/dist/webpack/node-process/bundle.js +1 -1
  36. package/dist/webpack/node-thread/bundle.js +1 -1
  37. package/dist/webpack/webview/index.html +1 -1
  38. package/package.json +3 -3
  39. package/dist/common/lockdown/lockdown.cjs +0 -29
  40. package/dist/common/lockdown/lockdown.cjs.map +0 -1
  41. package/dist/common/lockdown/lockdown.d.cts +0 -7
  42. package/dist/common/lockdown/lockdown.d.cts.map +0 -1
  43. package/dist/common/lockdown/lockdown.d.mts +0 -7
  44. package/dist/common/lockdown/lockdown.d.mts.map +0 -1
  45. package/dist/common/lockdown/lockdown.mjs +0 -25
  46. package/dist/common/lockdown/lockdown.mjs.map +0 -1
  47. package/dist/common/sortParams.cjs +0 -35
  48. package/dist/common/sortParams.cjs.map +0 -1
  49. package/dist/common/sortParams.d.cts +0 -17
  50. package/dist/common/sortParams.d.cts.map +0 -1
  51. package/dist/common/sortParams.d.mts +0 -17
  52. package/dist/common/sortParams.d.mts.map +0 -1
  53. package/dist/common/sortParams.mjs +0 -31
  54. package/dist/common/sortParams.mjs.map +0 -1
package/CHANGELOG.md CHANGED
@@ -7,6 +7,19 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [11.0.0]
11
+
12
+ ### Changed
13
+
14
+ - **BREAKING:** Pass executor parameters by object ([#3803](https://github.com/MetaMask/snaps/pull/3803))
15
+
16
+ ## [10.4.1]
17
+
18
+ ### Fixed
19
+
20
+ - Inspect `wallet_invokeMethod` requests before sending ([#3819](https://github.com/MetaMask/snaps/pull/3819))
21
+ - Block `metamask_sendDomainMetadata` ([#3818](https://github.com/MetaMask/snaps/pull/3818))
22
+
10
23
  ## [10.4.0]
11
24
 
12
25
  ### Added
@@ -591,7 +604,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
591
604
  - The version of the package no longer needs to match the version of all other
592
605
  MetaMask Snaps packages.
593
606
 
594
- [Unreleased]: https://github.com/MetaMask/snaps/compare/@metamask/snaps-execution-environments@10.4.0...HEAD
607
+ [Unreleased]: https://github.com/MetaMask/snaps/compare/@metamask/snaps-execution-environments@11.0.0...HEAD
608
+ [11.0.0]: https://github.com/MetaMask/snaps/compare/@metamask/snaps-execution-environments@10.4.1...@metamask/snaps-execution-environments@11.0.0
609
+ [10.4.1]: https://github.com/MetaMask/snaps/compare/@metamask/snaps-execution-environments@10.4.0...@metamask/snaps-execution-environments@10.4.1
595
610
  [10.4.0]: https://github.com/MetaMask/snaps/compare/@metamask/snaps-execution-environments@10.3.0...@metamask/snaps-execution-environments@10.4.0
596
611
  [10.3.0]: https://github.com/MetaMask/snaps/compare/@metamask/snaps-execution-environments@10.2.3...@metamask/snaps-execution-environments@10.3.0
597
612
  [10.2.3]: https://github.com/MetaMask/snaps/compare/@metamask/snaps-execution-environments@10.2.2...@metamask/snaps-execution-environments@10.2.3
@@ -18,7 +18,6 @@ const commands_1 = require("./commands.cjs");
18
18
  const endowments_1 = require("./endowments/index.cjs");
19
19
  const globalEvents_1 = require("./globalEvents.cjs");
20
20
  const SnapProvider_1 = require("./SnapProvider.cjs");
21
- const sortParams_1 = require("./sortParams.cjs");
22
21
  const utils_2 = require("./utils.cjs");
23
22
  const validation_1 = require("./validation.cjs");
24
23
  const logging_1 = require("../logging.cjs");
@@ -31,109 +30,31 @@ const unhandledError = rpc_errors_1.rpcErrors
31
30
  message: 'Unhandled Snap Error',
32
31
  })
33
32
  .serialize();
34
- /**
35
- * The supported methods in the execution environment. The validator checks the
36
- * incoming JSON-RPC request, and the `params` property is used for sorting the
37
- * parameters, if they are an object.
38
- */
39
- const EXECUTION_ENVIRONMENT_METHODS = {
40
- ping: {
41
- struct: validation_1.PingRequestArgumentsStruct,
42
- params: [],
43
- },
44
- executeSnap: {
45
- struct: validation_1.ExecuteSnapRequestArgumentsStruct,
46
- params: ['snapId', 'sourceCode', 'endowments'],
47
- },
48
- terminate: {
49
- struct: validation_1.TerminateRequestArgumentsStruct,
50
- params: [],
51
- },
52
- snapRpc: {
53
- struct: validation_1.SnapRpcRequestArgumentsStruct,
54
- params: ['target', 'handler', 'origin', 'request'],
55
- },
56
- };
57
33
  class BaseSnapExecutor {
58
- // TODO: Either fix this lint violation or explain why it's necessary to
59
- // ignore.
60
- // eslint-disable-next-line no-restricted-syntax
61
- snapData;
62
- // TODO: Either fix this lint violation or explain why it's necessary to
63
- // ignore.
64
- // eslint-disable-next-line no-restricted-syntax
65
- commandStream;
66
- // TODO: Either fix this lint violation or explain why it's necessary to
67
- // ignore.
68
- // eslint-disable-next-line no-restricted-syntax
69
- rpcStream;
70
- // TODO: Either fix this lint violation or explain why it's necessary to
71
- // ignore.
72
- // eslint-disable-next-line no-restricted-syntax
73
- methods;
74
- // TODO: Either fix this lint violation or explain why it's necessary to
75
- // ignore.
76
- // eslint-disable-next-line no-restricted-syntax
77
- snapErrorHandler;
78
- // TODO: Either fix this lint violation or explain why it's necessary to
79
- // ignore.
80
- // eslint-disable-next-line no-restricted-syntax
81
- snapPromiseErrorHandler;
82
- // TODO: Either fix this lint violation or explain why it's necessary to
83
- // ignore.
84
- // eslint-disable-next-line no-restricted-syntax
85
- lastTeardown = 0;
34
+ #snapData;
35
+ #commandStream;
36
+ #rpcStream;
37
+ #snapErrorHandler;
38
+ #snapPromiseErrorHandler;
39
+ #teardownRef = { lastTeardown: 0 };
86
40
  constructor(commandStream, rpcStream) {
87
- this.snapData = new Map();
88
- this.commandStream = commandStream;
89
- this.commandStream.on('data', (data) => {
90
- this.onCommandRequest(data).catch((error) => {
91
- // TODO: Decide how to handle errors.
41
+ this.#snapData = new Map();
42
+ this.#commandStream = commandStream;
43
+ this.#commandStream.on('data', (data) => {
44
+ /* istanbul ignore next 2 */
45
+ this.#onCommandRequest(data).catch((error) => {
92
46
  (0, snaps_utils_1.logError)(error);
93
47
  });
94
48
  });
95
- this.rpcStream = rpcStream;
96
- this.methods = (0, commands_1.getCommandMethodImplementations)(this.startSnap.bind(this), async (target, handlerType, args) => {
97
- const data = this.snapData.get(target);
98
- // We're capturing the handler in case someone modifies the data object
99
- // before the call.
100
- const handler = data?.exports[handlerType];
101
- const { required } = snaps_utils_1.SNAP_EXPORTS[handlerType];
102
- (0, utils_1.assert)(!required || handler !== undefined, `No ${handlerType} handler exported for snap "${target}".`, rpc_errors_1.rpcErrors.methodNotSupported);
103
- // Certain handlers are not required. If they are not exported, we
104
- // return null.
105
- if (!handler) {
106
- return null;
107
- }
108
- const result = await this.executeInSnapContext(target, async () =>
109
- // TODO: fix handler args type cast
110
- handler(args));
111
- // The handler might not return anything, but undefined is not valid JSON.
112
- if (result === undefined || result === null) {
113
- return null;
114
- }
115
- // /!\ Always return only sanitized JSON to prevent security flaws. /!\
116
- try {
117
- return (0, utils_1.getSafeJson)(result);
118
- }
119
- catch (error) {
120
- throw rpc_errors_1.rpcErrors.internal(`Received non-JSON-serializable value: ${error.message.replace(/^Assertion failed: /u, '')}`);
121
- }
122
- }, this.onTerminate.bind(this));
49
+ this.#rpcStream = rpcStream;
123
50
  }
124
- // TODO: Either fix this lint violation or explain why it's necessary to
125
- // ignore.
126
- // eslint-disable-next-line no-restricted-syntax
127
- errorHandler(error, data) {
51
+ #errorHandler(error, data) {
128
52
  const serializedError = (0, rpc_errors_1.serializeError)(error, {
129
53
  fallbackError: unhandledError,
130
54
  shouldIncludeStack: false,
131
55
  shouldPreserveMessage: false,
132
56
  });
133
57
  const errorData = (0, snaps_sdk_1.getErrorData)(serializedError);
134
- // TODO: Either fix this lint violation or explain why it's necessary to
135
- // ignore.
136
- // eslint-disable-next-line promise/no-promise-in-callback
137
58
  this.#notify({
138
59
  method: 'UnhandledError',
139
60
  params: {
@@ -149,19 +70,14 @@ class BaseSnapExecutor {
149
70
  (0, snaps_utils_1.logError)(notifyError);
150
71
  });
151
72
  }
152
- // TODO: Either fix this lint violation or explain why it's necessary to
153
- // ignore.
154
- // eslint-disable-next-line no-restricted-syntax
155
- async onCommandRequest(message) {
73
+ async #onCommandRequest(message) {
156
74
  if (!(0, utils_1.isJsonRpcRequest)(message)) {
157
75
  if ((0, utils_1.hasProperty)(message, 'id') &&
158
76
  (0, superstruct_1.is)(message.id, utils_1.JsonRpcIdStruct)) {
159
77
  // Instead of throwing, we directly respond with an error.
160
78
  // We can only do this if the message ID is still valid.
161
- await this.#write({
79
+ await this.#respond(message.id, {
162
80
  error: (0, rpc_errors_1.serializeError)(rpc_errors_1.rpcErrors.internal('JSON-RPC requests must be JSON serializable objects.')),
163
- id: message.id,
164
- jsonrpc: '2.0',
165
81
  });
166
82
  }
167
83
  else {
@@ -170,38 +86,8 @@ class BaseSnapExecutor {
170
86
  return;
171
87
  }
172
88
  const { id, method, params } = message;
173
- if (!(0, utils_1.hasProperty)(EXECUTION_ENVIRONMENT_METHODS, method)) {
174
- await this.#respond(id, {
175
- error: rpc_errors_1.rpcErrors
176
- .methodNotFound({
177
- data: {
178
- method,
179
- },
180
- })
181
- .serialize(),
182
- });
183
- return;
184
- }
185
- const methodObject = EXECUTION_ENVIRONMENT_METHODS[method];
186
- // support params by-name and by-position
187
- const paramsAsArray = (0, sortParams_1.sortParamKeys)(methodObject.params, params);
188
- const [error] = (0, superstruct_1.validate)(paramsAsArray, methodObject.struct);
189
- if (error) {
190
- await this.#respond(id, {
191
- error: rpc_errors_1.rpcErrors
192
- .invalidParams({
193
- message: `Invalid parameters for method "${method}": ${error.message}.`,
194
- data: {
195
- method,
196
- params: paramsAsArray,
197
- },
198
- })
199
- .serialize(),
200
- });
201
- return;
202
- }
203
89
  try {
204
- const result = await this.methods[method](...paramsAsArray);
90
+ const result = await this.#handleCommand(method, params);
205
91
  await this.#respond(id, { result });
206
92
  }
207
93
  catch (rpcError) {
@@ -213,12 +99,83 @@ class BaseSnapExecutor {
213
99
  });
214
100
  }
215
101
  }
102
+ /**
103
+ * Handle an incoming JSON-RPC command request.
104
+ *
105
+ * @param method - The JSON-RPC method name.
106
+ * @param params - The optional JSON-RPC parameters.
107
+ * @returns The response based on the JSON-RPC method invoked.
108
+ * @throws If the passed method is not available.
109
+ */
110
+ async #handleCommand(method, params) {
111
+ switch (method) {
112
+ case 'ping':
113
+ return 'OK';
114
+ case 'terminate': {
115
+ this.#handleTerminate();
116
+ return 'OK';
117
+ }
118
+ case 'executeSnap': {
119
+ (0, commands_1.assertCommandParams)(method, params, validation_1.ExecuteSnapRequestArgumentsStruct);
120
+ await this.#startSnap(params);
121
+ return 'OK';
122
+ }
123
+ case 'snapRpc': {
124
+ (0, commands_1.assertCommandParams)(method, params, validation_1.SnapRpcRequestArgumentsStruct);
125
+ return await this.#invokeSnap(params);
126
+ }
127
+ default:
128
+ throw rpc_errors_1.rpcErrors.methodNotFound({
129
+ data: {
130
+ method,
131
+ },
132
+ });
133
+ }
134
+ }
135
+ /**
136
+ * Invoke an exported handler on a running Snap.
137
+ *
138
+ * @param options - An options bag.
139
+ * @param options.snapId - The Snap ID.
140
+ * @param options.handler - The handler to invoke.
141
+ * @param options.origin - The origin invoking the handler.
142
+ * @param options.request - The JSON-RPC request to invoke the handler with.
143
+ * @returns The result of invoking the handler on the Snap.
144
+ */
145
+ async #invokeSnap({ snapId, handler: handlerType, origin, request, }) {
146
+ const args = (0, commands_1.getHandlerArguments)(origin, handlerType, request);
147
+ const data = this.#snapData.get(snapId);
148
+ // We're capturing the handler in case someone modifies the data object
149
+ // before the call.
150
+ const handler = data?.exports[handlerType];
151
+ const { required } = snaps_utils_1.SNAP_EXPORTS[handlerType];
152
+ (0, utils_1.assert)(!required || handler !== undefined, `No ${handlerType} handler exported for Snap "${snapId}".`, rpc_errors_1.rpcErrors.methodNotSupported);
153
+ // Certain handlers are not required. If they are not exported, we
154
+ // return null.
155
+ if (!handler) {
156
+ return null;
157
+ }
158
+ const result = await this.#executeInSnapContext(snapId, async () =>
159
+ // TODO: fix handler args type cast
160
+ handler(args));
161
+ // The handler might not return anything, but undefined is not valid JSON.
162
+ if (result === undefined || result === null) {
163
+ return null;
164
+ }
165
+ // /!\ Always return only sanitized JSON to prevent security flaws. /!\
166
+ try {
167
+ return (0, utils_1.getSafeJson)(result);
168
+ }
169
+ catch (error) {
170
+ throw rpc_errors_1.rpcErrors.internal(`Received non-JSON-serializable value: ${error.message.replace(/^Assertion failed: /u, '')}`);
171
+ }
172
+ }
216
173
  // Awaitable function that writes back to the command stream
217
174
  // To prevent snap execution from blocking writing we wrap in a promise
218
175
  // and await it before continuing execution
219
176
  async #write(chunk) {
220
177
  return new Promise((resolve, reject) => {
221
- this.commandStream.write(chunk, (error) => {
178
+ this.#commandStream.write(chunk, (error) => {
222
179
  if (error) {
223
180
  reject(error);
224
181
  return;
@@ -257,28 +214,29 @@ class BaseSnapExecutor {
257
214
  * Attempts to evaluate a snap in SES. Generates APIs for the snap. May throw
258
215
  * on errors.
259
216
  *
260
- * @param snapId - The id of the snap.
261
- * @param sourceCode - The source code of the snap, in IIFE format.
262
- * @param _endowments - An array of the names of the endowments.
217
+ * @param params - The parameters.
218
+ * @param params.snapId - The id of the snap.
219
+ * @param params.sourceCode - The source code of the snap, in IIFE format.
220
+ * @param params.endowments - An array of the names of the endowments.
263
221
  */
264
- async startSnap(snapId, sourceCode, _endowments) {
222
+ async #startSnap({ snapId, sourceCode, endowments: endowmentKeys, }) {
265
223
  (0, logging_1.log)(`Starting snap '${snapId}' in worker.`);
266
- if (this.snapPromiseErrorHandler) {
267
- (0, globalEvents_1.removeEventListener)('unhandledrejection', this.snapPromiseErrorHandler);
224
+ if (this.#snapPromiseErrorHandler) {
225
+ (0, globalEvents_1.removeEventListener)('unhandledrejection', this.#snapPromiseErrorHandler);
268
226
  }
269
- if (this.snapErrorHandler) {
270
- (0, globalEvents_1.removeEventListener)('error', this.snapErrorHandler);
227
+ if (this.#snapErrorHandler) {
228
+ (0, globalEvents_1.removeEventListener)('error', this.#snapErrorHandler);
271
229
  }
272
- this.snapErrorHandler = (error) => {
273
- this.errorHandler(error.error, { snapId });
230
+ this.#snapErrorHandler = (error) => {
231
+ this.#errorHandler(error.error, { snapId });
274
232
  };
275
- this.snapPromiseErrorHandler = (error) => {
276
- this.errorHandler(error instanceof Error ? error : error.reason, {
233
+ this.#snapPromiseErrorHandler = (error) => {
234
+ this.#errorHandler(error instanceof Error ? error : error.reason, {
277
235
  snapId,
278
236
  });
279
237
  };
280
238
  const multiplex = new object_multiplex_1.default();
281
- (0, readable_stream_1.pipeline)(this.rpcStream, multiplex, this.rpcStream, (error) => {
239
+ (0, readable_stream_1.pipeline)(this.#rpcStream, multiplex, this.#rpcStream, (error) => {
282
240
  if (error && !error.message?.match('Premature close')) {
283
241
  (0, snaps_utils_1.logError)(`Provider stream failure.`, error);
284
242
  }
@@ -291,8 +249,8 @@ class BaseSnapExecutor {
291
249
  rpcMiddleware: [(0, json_rpc_engine_1.createIdRemapMiddleware)()],
292
250
  });
293
251
  multichainProvider.initializeSync();
294
- const snap = this.createSnapGlobal(provider, multichainProvider);
295
- const ethereum = this.createEIP1193Provider(provider);
252
+ const snap = this.#createSnapGlobal(provider, multichainProvider);
253
+ const ethereum = this.#createEIP1193Provider(provider);
296
254
  // We specifically use any type because the Snap can modify the object any way they want
297
255
  const snapModule = { exports: {} };
298
256
  try {
@@ -300,18 +258,18 @@ class BaseSnapExecutor {
300
258
  snap,
301
259
  ethereum,
302
260
  snapId,
303
- endowments: _endowments,
261
+ endowments: endowmentKeys,
304
262
  notify: this.#notify.bind(this),
305
263
  });
306
264
  // !!! Ensure that this is the only place the data is being set.
307
265
  // Other methods access the object value and mutate its properties.
308
- this.snapData.set(snapId, {
266
+ this.#snapData.set(snapId, {
309
267
  idleTeardown: endowmentTeardown,
310
268
  runningEvaluations: new Set(),
311
269
  exports: {},
312
270
  });
313
- (0, globalEvents_1.addEventListener)('unhandledRejection', this.snapPromiseErrorHandler);
314
- (0, globalEvents_1.addEventListener)('error', this.snapErrorHandler);
271
+ (0, globalEvents_1.addEventListener)('unhandledRejection', this.#snapPromiseErrorHandler);
272
+ (0, globalEvents_1.addEventListener)('error', this.#snapErrorHandler);
315
273
  const compartment = new Compartment({
316
274
  ...endowments,
317
275
  module: snapModule,
@@ -325,13 +283,13 @@ class BaseSnapExecutor {
325
283
  compartment.globalThis.self = compartment.globalThis;
326
284
  compartment.globalThis.global = compartment.globalThis;
327
285
  compartment.globalThis.window = compartment.globalThis;
328
- await this.executeInSnapContext(snapId, async () => {
286
+ await this.#executeInSnapContext(snapId, async () => {
329
287
  compartment.evaluate(sourceCode);
330
- await this.registerSnapExports(snapId, snapModule);
288
+ await this.#registerSnapExports(snapId, snapModule);
331
289
  });
332
290
  }
333
291
  catch (error) {
334
- this.removeSnap(snapId);
292
+ this.#removeSnap(snapId);
335
293
  const [cause] = (0, snaps_utils_1.unwrapError)(error);
336
294
  throw rpc_errors_1.rpcErrors.internal({
337
295
  message: `Error while running snap '${snapId}': ${cause.message}`,
@@ -345,18 +303,15 @@ class BaseSnapExecutor {
345
303
  * Cancels all running evaluations of all snaps and clears all snap data.
346
304
  * NOTE:** Should only be called in response to the `terminate` RPC command.
347
305
  */
348
- onTerminate() {
306
+ #handleTerminate() {
349
307
  // `stop()` tears down snap endowments.
350
308
  // Teardown will also be run for each snap as soon as there are
351
309
  // no more running evaluations for that snap.
352
- this.snapData.forEach((data) => data.runningEvaluations.forEach((evaluation) => evaluation.stop()));
353
- this.snapData.clear();
310
+ this.#snapData.forEach((data) => data.runningEvaluations.forEach((evaluation) => evaluation.stop()));
311
+ this.#snapData.clear();
354
312
  }
355
- // TODO: Either fix this lint violation or explain why it's necessary to
356
- // ignore.
357
- // eslint-disable-next-line no-restricted-syntax
358
- async registerSnapExports(snapId, snapModule) {
359
- const data = this.snapData.get(snapId);
313
+ async #registerSnapExports(snapId, snapModule) {
314
+ const data = this.#snapData.get(snapId);
360
315
  // Somebody deleted the snap before we could register.
361
316
  if (!data) {
362
317
  return;
@@ -381,10 +336,7 @@ class BaseSnapExecutor {
381
336
  * @param multichainProvider - A StreamProvider connected to the CAIP-27 client stream.
382
337
  * @returns The snap provider object.
383
338
  */
384
- // TODO: Either fix this lint violation or explain why it's necessary to
385
- // ignore.
386
- // eslint-disable-next-line no-restricted-syntax
387
- createSnapGlobal(provider, multichainProvider) {
339
+ #createSnapGlobal(provider, multichainProvider) {
388
340
  const originalRequest = provider.request.bind(provider);
389
341
  const originalMultichainRequest = multichainProvider.request.bind(multichainProvider);
390
342
  const request = async (args) => {
@@ -392,9 +344,10 @@ class BaseSnapExecutor {
392
344
  const sanitizedArgs = (0, utils_2.sanitizeRequestArguments)(args);
393
345
  (0, utils_2.assertSnapOutboundRequest)(sanitizedArgs);
394
346
  if ((0, utils_2.isMultichainRequest)(sanitizedArgs)) {
395
- return await (0, utils_2.withTeardown)(originalMultichainRequest(sanitizedArgs), this);
347
+ (0, utils_2.assertMultichainOutboundRequest)(sanitizedArgs);
348
+ return await (0, utils_2.withTeardown)(originalMultichainRequest(sanitizedArgs), this.#teardownRef);
396
349
  }
397
- return await (0, utils_2.withTeardown)(originalRequest(sanitizedArgs), this);
350
+ return await (0, utils_2.withTeardown)(originalRequest(sanitizedArgs), this.#teardownRef);
398
351
  };
399
352
  const snapsProvider = { request };
400
353
  return harden(snapsProvider);
@@ -405,16 +358,13 @@ class BaseSnapExecutor {
405
358
  * @param provider - A StreamProvider connected to MetaMask.
406
359
  * @returns The EIP-1193 Ethereum provider object.
407
360
  */
408
- // TODO: Either fix this lint violation or explain why it's necessary to
409
- // ignore.
410
- // eslint-disable-next-line no-restricted-syntax
411
- createEIP1193Provider(provider) {
361
+ #createEIP1193Provider(provider) {
412
362
  const originalRequest = provider.request.bind(provider);
413
363
  const request = async (args) => {
414
364
  // As part of the sanitization, we validate that the args are valid JSON.
415
365
  const sanitizedArgs = (0, utils_2.sanitizeRequestArguments)(args);
416
366
  (0, utils_2.assertEthereumOutboundRequest)(sanitizedArgs);
417
- return await (0, utils_2.withTeardown)(originalRequest(sanitizedArgs), this);
367
+ return await (0, utils_2.withTeardown)(originalRequest(sanitizedArgs), this.#teardownRef);
418
368
  };
419
369
  const ethereumProvider = { request };
420
370
  return harden(ethereumProvider);
@@ -424,11 +374,8 @@ class BaseSnapExecutor {
424
374
  *
425
375
  * @param snapId - The id of the snap to remove.
426
376
  */
427
- // TODO: Either fix this lint violation or explain why it's necessary to
428
- // ignore.
429
- // eslint-disable-next-line no-restricted-syntax
430
- removeSnap(snapId) {
431
- this.snapData.delete(snapId);
377
+ #removeSnap(snapId) {
378
+ this.#snapData.delete(snapId);
432
379
  }
433
380
  /**
434
381
  * Calls the specified executor function in the context of the specified snap.
@@ -441,20 +388,14 @@ class BaseSnapExecutor {
441
388
  * @returns The executor's return value.
442
389
  * @template Result - The return value of the executor.
443
390
  */
444
- // TODO: Either fix this lint violation or explain why it's necessary to
445
- // ignore.
446
- // eslint-disable-next-line no-restricted-syntax
447
- async executeInSnapContext(snapId, executor) {
448
- const data = this.snapData.get(snapId);
391
+ async #executeInSnapContext(snapId, executor) {
392
+ const data = this.#snapData.get(snapId);
449
393
  if (data === undefined) {
450
394
  throw rpc_errors_1.rpcErrors.internal(`Tried to execute in context of unknown snap: "${snapId}".`);
451
395
  }
452
- let stop;
453
- const stopPromise = new Promise((_resolve, reject) => (stop = () => reject(
454
- // TODO(rekmarks): Specify / standardize error code for this case.
455
- rpc_errors_1.rpcErrors.internal(`The snap "${snapId}" has been terminated during execution.`))));
456
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
457
- const evaluationData = { stop: stop };
396
+ const { promise: stopPromise, reject } = (0, utils_1.createDeferredPromise)();
397
+ const stop = () => reject(rpc_errors_1.rpcErrors.internal(`The Snap "${snapId}" has been terminated during execution.`));
398
+ const evaluationData = { stop };
458
399
  try {
459
400
  data.runningEvaluations.add(evaluationData);
460
401
  // Notice that we have to await this executor.
@@ -468,7 +409,7 @@ class BaseSnapExecutor {
468
409
  finally {
469
410
  data.runningEvaluations.delete(evaluationData);
470
411
  if (data.runningEvaluations.size === 0) {
471
- this.lastTeardown += 1;
412
+ this.#teardownRef.lastTeardown += 1;
472
413
  await data.idleTeardown();
473
414
  }
474
415
  }