Інтеграція бота з DeDust SDK (TON)
TON — не EVM-сумісний блокчейн. Його архітектура принципово відрізняється від Ethereum: асинхронна модель повідомлень, actor model замість синхронних викликів, FunC/Tact замість Solidity. Розробник, який прийшов з EVM досвідом, першим делом шукає аналог ethers.js — і знаходить @ton/ton SDK. Але паттерни взаємодії повністю інші, і це стає ясно при першій спробі зробити своп на DeDust.
Як працює DeDust та чим він відрізняється від Uniswap
DeDust — AMM DEX на TON, який використовує архітектуру Volatile Pool (аналог Uniswap V2) та Stable Pool (аналог Curve). Основна відмінність від EVM DEX в тому, що взаємодія з пулом відбувається через відправку повідомлень на контракт гаманця токена, а не напрямо на пул.
Схема свопу TON → Jetton (аналог ERC-20 в TON):
- Відправити TON на контракт
NativeVaultз payload, який містить адресу пулу та параметри свопу -
NativeVaultпередає повідомлення вPool -
Poolвиконує розрахунок та відправляє Jetton до отримувача
Схема свопу Jetton → TON:
- Відправити повідомлення
transferна Jetton Wallet зforward_payloadдля DeDust - Jetton Wallet відправляє
transfer_notificationнаJettonVault -
JettonVaultпередає вPool, пул відправляє TON назад
Ключовий момент: кожен крок — окреме on-chain повідомлення. Немає атомарності в EVM-смислі. Якщо якийсь крок упадіт (недостатньо газу на проміжному контракті), токени можуть «зависнути» у vault. Саме тому queryId — не просто параметр, а механізм ідентифікації для bounce-повідомлень та відстеження стану транзакції.
Інтеграція через DeDust SDK
DeDust надає офіційний TypeScript SDK @dedust/sdk. Базовий своп через SDK:
import { Factory, MAINNET_FACTORY_ADDR, VaultNative, PoolType, Asset, ReadinessStatus } from "@dedust/sdk";
import { TonClient4, WalletContractV4, internal } from "@ton/ton";
const client = new TonClient4({ endpoint: "https://mainnet-v4.tonhubapi.com" });
const factory = client.open(Factory.createFromAddress(MAINNET_FACTORY_ADDR));
// Отримуємо адреси vault та пулу
const tonVault = client.open(await factory.getNativeVault());
const pool = client.open(await factory.getPool(PoolType.VOLATILE, [
Asset.native(),
Asset.jetton(JETTON_ADDRESS)
]));
// Перевіряємо готовність пулу
if ((await pool.getReadinessStatus()) !== ReadinessStatus.READY) {
throw new Error("Pool not ready");
}
// Відправляємо своп
await tonVault.sendSwap(wallet.sender(keyPair.secretKey), {
poolAddress: pool.address,
amount: toNano("1"), // 1 TON
gasAmount: toNano("0.25"),
// limit: мінімальна кількість токенів на виході
});
Параметр gasAmount — критичний. Недостатньо газу → повідомлення не доходить до пулу, TON повертається через bounce. Надлишок → ненужні витрати. Для свопу Jetton → TON газу більше: потрібно покрити transfer_notification + обробку у vault + відправку TON назад. Рекомендовані значення: 0.25-0.3 TON для TON→Jetton, 0.3-0.4 TON для Jetton→TON.
Відстеження виконання транзакції
На відміну від Ethereum, де await tx.wait() підтверджує фінальність, у TON потрібно відстежувати ланцюжок повідомлень. Транзакція може завершитися успішно, але одне з повідомлень у ланцюжку — з помилкою.
Паттерн моніторингу через queryId:
const queryId = BigInt(Date.now()); // Унікальний ID
// Передаємо queryId в параметри свопу
// Моніторинг через polling транзакцій цільового гаманця
async function waitForSwapResult(wallet: Address, queryId: bigint, timeout: number) {
const deadline = Date.now() + timeout;
while (Date.now() < deadline) {
const txs = await client.getTransactions(wallet, { limit: 10 });
const completed = txs.find(tx =>
tx.inMessage?.body.beginParse().loadUint(32) === 0x7362d09c // transfer_notification
// парсимо queryId та порівнюємо
);
if (completed) return completed;
await sleep(2000);
}
throw new Error("Swap timeout");
}
Для production бота правильніше використовувати TON HTTP API v2 з webhooks або IndexerAPI для більш надійного моніторингу eventi.
Розрахунок slippage та мінімального виходу
DeDust використовує формулу CPMM (x*y=k) для Volatile Pool. Розрахунок очікуваного виходу:
const [reserve0, reserve1] = await pool.getReserves();
const amountIn = toNano("1");
const fee = 3n; // 0.3% = 30 basis points з 10000
// Формула з fee
const amountInWithFee = amountIn * (10000n - fee);
const amountOut = (amountInWithFee * reserve1) / (reserve0 * 10000n + amountInWithFee);
// Мінімальний вихід з 1% слайпідж толерантністю
const minAmountOut = amountOut * 99n / 100n;
Параметр limit у sendSwap приймає саме цей minAmountOut. Якщо реальний вихід менший за мінімум — транзакція відхилена, TON повертається через bounce.
Особливості для торгового бота
Nonce та sequence number. У TON немає nonce в EVM-смислі. Замість нього — seqno гаманця. Два паралельних повідомлення з однаковим seqno → друге буде відхилено. Для бота з високою частотою транзакцій потрібно або використовувати окремі гаманці для кожного напрямку, або чергу з послідовною відправкою.
Мультигамацька архітектура. Якщо бот працює на кількох парах одночасно — рекомендуємо окремий гаманець на кожну торгову пару. Це уникає конфліктів seqno та спрощує облік балансу.
TON Connect vs backend signing. Для торгового бота — лише backend signing через мнемоніку або keystore. TON Connect призначений для користувацьких dApp, не для автоматичних операцій.
Орієнтири по строкам
Базова інтеграція з DeDust SDK (один напрямок свопу, моніторинг) — 3-4 дні. Повноцінний торговий бот з двусторонніми свопами, слайпідж захистом, моніторингом позицій — 1 тиждень. Вартість розраховується індивідуально.







