This guide walks through how to exchange tokens in a Saros DLMM pool from your frontend interface. The steps are:
Define swap parameters
Invoke the on-chain swap instruction
Swap Types
There are two types of swaps available:
Exact Input: You specify the exact amount of tokens you want to swap in, and receive the corresponding amount of tokens out
Exact Output: You specify the exact amount of tokens you want to receive, and provide the corresponding amount of tokens in
Swap Direction
Swaps can be performed in two directions:
Swap for Y: Swap token X for token Y
Swap for X: Swap token Y for token X
Example Code
Exact Input Swap
import { PublicKey } from "@solana/web3.js";
import { BN } from "@project-serum/anchor";
import { TOKEN_2022_PROGRAM_ID, TOKEN_PROGRAM_ID } from "@solana/spl-token";
// Define the amount of tokens to swap in
const amountIn = new BN(1000000); // Amount of token X or Y to swap in
// Define the minimum amount of tokens to receive (0 for no minimum)
const otherAmountThreshold = new BN(0);
// Set the swap direction (true for X to Y, false for Y to X)
const swapForY = true;
// Derive bin array PDAs
const [binArrayLowerPda] = PublicKey.findProgramAddressSync(
[Buffer.from("bin_array"), pairPda.toBuffer(), Buffer.from([0])],
program.programId
);
const [binArrayUpperPda] = PublicKey.findProgramAddressSync(
[Buffer.from("bin_array"), pairPda.toBuffer(), Buffer.from([1])],
program.programId
);
await program.methods
.swap(amountIn, otherAmountThreshold, swapForY, { exactInput: {} })
.accounts({
pair: pairPda,
binArrayLower: binArrayLowerPda,
binArrayUpper: binArrayUpperPda,
tokenMintX: tokenMintX,
tokenMintY: tokenMintY,
tokenVaultX: tokenVaultXPda,
tokenVaultY: tokenVaultYPda,
userVaultX: userVaultXPda,
userVaultY: userVaultYPda,
tokenProgramX: TOKEN_PROGRAM_ID,
tokenProgramY: TOKEN_PROGRAM_ID,
user: wallet.publicKey,
})
.signers([wallet.payer])
.rpc();
Exact Output Swap
import { PublicKey } from "@solana/web3.js";
import { BN } from "@project-serum/anchor";
import { TOKEN_2022_PROGRAM_ID, TOKEN_PROGRAM_ID } from "@solana/spl-token";
// Define the amount of tokens to receive
const amountOut = new BN(1000000); // Amount of token to receive
// Define the maximum amount of tokens to provide
const otherAmountThreshold = new BN(2000000); // Maximum amount of token provide
// Set the swap direction (true for X to Y, false for Y to X)
const swapForY = false;
// Derive bin array PDAs
const [binArrayLowerPda] = PublicKey.findProgramAddressSync(
[Buffer.from("bin_array"), pairPda.toBuffer(), Buffer.from([0])],
program.programId
);
const [binArrayUpperPda] = PublicKey.findProgramAddressSync(
[Buffer.from("bin_array"), pairPda.toBuffer(), Buffer.from([1])],
program.programId
);
await program.methods
.swap(amountOut, otherAmountThreshold, swapForY, { exactOutput: {} })
.accounts({
pair: pairPda,
binArrayLower: binArrayLowerPda,
binArrayUpper: binArrayUpperPda,
tokenMintX: tokenMintX,
tokenMintY: tokenMintY,
tokenVaultX: tokenVaultXPda,
tokenVaultY: tokenVaultYPda,
userVaultX: userVaultXPda,
userVaultY: userVaultYPda,
tokenProgramX: TOKEN_PROGRAM_ID,
tokenProgramY: TOKEN_PROGRAM_ID,
user: wallet.publicKey,
})
.signers([wallet.payer])
.rpc();
How the Swap Executes
When you perform a swap, the following happens:
Tokens are transferred from user to the pool's vault
The swap is executed across one or more bins, starting from the active bin
If the swap cannot be completed in a single bin, the active bin is moved and the swap continues
Tokens are transferred from the pool's vault to user
Protocol fees are collected and stored in the pair account