Эта страница переведена с помощью ИИ. За эталон принимается английская версия.Открыть английскую версию →
На этой странице описаны структура и назначение каждого аккаунта. Семена (seeds) канонические и перечислены в
reference/program-addresses. Пул CLMM требует больше аккаунтов, чем пул CPMM, потому что ликвидность хранится разреженно по диапазону тиков; понимание этой разреженности — основная часть этой страницы.Инвентарь аккаунтов
Активный пул CLMM описывается следующими семействами аккаунтов. Все принадлежат программе CLMM, кроме двух минтов и их хранилищ.PoolState
Живое состояние пула, читается при каждом свопе и каждом изменении позиции.
sqrt_price_x64иtick_current— состояние цены пула. Обновляются вместе при каждом свопе.tick_current— это пол отlog_{1.0001}(price).liquidity— это активная ликвидность — сумма значенийLдля всех позиций, чей диапазон содержитtick_current. Изменяется каждый раз, когда своп пересекает тик, и каждый раз, когда позиция открывается/закрывается/изменяется.fee_growth_global_{0,1}_x64— кумулятивные комиссии, заработанные на единицу ликвидности по всей истории пула. Позиции читают это, чтобы вычислить, что им причитается.tick_spacingзафиксирован вAmmConfigпри инициализации и никогда не меняется. Он определяет, какие индексы тиков могут быть конечными точками позиции.tick_array_bitmap— это встроенная битовая карта, охватывающая диапазон “близко к спот” — ±1024 массива тиков. За пределами этого диапазона (для экстремальных значений тиков) программа ведет отдельный аккаунт расширения.fee_onфиксируется при создании пула.0(FromInput) воспроизводит классическое поведение Uniswap-V3.1и2маршрутизируют комиссию своп на одну сторону книги — см.products/clmm/feesдля компромиссов.seed_index— это[0, 0]для каждого пула, созданного черезCreatePool/CreateCustomizablePool(один канонический пул на пару). Ненулевое значение означает, что пул был создан черезCreatePermissionedPool, и индекс является частью семян PDA пула, позволяя нескольким пулам сосуществовать для одной и той же(config, mint0, mint1). Чтобы повторно вывести адрес такого пула, вы должны знать егоseed_index.dynamic_fee_infoсодержит состояние волатильности для надбавки динамической комиссии. Когда включено, каждый своп пересчитываетdynamic_fee_componentповерхAmmConfig.trade_fee_rate. Структура документирована подDynamicFeeInfoниже; пулы без динамической комиссии оставляют всю структуру нулевой.
AmmConfig
GET https://api-v3.raydium.io/main/clmm-config):
protocol_fee_rate и fund_fee_rate — это доли торговой комиссии; то же соглашение, что и CPMM. См. products/clmm/fees.
TickArrayState
CLMM не хранит одну запись на тик. Это были бы миллиарды аккаунтов. Вместо этого он группирует TICK_ARRAY_SIZE соседних инициализированных или нет тиков (обычно 60 или 88 в зависимости от версии программы) в TickArrayState, который лениво создается при первом использовании.
order_phase— это id когорты. Он увеличивается каждый раз, когда когорта переходит из “полностью не заполнена” в “частично заполнена”.orders_amount— это общее количество входного токена текущей (новейшей) когорты.part_filled_orders_remainingотслеживает предыдущую когорту, которая в настоящее время заполняется текущими свопами.unfilled_ratio_x64— это множитель Q64.64, переносимый на когорту: когда своп заполняет X% когорты, коэффициент умножается на(1 − X). Каждый открытый ордер хранит свой собственный снимок(order_phase, unfilled_ratio_x64)в момент открытия, поэтому математика расчета сводится к сравнению снимков.
- Конечный тик позиции t должен удовлетворять
t % tick_spacing == 0. Программа отклоняет позиции с неправильным интервалом. - Массив тика расположен в
floor(t / (TICK_ARRAY_SIZE * tick_spacing)) * (TICK_ARRAY_SIZE * tick_spacing). - Массив тиков инициализируется лениво: первая позиция или своп, который трогает неинициализированный массив, создает его, оплачивая ренту.
- Массив тиков никогда не закрывается программой. После выделения он сохраняется на протяжении всей жизни пула, даже после того, как каждый тик внутри него вернется к
liquidity_gross == 0. Последующие позиции и свопы переиспользуют существующий аккаунт без дополнительной ренты. Нет пути очистки, управляемогоClosePosition, для массивов тиков.
TickArrayBitmapExtension
PoolState.tick_array_bitmap (встроенная) охватывает диапазон “близко к спот” — ±1024 массива тиков. За пределами этого диапазона (для экстремальных значений тиков) программа ведет аккаунт расширения:
(MIN_TICK, MAX_TICK)) требуют его; SDK разрешает это для вас.
Позиции
Позиция CLMM — это набор из трех аккаунтов плюс mint:Position NFT mint
SPL Token или Token-2022 mint с предложением 1. Position NFT в кошельке владельца — это ATA, содержащий этот единственный токен. Программа привязывает авторизацию к текущему держателю баланса ATA NFT, а не к Pubkey, хранящемуся в состоянии. Новые мints Position NFT устанавливаютpool_state как их freeze authority перед минтингом единственного токена и удалением mint authority. Установка freeze authority не замораживает сам аккаунт NFT. Аккаунт остается разморожен и передаваем, если не выполнены оба условия: вызывающий использует OpenPositionV2 или OpenPositionWithToken22Nft, и freeze authority по крайней мере одного базового vault mint появляется в списке restricted-issuer CLMM. Только тогда CLMM замораживает аккаунт NFT после минтинга. Это не изменяет ни один байт PersonalPositionState или PoolState.
PersonalPositionState
По одному на открытую позицию. Привязан к NFT mint.
ProtocolPositionState (устарело)
Более старые выпуски CLMM хранили агрегированное бухгалтерское учет на
(pool, tick_lower, tick_upper) в PDA ProtocolPositionState. Более новые выпуски больше не создают и не читают этот аккаунт. Слот по-прежнему появляется в списках аккаунтов OpenPosition / IncreaseLiquidity / DecreaseLiquidity как UncheckedAccount для совместимости ABI, но программа не пишет в него. Существующие аккаунты в цепи являются рудиментарными; администратор может вызвать CloseProtocolPosition, чтобы вернуть ренту для них.Агрегированное бухгалтерское учет диапазона теперь выводится непосредственно из двух конечных тиков (liquidity_gross, liquidity_net и fee_growth_outside_* / reward_growths_outside_x64 на тик) в TickArrayState. Формула fee-growth-inside fee_growth_inside = global − outside_lower − outside_upper продолжает работать без аккаунта агрегированной позиции.Observation
(tick_cumulative[t1] − tick_cumulative[t0]) / (t1 − t0), а затем price = 1.0001 ** tick. См. algorithms/clmm-math.
DynamicFeeConfig и DynamicFeeInfo
Параметры динамической комиссии живут в двух местах. Переиспользуемый шаблон — DynamicFeeConfig — управляется администратором и общий для пулов, которые подключаются. Состояние выполнения на пул — DynamicFeeInfo — встроено в PoolState и обновляется каждым свопом.
DynamicFeeConfig
["dynamic_fee_config", index.to_be_bytes()]. Создается через create_dynamic_fee_config (управляется администратором) и изменяется через update_dynamic_fee_config. Пул, созданный с enable_dynamic_fee = true, снимает пять параметров калибровки конфига (filter_period, decay_period, reduction_factor, dynamic_fee_control, max_volatility_accumulator) в свой собственный DynamicFeeInfo при создании; более поздние правки DynamicFeeConfig не влияют ретроактивно на существующие пулы.
DynamicFeeInfo (встроено в PoolState)
DynamicFeeConfig. Математика комиссий и правила затухания документированы под products/clmm/math и products/clmm/fees.
Константы, используемые формулой:
LimitOrderState
Один аккаунт на открытый лимитный ордер.
- Open — пользователь вызывает
open_limit_order, депонируетtotal_amountвходного токена, ордер привязан к когортеTickState. - (опционально) Increase / Decrease —
increase_limit_orderдобавляет кtotal_amount;decrease_limit_orderвозвращает незаполненные токены (и любой выполненный вывод до этого момента). - Settle — когда когорта полностью или частично заполнена, владелец или оперативный хранитель вызывает
settle_limit_order, чтобы отправить выходные токены на ATA владельца. - Close — как только
unfilled_amount == 0, аккаунт закрываем. Рента всегда возвращаетсяowner.
[owner.as_ref(), limit_order_nonce.key().as_ref(), limit_order_nonce.order_nonce.to_be_bytes().as_ref()]. Ордер PDA уникален на (owner, nonce_index, order_nonce).
LimitOrderNonce
Счетчик на (wallet, nonce_index), который позволяет одному пользователю запускать несколько параллельных конвейеров лимитных ордеров без столкновения на PDA.
[user_wallet.as_ref(), &[nonce_index]]. Большинство клиентов используют nonce_index = 0 и позволяют order_nonce нести мощность.
Permission
Аккаунт возможности, чье существование является грантом: если PDA Permission выведена для данного authority, этот authority может вызвать CreatePermissionedPool. Он не хранит ничего, кроме authority, для которого он был создан.
["permission", authority.as_ref()]. Создается администратором через CreatePermissionPda и удаляется через ClosePermissionPda (рента возвращается вызывающему). Обе администраторские инструкции принимают либо программный admin, либо выделенный ключ permission_pda_admin. Закрытие PDA отзывает грант — authority больше не может создавать дополнительные пулы, но пулы, которые он уже создал, не затронуты.
Вывод ключевых аккаунтов
reference/program-addresses.
Краткая справка по жизненному циклу
Аккаунты
TickArrayState никогда не закрываются программой — они сохраняются на протяжении всей жизни пула. После инициализации массива тиков он остается в цепи, даже когда каждый тик внутри него вернется к liquidity_gross == 0. Переиспользование существующего массива тиков бесплатно; только первая позиция, которая трогает никогда не инициализированный массив, платит его ренту.
Что читать где
- Математика тиков и механика диапазонов:
products/clmm/ticks-and-positions. - Прогулка по свопу и математика роста комиссий:
products/clmm/math. - Списки аккаунтов инструкций:
products/clmm/instructions. - Комиссии и начисление вознаграждений:
products/clmm/fees. - Канонические ID программ и семена:
reference/program-addresses.

