UNPKG

@metamask/snaps-rpc-methods

Version:
152 lines 5.76 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.providerRequestHandler = void 0; const rpc_errors_1 = require("@metamask/rpc-errors"); const superstruct_1 = require("@metamask/superstruct"); const utils_1 = require("@metamask/utils"); const endowments_1 = require("../endowments/index.cjs"); // Read-only methods that are currently allowed for this RPC method. const METHOD_ALLOWLIST = Object.freeze([ 'eth_blockNumber', 'eth_call', 'eth_chainId', 'eth_coinbase', 'eth_estimateGas', 'eth_feeHistory', 'eth_gasPrice', 'eth_getBalance', 'eth_getBlockByHash', 'eth_getBlockByNumber', 'eth_getBlockTransactionCountByHash', 'eth_getBlockTransactionCountByNumber', 'eth_getCode', 'eth_getFilterChanges', 'eth_getFilterLogs', 'eth_getLogs', 'eth_getProof', 'eth_getStorageAt', 'eth_getTransactionByBlockHashAndIndex', 'eth_getTransactionByBlockNumberAndIndex', 'eth_getTransactionByHash', 'eth_getTransactionCount', 'eth_getTransactionReceipt', 'eth_getUncleByBlockHashAndIndex', 'eth_getUncleByBlockNumberAndIndex', 'eth_getUncleCountByBlockHash', 'eth_getUncleCountByBlockNumber', 'eth_getWork', 'eth_hashrate', 'eth_mining', 'eth_newBlockFilter', 'eth_newFilter', 'eth_newPendingTransactionFilter', 'eth_protocolVersion', 'eth_sendRawTransaction', 'eth_submitHashrate', 'eth_submitWork', 'eth_syncing', 'eth_uninstallFilter', 'net_listening', 'net_peerCount', 'net_version', 'web3_clientVersion', 'web3_sha3', ]); const hookNames = { hasPermission: true, getNetworkConfigurationByChainId: true, getNetworkClientById: true, }; exports.providerRequestHandler = { methodNames: ['snap_experimentalProviderRequest'], implementation: providerRequestImplementation, hookNames, }; const ProviderRequestParametersStruct = (0, superstruct_1.object)({ chainId: utils_1.CaipChainIdStruct, request: (0, superstruct_1.type)({ method: (0, superstruct_1.string)(), params: (0, superstruct_1.optional)(utils_1.JsonRpcParamsStruct), }), }); /** * The `snap_experimentalProviderRequest` method implementation. * * This RPC method lets Snaps make requests to MetaMask networks that are not currently selected in the UI. * * The RPC method requires the caller to have the endowment:ethereum-provider permission. * * NOTE: This implementation is experimental and may be removed or changed without warning. * * @param req - The JSON-RPC request object. * @param res - The JSON-RPC response object. * @param _next - The `json-rpc-engine` "next" callback. Not used by this * function. * @param end - The `json-rpc-engine` "end" callback. * @param hooks - The RPC method hooks. * @param hooks.hasPermission - Checks whether a given origin has a given permission. * @param hooks.getNetworkConfigurationByChainId - Get a network configuration for a given chain ID. * @param hooks.getNetworkClientById - Get a network client for a given ID. * @returns Nothing. */ async function providerRequestImplementation(req, // `ProviderRequestResult` is an alias for `Json` (which is the default type // argument for `PendingJsonRpcResponse`), but that may not be the case in the // future. We use `ProviderRequestResult` here to make it clear that this is // the expected type of the result. // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-arguments res, _next, end, { hasPermission, getNetworkConfigurationByChainId, getNetworkClientById, }) { if (!hasPermission(endowments_1.SnapEndowments.EthereumProvider)) { return end(rpc_errors_1.rpcErrors.methodNotFound()); } const { params } = req; try { const { chainId, request } = getValidatedParams(params); if (!METHOD_ALLOWLIST.includes(request.method)) { return end(rpc_errors_1.rpcErrors.methodNotFound()); } const parsedChainId = (0, utils_1.parseCaipChainId)(chainId); if (parsedChainId.namespace !== 'eip155') { return end(rpc_errors_1.rpcErrors.invalidParams({ message: 'Only EVM networks are currently supported.', })); } const numericalChainId = BigInt(parsedChainId.reference); const networkConfiguration = getNetworkConfigurationByChainId((0, utils_1.bigIntToHex)(numericalChainId)); if (!networkConfiguration) { return end(rpc_errors_1.rpcErrors.invalidParams({ message: 'The requested network is not available.', })); } const rpc = networkConfiguration.rpcEndpoints[networkConfiguration.defaultRpcEndpointIndex]; const networkClient = getNetworkClientById(rpc.networkClientId); const { provider } = networkClient; res.result = await provider.request(request); } catch (error) { return end(error); } return end(); } /** * Validate the method `params` and returns them cast to the correct * type. Throws if validation fails. * * @param params - The unvalidated params object from the method request. * @returns The validated updateInterface method parameter object. */ function getValidatedParams(params) { try { return (0, superstruct_1.create)(params, ProviderRequestParametersStruct); } catch (error) { if (error instanceof superstruct_1.StructError) { throw rpc_errors_1.rpcErrors.invalidParams({ message: `Invalid params: ${error.message}.`, }); } /* istanbul ignore next */ throw rpc_errors_1.rpcErrors.internal(); } } //# sourceMappingURL=experimentalProviderRequest.cjs.map