Big News: Socket raises $60M Series C at a $1B valuation to secure software supply chains for AI-driven development.Announcement
Sign In

@metamask/snaps-controllers

Package Overview
Dependencies
Maintainers
4
Versions
140
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@metamask/snaps-controllers - npm Package Compare versions

Comparing version
18.0.3
to
18.0.4
+8
-1
CHANGELOG.md

@@ -10,2 +10,8 @@ # Changelog

## [18.0.4]
### Fixed
- Always attach error handler to RPC stream ([#3898](https://github.com/MetaMask/snaps/pull/3898))
## [18.0.3]

@@ -1073,3 +1079,4 @@

[Unreleased]: https://github.com/MetaMask/snaps/compare/@metamask/snaps-controllers@18.0.3...HEAD
[Unreleased]: https://github.com/MetaMask/snaps/compare/@metamask/snaps-controllers@18.0.4...HEAD
[18.0.4]: https://github.com/MetaMask/snaps/compare/@metamask/snaps-controllers@18.0.3...@metamask/snaps-controllers@18.0.4
[18.0.3]: https://github.com/MetaMask/snaps/compare/@metamask/snaps-controllers@18.0.2...@metamask/snaps-controllers@18.0.3

@@ -1076,0 +1083,0 @@ [18.0.2]: https://github.com/MetaMask/snaps/compare/@metamask/snaps-controllers@18.0.1...@metamask/snaps-controllers@18.0.2

@@ -172,2 +172,9 @@ "use strict";

});
// An error handler is not attached to the RPC stream until `setupSnapProvider` is called.
// We must set it up here to prevent errors from bubbling up if the stream is destroyed before then.
rpcStream.on('error', (error) => {
if (error && !error.message?.match('Premature close')) {
(0, snaps_utils_1.logError)(`Snap: "${snapId}" - RPC stream failure:`, error);
}
});
const originalWrite = rpcStream.write.bind(rpcStream);

@@ -174,0 +181,0 @@ // @ts-expect-error Hack to inspect the messages being written to the stream.

+1
-1

@@ -1,1 +0,1 @@

