UNPKG

viem-tracer

Version:

[![npm package][npm-img]][npm-url] [![Build Status][build-img]][build-url] [![Downloads][downloads-img]][downloads-url] [![Issues][issues-img]][issues-url] [![Commitizen Friendly][commitizen-img]][commitizen-url] [![Semantic Release][semantic-release-img]

113 lines (112 loc) 4.87 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.ExecutionRevertedTraceError = void 0; exports.traced = traced; const viem_1 = require("viem"); const format_1 = require("./format"); class ExecutionRevertedTraceError extends viem_1.BaseError { static code = 3; static nodeMessage = /execution reverted/; constructor(trace, message = "execution reverted for an unknown reason.") { super(message, { name: "ExecutionRevertedError", metaMessages: [trace], }); } } exports.ExecutionRevertedTraceError = ExecutionRevertedTraceError; /** * @description Overloads a transport intended to be used with a test client, to trace and debug transactions. */ function traced(transport, { all = false, next, failed = true, gas, raw } = {}) { // @ts-ignore: complex overload return (...config) => { const instance = transport(...config); instance.value = { ...instance.value, tracer: { all, next, failed, gas, raw }, }; return { ...instance, async request(args, options) { const { method, params } = args; if (method !== "eth_estimateGas" && method !== "eth_sendTransaction" && method !== "wallet_sendTransaction") return instance.request(args, options); const { tracer } = instance.value; // @ts-expect-error: params[0] is the rpc transaction request const tx = params[0]; const traceCall = async (message) => { const trace = await instance.request({ method: "debug_traceCall", params: [ tx, // @ts-expect-error: params[1] is either undefined or the block identifier params[1] || "latest", { // @ts-expect-error: params[2] may contain state and block overrides ...params[2], tracer: "callTracer", tracerConfig: { onlyTopCall: false, withLog: true, }, }, ], }, { retryCount: 0 }); return new ExecutionRevertedTraceError(await (0, format_1.formatFullTrace)(trace, tracer), message || trace.revertReason || trace.error); }; if (tracer.next || (tracer.next == null && tracer.all)) { try { console.log((await traceCall()).metaMessages[0]); } catch (error) { console.warn("Failed to trace transaction:"); console.trace(error); } } const res = await instance .request(args, options) .catch(async (error) => { if (tracer.next || (tracer.next == null && tracer.failed)) { const trace = await traceCall(error.details); trace.stack = error.stack; throw trace; } throw error; }) .finally(() => { tracer.next = undefined; }); if (method !== "eth_estimateGas") { let receipt = null; try { for (let i = 0; i < 720; i++) { receipt = await instance.request({ method: "eth_getTransactionReceipt", params: [res], }); if (receipt) break; await new Promise((resolve) => setTimeout(resolve, 250)); } if (!receipt) throw new viem_1.WaitForTransactionReceiptTimeoutError({ hash: res, }); if (receipt.status === "0x0") throw await traceCall(); } catch (error) { if (error instanceof ExecutionRevertedTraceError) throw error; console.warn("Failed to trace transaction:"); console.trace(error); } } return res; }, }; }; }