How to turn TON transaction data into a reliable pending, processing, completed, or failed state for a STON.fi swap.
When a user signs a STON.fi swap, your application still has an important job to do: determine what actually happened on-chain.
On TON, that is not always as simple as waiting for one transaction hash. A swap can involve several contracts and internal messages, so the wallet transaction that starts the operation is only the beginning of the execution path. A blockchain indexer lets you locate that transaction, follow its trace, inspect the resulting actions, and turn low-level blockchain data into a useful swap status.
For a production integration, the safest approach is to separate two questions: Has the TON trace finished? and Did the STON.fi swap itself succeed?
Why one transaction hash is not enough
Developers coming from EVM networks often expect a swap to map neatly to one transaction. TON works differently.
A transaction on TON records a state change for one account. If that account sends internal messages to other contracts, those messages can trigger additional transactions. The related messages and transactions form a trace. Because TON uses asynchronous message processing, different parts of that trace may execute across different blocks.
A simplified STON.fi swap can therefore look conceptually like this:
- Your wallet sends the initiating message.
- The wallet transaction sends an internal message toward the swap contracts.
- Router and pool contracts process the request.
- Jetton wallets may process token transfers.
- The output asset reaches the destination wallet.
- Excess TON or other follow-up messages may also be processed.
The exact path depends on the swap and protocol version, but the monitoring lesson stays the same: finding the first transaction does not prove that the entire swap has completed successfully.
TON defines traces specifically to connect these causally related transactions and messages. An indexer makes those traces much easier to query than reconstructing them manually from raw node data.
What an indexer adds to swap tracking
An indexer continuously reads blockchain data, parses transactions and messages, and stores structured results in a query-friendly database.
TON Center API v3 is one example. TON documentation describes it as an indexed access layer that supports historical transactions, traces, decoded Jetton data, and higher-level actions. Its mainnet endpoint is https://toncenter.com/api/v3.
For a STON.fi integration, that gives you several useful capabilities:
- find the transaction associated with the message sent by the wallet
- retrieve the full trace related to that transaction
- see whether the trace is still incomplete
- inspect pending messages
- request classified actions when available
- recover historical status after a page reload or backend restart
This is much more useful than repeatedly asking whether a single account has a new transaction.
A good architecture treats the indexer as an observation layer. Your application stores the swap identifiers, queries indexed blockchain state, and then maps the returned data into a much smaller set of statuses that make sense to the person waiting for the swap.
Build a status model for your application
Do not expose every low-level TON state directly to the UI. Define your own swap lifecycle instead.
| Application status | What you know | Typical evidence |
|---|---|---|
| Submitted | Wallet accepted the request | TON Connect returned the outgoing message BoC |
| Locating | Message was sent, but the indexed transaction is not available yet | No matching indexed transaction yet |
| Processing | Initial transaction exists and the trace is still progressing | Trace is incomplete or still has pending messages |
| Verifying | Trace is complete, but the protocol outcome still needs interpretation | Complete trace and available actions |
| Succeeded | Swap completed with the expected protocol result | Successful STON.fi swap status or validated swap action |
| Failed | Execution completed without a successful swap result | Failed or aborted protocol action, refund path, or other terminal failure |
The key distinction is between trace completion and swap success.
An indexer can tell you that the chain of messages has stopped progressing. It does not automatically mean your application's intended business operation succeeded. For a STON.fi swap, you should also interpret STON.fi-specific data rather than relying only on a generic transaction success flag.
Start with the message returned by TON Connect
After a user signs through TON Connect, sendTransaction() returns a serialized external message as a BoC.
That BoC is a useful tracking anchor, but TON recommends using the normalized hash of the external message for message lookup. Normalization exists because equivalent external messages can otherwise have different hashes depending on serialization details. TON documents the normalization rules in its TON Connect message lookup guide and notes that normalized message lookup is supported by many providers.
A shortened TypeScript version follows the same approach:
import {
beginCell,
Cell,
loadMessage,
storeMessage,
} from "@ton/core";
function getNormalizedHash(boc: string): string {
const message = loadMessage(
Cell.fromBase64(boc).beginParse()
);
if (message.info.type !== "external-in") {
throw new Error("Expected an external-in message");
}
const normalized = {
...message,
init: null,
info: {
...message.info,
src: undefined,
importFee: 0n,
},
};
return beginCell()
.store(storeMessage(normalized, { forceRef: true }))
.endCell()
.hash()
.toString("hex");
}
Save this tracking identifier with the swap record in your backend.
Do not depend on React component state alone. If the user closes the tab immediately after signing, you still want to be able to reconstruct the operation later.
Your stored swap record might contain:
- wallet address
- normalized external message hash
- STON.fi router used for the swap
- input and output assets
- expected output or minimum output
- STON.fi query ID when available
- creation time
- your current application status
Those fields give you enough context to recover after temporary API failures or user disconnects.
Follow the transaction into its trace
Once you know the transaction hash, TON Center API v3 can retrieve a trace with GET /traces.
The endpoint supports filters including trace_id, tx_hash, and msg_hash. You can also request classified actions with include_actions=true. The returned trace data includes fields such as is_incomplete, transaction information, actions, and trace metadata.
A simple backend request can look like this:
async function getTrace(txHash: string) {
const url = new URL(
"https://toncenter.com/api/v3/traces"
);
url.searchParams.append("tx_hash", txHash);
url.searchParams.set("include_actions", "true");
const response = await fetch(url, {
headers: {
"X-API-Key": process.env.TONCENTER_API_KEY!,
},
});
if (!response.ok) {
throw new Error(
`Indexer returned ${response.status}`
);
}
return response.json();
}
Keep API keys on the server. TON Center accepts API keys through the X-API-Key header, and its documentation explicitly recommends not exposing them in client-side applications or public repositories.
Your first status function can remain deliberately simple:
function getTraceState(data: any) {
const trace = data.traces?.[0];
if (!trace) {
return "locating";
}
if (
trace.is_incomplete ||
(trace.trace_info?.pending_messages ?? 0) > 0
) {
return "processing";
}
return "verifying";
}
Notice that the final state is verifying, not succeeded.
That extra step prevents one of the most common monitoring mistakes: treating a completed trace as proof that the desired swap completed.
Verify the STON.fi result, not only TON execution
STON.fi provides protocol-specific APIs that are useful once you need to interpret what happened.
The current STON.fi DEX API documents:
-
GET /v1/swap/statusfor checking a swap using router address, owner address, and query ID -
POST /v1/transaction/queryfor resolving a transaction from identifiers such as wallet address plus query ID or an external message hash -
POST /v1/transaction/action_treefor obtaining STON.fi actions and their statuses from an originating transaction
The API base URL is https://api.ston.fi.
These endpoints solve a different problem from a generic TON indexer.
The indexer answers:
What transactions and messages happened on TON?
STON.fi-specific decoding answers:
What did those transactions mean for this swap?
For a direct STON.fi DEX integration, combining both gives you a stronger status pipeline:
TON Connect
|
v
External message
|
v
Indexer finds transaction
|
v
Indexer follows TON trace
|
v
Trace completes
|
v
STON.fi status or action verification
|
+--> succeeded
|
+--> failed / aborted / recovery path
This also makes debugging much easier. If your UI says that a swap failed, you can distinguish between "the initiating transaction was never found", "the TON trace is still executing", and "execution completed but the swap did not produce the intended result."
What changes when the swap uses Omniston?
Do not confuse generic indexer tracking with Omniston's own trade tracking interface.
For Omniston swaps, STON.fi provides trackTrade functionality through its SDKs and the underlying trade.track API. Tracking uses the quote ID, trader wallet address, and outgoing transaction hash. Omniston can report states such as waiting for the initial transfer, transferring, swapping, receiving funds, and a final settled trade result.
If you are already building with the Omniston SDK, its native trade tracker should usually be your primary protocol-level status source.
An indexer is still valuable for:
- independent on-chain verification
- debugging failed or unusual traces
- rebuilding state after an application restart
- storing your own transaction history
- linking protocol status to raw TON transactions
The two approaches complement each other. They are not competing definitions of the same status.
Polling or streaming?
Polling is usually the easiest starting point.
After submission, poll quickly while the swap is active, then reduce the frequency after several unsuccessful attempts. Stop polling once you reach a terminal state. Add a maximum tracking window, but do not automatically classify a temporary timeout as an on-chain failure.
For faster interfaces, TON Center also provides a Streaming API using SSE and WebSockets. It can stream transactions, actions, and traces with pending, confirmed, and finalized finality levels. TON documentation warns that the streaming API does not replay events missed during a connection interruption, so applications that require complete state should resynchronize from API v3 after reconnecting.
A practical production pattern is therefore:
stream for responsiveness, query the indexer for recovery and truth reconstruction.
A practical STON.fi tracking checklist
Before shipping your status component, test more than the happy path.
Check that your application can recover a swap after a browser refresh, distinguish "not indexed yet" from "failed", follow the complete trace instead of only the wallet transaction, and validate the STON.fi-level result before displaying success.
Also store enough identifiers to investigate a transaction later. A wallet address by itself is usually not a strong correlation key when the same wallet can initiate several swaps close together.
Most importantly, make your status names describe what you actually know. Processing is safer than Success while internal messages are still active, and Verifying is safer than assuming every completed TON trace represents a completed swap.
Frequently Asked Questions
What is an indexer in TON?
An indexer reads blockchain data, parses transactions and messages, and stores them in a database optimized for queries. TON Center API v3 is an indexed API that supports traces, historical transactions, actions, Jetton data, and other structured information that is harder to obtain efficiently from raw node access.
Why can a STON.fi swap involve multiple transactions?
TON smart contracts communicate asynchronously through messages. One transaction processes a message for one account, and that account may send messages that trigger transactions on other accounts. A DEX operation can therefore become a trace containing wallet, router, pool, and token-related transactions rather than one monolithic transaction.
Does finding the wallet transaction mean the swap succeeded?
No. It proves that the initiating message was processed, not necessarily that the entire swap completed successfully. Follow the resulting trace and then verify the protocol-level swap result before showing a final success state.
What should I store after sending the swap?
Store a stable correlation record containing the wallet address, tracking hash or transaction identifier, swap creation time, and STON.fi-specific identifiers such as the query ID or router when your integration provides them. This lets your backend reconstruct status even if the frontend disappears.
Should I poll an indexer continuously?
Only while the operation is unresolved. Poll relatively frequently immediately after submission, then apply backoff. Once the swap reaches a terminal state, stop. For higher responsiveness, use streaming notifications while retaining historical polling as a recovery mechanism.
Can I use the STON.fi API instead of a TON indexer?
For some status questions, yes. STON.fi exposes swap status, transaction query, and transaction action-tree endpoints that understand STON.fi operations. A generic TON indexer is still useful when you need raw trace visibility, independent verification, historical analysis, or debugging outside STON.fi-specific abstractions.
How should I track an Omniston swap?
Use Omniston's native trade tracking when possible. Its SDK tracking accepts the quote ID, trader wallet address, and outgoing transaction hash and provides trade-specific lifecycle information. A TON indexer can then serve as an additional on-chain verification and debugging layer.
What is the safest way to display STON.fi swap status?
Use several stages rather than jumping directly from "sent" to "success": record the wallet submission, locate the transaction, wait for the trace to finish, and then verify the STON.fi-specific outcome. That model reflects TON's asynchronous execution much more accurately and produces a status UI that remains useful when something goes wrong.
Sources and Further Reading
- STON.fi DEX API Reference - official REST endpoints for swap status, transaction resolution, and STON.fi action trees
- STON.fi Omniston Swap Overview - official description of Omniston swap execution and the
trade.tracklifecycle - STON.fi Omniston React SDK - official SDK guidance for tracking an initiated Omniston trade
- TON Center API v3 Overview - official description of TON's indexed API layer and available trace and action endpoints
- TON Center Get Traces - official reference for querying traces by transaction, message, or trace identifiers
- TON Connect Message Lookup - official guidance for identifying transactions from messages returned after wallet submission
- TON Traces - explanation of how related messages and transactions form a TON execution trace
- TON Center Streaming API - official documentation for real-time transaction, action, and trace monitoring






Top comments (1)
Hi! If you find an error, please let me know in the comments! Help others who are also looking into this issue! Thank you so much for your support!