{"version":3,"file":"AbstractExecutionService.cjs","sourceRoot":"","sources":["../../src/services/AbstractExecutionService.ts"],"names":[],"mappings":"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","sourcesContent":["import { asV2Middleware } from '@metamask/json-rpc-engine';\nimport { JsonRpcEngineV2 as JsonRpcEngine } from '@metamask/json-rpc-engine/v2';\nimport { createStreamMiddleware } from '@metamask/json-rpc-middleware-stream';\nimport ObjectMultiplex from '@metamask/object-multiplex';\nimport type { BasePostMessageStream } from '@metamask/post-message-stream';\nimport type { SnapRpcHookArgs } from '@metamask/snaps-utils';\nimport { SNAP_STREAM_NAMES, logError, logWarning } from '@metamask/snaps-utils';\nimport type {\n Json,\n JsonRpcNotification,\n JsonRpcRequest,\n} from '@metamask/utils';\nimport {\n Duration,\n assertIsJsonRpcRequest,\n hasProperty,\n inMilliseconds,\n} from '@metamask/utils';\nimport { nanoid } from 'nanoid';\nimport { pipeline } from 'readable-stream';\nimport type { Duplex } from 'readable-stream';\n\nimport type {\n ExecutionService,\n ExecutionServiceMessenger,\n SnapErrorJson,\n SnapExecutionData,\n} from './ExecutionService';\nimport { log } from '../logging';\nimport { Timer } from '../snaps/Timer';\nimport { hasTimedOut, withTimeout } from '../utils';\n\nconst controllerName = 'ExecutionService';\n\nexport type SetupSnapProvider = (snapId: string, stream: Duplex) => void;\n\nexport type ExecutionServiceArgs = {\n setupSnapProvider: SetupSnapProvider;\n messenger: ExecutionServiceMessenger;\n initTimeout?: number;\n pingTimeout?: number;\n terminationTimeout?: number;\n usePing?: boolean;\n};\n\nexport type JobStreams = {\n command: Duplex;\n rpc: Duplex;\n connection: BasePostMessageStream;\n mux: ObjectMultiplex;\n};\n\nexport type Job<WorkerType> = {\n id: string;\n streams: JobStreams;\n rpcEngine: JsonRpcEngine<JsonRpcRequest>;\n worker: WorkerType;\n};\n\nexport type TerminateJobArgs<WorkerType> = Partial<Job<WorkerType>> &\n Pick<Job<WorkerType>, 'id'>;\n\n/** \n Statuses used for diagnostic purposes\n - created: The initial state, no initialization has started \n - initializing: Snap execution environment is initializing\n - initialized: Snap execution environment has initialized\n - executing: Snap source code is being executed\n - running: Snap executed and ready for RPC requests\n */\ntype ExecutionStatus =\n | 'created'\n | 'initializing'\n | 'initialized'\n | 'executing'\n | 'running';\n\nexport abstract class AbstractExecutionService<WorkerType>\n implements ExecutionService\n{\n name: typeof controllerName = controllerName;\n\n state = null;\n\n readonly #jobs: Map<string, Job<WorkerType>>;\n\n readonly #status: Map<string, ExecutionStatus>;\n\n readonly #setupSnapProvider: SetupSnapProvider;\n\n readonly #messenger: ExecutionServiceMessenger;\n\n readonly #initTimeout: number;\n\n readonly #pingTimeout: number;\n\n readonly #terminationTimeout: number;\n\n readonly #usePing: boolean;\n\n constructor({\n setupSnapProvider,\n messenger,\n initTimeout = inMilliseconds(60, Duration.Second),\n pingTimeout = inMilliseconds(10, Duration.Second),\n terminationTimeout = inMilliseconds(1, Duration.Second),\n usePing = true,\n }: ExecutionServiceArgs) {\n this.#jobs = new Map();\n this.#status = new Map();\n this.#setupSnapProvider = setupSnapProvider;\n this.#messenger = messenger;\n this.#initTimeout = initTimeout;\n this.#pingTimeout = pingTimeout;\n this.#terminationTimeout = terminationTimeout;\n this.#usePing = usePing;\n\n this.#registerMessageHandlers();\n }\n\n /**\n * Constructor helper for registering the controller's messaging system\n * actions.\n */\n #registerMessageHandlers(): void {\n this.#messenger.registerActionHandler(\n `${controllerName}:handleRpcRequest`,\n async (snapId: string, options: SnapRpcHookArgs) =>\n this.handleRpcRequest(snapId, options),\n );\n\n this.#messenger.registerActionHandler(\n `${controllerName}:executeSnap`,\n async (data: SnapExecutionData) => this.executeSnap(data),\n );\n\n this.#messenger.registerActionHandler(\n `${controllerName}:terminateSnap`,\n async (snapId: string) => this.terminateSnap(snapId),\n );\n\n this.#messenger.registerActionHandler(\n `${controllerName}:terminateAllSnaps`,\n async () => this.terminateAllSnaps(),\n );\n }\n\n /**\n * Performs additional necessary work during job termination. **MUST** be\n * implemented by concrete implementations. See\n * {@link AbstractExecutionService.terminate} for details.\n *\n * @param job - The object corresponding to the job to be terminated.\n */\n protected abstract terminateJob(\n job: TerminateJobArgs<WorkerType>,\n ): Promise<void>;\n\n /**\n * Terminates the Snap with the specified ID and deletes all its associated\n * data. Any subsequent messages targeting the Snap will fail with an error.\n * Throws an error if termination fails unexpectedly.\n *\n * @param snapId - The id of the Snap to be terminated.\n */\n public async terminateSnap(snapId: string): Promise<void> {\n const job = this.#jobs.get(snapId);\n if (!job) {\n return;\n }\n\n try {\n // Ping worker and tell it to run teardown, continue with termination if it takes too long\n const result = await withTimeout(\n this.#command(snapId, {\n jsonrpc: '2.0',\n method: 'terminate',\n id: nanoid(),\n }),\n this.#terminationTimeout,\n );\n\n if (result === hasTimedOut || result !== 'OK') {\n logWarning(`Snap \"${snapId}\" failed to terminate gracefully.`);\n }\n } catch {\n // Ignore\n }\n\n Object.values(job.streams).forEach((stream) => {\n try {\n if (!stream.destroyed) {\n stream.destroy();\n }\n } catch (error) {\n logError('Error while destroying stream', error);\n }\n });\n\n await this.terminateJob(job);\n\n this.#jobs.delete(snapId);\n this.#status.delete(snapId);\n log(`Snap \"${snapId}\" terminated.`);\n }\n\n /**\n * Initiates a job for a Snap.\n *\n * @param snapId - The ID of the Snap to initiate a job for.\n * @param timer - The timer to use for timeouts.\n * @returns Information regarding the created job.\n * @throws If the execution service returns an error or execution times out.\n */\n async #initJob(snapId: string, timer: Timer): Promise<Job<WorkerType>> {\n const { streams, worker } = await this.#initStreams(snapId, timer);\n\n const jsonRpcConnection = createStreamMiddleware();\n\n pipeline(\n jsonRpcConnection.stream,\n streams.command,\n jsonRpcConnection.stream,\n (error) => {\n if (error && !error.message?.match('Premature close')) {\n logError(`Command stream failure.`, error);\n }\n },\n );\n\n const rpcEngine = JsonRpcEngine.create({\n middleware: [asV2Middleware(jsonRpcConnection.middleware)],\n });\n\n const envMetadata = {\n id: snapId,\n streams,\n rpcEngine,\n worker,\n };\n this.#jobs.set(snapId, envMetadata);\n\n return envMetadata;\n }\n\n /**\n * Sets up the streams for an initiated job.\n *\n * @param snapId - The Snap ID.\n * @param timer - The timer to use for timeouts.\n * @returns The streams to communicate with the worker and the worker itself.\n * @throws If the execution service returns an error or execution times out.\n */\n async #initStreams(\n snapId: string,\n timer: Timer,\n ): Promise<{ streams: JobStreams; worker: WorkerType }> {\n const result = await withTimeout(this.initEnvStream(snapId), timer);\n\n if (result === hasTimedOut) {\n // For certain environments, such as the iframe we may have already created the worker and wish to terminate it.\n await this.terminateJob({ id: snapId });\n\n const status = this.#status.get(snapId);\n if (status === 'created') {\n // Currently this error can only be thrown by OffscreenExecutionService.\n throw new Error(\n `The executor for \"${snapId}\" couldn't start initialization. The offscreen document may not exist.`,\n );\n }\n throw new Error(\n `The executor for \"${snapId}\" failed to initialize. The iframe/webview/worker failed to load.`,\n );\n }\n\n const { worker, stream: envStream } = result;\n const mux = setupMultiplex(envStream, `Snap: \"${snapId}\"`);\n const commandStream = mux.createStream(SNAP_STREAM_NAMES.COMMAND);\n\n // Handle out-of-band errors, i.e. errors thrown from the Snap outside of the req/res cycle.\n // Also keep track of outbound request/responses\n const notificationHandler = (\n message:\n | JsonRpcRequest\n | JsonRpcNotification<Json[] | Record<string, Json>>,\n ) => {\n if (hasProperty(message, 'id')) {\n return;\n }\n\n if (message.method === 'OutboundRequest') {\n this.#messenger.publish('ExecutionService:outboundRequest', snapId);\n } else if (message.method === 'OutboundResponse') {\n this.#messenger.publish('ExecutionService:outboundResponse', snapId);\n } else if (message.method === 'UnhandledError') {\n this.#messenger.publish(\n 'ExecutionService:unhandledError',\n snapId,\n (message.params as { error: SnapErrorJson }).error,\n );\n commandStream.removeListener('data', notificationHandler);\n } else {\n logError(\n new Error(\n `Received unexpected command stream notification \"${message.method}\".`,\n ),\n );\n }\n };\n\n commandStream.on('data', notificationHandler);\n\n const rpcStream = mux\n .createStream(SNAP_STREAM_NAMES.JSON_RPC)\n .setMaxListeners(20);\n\n rpcStream.on('data', (chunk) => {\n if (chunk?.data && hasProperty(chunk?.data, 'id')) {\n this.#messenger.publish('ExecutionService:outboundRequest', snapId);\n }\n });\n\n const originalWrite = rpcStream.write.bind(rpcStream);\n\n // @ts-expect-error Hack to inspect the messages being written to the stream.\n rpcStream.write = (chunk, encoding, callback) => {\n // Ignore chain switching notifications as it doesn't matter for the SnapProvider.\n if (chunk?.data?.method === 'metamask_chainChanged') {\n return true;\n }\n\n if (chunk?.data && hasProperty(chunk?.data, 'id')) {\n this.#messenger.publish('ExecutionService:outboundResponse', snapId);\n }\n\n return originalWrite(chunk, encoding, callback);\n };\n\n return {\n streams: {\n command: commandStream,\n rpc: rpcStream,\n connection: envStream,\n mux,\n },\n worker,\n };\n }\n\n /**\n * Abstract function implemented by implementing class that spins up a new worker for a job.\n *\n * Depending on the execution environment, this may run forever if the Snap fails to start up properly, therefore any call to this function should be wrapped in a timeout.\n */\n protected abstract initEnvStream(snapId: string): Promise<{\n worker: WorkerType;\n stream: BasePostMessageStream;\n }>;\n\n /**\n * Set the execution status of the Snap.\n *\n * @param snapId - The Snap ID.\n * @param status - The current execution status.\n */\n protected setSnapStatus(snapId: string, status: ExecutionStatus) {\n this.#status.set(snapId, status);\n }\n\n async terminateAllSnaps() {\n await Promise.all(\n [...this.#jobs.keys()].map(async (snapId) => this.terminateSnap(snapId)),\n );\n }\n\n /**\n * Initializes and executes a Snap, setting up the communication channels to the Snap etc.\n *\n * @param snapData - Data needed for Snap execution.\n * @param snapData.snapId - The ID of the Snap to execute.\n * @param snapData.sourceCode - The source code of the Snap to execute.\n * @param snapData.endowments - The endowments available to the executing Snap.\n * @returns A string `OK` if execution succeeded.\n * @throws If the execution service returns an error or execution times out.\n */\n async executeSnap({\n snapId,\n sourceCode,\n endowments,\n }: SnapExecutionData): Promise<string> {\n if (this.#jobs.has(snapId)) {\n throw new Error(`\"${snapId}\" is already running.`);\n }\n\n this.setSnapStatus(snapId, 'created');\n\n const timer = new Timer(this.#initTimeout);\n\n // This may resolve even if the environment has failed to start up fully\n const job = await this.#initJob(snapId, timer);\n\n // Certain environments use ping as part of their initialization and thus can skip it here\n if (this.#usePing) {\n // Ping the worker to ensure that it started up\n const pingResult = await withTimeout(\n this.#command(job.id, {\n jsonrpc: '2.0',\n method: 'ping',\n id: nanoid(),\n }),\n this.#pingTimeout,\n );\n\n if (pingResult === hasTimedOut) {\n throw new Error(\n `The executor for \"${snapId}\" was unreachable. The executor did not respond in time.`,\n );\n }\n }\n\n const rpcStream = job.streams.rpc;\n\n this.#setupSnapProvider(snapId, rpcStream);\n\n // Use the remaining time as the timer, but ensure that the\n // Snap gets at least half the init timeout.\n const remainingTime = Math.max(timer.remaining, this.#initTimeout / 2);\n\n this.setSnapStatus(snapId, 'initialized');\n\n const request = {\n jsonrpc: '2.0',\n method: 'executeSnap',\n params: { snapId, sourceCode, endowments },\n id: nanoid(),\n };\n\n assertIsJsonRpcRequest(request);\n\n this.setSnapStatus(snapId, 'executing');\n\n const result = await withTimeout(\n this.#command(job.id, request),\n remainingTime,\n );\n\n if (result === hasTimedOut) {\n throw new Error(`${snapId} failed to start.`);\n }\n\n if (result === 'OK') {\n this.setSnapStatus(snapId, 'running');\n }\n\n return result as string;\n }\n\n async #command(\n snapId: string,\n message: JsonRpcRequest,\n ): Promise<Json | undefined> {\n const job = this.#jobs.get(snapId);\n if (!job) {\n throw new Error(`\"${snapId}\" is not currently running.`);\n }\n\n log('Parent: Sending Command', message);\n return await job.rpcEngine.handle(message);\n }\n\n /**\n * Handle RPC request.\n *\n * @param snapId - The ID of the recipient Snap.\n * @param options - Bag of options to pass to the RPC handler.\n * @returns Promise that can handle the request.\n */\n public async handleRpcRequest(\n snapId: string,\n options: SnapRpcHookArgs,\n ): Promise<unknown> {\n const { handler, request, origin } = options;\n\n return await this.#command(snapId, {\n id: nanoid(),\n jsonrpc: '2.0',\n method: 'snapRpc',\n params: {\n snapId,\n origin,\n handler,\n request: request as JsonRpcRequest,\n },\n });\n }\n}\n\n/**\n * Sets up stream multiplexing for the given stream.\n *\n * @param connectionStream - The stream to mux.\n * @param streamName - The name of the stream, for identification in errors.\n * @returns The multiplexed stream.\n */\nexport function setupMultiplex(\n connectionStream: Duplex,\n streamName: string,\n): ObjectMultiplex {\n const mux = new ObjectMultiplex();\n pipeline(connectionStream, mux, connectionStream, (error) => {\n if (error && !error.message?.match('Premature close')) {\n logError(`\"${streamName}\" stream failure.`, error);\n }\n });\n return mux;\n}\n"]}
{"version":3,"file":"AbstractExecutionService.cjs","sourceRoot":"","sources":["../../src/services/AbstractExecutionService.ts"],"names":[],"mappings":"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","sourcesContent":["import { asV2Middleware } from '@metamask/json-rpc-engine';\nimport { JsonRpcEngineV2 as JsonRpcEngine } from '@metamask/json-rpc-engine/v2';\nimport { createStreamMiddleware } from '@metamask/json-rpc-middleware-stream';\nimport ObjectMultiplex from '@metamask/object-multiplex';\nimport type { BasePostMessageStream } from '@metamask/post-message-stream';\nimport type { SnapRpcHookArgs } from '@metamask/snaps-utils';\nimport { SNAP_STREAM_NAMES, logError, logWarning } from '@metamask/snaps-utils';\nimport type {\n Json,\n JsonRpcNotification,\n JsonRpcRequest,\n} from '@metamask/utils';\nimport {\n Duration,\n assertIsJsonRpcRequest,\n hasProperty,\n inMilliseconds,\n} from '@metamask/utils';\nimport { nanoid } from 'nanoid';\nimport { pipeline } from 'readable-stream';\nimport type { Duplex } from 'readable-stream';\n\nimport type {\n ExecutionService,\n ExecutionServiceMessenger,\n SnapErrorJson,\n SnapExecutionData,\n} from './ExecutionService';\nimport { log } from '../logging';\nimport { Timer } from '../snaps/Timer';\nimport { hasTimedOut, withTimeout } from '../utils';\n\nconst controllerName = 'ExecutionService';\n\nexport type SetupSnapProvider = (snapId: string, stream: Duplex) => void;\n\nexport type ExecutionServiceArgs = {\n setupSnapProvider: SetupSnapProvider;\n messenger: ExecutionServiceMessenger;\n initTimeout?: number;\n pingTimeout?: number;\n terminationTimeout?: number;\n usePing?: boolean;\n};\n\nexport type JobStreams = {\n command: Duplex;\n rpc: Duplex;\n connection: BasePostMessageStream;\n mux: ObjectMultiplex;\n};\n\nexport type Job<WorkerType> = {\n id: string;\n streams: JobStreams;\n rpcEngine: JsonRpcEngine<JsonRpcRequest>;\n worker: WorkerType;\n};\n\nexport type TerminateJobArgs<WorkerType> = Partial<Job<WorkerType>> &\n Pick<Job<WorkerType>, 'id'>;\n\n/** \n Statuses used for diagnostic purposes\n - created: The initial state, no initialization has started \n - initializing: Snap execution environment is initializing\n - initialized: Snap execution environment has initialized\n - executing: Snap source code is being executed\n - running: Snap executed and ready for RPC requests\n */\ntype ExecutionStatus =\n | 'created'\n | 'initializing'\n | 'initialized'\n | 'executing'\n | 'running';\n\nexport abstract class AbstractExecutionService<WorkerType>\n implements ExecutionService\n{\n name: typeof controllerName = controllerName;\n\n state = null;\n\n readonly #jobs: Map<string, Job<WorkerType>>;\n\n readonly #status: Map<string, ExecutionStatus>;\n\n readonly #setupSnapProvider: SetupSnapProvider;\n\n readonly #messenger: ExecutionServiceMessenger;\n\n readonly #initTimeout: number;\n\n readonly #pingTimeout: number;\n\n readonly #terminationTimeout: number;\n\n readonly #usePing: boolean;\n\n constructor({\n setupSnapProvider,\n messenger,\n initTimeout = inMilliseconds(60, Duration.Second),\n pingTimeout = inMilliseconds(10, Duration.Second),\n terminationTimeout = inMilliseconds(1, Duration.Second),\n usePing = true,\n }: ExecutionServiceArgs) {\n this.#jobs = new Map();\n this.#status = new Map();\n this.#setupSnapProvider = setupSnapProvider;\n this.#messenger = messenger;\n this.#initTimeout = initTimeout;\n this.#pingTimeout = pingTimeout;\n this.#terminationTimeout = terminationTimeout;\n this.#usePing = usePing;\n\n this.#registerMessageHandlers();\n }\n\n /**\n * Constructor helper for registering the controller's messaging system\n * actions.\n */\n #registerMessageHandlers(): void {\n this.#messenger.registerActionHandler(\n `${controllerName}:handleRpcRequest`,\n async (snapId: string, options: SnapRpcHookArgs) =>\n this.handleRpcRequest(snapId, options),\n );\n\n this.#messenger.registerActionHandler(\n `${controllerName}:executeSnap`,\n async (data: SnapExecutionData) => this.executeSnap(data),\n );\n\n this.#messenger.registerActionHandler(\n `${controllerName}:terminateSnap`,\n async (snapId: string) => this.terminateSnap(snapId),\n );\n\n this.#messenger.registerActionHandler(\n `${controllerName}:terminateAllSnaps`,\n async () => this.terminateAllSnaps(),\n );\n }\n\n /**\n * Performs additional necessary work during job termination. **MUST** be\n * implemented by concrete implementations. See\n * {@link AbstractExecutionService.terminate} for details.\n *\n * @param job - The object corresponding to the job to be terminated.\n */\n protected abstract terminateJob(\n job: TerminateJobArgs<WorkerType>,\n ): Promise<void>;\n\n /**\n * Terminates the Snap with the specified ID and deletes all its associated\n * data. Any subsequent messages targeting the Snap will fail with an error.\n * Throws an error if termination fails unexpectedly.\n *\n * @param snapId - The id of the Snap to be terminated.\n */\n public async terminateSnap(snapId: string): Promise<void> {\n const job = this.#jobs.get(snapId);\n if (!job) {\n return;\n }\n\n try {\n // Ping worker and tell it to run teardown, continue with termination if it takes too long\n const result = await withTimeout(\n this.#command(snapId, {\n jsonrpc: '2.0',\n method: 'terminate',\n id: nanoid(),\n }),\n this.#terminationTimeout,\n );\n\n if (result === hasTimedOut || result !== 'OK') {\n logWarning(`Snap \"${snapId}\" failed to terminate gracefully.`);\n }\n } catch {\n // Ignore\n }\n\n Object.values(job.streams).forEach((stream) => {\n try {\n if (!stream.destroyed) {\n stream.destroy();\n }\n } catch (error) {\n logError('Error while destroying stream', error);\n }\n });\n\n await this.terminateJob(job);\n\n this.#jobs.delete(snapId);\n this.#status.delete(snapId);\n log(`Snap \"${snapId}\" terminated.`);\n }\n\n /**\n * Initiates a job for a Snap.\n *\n * @param snapId - The ID of the Snap to initiate a job for.\n * @param timer - The timer to use for timeouts.\n * @returns Information regarding the created job.\n * @throws If the execution service returns an error or execution times out.\n */\n async #initJob(snapId: string, timer: Timer): Promise<Job<WorkerType>> {\n const { streams, worker } = await this.#initStreams(snapId, timer);\n\n const jsonRpcConnection = createStreamMiddleware();\n\n pipeline(\n jsonRpcConnection.stream,\n streams.command,\n jsonRpcConnection.stream,\n (error) => {\n if (error && !error.message?.match('Premature close')) {\n logError(`Command stream failure.`, error);\n }\n },\n );\n\n const rpcEngine = JsonRpcEngine.create({\n middleware: [asV2Middleware(jsonRpcConnection.middleware)],\n });\n\n const envMetadata = {\n id: snapId,\n streams,\n rpcEngine,\n worker,\n };\n this.#jobs.set(snapId, envMetadata);\n\n return envMetadata;\n }\n\n /**\n * Sets up the streams for an initiated job.\n *\n * @param snapId - The Snap ID.\n * @param timer - The timer to use for timeouts.\n * @returns The streams to communicate with the worker and the worker itself.\n * @throws If the execution service returns an error or execution times out.\n */\n async #initStreams(\n snapId: string,\n timer: Timer,\n ): Promise<{ streams: JobStreams; worker: WorkerType }> {\n const result = await withTimeout(this.initEnvStream(snapId), timer);\n\n if (result === hasTimedOut) {\n // For certain environments, such as the iframe we may have already created the worker and wish to terminate it.\n await this.terminateJob({ id: snapId });\n\n const status = this.#status.get(snapId);\n if (status === 'created') {\n // Currently this error can only be thrown by OffscreenExecutionService.\n throw new Error(\n `The executor for \"${snapId}\" couldn't start initialization. The offscreen document may not exist.`,\n );\n }\n throw new Error(\n `The executor for \"${snapId}\" failed to initialize. The iframe/webview/worker failed to load.`,\n );\n }\n\n const { worker, stream: envStream } = result;\n const mux = setupMultiplex(envStream, `Snap: \"${snapId}\"`);\n const commandStream = mux.createStream(SNAP_STREAM_NAMES.COMMAND);\n\n // Handle out-of-band errors, i.e. errors thrown from the Snap outside of the req/res cycle.\n // Also keep track of outbound request/responses\n const notificationHandler = (\n message:\n | JsonRpcRequest\n | JsonRpcNotification<Json[] | Record<string, Json>>,\n ) => {\n if (hasProperty(message, 'id')) {\n return;\n }\n\n if (message.method === 'OutboundRequest') {\n this.#messenger.publish('ExecutionService:outboundRequest', snapId);\n } else if (message.method === 'OutboundResponse') {\n this.#messenger.publish('ExecutionService:outboundResponse', snapId);\n } else if (message.method === 'UnhandledError') {\n this.#messenger.publish(\n 'ExecutionService:unhandledError',\n snapId,\n (message.params as { error: SnapErrorJson }).error,\n );\n commandStream.removeListener('data', notificationHandler);\n } else {\n logError(\n new Error(\n `Received unexpected command stream notification \"${message.method}\".`,\n ),\n );\n }\n };\n\n commandStream.on('data', notificationHandler);\n\n const rpcStream = mux\n .createStream(SNAP_STREAM_NAMES.JSON_RPC)\n .setMaxListeners(20);\n\n rpcStream.on('data', (chunk) => {\n if (chunk?.data && hasProperty(chunk?.data, 'id')) {\n this.#messenger.publish('ExecutionService:outboundRequest', snapId);\n }\n });\n\n // An error handler is not attached to the RPC stream until `setupSnapProvider` is called.\n // We must set it up here to prevent errors from bubbling up if the stream is destroyed before then.\n rpcStream.on('error', (error) => {\n if (error && !error.message?.match('Premature close')) {\n logError(`Snap: \"${snapId}\" - RPC stream failure:`, error);\n }\n });\n\n const originalWrite = rpcStream.write.bind(rpcStream);\n\n // @ts-expect-error Hack to inspect the messages being written to the stream.\n rpcStream.write = (chunk, encoding, callback) => {\n // Ignore chain switching notifications as it doesn't matter for the SnapProvider.\n if (chunk?.data?.method === 'metamask_chainChanged') {\n return true;\n }\n\n if (chunk?.data && hasProperty(chunk?.data, 'id')) {\n this.#messenger.publish('ExecutionService:outboundResponse', snapId);\n }\n\n return originalWrite(chunk, encoding, callback);\n };\n\n return {\n streams: {\n command: commandStream,\n rpc: rpcStream,\n connection: envStream,\n mux,\n },\n worker,\n };\n }\n\n /**\n * Abstract function implemented by implementing class that spins up a new worker for a job.\n *\n * Depending on the execution environment, this may run forever if the Snap fails to start up properly, therefore any call to this function should be wrapped in a timeout.\n */\n protected abstract initEnvStream(snapId: string): Promise<{\n worker: WorkerType;\n stream: BasePostMessageStream;\n }>;\n\n /**\n * Set the execution status of the Snap.\n *\n * @param snapId - The Snap ID.\n * @param status - The current execution status.\n */\n protected setSnapStatus(snapId: string, status: ExecutionStatus) {\n this.#status.set(snapId, status);\n }\n\n async terminateAllSnaps() {\n await Promise.all(\n [...this.#jobs.keys()].map(async (snapId) => this.terminateSnap(snapId)),\n );\n }\n\n /**\n * Initializes and executes a Snap, setting up the communication channels to the Snap etc.\n *\n * @param snapData - Data needed for Snap execution.\n * @param snapData.snapId - The ID of the Snap to execute.\n * @param snapData.sourceCode - The source code of the Snap to execute.\n * @param snapData.endowments - The endowments available to the executing Snap.\n * @returns A string `OK` if execution succeeded.\n * @throws If the execution service returns an error or execution times out.\n */\n async executeSnap({\n snapId,\n sourceCode,\n endowments,\n }: SnapExecutionData): Promise<string> {\n if (this.#jobs.has(snapId)) {\n throw new Error(`\"${snapId}\" is already running.`);\n }\n\n this.setSnapStatus(snapId, 'created');\n\n const timer = new Timer(this.#initTimeout);\n\n // This may resolve even if the environment has failed to start up fully\n const job = await this.#initJob(snapId, timer);\n\n // Certain environments use ping as part of their initialization and thus can skip it here\n if (this.#usePing) {\n // Ping the worker to ensure that it started up\n const pingResult = await withTimeout(\n this.#command(job.id, {\n jsonrpc: '2.0',\n method: 'ping',\n id: nanoid(),\n }),\n this.#pingTimeout,\n );\n\n if (pingResult === hasTimedOut) {\n throw new Error(\n `The executor for \"${snapId}\" was unreachable. The executor did not respond in time.`,\n );\n }\n }\n\n const rpcStream = job.streams.rpc;\n\n this.#setupSnapProvider(snapId, rpcStream);\n\n // Use the remaining time as the timer, but ensure that the\n // Snap gets at least half the init timeout.\n const remainingTime = Math.max(timer.remaining, this.#initTimeout / 2);\n\n this.setSnapStatus(snapId, 'initialized');\n\n const request = {\n jsonrpc: '2.0',\n method: 'executeSnap',\n params: { snapId, sourceCode, endowments },\n id: nanoid(),\n };\n\n assertIsJsonRpcRequest(request);\n\n this.setSnapStatus(snapId, 'executing');\n\n const result = await withTimeout(\n this.#command(job.id, request),\n remainingTime,\n );\n\n if (result === hasTimedOut) {\n throw new Error(`${snapId} failed to start.`);\n }\n\n if (result === 'OK') {\n this.setSnapStatus(snapId, 'running');\n }\n\n return result as string;\n }\n\n async #command(\n snapId: string,\n message: JsonRpcRequest,\n ): Promise<Json | undefined> {\n const job = this.#jobs.get(snapId);\n if (!job) {\n throw new Error(`\"${snapId}\" is not currently running.`);\n }\n\n log('Parent: Sending Command', message);\n return await job.rpcEngine.handle(message);\n }\n\n /**\n * Handle RPC request.\n *\n * @param snapId - The ID of the recipient Snap.\n * @param options - Bag of options to pass to the RPC handler.\n * @returns Promise that can handle the request.\n */\n public async handleRpcRequest(\n snapId: string,\n options: SnapRpcHookArgs,\n ): Promise<unknown> {\n const { handler, request, origin } = options;\n\n return await this.#command(snapId, {\n id: nanoid(),\n jsonrpc: '2.0',\n method: 'snapRpc',\n params: {\n snapId,\n origin,\n handler,\n request: request as JsonRpcRequest,\n },\n });\n }\n}\n\n/**\n * Sets up stream multiplexing for the given stream.\n *\n * @param connectionStream - The stream to mux.\n * @param streamName - The name of the stream, for identification in errors.\n * @returns The multiplexed stream.\n */\nexport function setupMultiplex(\n connectionStream: Duplex,\n streamName: string,\n): ObjectMultiplex {\n const mux = new ObjectMultiplex();\n pipeline(connectionStream, mux, connectionStream, (error) => {\n if (error && !error.message?.match('Premature close')) {\n logError(`\"${streamName}\" stream failure.`, error);\n }\n });\n return mux;\n}\n"]}

