Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.mobula.io/llms.txt

Use this file to discover all available pages before exploring further.

Single endpoint, same shape as Solana / EVM. The TON-specific calldata sits under data.ton. See the Swap Quoting page for the full input parameters.

Native sentinel

EQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAM9c
Use this tokenIn / tokenOut for native TON. Internally routed through pTON v2.

Request

GET /api/2/swap/quoting?chainId=ton:mainnet
  &tokenIn=EQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAM9c
  &tokenOut=EQBL58cH_GfHhfdopPfcAW59dJmQPiZG-qokeJmL3V4cioTX
  &amount=1
  &walletAddress=UQ…
  &slippage=1
  &feePercentage=0.5
  &feeWallet=UQ…
ParamRequiredNotes
chainIdton:mainnet (or ton:testnet)
tokenIn / tokenOutFriendly EQ…/UQ… or raw 0:hex. Native = EQAA…M9c.
amount or amountRawHuman-readable ("1.5") or nanoTon ("1500000000")
walletAddressUser’s TON v4r2 address
slippage% (0-100, default 1)
feePercentageCaller referral fee 0-99% (Mobula skims 20%)
feeWalletRequired when feePercentage > 0

Response — data.ton

{
  "data": {
    "amountOutTokens": "12.345",
    "amountInUSD": 1.23,
    "amountOutUSD": 1.21,
    "slippagePercentage": 1,
    "marketImpactPercentage": 0.04,
    "poolFeesPercentage": 0.3,
    "tokenIn":  { "address": "EQAA…M9c", "symbol": "TON",  "decimals": 9 },
    "tokenOut": { "address": "EQBL58cH…", "symbol": "ES",   "decimals": 9 },
    "requestId": "f8b2…",
    "details": {
      "route": {
        "hops": [{ "poolAddress": "EQA…", "exchange": "DeDust", "feeBps": 30 }],
        "totalFeePercentage": 0.3,
        "aggregator": "mobula-ton"
      }
    },
    "fee": { "amount": "0.0005", "percentage": 0.5, "wallet": "UQ…", "deductedFrom": "input" },
    "ton": {
      "transaction":  { "to": "EQ…", "value": "299700000", "body": "te6cck…", "bounce": true },
      "transactions": [
        { "to": "EQ…",          "value": "299700000", "body": "te6cck…", "bounce": true  },
        { "to": "UQC4…M9c",     "value":  "50000000", "body": "te6cck…", "bounce": false },
        { "to": "UQuser…",      "value":  "50000000", "body": "te6cck…", "bounce": false }
      ],
      "fees": {
        "mobulaFeeAmount":   "30000",
        "referralFeeAmount": "200000",
        "swapAmount":        "49770000",
        "mobulaFeeBps": 10,
        "userFeeBps": 50,
        "platformCutBps": 2000
      }
    },
    "evm": null,
    "solana": null
  }
}

data.ton fields

FieldTypeDescription
transactionmessageBack-compat single-message access. Equal to transactions[0] (the swap). Old SDKs still work — they just won’t deliver the fee messages.
transactionsmessage[1..4]Full envelope: [0] = swap, [1] = Mobula 0.1% fee, [2] = caller referral fee. v4r2 wallet contract supports up to 4 per signature.
fees.mobulaFeeAmountstring nanoTonMobula’s slice (always-on 0.1% + 20% cut of referral).
fees.referralFeeAmountstring nanoTonCaller’s net (after Mobula’s cut). 0 when no referral.
fees.swapAmountstring nanoTonEnters the swap. mobula + referral + swap = amountIn.
fees.mobulaFeeBpsintAlways 10 (= 0.1%) in production.
fees.userFeeBpsintfeePercentage × 100.
fees.platformCutBpsintAlways 2000 (= 20%) in production.
Each message:
FieldTypeDescription
tostringFriendly EQ/UQ form preferred, raw 0:hex accepted
valuestringnanoTon, digit-only (bigint-safe)
bodystringInner message body BoC, base64
bouncebooltrue for jetton transfers (refund on failure)
stateInitstring?BoC base64 — set on first jetton-wallet deploy

Signing

import { useTonConnectUI, CHAIN } from '@tonconnect/ui-react';

const [tonConnectUI] = useTonConnectUI();
const { boc } = await tonConnectUI.sendTransaction({
  validUntil: Math.floor(Date.now() / 1000) + 600,
  network: CHAIN.MAINNET,
  messages: quote.data.ton.transactions.map((m) => ({
    address:  m.to,
    amount:   m.value,
    payload:  m.body,
    ...(m.stateInit ? { stateInit: m.stateInit } : {}),
  })),
});
// Wallet signs + broadcasts. No /swap/send call needed.

Privy embedded (Solana key reused via shared Ed25519)

TON’s wallet v4r2 verifies signatures with the same Ed25519 primitive Solana uses — a Privy Solana embedded wallet covers TON natively, no new key.
// 1. Derive v4r2 address from Privy's Solana base58 pubkey (deterministic).
// 2. Build v4r2 signing cell over `data.ton.transactions[]`.
// 3. Sign the 32-byte hash via privy `signMessage({message, address})`.
// 4. Wrap into external_in BoC, POST /swap/send with chainId='ton:mainnet'.
// Reference: apps/mtt/src/lib/ton.ts (`buildSignedTonExternal`).

Mnemonic (server-side / scripts)

See packages/execution-engine/src/spot/ton/signAndBroadcast.ts for the canonical reference (uses @ton/crypto mnemonicToWalletKey + sign(hash, secretKey)).

Send

POST /api/2/swap/send
{ "chainId": "ton:mainnet", "signedTransaction": "<base64 BoC>" }
Returns { data: { transactionHash } } once toncenter /message accepts the BoC.

Supported DEXs

DEXPoolNotes
Stonfi v2constant-productDefault for most pairs
Stonfi omniomni-routerMulti-hop
DeDust v2 (volatile)constant-productVolatile pairs
DeDust v2 (stable)curve-styleStablecoin pairs
pTON v2wrapped-TONUsed internally for native TON in/out
Stonfi v1 is excluded — its frozen pTON v1 master would bounce TON-input swaps.

Limits

  • Max 4 messages per signature (v4r2 wallet contract). Calldata builder enforces this.
  • No EIP-155 chainId — pass 'ton:mainnet' verbatim. TonConnect’s network field discriminates.
  • Address forms — both friendly (EQ…/UQ…) and raw (0:<hex>) accepted on input.