In recent discussions on the Telegram Dev Channel, a common question has emerged: "How can I track the outcome of a transaction sent on the TON blockchain?" Developers also seek clarity on interpreting the Boc (Bag of Cells) returned by TonClient and extracting actionable insights. This guide demystifies TON transactions, offering practical steps to monitor results and leverage TonClient effectively.
How TON Transactions Work
A TON transaction comprises three core components:
- Inbound Message: Initiates the contract (e.g., transfer request).
- Contract Actions: Updates to storage or logic triggered by the message.
- Outbound Messages: Notifications or further instructions sent to other contracts.
👉 Explore TON blockchain fundamentals
For example, transferring Toncoin involves sending a message to a wallet contract, which executes the transfer based on the message's payload.
Crafting a Transaction Message
To send a transaction via TonConnect, define a valid message using the JavaScript SDK. Here’s the structure:
interface SendTransactionRequest {
validUntil: number; // Deadline in Unix epoch seconds.
network?: CHAIN; // Mainnet or testnet.
messages: {
address: string; // Recipient address.
amount: string; // Amount in nanoTon.
payload?: string; // Optional contract-specific data.
}[];
}Example: Simple Transfer
const transaction = {
validUntil: Math.floor(Date.now() / 1000) + 600, // 10-minute validity.
messages: [{
address: "0:412410771DA82CBA...", // Recipient.
amount: "20000000", // 0.02 TON (in nanoTon).
}],
};Adding a Transaction Comment
TON comments require a Base64-encoded payload:
import { beginCell } from "@ton/ton";
const body = beginCell()
.storeUint(0, 32) // Comment identifier.
.storeStringTail("Hello, TON!") // Comment text.
.endCell();
const transaction = {
messages: [{
payload: body.toBoc().toString("base64"), // Include in payload.
}],
};Tracking Transaction Results
After sending a transaction via TonConnect, you receive a SendTransactionResponse containing a Boc:
const [tonConnectUi] = useTonConnectUI();
const { boc } = await tonConnectUi.sendTransaction(transaction);Confirming Transaction Completion
Use TonClient to poll for transaction status. Compare the inbound message hash with your Boc to verify execution:
const waitForTransaction = async (options, client) => {
const { hash, address } = options;
const walletAddress = Address.parse(address);
const state = await client.getContractState(walletAddress);
if (state?.lastTransaction) {
const { lt: lastLt, hash: lastHash } = state.lastTransaction;
const lastTx = await client.getTransaction(walletAddress, lastLt, lastHash);
const msgCell = beginCell().store(storeMessage(lastTx.inMessage)).endCell();
const inMsgHash = msgCell.hash().toString("base64");
if (inMsgHash === hash) return lastTx; // Transaction confirmed!
}
return null;
};👉 Learn advanced TonClient techniques
Key Takeaways
- Message-Based Design: TON’s asynchronous model requires tracking message hashes for confirmation.
- Boc Utility: The returned Boc contains critical transaction metadata.
- Monitoring Tools: Use
getContractStateandgetTransactionto verify on-chain execution.
For a live demo, check out this GitHub repository.
FAQ Section
Q1: How long does a TON transaction take to confirm?
A1: Typically seconds, but network congestion may cause delays. Polling intervals of 1–2 seconds are recommended.
Q2: Can I retrieve a transaction without the Boc?
A2: Yes, query the recipient’s address for recent transactions, but matching via Boc ensures accuracy.
Q3: What if my transaction fails?
A3: Verify the message format and sufficient gas. Use TonClient’s error logs for debugging.
Q4: How do I handle comments in transactions?
A4: Encode the text as a Base64 payload with a 32-bit header (storeUint(0, 32)).
Q5: Is TonClient compatible with testnet?
A5: Yes, specify network: CHAIN.TESTNET in your request.
By mastering these concepts, you’ll streamline TON dApp development and enhance user experiences. For updates, follow 0xAllenDev on X.