ESC
Start typing to search...

sdk.ton.dex — DEX Trading

Decentralized exchange operations via STON.fi and DeDust aggregators. Access via sdk.ton.dex in your plugin.

Quick Example

Get a quote and execute a swap
import type { PluginSDK } from "@teleton-agent/sdk";

const USDT = "EQCxE6mUtQJKFnGfaROTKOt1lZbDiiX1kCixRv7Nw2Id_sDs";

// Compare quotes from both DEXes
const quote = await sdk.ton.dex.quote({
  fromAsset: "ton",
  toAsset: USDT,
  amount: 10,
  slippage: 0.01, // 1%
});

console.log(`Recommended: ${quote.recommended}`);
console.log(`Savings: ${quote.savings}`);

if (quote.stonfi) {
  console.log(`STON.fi: ${quote.stonfi.expectedOutput} USDT (fee: ${quote.stonfi.fee})`);
}
if (quote.dedust) {
  console.log(`DeDust: ${quote.dedust.expectedOutput} USDT (fee: ${quote.dedust.fee})`);
}

// Execute swap on the recommended DEX
const result = await sdk.ton.dex.swap({
  fromAsset: "ton",
  toAsset: USDT,
  amount: 10,
  slippage: 0.01,
});
console.log(`Swapped on ${result.dex}: ${result.amountIn} TON -> ~${result.expectedOutput} USDT`);

Overview

The DEX SDK provides a dual-aggregator interface to the two largest decentralized exchanges on TON: STON.fi and DeDust. The quote() method queries both and recommends the best rate. The swap() method executes the trade, either auto-selecting the best DEX or using a specific one via the dex parameter.

All DEX operations are accessed through sdk.ton.dex, a sub-namespace of the TON SDK.

  • Use "ton" as the asset identifier for native TON
  • Use the jetton master contract address for any other token
  • Amounts are in human-readable units (e.g., 10 for 10 TON, not nanoTON)
  • Slippage is a decimal (e.g., 0.01 = 1%), range: 0.001 to 0.5

Methods

quote(params)

Compare quotes from both STON.fi and DeDust, and get a recommendation for the best rate.

MethodReturnsDescription
quote(params: DexQuoteParams)Promise<DexQuoteResult>Aggregated quote comparing both DEXes with a recommendation.
Aggregated quote
const SCALE = "EQBlqsm144Dq6SjbPI4jjZvlmHDqumGs1SfAW3IqjvnBqSZ8";

const quote = await sdk.ton.dex.quote({
  fromAsset: "ton",
  toAsset: SCALE,
  amount: 5,
  slippage: 0.02, // 2% slippage tolerance
});

// quote.recommended is "stonfi" or "dedust"
// quote.savings tells you the difference (e.g. "0.5%")
if (quote.recommended === "stonfi" && quote.stonfi) {
  console.log(`Best rate on STON.fi: ${quote.stonfi.rate}`);
  console.log(`Expected: ${quote.stonfi.expectedOutput} SCALE`);
  console.log(`Min output: ${quote.stonfi.minOutput} (after slippage)`);
}

quoteSTONfi(params) / quoteDeDust(params)

Get a quote from a specific DEX only. Returns null if the DEX has no liquidity for the pair.

MethodReturnsDescription
quoteSTONfi(params: DexQuoteParams)Promise<DexSingleQuote | null>Quote from STON.fi only. Null if no liquidity.
quoteDeDust(params: DexQuoteParams)Promise<DexSingleQuote | null>Quote from DeDust only. Null if no liquidity.
Single DEX quotes
const params = { fromAsset: "ton", toAsset: USDT, amount: 100 };

const stonfi = await sdk.ton.dex.quoteSTONfi(params);
const dedust = await sdk.ton.dex.quoteDeDust(params);

if (stonfi) {
  console.log(`STON.fi rate: ${stonfi.rate}, fee: ${stonfi.fee}`);
  if (stonfi.priceImpact) console.log(`Price impact: ${stonfi.priceImpact}`);
}

