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 existspositionId
: Position NFT to closetx
: 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:
Fetch position bins - Identifies all bins with liquidity
Remove liquidity - Withdraws from all active bins
Collect fees - Claims accumulated trading fees
Close position - Burns the position NFT
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
Exit Strategy: Complete withdrawal from a pool
Position Migration: Close old positions before creating new ones
Portfolio Cleanup: Remove empty or underperforming positions
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");
}
}
Related Topics
Remove All Liquidity - Just remove without closing
Get Position Bins - Check bins before closing
Calculate Output Amounts - Preview withdrawal
Open Position - Create new positions
Last updated