exchange.IO("lp.remove", ...)
Withdraw a position's liquidity and claim fees and rewards; withdrawing everything closes the position and returns its rent.
exchange.IO(k, positionIds)
exchange.IO(k, positionIds, ratio)
exchange.IO(k, positionIds, ratio, sell)Examples
Close all SOL/USDC positions and sell the SOL back to USDC.
javascript
function main() {
var list = exchange.IO("lp.positions", "SOL_USDC")
if (!list || list.length == 0) {
Log("No positions")
return
}
var ids = list.map(function(p) { return p.id })
var r = exchange.IO("lp.remove", ids, 1, true)
if (!r) {
Log("Remove failed:", GetLastError())
return
}
r.positions.forEach(function(p) {
Log(p.id, "principal", p.principalBase, p.principalQuote, "fees", p.feesBase, p.feesQuote,
"rent back", p.rentRefundSol, "SOL")
})
Log("Sold:", JSON.stringify(r.sells))
}Returns
| Type | Description |
object / null value |
|
Arguments
| Name | Type | Required | Description |
k | string | Yes | Set to |
positionIds | array / string | Yes | An array of position IDs; several IDs may also be passed as separate arguments (a number after them is |
ratio | number | No | The share to withdraw, (0, 1], default 1: withdraw everything and close; below 1 only that share is withdrawn and the position stays. |
sell | bool | No | With |
See Also
Jupiter exchange.IO exchange.IO("lp.decrease") exchange.IO("lp.collect") exchange.IO("lp.positions") exchange.IO("lp.add")
Remarks
Closing
With ratio 1 the position is emptied and then closed in the same flow, its rent returned to the wallet (rentRefundSol):
- Meteora DLMM: withdraws (
remove_liquidity_by_range2), claims (claim_fee2,claim_reward2) and closes the position account (close_position_if_empty). Positions wider than 70 bins take one transaction per 70 bins. - Raydium CLMM: after
decrease_liquidity_v2empties and claims,close_positionburns the NFT and closes the NFT account, the NFT mint and the position account. - Orca Whirlpools: after emptying and claiming the position is closed with
close_position_with_token_extensionsfor Token-2022 NFT positions,close_positionfor older SPL Token NFT positions andclose_bundled_positionfor positions in a Position Bundle; the rent of the position account, the NFT mint and the NFT token account is returned. Locked positions (lock_position) fail at the simulation.
Rent paid for new BinArrays and TickArrays belongs to the pool and is not returned. With ratio below 1 this is lp.decrease for several positions at once.
Position rows in the result
| Field | Description |
|---|---|
receivedBase, receivedQuote | The two token amounts actually received (from the balances before and after) |
feesBase, feesQuote | The fee part of them (split off by the amounts claimable on chain before sending) |
principalBase, principalQuote | The principal part = received − fees |
rewards | Farm rewards collected, [{mint, symbol, amount}] (excluding the pool's two tokens) |
rentRefundSol | Rent returned by closing (SOL) |
feeSol | Network fees paid by these transactions (SOL) |
The orientation (base and quote) takes the stablecoin (then SOL) as the quote. Each item of sells is {symbol, qty, txHash}, or {symbol, qty, error} when the sale failed; sales are Jupiter market orders that wait for the broadcast only, so check them with exchange.IO("receipt").
Execution
Every transaction is simulated by the node before sending and is not sent when the simulation fails, with the reason reported (DLMM, Raydium CLMM and Orca Whirlpool error codes with their names); the compute-unit limit is the simulated usage plus headroom, and the priority fee is the 75th percentile of recent fees paid by transactions writing the same accounts, capped by exchange.IO("priorityFee"). The call returns after confirmation, with actual amounts from the balances before and after. When within 120 seconds the transaction is neither confirmed nor provably expired, the error says outcome is unknown with the signature: it may have landed, so check it with exchange.IO("receipt") before retrying.