@metamask/snaps-execution-environments 0.24.0 → 0.25.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 (33) hide show
  1. package/dist/common/BaseSnapExecutor.d.ts +6 -6
  2. package/dist/common/BaseSnapExecutor.js +17 -10
  3. package/dist/common/BaseSnapExecutor.js.map +1 -1
  4. package/dist/common/commands.js +3 -5
  5. package/dist/common/commands.js.map +1 -1
  6. package/dist/common/endowments/index.d.ts +1 -1
  7. package/dist/common/endowments/index.js +2 -2
  8. package/dist/common/endowments/index.js.map +1 -1
  9. package/dist/common/endowments/interval.d.ts +1 -1
  10. package/dist/common/endowments/math.d.ts +43 -43
  11. package/dist/common/endowments/math.js.map +1 -1
  12. package/dist/common/endowments/network.d.ts +7 -7
  13. package/dist/common/endowments/network.js +24 -20
  14. package/dist/common/endowments/network.js.map +1 -1
  15. package/dist/common/endowments/timeout.d.ts +1 -1
  16. package/dist/common/globalObject.js +2 -0
  17. package/dist/common/globalObject.js.map +1 -1
  18. package/dist/common/sortParams.js +1 -1
  19. package/dist/common/sortParams.js.map +1 -1
  20. package/dist/common/utils.js +1 -1
  21. package/dist/common/utils.js.map +1 -1
  22. package/dist/common/validation.js.map +1 -1
  23. package/dist/iframe/IFrameSnapExecutor.js +4 -4
  24. package/dist/iframe/IFrameSnapExecutor.js.map +1 -1
  25. package/dist/node-process/ChildProcessSnapExecutor.js +4 -4
  26. package/dist/node-process/ChildProcessSnapExecutor.js.map +1 -1
  27. package/dist/node-thread/ThreadSnapExecutor.js +4 -4
  28. package/dist/node-thread/ThreadSnapExecutor.js.map +1 -1
  29. package/dist/webpack/iframe/bundle.js +1 -1
  30. package/dist/webpack/iframe/bundle.js.LICENSE.txt +6 -0
  31. package/dist/webpack/node-process/bundle.js +1 -1
  32. package/dist/webpack/node-thread/bundle.js +1 -1
  33. package/package.json +19 -17
@@ -1,15 +1,15 @@
1
1
  /// <reference types="node" />
2
2
  /// <reference types="ses" />
3
- import { Duplex } from 'stream';
4
- import { JsonRpcNotification, JsonRpcId, Json } from '@metamask/utils';
5
3
  import { HandlerType, SnapExportsParameters } from '@metamask/snaps-utils';
4
+ import { JsonRpcNotification, JsonRpcId, Json } from '@metamask/utils';
5
+ import { Duplex } from 'stream';
6
6
  export declare type InvokeSnapArgs = Omit<SnapExportsParameters[0], 'chainId'>;
7
7
  export declare type InvokeSnap = (target: string, handler: HandlerType, args: InvokeSnapArgs | undefined) => Promise<Json>;
