Разработка TON-приложения
TON — один из немногих блокчейнов, где архитектура платформы фундаментально влияет на архитектуру приложения. Бесконечный шардинг, actor model, асинхронные сообщения — это не детали реализации, которые можно проигнорировать. Это ограничения, вокруг которых строится вся система. Разработчик, пришедший с EVM без погружения в TON-специфику, скорее всего получит приложение, которое работает на testnet и ломается на mainnet при параллельных запросах.
Архитектурная база: actor model и message passing
В TON каждый смарт-контракт — это actor. Он обрабатывает входящие сообщения последовательно, но разные контракты выполняются параллельно и независимо. Нет глобального состояния, нет synchronous call — только сообщения с задержкой в один или несколько блоков.
Это означает: атомарность сложных операций невозможна через цепочку синхронных вызовов. Вместо этого — паттерн commit-confirm-rollback:
- Контракт A фиксирует предварительное состояние (commit) и отправляет запрос контракту B
- B обрабатывает запрос и отправляет confirm или reject
- A получает ответ и финализирует или откатывает состояние
Bounce-сообщения — механизм, через который TON сигнализирует об ошибке при обработке. Если B вернул ошибку, сообщение «bounced» обратно к A. Без bounce-handler-а в контракте A потеряются средства или состояние разойдётся.
Смарт-контракты: FunC vs Tact, когда что
Для большинства компонентов приложения используем Tact — строгая типизация, встроенные проверки, читаемый синтаксис. Jetton (TEP-74 стандарт), NFT (TEP-62), кастомная бизнес-логика — всё это на Tact.
FunC оставляем для случаев, где важна максимальная оптимизация газа или нестандартная работа с cell layout. Контракты с высоким объёмом транзакций, где каждый nanoton газа имеет значение — кандидаты на FunC.
Стандартные токены (Jetton Minter + Jetton Wallet) деплоим на основе аудированных шаблонов TON Foundation — не изобретаем велосипед там, где стандарт закрывает задачу.
Газ и стоимость хранения
TON взимает плату за хранение данных в контракте (storage fee). Контракт, который накапливает данные без механизма очистки, в конце концов исчерпает баланс и «заморозится». Проектируем state контрактов с учётом этого: храним только то, что необходимо, используем шардирование данных через дочерние контракты (один контракт на пользователя — стандартный TON паттерн).
TON Connect: интеграция кошелька
TON Connect 2.0 — протокол подключения кошелька к dApp. Работает с Tonkeeper, MyTonWallet, Tonhub. Интеграция через @tonconnect/sdk или @tonconnect/ui-react (если React).
Типичная сессия: пользователь сканирует QR или кликает deeplink → кошелёк подтверждает соединение → dApp получает адрес и может отправлять запросы на подпись транзакций.
Нюанс: TON Connect передаёт транзакцию в кошелёк для подписи, но транзакция выполняется асинхронно. dApp не знает результат в момент подписи — нужен polling статуса транзакции через TON API или WebSocket-подписка на события контракта.
import { useTonConnectUI } from '@tonconnect/ui-react';
const [tonConnectUI] = useTonConnectUI();
const sendTransaction = async () => {
const result = await tonConnectUI.sendTransaction({
messages: [{
address: contractAddress,
amount: toNano('0.05').toString(),
payload: beginCell()
.storeUint(0x1234, 32) // op code
.storeAddress(userAddress)
.endCell()
.toBoc()
.toString('base64')
}]
});
// result содержит только boc подписанной транзакции
// статус нужно проверять отдельно
};
Backend и индексация событий
TON не имеет event log как в EVM. Транзакции и их результаты читаются через TON HTTP API (toncenter.com) или tonapi.io. Для production используем tonapi.io — более надёжный, rate limits выше, есть webhook-и.
Для сложной индексации (история операций пользователя, агрегированные данные) — собственный индексер на основе ton-index-worker или TON Index API. Данные пишем в PostgreSQL, API строим на Node.js/FastAPI.
Альтернатива — The Open Network Indexer (TONX) и GetBlock для managed индексации, если объём данных не требует кастомной логики.
Frontend: стек и особенности
React + TypeScript + wagmi не подходят для TON — это EVM-стек. Для TON используем:
- @ton/core — базовая работа с cells, addresses, builders
- @ton/ton — HTTP-клиент для TON API
- @tonconnect/ui-react — компоненты подключения кошелька
- tonweb — устаревший, но всё ещё встречается в проектах
Telegram Mini App (TMA) — отдельный контекст для TON. TMA работает внутри Telegram WebView, имеет доступ к Telegram user data и может открывать кошелёк через @telegram-apps/sdk. Это основной UX-паттерн для TON-приложений с массовой аудиторией.
Процесс разработки
Проектирование (3-5 дней). Рисуем message flow diagram — все контракты и сообщения между ними. Определяем storage model каждого контракта. Рассчитываем примерные storage fees на 1 год.
Разработка контрактов (1-2 недели). Tact/FunC, тесты через Blueprint + sandbox, покрываем bounce-сценарии.
Backend (1-2 недели). API, индексер, интеграция с TON API.
Frontend + TON Connect (1-2 недели). React / TMA, интеграция кошелька, polling транзакций.
Деплой и мониторинг. Контракты деплоятся через npx blueprint run, mainnet адреса фиксируются в репозитории. Мониторинг через tonapi.io webhooks.
Итоговые сроки для полноценного TON-приложения (контракты + backend + frontend): 2-4 недели. Зависит от сложности бизнес-логики и количества контрактов в системе.
Частые ошибки при разработке на TON
Игнорировать bounce. Любой контракт, отправляющий средства или вызывающий другой контракт, обязан обрабатывать bounced messages. Иначе при любом downstream failure средства зависают.
Хранить всё в одном контракте. TON шардирует данные, размещая контракты в разных шардах. Один большой контракт со всеми данными пользователей — это anti-pattern, который противоречит архитектуре TON. Правильный паттерн: master + per-user contracts (как jetton minter + jetton wallet).
Не учитывать storage fees. Контракт с недостаточным балансом замораживается. Нужен механизм пополнения или ограничения объёма хранимых данных.







