Cette page est traduite automatiquement par IA. La version anglaise fait foi.Voir la version anglaise →
Cette page s’accompagne de
products/clmm/accounts (ce que sont les comptes) et products/clmm/math (ce que sont les mathématiques). Elle fait autorité pour les arguments et l’ordre des comptes ; les dispositions d’octets spécifiques proviennent de l’IDL.Inventaire des instructions
Il n’existe pas d’instruction d’initialisation de tick array, et aucune n’est nécessaire. Un tick
array est créé à l’intérieur de
OpenPosition* / IncreaseLiquidity* par
TickArrayState::get_or_create_tick_array, aux frais de payer. Passez la PDA de tick array
(éventuellement encore non initialisée et détenue par le système) comme tick_array_lower /
tick_array_upper et le programme l’alloue si elle est absente. OpenLimitOrder fait de même pour
son unique tick_array.CreateAmmConfig, UpdateAmmConfig, UpdatePoolStatus, CreateOperationAccount, UpdateOperationAccount, CloseProtocolPosition) sont contrôlées par la clé admin codée en dur du programme. CreatePermissionPda / ClosePermissionPda acceptent soit la clé admin soit une clé permission_pda_admin dédiée ; CreateSupportMintAssociated / CloseSupportMintAssociated acceptent soit la clé admin soit une clé dédiée de propriétaire des mints supportés. Les instructions d’admin de flux de récompenses (TransferRewardOwner, CollectRemainingRewards) sont contrôlées par le financeur de récompenses, pas par l’admin du programme.
Le suffixe V2 signifie « supporte Token-2022 sur les coffres / NFT, nécessite l’emplacement d’extension bitmap ». Le SDK choisit V2 par défaut pour les nouveaux pools.
CreatePool
Arguments
Préconditions
token_mint_0 < token_mint_1par ordre d’octets.amm_config.disable_create_pool == false.- Les mints ne sont pas rejetés par la liste blanche d’extension Token-2022.
pool_state.sqrt_price_x64 = sqrt_price_x64,tick_current = floor(log_{1.0001}(price)).pool_state.liquidity = 0(pas de positions encore).pool_state.fee_on = FromInput(défaut hérité).pool_state.dynamic_fee_infoest mis à zéro (frais dynamiques désactivés).
CreateCustomizablePool
Recommandé pour les nouveaux pools. Même effet que CreatePool plus le mode de collecte des frais par pool et un opt-in optionnel pour les frais dynamiques.
Arguments
CreatePool. dynamic_fee_config n’est pas un compte déclaré.
Préconditions — identiques à CreatePool. Si enable_dynamic_fee = false, aucun remaining_account n’est requis et ceux qui sont passés ne sont analysés qu’à la recherche d’enregistrements de mints supportés.
Postconditions
pool_state.fee_ondéfini à la varianteCollectFeeOnchoisie.- Si les frais dynamiques ont été activés :
pool_state.dynamic_fee_infoest initialisé à partir duDynamicFeeConfigfourni (cinq paramètres d’étalonnage copiés ; champs d’état mis à zéro). - Sinon :
pool_state.dynamic_fee_infoest mis à zéro (= frais dynamiques inactifs à jamais pour ce pool).
fee_on et le bit d’activation des frais dynamiques sont définis uniquement à la création du pool. Il n’y a pas de mise à niveau sur place — les pools créés via le CreatePool hérité ne peuvent pas rétroactivement obtenir des frais dynamiques ou des frais unilatéraux. Les nouveaux déploiements doivent utiliser cette instruction par défaut.
CreatePermissionedPool
À la fois CreatePool et CreateCustomizablePool dérivent le PDA du pool de ["pool", amm_config, token_mint_0, token_mint_1], donc il y a exactement une adresse de pool canonique par triplet (config, mint0, mint1) — un second init aux mêmes graines échoue. CreatePermissionedPool lève cette restriction en pliant un seed_index: u16 fourni par le client dans les graines du PDA du pool, permettant plusieurs pools pour la même paire et palier de frais — chacun à sa propre adresse. Parce qu’une adresse de pool arbitraire est une capacité privilégiée, le payeur doit détenir un PDA Permission qui l’autorise.
Tout le reste du pool est identique à CreateCustomizablePool : il prend les mêmes CreateCustomizableParams et supporte les frais unilatéraux et l’opt-in pour les frais dynamiques.
Arguments
CreateCustomizablePool plus, au début :
Le PDA
pool_state est dérivé de ["pool", amm_config, token_mint_0, token_mint_1, seed_index.to_le_bytes()].
Préconditions
seed_index != 0. Unseed_indexde0est réservé aux pools hérités et est rejeté ici ; la composante de graine[0, 0]est ce qui fait qu’une adresse de pool hérité s’effondre à la forme classique à quatre graines.- Le PDA
permissionpourpayerexiste (créé par un admin viaCreatePermissionPda). - Mêmes règles de mint / liste blanche que
CreatePool.
- Un nouveau
pool_stateexiste à l’adresse dérivée deseed_index, avecpool_state.seed_index = seed_index. - Tout autre post-état correspond à
CreateCustomizablePool(mode de frais, frais dynamiques optionnels).
Cette instruction ne pas élargir l’accès général à la création de pools — la création sans permission continue via
CreatePool / CreateCustomizablePool, qui restent un-pool-par-paire. CreatePermissionedPool existe pour le cas spécifique où un opérateur sur liste blanche a besoin de plusieurs pools pour la même paire (par exemple, prix initiaux différents ou cohortes de lancement) et détient un PDA Permission accordé par l’admin.OpenPositionV2 / OpenPositionWithToken22Nft
Créer une nouvelle position à l’intérieur d’un pool existant.
Arguments
OpenPositionWithToken22Nft est la même liste avec metadata_account (5) et metadata_program (19) retirés — il écrit les métadonnées de la position via l’extension de métadonnées Token-2022 sur le mint du NFT — soit 20 comptes. Son position_nft_mint est un simple Signer et son position_nft_account un UncheckedAccount.
Mathématiques — voir products/clmm/math. Donné base_flag, le programme résout soit liquidity soit (amount_0_max, amount_1_max) en L réel et les montants de jetons réels consommés.
Préconditions
tick_lower < tick_upper, tous deux multiples depool.tick_spacing, dans[MIN_TICK, MAX_TICK].- Les deux PDAs de tick array sont passées. Elles n’ont pas besoin d’exister déjà —
get_or_create_tick_arrayalloue celle qui manque aux frais dupayer, à l’intérieur de cette instruction. Il n’existe pas d’instruction distincte d’initialisation de tick array. - L’utilisateur a au moins
amount_0_maxetamount_1_maxdans les ATAs source.
personal_positionexiste,liquiditydéfini,fee_growth_inside_lastcapturé.- Les entrées du tick-array à
tick_lowerettick_uppermises à jour (liquidity_gross += L,liquidity_net ± L, instantanés de croissance des frais maintenus). pool_state.liquidity += Lsi la position est en plage (tick_lower ≤ tick_current < tick_upper).- Le mint NFT de la position enregistre
pool_statecomme autorité de gel. L’autorité de mint est supprimée après que le seul NFT soit frappé. L’enregistrement de l’autorité de gel ne change pas l’état du compte de jeton NFT. - Le compte de jeton NFT reste dégelé sauf si l’instruction est
OpenPositionV2ouOpenPositionWithToken22Nftet que l’autorité de gel de l’un des mints de coffre correspond à la liste des émetteurs restreints de CLMM. Seul ce chemin V2 correspondant gèle le compte.OpenPositionV1 ne gèle pas.
TickInvalidOrder (tick_lower >= tick_upper), TickAndSpacingNotMatch (une extrémité n’est pas un multiple de tick_spacing), InvalidTickIndex (en dehors de [MIN_TICK, MAX_TICK]), MissingTickArrayBitmapExtensionAccount (plage en dehors du bitmap inline et extension non ajoutée), NotApproved (pool_state.status bloque l’ouverture), ZeroAmountSpecified.
Le gel de position n’ajoute pas de comptes d’instruction déclarés ou d’arguments. Les clients peuvent ouvrir ces positions avec les dispositions V2 existantes. Le comportement est sélectionné on-chain à partir de
vault_0_mint et vault_1_mint.IncreaseLiquidityV2
Ajouter de la liquidité à une position déjà ouverte.
Arguments
OpenPosition : il n’y a ni rent, ni system_program, ni associated_token_program, ni compte de métadonnées.
Ajoutez la PDA
TickArrayBitmapExtension en tête, comme remaining_accounts[0], lorsque la plage de la position sort du bitmap inline.
Effet
- Transfère
amount_0_actual/amount_1_actualde l’utilisateur → coffres. - Incrémente
personal_position.liquidityetpool_state.liquidity(si en plage), et leliquidity_gross/liquidity_netdu tick d’extrémité en conséquence. - Collecte les frais et récompenses dus depuis le dernier toucher et les crédite à
token_fees_owed_{0,1}/reward_amount_owed. Ceux-ci ne sont payés que surDecreaseLiquidity/DecreaseLiquidityV2, pas sur l’augmentation — il n’existe pas d’instruction de collecte autonome.
DecreaseLiquidityV2
Retirer de la liquidité d’une position.
Arguments
IncreaseLiquidityV2 : personal_position et pool_state sont inversés, les coffres viennent avant les tick arrays, les comptes côté utilisateur sont nommés recipient_token_account_*, et il y a un memo_program supplémentaire.
Comptes restants — trois par récompense active collectée, dans l’ordre
reward_token_vault(W), recipient_token_account(W), reward_vault_mint. Ajoutez en tête la PDA TickArrayBitmapExtension lorsque la plage de la position sort du bitmap inline.
C’est aussi le seul moyen de collecter les frais et les récompenses. Pour collecter sans
modifier la position, appelez-la avec
liquidity = 0, amount_0_min = 0, amount_1_min = 0.- Calcule
(amount_0, amount_1)pour leLretiré donné lesqrt_price_x64actuel. - Règle les frais/récompenses accumulés depuis le dernier toucher, comme
IncreaseLiquidity. - Transfère
amount_0 + fees_owed_0etamount_1 + fees_owed_1hors des coffres vers l’utilisateur. - Décrémente les compteurs de liquidité ; si le nouveau
personal_position.liquidity == 0, la position est éligible pourClosePosition.
amount_0_min et amount_1_min sont les minimums que l’utilisateur accepte nets des frais de transfert Token-2022 du côté de la sortie.
ClosePosition
Brûler le NFT de position et fermer PersonalPositionState.
Comptes déclarés
Comptes restants
- NFT dégelé : aucun requis ; un compte de pool supplémentaire est inoffensif car le gestionnaire ne le lit pas.
- NFT gelé : ajouter
personal_position.pool_idcomme premier compte restant. Le programme le charge commePoolStateet utilise ses graines PDA pour signer le dégel.
personal_position.liquidity == 0.tokens_fees_owed_{0,1} == 0.- Tous les compteurs de récompenses
reward_amount_owed == 0.
- Si le compte de jeton NFT est gelé, vérifie que le premier compte restant égale
personal_position.pool_id, puis le dégèle avec le PDA du pool. - Brûle le NFT.
- Ferme le compte de jeton NFT et
personal_position, remboursant le loyer ànft_owner. Si le NFT de position utilise Token-2022, il ferme également le mint NFT ; les mints Token SPL classiques ne peuvent pas être fermés et restent avec l’approvisionnement zéro.
AccountLack lors de la fermeture d’une position gelée. Passer le pool pour chaque fermeture est la stratégie compatible la plus simple.
SwapV2
Parcourir la courbe de liquidité ; entrée exacte ou sortie exacte selon is_base_input.
Arguments
Les appelants passent une liste classée de tick arrays couvrant la marche de swap attendue ; le programme en utilise autant qu’il en a besoin. Le SDK calcule cette liste via
PoolUtils.computeAmountOutFormat ou le point de terminaison de devis de l’API.
Préconditions
pool_state.statuspermet le swap.now >= open_time.sqrt_price_limit_x64est du bon côté desqrt_price_x64pour la direction.
TooLittleOutputReceived (slippage en entrée exacte), TooMuchInputPaid (slippage en sortie exacte), SqrtPriceLimitOverflow, NotEnoughTickArrayAccount, InvalidFirstTickArrayAccount, MissingTickArrayBitmapExtensionAccount, LiquidityInsufficient, NotApproved (bit de swap positionné sur pool_state.status). Le CLMM n’a pas de variante ExceededSlippage — ce nom est celui du CPMM — ni de TickArrayNotFound.
Ce que SwapV2 fait en interne que les appelants doivent savoir (version post-2025) :
- Surcharge de frais dynamiques — si
pool.dynamic_fee_infoest non-zéro, le programme met à jour l’accumulateur de volatilité en utilisant la distance de tick parcourue depuis le dernier swap (avec les règles de filtre/décroissance deproducts/clmm/fees) et ajoute undynamic_fee_componenten plus deAmmConfig.trade_fee_rate. Le frais total est plafonné à 10% (MAX_FEE_RATE_NUMERATOR / 1_000_000). - Appariement des ordres limites — lorsque la marche de prix traverse un tick qui détient des ordres limites ouverts, le programme remplit d’abord la liquidité d’ordre limite disponible à ce tick (FIFO par
order_phase), puis procède le long de la courbe de liquidité LP. Les montants remplis mettent à jourtick.unfilled_ratio_x64ettick.part_filled_orders_remainingpour le règlement ultérieur ; les ordres eux-mêmes restent non dépensés jusqu’à ce que leur propriétaire appelleSettleLimitOrder. - Routage des frais unilatéraux — lorsque
pool.fee_on = Token0OnlyouToken1Only, l’étape de swap calcule toujours le même échange entrée-sortie ; le frais est ensuite acheminé vers le côté configuré. Pour les directions où le côté de frais configuré est la sortie, le frais est déduit de la sortie du swap (l’utilisateur reçoitout − fee) ; pour les directions où il est l’entrée, le comportement correspond àFromInput. Voiris_fee_on_input(zero_for_one)etis_fee_on_token0(zero_for_one)surPoolState.
Swap (V1) implémente les mêmes frais dynamiques, routage des frais unilatéraux et appariement des ordres limites que SwapV2 ; la seule fonctionnalité qu’il manque est le support Token-2022 — les deux coffres doivent être du Token SPL classique. Les pools avec n’importe quel mint Token-2022 doivent être échangés via SwapV2. L’agrégateur et le SDK préfèrent déjà V2 pour chaque jambe CLMM, donc les appelants n’ont pas à se brancher sur le type de mint.
OpenLimitOrder
Placer un ordre de vente à un tick spécifique. L’ordre reste dans une cohorte FIFO par tick et se remplit à mesure que le prix traverse.
Arguments
Comptes restants —
[0] tick_array_bitmap_extension, requis uniquement lors de l’initialisation d’un tick array dont l’index de début sort du bitmap inline du pool. Ne passez rien sinon.
Changement de liste de comptes (version 2026-07).
OpenLimitOrder prend maintenant aussi les comptes du côté de la sortie — output_token_account, output_vault et output_vault_mint — en plus du côté d’entrée. Ils sont utilisés uniquement pour la validation : le programme rejette l’ordre si le compte de jeton d’entrée ou de sortie du propriétaire est gelé. Cela garantit qu’un remplissage peut réellement être réglé à l’ATA de sortie du propriétaire, ce qui importe pour les mints Token-2022 avec liste blanche / gelés par défaut (par exemple, jetons autorisés) où un compte peut ne pas encore être dégelé. Les clients construits contre la liste de comptes unilatérale plus ancienne doivent ajouter les trois comptes de sortie.- Ni
input_token_accountnioutput_token_accountn’est gelé (sinonNotApproved). pool_state.statuspermet à la fois le swap (bit 4) et les opérations d’ordre limite (bit 5) (sinonNotApproved).tick_index % pool.tick_spacing == 0et dans[MIN_TICK, MAX_TICK].tick_indexest du bon côté depool.tick_currentpour la direction choisie (vendre token0 → le tick doit être au-dessus du courant, et vice versa). Vendre à un tick déjà traversé serait immédiatement appariée et est rejeté.
limit_orderexiste, capturanttick.order_phaseettick.unfilled_ratio_x64au moment de l’ouverture.tick.orders_amount += amount(dans la cohorte actuelle).limit_order_nonce.order_nonce += 1.OpenLimitOrderEventémis.
NotApproved (compte de jeton d’entrée ou de sortie gelé, ou le pool a le swap / ordre limite désactivé), ZeroAmountSpecified (amount == 0 après les frais de transfert côté entrée), InvalidLimitOrderAmount (le montant produirait une sortie inférieure à 1 unité de base à ce tick, ou déborderait u64), InvalidTickIndex (hors de [MIN_TICK, MAX_TICK], ou du mauvais côté de tick_current pour la direction choisie), TickAndSpacingNotMatch (tick_index % pool.tick_spacing != 0), OrderPhaseSaturated.
IncreaseLimitOrder
Ajouter à un ordre ouvert existant. Uniquement appelable par le owner de l’ordre.
Arguments
system_program.
Préconditions
limit_order.owner == signer.- L’ordre est toujours dans la même cohorte (
tick.order_phase == limit_order.order_phase). Si la cohorte a déjà commencé à se remplir, l’ordre est partiellement réglé — l’appelant doit d’abord appelerDecreaseLimitOrderouSettleLimitOrderpour avancer.
- Transfère
amountde l’ATA du propriétaire àinput_vault. limit_order.total_amount += amount;tick.orders_amount += amount.
DecreaseLimitOrder
Réduire ou annuler complètement un ordre ouvert. Paie le reste non rempli au propriétaire, plus tout résultat déjà réglé par les remplissages partiels passés.
Arguments
Effet
- Recalcule le montant rempli de l’ordre à partir du
unfilled_ratio_x64de la cohorte depuis l’ouverture. - Envoie la sortie remplie à
output_token_account. - Envoie
amountde l’entrée non remplie de retour àinput_token_account. - Met à jour
limit_orderen conséquence. Si le nouveau reste non rempli est zéro, le programme ferme le compte et rembourse le loyer àowner.
SettleLimitOrder
Pousser les jetons de sortie remplis vers le propriétaire sans modifier le reste non rempli de l’ordre. Utile lorsque les gardiens auto_withdraw veulent verser progressivement les remplissages partiels de longue durée.
Appelant — soit le owner de l’ordre, soit le limit_order_admin du programme (un portefeuille chaud opérationnel hors chaîne qui exécute une boucle de gardien automatisée). Le gardien n’a aucune autre autorité — il ne peut pas déplacer les fonds de l’utilisateur en dehors de pousser la sortie remplie à l’ATA owner.
Comptes
Effet
- Calcule la sortie cumulative due en utilisant
(limit_order.unfilled_ratio_x64, tick.unfilled_ratio_x64). - Transfère le delta à
output_token_account. - Met à jour
limit_order.settled_output. - Ne ferme pas l’ordre ; il est toujours ouvert contre toute entrée restante.
CloseLimitOrder
Fermer un compte d’ordre entièrement consommé. Le loyer est toujours retourné à limit_order.owner quel que soit le signataire.
Appelant — soit owner soit limit_order_admin.
Préconditions
- L’ordre a un reste non rempli zéro (soit
amount == total_amounta été rempli et réglé, soit le propriétaire a précédemment réduit l’ordre à zéro et a oublié de fermer).
- Ferme
limit_order; le loyer est envoyé àlimit_order.owner.
CreateDynamicFeeConfig (admin)
Créer un ensemble de paramètres réutilisable sous un index u16.
Arguments
Erreurs courantes —
InvalidDynamicFeeConfigParams si decay_period <= filter_period ou tout champ à valeur zéro est hors limites.
UpdateDynamicFeeConfig (admin)
Modifier un DynamicFeeConfig existant. Les pools qui ont déjà capturé la configuration à la création ne sont pas rétroactivement mis à jour ; seuls les pools nouvellement créés qui référencent cette configuration reprendront les nouvelles valeurs.
Arguments — mêmes cinq champs d’étalonnage que CreateDynamicFeeConfig (filter_period, decay_period, reduction_factor, dynamic_fee_control, max_volatility_accumulator) ; index est fixé à la création et n’est pas re-passé ici.
CollectProtocolFee / CollectFundFee
Balayer les frais de protocole/fonds accumulés des coffres du pool vers un destinataire, en mettant à zéro les champs correspondants PoolState.protocol_fees_* / fund_fees_*. Ce n’est pas le layout du CPMM — le CLMM n’a pas de compte authority, et les champs de destinataire sont nommés recipient_token_account_{0,1} plutôt que recipient_token_{0,1}_account.
Arguments — amount_0_requested: u64, amount_1_requested: u64.
InitializeReward
Ajouter un nouveau flux de récompenses à un pool. Jusqu’à 3 flux peuvent être actifs à la fois.
Arguments — une struct unique, param: InitializeRewardParam, soit un seul argument param :
param plutôt que trois arguments positionnels.
Comptes
Préconditions
- Moins de 3 flux actuellement actifs sur le pool.
- Le financeur dépose
total_emission = emissions_per_second × (end_time − open_time)de jeton de récompense dans le coffre dans le cadre de cette instruction. - Mint de récompense sur liste blanche par
operation_state.
SetRewardParams
Étendre, alimenter ou modifier le taux d’émission sur un flux de récompenses existant. Généralement appelé par un créateur de pool ou le multisig Raydium. Les contraintes vivent on-chain : vous pouvez généralement étendre end_time ou augmenter les émissions, pas les réduire rétroactivement. Vérifiez la liste des propriétaires de operation_state.
UpdateRewardInfos
Pur comptage — règle reward_growth_global_x64 à l’heure actuelle en multipliant emissions_per_second × Δt / liquidity. Appelé en interne par chaque instruction touchant la liquidité. Exposé en tant qu’instruction autonome car les acteurs externes (UIs, cranks) veulent parfois le déclencher.
Collecting rewards
Les récompenses dues à une position sont payées parDecreaseLiquidity / DecreaseLiquidityV2. Pour
collecter sans modifier la position, appelez-la avec liquidity = 0, amount_0_min = 0,
amount_1_min = 0. Les coffres de récompense et les comptes destinataires vont dans
remaining_accounts par groupes de trois par récompense active, dans l’ordre
reward_token_vault(W), recipient_token_account(W), reward_vault_mint.
CollectRemainingRewards est autre chose : il permet au financeur des récompenses, après le
end_time d’un flux, de balayer les jetons qui n’ont jamais été alloués à une position.
Matrice de changement d’état
Où aller ensuite
products/clmm/code-demos— exemples TypeScript exécutables.products/clmm/fees— détails sur l’accumulation des frais et récompenses.reference/error-codes— table d’erreur Anchor CLMM complète.
raydium-io/raydium-clmm—programs/amm/src/instructions- Raydium SDK v2 —
@raydium-io/raydium-sdk-v2

