Swap

Execute token swaps on Ferra pools.

Quick Start

// Simple swap: 1 SUI -> USDC
const swapParams = {
  pool_id: '0x...',
  coinTypeA: '0x2::sui::SUI',
  coinTypeB: '0x...::usdc::USDC',
  a2b: true,              // SUI -> USDC
  by_amount_in: true,     // Fix input amount
  amount: '1000000000',   // 1 SUI
  amount_limit: '990000', // Min 990 USDC (1% slippage)
}

const tx = await sdk.Swap.createSwapTransactionPayload(swapParams)

const result = await sdk.fullClient.signAndExecuteTransaction({
  transaction: tx,
  signer: keypair
})

Swap Parameters

Parameter
Type
Description

pool_id

string

Pool object ID

coinTypeA

string

First token type

coinTypeB

string

Second token type

a2b

boolean

Direction (true: A→B, false: B→A)

by_amount_in

boolean

Fix input (true) or output (false)

amount

string

Fixed amount

amount_limit

string

Slippage limit

swap_partner

string

Optional partner for fees

Swap Directions

Swap A to B

const params = {
  pool_id: poolId,
  coinTypeA: '0x2::sui::SUI',
  coinTypeB: '0x...::usdc::USDC',
  a2b: true,              // SUI -> USDC
  by_amount_in: true,
  amount: '1000000000',   // Input: 1 SUI
  amount_limit: '990000'  // Min output: 990 USDC
}

Swap B to A

const params = {
  pool_id: poolId,
  coinTypeA: '0x2::sui::SUI',
  coinTypeB: '0x...::usdc::USDC',
  a2b: false,             // USDC -> SUI
  by_amount_in: true,
  amount: '1000000',      // Input: 1000 USDC
  amount_limit: '990000000' // Min output: 0.99 SUI
}

Fix Output Amount

Get exactly the amount you want:

const params = {
  pool_id: poolId,
  coinTypeA: '0x2::sui::SUI',
  coinTypeB: '0x...::usdc::USDC',
  a2b: true,
  by_amount_in: false,    // Fix output amount
  amount: '1000000',      // Want exactly 1000 USDC
  amount_limit: '1010000000' // Max input: 1.01 SUI
}

Calculate Slippage

// 1. PreSwap to get expected amounts
const preSwap = await sdk.Swap.preswap({
  pool,
  coinTypeA: pool.coinTypeA,
  coinTypeB: pool.coinTypeB,
  decimalsA: 9,
  decimalsB: 6,
  a2b: true,
  byAmountIn: true,
  amount: '1000000000',
  currentSqrtPrice: pool.current_sqrt_price
})

// 2. Apply slippage (1%)
const slippage = 0.01
const expectedOut = Number(preSwap.estimatedAmountOut)
const minOutput = Math.floor(expectedOut * (1 - slippage))

// 3. Create swap transaction
const swapParams = {
  pool_id: pool.poolAddress,
  coinTypeA: pool.coinTypeA,
  coinTypeB: pool.coinTypeB,
  a2b: true,
  by_amount_in: true,
  amount: '1000000000',
  amount_limit: minOutput.toString()
}

const tx = await sdk.Swap.createSwapTransactionPayload(swapParams)

Gas Optimization (SUI)

Optimize gas when swapping SUI:

const gasConfig = {
  byAmountIn: true,
  slippage: new Percentage(1, 100), // 1%
  decimalsA: 9,
  decimalsB: 6,
  swapTicks: ticks,
  currentPool: pool
}

const tx = await sdk.Swap.createSwapTransactionPayload(
  swapParams,
  gasConfig
)

Partner Swaps

Route fees to partners:

const params = {
  ...swapParams,
  swap_partner: '0xpartner...' // Partner object ID
}

const tx = await sdk.Swap.createSwapTransactionPayload(params)

Advanced Usage

Manual Coin Management

// Get swap transaction without auto-transfer
const { tx, coinABs } = await sdk.Swap.createSwapTransactionWithoutTransferCoinsPayload(swapParams)

// coinABs[0] = coin A after swap
// coinABs[1] = coin B after swap

// Custom handling
tx.transferObjects([coinABs[1]], recipient)

const result = await sdk.fullClient.signAndExecuteTransaction({
  transaction: tx,
  signer: keypair
})

Batch Swaps

const tx = new Transaction()

// First swap: SUI -> USDC
await sdk.Swap.createSwapTransactionPayload(swap1Params, undefined, tx)

// Second swap: USDC -> USDT
await sdk.Swap.createSwapTransactionPayload(swap2Params, undefined, tx)

// Execute both
const result = await sdk.fullClient.signAndExecuteTransaction({
  transaction: tx,
  signer: keypair
})

Complete Example

async function swapTokens() {
  // 1. Get pool
  const pool = await sdk.Pool.getPool(poolId)
  
  // 2. Check current price
  const price = TickMath.sqrtPriceX64ToPrice(
    pool.current_sqrt_price,
    9, // SUI decimals
    6  // USDC decimals
  )
  console.log('Current price:', price.toString())
  
  // 3. PreSwap simulation
  const preSwap = await sdk.Swap.preswap({
    pool,
    coinTypeA: pool.coinTypeA,
    coinTypeB: pool.coinTypeB,
    decimalsA: 9,
    decimalsB: 6,
    a2b: true,
    byAmountIn: true,
    amount: '1000000000',
    currentSqrtPrice: pool.current_sqrt_price
  })
  
  // 4. Check if swap is viable
  if (preSwap.isExceed) {
    throw new Error('Insufficient liquidity')
  }
  
  // 5. Create swap with 0.5% slippage
  const minOutput = Math.floor(Number(preSwap.estimatedAmountOut) * 0.995)
  
  const swapParams = {
    pool_id: pool.poolAddress,
    coinTypeA: pool.coinTypeA,
    coinTypeB: pool.coinTypeB,
    a2b: true,
    by_amount_in: true,
    amount: '1000000000',
    amount_limit: minOutput.toString()
  }
  
  // 6. Execute swap
  const tx = await sdk.Swap.createSwapTransactionPayload(swapParams)
  
  const result = await sdk.fullClient.signAndExecuteTransaction({
    transaction: tx,
    signer: keypair
  })
  
  console.log('Swap completed:', result.digest)
}

Error Handling

try {
  const tx = await sdk.Swap.createSwapTransactionPayload(swapParams)
} catch (error) {
  if (error.code === 'InvalidSendAddress') {
    sdk.senderAddress = '0x...'
  }
  if (error.message.includes('Insufficient balance')) {
    console.log('Not enough tokens')
  }
  if (error.message.includes('Slippage exceeded')) {
    console.log('Price moved, increase slippage')
  }
}

Important Notes

  • Always use amount_limit for slippage protection

  • SDK automatically handles coin selection

  • Excess coins are returned to sender

  • Partner swaps share fees with partners

  • Gas optimization available for SUI swaps

Last updated