8
8
  export declare class BaseSnapExecutor {
9
- private snapData;
10
- private commandStream;
11
- private rpcStream;
12
- private methods;
9
+ private readonly snapData;
10
+ private readonly commandStream;
11
+ private readonly rpcStream;
12
+ private readonly methods;
13
13
  private snapErrorHandler?;
14
14
  private snapPromiseErrorHandler?;
15
15
  private lastTeardown;
@@ -4,11 +4,13 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.BaseSnapExecutor = void 0;
7
+ // eslint-disable-next-line @typescript-eslint/triple-slash-reference, spaced-comment
8
+ /// <reference path="../../../../node_modules/ses/index.d.ts" />
7
9
  const providers_1 = require("@metamask/providers");
8
- const json_rpc_engine_1 = require("json-rpc-engine");
9
- const eth_rpc_errors_1 = require("eth-rpc-errors");
10
- const utils_1 = require("@metamask/utils");
11
10
  const snaps_utils_1 = require("@metamask/snaps-utils");
11
+ const utils_1 = require("@metamask/utils");
12
+ const eth_rpc_errors_1 = require("eth-rpc-errors");
13
+ const json_rpc_engine_1 = require("json-rpc-engine");
12
14
  const superstruct_1 = require("superstruct");
13
15
  const openrpc_json_1 = __importDefault(require("../openrpc.json"));
14
16
  const commands_1 = require("./commands");
@@ -50,7 +52,12 @@ class BaseSnapExecutor {
50
52
  this.lastTeardown = 0;
51
53
  this.snapData = new Map();
52
54
  this.commandStream = commandStream;
53
- this.commandStream.on('data', this.onCommandRequest.bind(this));
55
+ this.commandStream.on('data', (data) => {
56
+ this.onCommandRequest(data).catch((error) => {
57
+ // TODO: Decide how to handle errors.
58
+ console.error(error);
59
+ });
60
+ });
54
61
  this.rpcStream = rpcStream;
55
62
  this.methods = (0, commands_1.getCommandMethodImplementations)(this.startSnap.bind(this), async (target, handlerName, args) => {
56
63
  const data = this.snapData.get(target);
@@ -130,9 +137,9 @@ class BaseSnapExecutor {
130
137
  const result = await this.methods[method](...paramsAsArray);
131
138
  this.respond(id, { result });
132
139
  }
133
- catch (e) {
140
+ catch (rpcError) {
134
141
  this.respond(id, {
135
- error: (0, eth_rpc_errors_1.serializeError)(e, {
142
+ error: (0, eth_rpc_errors_1.serializeError)(rpcError, {
136
143
  fallbackError,
137
144
  }),
138
145
  });
@@ -200,9 +207,9 @@ class BaseSnapExecutor {
200
207
  this.registerSnapExports(snapName, snapModule);
201
208
  });
202
209
  }
203
- catch (err) {
210
+ catch (error) {
204
211
  this.removeSnap(snapName);
205
- throw new Error(`Error while running snap '${snapName}': ${err.message}`);
212
+ throw new Error(`Error while running snap '${snapName}': ${error.message}`);
206
213
  }
207
214
  }
208
215
  /**
@@ -237,7 +244,7 @@ class BaseSnapExecutor {
237
244
  * @returns The snap provider object.
238
245
  */
239
246
  createSnapGlobal(provider) {
240
- const originalRequest = provider.request;
247
+ const originalRequest = provider.request.bind(provider);
241
248
  const request = async (args) => {
242
249
  (0, utils_1.assert)(args.method.startsWith('wallet_') || args.method.startsWith('snap_'), 'The global Snap API only allows RPC methods starting with `wallet_*` and `snap_*`.');
243
250
  this.notify({ method: 'OutboundRequest' });
@@ -257,7 +264,7 @@ class BaseSnapExecutor {
257
264
  * @returns The EIP-1193 Ethereum provider object.
258
265
  */
259
266
  createEIP1193Provider(provider) {
260
- const originalRequest = provider.request;
267
+ const originalRequest = provider.request.bind(provider);
261
268
  provider.request = async (args) => {
262
269
  (0, utils_1.assert)(!args.method.startsWith('snap_'), eth_rpc_errors_1.ethErrors.rpc.methodNotFound({
263
270
  data: {
@@ -1 +1 @@
1
- {"version":3,"file":"BaseSnapExecutor.js","sourceRoot":"","sources":["../../src/common/BaseSnapExecutor.ts"],"names":[],"mappings":"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","sourcesContent":["// eslint-disable-next-line @typescript-eslint/triple-slash-reference, spaced-comment\n/// <reference path=\"../../../../node_modules/ses/index.d.ts\" />\nimport { Duplex } from 'stream';\nimport { StreamProvider } from '@metamask/providers';\nimport { createIdRemapMiddleware } from 'json-rpc-engine';\nimport { SnapExports, SnapsGlobalObject } from '@metamask/snaps-types';\nimport { errorCodes, ethErrors, serializeError } from 'eth-rpc-errors';\nimport {\n isObject,\n isValidJson,\n JsonRpcNotification,\n assert,\n isJsonRpcRequest,\n JsonRpcId,\n JsonRpcRequest,\n JsonRpcParams,\n Json,\n hasProperty,\n} from '@metamask/utils';\nimport {\n HandlerType,\n SnapExportsParameters,\n SNAP_EXPORT_NAMES,\n} from '@metamask/snaps-utils';\n\nimport { validate } from 'superstruct';\nimport { RequestArguments } from '@metamask/providers/dist/BaseProvider';\nimport EEOpenRPCDocument from '../openrpc.json';\nimport {\n CommandMethodsMapping,\n getCommandMethodImplementations,\n} from './commands';\nimport { createEndowments } from './endowments';\nimport { addEventListener, removeEventListener } from './globalEvents';\nimport { wrapKeyring } from './keyring';\nimport { sortParamKeys } from './sortParams';\nimport { constructError, withTeardown } from './utils';\nimport {\n ExecuteSnapRequestArgumentsStruct,\n PingRequestArgumentsStruct,\n SnapRpcRequestArgumentsStruct,\n TerminateRequestArgumentsStruct,\n validateExport,\n} from './validation';\n\ntype EvaluationData = {\n stop: () => void;\n};\n\ntype SnapData = {\n exports: SnapExports;\n runningEvaluations: Set<EvaluationData>;\n idleTeardown: () => Promise<void>;\n};\n\nconst fallbackError = {\n code: errorCodes.rpc.internal,\n message: 'Execution Environment Error',\n};\n\n// TODO: `KeyringParameters` expects a `chainId` for certain methods, but we're\n// not providing it in `getHandlerArguments`, resulting in type errors.\nexport type InvokeSnapArgs = Omit<SnapExportsParameters[0], 'chainId'>;\n\nexport type InvokeSnap = (\n target: string,\n handler: HandlerType,\n args: InvokeSnapArgs | undefined,\n) => Promise<Json>;\n\n/**\n * The supported methods in the execution environment. The validator checks the\n * incoming JSON-RPC request, and the `params` property is used for sorting the\n * parameters, if they are an object.\n */\nconst EXECUTION_ENVIRONMENT_METHODS = {\n ping: {\n struct: PingRequestArgumentsStruct,\n params: [],\n },\n executeSnap: {\n struct: ExecuteSnapRequestArgumentsStruct,\n params: ['snapName', 'sourceCode', 'endowments'],\n },\n terminate: {\n struct: TerminateRequestArgumentsStruct,\n params: [],\n },\n snapRpc: {\n struct: SnapRpcRequestArgumentsStruct,\n params: ['target', 'handler', 'origin', 'request'],\n },\n};\n\nexport class BaseSnapExecutor {\n private snapData: Map<string, SnapData>;\n\n private commandStream: Duplex;\n\n private rpcStream: Duplex;\n\n private methods: CommandMethodsMapping;\n\n private snapErrorHandler?: (event: ErrorEvent) => void;\n\n private snapPromiseErrorHandler?: (event: PromiseRejectionEvent) => void;\n\n private lastTeardown = 0;\n\n protected constructor(commandStream: Duplex, rpcStream: Duplex) {\n this.snapData = new Map();\n this.commandStream = commandStream;\n this.commandStream.on('data', this.onCommandRequest.bind(this));\n this.rpcStream = rpcStream;\n\n this.methods = getCommandMethodImplementations(\n this.startSnap.bind(this),\n async (target, handlerName, args) => {\n const data = this.snapData.get(target);\n // We're capturing the handler in case someone modifies the data object before the call\n const handler =\n handlerName === HandlerType.SnapKeyring\n ? wrapKeyring(this.notify.bind(this), data?.exports.keyring)\n : data?.exports[handlerName];\n assert(\n handler !== undefined,\n `No ${handlerName} handler exported for snap \"${target}`,\n );\n // TODO: fix handler args type cast\n let result = await this.executeInSnapContext(target, () =>\n handler(args as any),\n );\n\n // The handler might not return anything, but undefined is not valid JSON.\n if (result === undefined) {\n result = null;\n }\n\n assert(\n isValidJson(result),\n new TypeError('Received non-JSON-serializable value.'),\n );\n return result;\n },\n this.onTerminate.bind(this),\n );\n }\n\n private errorHandler(error: unknown, data: Record<string, Json>) {\n const constructedError = constructError(error);\n const serializedError = serializeError(constructedError, {\n fallbackError,\n shouldIncludeStack: false,\n });\n\n // We're setting it this way to avoid sentData.stack = undefined\n const sentData: Json = { ...data, stack: constructedError?.stack ?? null };\n\n this.notify({\n method: 'UnhandledError',\n params: {\n error: {\n ...serializedError,\n data: sentData,\n },\n },\n });\n }\n\n private async onCommandRequest(message: JsonRpcRequest<JsonRpcParams>) {\n if (!isJsonRpcRequest(message)) {\n throw new Error('Command stream received a non-JSON-RPC request.');\n }\n\n const { id, method, params } = message;\n if (method === 'rpc.discover') {\n this.respond(id, {\n result: EEOpenRPCDocument,\n });\n return;\n }\n\n if (!hasProperty(EXECUTION_ENVIRONMENT_METHODS, method)) {\n this.respond(id, {\n error: ethErrors.rpc\n .methodNotFound({\n data: {\n method,\n },\n })\n .serialize(),\n });\n return;\n }\n\n const methodObject =\n EXECUTION_ENVIRONMENT_METHODS[\n method as keyof typeof EXECUTION_ENVIRONMENT_METHODS\n ];\n\n // support params by-name and by-position\n const paramsAsArray = sortParamKeys(methodObject.params, params);\n\n const [error] = validate<any, any>(paramsAsArray, methodObject.struct);\n if (error) {\n this.respond(id, {\n error: ethErrors.rpc\n .invalidParams({\n message: `Invalid parameters for method \"${method}\": ${error.message}.`,\n data: {\n method,\n params: paramsAsArray,\n },\n })\n .serialize(),\n });\n return;\n }\n\n try {\n const result = await (this.methods as any)[method](...paramsAsArray);\n this.respond(id, { result });\n } catch (e) {\n this.respond(id, {\n error: serializeError(e, {\n fallbackError,\n }),\n });\n }\n }\n\n protected notify(\n requestObject: Omit<\n JsonRpcNotification<Record<string, Json> | Json[] | undefined>,\n 'jsonrpc'\n >,\n ) {\n if (!isValidJson(requestObject) || !isObject(requestObject)) {\n throw new Error(\n 'JSON-RPC notifications must be JSON serializable objects',\n );\n }\n\n this.commandStream.write({\n ...requestObject,\n jsonrpc: '2.0',\n });\n }\n\n protected respond(id: JsonRpcId, requestObject: Record<string, unknown>) {\n if (!isValidJson(requestObject) || !isObject(requestObject)) {\n throw new Error('JSON-RPC responses must be JSON serializable objects.');\n }\n\n this.commandStream.write({\n ...requestObject,\n id,\n jsonrpc: '2.0',\n });\n }\n\n /**\n * Attempts to evaluate a snap in SES. Generates APIs for the snap. May throw\n * on errors.\n *\n * @param snapName - The name of the snap.\n * @param sourceCode - The source code of the snap, in IIFE format.\n * @param _endowments - An array of the names of the endowments.\n */\n protected async startSnap(\n snapName: string,\n sourceCode: string,\n _endowments?: string[],\n ): Promise<void> {\n console.log(`starting snap '${snapName}' in worker`);\n if (this.snapPromiseErrorHandler) {\n removeEventListener('unhandledrejection', this.snapPromiseErrorHandler);\n }\n\n if (this.snapErrorHandler) {\n removeEventListener('error', this.snapErrorHandler);\n }\n\n this.snapErrorHandler = (error: ErrorEvent) => {\n this.errorHandler(error.error, { snapName });\n };\n\n this.snapPromiseErrorHandler = (error: PromiseRejectionEvent) => {\n this.errorHandler(error instanceof Error ? error : error.reason, {\n snapName,\n });\n };\n\n const provider = new StreamProvider(this.rpcStream, {\n jsonRpcStreamName: 'metamask-provider',\n rpcMiddleware: [createIdRemapMiddleware()],\n });\n\n await provider.initialize();\n\n const snap = this.createSnapGlobal(provider);\n const ethereum = this.createEIP1193Provider(provider);\n // We specifically use any type because the Snap can modify the object any way they want\n const snapModule: any = { exports: {} };\n\n try {\n const { endowments, teardown: endowmentTeardown } = createEndowments(\n snap,\n ethereum,\n _endowments,\n );\n\n // !!! Ensure that this is the only place the data is being set.\n // Other methods access the object value and mutate its properties.\n this.snapData.set(snapName, {\n idleTeardown: endowmentTeardown,\n runningEvaluations: new Set(),\n exports: {},\n });\n\n addEventListener('unhandledRejection', this.snapPromiseErrorHandler);\n addEventListener('error', this.snapErrorHandler);\n\n const compartment = new Compartment({\n ...endowments,\n module: snapModule,\n exports: snapModule.exports,\n window: { ...endowments },\n self: { ...endowments },\n });\n\n await this.executeInSnapContext(snapName, () => {\n compartment.evaluate(sourceCode);\n this.registerSnapExports(snapName, snapModule);\n });\n } catch (err) {\n this.removeSnap(snapName);\n throw new Error(\n `Error while running snap '${snapName}': ${(err as Error).message}`,\n );\n }\n }\n\n /**\n * Cancels all running evaluations of all snaps and clears all snap data.\n * NOTE:** Should only be called in response to the `terminate` RPC command.\n */\n protected onTerminate() {\n // `stop()` tears down snap endowments.\n // Teardown will also be run for each snap as soon as there are\n // no more running evaluations for that snap.\n this.snapData.forEach((data) =>\n data.runningEvaluations.forEach((evaluation) => evaluation.stop()),\n );\n this.snapData.clear();\n }\n\n private registerSnapExports(snapName: string, snapModule: any) {\n const data = this.snapData.get(snapName);\n // Somebody deleted the Snap before we could register\n if (!data) {\n return;\n }\n\n data.exports = SNAP_EXPORT_NAMES.reduce((acc, exportName) => {\n const snapExport = snapModule.exports[exportName];\n if (validateExport(exportName, snapExport)) {\n return { ...acc, [exportName]: snapExport };\n }\n return acc;\n }, {});\n }\n\n /**\n * Instantiates a snap API object (i.e. `globalThis.snap`).\n *\n * @param provider - A StreamProvider connected to MetaMask.\n * @returns The snap provider object.\n */\n private createSnapGlobal(provider: StreamProvider): SnapsGlobalObject {\n const originalRequest = provider.request;\n\n const request = async (args: RequestArguments) => {\n assert(\n args.method.startsWith('wallet_') || args.method.startsWith('snap_'),\n 'The global Snap API only allows RPC methods starting with `wallet_*` and `snap_*`.',\n );\n this.notify({ method: 'OutboundRequest' });\n try {\n return await withTeardown(originalRequest(args), this as any);\n } finally {\n this.notify({ method: 'OutboundResponse' });\n }\n };\n\n return { request };\n }\n\n /**\n * Instantiates an EIP-1193 Ethereum provider object (i.e. `globalThis.ethereum`).\n *\n * @param provider - A StreamProvider connected to MetaMask.\n * @returns The EIP-1193 Ethereum provider object.\n */\n private createEIP1193Provider(provider: StreamProvider): StreamProvider {\n const originalRequest = provider.request;\n\n provider.request = async (args) => {\n assert(\n !args.method.startsWith('snap_'),\n ethErrors.rpc.methodNotFound({\n data: {\n method: args.method,\n },\n }),\n );\n this.notify({ method: 'OutboundRequest' });\n try {\n return await withTeardown(originalRequest(args), this as any);\n } finally {\n this.notify({ method: 'OutboundResponse' });\n }\n };\n\n return provider;\n }\n\n /**\n * Removes the snap with the given name.\n *\n * @param snapName - The name of the snap to remove.\n */\n private removeSnap(snapName: string): void {\n this.snapData.delete(snapName);\n }\n\n /**\n * Calls the specified executor function in the context of the specified snap.\n * Essentially, this means that the operation performed by the executor is\n * counted as an evaluation of the specified snap. When the count of running\n * evaluations of a snap reaches zero, its endowments are torn down.\n *\n * @param snapName - The name of the snap whose context to execute in.\n * @param executor - The function that will be executed in the snap's context.\n * @returns The executor's return value.\n * @template Result - The return value of the executor.\n */\n private async executeInSnapContext<Result>(\n snapName: string,\n executor: () => Promise<Result> | Result,\n ): Promise<Result> {\n const data = this.snapData.get(snapName);\n if (data === undefined) {\n throw new Error(\n `Tried to execute in context of unknown snap: \"${snapName}\".`,\n );\n }\n\n let stop: () => void;\n const stopPromise = new Promise<never>(\n (_, reject) =>\n (stop = () =>\n reject(\n // TODO(rekmarks): Specify / standardize error code for this case.\n ethErrors.rpc.internal(\n `The snap \"${snapName}\" has been terminated during execution.`,\n ),\n )),\n );\n\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n const evaluationData = { stop: stop! };\n\n try {\n data.runningEvaluations.add(evaluationData);\n // Notice that we have to await this executor.\n // If we didn't, we would decrease the amount of running evaluations\n // before the promise actually resolves\n return await Promise.race([executor(), stopPromise]);\n } finally {\n data.runningEvaluations.delete(evaluationData);\n\n if (data.runningEvaluations.size === 0) {\n this.lastTeardown += 1;\n await data.idleTeardown();\n }\n }\n }\n}\n"]}
1
+ {"version":3,"file":"BaseSnapExecutor.js","sourceRoot":"","sources":["../../src/common/BaseSnapExecutor.ts"],"names":[],"mappings":";;;;;;AAAA,qFAAqF;AACrF,gEAAgE;AAChE,mDAAqD;AAGrD,uDAI+B;AAC/B,2CAWyB;AACzB,mDAAuE;AACvE,qDAA0D;AAE1D,6CAAuC;AAEvC,mEAAgD;AAChD,yCAGoB;AACpB,6CAAgD;AAChD,iDAAuE;AACvE,uCAAwC;AACxC,6CAA6C;AAC7C,mCAAuD;AACvD,6CAMsB;AAYtB,MAAM,aAAa,GAAG;IACpB,IAAI,EAAE,2BAAU,CAAC,GAAG,CAAC,QAAQ;IAC7B,OAAO,EAAE,6BAA6B;CACvC,CAAC;AAYF;;;;GAIG;AACH,MAAM,6BAA6B,GAAG;IACpC,IAAI,EAAE;QACJ,MAAM,EAAE,uCAA0B;QAClC,MAAM,EAAE,EAAE;KACX;IACD,WAAW,EAAE;QACX,MAAM,EAAE,8CAAiC;QACzC,MAAM,EAAE,CAAC,UAAU,EAAE,YAAY,EAAE,YAAY,CAAC;KACjD;IACD,SAAS,EAAE;QACT,MAAM,EAAE,4CAA+B;QACvC,MAAM,EAAE,EAAE;KACX;IACD,OAAO,EAAE;QACP,MAAM,EAAE,0CAA6B;QACrC,MAAM,EAAE,CAAC,QAAQ,EAAE,SAAS,EAAE,QAAQ,EAAE,SAAS,CAAC;KACnD;CACF,CAAC;AAEF,MAAa,gBAAgB;IAe3B,YAAsB,aAAqB,EAAE,SAAiB;QAFtD,iBAAY,GAAG,CAAC,CAAC;QAGvB,IAAI,CAAC,QAAQ,GAAG,IAAI,GAAG,EAAE,CAAC;QAC1B,IAAI,CAAC,aAAa,GAAG,aAAa,CAAC;QACnC,IAAI,CAAC,aAAa,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE;YACrC,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;gBAC1C,qCAAqC;gBACrC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YACvB,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QACH,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;QAE3B,IAAI,CAAC,OAAO,GAAG,IAAA,0CAA+B,EAC5C,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,EACzB,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,IAAI,EAAE,EAAE;YAClC,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;YACvC,uFAAuF;YACvF,MAAM,OAAO,GACX,WAAW,KAAK,yBAAW,CAAC,WAAW;gBACrC,CAAC,CAAC,IAAA,qBAAW,EAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,IAAI,aAAJ,IAAI,uBAAJ,IAAI,CAAE,OAAO,CAAC,OAAO,CAAC;gBAC5D,CAAC,CAAC,IAAI,aAAJ,IAAI,uBAAJ,IAAI,CAAE,OAAO,CAAC,WAAW,CAAC,CAAC;YACjC,IAAA,cAAM,EACJ,OAAO,KAAK,SAAS,EACrB,MAAM,WAAW,+BAA+B,MAAM,EAAE,CACzD,CAAC;YACF,mCAAmC;YACnC,IAAI,MAAM,GAAG,MAAM,IAAI,CAAC,oBAAoB,CAAC,MAAM,EAAE,GAAG,EAAE,CACxD,OAAO,CAAC,IAAW,CAAC,CACrB,CAAC;YAEF,0EAA0E;YAC1E,IAAI,MAAM,KAAK,SAAS,EAAE;gBACxB,MAAM,GAAG,IAAI,CAAC;aACf;YAED,IAAA,cAAM,EACJ,IAAA,mBAAW,EAAC,MAAM,CAAC,EACnB,IAAI,SAAS,CAAC,uCAAuC,CAAC,CACvD,CAAC;YACF,OAAO,MAAM,CAAC;QAChB,CAAC,EACD,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,CAC5B,CAAC;IACJ,CAAC;IAEO,YAAY,CAAC,KAAc,EAAE,IAA0B;;QAC7D,MAAM,gBAAgB,GAAG,IAAA,sBAAc,EAAC,KAAK,CAAC,CAAC;QAC/C,MAAM,eAAe,GAAG,IAAA,+BAAc,EAAC,gBAAgB,EAAE;YACvD,aAAa;YACb,kBAAkB,EAAE,KAAK;SAC1B,CAAC,CAAC;QAEH,gEAAgE;QAChE,MAAM,QAAQ,mCAAc,IAAI,KAAE,KAAK,EAAE,MAAA,gBAAgB,aAAhB,gBAAgB,uBAAhB,gBAAgB,CAAE,KAAK,mCAAI,IAAI,GAAE,CAAC;QAE3E,IAAI,CAAC,MAAM,CAAC;YACV,MAAM,EAAE,gBAAgB;YACxB,MAAM,EAAE;gBACN,KAAK,kCACA,eAAe,KAClB,IAAI,EAAE,QAAQ,GACf;aACF;SACF,CAAC,CAAC;IACL,CAAC;IAEO,KAAK,CAAC,gBAAgB,CAAC,OAAsC;QACnE,IAAI,CAAC,IAAA,wBAAgB,EAAC,OAAO,CAAC,EAAE;YAC9B,MAAM,IAAI,KAAK,CAAC,iDAAiD,CAAC,CAAC;SACpE;QAED,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC;QACvC,IAAI,MAAM,KAAK,cAAc,EAAE;YAC7B,IAAI,CAAC,OAAO,CAAC,EAAE,EAAE;gBACf,MAAM,EAAE,sBAAiB;aAC1B,CAAC,CAAC;YACH,OAAO;SACR;QAED,IAAI,CAAC,IAAA,mBAAW,EAAC,6BAA6B,EAAE,MAAM,CAAC,EAAE;YACvD,IAAI,CAAC,OAAO,CAAC,EAAE,EAAE;gBACf,KAAK,EAAE,0BAAS,CAAC,GAAG;qBACjB,cAAc,CAAC;oBACd,IAAI,EAAE;wBACJ,MAAM;qBACP;iBACF,CAAC;qBACD,SAAS,EAAE;aACf,CAAC,CAAC;YACH,OAAO;SACR;QAED,MAAM,YAAY,GAChB,6BAA6B,CAC3B,MAAoD,CACrD,CAAC;QAEJ,yCAAyC;QACzC,MAAM,aAAa,GAAG,IAAA,0BAAa,EAAC,YAAY,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAEjE,MAAM,CAAC,KAAK,CAAC,GAAG,IAAA,sBAAQ,EAAW,aAAa,EAAE,YAAY,CAAC,MAAM,CAAC,CAAC;QACvE,IAAI,KAAK,EAAE;YACT,IAAI,CAAC,OAAO,CAAC,EAAE,EAAE;gBACf,KAAK,EAAE,0BAAS,CAAC,GAAG;qBACjB,aAAa,CAAC;oBACb,OAAO,EAAE,kCAAkC,MAAM,MAAM,KAAK,CAAC,OAAO,GAAG;oBACvE,IAAI,EAAE;wBACJ,MAAM;wBACN,MAAM,EAAE,aAAa;qBACtB;iBACF,CAAC;qBACD,SAAS,EAAE;aACf,CAAC,CAAC;YACH,OAAO;SACR;QAED,IAAI;YACF,MAAM,MAAM,GAAG,MAAO,IAAI,CAAC,OAAe,CAAC,MAAM,CAAC,CAAC,GAAG,aAAa,CAAC,CAAC;YACrE,IAAI,CAAC,OAAO,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;SAC9B;QAAC,OAAO,QAAQ,EAAE;YACjB,IAAI,CAAC,OAAO,CAAC,EAAE,EAAE;gBACf,KAAK,EAAE,IAAA,+BAAc,EAAC,QAAQ,EAAE;oBAC9B,aAAa;iBACd,CAAC;aACH,CAAC,CAAC;SACJ;IACH,CAAC;IAES,MAAM,CACd,aAGC;QAED,IAAI,CAAC,IAAA,mBAAW,EAAC,aAAa,CAAC,IAAI,CAAC,IAAA,gBAAQ,EAAC,aAAa,CAAC,EAAE;YAC3D,MAAM,IAAI,KAAK,CACb,0DAA0D,CAC3D,CAAC;SACH;QAED,IAAI,CAAC,aAAa,CAAC,KAAK,iCACnB,aAAa,KAChB,OAAO,EAAE,KAAK,IACd,CAAC;IACL,CAAC;IAES,OAAO,CAAC,EAAa,EAAE,aAAsC;QACrE,IAAI,CAAC,IAAA,mBAAW,EAAC,aAAa,CAAC,IAAI,CAAC,IAAA,gBAAQ,EAAC,aAAa,CAAC,EAAE;YAC3D,MAAM,IAAI,KAAK,CAAC,uDAAuD,CAAC,CAAC;SAC1E;QAED,IAAI,CAAC,aAAa,CAAC,KAAK,iCACnB,aAAa,KAChB,EAAE,EACF,OAAO,EAAE,KAAK,IACd,CAAC;IACL,CAAC;IAED;;;;;;;OAOG;IACO,KAAK,CAAC,SAAS,CACvB,QAAgB,EAChB,UAAkB,EAClB,WAAsB;QAEtB,OAAO,CAAC,GAAG,CAAC,kBAAkB,QAAQ,aAAa,CAAC,CAAC;QACrD,IAAI,IAAI,CAAC,uBAAuB,EAAE;YAChC,IAAA,kCAAmB,EAAC,oBAAoB,EAAE,IAAI,CAAC,uBAAuB,CAAC,CAAC;SACzE;QAED,IAAI,IAAI,CAAC,gBAAgB,EAAE;YACzB,IAAA,kCAAmB,EAAC,OAAO,EAAE,IAAI,CAAC,gBAAgB,CAAC,CAAC;SACrD;QAED,IAAI,CAAC,gBAAgB,GAAG,CAAC,KAAiB,EAAE,EAAE;YAC5C,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,KAAK,EAAE,EAAE,QAAQ,EAAE,CAAC,CAAC;QAC/C,CAAC,CAAC;QAEF,IAAI,CAAC,uBAAuB,GAAG,CAAC,KAA4B,EAAE,EAAE;YAC9D,IAAI,CAAC,YAAY,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,EAAE;gBAC/D,QAAQ;aACT,CAAC,CAAC;QACL,CAAC,CAAC;QAEF,MAAM,QAAQ,GAAG,IAAI,0BAAc,CAAC,IAAI,CAAC,SAAS,EAAE;YAClD,iBAAiB,EAAE,mBAAmB;YACtC,aAAa,EAAE,CAAC,IAAA,yCAAuB,GAAE,CAAC;SAC3C,CAAC,CAAC;QAEH,MAAM,QAAQ,CAAC,UAAU,EAAE,CAAC;QAE5B,MAAM,IAAI,GAAG,IAAI,CAAC,gBAAgB,CAAC,QAAQ,CAAC,CAAC;QAC7C,MAAM,QAAQ,GAAG,IAAI,CAAC,qBAAqB,CAAC,QAAQ,CAAC,CAAC;QACtD,wFAAwF;QACxF,MAAM,UAAU,GAAQ,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;QAExC,IAAI;YACF,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,iBAAiB,EAAE,GAAG,IAAA,6BAAgB,EAClE,IAAI,EACJ,QAAQ,EACR,WAAW,CACZ,CAAC;YAEF,gEAAgE;YAChE,mEAAmE;YACnE,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,EAAE;gBAC1B,YAAY,EAAE,iBAAiB;gBAC/B,kBAAkB,EAAE,IAAI,GAAG,EAAE;gBAC7B,OAAO,EAAE,EAAE;aACZ,CAAC,CAAC;YAEH,IAAA,+BAAgB,EAAC,oBAAoB,EAAE,IAAI,CAAC,uBAAuB,CAAC,CAAC;YACrE,IAAA,+BAAgB,EAAC,OAAO,EAAE,IAAI,CAAC,gBAAgB,CAAC,CAAC;YAEjD,MAAM,WAAW,GAAG,IAAI,WAAW,iCAC9B,UAAU,KACb,MAAM,EAAE,UAAU,EAClB,OAAO,EAAE,UAAU,CAAC,OAAO,EAC3B,MAAM,oBAAO,UAAU,GACvB,IAAI,oBAAO,UAAU,KACrB,CAAC;YAEH,MAAM,IAAI,CAAC,oBAAoB,CAAC,QAAQ,EAAE,GAAG,EAAE;gBAC7C,WAAW,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;gBACjC,IAAI,CAAC,mBAAmB,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;YACjD,CAAC,CAAC,CAAC;SACJ;QAAC,OAAO,KAAK,EAAE;YACd,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;YAC1B,MAAM,IAAI,KAAK,CACb,6BAA6B,QAAQ,MAAO,KAAe,CAAC,OAAO,EAAE,CACtE,CAAC;SACH;IACH,CAAC;IAED;;;OAGG;IACO,WAAW;QACnB,uCAAuC;QACvC,+DAA+D;QAC/D,6CAA6C;QAC7C,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE,CAC7B,IAAI,CAAC,kBAAkB,CAAC,OAAO,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC,CACnE,CAAC;QACF,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC;IACxB,CAAC;IAEO,mBAAmB,CAAC,QAAgB,EAAE,UAAe;QAC3D,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QACzC,qDAAqD;QACrD,IAAI,CAAC,IAAI,EAAE;YACT,OAAO;SACR;QAED,IAAI,CAAC,OAAO,GAAG,+BAAiB,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,UAAU,EAAE,EAAE;YAC1D,MAAM,UAAU,GAAG,UAAU,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;YAClD,IAAI,IAAA,2BAAc,EAAC,UAAU,EAAE,UAAU,CAAC,EAAE;gBAC1C,uCAAY,GAAG,KAAE,CAAC,UAAU,CAAC,EAAE,UAAU,IAAG;aAC7C;YACD,OAAO,GAAG,CAAC;QACb,CAAC,EAAE,EAAE,CAAC,CAAC;IACT,CAAC;IAED;;;;;OAKG;IACK,gBAAgB,CAAC,QAAwB;QAC/C,MAAM,eAAe,GAAG,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAExD,MAAM,OAAO,GAAG,KAAK,EAAE,IAAsB,EAAE,EAAE;YAC/C,IAAA,cAAM,EACJ,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,SAAS,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,OAAO,CAAC,EACpE,oFAAoF,CACrF,CAAC;YACF,IAAI,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,iBAAiB,EAAE,CAAC,CAAC;YAC3C,IAAI;gBACF,OAAO,MAAM,IAAA,oBAAY,EAAC,eAAe,CAAC,IAAI,CAAC,EAAE,IAAW,CAAC,CAAC;aAC/D;oBAAS;gBACR,IAAI,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,kBAAkB,EAAE,CAAC,CAAC;aAC7C;QACH,CAAC,CAAC;QAEF,OAAO,EAAE,OAAO,EAAE,CAAC;IACrB,CAAC;IAED;;;;;OAKG;IACK,qBAAqB,CAAC,QAAwB;QACpD,MAAM,eAAe,GAAG,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAExD,QAAQ,CAAC,OAAO,GAAG,KAAK,EAAE,IAAI,EAAE,EAAE;YAChC,IAAA,cAAM,EACJ,CAAC,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,OAAO,CAAC,EAChC,0BAAS,CAAC,GAAG,CAAC,cAAc,CAAC;gBAC3B,IAAI,EAAE;oBACJ,MAAM,EAAE,IAAI,CAAC,MAAM;iBACpB;aACF,CAAC,CACH,CAAC;YACF,IAAI,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,iBAAiB,EAAE,CAAC,CAAC;YAC3C,IAAI;gBACF,OAAO,MAAM,IAAA,oBAAY,EAAC,eAAe,CAAC,IAAI,CAAC,EAAE,IAAW,CAAC,CAAC;aAC/D;oBAAS;gBACR,IAAI,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,kBAAkB,EAAE,CAAC,CAAC;aAC7C;QACH,CAAC,CAAC;QAEF,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED;;;;OAIG;IACK,UAAU,CAAC,QAAgB;QACjC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IACjC,CAAC;IAED;;;;;;;;;;OAUG;IACK,KAAK,CAAC,oBAAoB,CAChC,QAAgB,EAChB,QAAwC;QAExC,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QACzC,IAAI,IAAI,KAAK,SAAS,EAAE;YACtB,MAAM,IAAI,KAAK,CACb,iDAAiD,QAAQ,IAAI,CAC9D,CAAC;SACH;QAED,IAAI,IAAgB,CAAC;QACrB,MAAM,WAAW,GAAG,IAAI,OAAO,CAC7B,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE,CACZ,CAAC,IAAI,GAAG,GAAG,EAAE,CACX,MAAM;QACJ,kEAAkE;QAClE,0BAAS,CAAC,GAAG,CAAC,QAAQ,CACpB,aAAa,QAAQ,yCAAyC,CAC/D,CACF,CAAC,CACP,CAAC;QAEF,oEAAoE;QACpE,MAAM,cAAc,GAAG,EAAE,IAAI,EAAE,IAAK,EAAE,CAAC;QAEvC,IAAI;YACF,IAAI,CAAC,kBAAkB,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;YAC5C,8CAA8C;YAC9C,oEAAoE;YACpE,uCAAuC;YACvC,OAAO,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,EAAE,WAAW,CAAC,CAAC,CAAC;SACtD;gBAAS;YACR,IAAI,CAAC,kBAAkB,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC;YAE/C,IAAI,IAAI,CAAC,kBAAkB,CAAC,IAAI,KAAK,CAAC,EAAE;gBACtC,IAAI,CAAC,YAAY,IAAI,CAAC,CAAC;gBACvB,MAAM,IAAI,CAAC,YAAY,EAAE,CAAC;aAC3B;SACF;IACH,CAAC;CACF;AA/YD,4CA+YC","sourcesContent":["// eslint-disable-next-line @typescript-eslint/triple-slash-reference, spaced-comment\n/// <reference path=\"../../../../node_modules/ses/index.d.ts\" />\nimport { StreamProvider } from '@metamask/providers';\nimport { RequestArguments } from '@metamask/providers/dist/BaseProvider';\nimport { SnapExports, SnapsGlobalObject } from '@metamask/snaps-types';\nimport {\n HandlerType,\n SnapExportsParameters,\n SNAP_EXPORT_NAMES,\n} from '@metamask/snaps-utils';\nimport {\n isObject,\n isValidJson,\n JsonRpcNotification,\n assert,\n isJsonRpcRequest,\n JsonRpcId,\n JsonRpcRequest,\n JsonRpcParams,\n Json,\n hasProperty,\n} from '@metamask/utils';\nimport { errorCodes, ethErrors, serializeError } from 'eth-rpc-errors';\nimport { createIdRemapMiddleware } from 'json-rpc-engine';\nimport { Duplex } from 'stream';\nimport { validate } from 'superstruct';\n\nimport EEOpenRPCDocument from '../openrpc.json';\nimport {\n CommandMethodsMapping,\n getCommandMethodImplementations,\n} from './commands';\nimport { createEndowments } from './endowments';\nimport { addEventListener, removeEventListener } from './globalEvents';\nimport { wrapKeyring } from './keyring';\nimport { sortParamKeys } from './sortParams';\nimport { constructError, withTeardown } from './utils';\nimport {\n ExecuteSnapRequestArgumentsStruct,\n PingRequestArgumentsStruct,\n SnapRpcRequestArgumentsStruct,\n TerminateRequestArgumentsStruct,\n validateExport,\n} from './validation';\n\ntype EvaluationData = {\n stop: () => void;\n};\n\ntype SnapData = {\n exports: SnapExports;\n runningEvaluations: Set<EvaluationData>;\n idleTeardown: () => Promise<void>;\n};\n\nconst fallbackError = {\n code: errorCodes.rpc.internal,\n message: 'Execution Environment Error',\n};\n\n// TODO: `KeyringParameters` expects a `chainId` for certain methods, but we're\n// not providing it in `getHandlerArguments`, resulting in type errors.\nexport type InvokeSnapArgs = Omit<SnapExportsParameters[0], 'chainId'>;\n\nexport type InvokeSnap = (\n target: string,\n handler: HandlerType,\n args: InvokeSnapArgs | undefined,\n) => Promise<Json>;\n\n/**\n * The supported methods in the execution environment. The validator checks the\n * incoming JSON-RPC request, and the `params` property is used for sorting the\n * parameters, if they are an object.\n */\nconst EXECUTION_ENVIRONMENT_METHODS = {\n ping: {\n struct: PingRequestArgumentsStruct,\n params: [],\n },\n executeSnap: {\n struct: ExecuteSnapRequestArgumentsStruct,\n params: ['snapName', 'sourceCode', 'endowments'],\n },\n terminate: {\n struct: TerminateRequestArgumentsStruct,\n params: [],\n },\n snapRpc: {\n struct: SnapRpcRequestArgumentsStruct,\n params: ['target', 'handler', 'origin', 'request'],\n },\n};\n\nexport class BaseSnapExecutor {\n private readonly snapData: Map<string, SnapData>;\n\n private readonly commandStream: Duplex;\n\n private readonly rpcStream: Duplex;\n\n private readonly methods: CommandMethodsMapping;\n\n private snapErrorHandler?: (event: ErrorEvent) => void;\n\n private snapPromiseErrorHandler?: (event: PromiseRejectionEvent) => void;\n\n private lastTeardown = 0;\n\n protected constructor(commandStream: Duplex, rpcStream: Duplex) {\n this.snapData = new Map();\n this.commandStream = commandStream;\n this.commandStream.on('data', (data) => {\n this.onCommandRequest(data).catch((error) => {\n // TODO: Decide how to handle errors.\n console.error(error);\n });\n });\n this.rpcStream = rpcStream;\n\n this.methods = getCommandMethodImplementations(\n this.startSnap.bind(this),\n async (target, handlerName, args) => {\n const data = this.snapData.get(target);\n // We're capturing the handler in case someone modifies the data object before the call\n const handler =\n handlerName === HandlerType.SnapKeyring\n ? wrapKeyring(this.notify.bind(this), data?.exports.keyring)\n : data?.exports[handlerName];\n assert(\n handler !== undefined,\n `No ${handlerName} handler exported for snap \"${target}`,\n );\n // TODO: fix handler args type cast\n let result = await this.executeInSnapContext(target, () =>\n handler(args as any),\n );\n\n // The handler might not return anything, but undefined is not valid JSON.\n if (result === undefined) {\n result = null;\n }\n\n assert(\n isValidJson(result),\n new TypeError('Received non-JSON-serializable value.'),\n );\n return result;\n },\n this.onTerminate.bind(this),\n );\n }\n\n private errorHandler(error: unknown, data: Record<string, Json>) {\n const constructedError = constructError(error);\n const serializedError = serializeError(constructedError, {\n fallbackError,\n shouldIncludeStack: false,\n });\n\n // We're setting it this way to avoid sentData.stack = undefined\n const sentData: Json = { ...data, stack: constructedError?.stack ?? null };\n\n this.notify({\n method: 'UnhandledError',\n params: {\n error: {\n ...serializedError,\n data: sentData,\n },\n },\n });\n }\n\n private async onCommandRequest(message: JsonRpcRequest<JsonRpcParams>) {\n if (!isJsonRpcRequest(message)) {\n throw new Error('Command stream received a non-JSON-RPC request.');\n }\n\n const { id, method, params } = message;\n if (method === 'rpc.discover') {\n this.respond(id, {\n result: EEOpenRPCDocument,\n });\n return;\n }\n\n if (!hasProperty(EXECUTION_ENVIRONMENT_METHODS, method)) {\n this.respond(id, {\n error: ethErrors.rpc\n .methodNotFound({\n data: {\n method,\n },\n })\n .serialize(),\n });\n return;\n }\n\n const methodObject =\n EXECUTION_ENVIRONMENT_METHODS[\n method as keyof typeof EXECUTION_ENVIRONMENT_METHODS\n ];\n\n // support params by-name and by-position\n const paramsAsArray = sortParamKeys(methodObject.params, params);\n\n const [error] = validate<any, any>(paramsAsArray, methodObject.struct);\n if (error) {\n this.respond(id, {\n error: ethErrors.rpc\n .invalidParams({\n message: `Invalid parameters for method \"${method}\": ${error.message}.`,\n data: {\n method,\n params: paramsAsArray,\n },\n })\n .serialize(),\n });\n return;\n }\n\n try {\n const result = await (this.methods as any)[method](...paramsAsArray);\n this.respond(id, { result });\n } catch (rpcError) {\n this.respond(id, {\n error: serializeError(rpcError, {\n fallbackError,\n }),\n });\n }\n }\n\n protected notify(\n requestObject: Omit<\n JsonRpcNotification<Record<string, Json> | Json[] | undefined>,\n 'jsonrpc'\n >,\n ) {\n if (!isValidJson(requestObject) || !isObject(requestObject)) {\n throw new Error(\n 'JSON-RPC notifications must be JSON serializable objects',\n );\n }\n\n this.commandStream.write({\n ...requestObject,\n jsonrpc: '2.0',\n });\n }\n\n protected respond(id: JsonRpcId, requestObject: Record<string, unknown>) {\n if (!isValidJson(requestObject) || !isObject(requestObject)) {\n throw new Error('JSON-RPC responses must be JSON serializable objects.');\n }\n\n this.commandStream.write({\n ...requestObject,\n id,\n jsonrpc: '2.0',\n });\n }\n\n /**\n * Attempts to evaluate a snap in SES. Generates APIs for the snap. May throw\n * on errors.\n *\n * @param snapName - The name of the snap.\n * @param sourceCode - The source code of the snap, in IIFE format.\n * @param _endowments - An array of the names of the endowments.\n */\n protected async startSnap(\n snapName: string,\n sourceCode: string,\n _endowments?: string[],\n ): Promise<void> {\n console.log(`starting snap '${snapName}' in worker`);\n if (this.snapPromiseErrorHandler) {\n removeEventListener('unhandledrejection', this.snapPromiseErrorHandler);\n }\n\n if (this.snapErrorHandler) {\n removeEventListener('error', this.snapErrorHandler);\n }\n\n this.snapErrorHandler = (error: ErrorEvent) => {\n this.errorHandler(error.error, { snapName });\n };\n\n this.snapPromiseErrorHandler = (error: PromiseRejectionEvent) => {\n this.errorHandler(error instanceof Error ? error : error.reason, {\n snapName,\n });\n };\n\n const provider = new StreamProvider(this.rpcStream, {\n jsonRpcStreamName: 'metamask-provider',\n rpcMiddleware: [createIdRemapMiddleware()],\n });\n\n await provider.initialize();\n\n const snap = this.createSnapGlobal(provider);\n const ethereum = this.createEIP1193Provider(provider);\n // We specifically use any type because the Snap can modify the object any way they want\n const snapModule: any = { exports: {} };\n\n try {\n const { endowments, teardown: endowmentTeardown } = createEndowments(\n snap,\n ethereum,\n _endowments,\n );\n\n // !!! Ensure that this is the only place the data is being set.\n // Other methods access the object value and mutate its properties.\n this.snapData.set(snapName, {\n idleTeardown: endowmentTeardown,\n runningEvaluations: new Set(),\n exports: {},\n });\n\n addEventListener('unhandledRejection', this.snapPromiseErrorHandler);\n addEventListener('error', this.snapErrorHandler);\n\n const compartment = new Compartment({\n ...endowments,\n module: snapModule,\n exports: snapModule.exports,\n window: { ...endowments },\n self: { ...endowments },\n });\n\n await this.executeInSnapContext(snapName, () => {\n compartment.evaluate(sourceCode);\n this.registerSnapExports(snapName, snapModule);\n });\n } catch (error) {\n this.removeSnap(snapName);\n throw new Error(\n `Error while running snap '${snapName}': ${(error as Error).message}`,\n );\n }\n }\n\n /**\n * Cancels all running evaluations of all snaps and clears all snap data.\n * NOTE:** Should only be called in response to the `terminate` RPC command.\n */\n protected onTerminate() {\n // `stop()` tears down snap endowments.\n // Teardown will also be run for each snap as soon as there are\n // no more running evaluations for that snap.\n this.snapData.forEach((data) =>\n data.runningEvaluations.forEach((evaluation) => evaluation.stop()),\n );\n this.snapData.clear();\n }\n\n private registerSnapExports(snapName: string, snapModule: any) {\n const data = this.snapData.get(snapName);\n // Somebody deleted the Snap before we could register\n if (!data) {\n return;\n }\n\n data.exports = SNAP_EXPORT_NAMES.reduce((acc, exportName) => {\n const snapExport = snapModule.exports[exportName];\n if (validateExport(exportName, snapExport)) {\n return { ...acc, [exportName]: snapExport };\n }\n return acc;\n }, {});\n }\n\n /**\n * Instantiates a snap API object (i.e. `globalThis.snap`).\n *\n * @param provider - A StreamProvider connected to MetaMask.\n * @returns The snap provider object.\n */\n private createSnapGlobal(provider: StreamProvider): SnapsGlobalObject {\n const originalRequest = provider.request.bind(provider);\n\n const request = async (args: RequestArguments) => {\n assert(\n args.method.startsWith('wallet_') || args.method.startsWith('snap_'),\n 'The global Snap API only allows RPC methods starting with `wallet_*` and `snap_*`.',\n );\n this.notify({ method: 'OutboundRequest' });\n try {\n return await withTeardown(originalRequest(args), this as any);\n } finally {\n this.notify({ method: 'OutboundResponse' });\n }\n };\n\n return { request };\n }\n\n /**\n * Instantiates an EIP-1193 Ethereum provider object (i.e. `globalThis.ethereum`).\n *\n * @param provider - A StreamProvider connected to MetaMask.\n * @returns The EIP-1193 Ethereum provider object.\n */\n private createEIP1193Provider(provider: StreamProvider): StreamProvider {\n const originalRequest = provider.request.bind(provider);\n\n provider.request = async (args) => {\n assert(\n !args.method.startsWith('snap_'),\n ethErrors.rpc.methodNotFound({\n data: {\n method: args.method,\n },\n }),\n );\n this.notify({ method: 'OutboundRequest' });\n try {\n return await withTeardown(originalRequest(args), this as any);\n } finally {\n this.notify({ method: 'OutboundResponse' });\n }\n };\n\n return provider;\n }\n\n /**\n * Removes the snap with the given name.\n *\n * @param snapName - The name of the snap to remove.\n */\n private removeSnap(snapName: string): void {\n this.snapData.delete(snapName);\n }\n\n /**\n * Calls the specified executor function in the context of the specified snap.\n * Essentially, this means that the operation performed by the executor is\n * counted as an evaluation of the specified snap. When the count of running\n * evaluations of a snap reaches zero, its endowments are torn down.\n *\n * @param snapName - The name of the snap whose context to execute in.\n * @param executor - The function that will be executed in the snap's context.\n * @returns The executor's return value.\n * @template Result - The return value of the executor.\n */\n private async executeInSnapContext<Result>(\n snapName: string,\n executor: () => Promise<Result> | Result,\n ): Promise<Result> {\n const data = this.snapData.get(snapName);\n if (data === undefined) {\n throw new Error(\n `Tried to execute in context of unknown snap: \"${snapName}\".`,\n );\n }\n\n let stop: () => void;\n const stopPromise = new Promise<never>(\n (_, reject) =>\n (stop = () =>\n reject(\n // TODO(rekmarks): Specify / standardize error code for this case.\n ethErrors.rpc.internal(\n `The snap \"${snapName}\" has been terminated during execution.`,\n ),\n )),\n );\n\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n const evaluationData = { stop: stop! };\n\n try {\n data.runningEvaluations.add(evaluationData);\n // Notice that we have to await this executor.\n // If we didn't, we would decrease the amount of running evaluations\n // before the promise actually resolves\n return await Promise.race([executor(), stopPromise]);\n } finally {\n data.runningEvaluations.delete(evaluationData);\n\n if (data.runningEvaluations.size === 0) {\n this.lastTeardown += 1;\n await data.idleTeardown();\n }\n }\n }\n}\n"]}
@@ -1,8 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getCommandMethodImplementations = exports.getHandlerArguments = void 0;
4
- const utils_1 = require("@metamask/utils");
5
4
  const snaps_utils_1 = require("@metamask/snaps-utils");
5
+ const utils_1 = require("@metamask/utils");
6
6
  const validation_1 = require("./validation");
7
7
  /**
8
8
  * Formats the arguments for the given handler.
@@ -47,12 +47,10 @@ exports.getHandlerArguments = getHandlerArguments;
47
47
  */
48
48
  function getCommandMethodImplementations(startSnap, invokeSnap, onTerminate) {
49
49
  return {
50
- ping: async () => {
51
- return 'OK';
52
- },
50
+ ping: async () => Promise.resolve('OK'),
53
51
  terminate: async () => {
54
52
  onTerminate();
55
- return 'OK';
53
+ return Promise.resolve('OK');
56
54
  },
57
55
  executeSnap: async (snapName, sourceCode, endowments) => {
58
56
  await startSnap(snapName, sourceCode, endowments);
@@ -1 +1 @@
1
- {"version":3,"file":"commands.js","sourceRoot":"","sources":["../../src/common/commands.ts"],"names":[],"mappings":";;;AAAA,2CAAmD;AACnD,uDAAoD;AAEpD,6CAOsB;AAStB;;;;;;;GAOG;AACH,SAAgB,mBAAmB,CACjC,MAAc,EACd,OAAoB,EACpB,OAAgC;IAEhC,sEAAsE;IAEtE,QAAQ,OAAO,EAAE;QACf,KAAK,yBAAW,CAAC,aAAa,CAAC,CAAC;YAC9B,IAAA,kDAAqC,EAAC,OAAO,CAAC,MAAM,CAAC,CAAC;YAEtD,MAAM,EAAE,WAAW,EAAE,OAAO,EAAE,iBAAiB,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC;YACnE,OAAO;gBACL,WAAW;gBACX,OAAO;gBACP,iBAAiB;aAClB,CAAC;SACH;QAED,KAAK,yBAAW,CAAC,YAAY,CAAC;QAC9B,KAAK,yBAAW,CAAC,WAAW;YAC1B,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC;QAE7B,KAAK,yBAAW,CAAC,SAAS;YACxB,OAAO,EAAE,OAAO,EAAE,CAAC;QAErB;YACE,OAAO,IAAA,wBAAgB,EAAC,OAAO,CAAC,CAAC;KACpC;AACH,CAAC;AA7BD,kDA6BC;AAED;;;;;;;;;;GAUG;AACH,SAAgB,+BAA+B,CAC7C,SAA8D,EAC9D,UAAsB,EACtB,WAAuB;IAEvB,OAAO;QACL,IAAI,EAAE,KAAK,IAAI,EAAE;YACf,OAAO,IAAI,CAAC;QACd,CAAC;QAED,SAAS,EAAE,KAAK,IAAI,EAAE;YACpB,WAAW,EAAE,CAAC;YACd,OAAO,IAAI,CAAC;QACd,CAAC;QAED,WAAW,EAAE,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,UAAU,EAAE,EAAE;YACtD,MAAM,SAAS,CAAC,QAAkB,EAAE,UAAoB,EAAE,UAAU,CAAC,CAAC;YACtE,OAAO,IAAI,CAAC;QACd,CAAC;QAED,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE;;YAClD,OAAO,CACL,MAAA,CAAC,MAAM,UAAU,CACf,MAAM,EACN,OAAO,EACP,mBAAmB,CAAC,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,CAC9C,CAAC,mCAAI,IAAI,CACX,CAAC;QACJ,CAAC;KACF,CAAC;AACJ,CAAC;AA9BD,0EA8BC","sourcesContent":["import { assertExhaustive } from '@metamask/utils';\nimport { HandlerType } from '@metamask/snaps-utils';\nimport { InvokeSnap, InvokeSnapArgs } from './BaseSnapExecutor';\nimport {\n assertIsOnTransactionRequestArguments,\n ExecuteSnap,\n JsonRpcRequestWithoutId,\n Ping,\n SnapRpc,\n Terminate,\n} from './validation';\n\nexport type CommandMethodsMapping = {\n ping: Ping;\n terminate: Terminate;\n executeSnap: ExecuteSnap;\n snapRpc: SnapRpc;\n};\n\n/**\n * Formats the arguments for the given handler.\n *\n * @param origin - The origin of the request.\n * @param handler - The handler to pass the request to.\n * @param request - The request object.\n * @returns The formatted arguments.\n */\nexport function getHandlerArguments(\n origin: string,\n handler: HandlerType,\n request: JsonRpcRequestWithoutId,\n): InvokeSnapArgs {\n // `request` is already validated by the time this function is called.\n\n switch (handler) {\n case HandlerType.OnTransaction: {\n assertIsOnTransactionRequestArguments(request.params);\n\n const { transaction, chainId, transactionOrigin } = request.params;\n return {\n transaction,\n chainId,\n transactionOrigin,\n };\n }\n\n case HandlerType.OnRpcRequest:\n case HandlerType.SnapKeyring:\n return { origin, request };\n\n case HandlerType.OnCronjob:\n return { request };\n\n default:\n return assertExhaustive(handler);\n }\n}\n\n/**\n * Gets an object mapping internal, \"command\" JSON-RPC method names to their\n * implementations.\n *\n * @param startSnap - A function that starts a snap.\n * @param invokeSnap - A function that invokes the RPC method handler of a\n * snap.\n * @param onTerminate - A function that will be called when this executor is\n * terminated in order to handle cleanup tasks.\n * @returns An object containing the \"command\" method implementations.\n */\nexport function getCommandMethodImplementations(\n startSnap: (...args: Parameters<ExecuteSnap>) => Promise<void>,\n invokeSnap: InvokeSnap,\n onTerminate: () => void,\n): CommandMethodsMapping {\n return {\n ping: async () => {\n return 'OK';\n },\n\n terminate: async () => {\n onTerminate();\n return 'OK';\n },\n\n executeSnap: async (snapName, sourceCode, endowments) => {\n await startSnap(snapName as string, sourceCode as string, endowments);\n return 'OK';\n },\n\n snapRpc: async (target, handler, origin, request) => {\n return (\n (await invokeSnap(\n target,\n handler,\n getHandlerArguments(origin, handler, request),\n )) ?? null\n );\n },\n };\n}\n"]}
1
+ {"version":3,"file":"commands.js","sourceRoot":"","sources":["../../src/common/commands.ts"],"names":[],"mappings":";;;AAAA,uDAAoD;AACpD,2CAAmD;AAGnD,6CAOsB;AAStB;;;;;;;GAOG;AACH,SAAgB,mBAAmB,CACjC,MAAc,EACd,OAAoB,EACpB,OAAgC;IAEhC,sEAAsE;IAEtE,QAAQ,OAAO,EAAE;QACf,KAAK,yBAAW,CAAC,aAAa,CAAC,CAAC;YAC9B,IAAA,kDAAqC,EAAC,OAAO,CAAC,MAAM,CAAC,CAAC;YAEtD,MAAM,EAAE,WAAW,EAAE,OAAO,EAAE,iBAAiB,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC;YACnE,OAAO;gBACL,WAAW;gBACX,OAAO;gBACP,iBAAiB;aAClB,CAAC;SACH;QAED,KAAK,yBAAW,CAAC,YAAY,CAAC;QAC9B,KAAK,yBAAW,CAAC,WAAW;YAC1B,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC;QAE7B,KAAK,yBAAW,CAAC,SAAS;YACxB,OAAO,EAAE,OAAO,EAAE,CAAC;QAErB;YACE,OAAO,IAAA,wBAAgB,EAAC,OAAO,CAAC,CAAC;KACpC;AACH,CAAC;AA7BD,kDA6BC;AAED;;;;;;;;;;GAUG;AACH,SAAgB,+BAA+B,CAC7C,SAA8D,EAC9D,UAAsB,EACtB,WAAuB;IAEvB,OAAO;QACL,IAAI,EAAE,KAAK,IAAI,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC;QACvC,SAAS,EAAE,KAAK,IAAI,EAAE;YACpB,WAAW,EAAE,CAAC;YACd,OAAO,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QAC/B,CAAC;QAED,WAAW,EAAE,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,UAAU,EAAE,EAAE;YACtD,MAAM,SAAS,CAAC,QAAQ,EAAE,UAAU,EAAE,UAAU,CAAC,CAAC;YAClD,OAAO,IAAI,CAAC;QACd,CAAC;QAED,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE;;YAClD,OAAO,CACL,MAAA,CAAC,MAAM,UAAU,CACf,MAAM,EACN,OAAO,EACP,mBAAmB,CAAC,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,CAC9C,CAAC,mCAAI,IAAI,CACX,CAAC;QACJ,CAAC;KACF,CAAC;AACJ,CAAC;AA3BD,0EA2BC","sourcesContent":["import { HandlerType } from '@metamask/snaps-utils';\nimport { assertExhaustive } from '@metamask/utils';\n\nimport { InvokeSnap, InvokeSnapArgs } from './BaseSnapExecutor';\nimport {\n assertIsOnTransactionRequestArguments,\n ExecuteSnap,\n JsonRpcRequestWithoutId,\n Ping,\n SnapRpc,\n Terminate,\n} from './validation';\n\nexport type CommandMethodsMapping = {\n ping: Ping;\n terminate: Terminate;\n executeSnap: ExecuteSnap;\n snapRpc: SnapRpc;\n};\n\n/**\n * Formats the arguments for the given handler.\n *\n * @param origin - The origin of the request.\n * @param handler - The handler to pass the request to.\n * @param request - The request object.\n * @returns The formatted arguments.\n */\nexport function getHandlerArguments(\n origin: string,\n handler: HandlerType,\n request: JsonRpcRequestWithoutId,\n): InvokeSnapArgs {\n // `request` is already validated by the time this function is called.\n\n switch (handler) {\n case HandlerType.OnTransaction: {\n assertIsOnTransactionRequestArguments(request.params);\n\n const { transaction, chainId, transactionOrigin } = request.params;\n return {\n transaction,\n chainId,\n transactionOrigin,\n };\n }\n\n case HandlerType.OnRpcRequest:\n case HandlerType.SnapKeyring:\n return { origin, request };\n\n case HandlerType.OnCronjob:\n return { request };\n\n default:\n return assertExhaustive(handler);\n }\n}\n\n/**\n * Gets an object mapping internal, \"command\" JSON-RPC method names to their\n * implementations.\n *\n * @param startSnap - A function that starts a snap.\n * @param invokeSnap - A function that invokes the RPC method handler of a\n * snap.\n * @param onTerminate - A function that will be called when this executor is\n * terminated in order to handle cleanup tasks.\n * @returns An object containing the \"command\" method implementations.\n */\nexport function getCommandMethodImplementations(\n startSnap: (...args: Parameters<ExecuteSnap>) => Promise<void>,\n invokeSnap: InvokeSnap,\n onTerminate: () => void,\n): CommandMethodsMapping {\n return {\n ping: async () => Promise.resolve('OK'),\n terminate: async () => {\n onTerminate();\n return Promise.resolve('OK');\n },\n\n executeSnap: async (snapName, sourceCode, endowments) => {\n await startSnap(snapName, sourceCode, endowments);\n return 'OK';\n },\n\n snapRpc: async (target, handler, origin, request) => {\n return (\n (await invokeSnap(\n target,\n handler,\n getHandlerArguments(origin, handler, request),\n )) ?? null\n );\n },\n };\n}\n"]}
@@ -1,5 +1,5 @@
1
- import { SnapsGlobalObject } from '@metamask/snaps-types';
2
1
  import { StreamProvider } from '@metamask/providers';
2
+ import { SnapsGlobalObject } from '@metamask/snaps-types';
3
3
  /**
4
4
  * Gets the endowments for a particular Snap. Some endowments, like `setTimeout`
5
5
  * and `clearTimeout`, must be attenuated so that they can only affect behavior
@@ -17,11 +17,11 @@ Object.defineProperty(exports, "__esModule", { value: true });
17
17
  exports.isConstructor = exports.createEndowments = void 0;
18
18
  const utils_1 = require("@metamask/utils");
19
19
  const globalObject_1 = require("../globalObject");
20
+ const crypto_1 = __importDefault(require("./crypto"));
20
21
  const interval_1 = __importDefault(require("./interval"));
22
+ const math_1 = __importDefault(require("./math"));
21
23
  const network_1 = __importDefault(require("./network"));
22
24
  const timeout_1 = __importDefault(require("./timeout"));
23
- const crypto_1 = __importDefault(require("./crypto"));
24
- const math_1 = __importDefault(require("./math"));
25
25
  /**
26
26
  * A map of endowment names to their factory functions. Some endowments share
27
27
  * the same factory function, but we only call each factory once for each snap.
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/common/endowments/index.ts"],"names":[],"mappings":"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","sourcesContent":["import { SnapsGlobalObject } from '@metamask/snaps-types';\nimport { hasProperty } from '@metamask/utils';\nimport { StreamProvider } from '@metamask/providers';\nimport { rootRealmGlobal } from '../globalObject';\nimport interval from './interval';\nimport network from './network';\nimport timeout from './timeout';\nimport crypto from './crypto';\nimport math from './math';\n\ntype EndowmentFactoryResult = {\n /**\n * A function that performs any necessary teardown when the snap becomes idle.\n *\n * NOTE:** The endowments are not reconstructed if the snap is re-invoked\n * before being terminated, so the teardown operation must not render the\n * endowments unusable; it should simply restore the endowments to their\n * original state.\n */\n teardownFunction?: () => Promise<void> | void;\n [key: string]: unknown;\n};\n\n/**\n * A map of endowment names to their factory functions. Some endowments share\n * the same factory function, but we only call each factory once for each snap.\n * See {@link createEndowments} for details.\n */\nconst endowmentFactories = [timeout, interval, network, crypto, math].reduce(\n (factories, builder) => {\n builder.names.forEach((name) => {\n factories.set(name, builder.factory);\n });\n return factories;\n },\n new Map<string, () => EndowmentFactoryResult>(),\n);\n\n/**\n * Gets the endowments for a particular Snap. Some endowments, like `setTimeout`\n * and `clearTimeout`, must be attenuated so that they can only affect behavior\n * within the Snap's own realm. Therefore, we use factory functions to create\n * such attenuated / modified endowments. Otherwise, the value that's on the\n * root realm global will be used.\n *\n * @param snap - The Snaps global API object.\n * @param ethereum - The Snap's EIP-1193 provider object.\n * @param endowments - The list of endowments to provide to the snap.\n * @returns An object containing the Snap's endowments.\n */\nexport function createEndowments(\n snap: SnapsGlobalObject,\n ethereum: StreamProvider,\n endowments: string[] = [],\n): { endowments: Record<string, unknown>; teardown: () => Promise<void> } {\n const attenuatedEndowments: Record<string, unknown> = {};\n\n // TODO: All endowments should be hardened to prevent covert communication\n // channels. Hardening the returned objects breaks tests elsewhere in the\n // monorepo, so further research is needed.\n const result = endowments.reduce(\n ({ allEndowments, teardowns }, endowmentName) => {\n // First, check if the endowment has a factory, and default to that.\n if (endowmentFactories.has(endowmentName)) {\n if (!hasProperty(attenuatedEndowments, endowmentName)) {\n // Call the endowment factory for the current endowment. If the factory\n // creates multiple endowments, they will all be assigned to the\n // `attenuatedEndowments` object, but will only be passed on to the snap\n // if explicitly listed among its endowment.\n // This may not have an actual use case, but, safety first.\n\n // We just confirmed that endowmentFactories has the specified key.\n const { teardownFunction, ...endowment } =\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n endowmentFactories.get(endowmentName)!();\n Object.assign(attenuatedEndowments, endowment);\n if (teardownFunction) {\n teardowns.push(teardownFunction);\n }\n }\n\n allEndowments[endowmentName] = attenuatedEndowments[endowmentName];\n } else if (endowmentName in rootRealmGlobal) {\n // If the endowment doesn't have a factory, just use whatever is on the\n // global object.\n const globalValue = (rootRealmGlobal as Record<string, unknown>)[\n endowmentName\n ];\n allEndowments[endowmentName] =\n typeof globalValue === 'function' && !isConstructor(globalValue)\n ? globalValue.bind(rootRealmGlobal)\n : globalValue;\n } else if (endowmentName === 'ethereum') {\n // Special case for adding the EIP-1193 provider.\n allEndowments[endowmentName] = ethereum;\n } else {\n // If we get to this point, we've been passed an endowment that doesn't\n // exist in our current environment.\n throw new Error(`Unknown endowment: \"${endowmentName}\".`);\n }\n return { allEndowments, teardowns };\n },\n {\n allEndowments: { snap } as Record<string, unknown>,\n teardowns: [] as (() => void)[],\n },\n );\n\n const teardown = async () => {\n await Promise.all(\n result.teardowns.map((teardownFunction) => teardownFunction()),\n );\n };\n return { endowments: result.allEndowments, teardown };\n}\n\n/**\n * Checks whether the specified function is a constructor.\n *\n * @param value - Any function value.\n * @returns Whether the specified function is a constructor.\n */\n// `Function` is exactly what we want here.\n// eslint-disable-next-line @typescript-eslint/ban-types\nexport function isConstructor<T extends Function>(value: T): boolean {\n // In our current usage, the string `prototype.constructor.name` should never\n // be empty, because you can't create a class with no name, and the\n // `prototype.constructor.name` property is configurable but not writable.\n // Nevertheless, that property was the empty string for `Date` in the iframe\n // execution environment during local testing. We have no idea why, but we\n // have to handle that case.\n // TODO: Does the `prototype` object always have a `constructor` property?\n return Boolean(typeof value.prototype?.constructor?.name === 'string');\n}\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/common/endowments/index.ts"],"names":[],"mappings":"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","sourcesContent":["import { StreamProvider } from '@metamask/providers';\nimport { SnapsGlobalObject } from '@metamask/snaps-types';\nimport { hasProperty } from '@metamask/utils';\n\nimport { rootRealmGlobal } from '../globalObject';\nimport crypto from './crypto';\nimport interval from './interval';\nimport math from './math';\nimport network from './network';\nimport timeout from './timeout';\n\ntype EndowmentFactoryResult = {\n /**\n * A function that performs any necessary teardown when the snap becomes idle.\n *\n * NOTE:** The endowments are not reconstructed if the snap is re-invoked\n * before being terminated, so the teardown operation must not render the\n * endowments unusable; it should simply restore the endowments to their\n * original state.\n */\n teardownFunction?: () => Promise<void> | void;\n [key: string]: unknown;\n};\n\n/**\n * A map of endowment names to their factory functions. Some endowments share\n * the same factory function, but we only call each factory once for each snap.\n * See {@link createEndowments} for details.\n */\nconst endowmentFactories = [timeout, interval, network, crypto, math].reduce(\n (factories, builder) => {\n builder.names.forEach((name) => {\n factories.set(name, builder.factory);\n });\n return factories;\n },\n new Map<string, () => EndowmentFactoryResult>(),\n);\n\n/**\n * Gets the endowments for a particular Snap. Some endowments, like `setTimeout`\n * and `clearTimeout`, must be attenuated so that they can only affect behavior\n * within the Snap's own realm. Therefore, we use factory functions to create\n * such attenuated / modified endowments. Otherwise, the value that's on the\n * root realm global will be used.\n *\n * @param snap - The Snaps global API object.\n * @param ethereum - The Snap's EIP-1193 provider object.\n * @param endowments - The list of endowments to provide to the snap.\n * @returns An object containing the Snap's endowments.\n */\nexport function createEndowments(\n snap: SnapsGlobalObject,\n ethereum: StreamProvider,\n endowments: string[] = [],\n): { endowments: Record<string, unknown>; teardown: () => Promise<void> } {\n const attenuatedEndowments: Record<string, unknown> = {};\n\n // TODO: All endowments should be hardened to prevent covert communication\n // channels. Hardening the returned objects breaks tests elsewhere in the\n // monorepo, so further research is needed.\n const result = endowments.reduce<{\n allEndowments: Record<string, unknown>;\n teardowns: (() => Promise<void> | void)[];\n }>(\n ({ allEndowments, teardowns }, endowmentName) => {\n // First, check if the endowment has a factory, and default to that.\n if (endowmentFactories.has(endowmentName)) {\n if (!hasProperty(attenuatedEndowments, endowmentName)) {\n // Call the endowment factory for the current endowment. If the factory\n // creates multiple endowments, they will all be assigned to the\n // `attenuatedEndowments` object, but will only be passed on to the snap\n // if explicitly listed among its endowment.\n // This may not have an actual use case, but, safety first.\n\n // We just confirmed that endowmentFactories has the specified key.\n const { teardownFunction, ...endowment } =\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n endowmentFactories.get(endowmentName)!();\n Object.assign(attenuatedEndowments, endowment);\n if (teardownFunction) {\n teardowns.push(teardownFunction);\n }\n }\n\n allEndowments[endowmentName] = attenuatedEndowments[endowmentName];\n } else if (endowmentName in rootRealmGlobal) {\n // If the endowment doesn't have a factory, just use whatever is on the\n // global object.\n const globalValue = (rootRealmGlobal as Record<string, unknown>)[\n endowmentName\n ];\n allEndowments[endowmentName] =\n typeof globalValue === 'function' && !isConstructor(globalValue)\n ? globalValue.bind(rootRealmGlobal)\n : globalValue;\n } else if (endowmentName === 'ethereum') {\n // Special case for adding the EIP-1193 provider.\n allEndowments[endowmentName] = ethereum;\n } else {\n // If we get to this point, we've been passed an endowment that doesn't\n // exist in our current environment.\n throw new Error(`Unknown endowment: \"${endowmentName}\".`);\n }\n return { allEndowments, teardowns };\n },\n {\n allEndowments: { snap },\n teardowns: [],\n },\n );\n\n const teardown = async () => {\n await Promise.all(\n result.teardowns.map((teardownFunction) => teardownFunction()),\n );\n };\n return { endowments: result.allEndowments, teardown };\n}\n\n/**\n * Checks whether the specified function is a constructor.\n *\n * @param value - Any function value.\n * @returns Whether the specified function is a constructor.\n */\n// `Function` is exactly what we want here.\n// eslint-disable-next-line @typescript-eslint/ban-types\nexport function isConstructor<T extends Function>(value: T): boolean {\n // In our current usage, the string `prototype.constructor.name` should never\n // be empty, because you can't create a class with no name, and the\n // `prototype.constructor.name` property is configurable but not writable.\n // Nevertheless, that property was the empty string for `Date` in the iframe\n // execution environment during local testing. We have no idea why, but we\n // have to handle that case.\n // TODO: Does the `prototype` object always have a `constructor` property?\n return Boolean(typeof value.prototype?.constructor?.name === 'string');\n}\n"]}
@@ -1,7 +1,7 @@
1
1
  declare const endowmentModule: {
2
2
  names: readonly ["setInterval", "clearInterval"];
3
3
  factory: () => {
4
- readonly setInterval: (handler: TimerHandler, timeout?: number | undefined) => unknown;
4
+ readonly setInterval: (handler: TimerHandler, timeout?: number) => unknown;
5
5
  readonly clearInterval: (handle: unknown) => void;
6
6
  readonly teardownFunction: () => void;
7
7
  };
@@ -8,49 +8,49 @@
8
8
  declare function createMath(): {
9
9
  Math: {
10
10
  random: () => number;
11
- E: number;
12
- LN10: number;
13
- LN2: number;
14
- LOG2E: number;
15
- LOG10E: number;
16
- PI: number;
17
- SQRT1_2: number;
18
- SQRT2: number;
19
- abs(x: number): number;
20
- acos(x: number): number;
21
- asin(x: number): number;
22
- atan(x: number): number;
23
- atan2(y: number, x: number): number;
24
- ceil(x: number): number;
25
- cos(x: number): number;
26
- exp(x: number): number;
27
- floor(x: number): number;
28
- log(x: number): number;
29
- max(...values: number[]): number;
30
- min(...values: number[]): number;
31
- pow(x: number, y: number): number;
32
- round(x: number): number;
33
- sin(x: number): number;
34
- sqrt(x: number): number;
35
- tan(x: number): number;
36
- clz32(x: number): number;
37
- imul(x: number, y: number): number;
38
- sign(x: number): number;
39
- log10(x: number): number;
40
- log2(x: number): number;
41
- log1p(x: number): number;
42
- expm1(x: number): number;
43
- cosh(x: number): number;
44
- sinh(x: number): number;
45
- tanh(x: number): number;
46
- acosh(x: number): number;
47
- asinh(x: number): number;
48
- atanh(x: number): number;
49
- hypot(...values: number[]): number;
50
- trunc(x: number): number;
51
- fround(x: number): number;
52
- cbrt(x: number): number;
53
- [Symbol.toStringTag]: string;
11
+ E?: number | undefined;
12
+ LN10?: number | undefined;
13
+ LN2?: number | undefined;
14
+ LOG2E?: number | undefined;
15
+ LOG10E?: number | undefined;
16
+ PI?: number | undefined;
17
+ SQRT1_2?: number | undefined;
18
+ SQRT2?: number | undefined;
19
+ abs?: ((x: number) => number) | undefined;
20
+ acos?: ((x: number) => number) | undefined;
21
+ asin?: ((x: number) => number) | undefined;
22
+ atan?: ((x: number) => number) | undefined;
23
+ atan2?: ((y: number, x: number) => number) | undefined;
24
+ ceil?: ((x: number) => number) | undefined;
25
+ cos?: ((x: number) => number) | undefined;
26
+ exp?: ((x: number) => number) | undefined;
27
+ floor?: ((x: number) => number) | undefined;
28
+ log?: ((x: number) => number) | undefined;
29
+ max?: ((...values: number[]) => number) | undefined;
30
+ min?: ((...values: number[]) => number) | undefined;
31
+ pow?: ((x: number, y: number) => number) | undefined;
32
+ round?: ((x: number) => number) | undefined;
33
+ sin?: ((x: number) => number) | undefined;
34
+ sqrt?: ((x: number) => number) | undefined;
35
+ tan?: ((x: number) => number) | undefined;
36
+ clz32?: ((x: number) => number) | undefined;
37
+ imul?: ((x: number, y: number) => number) | undefined;
38
+ sign?: ((x: number) => number) | undefined;
39
+ log10?: ((x: number) => number) | undefined;
40
+ log2?: ((x: number) => number) | undefined;
41
+ log1p?: ((x: number) => number) | undefined;
42
+ expm1?: ((x: number) => number) | undefined;
43
+ cosh?: ((x: number) => number) | undefined;
44
+ sinh?: ((x: number) => number) | undefined;
45
+ tanh?: ((x: number) => number) | undefined;
46
+ acosh?: ((x: number) => number) | undefined;
47
+ asinh?: ((x: number) => number) | undefined;
48
+ atanh?: ((x: number) => number) | undefined;
49
+ hypot?: ((...values: number[]) => number) | undefined;
50
+ trunc?: ((x: number) => number) | undefined;
51
+ fround?: ((x: number) => number) | undefined;
52
+ cbrt?: ((x: number) => number) | undefined;
53
+ [Symbol.toStringTag]?: string | undefined;
54
54
  };
55
55
  };
56
56
  declare const endowmentModule: {
@@ -1 +1 @@
1
- {"version":3,"file":"math.js","sourceRoot":"","sources":["../../../src/common/endowments/math.ts"],"names":[],"mappings":";;AAAA,kDAAkD;AAElD;;;;;;GAMG;AACH,SAAS,UAAU;IACjB,yEAAyE;IACzE,wDAAwD;IACxD,MAAM,IAAI,GAAG,MAAM,CAAC,mBAAmB,CACrC,8BAAe,CAAC,IAAI,CACI,CAAC;IAE3B,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAO,CAAC,MAAM,EAAE,GAAG,EAAE,EAAE;QAC7C,IAAI,GAAG,KAAK,QAAQ,EAAE;YACpB,OAAO,MAAM,CAAC;SACf;QAED,uCAAY,MAAM,KAAE,CAAC,GAAG,CAAC,EAAE,8BAAe,CAAC,IAAI,CAAC,GAAG,CAAC,IAAG;IACzD,CAAC,EAAE,EAAU,CAAC,CAAC;IAEf,OAAO;QACL,IAAI,kCACC,IAAI,KACP,MAAM,EAAE,GAAG,EAAE;gBACX,qEAAqE;gBACrE,wEAAwE;gBACxE,wEAAwE;gBACxE,gEAAgE;gBAChE,WAAW;gBACX,EAAE;gBACF,mEAAmE;gBACnE,qEAAqE;gBACrE,0BAA0B;gBAC1B,EAAE;gBACF,sEAAsE;gBACtE,sEAAsE;gBACtE,OAAO;gBACP,EAAE;gBACF,8EAA8E;gBAC9E,4EAA4E;gBAC5E,OAAO,MAAM,CAAC,eAAe,CAAC,IAAI,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;YACjE,CAAC,GACF;KACF,CAAC;AACJ,CAAC;AAED,MAAM,eAAe,GAAG;IACtB,KAAK,EAAE,CAAC,MAAM,CAAU;IACxB,OAAO,EAAE,UAAU;CACpB,CAAC;AAEF,kBAAe,eAAe,CAAC","sourcesContent":["import { rootRealmGlobal } from '../globalObject';\n\n/**\n * Create a {@link Math} object, with the same properties as the global\n * {@link Math} object, but with the {@link Math.random} method replaced.\n *\n * @returns The {@link Math} object with the {@link Math.random} method\n * replaced.\n */\nfunction createMath() {\n // `Math` does not work with `Object.keys`, `Object.entries`, etc., so we\n // need to create a new object with the same properties.\n const keys = Object.getOwnPropertyNames(\n rootRealmGlobal.Math,\n ) as (keyof typeof Math)[];\n\n const math = keys.reduce<Math>((target, key) => {\n if (key === 'random') {\n return target;\n }\n\n return { ...target, [key]: rootRealmGlobal.Math[key] };\n }, {} as Math);\n\n return {\n Math: {\n ...math,\n random: () => {\n // NOTE: This is not intended to be a secure replacement for the weak\n // random number generator used by `Math.random`. It is only intended to\n // prevent side channel attacks of `Math.random` by replacing it with an\n // alternative implementation that is not vulnerable to the same\n // attacks.\n //\n // This does not mean that this implementation is secure. It is not\n // intended to be used in a security context, and this implementation\n // may change at any time.\n //\n // To securely generate random numbers, use a cryptographically secure\n // random number generator, such as the one provided by the Web Crypto\n // API:\n //\n // - https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/generateKey\n // - https://developer.mozilla.org/en-US/docs/Web/API/Crypto/getRandomValues\n return crypto.getRandomValues(new Uint32Array(1))[0] / 2 ** 32;\n },\n },\n };\n}\n\nconst endowmentModule = {\n names: ['Math'] as const,\n factory: createMath,\n};\n\nexport default endowmentModule;\n"]}
1
+ {"version":3,"file":"math.js","sourceRoot":"","sources":["../../../src/common/endowments/math.ts"],"names":[],"mappings":";;AAAA,kDAAkD;AAElD;;;;;;GAMG;AACH,SAAS,UAAU;IACjB,yEAAyE;IACzE,wDAAwD;IACxD,MAAM,IAAI,GAAG,MAAM,CAAC,mBAAmB,CACrC,8BAAe,CAAC,IAAI,CACI,CAAC;IAE3B,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAgB,CAAC,MAAM,EAAE,GAAG,EAAE,EAAE;QACtD,IAAI,GAAG,KAAK,QAAQ,EAAE;YACpB,OAAO,MAAM,CAAC;SACf;QAED,uCAAY,MAAM,KAAE,CAAC,GAAG,CAAC,EAAE,8BAAe,CAAC,IAAI,CAAC,GAAG,CAAC,IAAG;IACzD,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,OAAO;QACL,IAAI,kCACC,IAAI,KACP,MAAM,EAAE,GAAG,EAAE;gBACX,qEAAqE;gBACrE,wEAAwE;gBACxE,wEAAwE;gBACxE,gEAAgE;gBAChE,WAAW;gBACX,EAAE;gBACF,mEAAmE;gBACnE,qEAAqE;gBACrE,0BAA0B;gBAC1B,EAAE;gBACF,sEAAsE;gBACtE,sEAAsE;gBACtE,OAAO;gBACP,EAAE;gBACF,8EAA8E;gBAC9E,4EAA4E;gBAC5E,OAAO,MAAM,CAAC,eAAe,CAAC,IAAI,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;YACjE,CAAC,GACF;KACF,CAAC;AACJ,CAAC;AAED,MAAM,eAAe,GAAG;IACtB,KAAK,EAAE,CAAC,MAAM,CAAU;IACxB,OAAO,EAAE,UAAU;CACpB,CAAC;AAEF,kBAAe,eAAe,CAAC","sourcesContent":["import { rootRealmGlobal } from '../globalObject';\n\n/**\n * Create a {@link Math} object, with the same properties as the global\n * {@link Math} object, but with the {@link Math.random} method replaced.\n *\n * @returns The {@link Math} object with the {@link Math.random} method\n * replaced.\n */\nfunction createMath() {\n // `Math` does not work with `Object.keys`, `Object.entries`, etc., so we\n // need to create a new object with the same properties.\n const keys = Object.getOwnPropertyNames(\n rootRealmGlobal.Math,\n ) as (keyof typeof Math)[];\n\n const math = keys.reduce<Partial<Math>>((target, key) => {\n if (key === 'random') {\n return target;\n }\n\n return { ...target, [key]: rootRealmGlobal.Math[key] };\n }, {});\n\n return {\n Math: {\n ...math,\n random: () => {\n // NOTE: This is not intended to be a secure replacement for the weak\n // random number generator used by `Math.random`. It is only intended to\n // prevent side channel attacks of `Math.random` by replacing it with an\n // alternative implementation that is not vulnerable to the same\n // attacks.\n //\n // This does not mean that this implementation is secure. It is not\n // intended to be used in a security context, and this implementation\n // may change at any time.\n //\n // To securely generate random numbers, use a cryptographically secure\n // random number generator, such as the one provided by the Web Crypto\n // API:\n //\n // - https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/generateKey\n // - https://developer.mozilla.org/en-US/docs/Web/API/Crypto/getRandomValues\n return crypto.getRandomValues(new Uint32Array(1))[0] / 2 ** 32;\n },\n },\n };\n}\n\nconst endowmentModule = {\n names: ['Math'] as const,\n factory: createMath,\n};\n\nexport default endowmentModule;\n"]}
@@ -4,12 +4,12 @@ declare const endowmentModule: {
4
4
  factory: () => {
5
5
  fetch: typeof fetch;
6
6
  WebSocket: {
7
- new (url: string | URL, protocols?: string | string[] | undefined): {
7
+ new (url: string | URL, protocols?: string | string[]): {
8
8
  onclose: WebSocketCallback | null;
9
9
  onerror: ((this: WebSocket, ev: Event) => any) | null;
10
- onmessage: ((this: WebSocket, ev: MessageEvent<any>) => any) | null;
10
+ onmessage: ((this: WebSocket, ev: MessageEvent) => any) | null;
11
11
  onopen: ((this: WebSocket, ev: Event) => any) | null;
12
- close(code?: number | undefined, reason?: string | undefined): void;
12
+ close(code?: number, reason?: string): void;
13
13
  send(data: string | Blob | ArrayBufferView | ArrayBufferLike): void;
14
14
  readonly CLOSED: number;
15
15
  readonly CLOSING: number;
@@ -21,10 +21,10 @@ declare const endowmentModule: {
21
21
  readonly protocol: string;
22
22
  readonly readyState: number;
23
23
  readonly url: string;
24
- addEventListener<K extends keyof WebSocketEventMap>(type: K, listener: (this: WebSocket, ev: WebSocketEventMap[K]) => any, options?: boolean | AddEventListenerOptions | undefined): void;
25
- addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions | undefined): void;
26
- removeEventListener<K_1 extends keyof WebSocketEventMap>(type: K_1, listener: (this: WebSocket, ev: WebSocketEventMap[K_1]) => any, options?: boolean | EventListenerOptions | undefined): void;
27
- removeEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | EventListenerOptions | undefined): void;
24
+ addEventListener<K extends keyof WebSocketEventMap>(type: K, listener: (this: WebSocket, ev: WebSocketEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void;
25
+ addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void;
26
+ removeEventListener<K_1 extends keyof WebSocketEventMap>(type: K_1, listener: (this: WebSocket, ev: WebSocketEventMap[K_1]) => any, options?: boolean | EventListenerOptions): void;
27
+ removeEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | EventListenerOptions): void;
28
28
  dispatchEvent(event: Event): boolean;
29
29
  "__#4@#teardownClose"(): Promise<void>;
30
30
  "__#4@#createWrapped"(listener: WebSocketCallback): WebSocketCallback;