Type/to search
Built-in Functions
Structures
Built-in Variables and Constants
Conventions
Exchanges
Capability Matrix
Centralized Exchanges
Decentralized Exchanges (DEX)
Prediction Markets
Securities and Futures
On-chain & Custom

Collect a position's fees and farm rewards without touching the principal.

exchange.IO(k, positionIds)
exchange.IO(k, positionIds, sell)
exchange.IO(k, id1, id2, ...)

Examples

Collect from every position whose uncollected fees exceed 1 USDC.

javascript
function main() { var list = exchange.IO("lp.positions", "SOL_USDC") if (!list) { Log("Query failed:", GetLastError()) return } var ids = list.filter(function(p) { return p.feesValue > 1 }).map(function(p) { return p.id }) if (ids.length == 0) { Log("Nothing to collect") return } var r = exchange.IO("lp.collect", ids) if (!r) { Log("Collect failed:", GetLastError()) return } r.positions.forEach(function(p) { Log(p.id, "fees", p.feesBase, "SOL", p.feesQuote, "USDC", "rewards", JSON.stringify(p.rewards)) }) }

Returns

TypeDescription

object / null value

{txHash, txHashes, positions, sells}: txHash is the first transaction signature and txHashes all of them; each item of positions is one position's {id, symbol, txHashes, principalBase, principalQuote, feesBase, feesQuote, receivedBase, receivedQuote, rewards, rentRefundSol, feeSol}, and sells lists the swaps back to the quote token, see the remarks. A null value is returned when a position does not belong to this wallet, a simulation fails or a transaction fails.

Arguments

NameTypeRequiredDescription

k

string

Yes

Set to lp.collect to collect fees and rewards.

positionIds

array / string

Yes

An array of position IDs; several IDs may also be passed as separate arguments. IDs are written as the id of lp.positions and must all belong to this wallet.

sell

bool

No

With true the base token collected is sold for the quote token with a Jupiter market order. Default false.

See Also

Remarks

One transaction per position: claim_fee2 and claim_reward2 on DLMM, a zero-liquidity decrease_liquidity_v2 on Raydium (which also settles all of the pool's initialized rewards), and update_fees_and_rewards + collect_fees_v2 + collect_reward_v2 on Orca. The position and its liquidity stay as they are; the principal part principalBase, principalQuote is normally 0.

lp.decrease and lp.remove collect fees and rewards as well, so there is no need to collect before withdrawing. Collecting costs a network fee, which is not worth it for tiny fees: check feesValue of lp.positions first.

Position rows in the result
FieldDescription
receivedBase, receivedQuoteThe two token amounts actually received (from the balances before and after)
feesBase, feesQuoteThe fee part of them (split off by the amounts claimable on chain before sending)
principalBase, principalQuoteThe principal part = received − fees
rewardsFarm rewards collected, [{mint, symbol, amount}] (excluding the pool's two tokens)
rentRefundSolRent returned by closing (SOL)
feeSolNetwork 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.