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

Инвентарь инструкций

Большинство инструкций только для администратора (CreateAmmConfig, UpdateAmmConfig, UpdatePoolStatus, CreateSupportMintAssociated, CreateOperationAccount, UpdateOperationAccount, CloseProtocolPosition) контролируются жестко закодированным публичным ключом admin программы. CreatePermissionPda / ClosePermissionPda принимают либо публичный ключ admin, либо выделенный ключ permission_pda_admin. Инструкции администратора потока вознаграждения (TransferRewardOwner, CollectRemainingRewards) контролируются финансистом вознаграждения, а не администратором программы. Суффикс V2 означает “поддерживает Token-2022 на хранилищах/NFT, требует слота расширения битовой карты”. 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, не могут ретроактивно получить динамическую комиссию или одностороннюю комиссию. Новые развертывания должны по умолчанию использовать эту инструкцию.

CreatePermissionedPool

Как CreatePool, так и CreateCustomizablePool выводят PDA пула из ["pool", amm_config, token_mint_0, token_mint_1], поэтому существует ровно один канонический адрес пула на тройку (config, mint0, mint1) — второй init с теми же семенами не удается. CreatePermissionedPool снимает это ограничение, встраивая предоставленный клиентом seed_index: u16 в семена PDA пула, позволяя несколько пулов для одной пары и уровня комиссии — каждый по своему адресу. Поскольку произвольный адрес пула — это привилегированная возможность, плательщик должен иметь PDA Permission, который его авторизует. Все остальное о пуле идентично CreateCustomizablePool: он принимает те же CreateCustomizableParams и поддерживает одностороннюю комиссию и опциональную динамическую комиссию. Аргументы
Аккаунты (сокращенно) — то же, что CreateCustomizablePool, плюс, в начале: PDA pool_state выводится из ["pool", amm_config, token_mint_0, token_mint_1, seed_index.to_le_bytes()]. Предусловия
  • seed_index != 0. seed_index из 0 зарезервирован для устаревших пулов и отклоняется здесь; компонент семени [0, 0] — это то, что заставляет адрес устаревшего пула свернуться в классическую четырехсемейную форму.
  • PDA permission для payer существует (создан администратором через CreatePermissionPda).
  • Те же правила монет/белого списка, что и CreatePool.
Постусловия
  • Новый pool_state существует по адресу, выведенному из seed_index, с pool_state.seed_index = seed_index.
  • Все остальное состояние соответствует CreateCustomizablePool (режим комиссии, опциональная динамическая комиссия).
Эта инструкция не расширяет общий доступ к созданию пула — бесправное создание продолжается через CreatePool / CreateCustomizablePool, которые остаются одним пулом на пару. CreatePermissionedPool существует для конкретного случая, когда оператор в белом списке нуждается в нескольких пулах для одной пары (например, различные начальные цены или когорты запуска) и имеет PDA Permission, предоставленный администратором.

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).
  • Минт NFT позиции записывает pool_state как полномочие заморозки. Полномочие минта удаляется после выпуска одного NFT. Запись полномочия заморозки не изменяет состояние аккаунта токена NFT.
  • Аккаунт токена NFT остается разморозенным, если инструкция не является OpenPositionV2 или OpenPositionWithToken22Nft и полномочие заморозки хранилища совпадает со списком ограниченных издателей CLMM. Только этот соответствующий путь V2 замораживает аккаунт. OpenPosition V1 не замораживает.
Распространенные ошибкиInvalidTickIndex, NotApproved, ZeroAmountSpecified, TransactionTooLarge (если слишком много массивов тиков).
Замораживание позиции не добавляет объявленные аккаунты инструкций или аргументы. Клиенты могут открывать эти позиции с существующими макетами V2. Поведение выбирается на цепи из vault_0_mint и vault_1_mint.

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.
Проскальзываниеamount_0_min и amount_1_min — это минимумы, которые пользователь принимает за вычетом комиссий передачи Token-2022 на выходной стороне.

ClosePosition

Сжечь NFT позиции и закрыть PersonalPositionState. Объявленные аккаунты Оставшиеся аккаунты
  • Разморозенный NFT: ничего не требуется; дополнительный аккаунт пула безвреден, потому что обработчик его не читает.
  • Замороженный NFT: добавить personal_position.pool_id как первый оставшийся аккаунт. Программа загружает его как PoolState и использует его семена PDA для подписания разморозки.
Предусловия
  • personal_position.liquidity == 0.
  • tokens_fees_owed_{0,1} == 0.
  • Все счетчики вознаграждений reward_amount_owed == 0.
(То есть сначала собрать все и уменьшить до нуля.) Эффект
  • Если аккаунт токена NFT заморожен, проверяет, что первый оставшийся аккаунт равен personal_position.pool_id, затем размораживает его с помощью PDA пула.
  • Сжигает NFT.
  • Закрывает аккаунт токена NFT и personal_position, возвращая арендную плату nft_owner. Если NFT позиции использует Token-2022, он также закрывает минт NFT; классические минты SPL Token не могут быть закрыты и остаются с нулевым предложением.
Разморозка, сжигание и закрытие атомарны. NFT не может стать передаваемым между этими шагами. Условный разрыв клиента — объявленный макет IDL не изменяется, поэтому устаревшие клиенты продолжают закрывать существующие и разморозенные позиции. Устаревший построитель, который опускает оставшийся аккаунт пула, не удается с AccountLack при закрытии замороженной позиции. Передача пула для каждого закрытия — это самая простая совместимая стратегия.

SwapV2

Пройти кривую ликвидности; точный вход или точный выход в зависимости от is_base_input. Аргументы
Аккаунты (сокращенно) Вызывающие передают ранжированный список массивов тиков, охватывающих ожидаемый проход своп; программа использует столько, сколько ей нужно. SDK вычисляет этот список через PoolUtils.computeAmountOutFormat или конечную точку котировки API. Предусловия
  • pool_state.status позволяет своп.
  • now >= open_time.
  • sqrt_price_limit_x64 находится на правильной стороне sqrt_price_x64 для направления.
Распространенные ошибкиExceededSlippage, SqrtPriceLimitOverflow, TickArrayNotFound, LiquidityInsufficient. Что SwapV2 делает внутри, что вызывающие должны знать (выпуск после 2025 года):
  1. Надбавка за динамическую комиссию — если pool.dynamic_fee_info ненулевой, программа обновляет накопитель волатильности, используя расстояние тика, пройденное с последнего своп (с правилами фильтра/затухания из 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, шаг своп все еще вычисляет одинаковый вход-выход торговли; комиссия затем маршрутизируется на настроенную сторону. Для направлений, где настроенная сторона комиссии является выходом, комиссия вычитается из выхода своп (пользователь получает 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. Агрегатор и SDK уже предпочитают V2 для каждого этапа CLMM, поэтому вызывающим не нужно ветвиться по типу минта.

OpenLimitOrder

Разместить ордер на продажу на конкретном тике. Ордер находится в когорте FIFO для каждого тика и заполняется при пересечении цены. Аргументы
Аккаунты (сокращенно)
Изменение списка аккаунтов (выпуск 2026-07). OpenLimitOrder теперь также принимает аккаунты выходной стороныoutput_token_account, output_vault и output_vault_mint — в дополнение к входной стороне. Они используются только для проверки: программа отклоняет ордер, если входной или выходной аккаунт токена владельца заморожен. Это гарантирует, что заполнение может быть фактически урегулировано на выходном ATA владельца, что важно для минтов Token-2022 с белым списком/замороженных по умолчанию (например, разрешенные токены), где аккаунт может быть еще не разморожен. Клиенты, построенные на основе старого одностороннего списка аккаунтов, должны добавить три выходных аккаунта.
Предусловия
  • Ни input_token_account, ни output_token_account не заморожены (иначе NotApproved).
  • pool_state.status позволяет как своп (бит 4), так и операции лимитного ордера (бит 5) (иначе NotApproved).
  • tick_index % pool.tick_spacing == 0 и в пределах [MIN_TICK, MAX_TICK].
  • tick_index находится на правильной стороне pool.tick_current для выбранного направления (продажа token0 → тик должен быть выше текущего, и наоборот). Продажа на уже пересеченном тике будет немедленно сопоставлена и отклонена.
Постусловия
  • limit_order существует, снимая tick.order_phase и tick.unfilled_ratio_x64 при открытии.
  • tick.orders_amount += amount (в текущей когорте).
  • limit_order_nonce.order_nonce += 1.
  • Выпущено OpenLimitOrderEvent.
Распространенные ошибкиNotApproved (входной или выходной аккаунт токена заморожен, или пул имеет отключенный своп/лимитный ордер), InvalidLimitOrderAmount (ноль или ниже минимума пула), InvalidTickIndex (вне [MIN_TICK, MAX_TICK], или на неправильной стороне tick_current для выбранного направления), TickAndSpacingNotMatch (tick_index % pool.tick_spacing != 0), OrderPhaseSaturated.

IncreaseLimitOrder

Добавить к существующему открытому ордеру. Может быть вызвана только владельцем ордера. Аргументы
Аккаунты — как 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

Отправить заполненные выходные токены владельцу без изменения неисполненного остатка ордера. Полезно, когда хранители auto_withdraw хотят капельно выплачивать долгосрочные частичные заполнения. Вызывающий — либо владелец ордера, либо limit_order_admin программы (горячий кошелек оперативной работы, который запускает автоматизированный цикл хранителя). Хранитель не имеет других полномочий — он не может перемещать средства пользователя вне отправки заполненного выхода на ATA владельца ордера. Аккаунты Эффект
  • Вычисляет кумулятивный выход, причитающийся, используя (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

Идентичная форма 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, cranks) иногда хотят ее запустить.

CollectReward

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

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

Куда дальше

Источники: