Close Position

Remove all remaining liquidity and burn the position NFT in a single transaction. This method efficiently withdraws all tokens and fees before permanently closing the position.

Prerequisites

Before closing a position:

  • Own the position NFT you want to close

  • Have sufficient gas for transaction

  • Understand this action is irreversible

  • Consider claiming fees first if needed separately

Basic Usage

// Get the pair
const pair = await sdk.Pair.getPair(pairAddress);
const positionId = "0x123...abc";

// Remove all liquidity and close position
const tx = await sdk.Pair.removeAndClosePosition(pair, positionId);

// Execute transaction
const result = await sdk.fullClient.signAndExecuteTransaction({
  transaction: tx,
  signer: keypair
});

console.log("Position closed:", result.digest);

Method Signature

async removeAndClosePosition(
  pair: LBPair, 
  positionId: string, 
  tx?: Transaction
): Promise<Transaction>

Parameters

  • pair: The LBPair where position exists

  • positionId: Position NFT to close

  • tx: Optional existing transaction to append to

Returns

  • Transaction that removes liquidity and burns NFT

  • Tokens are automatically sent to sender

How It Works

The method performs these steps automatically:

  1. Fetch position bins - Identifies all bins with liquidity

  2. Remove liquidity - Withdraws from all active bins

  3. Collect fees - Claims accumulated trading fees

  4. Close position - Burns the position NFT

  5. Transfer tokens - Sends all tokens to owner

Complete Example

// Close position with validation
async function closePositionSafely(pair: LBPair, positionId: string) {
  try {
    // Verify ownership
    const userPositions = await sdk.Position.getLbPositions([pair.id]);
    const ownsPosition = userPositions.some(p => p.id === positionId);
    
    if (!ownsPosition) {
      throw new Error("You don't own this position");
    }
    
    // Check current value before closing
    const bins = await sdk.Position.getPositionBins(pair, positionId);
    console.log(`Closing position with ${bins.length} active bins`);
    
    // Close position
    const tx = await sdk.Pair.removeAndClosePosition(pair, positionId);
    
    return await sdk.fullClient.signAndExecuteTransaction({
      transaction: tx,
      signer: keypair
    });
    
  } catch (error) {
    console.error("Failed to close position:", error);
    throw error;
  }
}

Handling Empty Positions

// The method handles empty positions gracefully
const bins = await sdk.Position.getPositionBins(pair, positionId);

if (bins.length === 0) {
  console.log("Position is empty, will only burn NFT");
}

// Still safe to call - will just burn the empty NFT
const tx = await sdk.Pair.removeAndClosePosition(pair, positionId);

Batch Operations

// Close multiple positions in one transaction
const tx = new Transaction();

for (const positionId of positionsToClose) {
  await sdk.Pair.removeAndClosePosition(pair, positionId, tx);
}

// Execute all closures at once
await sdk.fullClient.signAndExecuteTransaction({
  transaction: tx,
  signer: keypair
});

Alternative Approaches

Manual Two-Step Process

// Step 1: Remove all liquidity (keep position)
const bins = await sdk.Position.getPositionBins(pair, positionId);
const binIds = bins.map(b => b.id);

const removeTx = await sdk.Pair.removeLiquidity(pair, {
  positionId,
  binIds
});

// Step 2: Close empty position later
const closeTx = TransactionUtil.closePosition(
  pair, 
  { positionId }, 
  sdk.sdkOptions
);

Partial Withdrawal Before Closing

// Remove from specific bins first
await sdk.Pair.removeLiquidity(pair, {
  positionId,
  binIds: [8388608, 8388609] // Selected bins only
});

// Then close position with remaining liquidity
await sdk.Pair.removeAndClosePosition(pair, positionId);

What Happens to Your Assets

When closing a position:

  • Liquidity tokens are burned

  • Token X and Y are returned based on current bin reserves

  • Accumulated fees are included in the withdrawal

  • Position NFT is permanently destroyed

  • All assets are sent to transaction sender

Common Use Cases

  1. Exit Strategy: Complete withdrawal from a pool

  2. Position Migration: Close old positions before creating new ones

  3. Portfolio Cleanup: Remove empty or underperforming positions

  4. Emergency Exit: Quick withdrawal of all funds

Error Handling

try {
  await sdk.Pair.removeAndClosePosition(pair, positionId);
} catch (error) {
  if (error.message.includes("Invalid sender address")) {
    console.error("Set valid sender address first");
  } else if (error.message.includes("not match with pair")) {
    console.error("Position doesn't belong to this pair");
  }
}

Last updated