Remove All Liquidity

Withdraw all liquidity from a position in a single transaction while keeping the position NFT active. Useful for complete exits without burning the NFT.

Prerequisites

  • Position ID with active liquidity

  • Understanding this keeps NFT alive

  • Gas for transaction execution

  • Consider removeAndClosePosition if burning NFT

Basic Usage

// Get all bins for the position
const bins = await sdk.Position.getPositionBins(pair, positionId);
const allBinIds = bins.map(bin => bin.id);

// Remove from all bins at once
const tx = await sdk.Pair.removeLiquidity(pair, {
  positionId: "0x123...abc",
  binIds: allBinIds
});

await sdk.fullClient.signAndExecuteTransaction({
  transaction: tx,
  signer: keypair
});

Complete Withdrawal Pattern

async function removeAllLiquidity(pair: LBPair, positionId: string) {
  // Fetch current bins
  const bins = await sdk.Position.getPositionBins(pair, positionId);
  
  if (bins.length === 0) {
    console.log("Position already empty");
    return;
  }
  
  // Remove all liquidity
  const tx = await sdk.Pair.removeLiquidity(pair, {
    positionId,
    binIds: bins.map(b => b.id)
  });
  
  return await sdk.fullClient.signAndExecuteTransaction({
    transaction: tx,
    signer: keypair
  });
}

Preview Total Returns

// Calculate what you'll receive
const amounts = await sdk.Position.getPositionBinsAmount(pair, positionId);

const totals = amounts.reduce((sum, bin) => ({
  tokenX: sum.tokenX + bin.amountX,
  tokenY: sum.tokenY + bin.amountY
}), { tokenX: 0n, tokenY: 0n });

console.log("Total withdrawal:", {
  tokenX: formatUnits(totals.tokenX, 18),
  tokenY: formatUnits(totals.tokenY, 6)
});

Remove All vs Close Position

Remove All Liquidity

// Keeps position NFT alive
await sdk.Pair.removeLiquidity(pair, {
  positionId,
  binIds: allBinIds
});
// ✅ NFT still exists (empty)
// ✅ Can add liquidity again
// ❌ Two transactions if closing later

Remove AND Close

// One transaction - removes all + burns NFT
await sdk.Pair.removeAndClosePosition(pair, positionId);
// ✅ Single transaction
// ✅ Clean exit
// ❌ Need new NFT to re-enter

Common Use Cases

Temporary Exit

// Market uncertainty - exit but keep position
const bins = await sdk.Position.getPositionBins(pair, positionId);
await sdk.Pair.removeLiquidity(pair, {
  positionId,
  binIds: bins.map(b => b.id)
});
// Can re-enter later with same NFT

Fee Collection

// Remove all to collect fees, then re-add
// Step 1: Remove everything
await removeAllLiquidity(pair, positionId);

// Step 2: Add back with new distribution
await sdk.Pair.addLiquidity(pair, {
  positionId,  // Same position
  // ... new parameters
});

What You Receive

  • All tokens from all bins

  • Accumulated trading fees

  • Based on current bin reserves

  • Single transfer to your wallet

Error Handling

try {
  const bins = await sdk.Position.getPositionBins(pair, positionId);
  
  if (bins.length === 0) {
    throw new Error("No liquidity to remove");
  }
  
  await sdk.Pair.removeLiquidity(pair, {
    positionId,
    binIds: bins.map(b => b.id)
  });
  
} catch (error) {
  console.error("Removal failed:", error);
}

Last updated