DlmmProIDL in @meteora-ag/dlmm-pro-sdk) defines 39 callable instructions. It also lists for_idl_type_generation_do_not_call, which exists only for IDL type generation and is not in the deployed program. Build user transactions with the TypeScript SDK, or call the program by CPI using the account lists in the IDL. The SDK builder for each user instruction is named in the Use column.
Instructions that emit events through event CPI include the event_authority and program accounts. See Events.
Pool Creation
All three create the pool, its two reserve vaults and its oracle. The bitmap extension is created too when you pass it. The pool creator is recorded ascreator and does not sign.
A mint that needs a token badge is checked against the access registry during creation.
CollectFeeMode.OnlyY also needs a badge for token Y unless it is wrapped SOL or USDC. See Pool Creation and Activation.
Swap
input_amount is the exact input before the input mint transfer fee. minimum_output_amount is the least you accept after the output mint transfer fee. The optional referral token account receives the host fee and must hold the fee token.
Tick Arrays and Oracle
Positions
Instructions that act on range slots take a
u64 bitmap in which bit i selects slot i. add_liquidity, add_liquidity_by_weight, add_liquidity_imbalance, remove_liquidity, remove_liquidity_by_bps, remove_position, lock_permanent_position and lock_vesting_position also take expected_layout_version (Option<u16>) and fail with InvalidLayoutVersion when it differs from the position array. Pass None (null in the SDK) to skip the check. See Positions.
Liquidity
Each instruction needs the position NFT token account (nft_account) and the tick arrays of the selected slots.
A delegate that withdraws tokens can only pay into the owner associated token accounts, or the program fails with
IncorrectATA.
Fees and Locks
Fees and rewards accrue to a slot when it is refreshed. Claim after refreshing every slot that holds liquidity.
Limit Orders
See Limit Orders.
Rewards
Rewards apply to pools with the LiquidityMining extension. A pool has 2 reward slots. See Liquidity Mining.Partner and Protocol Fees
Operator and Admin
The SDK does not wrap these. Build them withclient.program.methods, where Anchor exposes each instruction in camel case (for example client.program.methods.createStaticConfig(...)).
Remaining Accounts
Instructions that transfer tokens take aRemainingAccountsInfo argument. Its slices list { accounts_type, length } entries, and the program consumes that many remaining accounts for each slice in order from the start. accounts_type is one of TransferHookX, TransferHookY, TransferHookReferral and TransferHookReward. Each type can appear once, and it must be valid for the instruction. Pass the extra accounts a Token 2022 transfer hook program needs for that leg. Use an empty list for mints without a hook.
Tick arrays follow the transfer hook accounts. They must be writable in every instruction except refresh_fees_and_rewards, and in swap every remaining account after the hook slices must be a tick array account:
The SDK builders resolve transfer hook accounts, and
quoteExactIn returns swap tick arrays in traversal order. See the TypeScript SDK reference for each builder and Rust library for account helpers.
Delegates
The owner of a position or limit order NFT can approve a delegate on the NFT token account (a Token 2022approve of amount 0, since a non-zero delegated amount fails with DelegatedAmountNonZero) and set its permissions with update_position_delegate_permission or update_limit_order_delegate_permission.
Instruction Reference
This section lists every callable instruction in the order of the tables above. Each entry gives the arguments, the accounts in IDL order, the remaining accounts, what the program checks and changes, the events, the errors a caller can plausibly hit and the SDK builder. Conventions used in every entry:- Token amounts are in atoms, the smallest unit of the mint. Prices are square roots in Q64.64, meaning a
u128that holds the value times 2^64, and a price is token Y atoms per token X atom. Shares are in basis points, 10000 being 100%. Liquidity is an unscaled integer. - A slot or timestamp means the unit chosen by the pool
activation_type: 0 is slots, 1 is unix seconds. Rewards and the dynamic fee always use unix seconds. - A Token 2022 transfer fee is charged by the token program on every transfer. Amounts that leave a user account, such as
input_amountand themax_amountcaps, include the fee, and the program grosses up deposits so the reserve receives exactly the amount it needs. Amounts that a receiver gets, such asmin_amountbounds andminimum_output_amount, are checked after the fee. A reserve or vault pays the full amount and the receiver is credited that amount minus the fee. - An optional account that you do not need is passed as the program ID
dPro1D5wiqnGMH8vMDG23jh35btTHoWdyqXjqkqxe8n, which is how Anchor encodes an omitted optional account. - Account constraints that Anchor checks before the program logic, such as a reserve or mint that does not match the pool, a token account with the wrong mint or authority, or an account owned by the wrong program, fail with Anchor constraint errors, not with the program errors listed. The Errors tables list only program errors.
event_authorityandprogramappear on every instruction that emits through event CPI, see Events.memo_programis the Memo program, which the program calls only when a receiving Token 2022 account requires incoming transfer memos.- Delegates are described under Delegates. A delegate that pays out tokens can only pay into the associated token account of the NFT owner, and fails with
IncorrectATAotherwise. - Instructions that transfer tokens take a
RemainingAccountsInfoargument, described under Remaining Accounts. The errors for it areMissingRemainingAccountForTransferHook,NoTransferHookProgram,InvalidRemainingAccountSlice,DuplicatedRemainingAccountTypesandInsufficientRemainingAccounts.
data field of BaseFeeConfigParameters depends on base_fee_mode. Offsets count inside the 31 bytes of data, integers are little-endian and unused bytes must be zero. Fee numerators use the denominator 1000000000, so 100000 is 0.01% and 990000000 is 99%. In the formulas, the current point is the current slot or timestamp and p is the number of periods passed.
The total swap fee numerator is the base fee plus the variable fee of the dynamic fee, capped at 990000000.
The
data field of PoolActivationInfoParameters depends on activation_mode. Offsets count inside the 15 bytes of data and integers are little-endian. A pool with two activation slots allows an action only when both slots allow it, except for the whitelisted wallet of that action.
initialize_pool_with_static_config
Creates a pool from aStaticConfig: the pool account, its two reserve vaults, its oracle and, optionally, its bitmap extension. Anyone can pay for it. The config fixes the fees, tick spacing, collect fee mode, activation type and extensions, and the config pool creator authority must sign unless the config is public.
Arguments
Accounts
Checks and Effects
- Each mint is validated. The Token 2022 native mint always fails. If a token badge is passed for the mint, its
token_mintmust equal the mint and nothing else is checked. Without a badge, wrapped SOL and USDC pass, a mint owned by the Token program passes (a freeze authority is allowed), and a Token 2022 mint passes only when its extensions are limited to transfer fee, metadata pointer, token metadata and a transfer hook that has neither a program nor an authority set. - The config must name the same
pool_creator_authorityas the account. If it is not the default key, that account must sign, or the call fails. - The collect fee mode comes from the config. If it is
OnlyYand token Y is not wrapped SOL or USDC,token_badge_ymust be passed and itstoken_mintmust equal the token Y mint. - The initial price must be within the sqrt price bounds and have a tick id within the tick bounds.
- Creates the pool, the two reserves and the oracle (one empty observation, which the first swap fills). The pool starts with liquidity 0, current tick from the initial price, token flags 0 for Token and 1 for Token 2022 recorded per mint, and the activation point set as described below. If
tick_array_bitmap_extensionis passed it is created, marked as initialized on the pool and anEvtInitializeBitmapExtensionlog is written. - The pool copies the fee schedule, tick spacing, collect fee mode, activation type and extensions from the config, and has pool type 0 (Static). The activation point is the current slot or unix timestamp, by the config activation type. Static configs cannot have the ActivationAccess extension, so the pool has no activation rules and no partner. With LiquidityMining the pool has two uninitialized reward slots.
- Rent for all new accounts is charged to
payer. The config account is only read.
Events
EvtInitializePool is emitted once the pool is set up. EvtInitializeBitmapExtension is written to the log when tick_array_bitmap_extension is passed.
Errors
SDK
client.pool.initializePoolWithStaticConfig. The builder marks the config pool creator authority as a signer when it is not the default key.
initialize_pool_with_dynamic_config
Creates a pool from aDynamicConfig with fees, tick spacing, price, activation and extensions chosen by the caller. The config pool creator authority must sign. It becomes the partner of the pool and earns the config partner fee share.
Arguments
Accounts
Checks and Effects
- Pool fees are validated. The base fee mode must be 0 to 4 and its
datamust pass the checks in the base fee data table. If the dynamic fee is set, its fields must pass the ranges in the argument table, including the check that the variable fee at the cap is at most 990000000. tick_spacingis 1 to 256,collect_fee_modeis 0 or 1, and the initial square root price is within the price bounds.extensionsis at most 3. Without the ActivationAccess bit,activation_pointandpool_activationmust beNone. With it,pool_activationmust beSome,activation_pointofNonemeans the current point, and each slot is validated by its mode as in the activation data table. The slot modes must form an allowed pair. Unless a slot is TimeBased,activation_pointmust be the current point, so passNone.- TimeBased slots must not set any of the three points before the current slot or timestamp, nor more than 2592000 seconds (10368000 slots) after it, and the swap point must equal the activation point. BondingCurve slots need
whitelisted_add_liquidityto be set, a target above 10000 bps, and a target price at or below the price of the largest spacing-aligned tick id. - When the collect fee mode is
OnlyYand token Y is not wrapped SOL or USDC,token_badge_ymust be passed and itstoken_mintmust equal the token Y mint. - Each mint is validated. The Token 2022 native mint always fails. If a token badge is passed for the mint, its
token_mintmust equal the mint and nothing else is checked. Without a badge, wrapped SOL and USDC pass, a mint owned by the Token program passes (a freeze authority is allowed), and a Token 2022 mint passes only when its extensions are limited to transfer fee, metadata pointer, token metadata and a transfer hook that has neither a program nor an authority set. When the config permission bitmask has bit 0 (CreatePoolWithoutMintValidation), only the native mint rejection remains and badges are not checked for these mints. - Creates the pool, the two reserves and the oracle (one empty observation, which the first swap fills). The pool starts with liquidity 0, current tick from the initial price, token flags 0 for Token and 1 for Token 2022 recorded per mint, and the activation point set as described below. If
tick_array_bitmap_extensionis passed it is created, marked as initialized on the pool and anEvtInitializeBitmapExtensionlog is written. - The pool has pool type 1 (Dynamic). The partner is set to
pool_creator_authorityandpartner_fee_bpsis copied from the config, even when it is 0, since an operator can raise it later withupdate_partner_fee. The activation point isparameters.activation_point, or the current point whenNone. With ActivationAccess the activation rules are written to the pool tail. With LiquidityMining the pool has two uninitialized reward slots. - Rent for all new accounts is charged to
payer. The config account is only read.
Events
EvtInitializePool is emitted once the pool is set up, with pool_activation as passed. EvtInitializeBitmapExtension is written to the log when tick_array_bitmap_extension is passed.
Errors
SDK
client.pool.initializePoolWithDynamicConfig.
initialize_launch_pool
Creates a launch pool, keyed by its mint pair alone with no config. Anyone can create it by proving withuser_token_x and user_token_y that the payer holds both tokens. Nothing is transferred. The pool has no partner and a 20% protocol share of the market maker fee.
Arguments
Accounts
Checks and Effects
- Both
user_token_xanduser_token_ymust have a balance above 0. - Pool fees are validated. The base fee mode must be 0 to 4 and its
datamust pass the checks in the base fee data table. If the dynamic fee is set, its fields must pass the ranges in the argument table, including the check that the variable fee at the cap is at most 990000000. tick_spacingis 1 to 256,collect_fee_modeis 0 or 1, and the initial square root price is within the price bounds.extensionsis at most 3. Without the ActivationAccess bit,activation_pointandpool_activationmust beNone. With it,pool_activationmust beSome,activation_pointofNonemeans the current point, and each slot is validated by its mode as in the activation data table. The slot modes must form an allowed pair. Unless a slot is TimeBased,activation_pointmust be the current point, so passNone.- TimeBased slots must not set any of the three points before the current slot or timestamp, nor more than 2592000 seconds (10368000 slots) after it, and the swap point must equal the activation point. BondingCurve slots need
whitelisted_add_liquidityto be set, a target above 10000 bps, and a target price at or below the price of the largest spacing-aligned tick id. - When the collect fee mode is
OnlyYand token Y is not wrapped SOL or USDC,token_badge_ymust be passed and itstoken_mintmust equal the token Y mint. - Each mint is validated. The Token 2022 native mint always fails. If a token badge is passed for the mint, its
token_mintmust equal the mint and nothing else is checked. Without a badge, wrapped SOL and USDC pass, a mint owned by the Token program passes (a freeze authority is allowed), and a Token 2022 mint passes only when its extensions are limited to transfer fee, metadata pointer, token metadata and a transfer hook that has neither a program nor an authority set. No wallet or config can skip this validation. - Creates the pool, the two reserves and the oracle (one empty observation, which the first swap fills). The pool starts with liquidity 0, current tick from the initial price, token flags 0 for Token and 1 for Token 2022 recorded per mint, and the activation point set as described below. If
tick_array_bitmap_extensionis passed it is created, marked as initialized on the pool and anEvtInitializeBitmapExtensionlog is written. - The pool has pool type 2 (LaunchPool). It has no partner, and the protocol takes 20% of the market maker fee instead of 10%. The activation point is
parameters.activation_point, or the current point whenNone. [Open, Open] is accepted. LiquidityMining and ActivationAccess are both available. - Rent for all new accounts is charged to
payer.
Events
EvtInitializePool is emitted once the pool is set up. EvtInitializeBitmapExtension is written to the log when tick_array_bitmap_extension is passed.
Errors
SDK
client.pool.initializeLaunchPool.
swap
Exact-in swap. The caller pays exactlyinput_amount of one token and receives the other, walking the tick arrays passed in swap direction. Anyone can call it, unless the pool activation rules limit swaps to a whitelisted wallet.
Arguments
Accounts
Remaining Accounts
First the transfer hook slices fromremaining_accounts_info: TransferHookX, TransferHookY and TransferHookReferral are accepted. The hook of the input mint is used for the transfer into the reserve, the hook of the output mint for the payment to the user, and the referral slice for the host fee payment.
Then the tick arrays, all writable, in swap direction: descending tick array index when swapping token X for token Y (swap_for_y), ascending otherwise. Every remaining account after the hook slices must be a tick array account. The program starts at the tick array that holds the current tick or the next one with liquidity and skips passed accounts that are not the next array with liquidity in direction. Pass the arrays of a quote whose amountLeft is 0.
Checks and Effects
input_amountmust be above 0.- The pool must have swaps enabled in
pool_status, and when the pool has ActivationAccess every activation slot must allow swaps at the current slot or timestamp, unless the signer iswhitelisted_swap. Open allows always, BondingCurve allows always, TimeBased allows from its swap point. - The input transfer fee is taken off
input_amountfirst. If the fee is on the input (collect fee modeOnlyYand token Y in, see below), the trading fee is charged step by step and rounded up in each step: a step that ends at a tick with input left grosses the fee up from the amount it consumed, and the last step takes the fee from the input that remains. The walk consumes the input tick by tick. At each tick it fills the market maker liquidity of the range first and then, with the input left, the limit orders of that tick at the tick price, processed orders before open orders. Amounts out are rounded down, and amounts in are rounded up. - The fee token follows the collect fee mode. With
OutputToken, the fee is taken from the output side, so token Y when swapping X for Y and token X otherwise. WithOnlyY, token Y is the fee token: it is taken from the output when swapping X for Y and from the input when swapping Y for X. When the fee is on the output it is rounded up and taken from the output of each step before the output transfer fee. - The trading fee numerator is the base fee at the current slot or timestamp and price, plus the variable fee of the dynamic fee state, capped at 990000000, over 1000000000. The dynamic fee volatility state is updated before the walk and again after it.
- The fee is split between the market maker side and the limit order side by the share of the fill each one provided. The protocol takes 10% of the market maker part (20% on a launch pool) and 50% of the limit order part. Two edge cases: when the limit order fill of a step rounds down to zero output, the protocol takes the whole limit order part of that step, and when a step fills nothing at all, the protocol takes the whole fee of that step. If a referral account is passed, the host fee is 20% of the protocol fee, where the limit order part of the protocol fee counts at no more than the market maker protocol rate. The host fee is paid from the reserve to
referral. If the pool has a partner andpartner_fee_bpsis above 0, the partner takes that share of the protocol fee left after the host fee. The protocol fee left accrues inprotocol_fee_xorprotocol_fee_yand the partner fee in the pending partner fee of the fee token. The market maker part left after the protocol fee accrues to liquidity providers through the fee growth of the fee token, and the limit order part left accrues to the filled limit orders of the tick. - The walk must consume the whole input after the transfer fee and the trading fee. If the tick arrays run out first, the call fails with NotConsumingFullAmountIn. If the pool has no tick array with liquidity in the swap direction, it fails with LiquidityIsZero.
- The output transfer fee is taken off the output.
minimum_output_amountis checked against the amount after that fee. The pool sends the full output to the user, the user receives it minus the transfer fee, and the host fee is paid from the reserve toreferralbefore it. - The price, current tick id and liquidity of the pool are updated, ticks crossed update their outside fee growth and reward growth, tick arrays that become empty or non-empty flip their bits in the pool bitmap (or extension), rewards are accrued up to now on LiquidityMining pools, and BondingCurve activation slots mark their target as reached once the price has risen to the target.
- The oracle is updated with the tick before the swap. The first swap starts it. A new observation is written when at least 15 seconds have passed since the last one was created, otherwise the latest observation is updated.
Events
EvtSwap is emitted with the amounts in and out, transfer fees and the fee split. amount_in is input_amount and amount_out is after the output transfer fee.
Errors
SDK
client.pool.swap, with client.pool.quoteExactIn to choose the tick arrays.
initialize_tick_array
Creates the tick array account of one tick array index with no ticks. Anyone can call it. It does nothing when the account already exists.Arguments
Accounts
Checks and Effects
- At least one usable tick id of the array lies within the tick bounds.
- If the account does not exist, creates it with the fixed header only (pool and index, 64 bytes including the discriminator) and charges the minimum rent to
funder. The size of a tick, which is larger on a LiquidityMining pool, only matters when ticks are added later. If it exists, nothing changes and no event is emitted. - Ticks are added later by
open_position,expand_positionandopen_limit_order, which also create the tick array when it is missing, so this instruction is optional.
Events
EvtInitializeTickArray is emitted only when the account is created.
Errors
SDK
client.pool.initializeTickArray.
initialize_tick_bitmap_extension
Creates the bitmap extension of a pool, which tracks tick arrays outside indexes -512 to 511. Anyone can call it. It does nothing when the pool already has one.Arguments
This instruction takes no arguments.Accounts
Checks and Effects
- If the pool has no extension yet, creates the account, marks the pool as having one and writes an
EvtInitializeBitmapExtensionlog. Otherwise nothing changes. - Instructions that touch tick arrays outside -512 to 511 need this account. Pool creation can create it at the same time when the initial tick is outside the inline range.
Events
EvtInitializeBitmapExtension is written to the log only when the account is created. This instruction has no event authority account.
Errors
This instruction checks no arguments, so it returns no program error from the IDL. Anchor account validation errors can still occur, for example whentick_array_bitmap_extension is not the address derived for the pool.
SDK
client.pool.initializeTickBitmapExtension.
increase_oracle_length
Grows the oracle ring buffer of a pool bylength_to_add observations. Anyone can call it and the payer funds the extra rent.
Arguments
Accounts
Checks and Effects
length_to_addis above 0 and the new length is at most 500.- When the ring buffer has wrapped, the observations are rotated so that the oldest is first and the newest last, and the index moves to the newest, so history keeps its order. New empty observations are appended after it.
- The account grows by 16 bytes per observation and
payertransfers the difference to reach the rent-exempt minimum of the new size.
Events
EvtIncreaseOracleLength is emitted with the old and new lengths.
Errors
SDK
client.pool.increaseOracleLength.
open_position
Mints a position NFT toowner and creates the position array with one empty range slot per entry of tick_ranges. Anyone can call it: the payer and the new NFT mint sign, and the owner does not need to sign. No liquidity is added.
Arguments
Accounts
Remaining Accounts
Tick arrays, all writable, one per distinct tick array index that holds a lower or upper tick id of the new ranges, in ascending index order with no duplicates and no other accounts in between. A missing array is created at its derived address, so pass the address even when the account does not exist yet. An existing array must belong to the pool and carry the expected index.Checks and Effects
- The pool must have adding liquidity enabled in
pool_status, and with ActivationAccess every activation slot must allow adding liquidity at the current point, unlessowneriswhitelisted_add_liquidity. BondingCurve allows only after its target is reached, TimeBased from its add liquidity point. - Each range needs lower below upper, both multiples of the pool tick spacing and within -443636 to 443636. There are 1 to 45 ranges. Overlapping and repeated ranges are allowed.
- Creates the position array with slots in the order given, each with zero liquidity,
layout_version0 anddelegate_permission0. Mints exactly 1 of the NFT toowner. payerpays the rent of one tick entry per reference, which is every lower and upper tick id of every range, even when ranges share a tick. Missing tick arrays are created and tick arrays grow to hold new ticks. Each tick keeps a reference count that goes up by one per use. The same rent returns to therent_receiverofremove_positionorclose_position.payeralso pays the rent-exempt minimum of each tick array this call creates. Tick arrays are never closed, so that part is not refunded.- No tokens move, the pool state does not change, and no
EvtInitializeTickArrayis emitted for tick arrays created here.
Events
EvtOpenPosition is emitted with the ranges.
Errors
SDK
client.position.openPosition. The nftMint keypair must co-sign the transaction.
expand_position
Appends empty range slots to a position. The NFT owner can call it, or a delegate with the UpdatePositionRange permission. The payer funds the extra rent and does not need to be the owner.Arguments
Accounts
Remaining Accounts
Tick arrays, all writable, one per distinct tick array index that holds a lower or upper tick id of the appended ranges, in ascending index order with no duplicates and no other accounts in between. A missing array is created at its derived address, so pass the address even when the account does not exist yet. An existing array must belong to the pool and carry the expected index.Checks and Effects
- The signer must be the NFT owner, or the delegate of the NFT token account with a zero delegated amount and the UpdatePositionRange permission bit.
- The pool must have adding liquidity enabled in
pool_status, and with ActivationAccess every activation slot must allow adding liquidity at the current point, unless the NFT owner iswhitelisted_add_liquidity. BondingCurve allows only after its target is reached, TimeBased from its add liquidity point. - The new ranges follow the same rules as in
open_position, and the slot count after the call must not exceed 45. - New slots are added after the existing ones, so existing slot indexes do not change.
layout_versiongoes up by 1. - The position array grows and
payertops it up to the rent-exempt minimum of the new size.payerpays the rent of one tick entry per reference, which is every lower and upper tick id of every range, even when ranges share a tick. Missing tick arrays are created and tick arrays grow to hold new ticks. Each tick keeps a reference count that goes up by one per use. The same rent returns to therent_receiverofremove_positionorclose_position.payeralso pays the rent-exempt minimum of each tick array this call creates. Tick arrays are never closed, so that part is not refunded.
Events
EvtExpandPosition is emitted with the appended ranges.
Errors
SDK
client.position.expandPosition.
remove_position
Removes empty range slots selected by a bitmap and refunds their rent. The NFT owner can call it, or a delegate with the UpdatePositionRange permission. At least one slot must remain.Arguments
Accounts
Remaining Accounts
Tick arrays, all writable, one per distinct tick array index that holds a lower or upper tick id of the removed ranges, in ascending index order with no duplicates and no other accounts in between.Checks and Effects
- The signer must be the NFT owner, or the delegate with a zero delegated amount and the UpdatePositionRange permission. A delegate must set
rent_receiverto the owner of the NFT token account. - Removing liquidity cannot be disabled in
pool_status. With ActivationAccess every activation slot must allow removing at the current point unless the NFT owner iswhitelisted_remove_liquidity. BondingCurve allows only after its target is reached, TimeBased from its remove liquidity point. expected_layout_version, when set, must match. The bitmap must be valid as described in the argument table.- Every selected slot must be empty: no unlocked, permanently locked or vesting liquidity, no pending fees and no pending rewards.
- The remaining slots keep their relative order and move down to fill the gaps, so slot indexes change.
layout_versiongoes up by 1. - The position array shrinks and the lamports above the new rent-exempt minimum go to
rent_receiver. The reference of each removed tick is dropped, ticks without references leave their tick arrays, and the matching tick rent also goes torent_receiver.
Events
EvtRemovePosition is emitted with the bitmap and the removed ranges.
Errors
SDK
client.position.removePosition. The builder rejects a delegate that does not name the owner as rentReceiver.
close_position
Closes a position whose slots are all empty. Only the NFT owner can call it. It burns the NFT, closes the NFT token account, the NFT mint and the position array, and sends all freed rent torent_receiver.
Arguments
This instruction takes no arguments.Accounts
Remaining Accounts
Tick arrays, all writable, one per distinct tick array index that holds a lower or upper tick id of any slot of the position, in ascending index order with no duplicates and no other accounts in between.Checks and Effects
- Every slot must be empty: no liquidity of any kind, no pending fees and no pending rewards. Claim and remove first.
- Pause and activation rules do not apply: an owner can always close.
- Burns the 1 NFT, closes the NFT token account and the NFT mint (the pool authority signs for the mint), and closes the position array. The rent of all three goes to
rent_receiver. - Drops the reference of every tick of the position. Ticks without references leave their tick arrays, the arrays shrink, and the rent paid for those ticks goes to
rent_receiver.
Events
EvtClosePosition is emitted.
Errors
SDK
client.position.closePosition.
update_position_delegate_permission
Sets the permission bitmask that the NFT delegate has on a position. Only the NFT owner can call it.Arguments
Accounts
Checks and Effects
permissionis at most 31.- Stores the bitmask on the position array. It does not approve a delegate: the owner does that with a Token 2022
approveof amount 0 on the NFT token account. A delegate with a non-zero delegated amount fails every delegated call. - The bitmask stays on the position when the NFT moves, so a new owner and the delegate they approve inherit it until it is changed.
Events
EvtUpdatePositionDelegatePermission is emitted with the permission and the current delegate of the NFT token account, if any.
Errors
SDK
client.position.updatePositionDelegatePermission.
add_liquidity
Deposits chosen liquidity amounts into selected range slots of a position, paying both tokens as needed. The NFT owner can call it, or a delegate with the AddLiquidity permission.Arguments
Accounts
Remaining Accounts
Transfer hook slices from theremaining_account_info argument, then tick arrays. TransferHookX and TransferHookY are accepted. The tick arrays are all writable, in any order, and every account after the hook slices must be a tick array of the pool. Pass the arrays that hold the lower and upper tick id of every selected slot.
Checks and Effects
- The position must exist for the NFT:
nft_accountholds 1 of the position NFT. The signer must be the NFT owner, or a delegate of the token account with a zero delegated amount and the AddLiquidity permission. - The pool must have adding liquidity enabled in
pool_status, and with ActivationAccess every activation slot must allow adding liquidity at the current point, unless the NFT owner iswhitelisted_add_liquidity. BondingCurve allows only after its target is reached, TimeBased from its add liquidity point. expected_layout_version, when set, must match the position layout version.- For each selected slot the position and its ticks are brought up to date first: released vesting liquidity becomes unlocked, and fees and rewards are accrued to the position. Then the liquidity is added to the slot unlocked liquidity and to the gross liquidity of its two ticks. The net liquidity of the lower tick goes up by the same amount and the net liquidity of the upper tick goes down by it. A tick cannot hold more gross liquidity than the largest
u128divided by the number of ticks of the pool. - Pool liquidity increases only by the liquidity of slots whose range contains the current tick, meaning lower tick id at or below it and upper tick id above it.
- Token amounts follow the current price: only token X when the price is below the range, only token Y when above, both when inside. Each amount is rounded up and summed over the slots. The program then adds the Token 2022 transfer fee of each mint, so that the reserve receives exactly the required amount. The fee-included total must not exceed the matching
max_amount. Nothing is paid for a token whose total is 0. - Tick arrays that change between holding no liquidity and holding some flip their bit in the pool bitmap, or in the extension for indexes outside -512 to 511.
Events
EvtAddLiquidity is emitted with the amounts paid, which include the transfer fee, and the pool price at execution.
Errors
SDK
client.position.addLiquidity.
add_liquidity_by_weight
Likeadd_liquidity, but each slot liquidity is given as a weight times a shared multiplier. The NFT owner can call it, or a delegate with the AddLiquidity permission.
Arguments
Accounts
Remaining Accounts
Transfer hook slices from theremaining_account_info argument, then tick arrays. TransferHookX and TransferHookY are accepted. The tick arrays are all writable, in any order, and every account after the hook slices must be a tick array of the pool. Pass the arrays that hold the lower and upper tick id of every selected slot.
Checks and Effects
- Each liquidity is
multiplier * weight, then the call behaves exactly asadd_liquiditywith those liquidities. - The position must exist for the NFT:
nft_accountholds 1 of the position NFT. The signer must be the NFT owner, or a delegate of the token account with a zero delegated amount and the AddLiquidity permission. - The pool must have adding liquidity enabled in
pool_status, and with ActivationAccess every activation slot must allow adding liquidity at the current point, unless the NFT owner iswhitelisted_add_liquidity. BondingCurve allows only after its target is reached, TimeBased from its add liquidity point. expected_layout_version, when set, must match the position layout version.- For each selected slot the position and its ticks are brought up to date first: released vesting liquidity becomes unlocked, and fees and rewards are accrued to the position. Then the liquidity is added to the slot unlocked liquidity and to the gross liquidity of its two ticks. The net liquidity of the lower tick goes up by the same amount and the net liquidity of the upper tick goes down by it. A tick cannot hold more gross liquidity than the largest
u128divided by the number of ticks of the pool. - Pool liquidity increases only by the liquidity of slots whose range contains the current tick, meaning lower tick id at or below it and upper tick id above it.
- Token amounts follow the current price: only token X when the price is below the range, only token Y when above, both when inside. Each amount is rounded up and summed over the slots. The program then adds the Token 2022 transfer fee of each mint, so that the reserve receives exactly the required amount. The fee-included total must not exceed the matching
max_amount. Nothing is paid for a token whose total is 0. - Tick arrays that change between holding no liquidity and holding some flip their bit in the pool bitmap, or in the extension for indexes outside -512 to 511.
Events
EvtAddLiquidity is emitted with the amounts paid and the resulting liquidities, as for add_liquidity.
Errors
SDK
client.position.addLiquidityByWeight.
add_liquidity_imbalance
Deposits into one range slot of a position, using up to the given maximum of each token and minting the liquidity that the smaller side allows. The NFT owner can call it, or a delegate with the AddLiquidity permission.Arguments
Accounts
Remaining Accounts
Transfer hook slices from theremaining_account_info argument, then tick arrays. TransferHookX and TransferHookY are accepted. The tick arrays are all writable, in any order, and every account after the hook slices must be a tick array of the pool. Pass the arrays that hold the lower and upper tick id of the slot.
Checks and Effects
- Parameters are validated: at least one maximum is set and above 0,
indexis a valid slot, the layout version matches, and whensqrt_price_slippageis set its bounds are inside the price limits, ordered, and contain the current price. - For each side with a maximum, the amount used is the smaller of the maximum and the token account balance. The Token 2022 transfer fee is removed from it, and the liquidity that this amount buys in the slot range is computed. A side that the range cannot take at the current price gives no liquidity and is ignored. When both sides give a value, the smaller liquidity is minted, so one side may be only partly used.
- The maximum passed on to the deposit is the given maximum for a side, and 0 for a side that is
None. The call then runs asadd_liquidityfor that single slot with that liquidity, so the amounts actually paid are rounded up from the liquidity and checked against the maximums. - A side that is
Nonehas a maximum of 0. If the range needs that token at the current price, which is the case whenever the current tick is inside the range, the call fails withExceededSlippage. Use a one-sided deposit only for a range that is entirely above the current tick (token X only) or that ends at or below it (token Y only). - The position must exist for the NFT:
nft_accountholds 1 of the position NFT. The signer must be the NFT owner, or a delegate of the token account with a zero delegated amount and the AddLiquidity permission. - The pool must have adding liquidity enabled in
pool_status, and with ActivationAccess every activation slot must allow adding liquidity at the current point, unless the NFT owner iswhitelisted_add_liquidity. BondingCurve allows only after its target is reached, TimeBased from its add liquidity point. expected_layout_version, when set, must match the position layout version.- For each selected slot the position and its ticks are brought up to date first: released vesting liquidity becomes unlocked, and fees and rewards are accrued to the position. Then the liquidity is added to the slot unlocked liquidity and to the gross liquidity of its two ticks. The net liquidity of the lower tick goes up by the same amount and the net liquidity of the upper tick goes down by it. A tick cannot hold more gross liquidity than the largest
u128divided by the number of ticks of the pool. - Pool liquidity increases only by the liquidity of slots whose range contains the current tick, meaning lower tick id at or below it and upper tick id above it.
- Token amounts follow the current price: only token X when the price is below the range, only token Y when above, both when inside. Each amount is rounded up and summed over the slots. The program then adds the Token 2022 transfer fee of each mint, so that the reserve receives exactly the required amount. The fee-included total must not exceed the matching
max_amount. Nothing is paid for a token whose total is 0. - Tick arrays that change between holding no liquidity and holding some flip their bit in the pool bitmap, or in the extension for indexes outside -512 to 511.
Events
EvtAddLiquidity is emitted with a bitmap of the single slot and the liquidity minted.
Errors
SDK
client.position.addLiquidityImbalance.
remove_liquidity
Withdraws chosen liquidity amounts from selected range slots of a position and pays out the tokens. The NFT owner can call it, or a delegate with the RemoveLiquidity permission.Arguments
Accounts
Remaining Accounts
Transfer hook slices from theremaining_account_info argument, then tick arrays. TransferHookX and TransferHookY are accepted. The tick arrays are all writable, in any order, and every account after the hook slices must be a tick array of the pool. Pass the arrays that hold the lower and upper tick id of every slot that is withdrawn from.
Checks and Effects
- The signer must be the NFT owner, or a delegate of the token account with a zero delegated amount and the RemoveLiquidity permission.
- Removing liquidity cannot be disabled in
pool_status. With ActivationAccess every activation slot must allow removing at the current point unless the NFT owner iswhitelisted_remove_liquidity. BondingCurve allows only after its target is reached, TimeBased from its remove liquidity point. expected_layout_version, when set, must match the position layout version.- For each selected slot the position is brought up to date first: released vesting liquidity becomes unlocked, and fees and rewards are accrued to the position. Liquidity is then taken from the slot unlocked liquidity only, so permanently locked and still vesting liquidity cannot leave. The gross liquidity of the two ticks drops by the same amount. The net liquidity of the lower tick drops by it and the net liquidity of the upper tick rises by it. Tick references are only dropped when the slot is removed or the position is closed.
- Pool liquidity decreases only by the liquidity of slots whose range contains the current tick.
- Token amounts follow the current price and are rounded down, summed over the slots. The amounts are taken out of the reserves in full, and the receiver gets them minus the Token 2022 transfer fee of each mint.
min_amount_xandmin_amount_yare checked against the amounts after that fee, and a minimum of 0 skips the check. - Fees and rewards that the slots earned are not paid out here. They stay pending on the position until
claim_feeandclaim_reward. - A delegate can only pay into the associated token account of the NFT owner for each mint and token program. The NFT owner can pay anywhere. If the receiver is a Token 2022 account that requires incoming transfer memos, a memo is written first.
- Tick arrays that change between holding no liquidity and holding some flip their bit in the pool bitmap, or in the extension for indexes outside -512 to 511.
Events
EvtRemoveLiquidity is emitted with the amounts taken from the reserves, before the transfer fee, and the pool price at execution.
Errors
SDK
client.position.removeLiquidity.
remove_liquidity_by_bps
Withdraws a share of the unlocked liquidity of selected range slots, after releasing vested liquidity. The NFT owner can call it, or a delegate with the RemoveLiquidity permission.Arguments
Accounts
Remaining Accounts
Transfer hook slices from theremaining_account_info argument, then tick arrays. TransferHookX and TransferHookY are accepted. The tick arrays are all writable, in any order, and every account after the hook slices must be a tick array of the pool. Pass the arrays that hold the lower and upper tick id of every slot that is withdrawn from.
Checks and Effects
- Released vesting liquidity of the position is unlocked first, so the share applies to the liquidity that is unlocked now.
- For each selected slot the liquidity removed is
unlocked liquidity * bps / 10000, rounded down. Slots that give 0 are left out. If every slot gives 0 the call fails. - The rest follows
remove_liquiditywith those liquidities and bitmap. - The signer must be the NFT owner, or a delegate of the token account with a zero delegated amount and the RemoveLiquidity permission.
- Removing liquidity cannot be disabled in
pool_status. With ActivationAccess every activation slot must allow removing at the current point unless the NFT owner iswhitelisted_remove_liquidity. BondingCurve allows only after its target is reached, TimeBased from its remove liquidity point. expected_layout_version, when set, must match the position layout version.- For each selected slot the position is brought up to date first: released vesting liquidity becomes unlocked, and fees and rewards are accrued to the position. Liquidity is then taken from the slot unlocked liquidity only, so permanently locked and still vesting liquidity cannot leave. The gross liquidity of the two ticks drops by the same amount. The net liquidity of the lower tick drops by it and the net liquidity of the upper tick rises by it. Tick references are only dropped when the slot is removed or the position is closed.
- Pool liquidity decreases only by the liquidity of slots whose range contains the current tick.
- Token amounts follow the current price and are rounded down, summed over the slots. The amounts are taken out of the reserves in full, and the receiver gets them minus the Token 2022 transfer fee of each mint.
min_amount_xandmin_amount_yare checked against the amounts after that fee, and a minimum of 0 skips the check. - Fees and rewards that the slots earned are not paid out here. They stay pending on the position until
claim_feeandclaim_reward. - A delegate can only pay into the associated token account of the NFT owner for each mint and token program. The NFT owner can pay anywhere. If the receiver is a Token 2022 account that requires incoming transfer memos, a memo is written first.
- Tick arrays that change between holding no liquidity and holding some flip their bit in the pool bitmap, or in the extension for indexes outside -512 to 511.
Events
EvtRemoveLiquidity is emitted with the bitmap of the slots withdrawn from and the liquidities removed.
Errors
SDK
client.position.removeLiquidityByBps.
refresh_fees_and_rewards
Accrues fees and rewards into the selected range slots of a position without moving tokens. The NFT owner can call it, or any delegate of the NFT token account, whatever its permissions.Arguments
Accounts
Remaining Accounts
Tick arrays that hold the lower and upper tick id of every selected slot that has liquidity, in any order. The program only reads them, so they can be read-only.Checks and Effects
- The signer must be the NFT owner or the delegate of the token account with a zero delegated amount.
- The bitmap must select at least one existing slot.
- For each selected slot with liquidity, the fees earned since its checkpoint are added to its pending fees, and on LiquidityMining pools the rewards earned are added to its pending rewards. Released vesting liquidity becomes unlocked. Slots with no liquidity are skipped. Accrual uses the fee growth and reward growth inside the range, which need both ticks of the range.
- Pool reward state is updated to the current time on LiquidityMining pools. No tokens move.
- Claim instructions pay only what has been accrued, so refresh every slot that holds liquidity before
claim_feeorclaim_reward.
Events
No event is emitted.Errors
SDK
client.position.refreshFeesAndRewards.
claim_fee
Pays out the pending fees of every slot of a position and resets them. The NFT owner can call it, or a delegate with the ClaimFee permission.Arguments
Accounts
Remaining Accounts
Transfer hook slices from theremaining_account_info argument. TransferHookX and TransferHookY are accepted. No tick arrays are needed.
Checks and Effects
- The signer must be the NFT owner, or a delegate of the token account with a zero delegated amount and the ClaimFee permission.
- Sums the pending fees of every slot and sets them to 0. Only fees already accrued to the slots are included, so refresh first (or have added or removed liquidity) to include recent swaps.
- The reserve pays the full pending amount. The receiver gets it minus the Token 2022 transfer fee.
min_amount_xandmin_amount_yare checked against the amounts after that fee, and 0 skips the check. Nothing is transferred for a token whose pending amount is 0. - A delegate can only pay into the associated token account of the NFT owner for that mint and token program. If the receiver is a Token 2022 account that requires incoming transfer memos, a memo is written first.
Events
EvtClaimFee is emitted with the amounts paid, before the transfer fee, even when both are 0.
Errors
SDK
client.position.claimFee.
lock_permanent_position
Locks a share of the unlocked liquidity of every slot of a position for good. Only the NFT owner can call it. The locked liquidity keeps earning fees and rewards but can never be removed.Arguments
Accounts
Checks and Effects
- The signer must own the NFT token account.
expected_layout_version, when set, must match, andbpsmust be 1 to 10000. - Released vesting liquidity is unlocked first, so it is included in the amount that is locked.
- Every slot moves
unlocked liquidity * bps / 10000, rounded down, from unlocked to permanently locked liquidity. All slots are affected, there is no bitmap. At least one slot must move a non-zero amount. - No tokens, ticks or pool values change. Locked liquidity stays in the pool, so fees and rewards keep accruing.
- There is no way to unlock.
close_positionandremove_positionstay blocked for a slot that holds locked liquidity.
Events
EvtLockPermanent is emitted with bps and the liquidity locked in each slot.
Errors
SDK
client.position.lockPermanentPosition.
lock_vesting_position
Moves a share of the unlocked liquidity of every slot into one vesting schedule, with an optional cliff and then periodic releases. Only the NFT owner can call it. A position can have one schedule in its lifetime.Arguments
Accounts
Checks and Effects
- The signer must own the NFT token account.
expected_layout_version, when set, must match. - Schedule rules:
cliff_unlock_bpsis above 0, or all ofperiod_frequency,bps_per_periodandnumber_of_periodare above 0. If any of those three is above 0, all three must be.cliff_unlock_bps + bps_per_period * number_of_periodmust equal exactly 10000. The cliff point is not in the past. The wait until the cliff plusperiod_frequency * number_of_periodis at most 10 years, which is 315360000 seconds or 1261440000 slots. - The position must not already have a schedule, even a fully released one.
- Every slot moves
unlocked liquidity * bps / 10000, rounded down, from unlocked to vesting liquidity. All slots are affected, there is no bitmap. At least one slot must move a non-zero amount. - Release: nothing before the cliff point. From the cliff the released share is
cliff_unlock_bpsplusbps_per_periodfor each full period elapsed since the cliff, of the vested total, and everything afternumber_of_periodperiods. Released liquidity becomes unlocked the next time the position is refreshed or its liquidity is changed. Vesting liquidity cannot be removed until released. - No tokens, ticks or pool values change. Vesting liquidity keeps earning fees and rewards.
Events
EvtLockVesting is emitted with the schedule and the liquidity moved in each slot.
Errors
SDK
client.position.lockVestingPosition.
open_limit_order
Mints a limit order NFT toowner and deposits one token into up to 25 ticks as resting orders. The owner and the payer sign. An ask order deposits token X above the current tick, a bid order deposits token Y at or below it.
Arguments
Accounts
Remaining Accounts
Transfer hook slice for the deposited token (TransferHookX for an ask order, TransferHookY for a bid order), then tick arrays, all writable. With relative_tick unset, pass one tick array per distinct tick array index of the order ticks in ascending index order. With relative_tick set, pass them in any order, extra arrays are allowed, and the program picks the ones it needs by address, so include the arrays for every offset you may land on. A missing array is created at its derived address.
Checks and Effects
- The pool must have adding liquidity enabled in
pool_status, and with ActivationAccess every activation slot must allow adding liquidity at the current point, unlessowneriswhitelisted_add_liquidity. BondingCurve allows only after its target is reached, TimeBased from its add liquidity point. - The
reserveandtoken_mintaccounts must be the ones of the deposited side. Withrelative_tick, the aligned current tick id must be inside its bounds. - Ticks: 1 to 25, strictly ascending ids, amounts above 0, valid tick ids after conversion, and on the correct side of the current tick. A tick that already holds unfilled orders accepts new orders only on the same side as the existing ones.
- Each tick adds the amount to its open order amount and records the order age of the tick. The order stores amount, age, side and tick id per entry. A tick with pending orders counts as having liquidity for the pool bitmap, so tick arrays can flip to non-empty in the bitmap or extension.
payerpays the rent of one tick entry per order tick. Missing tick arrays are created and tick arrays grow to hold new ticks. Each tick keeps a reference count that goes up by one per use. The same rent returns to therent_receiverofclose_limit_order.- The deposit moves from
user_tokento the reserve: the sum of the tick amounts plus the Token 2022 transfer fee, so that the reserve receives the sum exactly. That total must not exceedmax_amount. - Mints exactly 1 of the NFT to
owner.
Events
EvtOpenLimitOrder is emitted with the ticks as converted to absolute tick ids and the order age of each.
Errors
SDK
client.limitOrder.openLimitOrder. The nftMint keypair must co-sign the transaction.
cancel_limit_order
Cancels the order at the listed ticks and pays out the unfilled amount, the proceeds of the filled part and the owner share of the fee. The NFT owner can call it, or a delegate with the CancelLimitOrder permission. The order account and its tick references stay untilclose_limit_order.
Arguments
Accounts
Remaining Accounts
Transfer hook slices from theremaining_account_info argument (TransferHookX, TransferHookY, TransferHookReferral), then tick arrays, all writable, in any order, that hold every tick listed. Every account after the hook slices must be a tick array of the pool.
Checks and Effects
- The signer must be the NFT owner, or a delegate with a zero delegated amount and the CancelLimitOrder permission.
- Cancelling cannot be disabled in
pool_status. With ActivationAccess every activation slot must allow removing liquidity at the current point, unless the NFT owner iswhitelisted_remove_liquidity. BondingCurve allows only after its target is reached, TimeBased from its remove liquidity point. - For each tick id, the order entry must exist and not be canceled. What it gets depends on how far the tick was filled. Unfilled: the whole amount comes back in the deposited token. Partly filled: the amount is split in proportion between the unfilled part (rounded up, so earlier cancellers get slightly more of the unfilled side) and the filled part. Fully filled: the whole amount has been exchanged.
- The filled part is paid in the other token at the tick price (token Y per token X, the square of the tick square root price), rounded down, so the pool never pays out more than it took in. An ask order receives token Y and a bid order receives token X.
- The order also gets its share of the limit order fee collected at the tick, in proportion to its filled amount, rounded down. The fee token is token X for an ask order and token Y for a bid order with
OutputToken, and always token Y withOnlyY. - If the order has a referral wallet that is not the owner,
referral_tokenis passed and owned by that wallet, the referral gets 20% of the fee, rounded down, paid from the reserve of the fee token, and the owner gets the rest. Otherwise the owner gets all of it. A referral account that is missing or not owned by the referral wallet is not an error, the owner just keeps the whole fee. An account owned by the referral wallet must be for the fee token, or the transfer fails. - The owner payout is the unfilled amount plus the filled proceeds plus the owner fee, per token. It leaves the reserves in full and the receiver gets it minus the Token 2022 transfer fee.
min_amount_xandmin_amount_yare checked against the amounts after that fee. - A delegate can only pay into the associated token account of the NFT owner for that mint and token program. If a receiver is a Token 2022 account that requires incoming transfer memos, a memo is written first.
- Each canceled entry is zeroed and the tick drops the amounts. Ticks and their rent stay referenced by the order until it is closed. Tick arrays that change between holding no liquidity and holding some flip their bit in the pool bitmap, or in the extension for indexes outside -512 to 511.
Events
EvtCancelLimitOrder is emitted with the amounts paid to the owner, the fee parts and the referral fee.
Errors
SDK
client.limitOrder.cancelLimitOrder.
close_limit_order
Closes a limit order whose ticks are all canceled. Only the NFT owner can call it. It burns the NFT, closes the NFT token account, the NFT mint and the limit order account, and sends the freed rent torent_receiver.
Arguments
This instruction takes no arguments.Accounts
Remaining Accounts
Tick arrays, all writable, one per distinct tick array index of the ticks of the order, in ascending index order with no duplicates and no other accounts in between.Checks and Effects
- Every tick entry of the order must be canceled. Cancel first and claim the payout.
- Pause and activation rules do not apply: an owner can always close.
- Burns the 1 NFT, closes the NFT token account and the NFT mint (the pool authority signs for the mint), and closes the limit order. The rent of all three goes to
rent_receiver. - Drops the reference of every tick of the order and returns the rent of one tick entry per order tick to
rent_receiver. Ticks left without references are removed and their tick arrays shrink.
Events
EvtCloseLimitOrder is emitted.
Errors
SDK
client.limitOrder.closeLimitOrder.
update_limit_order_delegate_permission
Sets the permission bitmask that the NFT delegate has on a limit order. Only the NFT owner can call it.Arguments
Accounts
Checks and Effects
permissionis at most 1.- Stores the bitmask on the limit order. It does not approve a delegate: the owner does that with a Token 2022
approveof amount 0 on the NFT token account. A delegate with a non-zero delegated amount fails every delegated call. - The bitmask stays on the order when the NFT moves, so a new owner and the delegate they approve inherit it until it is changed.
Events
EvtUpdateLimitOrderDelegatePermission is emitted with the permission and the current delegate of the NFT token account, if any.
Errors
SDK
client.limitOrder.updateLimitOrderDelegatePermission.
initialize_reward
Creates the reward vault of a reward slot and sets its mint and authority. Needs an operator with the InitializeReward permission, or the pool creator for slot 0. Only pools with the LiquidityMining extension have rewards.Arguments
Accounts
Checks and Effects
- The pool must have the LiquidityMining extension,
indexmust be 0 or 1, and the slot must not be initialized. - With
operatorpassed, itswhitelisted_addressmust equal the signer and its permission bitmask must include InitializeReward. The mint is then checked like a pool mint: native Token 2022 mint fails, a passed badge must match the mint, and without a badge the mint must be supported without one (a freeze authority is allowed). - Without
operator, the signer must be the pool creator andindexmust be 0. The mint is checked the same way, but a freeze authority is not allowed without a badge, unless the mint is wrapped SOL or USDC. - Creates the vault and records the mint, the vault, the authority and the token program flag in the slot. No emission is set yet, so nothing is paid or accrued until
set_reward_emission.
Events
EvtInitializeReward is emitted.
Errors
SDK
client.reward.initializeReward. The builder covers the pool creator path only: slot 0 with no operator account. For an operator or slot 1, build it with client.program.methods.initializeReward.
update_reward_authority
Changes the authority of a reward slot. The pool creator can do it for slot 0, and an operator with the UpdateRewardAuthority permission for any slot. The current reward authority cannot change itself.Arguments
Accounts
Checks and Effects
- The pool must have the LiquidityMining extension,
indexmust be 0 or 1, and the slot must be initialized. new_authoritymust differ from the current authority.- If the signer is the pool creator and
indexis 0, no operator is needed. Otherwiseoperatormust be passed, itswhitelisted_addressmust equal the signer and its permission bitmask must include UpdateRewardAuthority. - Stores the new authority. The vault, mint and emission do not change.
Events
EvtUpdateRewardAuthority is emitted.
Errors
SDK
client.reward.updateRewardAuthority. The builder covers the pool creator path only: slot 0 with no operator account. For an operator or slot 1, build it with client.program.methods.updateRewardAuthority.
set_reward_emission
Funds the reward vault for a new emission window and sets its rate. The reward authority of the slot must sign, and a funder pays the tokens. The slot must have no emission running.Arguments
Accounts
Remaining Accounts
Transfer hook slice from theremaining_accounts_info argument. Only TransferHookReward is accepted.
Checks and Effects
- The pool must have the LiquidityMining extension,
indexmust be 0 or 1, the slot must be initialized, and the mint and vault must be the ones of the slot.authoritymust be the authority of the slot. emission_per_secondis above 0.- Pool reward state is brought up to now first. The previous window must have ended, and no ineligible reward from it may be waiting (see
withdraw_ineligible_rewards). A slot with no emission yet counts as ended. - The open time must not be before now and at most 30 days after it. The window must be 1 to 365 days.
- The whole reward for the window is paid up front into the vault: the amount is computed with rounding up, the Token 2022 transfer fee is added so the vault receives exactly that, and the total must not exceed
max_amount. - Sets the open time, end time and rate of the slot and the last update time to the open time. Rewards then accrue to in-range positions in proportion to their liquidity while the pool
liquidityis above 0.
Events
EvtSetRewardEmission is emitted with the resulting window and rate.
Errors
SDK
client.reward.setRewardEmission.
claim_reward
Pays out the pending amount of one reward slot, summed over every range slot of a position. The NFT owner can call it, or a delegate with the ClaimReward permission.Arguments
Accounts
Remaining Accounts
Transfer hook slice from theremaining_account_info argument. Only TransferHookReward is accepted. No tick arrays are needed.
Checks and Effects
- The signer must be the NFT owner, or a delegate with a zero delegated amount and the ClaimReward permission. A delegate can only pay into the associated token account of the NFT owner for the reward mint.
- The pool must have the LiquidityMining extension,
reward_indexmust be 0 or 1, the slot must be initialized, and the mint and vault must be those of the slot. - Sums the pending reward of the slot over every range slot of the position and sets it to 0. Only rewards already accrued to the range slots are included, so refresh first (or have added or removed liquidity).
- The vault pays the full amount. The receiver gets it minus the Token 2022 transfer fee, checked against
min_amount, and 0 skips the check. A memo is written first if the receiver requires incoming transfer memos. Nothing is paid when the total is 0.
Events
EvtClaimReward is emitted only when the amount paid is above 0.
Errors
SDK
client.reward.claimReward.
withdraw_ineligible_rewards
Withdraws the rewards that were emitted while the poolliquidity was 0, meaning no liquidity was in range at the current price, after the emission has ended. The reward authority of the slot signs and picks the receiving account.
Arguments
Accounts
Remaining Accounts
Transfer hook slice from theremaining_accounts_info argument. Only TransferHookReward is accepted.
Checks and Effects
- The pool must have the LiquidityMining extension,
indexmust be 0 or 1, the slot must be initialized, the mint and vault must be those of the slot, andauthoritymust be the authority of the slot. - The pool reward state is brought up to now. The emission must have been set and must have ended, meaning the last update time equals the end time and is above 0.
- The amount is the seconds counted with zero pool liquidity times
emission_per_second, divided by 2^64, rounded down. The counter is reset to 0 and the amount is checked againstmin_amountafter the transfer fee. - If the amount is 0 the call returns without moving tokens and without an event. Otherwise the vault pays the full amount, the receiver gets it minus the Token 2022 transfer fee, and a memo is written first if the receiver requires incoming transfer memos.
- The slot only counts as finished for
set_reward_emissionafter this counter is 0, so withdraw before starting a new emission.
Events
EvtWithdrawIneligibleReward is emitted only when the amount is above 0.
Errors
SDK
client.reward.withdrawIneligibleRewards.
claim_partner_fee
Pays out the accrued partner fee of a pool to receiver accounts chosen by the partner. Only the pool partner can call it.Arguments
Accounts
Remaining Accounts
Transfer hook slices from theremaining_accounts_info argument. TransferHookX and TransferHookY are accepted. No tick arrays are needed.
Checks and Effects
- The signer must equal the partner stored in the pool. Pools without a partner (static-config and launch pools) have no one who can claim.
- Claims the smaller of the pending fee and the cap, per token, and reduces the pending fee by that amount.
min_amount_xandmin_amount_yare checked against the claimed amounts after the Token 2022 transfer fee. This runs even when the amount is 0, so a minimum above 0 fails then.- If both claimed amounts are 0 the call returns without an event. Otherwise the reserve pays the full claimed amount, the receiver gets it minus the transfer fee, and a memo is written first if the receiver requires incoming transfer memos.
Events
EvtClaimPartnerFee is emitted only when at least one amount is above 0.
Errors
SDK
client.pool.claimPartnerFee.
claim_protocol_fee2
Pays out the accrued protocol fee of one token of a pool to the protocol. Only the fixed protocol fee authority can sign, so integrators cannot call it.Arguments
Accounts
Remaining Accounts
Transfer hook slices from theremaining_accounts_info argument. TransferHookX and TransferHookY are accepted.
Checks and Effects
- The signer must be the fixed address of the protocol fee authority.
- The mint of
receiver_token_accountmust be the token X or token Y mint of the pool, and the account must be owned by the token program passed for that token. - Claims the smaller of the pending protocol fee of that token and
max_amount, reduces the pending fee, and checks the amount after the transfer fee againstmin_amount. - If the amount is 0 the call returns without moving tokens and without an event. Otherwise the reserve pays the full amount and the receiver gets it minus the Token 2022 transfer fee. No memo is written.
Events
EvtClaimProtocolFee is written to the log, not as an inner instruction, and only when the amount is above 0. This instruction has no event authority account.
Errors
SDK
Not wrapped by the SDK. Build it withclient.program.methods.claimProtocolFee2. Only the protocol fee authority can sign it.
create_operator_account
Creates anOperator account that gives an address a set of operator permissions. Only the admin can call it.
Arguments
Accounts
Checks and Effects
- The signer must be the admin key, which is fixed in the program and not part of the IDL.
permissionis above 0 and uses only bits 0 to 5.- Creates the account with the whitelisted address and the bitmask. The operator account is 48 bytes after the discriminator.
Events
No event is emitted, although the instruction lists the event accounts.Errors
SDK
Not wrapped by the SDK. Build it withclient.program.methods.createOperatorAccount.
close_operator_account
Closes anOperator account and removes its permissions. Only the admin can call it.
Arguments
This instruction takes no arguments.Accounts
Checks and Effects
- The signer must be the admin key.
- Closes the account and sends its lamports to
rent_receiver. Pools and configs are not affected.
Events
No event is emitted, although the instruction lists the event accounts.Errors
SDK
Not wrapped by the SDK. Build it withclient.program.methods.closeOperatorAccount.
create_static_config
Creates aStaticConfig that fixes the fees, tick spacing, collect fee mode, activation type and extensions of pools created from it. Needs an operator with the CreateConfigKey permission.
Arguments
Accounts
Checks and Effects
- The operator must be the signer with CreateConfigKey.
- Fees are validated as in pool creation: base fee mode and data as in the base fee data table, and the dynamic fee fields as in the argument table.
tick_spacingis 1 to 256,collect_fee_modeandactivation_typeare valid values, andextensionshas no bits other than bit 0. ActivationAccess is not allowed on static configs.- Stores the settings. Pools created later copy them, so closing or replacing a config does not change existing pools.
Events
EvtCreateStaticConfig is emitted.
Errors
SDK
Not wrapped by the SDK. Build it withclient.program.methods.createStaticConfig.
create_dynamic_config
Creates aDynamicConfig that authorizes one pool creator authority to create pools with its own parameters and makes it the partner of those pools. Needs an operator with the CreateConfigKey permission.
Arguments
Accounts
Checks and Effects
- The operator must be the signer with CreateConfigKey.
permissionis at most 1 andpartner_fee_bpsis at most 5000.pool_creator_authorityis not the default key.- Stores the settings. Pools created later copy
partner_fee_bps, and an operator can change a pool partner fee withupdate_partner_fee.
Events
EvtCreateDynamicConfig is emitted.
Errors
SDK
Not wrapped by the SDK. Build it withclient.program.methods.createDynamicConfig.
close_config
Closes a static or a dynamic config and sends its rent torent_receiver. Needs an operator with the RemoveConfigKey permission.
Arguments
This instruction takes no arguments.Accounts
Checks and Effects
- The operator must be the signer with RemoveConfigKey.
- Exactly one of
static_configanddynamic_configmust be passed. - Closes it and sends its lamports to
rent_receiver. Pools already created from the config keep working, because pool creation copies the settings.
Events
EvtCloseConfig is emitted.
Errors
SDK
Not wrapped by the SDK. Build it withclient.program.methods.closeConfig.
set_pool_status
Sets the status bitmask of a pool, which disables or enables swaps and adding liquidity. Needs an operator with the SetPoolStatus permission. Removing liquidity cannot be disabled.Arguments
Accounts
Checks and Effects
- The operator must be the signer with SetPoolStatus.
statusis at most 3 and differs from the current status.- Stores the status. Swaps and deposits fail with InvalidActivationAccess while their bit is set. Withdrawals, claims and closes are not affected.
Events
EvtSetPoolStatus is emitted.
Errors
SDK
Not wrapped by the SDK. Build it withclient.program.methods.setPoolStatus.
update_partner_fee
Sets the partner fee share of a pool that has a partner. Needs an operator with the UpdatePartnerFee permission.Arguments
Accounts
Checks and Effects
- The operator must be the signer with UpdatePartnerFee.
partner_fee_bpsis at most 5000, and the pool must have a partner, which only pools from a dynamic config have.- Stores the new share. It applies to swaps after the change, and fees already accrued stay as they are.
Events
EvtUpdatePartnerFee is emitted with the old and new values.
Errors
SDK
Not wrapped by the SDK. Build it withclient.program.methods.updatePartnerFee.
