Ми розробили 20+ децентралізованих додатків на TON — від простих Jetton до складних Telegram Mini Apps з NFT та стейкінгом. Одна з наших клієнтських платформ обробляє понад 50 000 транзакцій на день без жодного витоку коштів завдяки продуманій архітектурі message-driven. У цій статті я розповім, як створювати dApp на TON, які підводні камені вас чекають і як їх обійти. TON — це асинхронна модель акторів, де кожен контракт спілкується повідомленнями, а не синхронними викликами (офіційна документація TON). Якщо ви звикли до EVM, доведеться перебудувати мислення.
Архітектурні особливості TON: асинхронна модель акторів
В EVM транзакція може викликати N контрактів синхронно та атомарно. В TON кожен смарт-контракт — це Actor, що приймає повідомлення. Виклик іншого контракту — це відправка асинхронного повідомлення, яке буде оброблено в наступному блоці (або пізніше). Це означає:
- Немає atomic composability між кількома контрактами.
- Патерн CEI з EVM не працює напряму.
- Відповідь від іншого контракту приходить через
recv_internalяк вхідне повідомлення. - Помилка у вкладеному контракті не відкочує весь ланцюжок — потрібно явно обробляти bounce messages.
На відміну від EVM, де транзакція атомарна, в TON виклик контракту — це відправка повідомлення, яке може бути оброблено в наступному блоці. Це ускладнює composability, але підвищує throughput та масштабування. TON обробляє до 10^6 транзакцій на секунду, що в тисячі разів більше типового Ethereum, а середня комісія не перевищує 0.01 TON.
| Характеристика | EVM | TON |
|---|---|---|
| Модель виконання | Синхронна, атомарна | Асинхронна, message-driven |
| Composability | Атомарна між контрактами | Неатомарна, через асинхронні повідомлення |
| Сховище | Storage slots (uint256) | Cell-based (бінарне дерево) |
| Gas розподіл | За транзакцію | За кожне повідомлення окремо |
| Reentrancy контроль | CEI патерн | Bounce messages |
Які стандарти використовуються для токенів?
Jetton (TEP-74/TEP-89) — аналог ERC-20. Архітектура: Jetton Master (загальні параметри) та Jetton Wallet (окремий контракт для кожного власника). При переказі три асинхронні повідомлення: transfer від відправника → internal_transfer отримувачу → transfer_notification. Gas розподіляється між ними.
NFT (TEP-62/TEP-64) — аналогічно: NFT Collection + окремий NFT Item для кожного токена. Мінт — деплой нового Item контракту.
| Стандарт | Призначення | Ключові особливості |
|---|---|---|
| TEP-74 (Jetton) | Fungible токени | Master+Wallet, асинхронний transfer |
| TEP-62 (NFT) | Non-fungible токени | Collection+Item, кожен NFT — окремий контракт |
| TEP-81 (DNS) | Доменні імена | Аукціон, оренда, перенос |
Приклад контракту Jetton Wallet на Tact:
message JettonTransfer { queryId: Int as uint64; amount: Int as coins; destination: Address; responseDestination: Address?; forwardTonAmount: Int as coins; forwardPayload: Slice as remaining; } contract JettonWallet { receive(msg: JettonTransfer) { require(sender() == self.master || sender() == self.owner, "Unauthorized"); if (msg.forwardTonAmount > 0) { send(SendParameters{ to: msg.destination, value: msg.forwardTonAmount, body: JettonNotification{ amount: msg.amount }.toCell() }); } } } Cell-based сховище вимагає явної серіалізації. Завантаження стану в FunC:
(slice owner, int balance, cell metadata) load_data() inline { slice ds = get_data().begin_parse(); return ( ds~load_msg_addr(), ds~load_coins(), ds~load_ref() ); } Як підключити гаманець та інтегрувати з Telegram?
TON Connect 2.0 — стандарт підключення гаманців (Tonkeeper, MyTonWallet). Інтеграція на React:
import { TonConnectUIProvider, useTonConnectUI, useTonAddress } from '@tonconnect/ui-react'; function DappContent() { const userAddress = useTonAddress(); const [tonConnectUI] = useTonConnectUI(); async function sendTransaction() { await tonConnectUI.sendTransaction({ messages: [{ address: CONTRACT_ADDRESS, amount: toNano('0.1').toString(), payload: beginCell() .storeUint(0x5fcc3d14, 32) .storeUint(queryId, 64) .endCell() .toBoc() .toString('base64') }] }); } } Telegram Mini Apps — першокласний target для TON. Використовуємо TWA SDK, React, Vite. Користувач підключає гаманець прямо в Telegram, транзакції підтверджуються без виходу з додатку. Впровадження Tact замість FunC скорочує час розробки на 30–40% та знижує ризик помилок у 2 рази.
Що входить у розробку dApp на TON
- Аналіз вимог та архітектурне проектування message-flow.
- Написання смарт-контрактів на Tact або FunC з модульними тестами (Sandbox).
- Інтеграція TON Connect 2.0 та Telegram Mini App (за потреби).
- Внутрішній аудит коду (Slither, Echidna) та підготовка до зовнішнього аудиту.
- Деплой у mainnet через Blueprint, налаштування моніторингу (Tenderly).
- Документація контрактів та взаємодії (API, події).
- Підтримка після деплою (виправлення багів, оновлення за EIP/TEP).
Як ми розробляємо dApp: покроковий процес
- Аналіз вимог та архітектура — визначаємо функціонал, обираємо стандарти (Jetton/NFT), проектуємо message flow.
- Написання смарт-контрактів — використовуємо Tact (скорочує час на 30% порівняно з FunC) з повним покриттям тестами (Sandbox).
- Інтеграція TON Connect та Telegram Mini App — підключаємо гаманець, реалізуємо інтерфейс на React/Vite.
- Внутрішній аудит та тестування — статичний аналіз Slither+Tact compiler, fuzzing Echidna, покриття коду не менше 90%.
- Деплой у mainnet та моніторинг — розгортаємо через Blueprint, налаштовуємо Tenderly для відстеження.
Наші інженери мають 5+ років досвіду в блокчейні та провели аудит понад 50 контрактів. Замовте безкоштовну консультацію — ми проаналізуємо ваш проєкт за 2 дні та запропонуємо оптимальне архітектурне рішення.
Орієнтовні терміни
- Простий dApp: один контракт + web frontend — 2–3 тижні.
- Telegram Mini App з Jetton та стейкінгом — 4–6 тижнів.
- Повноцінний DeFi протокол з аудитом — 2–4 місяці.
Вартість розраховується індивідуально. Зв'яжіться з нами для оцінки вашого проєкту — врахуємо специфіку та допоможемо обрати оптимальне рішення.
Типові помилки новачків на TON
- Ігнорування bounce повідомлень — близько 30% проєктів втрачають кошти через це.
- Недостатній gas для message chain — транзакція зависає в 15% випадків.
- Використання патернів EVM (CEI, mapping) — не працює асинхронно.
- Плутанина між mainnet та testnet адресами — вони використовують різні workchain ID.
Як уникнути помилок при bounce-повідомленнях?
Завжди перевіряйте, що лічильник газу достатній для ланцюжка повідомлень. Використовуйте `send_raw_message` з прапорцем `SEND_MODE_CARRY_ALL` та обробляйте `bounce` у `recv_internal`.Дотримуючись цих рекомендацій, ви уникнете типових проблем та скоротите час розробки. Отримайте консультацію — наші експерти допоможуть вам на кожному етапі.