if (dedust) {
  console.log(`DeDust rate: ${dedust.rate}, fee: ${dedust.fee}`);
  console.log(`Pool type: ${dedust.poolType}`); // "volatile" or "stable"
}

swap(params)

Execute a swap. By default, auto-selects the best DEX. Use params.dex to force a specific one.

MethodReturnsDescription
swap(params: DexSwapParams)Promise<DexSwapResult>Execute swap via recommended DEX (or forced via params.dex).
Auto-selected swap
// Auto-select best DEX
const result = await sdk.ton.dex.swap({
  fromAsset: "ton",
  toAsset: USDT,
  amount: 10,
  slippage: 0.01,
});

console.log(`Swapped on ${result.dex}`);
console.log(`Sent: ${result.amountIn} TON`);
console.log(`Expected: ${result.expectedOutput} USDT`);
console.log(`Min output: ${result.minOutput} USDT`);
console.log(`Slippage: ${result.slippage}`);
Force a specific DEX
// Force STON.fi
const stonfiResult = await sdk.ton.dex.swap({
  fromAsset: USDT,
  toAsset: "ton",
  amount: 50,
  slippage: 0.01,
  dex: "stonfi",
});

// Force DeDust
const dedustResult = await sdk.ton.dex.swap({
  fromAsset: USDT,
  toAsset: "ton",
  amount: 50,
  slippage: 0.01,
  dex: "dedust",
});

swapSTONfi(params) / swapDeDust(params)

Execute a swap on a specific DEX directly. Same as calling swap() with the dex parameter.

MethodReturnsDescription
swapSTONfi(params: DexSwapParams)Promise<DexSwapResult>Execute swap on STON.fi specifically.
swapDeDust(params: DexSwapParams)Promise<DexSwapResult>Execute swap on DeDust specifically.
Direct DEX swap
const result = await sdk.ton.dex.swapSTONfi({
  fromAsset: "ton",
  toAsset: USDT,
  amount: 5,
  slippage: 0.01,
});
console.log(`STON.fi swap: ${result.amountIn} -> ${result.expectedOutput}`);

Type Definitions

DexQuoteParams
interface DexQuoteParams {
  fromAsset: string;   // "ton" or jetton master address
  toAsset: string;     // "ton" or jetton master address
  amount: number;      // Human-readable units
  slippage?: number;   // 0.01 = 1% (default: 0.01, range: 0.001-0.5)
}
DexQuoteResult
interface DexQuoteResult {
  stonfi: DexSingleQuote | null;          // STON.fi quote (null if no liquidity)
  dedust: DexSingleQuote | null;          // DeDust quote (null if no liquidity)
  recommended: "stonfi" | "dedust";       // Best DEX for this trade
  savings: string;                         // Savings vs other DEX (e.g. "0.5%")
}
DexSingleQuote
interface DexSingleQuote {
  dex: "stonfi" | "dedust";   // DEX name
  expectedOutput: string;      // Expected output amount
  minOutput: string;           // Minimum after slippage
  rate: string;                // Exchange rate
  priceImpact?: string;        // Price impact percentage
  fee: string;                 // Fee amount
  poolType?: string;           // DeDust: "volatile" | "stable"
}
DexSwapParams
interface DexSwapParams extends DexQuoteParams {
  dex?: "stonfi" | "dedust";  // Force a specific DEX (omit for auto)
}
DexSwapResult
interface DexSwapResult {
  dex: "stonfi" | "dedust";   // DEX used
  fromAsset: string;           // Source asset address
  toAsset: string;             // Destination asset address
  amountIn: string;            // Amount sent
  expectedOutput: string;      // Expected output
  minOutput: string;           // Minimum after slippage
  slippage: string;            // Slippage used
}

STON.fi vs DeDust

