Skip to main content
The DLMM Pro IDL (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 as creator 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

swap is exact-in only. The program reverts with NotConsumingFullAmountIn unless the swap consumes all of input_amount. This happens when the tick arrays you pass run out of liquidity. Pass the tick arrays of a quote whose amountLeft is zero, in swap direction order (descending index for swap_for_y, ascending otherwise).
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 with client.program.methods, where Anchor exposes each instruction in camel case (for example client.program.methods.createStaticConfig(...)).

Remaining Accounts

Instructions that transfer tokens take a RemainingAccountsInfo 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 2022 approve 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 u128 that 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_amount and the max_amount caps, include the fee, and the program grosses up deposits so the reserve receives exactly the amount it needs. Amounts that a receiver gets, such as min_amount bounds and minimum_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_authority and program appear on every instruction that emits through event CPI, see Events. memo_program is 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 IncorrectATA otherwise.
  • Instructions that transfer tokens take a RemainingAccountsInfo argument, described under Remaining Accounts. The errors for it are MissingRemainingAccountForTransferHook, NoTransferHookProgram, InvalidRemainingAccountSlice, DuplicatedRemainingAccountTypes and InsufficientRemainingAccounts.
The 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 a StaticConfig: 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_mint must 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_authority as 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 OnlyY and token Y is not wrapped SOL or USDC, token_badge_y must be passed and its token_mint must 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_extension is passed it is created, marked as initialized on the pool and an EvtInitializeBitmapExtension log 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 a DynamicConfig 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 data must 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_spacing is 1 to 256, collect_fee_mode is 0 or 1, and the initial square root price is within the price bounds.
  • extensions is at most 3. Without the ActivationAccess bit, activation_point and pool_activation must be None. With it, pool_activation must be Some, activation_point of None means 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_point must be the current point, so pass None.
  • 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_liquidity to 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 OnlyY and token Y is not wrapped SOL or USDC, token_badge_y must be passed and its token_mint must 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_mint must 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_extension is passed it is created, marked as initialized on the pool and an EvtInitializeBitmapExtension log is written.
  • The pool has pool type 1 (Dynamic). The partner is set to pool_creator_authority and partner_fee_bps is copied from the config, even when it is 0, since an operator can raise it later with update_partner_fee. The activation point is parameters.activation_point, or the current point when None. 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 with user_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_x and user_token_y must have a balance above 0.
  • Pool fees are validated. The base fee mode must be 0 to 4 and its data must 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_spacing is 1 to 256, collect_fee_mode is 0 or 1, and the initial square root price is within the price bounds.
  • extensions is at most 3. Without the ActivationAccess bit, activation_point and pool_activation must be None. With it, pool_activation must be Some, activation_point of None means 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_point must be the current point, so pass None.
  • 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_liquidity to 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 OnlyY and token Y is not wrapped SOL or USDC, token_badge_y must be passed and its token_mint must 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_mint must 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_extension is passed it is created, marked as initialized on the pool and an EvtInitializeBitmapExtension log 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 when None. [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 exactly input_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 from remaining_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_amount must 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 is whitelisted_swap. Open allows always, BondingCurve allows always, TimeBased allows from its swap point.
  • The input transfer fee is taken off input_amount first. If the fee is on the input (collect fee mode OnlyY and 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. With OnlyY, 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 and partner_fee_bps is above 0, the partner takes that share of the protocol fee left after the host fee. The protocol fee left accrues in protocol_fee_x or protocol_fee_y and 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_amount is 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 to referral before 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_position and open_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 EvtInitializeBitmapExtension log. 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 when tick_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 by length_to_add observations. Anyone can call it and the payer funds the extra rent.

Arguments

Accounts

Checks and Effects

  • length_to_add is 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 payer transfers 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 to owner 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, unless owner is whitelisted_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_version 0 and delegate_permission 0. Mints exactly 1 of the NFT to owner.
  • payer pays 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 the rent_receiver of remove_position or close_position. payer also 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 EvtInitializeTickArray is 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 is whitelisted_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_version goes up by 1.
  • The position array grows and payer tops it up to the rent-exempt minimum of the new size. payer pays 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 the rent_receiver of remove_position or close_position. payer also 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_receiver to 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 is whitelisted_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_version goes 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 to rent_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 to rent_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

  • permission is at most 31.
  • Stores the bitmask on the position array. It does not approve a delegate: the owner does that with a Token 2022 approve of 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 the remaining_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_account holds 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 is whitelisted_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 u128 divided 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

Like add_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 the remaining_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 as add_liquidity with those liquidities.
  • The position must exist for the NFT: nft_account holds 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 is whitelisted_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 u128 divided 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 the remaining_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, index is a valid slot, the layout version matches, and when sqrt_price_slippage is 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 as add_liquidity for 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 None has 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 with ExceededSlippage. 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_account holds 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 is whitelisted_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 u128 divided 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 the remaining_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 is whitelisted_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_x and min_amount_y are 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_fee and claim_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 the remaining_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_liquidity with 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 is whitelisted_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_x and min_amount_y are 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_fee and claim_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_fee or claim_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 the remaining_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_x and min_amount_y are 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, and bps must 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_position and remove_position stay 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_bps is above 0, or all of period_frequency, bps_per_period and number_of_period are above 0. If any of those three is above 0, all three must be. cliff_unlock_bps + bps_per_period * number_of_period must equal exactly 10000. The cliff point is not in the past. The wait until the cliff plus period_frequency * number_of_period is 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_bps plus bps_per_period for each full period elapsed since the cliff, of the vested total, and everything after number_of_period periods. 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 to owner 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, unless owner is whitelisted_add_liquidity. BondingCurve allows only after its target is reached, TimeBased from its add liquidity point.
  • The reserve and token_mint accounts must be the ones of the deposited side. With relative_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.
  • payer pays 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 the rent_receiver of close_limit_order.
  • The deposit moves from user_token to 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 exceed max_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 until close_limit_order.

Arguments

Accounts

Remaining Accounts

Transfer hook slices from the remaining_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 is whitelisted_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 with OnlyY.
  • If the order has a referral wallet that is not the owner, referral_token is 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_x and min_amount_y are 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 to rent_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

  • permission is at most 1.
  • Stores the bitmask on the limit order. It does not approve a delegate: the owner does that with a Token 2022 approve of 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, index must be 0 or 1, and the slot must not be initialized.
  • With operator passed, its whitelisted_address must 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 and index must 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, index must be 0 or 1, and the slot must be initialized.
  • new_authority must differ from the current authority.
  • If the signer is the pool creator and index is 0, no operator is needed. Otherwise operator must be passed, its whitelisted_address must 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 the remaining_accounts_info argument. Only TransferHookReward is accepted.

Checks and Effects

  • The pool must have the LiquidityMining extension, index must be 0 or 1, the slot must be initialized, and the mint and vault must be the ones of the slot. authority must be the authority of the slot.
  • emission_per_second is 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 liquidity is 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 the remaining_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_index must 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 pool liquidity 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 the remaining_accounts_info argument. Only TransferHookReward is accepted.

Checks and Effects

  • The pool must have the LiquidityMining extension, index must be 0 or 1, the slot must be initialized, the mint and vault must be those of the slot, and authority must 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 against min_amount after 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_emission after 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 the remaining_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_x and min_amount_y are 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 the remaining_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_account must 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 against min_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 with client.program.methods.claimProtocolFee2. Only the protocol fee authority can sign it.

create_operator_account

Creates an Operator 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.
  • permission is 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 with client.program.methods.createOperatorAccount.

close_operator_account

Closes an Operator 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 with client.program.methods.closeOperatorAccount.

create_static_config

Creates a StaticConfig 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_spacing is 1 to 256, collect_fee_mode and activation_type are valid values, and extensions has 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 with client.program.methods.createStaticConfig.

create_dynamic_config

Creates a DynamicConfig 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.
  • permission is at most 1 and partner_fee_bps is at most 5000.
  • pool_creator_authority is not the default key.
  • Stores the settings. Pools created later copy partner_fee_bps, and an operator can change a pool partner fee with update_partner_fee.

Events

EvtCreateDynamicConfig is emitted.

Errors

SDK

Not wrapped by the SDK. Build it with client.program.methods.createDynamicConfig.

close_config

Closes a static or a dynamic config and sends its rent to rent_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_config and dynamic_config must 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 with client.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.
  • status is 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 with client.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_bps is 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 with client.program.methods.updatePartnerFee.