A trace expands a single transaction into a tree of all triggered calls, including intermediate contract executions, fees, and message flows across accounts. This recipe is useful for:
- Exchanges validating deposits end-to-end
- DApps debugging complex interactions (e.g., Jetton swaps, NFT mints)
- Explorers building a visual graph of what happened in a transaction
- Bridges indexing trace finality to confirm cross-chain settlement consistency
The examples use the public Ton Center endpoint:For production, request your own API key and use a dedicated endpoint for higher rate limits and stability.
Understanding Traces
A trace represents the complete on-chain execution flow of a transaction. It shows every step that occurred as the message propagated through the network—covering all internal calls, fees, and resulting state changes. In other words, it provides:- the full call chain (incoming -> outgoing -> nested calls),
- all intermediate transactions involved,
- state updates and fees for each phase,
- bounce behavior and exit codes indicating success or failure.
Emulation vs. On-chain Trace
While traces show what actually happened, trace emulation predicts what would happen if a message were processed at the current network state. Emulation is typically used before sending a transaction to:- estimate whether it will succeed or fail,
- preview gas consumption and expected actions,
- simulate complex interactions like swaps or NFT mints.
Workflow tip
- Before sending: emulate to check success, cost, and side effects.
- After confirmation: fetch the on-chain trace to verify final behavior and outcomes.
How to obtain the transaction hash
You need a transaction hash (or a normalized external-in hash) to fetch a trace.- From a block explorer like tonviewer.com or tonscan.org (copy the tx hash from the UI).
- From Ton Center APIs that return transactions.
- If you start from an external-in (e.g., sent through TON Connect), compute the normalized external-in hash per [TEP-467] and locate the resulting transaction. See the dedicated guide for message lookup.
- compute the normalized hash of the external-in,
- page through the destination account’s history,
- match the transaction by comparing the normalized input message.
Fetching and Analyzing Traces
1. Fetch a trace by transaction hash
/traces with that hash.
2. Understanding the response
A trace response has three layers:- Trace envelope (per trace):
trace_id: identifier for this end-to-end trace.external_hash(optional): normalized hash of the originating external-in (if any).mc_seqno_start,mc_seqno_end: masterchain boundaries in which the trace executed.start_lt/end_lt,start_utime/end_utime: logical times and timestamps for the trace window.trace_info: summary objecttrace_state: e.g.complete/incomplete- counters:
messages,transactions,pending_messages classification_state: internal/heuristic classification state (provider-specific)
is_incomplete:truewhen some sub-messages are still pending (e.g., delayed/IHR paths).
- Trace tree (
trace):
- A root node
{ tx_hash, in_msg_hash, children[] }. - Children recursively enumerate sub-transactions spawned by out-messages.
- Transactions map (
transactions) and order (transactions_order):
transactionsis a hash -> transaction dictionary giving full details for each tx in the tree.transactions_orderoffers a deterministic ordering for UI rendering.
account,hash,lt,now,mc_block_seqno- Phases under
description:storage_ph: storage fee collection and status changecredit_ph: inbound value credit (if any)compute_ph: VM execution info (success,exit_code,gas_used,vm_steps, etc.)action: actions taken, msgs_created, fwd fees, result_code
in_msg: the inbound message (fields likesource,destination,value,opcode,bounce,message_content, etc.)out_msgs: array of messages produced by this txaccount_state_before/account_state_after: balance, code/data hashes, status transitionsemulated: whether this record was emulated (for real on-chain traces this isfalse)
Full output example
Full output example
Output for transaction hash
Vy11B+AiGGrDBcGx3UiUFUJozUQ3U2yHvaATSrS03og=:- External -> 0:9B14…27D1 : 0 — the trace starts from an external-in with 0 nanotons attached.
- 0:9B14…27D1 -> 0:52D7…1C77 : 565,276,000 — value forwarded to a contract.
- 0:52D7…1C77 -> 0:1C22…8E34 : 547,800,000 — the contract performs a sub-transfer.
- 0:1C22…8E34 -> 0:8524…283A : 543,800,000 (100 Telegram Stars) — main action.
- 0:52D7…1C77 -> 0:F9BC…94A1 : 4,350,400 (Fee) — processing fee path.
- 0:52D7…1C77 -> 0:7D87…5E19 : 6,525,600 — small commission/auxiliary payout.
compute_ph.successandexit_codeto confirm execution success.action.msgs_createdand each message’sbounce/bouncedflags.total_fees,gas_usedfor cost analysis.account_state_*to verify code/data and balance deltas.
| Field | Where | Why it matters |
|---|---|---|
trace_id | root | Stable identifier for correlating logs/UX to one end-to-end execution. |
external_hash | root | Binds the trace back to the normalized external-in; use for UX linking from TON Connect flows. |
trace_info.trace_state | root | complete vs incomplete; incomplete means some sub-messages may still be in flight—poll again. |
is_incomplete | root | Boolean shortcut for the above. Useful for retry logic. |
transactions_order | root | Deterministic order to render steps in a UI/timeline. |
mc_seqno_start/end | root | Masterchain boundaries; handy for indexing and cross-provider reconciliation. |
start_lt/end_lt, start_utime/end_utime | root | Time/ordering window for analytics and SLA metrics. |
compute_ph.exit_code | transaction.description | Primary success/failure code for VM execution. Non-zero indicates an error. |
compute_ph.success | transaction.description | Quick boolean for UI badges/alerts. |
compute_ph.gas_used / gas_fees | transaction.description | Cost analysis and anomaly detection. |
action.msgs_created | transaction.description | How many outgoing messages (children) were produced from this step. |
action.total_fwd_fees / total_action_fees | transaction.description | Forwarding + action fees; useful for fee breakdowns. |
in_msg.bounce / bounced | transaction.in_msg | Detect bounced paths and failed deliveries. |
in_msg.opcode | transaction.in_msg | Classify calls (e.g., known method selectors) for analytics. |
out_msgs[].message_content.decoded | transaction.out_msgs | Human-readable comments/decoded payloads (when available) for UX tooltips. |
account_state_before/after.balance | transaction | Verify value flows and final balances. |
account_state_*.code_hash / account_state_*.data_hash | transaction | Detect contract upgrades or state changes across the trace. |
block_ref.seqno / mc_block_seqno | transaction | Precise anchoring in the chain for explorers/indexers. |
3. End-to-end flow
Below is a pragmatic end-to-end flow developers typically implement:- Create an external-in (e.g., via TON Connect).
- Emulate (optional but recommended) to anticipate success and costs.
- Send.
- Wait for inclusion using Message lookup (normalized hash).
- Trace the final transaction with
/tracesand render the call tree.
- JavaScript (fetch) – Trace by tx hash
- From external-in -> tx (Message lookup)
Troubleshooting
is_incomplete: true: some sub-messages were still pending at query time—poll again.- No trace found: the transaction may not be finalized or you’re using the wrong hash. If starting from an external-in, verify normalization and use the Message lookup flow.
- Bounced messages: look for
bounce: trueandbounced: truein message nodes; checkexit_codeandcompute_phfor the failing hop.