@metamask/snaps-controllers 7.0.1 → 8.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (153) hide show
  1. package/CHANGELOG.md +26 -1
  2. package/dist/{chunk-Q2ON6SMV.js → chunk-2UAU42DO.js} +17 -25
  3. package/dist/chunk-2UAU42DO.js.map +1 -0
  4. package/dist/{chunk-Y5KX5ICF.mjs → chunk-3Y4IJKZY.mjs} +3 -3
  5. package/dist/chunk-3Y4IJKZY.mjs.map +1 -0
  6. package/dist/{chunk-XE5IWVNV.js → chunk-4DPX4O3T.js} +17 -6
  7. package/dist/chunk-4DPX4O3T.js.map +1 -0
  8. package/dist/{chunk-YVNRYLOC.js → chunk-74GN6MIJ.js} +3 -3
  9. package/dist/{chunk-NOLPMHXS.js → chunk-BOFPNIRX.js} +21 -3
  10. package/dist/chunk-BOFPNIRX.js.map +1 -0
  11. package/dist/{chunk-3ZC4LB7T.js → chunk-E5RRFMGF.js} +3 -3
  12. package/dist/chunk-E5RRFMGF.js.map +1 -0
  13. package/dist/{chunk-WVGK5B5P.mjs → chunk-FCCGRGQS.mjs} +83 -48
  14. package/dist/chunk-FCCGRGQS.mjs.map +1 -0
  15. package/dist/{chunk-NSLYI2LS.js → chunk-FCRPOA4I.js} +12 -4
  16. package/dist/chunk-FCRPOA4I.js.map +1 -0
  17. package/dist/{chunk-63GNCRER.js → chunk-G4S6UXQ2.js} +4 -4
  18. package/dist/chunk-G4S6UXQ2.js.map +1 -0
  19. package/dist/{chunk-MYWDTEX2.js → chunk-GRBWVPLF.js} +4 -4
  20. package/dist/{chunk-36YC4Z3T.mjs → chunk-GTDDODNP.mjs} +13 -2
  21. package/dist/chunk-GTDDODNP.mjs.map +1 -0
  22. package/dist/{chunk-5MVIYRYL.mjs → chunk-IPYO7FKR.mjs} +40 -26
  23. package/dist/chunk-IPYO7FKR.mjs.map +1 -0
  24. package/dist/{chunk-75VM3O4K.mjs → chunk-P5MRZOGW.mjs} +2 -2
  25. package/dist/{chunk-Z6SOB3SY.js → chunk-PAFO2KIN.js} +3 -3
  26. package/dist/chunk-PAFO2KIN.js.map +1 -0
  27. package/dist/{chunk-25LS4KZK.mjs → chunk-PXKCSAT6.mjs} +3 -3
  28. package/dist/chunk-PXKCSAT6.mjs.map +1 -0
  29. package/dist/{chunk-BJOQRBH2.mjs → chunk-QLEQIXCE.mjs} +2 -2
  30. package/dist/chunk-QLEQIXCE.mjs.map +1 -0
  31. package/dist/{chunk-K276CM3B.mjs → chunk-QP5LV734.mjs} +20 -28
  32. package/dist/chunk-QP5LV734.mjs.map +1 -0
  33. package/dist/{chunk-SCERVW3B.mjs → chunk-RS3WN6D3.mjs} +2 -2
  34. package/dist/chunk-RS3WN6D3.mjs.map +1 -0
  35. package/dist/{chunk-54TYYPAN.js → chunk-SIW7ZXQF.js} +83 -48
  36. package/dist/chunk-SIW7ZXQF.js.map +1 -0
  37. package/dist/{chunk-Q4I5QTVC.mjs → chunk-TO6ZEBIA.mjs} +11 -3
  38. package/dist/chunk-TO6ZEBIA.mjs.map +1 -0
  39. package/dist/chunk-U4DZUKNN.js +80 -0
  40. package/dist/chunk-U4DZUKNN.js.map +1 -0
  41. package/dist/{chunk-2KCUVQFS.mjs → chunk-X5MFC3VX.mjs} +2 -2
  42. package/dist/{chunk-VOZOZKRC.mjs → chunk-XO7KDFBY.mjs} +21 -3
  43. package/dist/chunk-XO7KDFBY.mjs.map +1 -0
  44. package/dist/{chunk-ZETJVFUS.mjs → chunk-XSFI32LB.mjs} +2 -2
  45. package/dist/{chunk-WQYMF7QP.js → chunk-Y7ZOSPEN.js} +3 -3
  46. package/dist/{chunk-CJN25EXL.js → chunk-YP37KUG5.js} +46 -32
  47. package/dist/chunk-YP37KUG5.js.map +1 -0
  48. package/dist/chunk-ZQNBP53T.mjs +80 -0
  49. package/dist/chunk-ZQNBP53T.mjs.map +1 -0
  50. package/dist/{chunk-N7WIJNHY.js → chunk-ZVGZG25U.js} +4 -4
  51. package/dist/chunk-ZVGZG25U.js.map +1 -0
  52. package/dist/cronjob/CronjobController.js +12 -12
  53. package/dist/cronjob/CronjobController.mjs +11 -11
  54. package/dist/cronjob/index.js +12 -12
  55. package/dist/cronjob/index.mjs +11 -11
  56. package/dist/index.js +14 -12
  57. package/dist/index.mjs +13 -11
  58. package/dist/interface/SnapInterfaceController.js +3 -3
  59. package/dist/interface/SnapInterfaceController.mjs +2 -2
  60. package/dist/interface/index.js +3 -3
  61. package/dist/interface/index.mjs +2 -2
  62. package/dist/interface/utils.js +2 -4
  63. package/dist/interface/utils.mjs +5 -7
  64. package/dist/node.js +16 -14
  65. package/dist/node.mjs +15 -13
  66. package/dist/react-native.js +15 -13
  67. package/dist/react-native.mjs +14 -12
  68. package/dist/services/AbstractExecutionService.js +4 -4
  69. package/dist/services/AbstractExecutionService.mjs +3 -3
  70. package/dist/services/browser.js +9 -9
  71. package/dist/services/browser.mjs +8 -8
  72. package/dist/services/iframe/IframeExecutionService.js +5 -5
  73. package/dist/services/iframe/IframeExecutionService.mjs +4 -4
  74. package/dist/services/iframe/index.js +5 -5
  75. package/dist/services/iframe/index.mjs +4 -4
  76. package/dist/services/index.js +8 -8
  77. package/dist/services/index.mjs +7 -7
  78. package/dist/services/node-js/NodeProcessExecutionService.js +9 -9
  79. package/dist/services/node-js/NodeProcessExecutionService.mjs +8 -8
  80. package/dist/services/node-js/NodeThreadExecutionService.js +9 -9
  81. package/dist/services/node-js/NodeThreadExecutionService.mjs +8 -8
  82. package/dist/services/node-js/index.js +10 -10
  83. package/dist/services/node-js/index.mjs +9 -9
  84. package/dist/services/node.js +10 -10
  85. package/dist/services/node.mjs +9 -9
  86. package/dist/services/offscreen/OffscreenExecutionService.js +6 -6
  87. package/dist/services/offscreen/OffscreenExecutionService.mjs +5 -5
  88. package/dist/services/offscreen/index.js +6 -6
  89. package/dist/services/offscreen/index.mjs +5 -5
  90. package/dist/services/proxy/ProxyExecutionService.js +5 -5
  91. package/dist/services/proxy/ProxyExecutionService.mjs +4 -4
  92. package/dist/services/react-native.js +9 -9
  93. package/dist/services/react-native.mjs +8 -8
  94. package/dist/services/webview/WebViewExecutionService.js +6 -6
  95. package/dist/services/webview/WebViewExecutionService.mjs +5 -5
  96. package/dist/services/webview/index.js +6 -6
  97. package/dist/services/webview/index.mjs +5 -5
  98. package/dist/services/webworker/WebWorkerExecutionService.js +5 -5
  99. package/dist/services/webworker/WebWorkerExecutionService.mjs +4 -4
  100. package/dist/services/webworker/index.js +5 -5
  101. package/dist/services/webworker/index.mjs +4 -4
  102. package/dist/snaps/SnapController.js +4 -4
  103. package/dist/snaps/SnapController.mjs +3 -3
  104. package/dist/snaps/Timer.js +2 -2
  105. package/dist/snaps/Timer.mjs +1 -1
  106. package/dist/snaps/index.js +4 -4
  107. package/dist/snaps/index.mjs +3 -3
  108. package/dist/tsconfig.build.tsbuildinfo +1 -1
  109. package/dist/types/interface/SnapInterfaceController.d.ts +5 -4
  110. package/dist/types/interface/utils.d.ts +11 -20
  111. package/dist/types/services/AbstractExecutionService.d.ts +18 -12
  112. package/dist/types/services/ExecutionService.d.ts +1 -1
  113. package/dist/types/services/iframe/IframeExecutionService.d.ts +2 -2
  114. package/dist/types/services/node-js/NodeProcessExecutionService.d.ts +2 -2
  115. package/dist/types/services/node-js/NodeThreadExecutionService.d.ts +2 -2
  116. package/dist/types/services/proxy/ProxyExecutionService.d.ts +2 -2
  117. package/dist/types/services/webworker/WebWorkerExecutionService.d.ts +2 -2
  118. package/dist/types/snaps/SnapController.d.ts +5 -6
  119. package/dist/types/snaps/Timer.d.ts +7 -0
  120. package/dist/types/utils.d.ts +12 -0
  121. package/dist/utils.js +5 -3
  122. package/dist/utils.mjs +4 -2
  123. package/package.json +8 -7
  124. package/dist/chunk-25LS4KZK.mjs.map +0 -1
  125. package/dist/chunk-36YC4Z3T.mjs.map +0 -1
  126. package/dist/chunk-3ZC4LB7T.js.map +0 -1
  127. package/dist/chunk-54TYYPAN.js.map +0 -1
  128. package/dist/chunk-5MVIYRYL.mjs.map +0 -1
  129. package/dist/chunk-63GNCRER.js.map +0 -1
  130. package/dist/chunk-BJOQRBH2.mjs.map +0 -1
  131. package/dist/chunk-CJN25EXL.js.map +0 -1
  132. package/dist/chunk-K276CM3B.mjs.map +0 -1
  133. package/dist/chunk-KLK7ZRMH.js +0 -55
  134. package/dist/chunk-KLK7ZRMH.js.map +0 -1
  135. package/dist/chunk-N7WIJNHY.js.map +0 -1
  136. package/dist/chunk-NOLPMHXS.js.map +0 -1
  137. package/dist/chunk-NSLYI2LS.js.map +0 -1
  138. package/dist/chunk-Q2ON6SMV.js.map +0 -1
  139. package/dist/chunk-Q4I5QTVC.mjs.map +0 -1
  140. package/dist/chunk-RIU3ZIXZ.mjs +0 -55
  141. package/dist/chunk-RIU3ZIXZ.mjs.map +0 -1
  142. package/dist/chunk-SCERVW3B.mjs.map +0 -1
  143. package/dist/chunk-VOZOZKRC.mjs.map +0 -1
  144. package/dist/chunk-WVGK5B5P.mjs.map +0 -1
  145. package/dist/chunk-XE5IWVNV.js.map +0 -1
  146. package/dist/chunk-Y5KX5ICF.mjs.map +0 -1
  147. package/dist/chunk-Z6SOB3SY.js.map +0 -1
  148. /package/dist/{chunk-YVNRYLOC.js.map → chunk-74GN6MIJ.js.map} +0 -0
  149. /package/dist/{chunk-MYWDTEX2.js.map → chunk-GRBWVPLF.js.map} +0 -0
  150. /package/dist/{chunk-75VM3O4K.mjs.map → chunk-P5MRZOGW.mjs.map} +0 -0
  151. /package/dist/{chunk-2KCUVQFS.mjs.map → chunk-X5MFC3VX.mjs.map} +0 -0
  152. /package/dist/{chunk-ZETJVFUS.mjs.map → chunk-XSFI32LB.mjs.map} +0 -0
  153. /package/dist/{chunk-WQYMF7QP.js.map → chunk-Y7ZOSPEN.js.map} +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/services/AbstractExecutionService.ts"],"sourcesContent":["import { JsonRpcEngine } from '@metamask/json-rpc-engine';\nimport { createStreamMiddleware } from '@metamask/json-rpc-middleware-stream';\nimport ObjectMultiplex from '@metamask/object-multiplex';\nimport type { BasePostMessageStream } from '@metamask/post-message-stream';\nimport { JsonRpcError } from '@metamask/rpc-errors';\nimport type { SnapRpcHook, SnapRpcHookArgs } from '@metamask/snaps-utils';\nimport { SNAP_STREAM_NAMES, logError } from '@metamask/snaps-utils';\nimport type {\n Json,\n JsonRpcNotification,\n JsonRpcRequest,\n PendingJsonRpcResponse,\n} from '@metamask/utils';\nimport {\n Duration,\n assertIsJsonRpcRequest,\n inMilliseconds,\n isJsonRpcNotification,\n isObject,\n} from '@metamask/utils';\nimport { nanoid } from 'nanoid';\nimport { pipeline } from 'readable-stream';\nimport type { Duplex } from 'readable-stream';\n\nimport { log } from '../logging';\nimport { Timer } from '../snaps/Timer';\nimport { hasTimedOut, withTimeout } from '../utils';\nimport type {\n ExecutionService,\n ExecutionServiceMessenger,\n SnapErrorJson,\n SnapExecutionData,\n} from './ExecutionService';\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};\n\nexport type Job<WorkerType> = {\n id: string;\n streams: JobStreams;\n rpcEngine: JsonRpcEngine;\n worker: WorkerType;\n};\n\nexport type TerminateJobArgs<WorkerType> = Partial<Job<WorkerType>> &\n Pick<Job<WorkerType>, 'id'>;\n\nexport abstract class AbstractExecutionService<WorkerType>\n implements ExecutionService\n{\n #snapRpcHooks: Map<string, SnapRpcHook>;\n\n // Cannot be hash private yet because of tests.\n protected jobs: Map<string, Job<WorkerType>>;\n\n // Cannot be hash private yet because of tests.\n private readonly setupSnapProvider: SetupSnapProvider;\n\n #snapToJobMap: Map<string, string>;\n\n #jobToSnapMap: Map<string, string>;\n\n #messenger: ExecutionServiceMessenger;\n\n #initTimeout: number;\n\n #pingTimeout: number;\n\n #terminationTimeout: number;\n\n #usePing: boolean;\n\n constructor({\n setupSnapProvider,\n messenger,\n initTimeout = inMilliseconds(60, Duration.Second),\n pingTimeout = inMilliseconds(2, Duration.Second),\n terminationTimeout = inMilliseconds(1, Duration.Second),\n usePing = true,\n }: ExecutionServiceArgs) {\n this.#snapRpcHooks = new Map();\n this.jobs = new Map();\n this.setupSnapProvider = setupSnapProvider;\n this.#snapToJobMap = new Map();\n this.#jobToSnapMap = new Map();\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 private 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(job: TerminateJobArgs<WorkerType>): void;\n\n /**\n * Terminates the job with the specified ID and deletes all its associated\n * data. Any subsequent messages targeting the job will fail with an error.\n * Throws an error if the specified job does not exist, or if termination\n * fails unexpectedly.\n *\n * @param jobId - The id of the job to be terminated.\n */\n public async terminate(jobId: string): Promise<void> {\n const jobWrapper = this.jobs.get(jobId);\n if (!jobWrapper) {\n throw new Error(`Job with id \"${jobId}\" not found.`);\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(jobId, {\n jsonrpc: '2.0',\n method: 'terminate',\n params: [],\n id: nanoid(),\n }),\n this.#terminationTimeout,\n );\n\n if (result === hasTimedOut || result !== 'OK') {\n // We tried to shutdown gracefully but failed. This probably means the Snap is in infinite loop and\n // hogging down the whole JS process.\n // TODO(ritave): It might be doing weird things such as posting a lot of setTimeouts. Add a test to ensure that this behaviour\n // doesn't leak into other workers. Especially important in IframeExecutionEnvironment since they all share the same\n // JS process.\n logError(`Job \"${jobId}\" failed to terminate gracefully.`, result);\n }\n } catch {\n // Ignore\n }\n\n Object.values(jobWrapper.streams).forEach((stream) => {\n try {\n !stream.destroyed && stream.destroy();\n stream.removeAllListeners();\n } catch (error) {\n logError('Error while destroying stream', error);\n }\n });\n\n this.terminateJob(jobWrapper);\n\n this.jobs.delete(jobId);\n this.#removeSnapAndJobMapping(jobId);\n log(`Job \"${jobId}\" terminated.`);\n }\n\n /**\n * Initiates a job for a snap.\n *\n * @param jobId - The ID of the job to initiate.\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 protected async initJob(\n jobId: string,\n timer: Timer,\n ): Promise<Job<WorkerType>> {\n const { streams, worker } = await this.initStreams(jobId, timer);\n const rpcEngine = new JsonRpcEngine();\n\n const jsonRpcConnection = createStreamMiddleware();\n\n pipeline(\n jsonRpcConnection.stream,\n streams.command,\n jsonRpcConnection.stream,\n (error) => {\n if (error) {\n logError(`Command stream failure.`, error);\n }\n },\n );\n\n rpcEngine.push(jsonRpcConnection.middleware);\n\n const envMetadata = {\n id: jobId,\n streams,\n rpcEngine,\n worker,\n };\n this.jobs.set(jobId, envMetadata);\n\n return envMetadata;\n }\n\n /**\n * Sets up the streams for an initiated job.\n *\n * @param jobId - The id of the job.\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 protected async initStreams(\n jobId: string,\n timer: Timer,\n ): Promise<{ streams: JobStreams; worker: WorkerType }> {\n const result = await withTimeout(this.initEnvStream(jobId), 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 this.terminateJob({ id: jobId });\n throw new Error('The Snaps execution environment failed to start.');\n }\n\n const { worker, stream: envStream } = result;\n const mux = setupMultiplex(envStream, `Job: \"${jobId}\"`);\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 (!isJsonRpcNotification(message)) {\n return;\n }\n\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n const snapId = this.#jobToSnapMap.get(jobId)!;\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 if (isObject(message.params) && message.params.error) {\n this.#messenger.publish(\n 'ExecutionService:unhandledError',\n snapId,\n message.params.error as SnapErrorJson,\n );\n commandStream.removeListener('data', notificationHandler);\n } else {\n logError(\n new Error(\n `Received malformed \"${message.method}\" command stream notification.`,\n ),\n );\n }\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 const rpcStream = mux.createStream(SNAP_STREAM_NAMES.JSON_RPC);\n\n // Typecast: stream type mismatch\n return {\n streams: {\n command: commandStream,\n rpc: rpcStream,\n // eslint-disable-next-line @typescript-eslint/naming-convention\n _connection: envStream,\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(jobId: string): Promise<{\n worker: WorkerType;\n stream: BasePostMessageStream;\n }>;\n\n /**\n * Terminates the Snap with the specified ID. May throw an error if\n * termination unexpectedly fails, but will not fail if no job for the snap\n * with the specified ID is found.\n *\n * @param snapId - The ID of the snap to terminate.\n */\n async terminateSnap(snapId: string) {\n const jobId = this.#snapToJobMap.get(snapId);\n if (jobId) {\n await this.terminate(jobId);\n }\n }\n\n async terminateAllSnaps() {\n await Promise.all(\n [...this.jobs.keys()].map(async (jobId) => this.terminate(jobId)),\n );\n this.#snapRpcHooks.clear();\n }\n\n /**\n * Gets the RPC request handler for the given snap.\n *\n * @param snapId - The id of the Snap whose message handler to get.\n * @returns The RPC request handler for the snap.\n */\n private getRpcRequestHandler(snapId: string) {\n return this.#snapRpcHooks.get(snapId);\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.#snapToJobMap.has(snapId)) {\n throw new Error(`Snap \"${snapId}\" is already being executed.`);\n }\n\n const jobId = nanoid();\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(jobId, timer);\n\n this.#mapSnapAndJob(snapId, job.id);\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('The Snaps execution environment failed to start.');\n }\n }\n\n const rpcStream = job.streams.rpc;\n\n this.setupSnapProvider(snapId, rpcStream);\n\n const remainingTime = timer.remaining;\n\n const result = await withTimeout(\n this.command(job.id, {\n jsonrpc: '2.0',\n method: 'executeSnap',\n params: { snapId, sourceCode, endowments },\n id: nanoid(),\n }),\n remainingTime,\n );\n\n if (result === hasTimedOut) {\n throw new Error(`${snapId} failed to start.`);\n }\n\n this.#createSnapHooks(snapId, job.id);\n return result as string;\n }\n\n // Cannot be hash private yet because of tests.\n private async command(\n jobId: string,\n message: JsonRpcRequest,\n ): Promise<Json | undefined> {\n assertIsJsonRpcRequest(message);\n\n const job = this.jobs.get(jobId);\n if (!job) {\n throw new Error(`Job with id \"${jobId}\" not found.`);\n }\n\n log('Parent: Sending Command', message);\n const response: PendingJsonRpcResponse<Json> = await job.rpcEngine.handle(\n message,\n );\n\n if (response.error) {\n throw new JsonRpcError(\n response.error.code,\n response.error.message,\n response.error.data,\n );\n }\n\n return response.result;\n }\n\n #removeSnapHooks(snapId: string) {\n this.#snapRpcHooks.delete(snapId);\n }\n\n #createSnapHooks(snapId: string, workerId: string) {\n const rpcHook = async ({ origin, handler, request }: SnapRpcHookArgs) => {\n return await this.command(workerId, {\n id: nanoid(),\n jsonrpc: '2.0',\n method: 'snapRpc',\n params: {\n origin,\n handler,\n request: request as JsonRpcRequest,\n target: snapId,\n },\n });\n };\n\n this.#snapRpcHooks.set(snapId, rpcHook);\n }\n\n #mapSnapAndJob(snapId: string, jobId: string): void {\n this.#snapToJobMap.set(snapId, jobId);\n this.#jobToSnapMap.set(jobId, snapId);\n }\n\n #removeSnapAndJobMapping(jobId: string): void {\n const snapId = this.#jobToSnapMap.get(jobId);\n if (!snapId) {\n throw new Error(`job: \"${jobId}\" has no mapped snap.`);\n }\n\n this.#jobToSnapMap.delete(jobId);\n this.#snapToJobMap.delete(snapId);\n this.#removeSnapHooks(snapId);\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 rpcRequestHandler = this.getRpcRequestHandler(snapId);\n\n if (!rpcRequestHandler) {\n throw new Error(\n `Snap execution service returned no RPC handler for running snap \"${snapId}\".`,\n );\n }\n\n return rpcRequestHandler(options);\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) {\n streamName\n ? logError(`\"${streamName}\" stream failure.`, error)\n : logError(error);\n }\n });\n return mux;\n}\n"],"mappings":"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","names":[]}
@@ -1,6 +1,6 @@
1
1
  "use strict";Object.defineProperty(exports, "__esModule", {value: true});
2
2
 
3
- var _chunk54TYYPANjs = require('./chunk-54TYYPAN.js');
3
+ var _chunkSIW7ZXQFjs = require('./chunk-SIW7ZXQF.js');
4
4
 
5
5
 
6
6
  var _chunk7Y6P5FRNjs = require('./chunk-7Y6P5FRN.js');
@@ -13,7 +13,7 @@ var _chunkEXN2TFDJjs = require('./chunk-EXN2TFDJ.js');
13
13
  // src/services/proxy/ProxyExecutionService.ts
14
14
  var _nanoid = require('nanoid');
15
15
  var _stream;
16
- var ProxyExecutionService = class extends _chunk54TYYPANjs.AbstractExecutionService {
16
+ var ProxyExecutionService = class extends _chunkSIW7ZXQFjs.AbstractExecutionService {
17
17
  /**
18
18
  * Create a new proxy execution service.
19
19
  *
@@ -32,7 +32,8 @@ var ProxyExecutionService = class extends _chunk54TYYPANjs.AbstractExecutionServ
32
32
  }) {
33
33
  super({
34
34
  messenger,
35
- setupSnapProvider
35
+ setupSnapProvider,
36
+ usePing: false
36
37
  });
37
38
  _chunkEXN2TFDJjs.__privateAdd.call(void 0, this, _stream, void 0);
38
39
  _chunkEXN2TFDJjs.__privateSet.call(void 0, this, _stream, stream);
@@ -63,6 +64,13 @@ var ProxyExecutionService = class extends _chunk54TYYPANjs.AbstractExecutionServ
63
64
  stream: _chunkEXN2TFDJjs.__privateGet.call(void 0, this, _stream),
64
65
  jobId
65
66
  });
67
+ await new Promise((resolve) => {
68
+ stream.once("data", resolve);
69
+ stream.write({
70
+ name: "command",
71
+ data: { jsonrpc: "2.0", method: "ping", id: _nanoid.nanoid.call(void 0, ) }
72
+ });
73
+ });
66
74
  return { worker: jobId, stream };
67
75
  }
68
76
  };
@@ -71,4 +79,4 @@ _stream = new WeakMap();
71
79
 
72
80
 
73
81
  exports.ProxyExecutionService = ProxyExecutionService;
74
- //# sourceMappingURL=chunk-NSLYI2LS.js.map
82
+ //# sourceMappingURL=chunk-FCRPOA4I.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/services/proxy/ProxyExecutionService.ts"],"names":[],"mappings":";;;;;;;;;;;;;AACA,SAAS,cAAc;AADvB;AAcO,IAAM,wBAAN,cAAoC,yBAAiC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAc1E,YAAY;AAAA,IACV;AAAA,IACA;AAAA,IACA;AAAA,EACF,GAAyC;AACvC,UAAM;AAAA,MACJ;AAAA,MACA;AAAA,MACA,SAAS;AAAA,IACX,CAAC;AAtBH,uBAAS,SAAT;AAwBE,uBAAK,SAAU;AAAA,EACjB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAgB,aAAa,KAA+B;AAG1D,uBAAK,SAAQ,MAAM;AAAA,MACjB,OAAO,IAAI;AAAA,MACX,MAAM;AAAA,QACJ,SAAS;AAAA,QACT,QAAQ;AAAA,QACR,IAAI,OAAO;AAAA,MACb;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAgB,cAAc,OAAe;AAC3C,UAAM,SAAS,IAAI,uBAAuB;AAAA,MACxC,QAAQ,mBAAK;AAAA,MACb;AAAA,IACF,CAAC;AAMD,UAAM,IAAI,QAAQ,CAAC,YAAY;AAC7B,aAAO,KAAK,QAAQ,OAAO;AAC3B,aAAO,MAAM;AAAA,QACX,MAAM;AAAA,QACN,MAAM,EAAE,SAAS,OAAO,QAAQ,QAAQ,IAAI,OAAO,EAAE;AAAA,MACvD,CAAC;AAAA,IACH,CAAC;AAED,WAAO,EAAE,QAAQ,OAAO,OAAO;AAAA,EACjC;AACF;AAvEW","sourcesContent":["import type { BasePostMessageStream } from '@metamask/post-message-stream';\nimport { nanoid } from 'nanoid';\n\nimport type {\n ExecutionServiceArgs,\n TerminateJobArgs,\n} from '../AbstractExecutionService';\nimport { AbstractExecutionService } from '../AbstractExecutionService';\nimport { ProxyPostMessageStream } from '../ProxyPostMessageStream';\n\ntype ProxyExecutionEnvironmentServiceArgs = {\n stream: BasePostMessageStream;\n} & ExecutionServiceArgs;\n\nexport class ProxyExecutionService extends AbstractExecutionService<string> {\n readonly #stream: BasePostMessageStream;\n\n /**\n * Create a new proxy execution service.\n *\n * @param args - The constructor arguments.\n * @param args.messenger - The messenger to use for communication with the\n * `SnapController`.\n * @param args.setupSnapProvider - The function to use to set up the snap\n * provider.\n * @param args.stream - The stream to use for communicating with the proxy\n * executor.\n */\n constructor({\n stream,\n messenger,\n setupSnapProvider,\n }: ProxyExecutionEnvironmentServiceArgs) {\n super({\n messenger,\n setupSnapProvider,\n usePing: false,\n });\n\n this.#stream = stream;\n }\n\n /**\n * Send a termination command to the proxy stream.\n *\n * @param job - The job to terminate.\n */\n protected async terminateJob(job: TerminateJobArgs<string>) {\n // The `AbstractExecutionService` will have already closed the job stream,\n // so we write to the runtime stream directly.\n this.#stream.write({\n jobId: job.id,\n data: {\n jsonrpc: '2.0',\n method: 'terminateJob',\n id: nanoid(),\n },\n });\n }\n\n /**\n * Create a new stream for the specified job. This wraps the root stream\n * in a stream specific to the job.\n *\n * @param jobId - The job ID.\n */\n protected async initEnvStream(jobId: string) {\n const stream = new ProxyPostMessageStream({\n stream: this.#stream,\n jobId,\n });\n\n // Send a request and await any response before continuing\n // This simulates the behaviour of non-proxy environments by effectively awaiting\n // the load of the environment inside the proxy environment\n // This assumes the proxy environment is already loaded before this function is called\n await new Promise((resolve) => {\n stream.once('data', resolve);\n stream.write({\n name: 'command',\n data: { jsonrpc: '2.0', method: 'ping', id: nanoid() },\n });\n });\n\n return { worker: jobId, stream };\n }\n}\n"]}
@@ -1,6 +1,6 @@
1
1
  "use strict";Object.defineProperty(exports, "__esModule", {value: true});
2
2
 
3
- var _chunk54TYYPANjs = require('./chunk-54TYYPAN.js');
3
+ var _chunkSIW7ZXQFjs = require('./chunk-SIW7ZXQF.js');
4
4
 
5
5
 
6
6
  var _chunkEXN2TFDJjs = require('./chunk-EXN2TFDJ.js');
@@ -8,7 +8,7 @@ var _chunkEXN2TFDJjs = require('./chunk-EXN2TFDJ.js');
8
8
  // src/services/node-js/NodeThreadExecutionService.ts
9
9
  var _postmessagestream = require('@metamask/post-message-stream');
10
10
  var _worker_threads = require('worker_threads');
11
- var NodeThreadExecutionService = class extends _chunk54TYYPANjs.AbstractExecutionService {
11
+ var NodeThreadExecutionService = class extends _chunkSIW7ZXQFjs.AbstractExecutionService {
12
12
  async initEnvStream() {
13
13
  const worker = new (0, _worker_threads.Worker)(
14
14
  _chunkEXN2TFDJjs.__require.resolve(
@@ -29,11 +29,11 @@ var NodeThreadExecutionService = class extends _chunk54TYYPANjs.AbstractExecutio
29
29
  return Promise.resolve({ worker, stream });
30
30
  }
31
31
  async terminateJob(jobWrapper) {
32
- await jobWrapper.worker.terminate();
32
+ await jobWrapper.worker?.terminate();
33
33
  }
34
34
  };
35
35
 
36
36
 
37
37
 
38
38
  exports.NodeThreadExecutionService = NodeThreadExecutionService;
39
- //# sourceMappingURL=chunk-63GNCRER.js.map
39
+ //# sourceMappingURL=chunk-G4S6UXQ2.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/services/node-js/NodeThreadExecutionService.ts"],"names":[],"mappings":";;;;;;;;AACA,SAAS,iCAAiC;AAE1C,SAAS,cAAc;AAKhB,IAAM,6BAAN,cAAyC,yBAAiC;AAAA,EAC/E,MAAgB,gBAGb;AACD,UAAM,SAAS,IAAI;AAAA,MACjB,UAAQ;AAAA,QACN;AAAA,MACF;AAAA,MACA;AAAA,QACE,QAAQ;AAAA,QACR,QAAQ;AAAA,MACV;AAAA,IACF;AAIA,WAAO,OAAO,GAAG,QAAQ,CAAC,SAAS;AAEjC,cAAQ,IAAI,KAAK,SAAS,CAAC;AAAA,IAC7B,CAAC;AAED,WAAO,OAAO,GAAG,QAAQ,CAAC,SAAS;AAEjC,cAAQ,MAAM,KAAK,SAAS,CAAC;AAAA,IAC/B,CAAC;AAED,UAAM,SAAS,IAAI,0BAA0B,EAAE,QAAQ,OAAO,CAAC;AAC/D,WAAO,QAAQ,QAAQ,EAAE,QAAQ,OAAO,CAAC;AAAA,EAC3C;AAAA,EAEA,MAAgB,aACd,YACe;AACf,UAAM,WAAW,QAAQ,UAAU;AAAA,EACrC;AACF","sourcesContent":["import type { BasePostMessageStream } from '@metamask/post-message-stream';\nimport { ThreadParentMessageStream } from '@metamask/post-message-stream';\n// eslint-disable-next-line @typescript-eslint/no-shadow\nimport { Worker } from 'worker_threads';\n\nimport type { TerminateJobArgs } from '..';\nimport { AbstractExecutionService } from '..';\n\nexport class NodeThreadExecutionService extends AbstractExecutionService<Worker> {\n protected async initEnvStream(): Promise<{\n worker: Worker;\n stream: BasePostMessageStream;\n }> {\n const worker = new Worker(\n require.resolve(\n '@metamask/snaps-execution-environments/dist/browserify/node-thread/bundle.js',\n ),\n {\n stdout: true,\n stderr: true,\n },\n );\n\n // Capturing `stdout` and `stderr` from the worker prevents the worker from\n // writing to them directly, making it easier to capture them Jest.\n worker.stdout.on('data', (data) => {\n // eslint-disable-next-line no-console\n console.log(data.toString());\n });\n\n worker.stderr.on('data', (data) => {\n // eslint-disable-next-line no-console\n console.error(data.toString());\n });\n\n const stream = new ThreadParentMessageStream({ thread: worker });\n return Promise.resolve({ worker, stream });\n }\n\n protected async terminateJob(\n jobWrapper: TerminateJobArgs<Worker>,\n ): Promise<void> {\n await jobWrapper.worker?.terminate();\n }\n}\n"]}
@@ -3,7 +3,7 @@
3
3
  var _chunkYYPUPKQYjs = require('./chunk-YYPUPKQY.js');
4
4
 
5
5
 
6
- var _chunkNOLPMHXSjs = require('./chunk-NOLPMHXS.js');
6
+ var _chunkBOFPNIRXjs = require('./chunk-BOFPNIRX.js');
7
7
 
8
8
 
9
9
 
@@ -133,7 +133,7 @@ var CronjobController = class extends _basecontroller.BaseController {
133
133
  if (ms > DAILY_TIMEOUT) {
134
134
  return;
135
135
  }
136
- const timer = new (0, _chunkNOLPMHXSjs.Timer)(ms);
136
+ const timer = new (0, _chunkBOFPNIRXjs.Timer)(ms);
137
137
  timer.start(() => {
138
138
  this.executeCronjob(job).catch((error) => {
139
139
  _snapsutils.logError.call(void 0, error);
@@ -209,7 +209,7 @@ var CronjobController = class extends _basecontroller.BaseController {
209
209
  }
210
210
  this.schedule(job);
211
211
  }
212
- _chunkEXN2TFDJjs.__privateSet.call(void 0, this, _dailyTimer, new (0, _chunkNOLPMHXSjs.Timer)(DAILY_TIMEOUT));
212
+ _chunkEXN2TFDJjs.__privateSet.call(void 0, this, _dailyTimer, new (0, _chunkBOFPNIRXjs.Timer)(DAILY_TIMEOUT));
213
213
  _chunkEXN2TFDJjs.__privateGet.call(void 0, this, _dailyTimer).start(() => {
214
214
  this.dailyCheckIn().catch((error) => {
215
215
  _snapsutils.logError.call(void 0, error);
@@ -280,4 +280,4 @@ _snapIds = new WeakMap();
280
280
 
281
281
 
282
282
  exports.DAILY_TIMEOUT = DAILY_TIMEOUT; exports.CronjobController = CronjobController;
283
- //# sourceMappingURL=chunk-MYWDTEX2.js.map
283
+ //# sourceMappingURL=chunk-GRBWVPLF.js.map
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  Timer
3
- } from "./chunk-VOZOZKRC.mjs";
3
+ } from "./chunk-XO7KDFBY.mjs";
4
4
 
5
5
  // src/utils.ts
6
6
  import { getErrorMessage } from "@metamask/snaps-sdk";
@@ -9,6 +9,7 @@ import {
9
9
  getValidatedLocalizationFiles,
10
10
  validateFetchedSnap
11
11
  } from "@metamask/snaps-utils";
12
+ import deepEqual from "fast-deep-equal";
12
13
  function setDiff(objectA, objectB) {
13
14
  return Object.entries(objectA).reduce(
14
15
  (acc, [key, value]) => {
@@ -20,6 +21,15 @@ function setDiff(objectA, objectB) {
20
21
  {}
21
22
  );
22
23
  }
24
+ function permissionsDiff(permissionsA, permissionsB) {
25
+ return Object.entries(permissionsA).reduce((acc, [key, value]) => {
26
+ const isIncluded = key in permissionsB;
27
+ if (!isIncluded || isIncluded && !deepEqual(value.caveats ?? [], permissionsB[key].caveats ?? [])) {
28
+ acc[key] = value;
29
+ }
30
+ return acc;
31
+ }, {});
32
+ }
23
33
  function delay(ms, result) {
24
34
  return delayWithTimer(new Timer(ms), result);
25
35
  }
@@ -99,6 +109,7 @@ async function fetchSnap(snapId, location) {
99
109
 
100
110
  export {
101
111
  setDiff,
112
+ permissionsDiff,
102
113
  delay,
103
114
  delayWithTimer,
104
115
  hasTimedOut,
@@ -106,4 +117,4 @@ export {
106
117
  getSnapFiles,
107
118
  fetchSnap
108
119
  };
109
- //# sourceMappingURL=chunk-36YC4Z3T.mjs.map
120
+ //# sourceMappingURL=chunk-GTDDODNP.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/utils.ts"],"sourcesContent":["import type { PermissionConstraint } from '@metamask/permission-controller';\nimport type { SnapId } from '@metamask/snaps-sdk';\nimport { getErrorMessage } from '@metamask/snaps-sdk';\nimport {\n encodeBase64,\n getValidatedLocalizationFiles,\n validateFetchedSnap,\n} from '@metamask/snaps-utils';\nimport deepEqual from 'fast-deep-equal';\n\nimport type { SnapLocation } from './snaps';\nimport { Timer } from './snaps/Timer';\n\n/**\n * Takes two objects and does a Set Difference of them.\n * Set Difference is generally defined as follows:\n * ```\n * 𝑥 ∈ A ∖ B ⟺ 𝑥 ∈ A ∧ 𝑥 ∉ B\n * ```\n * Meaning that the returned object contains all properties of A expect those that also\n * appear in B. Notice that properties that appear in B, but not in A, have no effect.\n *\n * @see [Set Difference]{@link https://proofwiki.org/wiki/Definition:Set_Difference}\n * @param objectA - The object on which the difference is being calculated.\n * @param objectB - The object whose properties will be removed from objectA.\n * @returns The objectA without properties from objectB.\n */\nexport function setDiff<\n ObjectA extends Record<any, unknown>,\n ObjectB extends Record<any, unknown>,\n>(objectA: ObjectA, objectB: ObjectB): Diff<ObjectA, ObjectB> {\n return Object.entries(objectA).reduce<Record<any, unknown>>(\n (acc, [key, value]) => {\n if (!(key in objectB)) {\n acc[key] = value;\n }\n return acc;\n },\n {},\n ) as Diff<ObjectA, ObjectB>;\n}\n\n/**\n * Calculate a difference between two permissions objects.\n *\n * Similar to `setDiff` except for one additional condition:\n * Permissions in B should be removed from A if they exist in both and have differing caveats.\n *\n * @param permissionsA - An object containing one or more partial permissions.\n * @param permissionsB - An object containing one or more partial permissions to be subtracted from A.\n * @returns The permissions set A without properties from B.\n */\nexport function permissionsDiff<\n PermissionsA extends Record<string, Pick<PermissionConstraint, 'caveats'>>,\n PermissionsB extends Record<string, Pick<PermissionConstraint, 'caveats'>>,\n>(\n permissionsA: PermissionsA,\n permissionsB: PermissionsB,\n): Diff<PermissionsA, PermissionsB> {\n return Object.entries(permissionsA).reduce<\n Record<string, Pick<PermissionConstraint, 'caveats'>>\n >((acc, [key, value]) => {\n const isIncluded = key in permissionsB;\n if (\n !isIncluded ||\n (isIncluded &&\n !deepEqual(value.caveats ?? [], permissionsB[key].caveats ?? []))\n ) {\n acc[key] = value;\n }\n return acc;\n }, {}) as Diff<PermissionsA, PermissionsB>;\n}\n\n/**\n * A Promise that delays its return for a given amount of milliseconds.\n *\n * @param ms - Milliseconds to delay the execution for.\n * @param result - The result to return from the Promise after delay.\n * @returns A promise that is void if no result provided, result otherwise.\n * @template Result - The `result`.\n */\nexport function delay<Result = void>(\n ms: number,\n result?: Result,\n): Promise<Result> & { cancel: () => void } {\n return delayWithTimer(new Timer(ms), result);\n}\n\n/**\n * A Promise that delays it's return by using a pausable Timer.\n *\n * @param timer - Timer used to control the delay.\n * @param result - The result to return from the Promise after delay.\n * @returns A promise that is void if no result provided, result otherwise.\n * @template Result - The `result`.\n */\nexport function delayWithTimer<Result = void>(\n timer: Timer,\n result?: Result,\n): Promise<Result> & { cancel: () => void } {\n let rejectFunc: (reason: Error) => void;\n const promise: any = new Promise<Result>((resolve: any, reject) => {\n timer.start(() => {\n result === undefined ? resolve() : resolve(result);\n });\n rejectFunc = reject;\n });\n\n promise.cancel = () => {\n if (timer.status !== 'finished') {\n timer.cancel();\n rejectFunc(new Error('The delay has been canceled.'));\n }\n };\n return promise;\n}\n\n/*\n * We use a Symbol instead of rejecting the promise so that Errors thrown\n * by the main promise will propagate.\n */\nexport const hasTimedOut = Symbol(\n 'Used to check if the requested promise has timeout (see withTimeout)',\n);\n\n/**\n * Executes the given Promise, if the Timer expires before the Promise settles, we return earlier.\n *\n * NOTE:** The given Promise is not cancelled or interrupted, and will continue to execute uninterrupted. We will just discard its result if it does not complete before the timeout.\n *\n * @param promise - The promise that you want to execute.\n * @param timerOrMs - The timer controlling the timeout or a ms value.\n * @returns The resolved `PromiseValue`, or the hasTimedOut symbol if\n * returning early.\n * @template PromiseValue - The value of the Promise.\n */\nexport async function withTimeout<PromiseValue = void>(\n promise: Promise<PromiseValue>,\n timerOrMs: Timer | number,\n): Promise<PromiseValue | typeof hasTimedOut> {\n const timer =\n typeof timerOrMs === 'number' ? new Timer(timerOrMs) : timerOrMs;\n const delayPromise = delayWithTimer(timer, hasTimedOut);\n try {\n return await Promise.race([promise, delayPromise]);\n } finally {\n delayPromise.cancel();\n }\n}\n\n/**\n * Checks whether the type is composed of literal types\n *\n * @returns @type {true} if whole type is composed of literals, @type {false} if whole type is not literals, @type {boolean} if mixed\n * @example\n * ```\n * type t1 = IsLiteral<1 | 2 | \"asd\" | true>;\n * // t1 = true\n *\n * type t2 = IsLiteral<number | string>;\n * // t2 = false\n *\n * type t3 = IsLiteral<1 | string>;\n * // t3 = boolean\n *\n * const s = Symbol();\n * type t4 = IsLiteral<typeof s>;\n * // t4 = true\n *\n * type t5 = IsLiteral<symbol>\n * // t5 = false;\n * ```\n */\ntype IsLiteral<Type> = Type extends string | number | boolean | symbol\n ? Extract<string | number | boolean | symbol, Type> extends never\n ? true\n : false\n : false;\n\n/**\n * Returns all keys of an object, that are literal, as an union\n *\n * @example\n * ```\n * type t1 = _LiteralKeys<{a: number, b: 0, c: 'foo', d: string}>\n * // t1 = 'b' | 'c'\n * ```\n * @see [Literal types]{@link https://www.typescriptlang.org/docs/handbook/literal-types.html}\n */\ntype LiteralKeys<Type> = NonNullable<\n {\n [Key in keyof Type]: IsLiteral<Key> extends true ? Key : never;\n }[keyof Type]\n>;\n\n/**\n * Returns all keys of an object, that are not literal, as an union\n *\n * @example\n * ```\n * type t1 = _NonLiteralKeys<{a: number, b: 0, c: 'foo', d: string}>\n * // t1 = 'a' | 'd'\n * ```\n * @see [Literal types]{@link https://www.typescriptlang.org/docs/handbook/literal-types.html}\n */\ntype NonLiteralKeys<Type> = NonNullable<\n {\n [Key in keyof Type]: IsLiteral<Key> extends false ? Key : never;\n }[keyof Type]\n>;\n\n/**\n * A set difference of two objects based on their keys\n *\n * @example\n * ```\n * type t1 = Diff<{a: string, b: string}, {a: number}>\n * // t1 = {b: string};\n * type t2 = Diff<{a: string, 0: string}, Record<string, unknown>>;\n * // t2 = { a?: string, 0: string};\n * type t3 = Diff<{a: string, 0: string, 1: string}, Record<1 | string, unknown>>;\n * // t3 = {a?: string, 0: string}\n * ```\n * @see {@link setDiff} for the main use-case\n */\nexport type Diff<First, Second> = Omit<First, LiteralKeys<Second>> &\n Partial<Pick<First, Extract<keyof First, NonLiteralKeys<Second>>>>;\n\n/**\n * Makes every specified property of the specified object type mutable.\n *\n * @template Type - The object whose readonly properties to make mutable.\n * @template TargetKey - The property key(s) to make mutable.\n */\nexport type Mutable<\n Type extends Record<string, unknown>,\n TargetKey extends string,\n> = {\n -readonly [Key in keyof Pick<Type, TargetKey>]: Type[Key];\n} & {\n [Key in keyof Omit<Type, TargetKey>]: Type[Key];\n};\n\n/**\n * Get all files in a Snap from an array of file paths.\n *\n * @param location - The location of the Snap.\n * @param files - The array of file paths.\n * @returns The array of files as {@link VirtualFile}s.\n */\nexport async function getSnapFiles(\n location: SnapLocation,\n files?: string[] | undefined,\n) {\n if (!files || files.length === 0) {\n return [];\n }\n\n return await Promise.all(\n files.map(async (filePath) => location.fetch(filePath)),\n );\n}\n\n/**\n * Fetch the Snap manifest, source code, and any other files from the given\n * location.\n *\n * @param snapId - The ID of the Snap to fetch.\n * @param location - The location of the Snap.\n * @returns The Snap files and location.\n * @throws If the Snap files are invalid, or if the Snap could not be fetched.\n */\nexport async function fetchSnap(snapId: SnapId, location: SnapLocation) {\n try {\n const manifest = await location.manifest();\n const sourceCode = await location.fetch(\n manifest.result.source.location.npm.filePath,\n );\n const { iconPath } = manifest.result.source.location.npm;\n const svgIcon = iconPath ? await location.fetch(iconPath) : undefined;\n\n const auxiliaryFiles = await getSnapFiles(\n location,\n manifest.result.source.files,\n );\n\n await Promise.all(\n auxiliaryFiles.map(async (file) => {\n // This should still be safe\n // eslint-disable-next-line require-atomic-updates\n file.data.base64 = await encodeBase64(file);\n }),\n );\n\n const localizationFiles = await getSnapFiles(\n location,\n manifest.result.source.locales,\n );\n\n const validatedLocalizationFiles =\n getValidatedLocalizationFiles(localizationFiles);\n\n const files = {\n manifest,\n sourceCode,\n svgIcon,\n auxiliaryFiles,\n localizationFiles: validatedLocalizationFiles,\n };\n\n await validateFetchedSnap(files);\n\n return files;\n } catch (error) {\n throw new Error(\n `Failed to fetch snap \"${snapId}\": ${getErrorMessage(error)}.`,\n );\n }\n}\n"],"mappings":"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","names":[]}
@@ -17,12 +17,13 @@ import {
17
17
  import {
18
18
  fetchSnap,
19
19
  hasTimedOut,
20
+ permissionsDiff,
20
21
  setDiff,
21
22
  withTimeout
22
- } from "./chunk-36YC4Z3T.mjs";
23
+ } from "./chunk-GTDDODNP.mjs";
23
24
  import {
24
25
  Timer
25
- } from "./chunk-VOZOZKRC.mjs";
26
+ } from "./chunk-XO7KDFBY.mjs";
26
27
  import {
27
28
  __privateAdd,
28
29
  __privateGet,
@@ -116,7 +117,7 @@ function truncateSnap(snap) {
116
117
  return truncatedSnap;
117
118
  }
118
119
  var name = "SnapController";
119
- var _closeAllConnections, _dynamicPermissions, _environmentEndowmentPermissions, _excludedPermissions, _featureFlags, _fetchFunction, _idleTimeCheckInterval, _maxIdleTime, _maxInitTime, _encryptor, _getMnemonic, _detectSnapLocation, _snapsRuntimeData, _rollbackSnapshots, _timeoutForLastRequestStatus, _statusMachine, _initializeStateMachine, initializeStateMachine_fn, _registerMessageHandlers, registerMessageHandlers_fn, _handlePreinstalledSnaps, handlePreinstalledSnaps_fn, _pollForLastRequestStatus, pollForLastRequestStatus_fn, _blockSnap, blockSnap_fn, _unblockSnap, unblockSnap_fn, _assertIsInstallAllowed, assertIsInstallAllowed_fn, _stopSnapsLastRequestPastMax, stopSnapsLastRequestPastMax_fn, _transition, transition_fn, _terminateSnap, terminateSnap_fn, _getSnapEncryptionKey, getSnapEncryptionKey_fn, _decryptSnapState, decryptSnapState_fn, _encryptSnapState, encryptSnapState_fn, _handleInitialConnections, handleInitialConnections_fn, _addSnapToSubject, addSnapToSubject_fn, _removeSnapFromSubjects, removeSnapFromSubjects_fn, _revokeAllSnapPermissions, revokeAllSnapPermissions_fn, _createApproval, createApproval_fn, _updateApproval, updateApproval_fn, _resolveAllowlistVersion, resolveAllowlistVersion_fn, _add, add_fn, _startSnap, startSnap_fn, _getEndowments, getEndowments_fn, _set, set_fn, _validateSnapPermissions, validateSnapPermissions_fn, _getExecutionTimeout, getExecutionTimeout_fn, _getRpcRequestHandler, getRpcRequestHandler_fn, _createInterface, createInterface_fn, _assertInterfaceExists, assertInterfaceExists_fn, _transformSnapRpcRequestResult, transformSnapRpcRequestResult_fn, _assertSnapRpcRequestResult, assertSnapRpcRequestResult_fn, _recordSnapRpcRequestStart, recordSnapRpcRequestStart_fn, _recordSnapRpcRequestFinish, recordSnapRpcRequestFinish_fn, _getRollbackSnapshot, getRollbackSnapshot_fn, _createRollbackSnapshot, createRollbackSnapshot_fn, _rollbackSnap, rollbackSnap_fn, _rollbackSnaps, rollbackSnaps_fn, _getRuntime, getRuntime_fn, _getRuntimeExpect, getRuntimeExpect_fn, _setupRuntime, setupRuntime_fn, _calculatePermissionsChange, calculatePermissionsChange_fn, _updatePermissions, updatePermissions_fn, _isValidUpdate, isValidUpdate_fn, _callLifecycleHook, callLifecycleHook_fn;
120
+ var _closeAllConnections, _dynamicPermissions, _environmentEndowmentPermissions, _excludedPermissions, _featureFlags, _fetchFunction, _idleTimeCheckInterval, _maxIdleTime, _encryptor, _getMnemonic, _detectSnapLocation, _snapsRuntimeData, _rollbackSnapshots, _timeoutForLastRequestStatus, _statusMachine, _initializeStateMachine, initializeStateMachine_fn, _registerMessageHandlers, registerMessageHandlers_fn, _handlePreinstalledSnaps, handlePreinstalledSnaps_fn, _pollForLastRequestStatus, pollForLastRequestStatus_fn, _blockSnap, blockSnap_fn, _unblockSnap, unblockSnap_fn, _assertIsInstallAllowed, assertIsInstallAllowed_fn, _stopSnapsLastRequestPastMax, stopSnapsLastRequestPastMax_fn, _transition, transition_fn, _terminateSnap, terminateSnap_fn, _getSnapEncryptionKey, getSnapEncryptionKey_fn, _decryptSnapState, decryptSnapState_fn, _encryptSnapState, encryptSnapState_fn, _handleInitialConnections, handleInitialConnections_fn, _addSnapToSubject, addSnapToSubject_fn, _removeSnapFromSubjects, removeSnapFromSubjects_fn, _revokeAllSnapPermissions, revokeAllSnapPermissions_fn, _createApproval, createApproval_fn, _updateApproval, updateApproval_fn, _resolveAllowlistVersion, resolveAllowlistVersion_fn, _add, add_fn, _startSnap, startSnap_fn, _getEndowments, getEndowments_fn, _set, set_fn, _validateSnapPermissions, validateSnapPermissions_fn, _getExecutionTimeout, getExecutionTimeout_fn, _getRpcRequestHandler, getRpcRequestHandler_fn, _createInterface, createInterface_fn, _assertInterfaceExists, assertInterfaceExists_fn, _transformSnapRpcRequestResult, transformSnapRpcRequestResult_fn, _assertSnapRpcRequestResult, assertSnapRpcRequestResult_fn, _recordSnapRpcRequestStart, recordSnapRpcRequestStart_fn, _recordSnapRpcRequestFinish, recordSnapRpcRequestFinish_fn, _getRollbackSnapshot, getRollbackSnapshot_fn, _createRollbackSnapshot, createRollbackSnapshot_fn, _rollbackSnap, rollbackSnap_fn, _rollbackSnaps, rollbackSnaps_fn, _getRuntime, getRuntime_fn, _getRuntimeExpect, getRuntimeExpect_fn, _setupRuntime, setupRuntime_fn, _calculatePermissionsChange, calculatePermissionsChange_fn, _updatePermissions, updatePermissions_fn, _isValidUpdate, isValidUpdate_fn, _callLifecycleHook, callLifecycleHook_fn;
120
121
  var SnapController = class extends BaseController {
121
122
  constructor({
122
123
  closeAllConnections,
@@ -128,7 +129,6 @@ var SnapController = class extends BaseController {
128
129
  idleTimeCheckInterval = inMilliseconds(5, Duration.Second),
129
130
  maxIdleTime = inMilliseconds(30, Duration.Second),
130
131
  maxRequestTime = inMilliseconds(60, Duration.Second),
131
- maxInitTime = inMilliseconds(60, Duration.Second),
132
132
  fetchFunction = globalThis.fetch.bind(globalThis),
133
133
  featureFlags = {},
134
134
  detectSnapLocation: detectSnapLocationFunction = detectSnapLocation,
@@ -418,7 +418,7 @@ var SnapController = class extends BaseController {
418
418
  * to return false in that scenario.
419
419
  *
420
420
  * @param snapId - The snap id.
421
- * @param newVersionRange - The new version range being requsted.
421
+ * @param newVersionRange - The new version range being requested.
422
422
  * @returns `true` if validation checks pass and `false` if they do not.
423
423
  */
424
424
  __privateAdd(this, _isValidUpdate);
@@ -441,7 +441,6 @@ var SnapController = class extends BaseController {
441
441
  __privateAdd(this, _fetchFunction, void 0);
442
442
  __privateAdd(this, _idleTimeCheckInterval, void 0);
443
443
  __privateAdd(this, _maxIdleTime, void 0);
444
- __privateAdd(this, _maxInitTime, void 0);
445
444
  __privateAdd(this, _encryptor, void 0);
446
445
  __privateAdd(this, _getMnemonic, void 0);
447
446
  __privateAdd(this, _detectSnapLocation, void 0);
@@ -458,7 +457,6 @@ var SnapController = class extends BaseController {
458
457
  __privateSet(this, _idleTimeCheckInterval, idleTimeCheckInterval);
459
458
  __privateSet(this, _maxIdleTime, maxIdleTime);
460
459
  this.maxRequestTime = maxRequestTime;
461
- __privateSet(this, _maxInitTime, maxInitTime);
462
460
  __privateSet(this, _detectSnapLocation, detectSnapLocationFunction);
463
461
  __privateSet(this, _encryptor, encryptor);
464
462
  __privateSet(this, _getMnemonic, getMnemonic);
@@ -625,15 +623,20 @@ var SnapController = class extends BaseController {
625
623
  if (!runtime) {
626
624
  throw new Error(`The snap "${snapId}" is not running.`);
627
625
  }
628
- runtime.lastRequest = null;
629
- runtime.pendingInboundRequests = [];
630
- runtime.pendingOutboundRequests = 0;
626
+ if (runtime.stopping) {
627
+ return;
628
+ }
629
+ runtime.stopping = true;
631
630
  try {
632
631
  if (this.isRunning(snapId)) {
633
632
  (_a = __privateGet(this, _closeAllConnections)) == null ? void 0 : _a.call(this, snapId);
634
633
  await __privateMethod(this, _terminateSnap, terminateSnap_fn).call(this, snapId);
635
634
  }
636
635
  } finally {
636
+ runtime.lastRequest = null;
637
+ runtime.pendingInboundRequests = [];
638
+ runtime.pendingOutboundRequests = 0;
639
+ runtime.stopping = false;
637
640
  if (this.isRunning(snapId)) {
638
641
  __privateMethod(this, _transition, transition_fn).call(this, snapId, statusEvent);
639
642
  }
@@ -1410,7 +1413,6 @@ _featureFlags = new WeakMap();
1410
1413
  _fetchFunction = new WeakMap();
1411
1414
  _idleTimeCheckInterval = new WeakMap();
1412
1415
  _maxIdleTime = new WeakMap();
1413
- _maxInitTime = new WeakMap();
1414
1416
  _encryptor = new WeakMap();
1415
1417
  _getMnemonic = new WeakMap();
1416
1418
  _detectSnapLocation = new WeakMap();
@@ -1698,6 +1700,10 @@ transition_fn = function(snapId, event) {
1698
1700
  _terminateSnap = new WeakSet();
1699
1701
  terminateSnap_fn = async function(snapId) {
1700
1702
  await this.messagingSystem.call("ExecutionService:terminateSnap", snapId);
1703
+ await new Promise((resolve) => setTimeout(resolve, 1));
1704
+ const runtime = __privateMethod(this, _getRuntimeExpect, getRuntimeExpect_fn).call(this, snapId);
1705
+ runtime.pendingInboundRequests.filter((pendingRequest) => pendingRequest.timer.status !== "finished").forEach((pendingRequest) => pendingRequest.timer.finish());
1706
+ await new Promise((resolve) => setTimeout(resolve, 1));
1701
1707
  this.messagingSystem.publish(
1702
1708
  "SnapController:snapTerminated",
1703
1709
  this.getTruncatedExpect(snapId)
@@ -1923,16 +1929,13 @@ startSnap_fn = async function(snapData) {
1923
1929
  }
1924
1930
  try {
1925
1931
  const runtime = __privateMethod(this, _getRuntimeExpect, getRuntimeExpect_fn).call(this, snapId);
1926
- const result = await withTimeout(
1927
- this.messagingSystem.call("ExecutionService:executeSnap", {
1932
+ const result = await this.messagingSystem.call(
1933
+ "ExecutionService:executeSnap",
1934
+ {
1928
1935
  ...snapData,
1929
1936
  endowments: await __privateMethod(this, _getEndowments, getEndowments_fn).call(this, snapId)
1930
- }),
1931
- __privateGet(this, _maxInitTime)
1937
+ }
1932
1938
  );
1933
- if (result === hasTimedOut) {
1934
- throw new Error(`${snapId} failed to start.`);
1935
- }
1936
1939
  __privateMethod(this, _transition, transition_fn).call(this, snapId, SnapStatusEvents.Start);
1937
1940
  runtime.lastRequest = Date.now();
1938
1941
  return result;
@@ -2152,15 +2155,16 @@ getRpcRequestHandler_fn = function(snapId) {
2152
2155
  );
2153
2156
  }
2154
2157
  await __privateMethod(this, _assertSnapRpcRequestResult, assertSnapRpcRequestResult_fn).call(this, snapId, handlerType, result);
2155
- return __privateMethod(this, _transformSnapRpcRequestResult, transformSnapRpcRequestResult_fn).call(this, snapId, handlerType, result);
2158
+ const transformedResult = await __privateMethod(this, _transformSnapRpcRequestResult, transformSnapRpcRequestResult_fn).call(this, snapId, handlerType, result);
2159
+ __privateMethod(this, _recordSnapRpcRequestFinish, recordSnapRpcRequestFinish_fn).call(this, snapId, request.id);
2160
+ return transformedResult;
2156
2161
  } catch (error) {
2162
+ __privateMethod(this, _recordSnapRpcRequestFinish, recordSnapRpcRequestFinish_fn).call(this, snapId, request.id);
2157
2163
  const [jsonRpcError, handled] = unwrapError(error);
2158
2164
  if (!handled) {
2159
2165
  await this.stopSnap(snapId, SnapStatusEvents.Crash);
2160
2166
  }
2161
2167
  throw jsonRpcError;
2162
- } finally {
2163
- __privateMethod(this, _recordSnapRpcRequestFinish, recordSnapRpcRequestFinish_fn).call(this, snapId, request.id);
2164
2168
  }
2165
2169
  };
2166
2170
  runtime.rpcHandler = rpcHandler;
@@ -2344,7 +2348,8 @@ setupRuntime_fn = function(snapId) {
2344
2348
  activeReferences: 0,
2345
2349
  pendingInboundRequests: [],
2346
2350
  pendingOutboundRequests: 0,
2347
- interpreter
2351
+ interpreter,
2352
+ stopping: false
2348
2353
  });
2349
2354
  };
2350
2355
  _calculatePermissionsChange = new WeakSet();
@@ -2353,9 +2358,18 @@ calculatePermissionsChange_fn = function(snapId, desiredPermissionsSet) {
2353
2358
  "PermissionController:getPermissions",
2354
2359
  snapId
2355
2360
  ) ?? {};
2356
- const newPermissions = setDiff(desiredPermissionsSet, oldPermissions);
2357
- const unusedPermissions = setDiff(oldPermissions, desiredPermissionsSet);
2358
- const approvedPermissions = setDiff(oldPermissions, unusedPermissions);
2361
+ const newPermissions = permissionsDiff(
2362
+ desiredPermissionsSet,
2363
+ oldPermissions
2364
+ );
2365
+ const unusedPermissions = permissionsDiff(
2366
+ oldPermissions,
2367
+ desiredPermissionsSet
2368
+ );
2369
+ const approvedPermissions = permissionsDiff(
2370
+ oldPermissions,
2371
+ unusedPermissions
2372
+ );
2359
2373
  return { newPermissions, unusedPermissions, approvedPermissions };
2360
2374
  };
2361
2375
  _updatePermissions = new WeakSet();
@@ -2420,4 +2434,4 @@ export {
2420
2434
  SNAP_APPROVAL_RESULT,
2421
2435
  SnapController
2422
2436
  };
2423
- //# sourceMappingURL=chunk-5MVIYRYL.mjs.map
2437
+ //# sourceMappingURL=chunk-IPYO7FKR.mjs.map