{"version":3,"file":"request.cjs","sourceRoot":"","sources":["../src/request.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ExecutionService } from '@metamask/snaps-controllers';\nimport {\n  type ComponentOrElement,\n  ComponentOrElementStruct,\n  type JsonRpcError,\n  type SnapId,\n} from '@metamask/snaps-sdk';\nimport type { HandlerType } from '@metamask/snaps-utils';\nimport { unwrapError } from '@metamask/snaps-utils';\nimport { is } from '@metamask/superstruct';\nimport {\n  assert,\n  getSafeJson,\n  hasProperty,\n  isPlainObject,\n} from '@metamask/utils';\nimport { nanoid } from '@reduxjs/toolkit';\n\nimport type { RootControllerMessenger } from './controllers';\nimport { getInterface, getInterfaceActions } from './interface';\nimport type { SimulationOptions } from './options';\nimport type { RunSagaFunction, Store } from './store';\nimport {\n  getTraces,\n  getErrors,\n  clearNotifications,\n  getNotifications,\n  getEvents,\n  clearTrackables,\n} from './store';\nimport { SnapResponseStruct } from './structs';\nimport type {\n  RequestOptions,\n  SnapHandlerInterface,\n  SnapRequest,\n} from './types';\n\nexport type HandleRequestOptions = {\n  snapId: SnapId;\n  store: Store;\n  executionService: ExecutionService;\n  handler: HandlerType;\n  controllerMessenger: RootControllerMessenger;\n  simulationOptions: SimulationOptions;\n  runSaga: RunSagaFunction;\n  request: RequestOptions;\n};\n\n/**\n * Send a JSON-RPC request to the Snap, and wrap the response in a\n * {@link SnapResponse} object.\n *\n * @param options - The request options.\n * @param options.snapId - The ID of the Snap to send the request to.\n * @param options.store - The Redux store.\n * @param options.executionService - The execution service to use to send the\n * request.\n * @param options.handler - The handler to use to send the request.\n * @param options.controllerMessenger - The controller messenger used to call actions.\n * @param options.simulationOptions - The simulation options.\n * @param options.runSaga - A function to run a saga outside the usual Redux\n * flow.\n * @param options.request - The request to send.\n * @param options.request.id - The ID of the request. If not provided, a random\n * ID will be generated.\n * @param options.request.origin - The origin of the request. Defaults to\n * `https://metamask.io`.\n * @returns The response, wrapped in a {@link SnapResponse} object.\n */\nexport function handleRequest({\n  snapId,\n  store,\n  executionService,\n  handler,\n  controllerMessenger,\n  simulationOptions,\n  runSaga,\n  request: { id = nanoid(), origin = 'https://metamask.io', ...options },\n}: HandleRequestOptions): SnapRequest {\n  const getInterfaceError = () => {\n    throw new Error(\n      'Unable to get the interface from the Snap: The request to the Snap failed.',\n    );\n  };\n\n  const promise = executionService\n    .handleRpcRequest(snapId, {\n      origin,\n      handler,\n      request: {\n        jsonrpc: '2.0',\n        id: 1,\n        ...options,\n      },\n    })\n    .then(async (result) => {\n      const state = store.getState();\n      const notifications = getNotifications(state);\n      const errors = getErrors(state);\n      const events = getEvents(state);\n      const traces = getTraces(state);\n      const interfaceId = notifications[0]?.content;\n\n      store.dispatch(clearNotifications());\n      store.dispatch(clearTrackables());\n\n      try {\n        const getInterfaceFn = await getInterfaceApi(\n          result,\n          snapId,\n          controllerMessenger,\n          simulationOptions,\n          interfaceId,\n        );\n\n        return {\n          id: String(id),\n          response: {\n            result: getSafeJson(result),\n          },\n          notifications,\n          tracked: {\n            errors,\n            events,\n            traces,\n          },\n          ...(getInterfaceFn ? { getInterface: getInterfaceFn } : {}),\n        };\n      } catch (error) {\n        const [unwrappedError] = unwrapError(error);\n        return {\n          id: String(id),\n          response: {\n            error: unwrappedError.serialize(),\n          },\n          notifications: [],\n          tracked: {\n            errors: [],\n            events: [],\n            traces: [],\n          },\n          getInterface: getInterfaceError,\n        };\n      }\n    })\n    .catch((error) => {\n      const [unwrappedError] = unwrapError(error);\n\n      return {\n        id: String(id),\n        response: {\n          error: unwrappedError.serialize(),\n        },\n        notifications: [],\n        tracked: {\n          errors: [],\n          events: [],\n          traces: [],\n        },\n        getInterface: getInterfaceError,\n      };\n    }) as unknown as SnapRequest;\n\n  promise.getInterface = async () => {\n    const sagaPromise = runSaga(\n      getInterface,\n      runSaga,\n      snapId,\n      controllerMessenger,\n      simulationOptions,\n    ).toPromise();\n    const result = await Promise.race([promise, sagaPromise]);\n\n    // If the request promise has resolved to an error, we should throw\n    // instead of waiting for an interface that likely will never be displayed\n    if (\n      is(result, SnapResponseStruct) &&\n      hasProperty(result.response, 'error')\n    ) {\n      throw new Error(\n        `Unable to get the interface from the Snap: The returned interface may be invalid. The error message received was: ${\n          (result.response.error as JsonRpcError).message\n        }`,\n      );\n    }\n\n    return await sagaPromise;\n  };\n\n  return promise;\n}\n\n/**\n * Get the interface ID from the result if it's available or create a new interface if the result contains static components.\n *\n * @param result - The handler result object.\n * @param snapId - The Snap ID.\n * @param controllerMessenger - The controller messenger.\n * @returns The interface ID or undefined if the result doesn't include content.\n */\nexport async function getInterfaceFromResult(\n  result: unknown,\n  snapId: SnapId,\n  controllerMessenger: RootControllerMessenger,\n) {\n  if (isPlainObject(result) && hasProperty(result, 'id')) {\n    return result.id as string;\n  }\n\n  if (isPlainObject(result) && hasProperty(result, 'content')) {\n    assert(\n      is(result.content, ComponentOrElementStruct),\n      'The Snap returned an invalid interface.',\n    );\n\n    const id = controllerMessenger.call(\n      'SnapInterfaceController:createInterface',\n      snapId,\n      result.content as ComponentOrElement,\n    );\n\n    return id;\n  }\n\n  return undefined;\n}\n\n/**\n * Get the response content from the `SnapInterfaceController` and include the\n * interaction methods.\n *\n * @param result - The handler result object.\n * @param snapId - The Snap ID.\n * @param controllerMessenger - The controller messenger.\n * @param options - The simulation options.\n * @param contentId - The id of the interface if it exists outside of the result.\n * @returns The content components if any.\n */\nexport async function getInterfaceApi(\n  result: unknown,\n  snapId: SnapId,\n  controllerMessenger: RootControllerMessenger,\n  options: SimulationOptions,\n  contentId?: string,\n): Promise<(() => SnapHandlerInterface) | undefined> {\n  const interfaceId = await getInterfaceFromResult(\n    result,\n    snapId,\n    controllerMessenger,\n  );\n\n  const id = interfaceId ?? contentId;\n\n  if (id) {\n    try {\n      controllerMessenger.call(\n        'SnapInterfaceController:setInterfaceDisplayed',\n        snapId,\n        id,\n      );\n    } catch {\n      // The call will fail for invalid interfaces, but we can just ignore that\n      // here.\n    }\n\n    return () => {\n      const { content } = controllerMessenger.call(\n        'SnapInterfaceController:getInterface',\n        snapId,\n        id,\n      );\n\n      const actions = getInterfaceActions(\n        snapId,\n        controllerMessenger,\n        options,\n        {\n          id,\n          content,\n        },\n      );\n\n      return {\n        content,\n        ...actions,\n      };\n    };\n  }\n\n  return undefined;\n}\n"]}