Эта страница переведена с помощью ИИ. За эталон принимается английская версия.Открыть английскую версию →
Установка
raydium-sdk-V2-demo/src/clmm. Ссылка на GitHub указана рядом с каждым разделом. Инициализация повторяет config.ts.template из демо-репозитория (исходный код). Для любой нетривиальной интеграции рекомендуется disableFeatureCheck: true:
Создание пула CLMM
Источник:src/clmm/createPool.ts
- Сортирует
mint1иmint2по порядку байтов перед вычислением адреса. - Вычисляет
sqrt_price_x64 = floor(sqrt(initialPrice × 10^(dB−dA)) × 2^64). - Создаёт аккаунты
observationиtick_array_bitmap_extension. - Оплачивает комиссию за создание пула, заданную в
ammConfig.
Открытие позиции в выбранном диапазоне
Источник:src/clmm/createPosition.ts
OpenPosition* при необходимости создаёт недостающий tick-массив самостоятельно, за счёт плательщика.
Увеличение ликвидности существующей позиции
Источник:src/clmm/increaseLiquidity.ts
Уменьшение ликвидности (с одновременным сбором комиссий)
Источник:src/clmm/decreaseLiquidity.ts и src/clmm/closePosition.ts
decreaseLiquidity с liquidity = new BN(0). Побочный эффект инструкции — расчёт token_fees_owed_{0,1} и reward_amount_owed и перевод этих средств владельцу. Другого способа собрать их нет.
Чтобы полностью закрыть позицию после обнуления ликвидности и комиссий, передайте ownerInfo: { closePosition: true } в последний вызов decreaseLiquidity. SDK добавит ClosePosition и сожжёт NFT.
Для прямого Anchor-клиента оставьте объявленные аккаунты без изменений и добавьте пул в конец:
poolId можно передавать при каждом закрытии. CLMM читает его только тогда, когда positionNftAccount заморожен, поэтому один клиентский путь работает и со старыми, и с новыми позициями.
Сбор наград
Источник:src/clmm/harvestAllRewards.ts
harvestAllRewards обходит все позиции во всех переданных пулах, группирует вызовы DecreaseLiquidity с нулевой ликвидностью, которые рассчитывают комиссии и награды (а также UpdateRewardInfos, если нужно), и при необходимости распределяет их по нескольким транзакциям.
Swap
Источник:src/clmm/swap.ts
Этот пример повторяет src/clmm/swap.ts: симуляция выполняется через swapInternal, а не через PoolUtils.computeAmountOutFormat.
amountCalculated) и точный список аккаунтов, которые затронет своп (accounts).
Всегда передавайте remainingAccounts, которые возвращает симуляция: если их меньше, своп откатится посередине обхода с ошибкой NotEnoughTickArrayAccount; лишние аккаунты просто расходуют вычислительный бюджет.
PoolUtils.computeAmountOutFormat по-прежнему существует, но для его вызова нужен ComputeClmmPoolInfo (это computePoolInfo из getPoolInfoFromRpc, а не объект пула из API), а также два обязательных аргумента — tickarrayBitmapExtension и blockTimestamp. Кроме того, метода raydium.clmm.fetchTickArrays не существует: fetchTickArrays — это самостоятельная функция, а вспомогательные функции уровня модуля — это PoolUtils.fetchMultiplePoolTickArrays и tickData / tickArrays, которые возвращает getPoolInfoFromRpc.Создание кастомизируемого пула CLMM
createCustomizablePool — это точка входа, которая на этапе создания пула открывает переключатели динамической комиссии и комиссии с одной стороны. Она принимает те же параметры, что и createPool, плюс два дополнительных:
createPool по-прежнему работает для пути с комиссией по умолчанию и без динамической комиссии. Используйте createCustomizablePool, когда нужен любой из этих параметров. Список аккаунтов on-chain см. в разделе products/clmm/instructions.
Лимитные ордера
Лимитный ордер размещает средства пользователя на одном тике и исполняется по принципу FIFO, когда своп пересекает этот тик. Результат отправляется на ATA владельца в момент расчёта; владельцу не нужно быть онлайн, чтобы ордер исполнился.Открытие лимитного ордера
Конфигурационного аккаунта лимитных ордеров для каждого пула и вспомогательной функцииgetClmmLimitOrderConfigs() не существует: ордера адресуются по тику.
LimitOrderState из (owner, nonce PDA, order nonce), увеличивает LimitOrderNonce для данного кошелька и добавляет ордер в очередь FIFO на этом тике.
Увеличение и уменьшение открытого ордера
decreaseLimitOrder может убрать средства только из неисполненной части ордера; исполненная часть заблокирована до расчёта. Обе инструкции откатываются с ошибкой InvalidOrderPhase, если ордер уже полностью исполнен.
Расчёт исполненного ордера
settleLimitOrder сверяет unfilled_ratio_x64 ордера с трекером очереди, вычисляет исполненный результат и переводит его на ATA владельца. Владелец может вызвать эту инструкцию сам; limit_order_admin (офчейн-оператор-кипер) также может вызвать её от имени владельца — результат всё равно уйдёт владельцу.
Чтобы закрыть полностью рассчитанные ордера и вернуть ренту, используйте closeLimitOrder (один ордер) или closeAllLimitOrder (пакетно). Для расчёта сразу многих ордеров settleAllLimitOrder упаковывает столько вызовов SettleLimitOrder, сколько помещается в одну v0-транзакцию.
Список активных ордеров кошелька (офчейн)
totalAmount / filledAmount / pendingSettle). Для истории закрытых ордеров используйте /limit-order/history/order/list-by-user?wallet=… (по кошельку, с постраничной навигацией через nextPageId); для полного журнала событий конкретного ордера используйте /limit-order/history/event/list-by-pda?pda=….
Скелет CPI на Rust
SwapV2:
Типичные ошибки
- Неправильно выровненные границы тика →
TickAndSpacingNotMatch. Всегда приводите значения черезTickUtil.getPriceAndTick(единственное число,TickUtil). - Недостаточно tick-массивов в
SwapV2→NotEnoughTickArrayAccount. Берите список изswapInternal(...).accounts. - Позиция на всём диапазоне без расширения bitmap → PDA расширения должен быть доступен для записи; SDK делает это автоматически.
- Путаница между
sqrt_price_x64иprice→ ошибка в два раза здесь особенно болезненна. Если сомневаетесь, пусть SDK вычислит значение из читаемой цены. - Слишком частый сбор наград → каждый сбор — это
DecreaseLiquidityс нулевой ликвидностью, и он стоит одну транзакцию. Объединяйте сборы черезharvestAllRewardsдля нескольких позиций и помните, что егоexecuteтребует{ sequentially: true }. - Самостоятельное закрытие NFT-аккаунтов →
ClosePositionсжигает NFT и закрывает его ATA. Он также закрывает mint NFT в Token-2022; mint в классическом SPL Token остаётся с нулевым предложением, так как эта программа не умеет закрывать mint’ы. Не закрывайте поддерживаемые аккаунты отдельно, иначе инструкция завершится с ошибкой. - Открытие лимитного ордера на тике, не кратном шагу →
TickAndSpacingNotMatch. Всегда квантуйте через экспортируемый хелперgetOrderTick. - Вызов
decreaseLimitOrderдля полностью исполненного ордера →InvalidOrderPhase. Вместо этого используйтеsettleLimitOrder, а затемcloseLimitOrder. - Ожидание флага
enableDynamicFee→ такого флага нет. Если не передатьdynamicFeeConfig, создаётся пул со статической комиссией, без предупреждений и ошибок. Если нужны динамические комиссии, передайтеPublicKeyаккаунта конфигурации, выбрав его в/main/clmm-dynamic-config.
Что дальше
sdk-api/typescript-sdk— полный интерфейс SDK.sdk-api/rest-api— эндпоинты для котировок и метаданных пулов.user-flows/create-clmm-pool— пошаговое руководство без кода.integration-guides/aggregator— маршрутизация CLMM как части пути обмена.