FeatureSTON.fiDeDust
Pool typesConstant product (v1/v2)Volatile + Stable pools
Stablecoin pairsStandard AMMOptimized stable curve
LiquidityGenerally higher for major pairsGrowing, strong on stables
Pool type infoNot exposedAvailable via poolType
Price impactAvailable via priceImpactAvailable via priceImpact
Best forMajor TON/jetton pairsStablecoin swaps, newer tokens

Use the aggregated quote() method to automatically find the best rate. The recommended field and savings percentage make it easy to present the comparison to users.

Risk Warnings

  • Swaps are irreversible — once a swap transaction is sent to the blockchain, it cannot be undone. Always confirm with the user before executing.
  • Slippage tolerance — setting slippage too low may cause the swap to fail. Setting it too high may result in unfavorable rates. The default 1% is suitable for most trades.
  • Price impact — large trades relative to pool liquidity will move the price. Check priceImpact in the quote before executing. Warn users if impact exceeds 3-5%.
  • MEV / frontrunning — on-chain swaps on TON are less susceptible to MEV than Ethereum, but large trades can still be sandwiched. Consider splitting large trades.
  • Token verification — always verify the jetton address before swapping. Use sdk.ton.getJettonInfo() to check the verified field and confirm the token is legitimate.
  • Liquidity — a quote returning null means the DEX has no liquidity for the pair. Both DEXes returning null means the token is not tradable.

Complete Example: Quote, Compare, Swap

Full DEX trading flow
import type { PluginSDK, DexQuoteResult, DexSwapResult } from "@teleton-agent/sdk";

const USDT = "EQCxE6mUtQJKFnGfaROTKOt1lZbDiiX1kCixRv7Nw2Id_sDs";

export default {
  name: "dex-trader",
  version: "1.0.0",
  tools: [
    {
      name: "swap_ton_to_usdt",
      description: "Swap TON for USDT via the best DEX",
      parameters: {
        type: "object",
        properties: {
          amount: { type: "number", description: "TON amount to swap" },
          maxSlippage: { type: "number", description: "Max slippage (default 0.01)" },
        },
        required: ["amount"],
      },
      execute: async (args: { amount: number; maxSlippage?: number }, sdk: PluginSDK) => {
        const slippage = args.maxSlippage ?? 0.01;

        // Step 1: Verify the token
        const info = await sdk.ton.getJettonInfo(USDT);
        if (!info?.verified) {
          return { error: "USDT token not verified" };
        }

        // Step 2: Check balance
        const balance = await sdk.ton.getBalance();
        if (!balance || parseFloat(balance.balance) < args.amount + 0.5) {
          return { error: "Insufficient balance (need amount + ~0.5 TON for gas)" };
        }

        // Step 3: Get quotes from both DEXes
        const quote = await sdk.ton.dex.quote({
          fromAsset: "ton",
          toAsset: USDT,
          amount: args.amount,
          slippage,
        });

        // Step 4: Check for liquidity
        if (!quote.stonfi && !quote.dedust) {
          return { error: "No liquidity on either DEX" };
        }

        // Step 5: Check price impact
        const best = quote.recommended === "stonfi" ? quote.stonfi! : quote.dedust!;
        if (best.priceImpact && parseFloat(best.priceImpact) > 5) {
          return {
            warning: `High price impact: ${best.priceImpact}%. Consider a smaller trade.`,
            quote: {
              dex: quote.recommended,
              output: best.expectedOutput,
              minOutput: best.minOutput,
              rate: best.rate,
            },
          };
        }

        // Step 6: Execute the swap
        const result = await sdk.ton.dex.swap({
          fromAsset: "ton",
          toAsset: USDT,
          amount: args.amount,
          slippage,
        });

        return {
          success: true,
          dex: result.dex,
          sent: `${result.amountIn} TON`,
          expected: `${result.expectedOutput} USDT`,
          minOutput: `${result.minOutput} USDT`,
          slippage: result.slippage,
          savings: quote.savings,
        };
      },
    },
  ],
};