UNPKG

@rarible/estimate-middleware

Version:
120 lines (119 loc) 5.03 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.createEstimateGasMiddleware = void 0; const tslib_1 = require("tslib"); const json_rpc_engine_1 = require("json-rpc-engine"); const index_1 = require("@rarible/utils/bn/index"); const utils_js_1 = require("./utils.js"); /** * Creates async middleware for gas estimation if gas not defined * @param engine JsonRpcEngine to use for gas estimation * @param force set true if estimate tx even if gas is provided */ function createEstimateGasMiddleware(engine, force = false, threshold = 1.03, multiplier = 2) { return (0, json_rpc_engine_1.createAsyncMiddleware)((req, res, next) => tslib_1.__awaiter(this, void 0, void 0, function* () { if (req.method === "eth_subscribe") { res.error = new utils_js_1.RpcError("Notifications not supported", -32000); return next(); } if (req.method === "eth_sendTransaction") { try { const params = getTransactionParams(req); if (force || !params.gas) { const gasLimitResponse = yield engine.handle({ jsonrpc: "2.0", id: (0, json_rpc_engine_1.getUniqueId)(), params: [getEstimateParams(params)], method: "eth_estimateGas", }); const limitRaw = handleHexResponse(gasLimitResponse); if (limitRaw) { const limitHex = extractHex(limitRaw); const multiplied = (0, index_1.toBn)(limitHex, 16).multipliedBy(threshold).toFixed(0); params["gas"] = withPrefix((0, index_1.toBn)(multiplied).toString(16)); } const maxPriorityFeePerGasResponse = yield engine.handle({ jsonrpc: "2.0", id: (0, json_rpc_engine_1.getUniqueId)(), params: [], method: "eth_maxPriorityFeePerGas", }); const maxPriorityFeePerGasResponseRaw = handleHexResponse(maxPriorityFeePerGasResponse); const blockResponse = yield engine.handle({ jsonrpc: "2.0", id: (0, json_rpc_engine_1.getUniqueId)(), params: ["pending", false], method: "eth_getBlockByNumber", }); const baseFeeRaw = extractBaseFeePerGas(blockResponse); if (maxPriorityFeePerGasResponseRaw && baseFeeRaw) { if (params.gasPrice !== undefined) { delete params.gasPrice; } const baseFee = (0, index_1.toBn)(extractHex(baseFeeRaw), 16).multipliedBy(multiplier).toFixed(0); const maxPriorityFeePerGas = extractHex(maxPriorityFeePerGasResponseRaw); const maxFeePerGasHex = (0, index_1.toBn)(maxPriorityFeePerGas, 16).plus(baseFee).toString(16); params["maxPriorityFeePerGas"] = maxPriorityFeePerGasResponseRaw; params["maxFeePerGas"] = withPrefix(maxFeePerGasHex); } } } catch (error) { res.error = (0, utils_js_1.extractError)(error); } } return next(); })); } exports.createEstimateGasMiddleware = createEstimateGasMiddleware; function withPrefix(value) { return `0x${value}`; } function extractHex(value) { return value.startsWith("0x") ? value.substring(2) : value; } function handleHexResponse(response) { if (isJSONRpcResponse(response)) { if (response.error) { throw response.error; } if (typeof response.result === "string") { return response.result; } } throw new utils_js_1.RpcError("Can't handle JSON rpc response", -32700); } function extractBaseFeePerGas(response) { if (isJSONRpcResponse(response)) { if (response.error) { throw response.error; } if (typeof response.result === "object") { return response.result.baseFeePerGas; } } throw new utils_js_1.RpcError("Can't handle JSON rpc response", -32700); } function getTransactionParams(request) { if (request.params) { const [tx] = request.params; if (isSendParams(tx)) { return tx; } } throw new utils_js_1.RpcError("Can't parse eth_sendTransaction params", -32600); } function isJSONRpcResponse(x) { return typeof x === "object" && x !== null && "jsonrpc" in x && "id" in x; } function isSendParams(x) { return typeof x === "object" && x !== null && "to" in x; } function getEstimateParams(params) { return { to: params.to, data: params.data, value: params.value, from: params.from, }; }