trace_transaction
https://api.triport.io/v1/polygonReturns the Parity-style call tree for a single already-mined Polygon transaction, identified by its hash.
trace_transaction replays one transaction that has already been included in a
block and returns its execution as a flat list of Parity-style trace frames —
one entry per internal call (call, create, suicide, reward), each tagged
with its position in the call tree. It is the most convenient method for
single-transaction forensic analysis: MEV path reconstruction, internal
token-transfer tracing, and revert diagnosis without having to pull and walk a
whole block.
Compared to its siblings, trace_transaction is the lightest of the
block-scoped trace methods — it returns only the frames for one transaction, so
it is far cheaper than trace_block (the full-block call
tree) or trace_replayBlockTransactions (full block replay with state diffs),
yet richer than eth_getTransactionReceipt, which gives you only the top-level
result and logs.
This is a trace-namespace (Parity) method available on the Pro tier and
above. It is rate limited per tier (3 RPS on Pro, 10 RPS on Business) with a
short burst allowance; there is no daily quota. If the hash does not correspond
to a mined transaction — unknown, or still pending in the mempool — the method
returns null rather than an error.
Parameters
One positional parameter.
txHashstringrequired0x-prefixed 32-byte hash of the transaction to trace. The transaction must already be mined into a block; pending or unknown hashes yield a null result.Response
The result is an array of trace frames, ordered by traceAddress (execution
order). A simple transfer plus one internal call looks like this:
For an unknown or pending transaction, the result is null:
{ "jsonrpc": "2.0", "id": 1, "result": null }actionobjectcall frame: callType (call, delegatecall, staticcall, callcode), from, to, gas, input, value. create frames carry init and creationMethod; suicide frames carry address, refundAddress, balance.resultobjectgasUsed, and output for calls or address/code for creates. Absent (replaced by error) when the frame failed.errorstringReverted, Out of gas.subtracesintegertraceAddressarray[0, 1]). Empty for the top-level call.typestringcall, create, suicide, or reward.blockHashstringblockNumberintegertransactionHashstringtxHash).transactionPositionintegerErrors
| Code | Meaning | When it happens |
|---|---|---|
-32002 | tier_insufficient | Your API key's tier is below Pro; this trace-namespace method is not enabled for it. The error.data carries current_tier, required_tier, method, category, and upgrade_url. |
-32003 | rate_limited | You exceeded your tier's request rate (3 RPS on Pro, 10 RPS on Business) including burst. Honor the Retry-After header / error.data.retry_after_sec and retry after a short back-off. |
Note that an unknown or pending transaction is not an error — it returns a
null result with HTTP 200. See the shared
error envelope reference for the full error object shape and
handling guidance.
Examples
JavaScript (fetch)
const res = await fetch("https://api.triport.io/v1/polygon", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.TRIPORT_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
jsonrpc: "2.0",
id: 1,
method: "trace_transaction",
params: ["0x3a1f2b9c8d7e6f5a4b3c2d1e0f9a8b7c6d5e4f3a2b1c0d9e8f7a6b5c4d3e2f1a"],
}),
});
const { result } = await res.json();
if (result === null) {
console.log("transaction not found (unknown or pending)");
} else {
console.log(`${result.length} trace frames`);
}TypeScript SDK (@triport/sdk)
import { Triport } from "@triport/sdk";
const triport = new Triport({ apiKey: process.env.TRIPORT_API_KEY! });
const frames = await triport.polygon.request("trace_transaction", [
"0x3a1f2b9c8d7e6f5a4b3c2d1e0f9a8b7c6d5e4f3a2b1c0d9e8f7a6b5c4d3e2f1a",
]);
for (const f of frames ?? []) {
console.log(f.type, f.traceAddress.join("."), f.action.from, "→", f.action.to);
}Python (triport-sdk)
import os
from triport import Triport
triport = Triport(api_key=os.environ["TRIPORT_API_KEY"])
frames = triport.polygon.request(
"trace_transaction",
["0x3a1f2b9c8d7e6f5a4b3c2d1e0f9a8b7c6d5e4f3a2b1c0d9e8f7a6b5c4d3e2f1a"],
)
if frames is None:
print("transaction not found (unknown or pending)")
else:
print(f"{len(frames)} trace frames")Notes
- Parity shape, not Geth.
trace_transactionreturns the flat Parity trace format (frames keyed bytraceAddress), which differs from the nestedcallTracertree returned by Geth-styledebugmethods. If your tooling expects the Geth shape, reach for thedebugnamespace instead; if you index both, normalise one format to the other. - Bor quirk. Polygon's Bor client can map a frame's
callTypeslightly differently from a vanilla Geth/Parity node (for examplecallvsdelegatecallfor proxy dispatch). Handle both when reconstructing call trees. nullmeans not found. Anullresult is the expected answer for a hash that is unknown or still pending — poll again once the transaction is mined rather than treating it as a failure.- Related methods. For the full call tree of every transaction in a block,
use
trace_block; for a range query across many blocks, usetrace_filter; to simulate a not-yet-sent transaction, usetrace_call. See the Polygon RPC overview for the full trace namespace.