Calculate Output Amounts

Preview exact token amounts you'll receive before removing liquidity. Essential for setting expectations and avoiding surprises from price movements.

Prerequisites

  • Position ID to analyze

  • Understanding of bin reserves and fees

  • Current pair state data

Basic Calculation

// Get amounts for all bins in position
const amounts = await sdk.Position.getPositionBinsAmount(pair, positionId);

// Calculate total returns
const totals = amounts.reduce((sum, bin) => ({
  x: sum.x + bin.amountX,
  y: sum.y + bin.amountY
}), { x: 0n, y: 0n });

console.log("Will receive:", {
  tokenX: formatUnits(totals.x, 18),
  tokenY: formatUnits(totals.y, 6)
});

Understanding the Calculation

For each bin, you receive:

Your Amount = (Your Liquidity / Total Supply) × (Reserves + Fees)

The SDK's getPositionBinsAmount handles this automatically.

Preview Specific Bins

// Calculate for selected bins only
const binsToRemove = [8388606, 8388607, 8388608];
const amounts = await sdk.Position.getPositionBinsAmount(pair, positionId);

const selectedAmounts = amounts
  .filter(bin => binsToRemove.includes(bin.id))
  .reduce((sum, bin) => ({
    x: sum.x + bin.amountX,
    y: sum.y + bin.amountY
  }), { x: 0n, y: 0n });

console.log("Selected bins will return:", selectedAmounts);

Manual Calculation Method

import { getAmountOutOfBin } from '@ferra-labs/dlmm';

// For precise control
async function calculateBinReturns(
  pair: LBPair,
  positionId: string,
  binId: number
) {
  // Get position's liquidity in bin
  const positionBins = await sdk.Position.getPositionBins(pair, positionId);
  const positionLiquidity = positionBins.find(b => b.id === binId)?.liquidity || 0n;
  
  // Get bin reserves and total supply
  const reserves = await sdk.Pair.getPairReserves(pair);
  const binReserve = reserves.find(r => r.id === binId);
  const totalSupply = await getTotalSupply(pair, binId);
  
  // Calculate output
  return getAmountOutOfBin(binReserve, positionLiquidity, totalSupply);
}

Compare to Initial Investment

// Track profit/loss
const currentAmounts = await sdk.Position.getPositionBinsAmount(pair, positionId);
const currentValue = {
  x: currentAmounts.reduce((sum, b) => sum + b.amountX, 0n),
  y: currentAmounts.reduce((sum, b) => sum + b.amountY, 0n)
};

// Compare to initial (stored elsewhere)
const pnl = {
  tokenX: currentValue.x - initialDeposit.x,
  tokenY: currentValue.y - initialDeposit.y
};

console.log("P&L:", pnl);

Include Price Impact

// Consider current price vs entry
const currentPrice = getPriceFromBinId(
  pair.parameters.active_id,
  Number(pair.binStep)
);

// Value in quote token
const totalValueUSD = 
  Number(totals.x) * currentPrice + 
  Number(totals.y);

console.log("Total value:", totalValueUSD);

Preview with Slippage

// Add safety margin for price movements
const slippage = 0.01; // 1%

const minAmounts = {
  x: totals.x * BigInt(Math.floor((1 - slippage) * 1000)) / 1000n,
  y: totals.y * BigInt(Math.floor((1 - slippage) * 1000)) / 1000n
};

console.log("Minimum expected (1% slippage):", minAmounts);

Common Patterns

Full Position Preview

async function previewFullRemoval(pair: LBPair, positionId: string) {
  const amounts = await sdk.Position.getPositionBinsAmount(pair, positionId);
  
  return {
    totalX: amounts.reduce((sum, b) => sum + b.amountX, 0n),
    totalY: amounts.reduce((sum, b) => sum + b.amountY, 0n),
    binCount: amounts.length,
    bins: amounts.map(b => ({
      id: b.id,
      amountX: b.amountX,
      amountY: b.amountY
    }))
  };
}

Important Notes

  • Amounts include accumulated fees

  • Price changes affect token ratios

  • Calculation assumes no other trades

  • Always use recent data

Last updated