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…
| Param | Required | Notes |
|---|
chainId | ✓ | ton:mainnet (or ton:testnet) |
tokenIn / tokenOut | ✓ | Friendly EQ…/UQ… or raw 0:hex. Native = EQAA…M9c. |
amount or amountRaw | ✓ | Human-readable ("1.5") or nanoTon ("1500000000") |
walletAddress | ✓ | User’s TON v4r2 address |
slippage | – | % (0-100, default 1) |
feePercentage | – | Caller referral fee 0-99% (Mobula skims 20%) |
feeWallet | – | Required 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
| Field | Type | Description |
|---|
transaction | message | Back-compat single-message access. Equal to transactions[0] (the swap). Old SDKs still work — they just won’t deliver the fee messages. |
transactions | message[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.mobulaFeeAmount | string nanoTon | Mobula’s slice (always-on 0.1% + 20% cut of referral). |
fees.referralFeeAmount | string nanoTon | Caller’s net (after Mobula’s cut). 0 when no referral. |
fees.swapAmount | string nanoTon | Enters the swap. mobula + referral + swap = amountIn. |
fees.mobulaFeeBps | int | Always 10 (= 0.1%) in production. |
fees.userFeeBps | int | feePercentage × 100. |
fees.platformCutBps | int | Always 2000 (= 20%) in production. |
Each message:
| Field | Type | Description |
|---|
to | string | Friendly EQ/UQ form preferred, raw 0:hex accepted |
value | string | nanoTon, digit-only (bigint-safe) |
body | string | Inner message body BoC, base64 |
bounce | bool | true for jetton transfers (refund on failure) |
stateInit | string? | BoC base64 — set on first jetton-wallet deploy |
Signing
TonConnect (recommended)
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
| DEX | Pool | Notes |
|---|
| Stonfi v2 | constant-product | Default for most pairs |
| Stonfi omni | omni-router | Multi-hop |
| DeDust v2 (volatile) | constant-product | Volatile pairs |
| DeDust v2 (stable) | curve-style | Stablecoin pairs |
| pTON v2 | wrapped-TON | Used 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.