{"version":3,"file":"invokeKeyring.cjs","sourceRoot":"","sources":["../../src/permitted/invokeKeyring.ts"],"names":[],"mappings":";;;AAEA,qDAAiD;AAOjD,uDAAgF;AAMhF,2CAA8C;AAE9C,2DAAuD;AAGvD,MAAM,SAAS,GAA0C;IACvD,aAAa,EAAE,IAAI;IACnB,oBAAoB,EAAE,IAAI;IAC1B,OAAO,EAAE,IAAI;IACb,wBAAwB,EAAE,IAAI;CAC/B,CAAC;AAEF;;GAEG;AACU,QAAA,oBAAoB,GAI7B;IACF,WAAW,EAAE,CAAC,sBAAsB,CAAC;IACrC,cAAc,EAAE,2BAA2B;IAC3C,SAAS;CACV,CAAC;AAgBF;;;;;;;;;;;;;;;;GAgBG;AACH,KAAK,UAAU,2BAA2B,CACxC,GAAwC;AACxC,0EAA0E;AAC1E,8EAA8E;AAC9E,8EAA8E;AAC9E,+BAA+B;AAC/B,4EAA4E;AAC5E,GAAgD,EAChD,KAAc,EACd,GAA6B,EAC7B,EACE,oBAAoB,EACpB,aAAa,EACb,OAAO,EACP,wBAAwB,GACL;IAErB,IAAI,MAAwB,CAAC;IAC7B,IAAI,CAAC;QACH,MAAM,GAAG,IAAA,oCAAkB,EAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IAC1C,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,GAAG,CAAC,KAAK,CAAC,CAAC;IACpB,CAAC;IAED,yEAAyE;IACzE,MAAM,EAAE,MAAM,EAAE,GAAG,GAA0C,CAAC;IAC9D,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,CAAC;IAEnC,IAAI,CAAC,MAAM,IAAI,CAAC,aAAa,CAAC,wCAA0B,CAAC,EAAE,CAAC;QAC1D,OAAO,GAAG,CACR,sBAAS,CAAC,cAAc,CAAC;YACvB,OAAO,EAAE,aAAa,MAAM,0BAA0B,MAAM,6CAA6C;SAC1G,CAAC,CACH,CAAC;IACJ,CAAC;IAED,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QACrB,OAAO,GAAG,CACR,sBAAS,CAAC,cAAc,CAAC;YACvB,OAAO,EAAE,aAAa,MAAM,wEAAwE;SACrG,CAAC,CACH,CAAC;IACJ,CAAC;IAED,IAAI,CAAC,IAAA,mBAAW,EAAC,OAAO,EAAE,QAAQ,CAAC,IAAI,OAAO,OAAO,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;QAC1E,OAAO,GAAG,CACR,sBAAS,CAAC,cAAc,CAAC;YACvB,OAAO,EAAE,iCAAiC;SAC3C,CAAC,CACH,CAAC;IACJ,CAAC;IAED,MAAM,cAAc,GAAG,wBAAwB,EAAE,CAAC;IAClD,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QAC7C,OAAO,GAAG,CACR,sBAAS,CAAC,cAAc,CAAC;YACvB,OAAO,EAAE,eAAe,MAAM,0CAA0C,OAAO,CAAC,MAAM,IAAI;SAC3F,CAAC,CACH,CAAC;IACJ,CAAC;IAED,IAAI,CAAC;QACH,GAAG,CAAC,MAAM,GAAG,CAAC,MAAM,oBAAoB,CAAC;YACvC,MAAM;YACN,OAAO;YACP,OAAO,EAAE,yBAAW,CAAC,gBAAgB;SACtC,CAAC,CAAS,CAAC;IACd,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,GAAG,CAAC,KAAK,CAAC,CAAC;IACpB,CAAC;IAED,OAAO,GAAG,EAAE,CAAC;AACf,CAAC","sourcesContent":["import type { JsonRpcEngineEndCallback } from '@metamask/json-rpc-engine';\nimport type { PermittedHandlerExport } from '@metamask/permission-controller';\nimport { rpcErrors } from '@metamask/rpc-errors';\nimport type {\n  InvokeKeyringParams,\n  InvokeKeyringResult,\n  InvokeSnapParams,\n} from '@metamask/snaps-sdk';\nimport type { Snap, SnapRpcHookArgs } from '@metamask/snaps-utils';\nimport { HandlerType, WALLET_SNAP_PERMISSION_KEY } from '@metamask/snaps-utils';\nimport type {\n  PendingJsonRpcResponse,\n  Json,\n  JsonRpcRequest,\n} from '@metamask/utils';\nimport { hasProperty } from '@metamask/utils';\n\nimport { getValidatedParams } from './invokeSnapSugar';\nimport type { MethodHooksObject } from '../utils';\n\nconst hookNames: MethodHooksObject<InvokeKeyringHooks> = {\n  hasPermission: true,\n  handleSnapRpcRequest: true,\n  getSnap: true,\n  getAllowedKeyringMethods: true,\n};\n\n/**\n * `wallet_invokeKeyring` gets the requester's permitted and installed Snaps.\n */\nexport const invokeKeyringHandler: PermittedHandlerExport<\n  InvokeKeyringHooks,\n  InvokeSnapParams,\n  InvokeKeyringResult\n> = {\n  methodNames: ['wallet_invokeKeyring'],\n  implementation: invokeKeyringImplementation,\n  hookNames,\n};\n\nexport type InvokeKeyringHooks = {\n  hasPermission: (permissionName: string) => boolean;\n\n  handleSnapRpcRequest: ({\n    snapId,\n    handler,\n    request,\n  }: Omit<SnapRpcHookArgs, 'origin'> & { snapId: string }) => Promise<unknown>;\n\n  getSnap: (snapId: string) => Snap | undefined;\n\n  getAllowedKeyringMethods: () => string[];\n};\n\n/**\n * The `wallet_invokeKeyring` method implementation.\n * Invokes onKeyringRequest if the snap requested is installed and connected to the dapp.\n *\n * @param req - The JSON-RPC request object.\n * @param res - The JSON-RPC response object.\n * @param _next - The `json-rpc-engine` \"next\" callback. Not used by this\n * function.\n * @param end - The `json-rpc-engine` \"end\" callback.\n * @param hooks - The RPC method hooks.\n * @param hooks.handleSnapRpcRequest - Invokes a snap with a given RPC request.\n * @param hooks.hasPermission - Checks whether a given origin has a given permission.\n * @param hooks.getSnap - Gets information about a given snap.\n * @param hooks.getAllowedKeyringMethods - Get the list of allowed Keyring\n * methods for a given origin.\n * @returns Nothing.\n */\nasync function invokeKeyringImplementation(\n  req: JsonRpcRequest<InvokeKeyringParams>,\n  // `InvokeKeyringResult` is an alias for `Json` (which is the default type\n  // argument for `PendingJsonRpcResponse`), but that may not be the case in the\n  // future. We use `InvokeKeyringResult` here to make it clear that this is the\n  // expected type of the result.\n  // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-arguments\n  res: PendingJsonRpcResponse<InvokeKeyringResult>,\n  _next: unknown,\n  end: JsonRpcEngineEndCallback,\n  {\n    handleSnapRpcRequest,\n    hasPermission,\n    getSnap,\n    getAllowedKeyringMethods,\n  }: InvokeKeyringHooks,\n): Promise<void> {\n  let params: InvokeSnapParams;\n  try {\n    params = getValidatedParams(req.params);\n  } catch (error) {\n    return end(error);\n  }\n\n  // We expect the MM middleware stack to always add the origin to requests\n  const { origin } = req as JsonRpcRequest & { origin: string };\n  const { snapId, request } = params;\n\n  if (!origin || !hasPermission(WALLET_SNAP_PERMISSION_KEY)) {\n    return end(\n      rpcErrors.invalidRequest({\n        message: `The snap \"${snapId}\" is not connected to \"${origin}\". Please connect before invoking the snap.`,\n      }),\n    );\n  }\n\n  if (!getSnap(snapId)) {\n    return end(\n      rpcErrors.invalidRequest({\n        message: `The snap \"${snapId}\" is not installed. Please install it first, before invoking the snap.`,\n      }),\n    );\n  }\n\n  if (!hasProperty(request, 'method') || typeof request.method !== 'string') {\n    return end(\n      rpcErrors.invalidRequest({\n        message: 'The request must have a method.',\n      }),\n    );\n  }\n\n  const allowedMethods = getAllowedKeyringMethods();\n  if (!allowedMethods.includes(request.method)) {\n    return end(\n      rpcErrors.invalidRequest({\n        message: `The origin \"${origin}\" is not allowed to invoke the method \"${request.method}\".`,\n      }),\n    );\n  }\n\n  try {\n    res.result = (await handleSnapRpcRequest({\n      snapId,\n      request,\n      handler: HandlerType.OnKeyringRequest,\n    })) as Json;\n  } catch (error) {\n    return end(error);\n  }\n\n  return end();\n}\n"]}