This guide shows how to remove liquidity from a V2.2 pool using the SDKs, and Viem. In this example, we will be removing liquidity from a LBPair of USDC/USDC.e/1bps
1. Required imports and constants for this guide
Imports
import { ChainId, Token } from '@traderjoe-xyz/sdk-core'
import { PairV2, LB_ROUTER_V22_ADDRESS, jsonAbis, } from '@traderjoe-xyz/sdk-v2'
import { getContract, createPublicClient, createWalletClient, http, BaseError, ContractFunctionRevertedError } from 'viem'
import { privateKeyToAccount } from 'viem/accounts'
import { avalanche } from 'viem/chains'
import { config } from 'dotenv';
Note that in your project, you most likely will not hardcode the private key at any time. You would be using libraries like or to connect to a wallet, sign messages, interact with contracts, and get the values for PROVIDER, SIGNER and ACCOUNT
const pair = new PairV2(USDC, USDC_E)
const binStep = Number(BIN_STEP)
const pairVersion = 'v22'
const lbPair = await pair.fetchLBPair(binStep, pairVersion, publicClient, CHAIN_ID)
if (lbPair.LBPair == "0x0000000000000000000000000000000000000000") {
console.log("No LB pair found with given parameters")
return
}
const lbPairData = await PairV2.getLBPairReservesAndId(lbPair.LBPair, pairVersion, publicClient)
const activeBinId = lbPairData.activeId.toNumber()
Liquidity positions
Use the below code to fetch your positions directly from chain. You need all the binIds where you have liquidity and the amount of liquidity in each bin.
const pairContract = getContract({ address: lbPair.LBPair, abi: LBPairV21ABI })
const range = 200 // should be enough in most cases
const addressArray = Array.from({ length: 2 * range + 1 }).fill(account.address);
const binsArray = [];
for (let i = activeBinId - range; i <= activeBinId + range; i++) {
binsArray.push(i);
}
const allBins: Bigint[] = await publicClient.readContract({
address: pairContract.address,
abi: pairContract.abi,
functionName: 'balanceOfBatch',
args: [addressArray, binsArray]
})
const userOwnedBins = binsArray.filter((bin, index) => allBins[index] != 0n);
const nonZeroAmounts = allBins.filter(amount => amount !== 0n);
Please take note, that we aren't fetching ERC20 token amounts underlying for this example. This results in using parameters amountXmin and amountYmin equal to zero. Calculating them would require additionally:
Fetch tokenSupply of all owned bins
Fetch reserves of all owned bins
Calculate reserves owned by user (ownedReserves * liquidityOwned / totalSupply)
Applying desired slippage to above.
This process will become easier, when public API is opened.