UNPKG

deth

Version:

Ethereum node focused on Developer Experience

84 lines (83 loc) 3.23 kB
"use strict"; var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k]; result["default"] = mod; return result; }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const ts_essentials_1 = require("ts-essentials"); const async_mutex_1 = require("async-mutex"); const t = __importStar(require("io-ts")); const Either_1 = require("fp-ts/lib/Either"); const restless_1 = require("@restless/restless"); const errorHandler_1 = require("../errorHandler"); const debug_1 = __importDefault(require("debug")); const d = debug_1.default('deth:rpc'); const executionMutex = new async_mutex_1.Mutex(); const jsonRpcEnvelope = t.type({ jsonrpc: t.literal('2.0'), id: t.union([t.number, t.string]), method: t.string, params: t.any, }); function sanitizeRPCEnvelope() { return (_data, req) => { const result = jsonRpcEnvelope.decode(req.body); if (Either_1.isLeft(result)) { throw new errorHandler_1.IOTSError(result); } }; } exports.sanitizeRPCEnvelope = sanitizeRPCEnvelope; function sanitizeRPC(schema) { return (_data, req) => { const m = req.body.method; const rpcDescription = schema[m]; d(`--> RPC call ${m}`); d(`--> RPC call data ${JSON.stringify(req.body.params)}`); if (!rpcDescription) { throw new errorHandler_1.NotFoundHttpError([`RPC method: ${m} called with ${JSON.stringify(req.body.params)} not found`]); } const params = req.body.params; // we need to normalize empty arrays to undefineds const normalizedParams = Array.isArray(params) && params.length === 0 ? undefined : params; const res = rpcDescription.parameters.decode(normalizedParams); if (Either_1.isRight(res)) { return res.right; } throw new errorHandler_1.IOTSError(res); }; } exports.sanitizeRPC = sanitizeRPC; function executeRPC(executors) { return async (data, req) => { const method = req.body.method; const executor = executors[method]; ts_essentials_1.assert(executor, `Couldn't find executor for ${method}`); // @todo: NOTE currently we run RPC calls sequentially. This limits performance but solves concurrency issues. return executionMutex.runExclusive(async () => { return executor(data); }); }; } exports.executeRPC = executeRPC; function respondRPC(schema) { return (data, req) => { const method = req.body.method; const rpcDescription = schema[method]; d(`<-- RES: ${JSON.stringify(data)}`); ts_essentials_1.assert(rpcDescription, `Couldn't find rpc description for ${method}`); const result = rpcDescription.returns.encode(data); return restless_1.responseOf({ jsonrpc: '2.0', id: req.body.id, result: result, }); }; } exports.respondRPC = respondRPC;