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
:true
when 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
):
transactions
is a hash -> transaction dictionary giving full details for each tx in the tree.transactions_order
offers 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.success
andexit_code
to confirm execution success.action.msgs_created
and each message’sbounce
/bounced
flags.total_fees
,gas_used
for 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: create -> emulate -> wait -> trace
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
/traces
and 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: true
andbounced: true
in message nodes; checkexit_code
andcompute_ph
for the failing hop. - High fees: inspect
gas_used
,total_fwd_fees
, andtotal_action_fees
indescription
.