Skip to main content

sdk.swap()

Build an unsigned swap transaction ready to be signed and submitted to the Solana network.
const swap = await sdk.swap(params: SwapRequest): Promise<SwapResponse>

Parameters (SwapRequest)

FieldTypeRequiredDefaultDescription
userWalletstringyesUser’s wallet address (base58). Must have sufficient balance.
inputMintstringyesInput token mint address
outputMintstringyesOutput token mint address
amountstringyesAmount in smallest token units
swapMode"ExactIn" | "ExactOut"yesSwap direction
slippageBpsnumberno50Slippage tolerance in basis points
skipSimulationbooleannofalseSkip pre-flight simulation. Faster but no validation.

Response (SwapResponse)

{
  "transaction": "AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAQAHEAo...",
  "lastValidBlockHeight": 245832190,
  "amountIn": "1000000000",
  "amountOut": "145320000",
  "minAmountOut": "144593400",
  "feeAmount": "0",
  "simulation": {
    "success": true,
    "computeUnitsConsumed": 85000,
    "computeUnitsTotal": 200000,
    "logs": ["Program ... invoke", "..."],
    "error": "",
    "slippageExceeded": false,
    "insufficientFunds": false,
    "accountsNeeded": []
  },
  "computeUnitsEstimate": 85000,
  "route": [
    "So11111111111111111111111111111111111111112",
    "uSd2czE61Evaf76RNbq4KPpXnkiL3irdzgLFUMe3NoG"
  ],
  "hopCount": 1,
  "pools": ["HJPjoWUrhoZzkNfRpHuieeFk9WcZWjwy6PBjZ81ngndJ"],
  "isSplitRoute": false
}

Response Fields

FieldTypeDescription
transactionstringBase64-encoded unsigned v0 transaction
lastValidBlockHeightnumberTransaction expires after this block height (~60 seconds)
amountInstringInput amount
amountOutstringEstimated output amount
minAmountOutstring?Minimum output after slippage (ExactIn). Transaction reverts if actual output is less.
maxAmountInstring?Maximum input after slippage (ExactOut). Transaction reverts if actual input exceeds this.
feeAmountstringAggregator fee in output token units
simulationSimulationResult?Simulation result (null if skipSimulation=true)
computeUnitsEstimatenumber?Estimated compute units
routestring[]Token mint path in execution order
hopCountnumberNumber of swap hops
poolsstring[]Pool addresses used, in execution order
isSplitRouteboolean?Whether liquidity is split across pools
splitPercentsnumber[]?Per-pool percentage split (only if isSplitRoute=true)

SimulationResult

FieldTypeDescription
successbooleanWhether simulation passed
computeUnitsConsumednumberCU consumed
computeUnitsTotalnumberCU limit
logsstring[]Transaction logs
errorstringError message if simulation failed
slippageExceededbooleanWhether slippage check failed
insufficientFundsbooleanWhether wallet has insufficient balance
accountsNeededstring[]Missing accounts (e.g. ATAs that need creation)

Sign and Submit

After receiving the SwapResponse, deserialize, sign, and submit the transaction.

With @solana/web3.js

import { Connection, VersionedTransaction, Keypair } from "@solana/web3.js";

const connection = new Connection("https://mainnet.fogo.io");
const wallet = Keypair.fromSecretKey(/* ... */);

const swap = await sdk.swap({
  userWallet: wallet.publicKey.toBase58(),
  inputMint: "So11111111111111111111111111111111111111112",
  outputMint: "uSd2czE61Evaf76RNbq4KPpXnkiL3irdzgLFUMe3NoG",
  amount: "1000000000",
  swapMode: "ExactIn",
  slippageBps: 50,
});

const tx = VersionedTransaction.deserialize(
  Buffer.from(swap.transaction, "base64")
);
tx.sign([wallet]);

const sig = await connection.sendTransaction(tx, { maxRetries: 3 });
const confirmation = await connection.confirmTransaction({
  signature: sig,
  lastValidBlockHeight: swap.lastValidBlockHeight,
  blockhash: tx.message.recentBlockhash,
});

if (confirmation.value.err) {
  console.error("Transaction failed:", confirmation.value.err);
} else {
  console.log("Swap confirmed:", sig);
}

With Wallet Adapter (React)

import { useWallet, useConnection } from "@solana/wallet-adapter-react";
import { VersionedTransaction } from "@solana/web3.js";

const { publicKey, signTransaction } = useWallet();
const { connection } = useConnection();

const swap = await sdk.swap({
  userWallet: publicKey.toBase58(),
  inputMint: "So11111111111111111111111111111111111111112",
  outputMint: "uSd2czE61Evaf76RNbq4KPpXnkiL3irdzgLFUMe3NoG",
  amount: "1000000000",
  swapMode: "ExactIn",
});

const tx = VersionedTransaction.deserialize(
  Buffer.from(swap.transaction, "base64")
);
const signed = await signTransaction(tx);
const sig = await connection.sendRawTransaction(signed.serialize());

Notes

  • The transaction includes automatic ATA (Associated Token Account) creation if the user doesn’t have token accounts for the swap tokens.
  • Compute budget is set based on hop count and DEX complexity.
  • Address Lookup Tables are used to keep the transaction within Solana’s size limits.
  • Submit the transaction quickly — it expires after lastValidBlockHeight (~60 seconds).