Skip to main content
Эта страница переведена с помощью ИИ. За эталон принимается английская версия.Открыть английскую версию →
Что это делает. Создаёт новый пул CLMM с выбранным вами уровнем комиссии, затем открывает начальную концентрированную позицию. Две транзакции в четырёх файлах — config.ts, createPool.ts, createPosition.ts и utils.ts — запускаются через npx tsx. Код взят из официальных примеров в raydium-sdk-V2-demo/src/clmm и адаптирован для автономного запуска.

Подготовка

Убедитесь, что вы прочитали Предварительные требования быстрого старта и у вас установлены RPC_URL, KEYPAIR и необходимые зависимости. Помимо зависимостей из быстрого старта вам нужны:
  • decimal.js — математика цен и тиков в createPool.ts и createPosition.ts.
  • bs58 — декодирует base58-кодированный keypair в config.ts, если вы используете KEYPAIR_BS58 вместо JSON-файла.
  • tsx — запускает файлы .ts напрямую через npx tsx; в отличие от скриптов swap и CPMM, это не простой файл .mjs, запускаемый через node.
Создание пула CLMM имеет единовременную комиссию плюс аренду за массив тиков для начальной позиции. Вам также нужны оба seed-mint в кошельке — открытие позиции, когда цена находится внутри выбранного диапазона, требует ликвидности с обеих сторон. Запуск на devnet. Изменение cluster на "devnet" в config.ts недостаточно. createPool.ts передаёт явный programId: CLMM_PROGRAM_ID, фиксированную константу mainnet, которая не следует за cluster — замените его на строку DEVNET_PROGRAM_ID.CLMM_PROGRAM_ID, закомментированную прямо выше. createPosition.ts также жёстко кодирует mainnet poolId (пул RAY-USDC); замените его на ID пула devnet, который вы создали на шаге 2.

Шаг 1 — config.ts

Сохраните как config.ts. Это та же структура, что и в src/config.ts.template репозитория примеров — disableFeatureCheck принудительно установлен в true (рекомендуется для любой нетривиальной интеграции, чтобы SDK не блокировался при запуске на проверке функций):
config.ts

Шаг 2 — createPool.ts

Сохраните рядом с config.ts. Источник: src/clmm/createPool.ts.
createPool.ts

Шаг 3 — createPosition.ts

Источник: src/clmm/createPosition.ts.
createPosition.ts

Шаг 4 — utils.ts

Источник: src/clmm/utils.ts.
utils.ts

Запуск

Что произошло

Транзакция 1 — raydium.clmm.createPool инициализировала:
  • состояние пула по каноническому PDA для (mint1, mint2, ammConfig),
  • token_0_vault и token_1_vault (отсортированные по порядку байтов mint),
  • кольцевой буфер observation,
  • встроенную bitmap массива тиков,
и установила начальный sqrt_price_x64 из вашего initialPrice. Транзакция 2 — raydium.clmm.openPositionFromBase открыла концентрированную позицию:
  • выпустила NFT позиции в ваш кошелёк (NFT является позицией; передача его передаёт позицию),
  • выделила массивы тиков на нижней и верхней границах (единовременная аренда, если это первая позиция в этих диапазонах; массивы тиков никогда не закрываются программой, поэтому последующие позиции в одних и тех же массивах не требуют дополнительной аренды),
  • внесла inputAmount mint1 и соответствующую сумму mint2 (вычислено PoolUtils.getLiquidityAmountOutFromAmountIn),
  • зачислила позицию ликвидностью, пропорциональной ширине диапазона.
Чем уже диапазон, тем выше эффективность капитала на доллар TVL — и тем болезненнее временные потери, когда цена выходит за пределы диапазона. Диапазон, используемый выше ([0.000001, 100000]), фактически полный; сузьте его, чтобы сконцентрировать комиссии рядом с текущей спотовой ценой.

Выбор уровня комиссии

clmmConfigs[0] — это уровень с самой низкой комиссией. Полный набор опубликован на GET https://api-v3.raydium.io/main/clmm-config: Полную матрицу решений см. в user-flows/choosing-a-pool-type.

Частые ошибки

  • Pool already exists for this config — Пул CLMM уже существует для этой тройки (mint1, mint2, ammConfig). Найдите существующий ID пула и пропустите шаг 2.
  • Insufficient funds for amount B — Ваш кошелёк имеет запрошенную сумму mintA, но не соответствующую mintB. Открытие позиции, когда цена находится внутри диапазона, требует ликвидности с обеих сторон.
  • Tick out of range — Ваш lowerPrice или upperPrice выходит за пределы представимого диапазона цен. Используйте более разумный диапазон относительно текущей цены.
  • Устаревшая цена — Котировка из API может быть устаревшей на 5–60 секунд. Если executePosition не пройдёт из-за slippage, раскомментируйте блок getRpcClmmPoolInfo в createPosition.ts, чтобы повторно получить живую цену прямо перед подписанием.

Оговорки

  • NFT позиции — ваш единственный способ доступа. Потеряйте NFT или передайте его — потеряйте доступ к позиции. Относитесь к нему как к ключу.
  • Позиции вне диапазона не приносят комиссии. Если цена выходит за пределы [lowerPrice, upperPrice], ваша позиция полностью припаркована в одном активе и ничего не приносит, пока вы не перебалансируете.
  • Аренда массива тиков — в одну сторону. Первая позиция, которая касается никогда не инициализированного массива тиков, платит его аренду; программа не предоставляет способ закрыть массивы тиков, поэтому эта аренда постоянна. Последующие позиции в одном и том же массиве бесплатны.

Далее

Источники: