Перейти к основному содержанию
Эта страница переведена с помощью ИИ. За эталон принимается английская версия.Открыть английскую версию →
Эта страница дополняет products/clmm/accounts (описание аккаунтов) и products/clmm/math (описание математики). Здесь приведены авторитетные сведения об аргументах и порядке аккаунтов; конкретные байтовые раскладки берите из IDL.

Список инструкций

Большинство инструкций только для admin (CreateAmmConfig, UpdateAmmConfig, UpdatePoolStatus, CreateSupportMintAssociated, CreateOperationAccount, UpdateOperationAccount, CloseProtocolPosition) защищены захардкоженным pubkey admin программы. Инструкции admin потока вознаграждений (TransferRewardOwner, CollectRemainingRewards) защищены фандером вознаграждения, а не admin программы. Суффикс V2 означает «поддержка Token-2022 на хранилищах/NFT, требуется слот bitmap-extension». SDK по умолчанию использует V2 для новых пулов.

CreatePool

Аргументы
Аккаунты (сокращённо) Предусловия
  • token_mint_0 < token_mint_1 по порядку байт.
  • amm_config.disable_create_pool == false.
  • Минты не отклонены белым списком расширений Token-2022.
Постусловия
  • pool_state.sqrt_price_x64 = sqrt_price_x64, tick_current = floor(log_{1.0001}(price)).
  • pool_state.liquidity = 0 (позиций ещё нет).
  • pool_state.fee_on = FromInput (устаревшее значение по умолчанию).
  • pool_state.dynamic_fee_info обнулён (динамическая комиссия отключена).

CreateCustomizablePool

Рекомендуется для новых пулов. Работает так же, как CreatePool, добавляя режим сбора комиссий на уровне пула и опциональное включение динамической комиссии. Аргументы
Аккаунты (сокращённо) — те же, что у CreatePool, плюс при enable_dynamic_fee = true: Предусловия — те же, что у CreatePool. Если enable_dynamic_fee = false, dynamic_fee_config игнорируется. Постусловия
  • pool_state.fee_on устанавливается в выбранный вариант CollectFeeOn.
  • Если динамическая комиссия включена: pool_state.dynamic_fee_info инициализируется из переданного DynamicFeeConfig (копируются пять калибровочных параметров; поля состояния обнуляются).
  • В противном случае: pool_state.dynamic_fee_info обнулён (динамическая комиссия навсегда неактивна для этого пула).
fee_on и бит включения динамической комиссии устанавливаются только при создании пула. Обновление на месте невозможно — пулы, созданные через устаревший CreatePool, не могут получить динамическую комиссию или одностороннюю комиссию задним числом. Для новых развёртываний следует использовать эту инструкцию.

OpenPositionV2 / OpenPositionWithToken22Nft

Создать новую позицию в существующем пуле. Аргументы
Аккаунты (сокращённо) Математика — см. products/clmm/math. По значению base_flag программа приводит либо liquidity, либо (amount_0_max, amount_1_max) к фактическому L и фактически потреблённым суммам токенов. Предусловия
  • tick_lower < tick_upper, оба кратны pool.tick_spacing, в диапазоне [MIN_TICK, MAX_TICK].
  • Требуемые массивы тиков переданы и инициализированы (или созданы здесь через CPI InitTickArray в транзакции).
  • У пользователя не менее amount_0_max и amount_1_max в исходных ATA.
Постусловия
  • personal_position существует, liquidity установлено, fee_growth_inside_last зафиксировано.
  • Записи массива тиков на tick_lower и tick_upper обновлены (liquidity_gross += L, liquidity_net ± L, снимки роста комиссий сохранены).
  • pool_state.liquidity += L, если позиция в диапазоне (tick_lower ≤ tick_current < tick_upper).
Частые ошибкиInvalidTickIndex, NotApproved, ZeroAmountSpecified, TransactionTooLarge (при слишком большом количестве массивов тиков).

IncreaseLiquidityV2

Добавить ликвидность в уже открытую позицию. Аргументы
Аккаунты — как у OpenPosition, за исключением минта NFT (позиция уже существует; NFT передаётся как ATA владельца, содержащая 1 токен). Эффект
  • Переводит amount_0_actual / amount_1_actual от пользователя в хранилища.
  • Увеличивает personal_position.liquidity и pool_state.liquidity (если в диапазоне), а также liquidity_gross / liquidity_net граничных тиков.
  • Собирает комиссии и вознаграждения, накопленные с последнего обращения, и зачисляет их в tokens_fees_owed_{0,1} / reward_amount_owed. Выплата происходит только при вызове DecreaseLiquidity или CollectReward, но не при увеличении позиции.

DecreaseLiquidityV2

Снять ликвидность из позиции. Аргументы
Аккаунты — такая же структура, как у IncreaseLiquidity. Эффект
  • Вычисляет (amount_0, amount_1) для удалённого L при текущем sqrt_price_x64.
  • Начисляет комиссии и вознаграждения, накопленные с последнего обращения, — аналогично IncreaseLiquidity.
  • Переводит amount_0 + fees_owed_0 и amount_1 + fees_owed_1 из хранилищ пользователю.
  • Уменьшает счётчики ликвидности; если новое personal_position.liquidity == 0, позицию можно закрыть через ClosePosition.
Slippageamount_0_min и amount_1_min — минимумы, которые пользователь принимает с учётом комиссий за перевод Token-2022 на стороне вывода.

ClosePosition

Сжечь NFT позиции и закрыть PersonalPositionState. Предусловия
  • personal_position.liquidity == 0.
  • tokens_fees_owed_{0,1} == 0.
  • Все счётчики вознаграждений reward_amount_owed == 0.
(То есть сначала необходимо всё собрать и уменьшить позицию до нуля.) Эффект
  • Сжигает NFT.
  • Закрывает аккаунт минта NFT и аккаунт personal_position, возвращая ренту payer.

SwapV2

Обход кривой ликвидности; точный ввод или точный вывод в зависимости от is_base_input. Аргументы
Аккаунты (сокращённо) Вызывающий передаёт ранжированный список массивов тиков, охватывающих ожидаемый обход swap; программа использует столько, сколько нужно. SDK вычисляет этот список через PoolUtils.computeAmountOutFormat или конечную точку котировок API. Предусловия
  • pool_state.status разрешает swap.
  • now >= open_time.
  • sqrt_price_limit_x64 находится на корректной стороне от sqrt_price_x64 для выбранного направления.
Частые ошибкиExceededSlippage, SqrtPriceLimitOverflow, TickArrayNotFound, LiquidityInsufficient. Что SwapV2 делает внутри и что важно знать вызывающему (релиз после 2025 года):
  1. Надбавка динамической комиссии — если pool.dynamic_fee_info ненулевой, программа обновляет аккумулятор волатильности, используя расстояние по тикам, пройденное с момента последнего swap (с правилами фильтра/затухания из products/clmm/fees), и добавляет dynamic_fee_component поверх AmmConfig.trade_fee_rate. Суммарная комиссия ограничена 10% (MAX_FEE_RATE_NUMERATOR / 1_000_000).
  2. Исполнение лимитных ордеров — когда обход цены пересекает тик с открытыми лимитными ордерами, программа сначала исполняет доступную ликвидность лимитных ордеров на этом тике (FIFO по order_phase), затем продолжает по кривой ликвидности LP. Исполненные суммы обновляют tick.unfilled_ratio_x64 и tick.part_filled_orders_remaining для последующего расчёта; сами ордера остаются незавершёнными до тех пор, пока владелец не вызовет SettleLimitOrder.
  3. Маршрутизация комиссий на одну сторону — при pool.fee_on = Token0Only или Token1Only шаг swap по-прежнему вычисляет то же соотношение ввода и вывода; комиссия затем направляется на настроенную сторону. Для направлений, где настроенная сторона комиссии является выводом, комиссия вычитается из вывода swap (пользователь получает out − fee); для направлений, где это ввод, поведение совпадает с FromInput. См. is_fee_on_input(zero_for_one) и is_fee_on_token0(zero_for_one) на PoolState.
Swap (V1) реализует те же динамическую комиссию, маршрутизацию комиссий на одну сторону и исполнение лимитных ордеров, что и SwapV2; единственная недостающая возможность — поддержка Token-2022: оба хранилища должны быть классическим SPL Token. Пулы с любым минтом Token-2022 должны использовать SwapV2 для swap-операций. Агрегатор и SDK уже предпочитают V2 для каждого плеча CLMM, поэтому вызывающим не нужно ветвиться по типу минта.

OpenLimitOrder

Разместить ордер на продажу на конкретном тике. Ордер находится в FIFO-когорте на тике и исполняется по мере прохождения цены. Аргументы
Аккаунты (сокращённо) Предусловия
  • tick_index % pool.tick_spacing == 0 и в диапазоне [MIN_TICK, MAX_TICK].
  • tick_index находится на правильной стороне от pool.tick_current для выбранного направления (продажа token0 → тик должен быть выше текущего, и наоборот). Продажа на уже пройденном тике будет немедленно исполнена и отклонена.
  • pool_state.status разрешает операцию с лимитным ордером (бит 5).
Постусловия
  • limit_order существует, зафиксированы tick.order_phase и tick.unfilled_ratio_x64 на момент открытия.
  • tick.orders_amount += amount (в текущей когорте).
  • limit_order_nonce.order_nonce += 1.
  • Эмитировано OpenLimitOrderEvent.
Частые ошибкиInvalidLimitOrderAmount (ноль или ниже минимума пула), InvalidTickIndex (за пределами [MIN_TICK, MAX_TICK] или не на той стороне от tick_current для выбранного направления), TickAndSpacingNotMatch (tick_index % pool.tick_spacing != 0), OrderPhaseSaturated.

IncreaseLimitOrder

Увеличить существующий открытый ордер. Может вызвать только owner ордера. Аргументы
Аккаунты — как у OpenLimitOrder, без nonce-аккаунта; PDA limit_order передаётся напрямую. Предусловия
  • limit_order.owner == signer.
  • Ордер всё ещё находится в той же когорте (tick.order_phase == limit_order.order_phase). Если когорта уже начала исполняться, ордер частично завершён — вызывающему следует сначала вызвать DecreaseLimitOrder или SettleLimitOrder для продвижения вперёд.
Эффект
  • Переводит amount из ATA владельца в input_vault.
  • limit_order.total_amount += amount; tick.orders_amount += amount.

DecreaseLimitOrder

Уменьшить или полностью отменить открытый ордер. Возвращает владельцу неисполненный остаток плюс любой вывод, уже зачисленный предыдущими частичными исполнениями. Аргументы
Аккаунты — обе стороны: входной и выходной токены: Эффект
  • Пересчитывает исполненную сумму ордера по unfilled_ratio_x64 когорты с момента открытия.
  • Отправляет исполненный вывод на output_token_account.
  • Возвращает amount неисполненного ввода на input_token_account.
  • Соответственно обновляет limit_order. Если новый неисполненный остаток равен нулю, программа закрывает аккаунт и возвращает ренту owner.

SettleLimitOrder

Передать исполненные выходные токены владельцу, не изменяя неисполненный остаток ордера. Полезно, когда keeper-ы с auto_withdraw хотят постепенно выплачивать долгосрочные частичные исполнения. Вызывающий — либо owner ордера, либо limit_order_admin программы (офчейновый операционный горячий кошелёк, выполняющий автоматический keeper-цикл). У keeper-а нет других полномочий — он не может перемещать средства пользователей за пределами передачи исполненного вывода на ATA owner ордера. Аккаунты Эффект
  • Вычисляет накопленный вывод по (limit_order.unfilled_ratio_x64, tick.unfilled_ratio_x64).
  • Переводит дельту на output_token_account.
  • Обновляет limit_order.settled_output.
  • Не закрывает ордер; он остаётся открытым против любого оставшегося ввода.

CloseLimitOrder

Закрыть полностью исполненный аккаунт ордера. Рента всегда возвращается limit_order.owner независимо от того, кто подписывает. Вызывающий — либо owner, либо limit_order_admin. Предусловия
  • Неисполненный остаток ордера равен нулю (либо amount == total_amount было исполнено и рассчитано, либо владелец ранее уменьшил ордер до нуля и забыл закрыть).
Эффект
  • Закрывает limit_order; рента отправляется limit_order.owner.

CreateDynamicFeeConfig (admin)

Создать переиспользуемый набор параметров с индексом u16. Аргументы
Аккаунты Частые ошибкиInvalidDynamicFeeConfigParams, если decay_period <= filter_period или любое поле с нулевым значением выходит за допустимые пределы.

UpdateDynamicFeeConfig (admin)

Изменить существующий DynamicFeeConfig. Пулы, уже снявшие снимок конфига при создании, не обновляются задним числом; новые значения подхватят только пулы, созданные после этого изменения и ссылающиеся на данный конфиг. Аргументы — те же пять калибровочных полей, что у CreateDynamicFeeConfig (filter_period, decay_period, reduction_factor, dynamic_fee_control, max_volatility_accumulator); index фиксируется при создании и здесь не передаётся повторно.

CollectProtocolFee / CollectFundFee

Идентичны по форме аналогичным инструкциям CPMM. Подписант должен совпадать с AmmConfig.owner / AmmConfig.fund_owner. Очищает накопленные протокольные/фондовые комиссии из хранилищ пула в адрес получателя, обнуляя соответствующие поля PoolState.protocol_fees_* / fund_fees_*.

InitializeReward

Подключить новый поток вознаграждений к пулу. Одновременно может быть активно не более 3 потоков. Аргументы
Аккаунты Предусловия
  • На пуле активно менее 3 потоков.
  • Фандер вносит total_emission = emissions_per_second × (end_time − open_time) токенов вознаграждения в хранилище в рамках этой инструкции.
  • Минт вознаграждения входит в белый список operation_state.

SetRewardParams

Продлить, пополнить или изменить скорость эмиссии существующего потока вознаграждений. Обычно вызывается создателем пула или мультисигом Raydium. Ограничения хранятся ончейн: как правило, можно увеличить end_time или эмиссию, но нельзя уменьшить их задним числом. Проверьте список владельцев operation_state.

UpdateRewardInfos

Чисто бухгалтерская операция — начисляет reward_growth_global_x64 до текущего момента путём умножения emissions_per_second × Δt / liquidity. Вызывается внутри каждой инструкции, затрагивающей ликвидность. Доступна как самостоятельная инструкция, поскольку внешние участники (UI, кранки) иногда хотят запустить её явно.

CollectReward

Владелец позиции забирает накопленные токены вознаграждения. Аккаунты Эффект
  • Начисляет рост вознаграждений (по той же схеме, что и комиссии).
  • Переводит причитающуюся сумму на ATA получателя, обнуляет reward_amount_owed[i].

Матрица изменения состояния

Что дальше

Источники: