Интеграция с TON API
TON (The Open Network) — это не EVM. Прежде чем интегрировать, важно понять несколько вещей, которые ломают интуицию разработчика с EVM-бэкграундом: смарт-контракты написаны на FunC/Tact, адреса имеют два формата (raw и user-friendly), и каждый контракт — независимый actor с собственным хранилищем.
Выбор API
TON Center API — публичный RPC, бесплатный с лимитами (1 req/sec без ключа, 10 req/sec с ключом). Достаточно для прототипа.
TON Console (tonconsole.com) — платный API с более высокими лимитами, SDK, webhooks. Production стандарт.
TonWeb (tonweb npm пакет) и @ton/ton (официальный SDK) — основные клиентские библиотеки.
Работа с адресами
TON адреса существуют в трёх форматах:
import { Address } from "@ton/ton";
// Raw формат: workchain:hex
const raw = "0:abcdef1234567890...";
// User-friendly: bounceable (для контрактов)
const bounceable = "EQCr..."; // начинается с EQ
// User-friendly: non-bounceable (для кошельков при первой отправке)
const nonBounceable = "UQCr..."; // начинается с UQ
const addr = Address.parse(bounceable);
console.log(addr.toRawString()); // 0:...
console.log(addr.toString()); // EQ...
console.log(addr.toString({ bounceable: false })); // UQ...
Критичный момент: при первой отправке TON на новый кошелёк нужно использовать non-bounceable адрес. Если кошелёк не существует и вы отправили на bounceable — монеты вернутся. Стандартная ошибка при интеграции.
Получение баланса
import { TonClient, Address } from "@ton/ton";
const client = new TonClient({
endpoint: "https://toncenter.com/api/v2/jsonRPC",
apiKey: process.env.TON_CENTER_API_KEY,
});
async function getTonBalance(address: string): Promise<bigint> {
const addr = Address.parse(address);
return client.getBalance(addr);
// Возвращает nanotons (1 TON = 1e9 nanotons)
}
// Для Jetton (TON токены) нужен другой подход — через Jetton wallet контракт
async function getJettonBalance(
ownerAddress: string,
jettonMasterAddress: string
): Promise<bigint> {
const master = client.open(JettonMaster.create(Address.parse(jettonMasterAddress)));
const walletAddress = await master.getWalletAddress(Address.parse(ownerAddress));
const wallet = client.open(JettonWallet.create(walletAddress));
const data = await wallet.getWalletData();
return data.balance;
}
Мониторинг транзакций
TON не имеет event logs как в Ethereum. Для мониторинга входящих платежей — polling списка транзакций адреса:
async function getTransactions(address: string, limit = 20) {
const response = await fetch(
`https://toncenter.com/api/v2/getTransactions?` +
`address=${address}&limit=${limit}&archival=true`,
{ headers: { "X-API-Key": process.env.TON_CENTER_API_KEY! } }
);
const { result } = await response.json();
return result;
}
// Новее — через TON API v3 (tonapi.io)
async function getIncomingPayments(address: string, afterLt?: string) {
const params = new URLSearchParams({
account: address,
limit: "50",
...(afterLt && { after_lt: afterLt }),
});
const response = await fetch(
`https://tonapi.io/v2/accounts/${address}/transactions?${params}`,
{ headers: { Authorization: `Bearer ${process.env.TONAPI_KEY}` } }
);
return response.json();
}
Logical Time (lt) в TON — аналог block number для сортировки транзакций. При polling сохраняем последний обработанный lt и запрашиваем только новые.
Отправка TON
import { WalletContractV4, internal } from "@ton/ton";
import { mnemonicToPrivateKey } from "@ton/crypto";
async function sendTon(toAddress: string, amount: bigint, comment?: string) {
const keyPair = await mnemonicToPrivateKey(process.env.MNEMONIC!.split(" "));
const wallet = WalletContractV4.create({
publicKey: keyPair.publicKey,
workchain: 0,
});
const contract = client.open(wallet);
const seqno = await contract.getSeqno();
await contract.sendTransfer({
secretKey: keyPair.secretKey,
seqno,
messages: [
internal({
to: toAddress,
value: amount, // в nanotons
bounce: false,
body: comment, // текстовый комментарий к переводу
}),
],
});
}
Webhooks через TON Console
Для production лучше webhooks, чем polling:
// Регистрация webhook в TON Console Dashboard
// POST https://console.tonconsole.com/api/v1/webhook
{
"url": "https://your-backend.com/webhooks/ton",
"accounts": ["EQCr..."], // адреса для мониторинга
"event_types": ["transaction"]
}
// Обработчик
app.post("/webhooks/ton", (req, res) => {
const { account, transactions } = req.body;
for (const tx of transactions) {
if (tx.in_msg && tx.in_msg.value > 0) {
// Входящий платёж
processPayment(account, tx.in_msg.value, tx.hash);
}
}
res.sendStatus(200);
});
Интеграция TON API для базового приёма платежей и мониторинга: 1–2 дня, включая тестирование на testnet (testnet.toncenter.com).