@@ -1,1 +0,1 @@

{"version":3,"file":"AbstractExecutionService.d.cts","sourceRoot":"","sources":["../../src/services/AbstractExecutionService.ts"],"names":[],"mappings":"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"}
{"version":3,"file":"AbstractExecutionService.d.cts","sourceRoot":"","sources":["../../src/services/AbstractExecutionService.ts"],"names":[],"mappings":"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"}

@@ -1,1 +0,1 @@

{"version":3,"file":"AbstractExecutionService.d.mts","sourceRoot":"","sources":["../../src/services/AbstractExecutionService.ts"],"names":[],"mappings":"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"}
{"version":3,"file":"AbstractExecutionService.d.mts","sourceRoot":"","sources":["../../src/services/AbstractExecutionService.ts"],"names":[],"mappings":"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"}

@@ -173,2 +173,9 @@ function $importDefault(module) {

});
// An error handler is not attached to the RPC stream until `setupSnapProvider` is called.
// We must set it up here to prevent errors from bubbling up if the stream is destroyed before then.
rpcStream.on('error', (error) => {
if (error && !error.message?.match('Premature close')) {
logError(`Snap: "${snapId}" - RPC stream failure:`, error);
}
});
const originalWrite = rpcStream.write.bind(rpcStream);

@@ -175,0 +182,0 @@ // @ts-expect-error Hack to inspect the messages being written to the stream.

