TON SDK Frontend Integration
TON differs fundamentally from the EVM ecosystem — a different account model (every contract is a separate cell with its own code and data), asynchronous message delivery between contracts, and Cell-based serialization instead of ABI. Before integrating TON SDK into your frontend, it's important to understand this difference, otherwise the application behavior will seem illogical.
Toolkit Stack
Main libraries for frontend:
-
@ton/ton— main SDK for blockchain interaction (reading state, sending messages) -
@ton/core— primitives: Cell, Address, Builder, Slice -
@tonconnect/sdk/@tonconnect/ui-react— wallet connection standard (TON equivalent of WalletConnect)
TonConnect is the de facto standard. Supported by Tonkeeper, MyTonWallet, Telegram Wallet, and dozens of others. Don't invent your own connection protocol.
Wallet Connection via TonConnect
import { TonConnectUI } from '@tonconnect/ui-react';
// Initialization (manifestUrl is required)
const tonConnectUI = new TonConnectUI({
manifestUrl: 'https://yourdomain.com/tonconnect-manifest.json',
});
// Connect
await tonConnectUI.connectWallet();
const wallet = tonConnectUI.wallet;
const userAddress = wallet?.account.address; // raw form: 0:abc...
The tonconnect-manifest.json file describes your application — name, icon, URL. The wallet shows it to the user when requesting connection. Without a proper manifest at a public URL, connection doesn't work.
Sending Transactions
In TON, frontend doesn't send a transaction, it sends a message (external message) to the wallet contract. The wallet signs it and broadcasts to the network.
import { toNano } from '@ton/ton';
await tonConnectUI.sendTransaction({
validUntil: Math.floor(Date.now() / 1000) + 600,
messages: [
{
address: '0:contractAddress',
amount: toNano('0.05').toString(), // in nanotons
payload: buildPayload().toBoc().toString('base64'), // Cell in base64
},
],
});
payload is a Cell serialized to BOC (Bag of Cells). To interact with a specific contract, you need to know its TL-B schema and build the Cell manually via beginCell()...endCell().
Reading Contract State
import { TonClient, Address } from '@ton/ton';
const client = new TonClient({
endpoint: 'https://toncenter.com/api/v2/jsonRPC',
apiKey: 'YOUR_KEY',
});
const address = Address.parse('EQD...');
const result = await client.runMethod(address, 'get_wallet_data', []);
// Result — stack of values in TVM format
const balance = result.stack.readBigNumber();
For production, use your own toncenter or TON API from tonapi.io — the public endpoint has rate limiting and unstable performance under load.
Peculiarities That Surprise EVM Developers
A transaction in TON doesn't finalize instantly — between sending and contract execution, several seconds pass, and chains of inter-contract messages unfold asynchronously. To confirm execution has happened, you need to poll the account's transaction history, not just wait for a receipt like in Ethereum.







