UNPKG

@metamask/snaps-rpc-methods

Version:
1 lines 7.19 kB
{"version":3,"file":"invokeKeyring.mjs","sourceRoot":"","sources":["../../src/permitted/invokeKeyring.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,SAAS,EAAE,6BAA6B;AAMjD,OAAO,EAAE,WAAW,EAAE,0BAA0B,EAAE,8BAA8B;AAEhF,OAAO,EAAE,WAAW,EAAE,wBAAwB;AAE9C,OAAO,EAAE,kBAAkB,EAAE,8BAA0B;AAQvD,MAAM,SAAS,GAAgD;IAC7D,wBAAwB,EAAE,IAAI;CAC/B,CAAC;AAgBF;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG;IAClC,cAAc,EAAE,2BAA2B;IAC3C,SAAS;IACT,WAAW,EAAE;QACX,oCAAoC;QACpC,8BAA8B;QAC9B,wBAAwB;KACzB;CAOF,CAAC;AAEF;;;;;;;;;;;;;;GAcG;AACH,KAAK,UAAU,2BAA2B,CACxC,GAAkD;AAClD,0EAA0E;AAC1E,8EAA8E;AAC9E,8EAA8E;AAC9E,+BAA+B;AAC/B,4EAA4E;AAC5E,GAAgD,EAChD,KAAc,EACd,GAA6B,EAC7B,EAAE,wBAAwB,EAA4B,EACtD,SAAwD;IAExD,IAAI,MAAwB,CAAC;IAC7B,IAAI,CAAC;QACH,MAAM,GAAG,kBAAkB,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IAC1C,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,GAAG,CAAC,KAAK,CAAC,CAAC;IACpB,CAAC;IAED,MAAM,EAAE,MAAM,EAAE,GAAG,GAAG,CAAC;IACvB,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,CAAC;IAEnC,IACE,CAAC,MAAM;QACP,CAAC,SAAS,CAAC,IAAI,CACb,oCAAoC,EACpC,MAAM,EACN,0BAA0B,CAC3B,EACD,CAAC;QACD,OAAO,GAAG,CACR,SAAS,CAAC,cAAc,CAAC;YACvB,OAAO,EAAE,aAAa,MAAM,0BAA0B,MAAM,6CAA6C;SAC1G,CAAC,CACH,CAAC;IACJ,CAAC;IAED,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,wBAAwB,EAAE,MAAM,CAAC,EAAE,CAAC;QACtD,OAAO,GAAG;QACR,4CAA4C;QAC5C,SAAS,CAAC,cAAc,CAAC;YACvB,OAAO,EAAE,aAAa,MAAM,2DAA2D;SACxF,CAAC,CACH,CAAC;IACJ,CAAC;IAED,IAAI,CAAC,WAAW,CAAC,OAAO,EAAE,QAAQ,CAAC,IAAI,OAAO,OAAO,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;QAC1E,OAAO,GAAG,CACR,SAAS,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,SAAS,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,SAAS,CAAC,IAAI,CAAC,8BAA8B,EAAE;YACjE,MAAM;YACN,MAAM;YACN,OAAO;YACP,OAAO,EAAE,WAAW,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 {\n JsonRpcEngineEndCallback,\n MethodHandler,\n} from '@metamask/json-rpc-engine';\nimport type { Messenger } from '@metamask/messenger';\nimport type { PermissionControllerHasPermissionAction } from '@metamask/permission-controller';\nimport { rpcErrors } from '@metamask/rpc-errors';\nimport type {\n InvokeKeyringParams,\n InvokeKeyringResult,\n InvokeSnapParams,\n} from '@metamask/snaps-sdk';\nimport { HandlerType, WALLET_SNAP_PERMISSION_KEY } from '@metamask/snaps-utils';\nimport type { PendingJsonRpcResponse, Json } from '@metamask/utils';\nimport { hasProperty } from '@metamask/utils';\n\nimport { getValidatedParams } from './invokeSnapSugar';\nimport type {\n JsonRpcRequestWithOrigin,\n SnapControllerGetSnapAction,\n SnapControllerHandleRequestAction,\n} from '../types';\nimport type { MethodHooksObject } from '../utils';\n\nconst hookNames: MethodHooksObject<InvokeKeyringMethodHooks> = {\n getAllowedKeyringMethods: true,\n};\n\nexport type InvokeKeyringMethodHooks = {\n /**\n * Get the list of allowed Keyring methods for a given origin.\n *\n * @returns The list of allowed Keyring methods.\n */\n getAllowedKeyringMethods: () => string[];\n};\n\nexport type InvokeKeyringMethodActions =\n | PermissionControllerHasPermissionAction\n | SnapControllerHandleRequestAction\n | SnapControllerGetSnapAction;\n\n/**\n * Invoke a keyring method of a Snap. This calls the `onKeyringRequest` handler\n * of the Snap.\n *\n * The Snap must be installed and the dapp must have permission to communicate\n * with the Snap, or the request is rejected. The dapp can install the Snap and\n * request permission to communicate with it using [`wallet_requestSnaps`](https://docs.metamask.io/snaps/reference/snaps-api/wallet_requestsnaps).\n */\nexport const invokeKeyringHandler = {\n implementation: invokeKeyringImplementation,\n hookNames,\n actionNames: [\n 'PermissionController:hasPermission',\n 'SnapController:handleRequest',\n 'SnapController:getSnap',\n ],\n} satisfies MethodHandler<\n InvokeKeyringMethodHooks,\n InvokeKeyringMethodActions,\n InvokeSnapParams,\n InvokeKeyringResult,\n { origin: 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.getAllowedKeyringMethods - Get the list of allowed Keyring\n * methods for a given origin.\n * @param messenger - The messenger used to call controller actions.\n * @returns Nothing.\n */\nasync function invokeKeyringImplementation(\n req: JsonRpcRequestWithOrigin<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 { getAllowedKeyringMethods }: InvokeKeyringMethodHooks,\n messenger: Messenger<string, InvokeKeyringMethodActions>,\n): Promise<void> {\n let params: InvokeSnapParams;\n try {\n params = getValidatedParams(req.params);\n } catch (error) {\n return end(error);\n }\n\n const { origin } = req;\n const { snapId, request } = params;\n\n if (\n !origin ||\n !messenger.call(\n 'PermissionController:hasPermission',\n origin,\n WALLET_SNAP_PERMISSION_KEY,\n )\n ) {\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 (!messenger.call('SnapController:getSnap', snapId)) {\n return end(\n // Mirror error message from SnapController.\n rpcErrors.invalidRequest({\n message: `The Snap \"${snapId}\" is not installed. Please install it before invoking it.`,\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 messenger.call('SnapController:handleRequest', {\n origin,\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"]}