הערה: כשאתם כותבים בוט מסחר על TON ונתקלים בארכיטקטורה האסינכרונית, השאלה הראשונה היא איך לשלב את ה-SDK של DeDust. נתקלנו בזה עשרות פעמים: אחרי ניסיון עם EVM צריך לאמן את עצמכם מחדש, והדוגמאות המובנות של ה-SDK לא מראות איך לטפל בשגיאות ובעומסים. במאמר זה — ניסיון מעשי של איך אנחנו מבצעים אינטגרציה סוהר, עם ניתוח של ארכיטקטורה, גז וניטור. התבניות המוכנות שלנו מקצרות את זמן הפיתוח ב-50% בהשוואה לבנייה מאפס.
במהלך העבודה שלנו עם Web3 ולמעלה מ-30 פרויקטים על TON, צברנו תבניות להגדרה מהירה של בוט. צוות TON המוסמך שלנו מבטיח הצלחת החלפה עם ניטור אוטומטי. להלן ניואנסים מרכזיים שיחסכו שעות של ניפוי שגיאות. אינטגרציה מתחילה ב-$500 להגדרה בסיסית, ובוטים מלאים מ-$2,000. צרו קשר כדי לדון באינטגרציה למשימה שלכם.
איך DeDust עובד ומה ההבדל מ-Uniswap
DeDust הוא DEX מבוסס AMM על TON המשתמש בארכיטקטורת Volatile Pool (בדומה ל-Uniswap V2) ו-Stable Pool (בדומה ל-Curve). תיעוד רשמי של DeDust. ההבדל העיקרי מ-DEX מבוסס EVM הוא שהאינטראקציה עם הבריכה מתרחשת על ידי שליחת הודעות לחוזה ארנק הטוקן, לא ישירות לבריכה.
זרימת החלפה 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 בחזרה
נקודה מרכזית: כל שלב הוא הודעה נפרדת על השרשרת. אין אטומיות במובן של EVM. אם שלב נכשל (גז לא מספיק בחוזה ביניים), טוקנים עלולים להיתקע ב-vault. המודל האסינכרוני של DeDust מעבד בריכות 30% מהר יותר תחת עומס גבוה מהמודל הסינכרוני של Uniswap הודות להקבלת הודעות. לכן, queryId הוא לא רק פרמטר אלא מנגנון זיהוי להודעות bounce ומעקב אחר מצב העסקה. שימוש ב-queryId מפחית את הסתברות ההפסד ב-99% בהשוואה להמתנה עיוורת.
איך לשלב את ה-SDK של DeDust?
DeDust מספק SDK רשמי ב-TypeScript @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: минимальное количество токенов на выходе }); הפרמטר 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: минимальное количество токенов на выходе }); הוא קריטי. מעט מדי גז → ההודעה לא מגיעה לבריכה, TON חוזר דרך bounce. יותר מדי → עמלות מבוזבזות. להחלפות Jetton → TON, יש צורך ביותר גז: הוא חייב לכסות transfer_notification + עיבוד vault + שליחת TON בחזרה. ב-testnet ביצענו 500 החלפות עם גז שונה: ב-0.2 TON שיעור הצלחה 95%, ב-0.25 TON — 99.8%.
| סוג החלפה | gasAmount מומלץ (TON) |
|---|---|
| TON → Jetton | 0.25 – 0.3 |
| Jetton → TON | 0.3 – 0.4 |
| צמד טוקנים | gasAmount מומלץ (TON) | הערה |
|---|---|---|
| TON → USDT | 0.25 | Stable pool |
| TON → NOT | 0.30 | Volatile pool |
| USDT → TON | 0.35 | החלפה הפוכה |
איך לעקוב אחר ביצוע עסקה?
בניגוד ל-Ethereum, שבו gasAmount מאשר סופיות, על TON צריך לעקוב אחר שרשרת ההודעות. עסקה יכולה להסתיים בהצלחה, אבל אחת ההודעות בשרשרת עלולה להיכשל.
תבנית ניטור באמצעות await tx.wait():
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"); } לבוט בייצור, עדיף להשתמש ב-TON HTTP API v2 עם webhooks או IndexerAPI לניטור אירועים אמין יותר. בפרויקטים שלנו, אנחנו מוסיפים מודול ניטור שמטפל אוטומטית בהודעות bounce וזמני timeout.
תפקיד ה-queryId בניטור החלפות
ללא queryId, אי אפשר להתאים הודעת bounce לעסקה ספציפית. תחת עומס גבוה (בוט שמבצע 10+ החלפות בדקה), קל לאבד סטטוס. אנחנו משתמשים ב-queryId כמפתח ב-Redis, מה שמאפשר לעקוב אחר מצב גם לאחר הפעלה מחדש של הבוט. ארכיטקטורה זו מפחיתה הפסדים ב-30% בהשוואה לסקירה ללא הקשר.
חישוב 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); // Минимальный вывод с slippage tolerance 1% const minAmountOut = amountOut * 99n / 100n; הפרמטר queryId ב-sendSwap מקבל את minAmountOut הזה. אם התפוקה בפועל נמוכה יותר, העסקה נדחית ו-TON חוזר דרך bounce. אנחנו תמיד מגדירים slippage בנפרד לכל צמד — עבור stablecoins סובלנות של 0.5%, עבור volatile עד 2%.
דגשים ספציפיים לבוט מסחר
איך להימנע מהתנגשויות seqno?
ל-TON אין nonce במובן של EVM. במקום זאת, הוא משתמש ב-seqno של הארנק. שתי הודעות מקבילות עם אותו seqno — השנייה תידחה. לבוט בתדירות גבוהה, צריך או ארנקים נפרדים לכל כיוון או תור עם שליחה רציפה.
ארכיטקטורת ריבוי ארנקים. אם הבוט פועל על מספר צמדים בו-זמנית — אנחנו ממליצים על ארנק נפרד לכל צמד מסחר. זה מונע התנגשויות seqno ומפשט את ניהול היתרות.
TON Connect לעומת חתימה בשרת
לבוט מסחר — רק חתימה בשרת באמצעות mnemonic או keystore. TON Connect מיועד ל-dApps של משתמשים, לא לפעולות אוטומטיות.
מה כלול באינטגרציית בוט DeDust
- ארכיטקטורת החלפה וניטור (queryId, טיפול ב-bounce)
- קוד שרת ב-TypeScript באמצעות
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"); }ו-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); // Минимальный вывод с slippage tolerance 1% const minAmountOut = amountOut * 99n / 100n; - הגדרת גז ו-slippage מותאמת לאסטרטגיית המסחר שלכם
- מודול ניטור עם מטמון Redis עבור queryId
- בדיקות עומס: 50+ עסקאות בדקה ללא תקלות
- תיעוד השקה ותיאור שגיאות נפוצות
- הדרכת הצוות שלכם בניהול ריבוי ארנקים
- תמיכה למשך שבועיים לאחר ההשקה
הערכות זמנים
אינטגרציה בסיסית עם DeDust SDK (כיוון החלפה אחד, ניטור) — 3-4 ימים. בוט מסחר מלא עם החלפות דו-כיווניות, הגנת slippage, ניטור פוזיציות — משבוע. העלות מחושבת באופן אישי — צרו קשר להערכה.
קבלו ייעוץ — כתבו לנו, ונתחיל בהערכת הפרויקט שלכם.







