Skip to main content

🔓 Remove Liquidity

Remove Liquidity​

As we aim removing Liquidity we need some new Helper functions from the @saros-finance/dlmm-sdk:

RemoveLiquidity.tsx
TypeScript
import {
  RemoveLiquidityType,
  PositionInfo,
  BIN_STEP_CONFIGS,
  LiquidityBookServices,
  MODE,
} from "@saros - finance / dlmm - sdk";
import {
  PublicKey,
  Transaction,
  Keypair,
  signTransaction,
} from "@solana / web3.js";

Remove Liquidity Configs​

So now that we are almost ready lets configure the liquidity book service using our preffered network mainnet or devnet.

RemoveLiquidity.tsx
TypeScript
const liquidityBookService = new LiquidityBookServices({
  mode: MODE.MAINNET,
});

Tokens and Pool configs​

RemoveLiquidity.tsx
TypeScript
interface Token {
  id: string;
  mintAddress: string;
  symbol: string;
  name: string;
  decimal: number;
  addressSPL: string;
}
const userAddress = "Fke5jj8NMGGes1fyMysvfpi67BkBF5DiQPCQzoT6yCyj"; //user wallet

// Pool example on saros C98 to USDC
const USDC_TOKEN: Token = {
  id: "usd - coin",
  mintAddress: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
  symbol: "usdc",
  name: "USD Coin",
  decimals: 6,
  addressSPL: "FXRiEosEvHnpc3XZY1NS7an2PB1SunnYW1f5zppYhXb3",
};

const C98_TOKEN: Token = {
  id: "coin98",
  mintAddress: "C98A4nkJXhpVZNAZdHUA95RpTF3T4whtQubL3YobiUX9",
  symbol: "C98",
  name: "Coin98",
  decimals: 6,
  addressSPL: "EKCdCBjfQ6t5FBfDC2zvmr27PgfVVZU37C8LUE4UenKb",
};

const POOL_PARAMS = {
  address: "EwsqJeioGAXE5EdZHj1QvcuvqgVhJDp9729H5wjh28DD",
  baseToken: C98_TOKEN,
  quoteToken: USDC_TOKEN,
  slippage: 0.5,
  hook: "", // config for reward, adding later
};

//Devnet Tokens and Pool_Params
const WSOL_TOKEN_DEVNET: Token = {
  id: "wsol",
  mintAddress: "So11111111111111111111111111111111111111112",
  symbol: "WSOL",
  name: "WSOL",
  decimals: 9,
};

const SAROS_TOKEN_DEVNET: Token = {
  id: "saros",
  mintAddress: "mntCAkd76nKSVTYxwu8qwQnhPcEE9JyEbgW6eEpwr1N",
  symbol: "DEXV3 - SAROS",
  name: "Dex V3 Saros",
  decimals: 6,
};

const POOL_PARAMS_DEVNET = {
  address: "C8xWcMpzqetpxwLj7tJfSQ6J8Juh1wHFdT5KrkwdYPQB",
  baseToken: SAROS_TOKEN_DEVNET,
  quoteToken: SOL_TOKEN_DEVNET,
  slippage: 0.5,
  hook: "", // config for reward, adding later
};

Usage​

RemoveLiquidity.tsx
TypeScript
const removeLiquidity = async () => {
  try {
    const baseToken = C98_TOKEN;
    const quoteToken = USDC_TOKEN;

    const payer = new PublicKey(userAddress);
    const pair = new PublicKey(POOL_PARAMS.address);
    const type = RemoveLiquidityType.BOTH;
    const connection = liquidityBookService.connection;

    if (!type) {
      throw new Error("Invalid Liquity Type")
    }

    const pairInfo = await liquidityBookService.getPairAccount(pair);
    const activeId = pairInfo.activeId;

    const range = [activeId - 3, activeId + 3] as [number, number];

    const userPositions = await liquidityBookService.getUserPositions({
      payer,
      pair
    });

    const positionList = userPositions.filter((item: PositionInfo) => {
      return !(item.upperBinId < range[0] || item.lowerBinId > range[1]);
    })

    if (!positionList.length) throw Error("No position found in this range");

    const maxPositionList = positionList.map((item: PositionInfo) => {
      const start = range[0] > item.lowerBinId ? range[0] : item.lowerBinId;
      const end = range[1] < item.upperBinId ? range[1] : item.upperBinId;

      return {
        position: item.position,
        start,
        end,
        positionMint: item.positionMint
      }
    });


    const { blockhash, lastValidBlockHeight } = await connection. getLatestBlockhash({
      commitment: "confirmed",
    });

    const { txs, txCreateAccount, txCloseAccount } =
    await liquidityBookService.removeMultipleLiquidity({
      maxPositionList: maxPositionList,
      payer,
      type,
      pair: new PublicKey(pair),
      tokenMintX: new PublicKey(baseToken.mintAddress),
      tokenMintY: new PublicKey(quoteToken.mintAddress),
      activeId,
    });

    const allTxs = [...txs];

    if (txCreateAccount) {
      allTxs.unshift(txCreateAccount);
    }
    if (txCloseAccount) {
      allTxs.push(txCloseAccount);
    }

    allTxs.forEach((tx) => {
      tx.feePayer = payer;
      tx.recentBlockhash = blockhash;
    });

    return allTxs;
  } catch (error) {
    if (error instanceOf Error) console.error(error.message);
  }

}