@@ -1,1 +0,1 @@

{"version":3,"file":"AbstractExecutionService.mjs","sourceRoot":"","sources":["../../src/services/AbstractExecutionService.ts"],"names":[],"mappings":"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","sourcesContent":["import { asV2Middleware } from '@metamask/json-rpc-engine';\nimport { JsonRpcEngineV2 as JsonRpcEngine } from '@metamask/json-rpc-engine/v2';\nimport { createStreamMiddleware } from '@metamask/json-rpc-middleware-stream';\nimport ObjectMultiplex from '@metamask/object-multiplex';\nimport type { BasePostMessageStream } from '@metamask/post-message-stream';\nimport type { SnapRpcHookArgs } from '@metamask/snaps-utils';\nimport { SNAP_STREAM_NAMES, logError, logWarning } from '@metamask/snaps-utils';\nimport type {\n Json,\n JsonRpcNotification,\n JsonRpcRequest,\n} from '@metamask/utils';\nimport {\n Duration,\n assertIsJsonRpcRequest,\n hasProperty,\n inMilliseconds,\n} from '@metamask/utils';\nimport { nanoid } from 'nanoid';\nimport { pipeline } from 'readable-stream';\nimport type { Duplex } from 'readable-stream';\n\nimport type {\n ExecutionService,\n ExecutionServiceMessenger,\n SnapErrorJson,\n SnapExecutionData,\n} from './ExecutionService';\nimport { log } from '../logging';\nimport { Timer } from '../snaps/Timer';\nimport { hasTimedOut, withTimeout } from '../utils';\n\nconst controllerName = 'ExecutionService';\n\nexport type SetupSnapProvider = (snapId: string, stream: Duplex) => void;\n\nexport type ExecutionServiceArgs = {\n setupSnapProvider: SetupSnapProvider;\n messenger: ExecutionServiceMessenger;\n initTimeout?: number;\n pingTimeout?: number;\n terminationTimeout?: number;\n usePing?: boolean;\n};\n\nexport type JobStreams = {\n command: Duplex;\n rpc: Duplex;\n connection: BasePostMessageStream;\n mux: ObjectMultiplex;\n};\n\nexport type Job<WorkerType> = {\n id: string;\n streams: JobStreams;\n rpcEngine: JsonRpcEngine<JsonRpcRequest>;\n worker: WorkerType;\n};\n\nexport type TerminateJobArgs<WorkerType> = Partial<Job<WorkerType>> &\n Pick<Job<WorkerType>, 'id'>;\n\n/** \n Statuses used for diagnostic purposes\n - created: The initial state, no initialization has started \n - initializing: Snap execution environment is initializing\n - initialized: Snap execution environment has initialized\n - executing: Snap source code is being executed\n - running: Snap executed and ready for RPC requests\n */\ntype ExecutionStatus =\n | 'created'\n | 'initializing'\n | 'initialized'\n | 'executing'\n | 'running';\n\nexport abstract class AbstractExecutionService<WorkerType>\n implements ExecutionService\n{\n name: typeof controllerName = controllerName;\n\n state = null;\n\n readonly #jobs: Map<string, Job<WorkerType>>;\n\n readonly #status: Map<string, ExecutionStatus>;\n\n readonly #setupSnapProvider: SetupSnapProvider;\n\n readonly #messenger: ExecutionServiceMessenger;\n\n readonly #initTimeout: number;\n\n readonly #pingTimeout: number;\n\n readonly #terminationTimeout: number;\n\n readonly #usePing: boolean;\n\n constructor({\n setupSnapProvider,\n messenger,\n initTimeout = inMilliseconds(60, Duration.Second),\n pingTimeout = inMilliseconds(10, Duration.Second),\n terminationTimeout = inMilliseconds(1, Duration.Second),\n usePing = true,\n }: ExecutionServiceArgs) {\n this.#jobs = new Map();\n this.#status = new Map();\n this.#setupSnapProvider = setupSnapProvider;\n this.#messenger = messenger;\n this.#initTimeout = initTimeout;\n this.#pingTimeout = pingTimeout;\n this.#terminationTimeout = terminationTimeout;\n this.#usePing = usePing;\n\n this.#registerMessageHandlers();\n }\n\n /**\n * Constructor helper for registering the controller's messaging system\n * actions.\n */\n #registerMessageHandlers(): void {\n this.#messenger.registerActionHandler(\n `${controllerName}:handleRpcRequest`,\n async (snapId: string, options: SnapRpcHookArgs) =>\n this.handleRpcRequest(snapId, options),\n );\n\n this.#messenger.registerActionHandler(\n `${controllerName}:executeSnap`,\n async (data: SnapExecutionData) => this.executeSnap(data),\n );\n\n this.#messenger.registerActionHandler(\n `${controllerName}:terminateSnap`,\n async (snapId: string) => this.terminateSnap(snapId),\n );\n\n this.#messenger.registerActionHandler(\n `${controllerName}:terminateAllSnaps`,\n async () => this.terminateAllSnaps(),\n );\n }\n\n /**\n * Performs additional necessary work during job termination. **MUST** be\n * implemented by concrete implementations. See\n * {@link AbstractExecutionService.terminate} for details.\n *\n * @param job - The object corresponding to the job to be terminated.\n */\n protected abstract terminateJob(\n job: TerminateJobArgs<WorkerType>,\n ): Promise<void>;\n\n /**\n * Terminates the Snap with the specified ID and deletes all its associated\n * data. Any subsequent messages targeting the Snap will fail with an error.\n * Throws an error if termination fails unexpectedly.\n *\n * @param snapId - The id of the Snap to be terminated.\n */\n public async terminateSnap(snapId: string): Promise<void> {\n const job = this.#jobs.get(snapId);\n if (!job) {\n return;\n }\n\n try {\n // Ping worker and tell it to run teardown, continue with termination if it takes too long\n const result = await withTimeout(\n this.#command(snapId, {\n jsonrpc: '2.0',\n method: 'terminate',\n id: nanoid(),\n }),\n this.#terminationTimeout,\n );\n\n if (result === hasTimedOut || result !== 'OK') {\n logWarning(`Snap \"${snapId}\" failed to terminate gracefully.`);\n }\n } catch {\n // Ignore\n }\n\n Object.values(job.streams).forEach((stream) => {\n try {\n if (!stream.destroyed) {\n stream.destroy();\n }\n } catch (error) {\n logError('Error while destroying stream', error);\n }\n });\n\n await this.terminateJob(job);\n\n this.#jobs.delete(snapId);\n this.#status.delete(snapId);\n log(`Snap \"${snapId}\" terminated.`);\n }\n\n /**\n * Initiates a job for a Snap.\n *\n * @param snapId - The ID of the Snap to initiate a job for.\n * @param timer - The timer to use for timeouts.\n * @returns Information regarding the created job.\n * @throws If the execution service returns an error or execution times out.\n */\n async #initJob(snapId: string, timer: Timer): Promise<Job<WorkerType>> {\n const { streams, worker } = await this.#initStreams(snapId, timer);\n\n const jsonRpcConnection = createStreamMiddleware();\n\n pipeline(\n jsonRpcConnection.stream,\n streams.command,\n jsonRpcConnection.stream,\n (error) => {\n if (error && !error.message?.match('Premature close')) {\n logError(`Command stream failure.`, error);\n }\n },\n );\n\n const rpcEngine = JsonRpcEngine.create({\n middleware: [asV2Middleware(jsonRpcConnection.middleware)],\n });\n\n const envMetadata = {\n id: snapId,\n streams,\n rpcEngine,\n worker,\n };\n this.#jobs.set(snapId, envMetadata);\n\n return envMetadata;\n }\n\n /**\n * Sets up the streams for an initiated job.\n *\n * @param snapId - The Snap ID.\n * @param timer - The timer to use for timeouts.\n * @returns The streams to communicate with the worker and the worker itself.\n * @throws If the execution service returns an error or execution times out.\n */\n async #initStreams(\n snapId: string,\n timer: Timer,\n ): Promise<{ streams: JobStreams; worker: WorkerType }> {\n const result = await withTimeout(this.initEnvStream(snapId), timer);\n\n if (result === hasTimedOut) {\n // For certain environments, such as the iframe we may have already created the worker and wish to terminate it.\n await this.terminateJob({ id: snapId });\n\n const status = this.#status.get(snapId);\n if (status === 'created') {\n // Currently this error can only be thrown by OffscreenExecutionService.\n throw new Error(\n `The executor for \"${snapId}\" couldn't start initialization. The offscreen document may not exist.`,\n );\n }\n throw new Error(\n `The executor for \"${snapId}\" failed to initialize. The iframe/webview/worker failed to load.`,\n );\n }\n\n const { worker, stream: envStream } = result;\n const mux = setupMultiplex(envStream, `Snap: \"${snapId}\"`);\n const commandStream = mux.createStream(SNAP_STREAM_NAMES.COMMAND);\n\n // Handle out-of-band errors, i.e. errors thrown from the Snap outside of the req/res cycle.\n // Also keep track of outbound request/responses\n const notificationHandler = (\n message:\n | JsonRpcRequest\n | JsonRpcNotification<Json[] | Record<string, Json>>,\n ) => {\n if (hasProperty(message, 'id')) {\n return;\n }\n\n if (message.method === 'OutboundRequest') {\n this.#messenger.publish('ExecutionService:outboundRequest', snapId);\n } else if (message.method === 'OutboundResponse') {\n this.#messenger.publish('ExecutionService:outboundResponse', snapId);\n } else if (message.method === 'UnhandledError') {\n this.#messenger.publish(\n 'ExecutionService:unhandledError',\n snapId,\n (message.params as { error: SnapErrorJson }).error,\n );\n commandStream.removeListener('data', notificationHandler);\n } else {\n logError(\n new Error(\n `Received unexpected command stream notification \"${message.method}\".`,\n ),\n );\n }\n };\n\n commandStream.on('data', notificationHandler);\n\n const rpcStream = mux\n .createStream(SNAP_STREAM_NAMES.JSON_RPC)\n .setMaxListeners(20);\n\n rpcStream.on('data', (chunk) => {\n if (chunk?.data && hasProperty(chunk?.data, 'id')) {\n this.#messenger.publish('ExecutionService:outboundRequest', snapId);\n }\n });\n\n const originalWrite = rpcStream.write.bind(rpcStream);\n\n // @ts-expect-error Hack to inspect the messages being written to the stream.\n rpcStream.write = (chunk, encoding, callback) => {\n // Ignore chain switching notifications as it doesn't matter for the SnapProvider.\n if (chunk?.data?.method === 'metamask_chainChanged') {\n return true;\n }\n\n if (chunk?.data && hasProperty(chunk?.data, 'id')) {\n this.#messenger.publish('ExecutionService:outboundResponse', snapId);\n }\n\n return originalWrite(chunk, encoding, callback);\n };\n\n return {\n streams: {\n command: commandStream,\n rpc: rpcStream,\n connection: envStream,\n mux,\n },\n worker,\n };\n }\n\n /**\n * Abstract function implemented by implementing class that spins up a new worker for a job.\n *\n * Depending on the execution environment, this may run forever if the Snap fails to start up properly, therefore any call to this function should be wrapped in a timeout.\n */\n protected abstract initEnvStream(snapId: string): Promise<{\n worker: WorkerType;\n stream: BasePostMessageStream;\n }>;\n\n /**\n * Set the execution status of the Snap.\n *\n * @param snapId - The Snap ID.\n * @param status - The current execution status.\n */\n protected setSnapStatus(snapId: string, status: ExecutionStatus) {\n this.#status.set(snapId, status);\n }\n\n async terminateAllSnaps() {\n await Promise.all(\n [...this.#jobs.keys()].map(async (snapId) => this.terminateSnap(snapId)),\n );\n }\n\n /**\n * Initializes and executes a Snap, setting up the communication channels to the Snap etc.\n *\n * @param snapData - Data needed for Snap execution.\n * @param snapData.snapId - The ID of the Snap to execute.\n * @param snapData.sourceCode - The source code of the Snap to execute.\n * @param snapData.endowments - The endowments available to the executing Snap.\n * @returns A string `OK` if execution succeeded.\n * @throws If the execution service returns an error or execution times out.\n */\n async executeSnap({\n snapId,\n sourceCode,\n endowments,\n }: SnapExecutionData): Promise<string> {\n if (this.#jobs.has(snapId)) {\n throw new Error(`\"${snapId}\" is already running.`);\n }\n\n this.setSnapStatus(snapId, 'created');\n\n const timer = new Timer(this.#initTimeout);\n\n // This may resolve even if the environment has failed to start up fully\n const job = await this.#initJob(snapId, timer);\n\n // Certain environments use ping as part of their initialization and thus can skip it here\n if (this.#usePing) {\n // Ping the worker to ensure that it started up\n const pingResult = await withTimeout(\n this.#command(job.id, {\n jsonrpc: '2.0',\n method: 'ping',\n id: nanoid(),\n }),\n this.#pingTimeout,\n );\n\n if (pingResult === hasTimedOut) {\n throw new Error(\n `The executor for \"${snapId}\" was unreachable. The executor did not respond in time.`,\n );\n }\n }\n\n const rpcStream = job.streams.rpc;\n\n this.#setupSnapProvider(snapId, rpcStream);\n\n // Use the remaining time as the timer, but ensure that the\n // Snap gets at least half the init timeout.\n const remainingTime = Math.max(timer.remaining, this.#initTimeout / 2);\n\n this.setSnapStatus(snapId, 'initialized');\n\n const request = {\n jsonrpc: '2.0',\n method: 'executeSnap',\n params: { snapId, sourceCode, endowments },\n id: nanoid(),\n };\n\n assertIsJsonRpcRequest(request);\n\n this.setSnapStatus(snapId, 'executing');\n\n const result = await withTimeout(\n this.#command(job.id, request),\n remainingTime,\n );\n\n if (result === hasTimedOut) {\n throw new Error(`${snapId} failed to start.`);\n }\n\n if (result === 'OK') {\n this.setSnapStatus(snapId, 'running');\n }\n\n return result as string;\n }\n\n async #command(\n snapId: string,\n message: JsonRpcRequest,\n ): Promise<Json | undefined> {\n const job = this.#jobs.get(snapId);\n if (!job) {\n throw new Error(`\"${snapId}\" is not currently running.`);\n }\n\n log('Parent: Sending Command', message);\n return await job.rpcEngine.handle(message);\n }\n\n /**\n * Handle RPC request.\n *\n * @param snapId - The ID of the recipient Snap.\n * @param options - Bag of options to pass to the RPC handler.\n * @returns Promise that can handle the request.\n */\n public async handleRpcRequest(\n snapId: string,\n options: SnapRpcHookArgs,\n ): Promise<unknown> {\n const { handler, request, origin } = options;\n\n return await this.#command(snapId, {\n id: nanoid(),\n jsonrpc: '2.0',\n method: 'snapRpc',\n params: {\n snapId,\n origin,\n handler,\n request: request as JsonRpcRequest,\n },\n });\n }\n}\n\n/**\n * Sets up stream multiplexing for the given stream.\n *\n * @param connectionStream - The stream to mux.\n * @param streamName - The name of the stream, for identification in errors.\n * @returns The multiplexed stream.\n */\nexport function setupMultiplex(\n connectionStream: Duplex,\n streamName: string,\n): ObjectMultiplex {\n const mux = new ObjectMultiplex();\n pipeline(connectionStream, mux, connectionStream, (error) => {\n if (error && !error.message?.match('Premature close')) {\n logError(`\"${streamName}\" stream failure.`, error);\n }\n });\n return mux;\n}\n"]}
{"version":3,"file":"AbstractExecutionService.mjs","sourceRoot":"","sources":["../../src/services/AbstractExecutionService.ts"],"names":[],"mappings":";;;;;;AAAA,OAAO,EAAE,cAAc,EAAE,kCAAkC;AAC3D,OAAO,EAAE,eAAe,IAAI,aAAa,EAAE,qCAAqC;AAChF,OAAO,EAAE,sBAAsB,EAAE,6CAA6C;AAC9E,OAAO,gBAAe,mCAAmC;;AAGzD,OAAO,EAAE,iBAAiB,EAAE,QAAQ,EAAE,UAAU,EAAE,8BAA8B;AAMhF,OAAO,EACL,QAAQ,EACR,sBAAsB,EACtB,WAAW,EACX,cAAc,EACf,wBAAwB;AACzB,OAAO,EAAE,MAAM,EAAE,eAAe;AAChC,OAAO,EAAE,QAAQ,EAAE,wBAAwB;AAS3C,OAAO,EAAE,GAAG,EAAE,uBAAmB;AACjC,OAAO,EAAE,KAAK,EAAE,2BAAuB;AACvC,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,qBAAiB;AAEpD,MAAM,cAAc,GAAG,kBAAkB,CAAC;AA6C1C,MAAM,OAAgB,wBAAwB;IAG5C,IAAI,GAA0B,cAAc,CAAC;IAE7C,KAAK,GAAG,IAAI,CAAC;IAEJ,KAAK,CAA+B;IAEpC,OAAO,CAA+B;IAEtC,kBAAkB,CAAoB;IAEtC,UAAU,CAA4B;IAEtC,YAAY,CAAS;IAErB,YAAY,CAAS;IAErB,mBAAmB,CAAS;IAE5B,QAAQ,CAAU;IAE3B,YAAY,EACV,iBAAiB,EACjB,SAAS,EACT,WAAW,GAAG,cAAc,CAAC,EAAE,EAAE,QAAQ,CAAC,MAAM,CAAC,EACjD,WAAW,GAAG,cAAc,CAAC,EAAE,EAAE,QAAQ,CAAC,MAAM,CAAC,EACjD,kBAAkB,GAAG,cAAc,CAAC,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,EACvD,OAAO,GAAG,IAAI,GACO;QACrB,IAAI,CAAC,KAAK,GAAG,IAAI,GAAG,EAAE,CAAC;QACvB,IAAI,CAAC,OAAO,GAAG,IAAI,GAAG,EAAE,CAAC;QACzB,IAAI,CAAC,kBAAkB,GAAG,iBAAiB,CAAC;QAC5C,IAAI,CAAC,UAAU,GAAG,SAAS,CAAC;QAC5B,IAAI,CAAC,YAAY,GAAG,WAAW,CAAC;QAChC,IAAI,CAAC,YAAY,GAAG,WAAW,CAAC;QAChC,IAAI,CAAC,mBAAmB,GAAG,kBAAkB,CAAC;QAC9C,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC;QAExB,IAAI,CAAC,wBAAwB,EAAE,CAAC;IAClC,CAAC;IAED;;;OAGG;IACH,wBAAwB;QACtB,IAAI,CAAC,UAAU,CAAC,qBAAqB,CACnC,GAAG,cAAc,mBAAmB,EACpC,KAAK,EAAE,MAAc,EAAE,OAAwB,EAAE,EAAE,CACjD,IAAI,CAAC,gBAAgB,CAAC,MAAM,EAAE,OAAO,CAAC,CACzC,CAAC;QAEF,IAAI,CAAC,UAAU,CAAC,qBAAqB,CACnC,GAAG,cAAc,cAAc,EAC/B,KAAK,EAAE,IAAuB,EAAE,EAAE,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAC1D,CAAC;QAEF,IAAI,CAAC,UAAU,CAAC,qBAAqB,CACnC,GAAG,cAAc,gBAAgB,EACjC,KAAK,EAAE,MAAc,EAAE,EAAE,CAAC,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,CACrD,CAAC;QAEF,IAAI,CAAC,UAAU,CAAC,qBAAqB,CACnC,GAAG,cAAc,oBAAoB,EACrC,KAAK,IAAI,EAAE,CAAC,IAAI,CAAC,iBAAiB,EAAE,CACrC,CAAC;IACJ,CAAC;IAaD;;;;;;OAMG;IACI,KAAK,CAAC,aAAa,CAAC,MAAc;QACvC,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QACnC,IAAI,CAAC,GAAG,EAAE,CAAC;YACT,OAAO;QACT,CAAC;QAED,IAAI,CAAC;YACH,0FAA0F;YAC1F,MAAM,MAAM,GAAG,MAAM,WAAW,CAC9B,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE;gBACpB,OAAO,EAAE,KAAK;gBACd,MAAM,EAAE,WAAW;gBACnB,EAAE,EAAE,MAAM,EAAE;aACb,CAAC,EACF,IAAI,CAAC,mBAAmB,CACzB,CAAC;YAEF,IAAI,MAAM,KAAK,WAAW,IAAI,MAAM,KAAK,IAAI,EAAE,CAAC;gBAC9C,UAAU,CAAC,SAAS,MAAM,mCAAmC,CAAC,CAAC;YACjE,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,SAAS;QACX,CAAC;QAED,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,EAAE;YAC5C,IAAI,CAAC;gBACH,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC;oBACtB,MAAM,CAAC,OAAO,EAAE,CAAC;gBACnB,CAAC;YACH,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,QAAQ,CAAC,+BAA+B,EAAE,KAAK,CAAC,CAAC;YACnD,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,MAAM,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC;QAE7B,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QAC1B,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QAC5B,GAAG,CAAC,SAAS,MAAM,eAAe,CAAC,CAAC;IACtC,CAAC;IAED;;;;;;;OAOG;IACH,KAAK,CAAC,QAAQ,CAAC,MAAc,EAAE,KAAY;QACzC,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;QAEnE,MAAM,iBAAiB,GAAG,sBAAsB,EAAE,CAAC;QAEnD,QAAQ,CACN,iBAAiB,CAAC,MAAM,EACxB,OAAO,CAAC,OAAO,EACf,iBAAiB,CAAC,MAAM,EACxB,CAAC,KAAK,EAAE,EAAE;YACR,IAAI,KAAK,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,iBAAiB,CAAC,EAAE,CAAC;gBACtD,QAAQ,CAAC,yBAAyB,EAAE,KAAK,CAAC,CAAC;YAC7C,CAAC;QACH,CAAC,CACF,CAAC;QAEF,MAAM,SAAS,GAAG,aAAa,CAAC,MAAM,CAAC;YACrC,UAAU,EAAE,CAAC,cAAc,CAAC,iBAAiB,CAAC,UAAU,CAAC,CAAC;SAC3D,CAAC,CAAC;QAEH,MAAM,WAAW,GAAG;YAClB,EAAE,EAAE,MAAM;YACV,OAAO;YACP,SAAS;YACT,MAAM;SACP,CAAC;QACF,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;QAEpC,OAAO,WAAW,CAAC;IACrB,CAAC;IAED;;;;;;;OAOG;IACH,KAAK,CAAC,YAAY,CAChB,MAAc,EACd,KAAY;QAEZ,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,EAAE,KAAK,CAAC,CAAC;QAEpE,IAAI,MAAM,KAAK,WAAW,EAAE,CAAC;YAC3B,gHAAgH;YAChH,MAAM,IAAI,CAAC,YAAY,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;YAExC,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;YACxC,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;gBACzB,wEAAwE;gBACxE,MAAM,IAAI,KAAK,CACb,qBAAqB,MAAM,wEAAwE,CACpG,CAAC;YACJ,CAAC;YACD,MAAM,IAAI,KAAK,CACb,qBAAqB,MAAM,mEAAmE,CAC/F,CAAC;QACJ,CAAC;QAED,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,GAAG,MAAM,CAAC;QAC7C,MAAM,GAAG,GAAG,cAAc,CAAC,SAAS,EAAE,UAAU,MAAM,GAAG,CAAC,CAAC;QAC3D,MAAM,aAAa,GAAG,GAAG,CAAC,YAAY,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAC;QAElE,4FAA4F;QAC5F,gDAAgD;QAChD,MAAM,mBAAmB,GAAG,CAC1B,OAEsD,EACtD,EAAE;YACF,IAAI,WAAW,CAAC,OAAO,EAAE,IAAI,CAAC,EAAE,CAAC;gBAC/B,OAAO;YACT,CAAC;YAED,IAAI,OAAO,CAAC,MAAM,KAAK,iBAAiB,EAAE,CAAC;gBACzC,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,kCAAkC,EAAE,MAAM,CAAC,CAAC;YACtE,CAAC;iBAAM,IAAI,OAAO,CAAC,MAAM,KAAK,kBAAkB,EAAE,CAAC;gBACjD,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,mCAAmC,EAAE,MAAM,CAAC,CAAC;YACvE,CAAC;iBAAM,IAAI,OAAO,CAAC,MAAM,KAAK,gBAAgB,EAAE,CAAC;gBAC/C,IAAI,CAAC,UAAU,CAAC,OAAO,CACrB,iCAAiC,EACjC,MAAM,EACL,OAAO,CAAC,MAAmC,CAAC,KAAK,CACnD,CAAC;gBACF,aAAa,CAAC,cAAc,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAC;YAC5D,CAAC;iBAAM,CAAC;gBACN,QAAQ,CACN,IAAI,KAAK,CACP,oDAAoD,OAAO,CAAC,MAAM,IAAI,CACvE,CACF,CAAC;YACJ,CAAC;QACH,CAAC,CAAC;QAEF,aAAa,CAAC,EAAE,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAC;QAE9C,MAAM,SAAS,GAAG,GAAG;aAClB,YAAY,CAAC,iBAAiB,CAAC,QAAQ,CAAC;aACxC,eAAe,CAAC,EAAE,CAAC,CAAC;QAEvB,SAAS,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,EAAE;YAC7B,IAAI,KAAK,EAAE,IAAI,IAAI,WAAW,CAAC,KAAK,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,CAAC;gBAClD,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,kCAAkC,EAAE,MAAM,CAAC,CAAC;YACtE,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,0FAA0F;QAC1F,oGAAoG;QACpG,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE;YAC9B,IAAI,KAAK,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,iBAAiB,CAAC,EAAE,CAAC;gBACtD,QAAQ,CAAC,UAAU,MAAM,yBAAyB,EAAE,KAAK,CAAC,CAAC;YAC7D,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,MAAM,aAAa,GAAG,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAEtD,6EAA6E;QAC7E,SAAS,CAAC,KAAK,GAAG,CAAC,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE;YAC9C,kFAAkF;YAClF,IAAI,KAAK,EAAE,IAAI,EAAE,MAAM,KAAK,uBAAuB,EAAE,CAAC;gBACpD,OAAO,IAAI,CAAC;YACd,CAAC;YAED,IAAI,KAAK,EAAE,IAAI,IAAI,WAAW,CAAC,KAAK,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,CAAC;gBAClD,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,mCAAmC,EAAE,MAAM,CAAC,CAAC;YACvE,CAAC;YAED,OAAO,aAAa,CAAC,KAAK,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC;QAClD,CAAC,CAAC;QAEF,OAAO;YACL,OAAO,EAAE;gBACP,OAAO,EAAE,aAAa;gBACtB,GAAG,EAAE,SAAS;gBACd,UAAU,EAAE,SAAS;gBACrB,GAAG;aACJ;YACD,MAAM;SACP,CAAC;IACJ,CAAC;IAYD;;;;;OAKG;IACO,aAAa,CAAC,MAAc,EAAE,MAAuB;QAC7D,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,CAAC;IAED,KAAK,CAAC,iBAAiB;QACrB,MAAM,OAAO,CAAC,GAAG,CACf,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,CAAC,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,CACzE,CAAC;IACJ,CAAC;IAED;;;;;;;;;OASG;IACH,KAAK,CAAC,WAAW,CAAC,EAChB,MAAM,EACN,UAAU,EACV,UAAU,GACQ;QAClB,IAAI,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;YAC3B,MAAM,IAAI,KAAK,CAAC,IAAI,MAAM,uBAAuB,CAAC,CAAC;QACrD,CAAC;QAED,IAAI,CAAC,aAAa,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;QAEtC,MAAM,KAAK,GAAG,IAAI,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QAE3C,wEAAwE;QACxE,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;QAE/C,0FAA0F;QAC1F,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAClB,+CAA+C;YAC/C,MAAM,UAAU,GAAG,MAAM,WAAW,CAClC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,EAAE;gBACpB,OAAO,EAAE,KAAK;gBACd,MAAM,EAAE,MAAM;gBACd,EAAE,EAAE,MAAM,EAAE;aACb,CAAC,EACF,IAAI,CAAC,YAAY,CAClB,CAAC;YAEF,IAAI,UAAU,KAAK,WAAW,EAAE,CAAC;gBAC/B,MAAM,IAAI,KAAK,CACb,qBAAqB,MAAM,0DAA0D,CACtF,CAAC;YACJ,CAAC;QACH,CAAC;QAED,MAAM,SAAS,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC;QAElC,IAAI,CAAC,kBAAkB,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;QAE3C,2DAA2D;QAC3D,4CAA4C;QAC5C,MAAM,aAAa,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,SAAS,EAAE,IAAI,CAAC,YAAY,GAAG,CAAC,CAAC,CAAC;QAEvE,IAAI,CAAC,aAAa,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;QAE1C,MAAM,OAAO,GAAG;YACd,OAAO,EAAE,KAAK;YACd,MAAM,EAAE,aAAa;YACrB,MAAM,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU,EAAE;YAC1C,EAAE,EAAE,MAAM,EAAE;SACb,CAAC;QAEF,sBAAsB,CAAC,OAAO,CAAC,CAAC;QAEhC,IAAI,CAAC,aAAa,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;QAExC,MAAM,MAAM,GAAG,MAAM,WAAW,CAC9B,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,EAAE,OAAO,CAAC,EAC9B,aAAa,CACd,CAAC;QAEF,IAAI,MAAM,KAAK,WAAW,EAAE,CAAC;YAC3B,MAAM,IAAI,KAAK,CAAC,GAAG,MAAM,mBAAmB,CAAC,CAAC;QAChD,CAAC;QAED,IAAI,MAAM,KAAK,IAAI,EAAE,CAAC;YACpB,IAAI,CAAC,aAAa,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;QACxC,CAAC;QAED,OAAO,MAAgB,CAAC;IAC1B,CAAC;IAED,KAAK,CAAC,QAAQ,CACZ,MAAc,EACd,OAAuB;QAEvB,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QACnC,IAAI,CAAC,GAAG,EAAE,CAAC;YACT,MAAM,IAAI,KAAK,CAAC,IAAI,MAAM,6BAA6B,CAAC,CAAC;QAC3D,CAAC;QAED,GAAG,CAAC,yBAAyB,EAAE,OAAO,CAAC,CAAC;QACxC,OAAO,MAAM,GAAG,CAAC,SAAS,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAC7C,CAAC;IAED;;;;;;OAMG;IACI,KAAK,CAAC,gBAAgB,CAC3B,MAAc,EACd,OAAwB;QAExB,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC;QAE7C,OAAO,MAAM,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE;YACjC,EAAE,EAAE,MAAM,EAAE;YACZ,OAAO,EAAE,KAAK;YACd,MAAM,EAAE,SAAS;YACjB,MAAM,EAAE;gBACN,MAAM;gBACN,MAAM;gBACN,OAAO;gBACP,OAAO,EAAE,OAAyB;aACnC;SACF,CAAC,CAAC;IACL,CAAC;CACF;AAED;;;;;;GAMG;AACH,MAAM,UAAU,cAAc,CAC5B,gBAAwB,EACxB,UAAkB;IAElB,MAAM,GAAG,GAAG,IAAI,eAAe,EAAE,CAAC;IAClC,QAAQ,CAAC,gBAAgB,EAAE,GAAG,EAAE,gBAAgB,EAAE,CAAC,KAAK,EAAE,EAAE;QAC1D,IAAI,KAAK,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,iBAAiB,CAAC,EAAE,CAAC;YACtD,QAAQ,CAAC,IAAI,UAAU,mBAAmB,EAAE,KAAK,CAAC,CAAC;QACrD,CAAC;IACH,CAAC,CAAC,CAAC;IACH,OAAO,GAAG,CAAC;AACb,CAAC","sourcesContent":["import { asV2Middleware } from '@metamask/json-rpc-engine';\nimport { JsonRpcEngineV2 as JsonRpcEngine } from '@metamask/json-rpc-engine/v2';\nimport { createStreamMiddleware } from '@metamask/json-rpc-middleware-stream';\nimport ObjectMultiplex from '@metamask/object-multiplex';\nimport type { BasePostMessageStream } from '@metamask/post-message-stream';\nimport type { SnapRpcHookArgs } from '@metamask/snaps-utils';\nimport { SNAP_STREAM_NAMES, logError, logWarning } from '@metamask/snaps-utils';\nimport type {\n Json,\n JsonRpcNotification,\n JsonRpcRequest,\n} from '@metamask/utils';\nimport {\n Duration,\n assertIsJsonRpcRequest,\n hasProperty,\n inMilliseconds,\n} from '@metamask/utils';\nimport { nanoid } from 'nanoid';\nimport { pipeline } from 'readable-stream';\nimport type { Duplex } from 'readable-stream';\n\nimport type {\n ExecutionService,\n ExecutionServiceMessenger,\n SnapErrorJson,\n SnapExecutionData,\n} from './ExecutionService';\nimport { log } from '../logging';\nimport { Timer } from '../snaps/Timer';\nimport { hasTimedOut, withTimeout } from '../utils';\n\nconst controllerName = 'ExecutionService';\n\nexport type SetupSnapProvider = (snapId: string, stream: Duplex) => void;\n\nexport type ExecutionServiceArgs = {\n setupSnapProvider: SetupSnapProvider;\n messenger: ExecutionServiceMessenger;\n initTimeout?: number;\n pingTimeout?: number;\n terminationTimeout?: number;\n usePing?: boolean;\n};\n\nexport type JobStreams = {\n command: Duplex;\n rpc: Duplex;\n connection: BasePostMessageStream;\n mux: ObjectMultiplex;\n};\n\nexport type Job<WorkerType> = {\n id: string;\n streams: JobStreams;\n rpcEngine: JsonRpcEngine<JsonRpcRequest>;\n worker: WorkerType;\n};\n\nexport type TerminateJobArgs<WorkerType> = Partial<Job<WorkerType>> &\n Pick<Job<WorkerType>, 'id'>;\n\n/** \n Statuses used for diagnostic purposes\n - created: The initial state, no initialization has started \n - initializing: Snap execution environment is initializing\n - initialized: Snap execution environment has initialized\n - executing: Snap source code is being executed\n - running: Snap executed and ready for RPC requests\n */\ntype ExecutionStatus =\n | 'created'\n | 'initializing'\n | 'initialized'\n | 'executing'\n | 'running';\n\nexport abstract class AbstractExecutionService<WorkerType>\n implements ExecutionService\n{\n name: typeof controllerName = controllerName;\n\n state = null;\n\n readonly #jobs: Map<string, Job<WorkerType>>;\n\n readonly #status: Map<string, ExecutionStatus>;\n\n readonly #setupSnapProvider: SetupSnapProvider;\n\n readonly #messenger: ExecutionServiceMessenger;\n\n readonly #initTimeout: number;\n\n readonly #pingTimeout: number;\n\n readonly #terminationTimeout: number;\n\n readonly #usePing: boolean;\n\n constructor({\n setupSnapProvider,\n messenger,\n initTimeout = inMilliseconds(60, Duration.Second),\n pingTimeout = inMilliseconds(10, Duration.Second),\n terminationTimeout = inMilliseconds(1, Duration.Second),\n usePing = true,\n }: ExecutionServiceArgs) {\n this.#jobs = new Map();\n this.#status = new Map();\n this.#setupSnapProvider = setupSnapProvider;\n this.#messenger = messenger;\n this.#initTimeout = initTimeout;\n this.#pingTimeout = pingTimeout;\n this.#terminationTimeout = terminationTimeout;\n this.#usePing = usePing;\n\n this.#registerMessageHandlers();\n }\n\n /**\n * Constructor helper for registering the controller's messaging system\n * actions.\n */\n #registerMessageHandlers(): void {\n this.#messenger.registerActionHandler(\n `${controllerName}:handleRpcRequest`,\n async (snapId: string, options: SnapRpcHookArgs) =>\n this.handleRpcRequest(snapId, options),\n );\n\n this.#messenger.registerActionHandler(\n `${controllerName}:executeSnap`,\n async (data: SnapExecutionData) => this.executeSnap(data),\n );\n\n this.#messenger.registerActionHandler(\n `${controllerName}:terminateSnap`,\n async (snapId: string) => this.terminateSnap(snapId),\n );\n\n this.#messenger.registerActionHandler(\n `${controllerName}:terminateAllSnaps`,\n async () => this.terminateAllSnaps(),\n );\n }\n\n /**\n * Performs additional necessary work during job termination. **MUST** be\n * implemented by concrete implementations. See\n * {@link AbstractExecutionService.terminate} for details.\n *\n * @param job - The object corresponding to the job to be terminated.\n */\n protected abstract terminateJob(\n job: TerminateJobArgs<WorkerType>,\n ): Promise<void>;\n\n /**\n * Terminates the Snap with the specified ID and deletes all its associated\n * data. Any subsequent messages targeting the Snap will fail with an error.\n * Throws an error if termination fails unexpectedly.\n *\n * @param snapId - The id of the Snap to be terminated.\n */\n public async terminateSnap(snapId: string): Promise<void> {\n const job = this.#jobs.get(snapId);\n if (!job) {\n return;\n }\n\n try {\n // Ping worker and tell it to run teardown, continue with termination if it takes too long\n const result = await withTimeout(\n this.#command(snapId, {\n jsonrpc: '2.0',\n method: 'terminate',\n id: nanoid(),\n }),\n this.#terminationTimeout,\n );\n\n if (result === hasTimedOut || result !== 'OK') {\n logWarning(`Snap \"${snapId}\" failed to terminate gracefully.`);\n }\n } catch {\n // Ignore\n }\n\n Object.values(job.streams).forEach((stream) => {\n try {\n if (!stream.destroyed) {\n stream.destroy();\n }\n } catch (error) {\n logError('Error while destroying stream', error);\n }\n });\n\n await this.terminateJob(job);\n\n this.#jobs.delete(snapId);\n this.#status.delete(snapId);\n log(`Snap \"${snapId}\" terminated.`);\n }\n\n /**\n * Initiates a job for a Snap.\n *\n * @param snapId - The ID of the Snap to initiate a job for.\n * @param timer - The timer to use for timeouts.\n * @returns Information regarding the created job.\n * @throws If the execution service returns an error or execution times out.\n */\n async #initJob(snapId: string, timer: Timer): Promise<Job<WorkerType>> {\n const { streams, worker } = await this.#initStreams(snapId, timer);\n\n const jsonRpcConnection = createStreamMiddleware();\n\n pipeline(\n jsonRpcConnection.stream,\n streams.command,\n jsonRpcConnection.stream,\n (error) => {\n if (error && !error.message?.match('Premature close')) {\n logError(`Command stream failure.`, error);\n }\n },\n );\n\n const rpcEngine = JsonRpcEngine.create({\n middleware: [asV2Middleware(jsonRpcConnection.middleware)],\n });\n\n const envMetadata = {\n id: snapId,\n streams,\n rpcEngine,\n worker,\n };\n this.#jobs.set(snapId, envMetadata);\n\n return envMetadata;\n }\n\n /**\n * Sets up the streams for an initiated job.\n *\n * @param snapId - The Snap ID.\n * @param timer - The timer to use for timeouts.\n * @returns The streams to communicate with the worker and the worker itself.\n * @throws If the execution service returns an error or execution times out.\n */\n async #initStreams(\n snapId: string,\n timer: Timer,\n ): Promise<{ streams: JobStreams; worker: WorkerType }> {\n const result = await withTimeout(this.initEnvStream(snapId), timer);\n\n if (result === hasTimedOut) {\n // For certain environments, such as the iframe we may have already created the worker and wish to terminate it.\n await this.terminateJob({ id: snapId });\n\n const status = this.#status.get(snapId);\n if (status === 'created') {\n // Currently this error can only be thrown by OffscreenExecutionService.\n throw new Error(\n `The executor for \"${snapId}\" couldn't start initialization. The offscreen document may not exist.`,\n );\n }\n throw new Error(\n `The executor for \"${snapId}\" failed to initialize. The iframe/webview/worker failed to load.`,\n );\n }\n\n const { worker, stream: envStream } = result;\n const mux = setupMultiplex(envStream, `Snap: \"${snapId}\"`);\n const commandStream = mux.createStream(SNAP_STREAM_NAMES.COMMAND);\n\n // Handle out-of-band errors, i.e. errors thrown from the Snap outside of the req/res cycle.\n // Also keep track of outbound request/responses\n const notificationHandler = (\n message:\n | JsonRpcRequest\n | JsonRpcNotification<Json[] | Record<string, Json>>,\n ) => {\n if (hasProperty(message, 'id')) {\n return;\n }\n\n if (message.method === 'OutboundRequest') {\n this.#messenger.publish('ExecutionService:outboundRequest', snapId);\n } else if (message.method === 'OutboundResponse') {\n this.#messenger.publish('ExecutionService:outboundResponse', snapId);\n } else if (message.method === 'UnhandledError') {\n this.#messenger.publish(\n 'ExecutionService:unhandledError',\n snapId,\n (message.params as { error: SnapErrorJson }).error,\n );\n commandStream.removeListener('data', notificationHandler);\n } else {\n logError(\n new Error(\n `Received unexpected command stream notification \"${message.method}\".`,\n ),\n );\n }\n };\n\n commandStream.on('data', notificationHandler);\n\n const rpcStream = mux\n .createStream(SNAP_STREAM_NAMES.JSON_RPC)\n .setMaxListeners(20);\n\n rpcStream.on('data', (chunk) => {\n if (chunk?.data && hasProperty(chunk?.data, 'id')) {\n this.#messenger.publish('ExecutionService:outboundRequest', snapId);\n }\n });\n\n // An error handler is not attached to the RPC stream until `setupSnapProvider` is called.\n // We must set it up here to prevent errors from bubbling up if the stream is destroyed before then.\n rpcStream.on('error', (error) => {\n if (error && !error.message?.match('Premature close')) {\n logError(`Snap: \"${snapId}\" - RPC stream failure:`, error);\n }\n });\n\n const originalWrite = rpcStream.write.bind(rpcStream);\n\n // @ts-expect-error Hack to inspect the messages being written to the stream.\n rpcStream.write = (chunk, encoding, callback) => {\n // Ignore chain switching notifications as it doesn't matter for the SnapProvider.\n if (chunk?.data?.method === 'metamask_chainChanged') {\n return true;\n }\n\n if (chunk?.data && hasProperty(chunk?.data, 'id')) {\n this.#messenger.publish('ExecutionService:outboundResponse', snapId);\n }\n\n return originalWrite(chunk, encoding, callback);\n };\n\n return {\n streams: {\n command: commandStream,\n rpc: rpcStream,\n connection: envStream,\n mux,\n },\n worker,\n };\n }\n\n /**\n * Abstract function implemented by implementing class that spins up a new worker for a job.\n *\n * Depending on the execution environment, this may run forever if the Snap fails to start up properly, therefore any call to this function should be wrapped in a timeout.\n */\n protected abstract initEnvStream(snapId: string): Promise<{\n worker: WorkerType;\n stream: BasePostMessageStream;\n }>;\n\n /**\n * Set the execution status of the Snap.\n *\n * @param snapId - The Snap ID.\n * @param status - The current execution status.\n */\n protected setSnapStatus(snapId: string, status: ExecutionStatus) {\n this.#status.set(snapId, status);\n }\n\n async terminateAllSnaps() {\n await Promise.all(\n [...this.#jobs.keys()].map(async (snapId) => this.terminateSnap(snapId)),\n );\n }\n\n /**\n * Initializes and executes a Snap, setting up the communication channels to the Snap etc.\n *\n * @param snapData - Data needed for Snap execution.\n * @param snapData.snapId - The ID of the Snap to execute.\n * @param snapData.sourceCode - The source code of the Snap to execute.\n * @param snapData.endowments - The endowments available to the executing Snap.\n * @returns A string `OK` if execution succeeded.\n * @throws If the execution service returns an error or execution times out.\n */\n async executeSnap({\n snapId,\n sourceCode,\n endowments,\n }: SnapExecutionData): Promise<string> {\n if (this.#jobs.has(snapId)) {\n throw new Error(`\"${snapId}\" is already running.`);\n }\n\n this.setSnapStatus(snapId, 'created');\n\n const timer = new Timer(this.#initTimeout);\n\n // This may resolve even if the environment has failed to start up fully\n const job = await this.#initJob(snapId, timer);\n\n // Certain environments use ping as part of their initialization and thus can skip it here\n if (this.#usePing) {\n // Ping the worker to ensure that it started up\n const pingResult = await withTimeout(\n this.#command(job.id, {\n jsonrpc: '2.0',\n method: 'ping',\n id: nanoid(),\n }),\n this.#pingTimeout,\n );\n\n if (pingResult === hasTimedOut) {\n throw new Error(\n `The executor for \"${snapId}\" was unreachable. The executor did not respond in time.`,\n );\n }\n }\n\n const rpcStream = job.streams.rpc;\n\n this.#setupSnapProvider(snapId, rpcStream);\n\n // Use the remaining time as the timer, but ensure that the\n // Snap gets at least half the init timeout.\n const remainingTime = Math.max(timer.remaining, this.#initTimeout / 2);\n\n this.setSnapStatus(snapId, 'initialized');\n\n const request = {\n jsonrpc: '2.0',\n method: 'executeSnap',\n params: { snapId, sourceCode, endowments },\n id: nanoid(),\n };\n\n assertIsJsonRpcRequest(request);\n\n this.setSnapStatus(snapId, 'executing');\n\n const result = await withTimeout(\n this.#command(job.id, request),\n remainingTime,\n );\n\n if (result === hasTimedOut) {\n throw new Error(`${snapId} failed to start.`);\n }\n\n if (result === 'OK') {\n this.setSnapStatus(snapId, 'running');\n }\n\n return result as string;\n }\n\n async #command(\n snapId: string,\n message: JsonRpcRequest,\n ): Promise<Json | undefined> {\n const job = this.#jobs.get(snapId);\n if (!job) {\n throw new Error(`\"${snapId}\" is not currently running.`);\n }\n\n log('Parent: Sending Command', message);\n return await job.rpcEngine.handle(message);\n }\n\n /**\n * Handle RPC request.\n *\n * @param snapId - The ID of the recipient Snap.\n * @param options - Bag of options to pass to the RPC handler.\n * @returns Promise that can handle the request.\n */\n public async handleRpcRequest(\n snapId: string,\n options: SnapRpcHookArgs,\n ): Promise<unknown> {\n const { handler, request, origin } = options;\n\n return await this.#command(snapId, {\n id: nanoid(),\n jsonrpc: '2.0',\n method: 'snapRpc',\n params: {\n snapId,\n origin,\n handler,\n request: request as JsonRpcRequest,\n },\n });\n }\n}\n\n/**\n * Sets up stream multiplexing for the given stream.\n *\n * @param connectionStream - The stream to mux.\n * @param streamName - The name of the stream, for identification in errors.\n * @returns The multiplexed stream.\n */\nexport function setupMultiplex(\n connectionStream: Duplex,\n streamName: string,\n): ObjectMultiplex {\n const mux = new ObjectMultiplex();\n pipeline(connectionStream, mux, connectionStream, (error) => {\n if (error && !error.message?.match('Premature close')) {\n logError(`\"${streamName}\" stream failure.`, error);\n }\n });\n return mux;\n}\n"]}
{
"name": "@metamask/snaps-controllers",
"version": "18.0.3",
"version": "18.0.4",
"description": "Controllers for MetaMask Snaps",

@@ -5,0 +5,0 @@ "keywords": [