Skip to main content
Cette page est traduite automatiquement par IA. La version anglaise fait foi.Voir la version anglaise →
Banneau de version. Tous les démonstrations TypeScript ciblent @raydium-io/raydium-sdk-v2@0.2.64-alpha ; elles ont été exécutées pour la dernière fois contre 0.2.42-alpha (2026-04) et leurs signatures d’appel ont été revérifiées contre la source 0.2.64-alpha le 2026-09-09, sur Solana mainnet-beta. Le squelette CPI Rust à la fin cible raydium-clmm sur la branche chore/upgrade-anchor, Anchor 1.0.2, le même pin que la page CPMM, afin que les deux puissent coexister dans une même crate. master épingle toujours 0.32.1. Les ID de programme proviennent de reference/program-addresses via le SDK.

Configuration

Chaque démonstration sur cette page reflète un fichier dans raydium-sdk-V2-demo/src/clmm ; le lien GitHub se trouve à côté de chaque section. L’amorçage suit le config.ts.template du dépôt de démonstration (source) — disableFeatureCheck: true est le paramètre recommandé pour toute intégration non triviale :

Créer un pool CLMM

Source : src/clmm/createPool.ts
Le SDK :
  • Trie mint1/mint2 par ordre d’octets avant la dérivation.
  • Calcule sqrt_price_x64 = floor(sqrt(initialPrice × 10^(dB−dA)) × 2^64).
  • Crée les comptes observation et tick_array_bitmap_extension.
  • Paie les frais de création du pool définis par ammConfig.

Ouvrir une position dans une plage choisie

Source : src/clmm/createPosition.ts
Le SDK calcule quels tick arrays la plage touche et les passe en tant que comptes. Il n’a pas besoin de regrouper une instruction init — il n’y a pas d’instruction init-tick-array ; OpenPosition* alloue un tick array manquant lui-même, aux frais du payeur.

Augmenter la liquidité sur une position existante

Source : src/clmm/increaseLiquidity.ts

Diminuer la liquidité (et collecter les frais en même temps)

Source : src/clmm/decreaseLiquidity.ts et src/clmm/closePosition.ts
Pour collecter uniquement les frais et récompenses, appelez decreaseLiquidity avec liquidity = new BN(0). L’effet secondaire de l’instruction est de régler token_fees_owed_{0,1} et reward_amount_owed et de les transférer — c’est la seule façon de collecter l’un ou l’autre. Pour fermer complètement la position après avoir annulé la liquidité et les frais, passez ownerInfo: { closePosition: true } sur l’appel decreaseLiquidity final. Le SDK ajoute ClosePosition et brûle le NFT.
Les positions d’émetteur restreint nécessitent un générateur de fermeture compatible. Ces positions ont un compte de token NFT gelé. ClosePosition doit ajouter l’ID du pool de la position en tant que premier compte restant afin que CLMM puisse dégeler le compte avant de brûler le NFT. La branche source du programme n’inclut pas de changement SDK. Confirmez que votre version SDK supporte explicitement le chemin de fermeture gelé avant d’activer la création de positions d’émetteur restreint.
Pour un client Anchor direct, gardez les comptes déclarés inchangés et ajoutez le pool :
Vous pouvez passer poolId à chaque fermeture. CLMM ne le lit que lorsque positionNftAccount est gelé, ce qui garde un chemin client compatible avec les anciennes et nouvelles positions.

Collecter la/les récompense(s)

Source : src/clmm/harvestAllRewards.ts
harvestAllRewards parcourt chaque position sur chaque pool passé, regroupe les appels DecreaseLiquidity à liquidité zéro qui règlent les frais et récompenses (plus tout UpdateRewardInfos), et les divise entre les transactions si nécessaire.

Swap

Source : src/clmm/swap.ts
La simulation parcourt la carte des ticks hors chaîne avec la même logique que le programme on-chain et retourne le montant de sortie (amountCalculated) plus la liste exacte des comptes que le swap touchera (accounts). Passez toujours les remainingAccounts que la simulation retourne : trop peu et le swap revient en arrière au milieu de la marche avec NotEnoughTickArrayAccount ; les comptes obsolètes gaspillent simplement du calcul.
PoolUtils.computeAmountOutFormat existe toujours, mais il a besoin d’une ComputeClmmPoolInfo (le computePoolInfo de getPoolInfoFromRpc, pas un objet pool API) plus deux arguments supplémentaires requis — tickarrayBitmapExtension et blockTimestamp — et il n’y a pas de méthode raydium.clmm.fetchTickArrays (fetchTickArrays est une fonction libre ; les aides au niveau du module sont PoolUtils.fetchMultiplePoolTickArrays et les tickData / tickArrays retournés par getPoolInfoFromRpc).

Créer un pool CLMM personnalisable

createCustomizablePool est le point d’entrée qui expose les bascules de frais dynamiques et de frais unilatéraux au moment de la création du pool. Il prend la forme de createPool plus deux ajouts :
Il n’y a pas de drapeau enableDynamicFee et pas de paramètre dynamicFeeConfigId, et pas de startTime. Fournir dynamicFeeConfig est ce qui active les frais dynamiques — l’omettre et vous obtenez un pool à frais statiques, silencieusement et sans erreur. Notez également que les membres de l’énumération SDK sont TokenOnlyA / TokenOnlyB, tandis que l’énumération Rust on-chain les épelle Token0Only / Token1Only ; les valeurs numériques correspondent (FromInput = 0).
createPool continue de fonctionner pour le chemin par défaut sans frais dynamiques. Utilisez createCustomizablePool chaque fois que vous avez besoin de l’un ou l’autre. Voir products/clmm/instructions pour la liste des comptes on-chain.

Ordres limités

Un ordre limité gare l’entrée utilisateur à un seul tick et est rempli FIFO lorsqu’un swap traverse ce tick. Les sorties sont poussées vers l’ATA du propriétaire au moment du règlement ; le propriétaire n’a pas besoin d’être en ligne pour être rempli.

Ouvrir un ordre limité

Le SDK dérive le PDA LimitOrderState de (owner, nonce PDA, order nonce), incrémente le LimitOrderNonce par portefeuille, et insère l’ordre dans la cohorte FIFO à ce tick.

Augmenter / diminuer un ordre ouvert

decreaseLimitOrder ne peut supprimer que de la portion non remplie de l’ordre ; la portion remplie est verrouillée jusqu’au règlement. Les deux instructions reviennent avec InvalidOrderPhase si l’ordre a déjà été entièrement rempli.

Régler un ordre rempli

settleLimitOrder lit le unfilled_ratio_x64 de l’ordre par rapport au suivi de la cohorte, calcule la sortie remplie, et la transfère à l’ATA du propriétaire. Le propriétaire peut appeler ceci lui-même ; limit_order_admin (un gardien opérationnel hors chaîne) peut également l’appeler au nom du propriétaire — la sortie va toujours au propriétaire. Pour fermer les ordres entièrement réglés afin de récupérer le loyer, utilisez closeLimitOrder (unique) ou closeAllLimitOrder (lot). Pour régler beaucoup à la fois, settleAllLimitOrder regroupe autant d’appels SettleLimitOrder que possible dans une tx v0.

Lister les ordres garés d’un portefeuille (hors chaîne)

Le point de terminaison des ordres actifs retourne les ordres non remplis et partiellement remplis dans une seule charge utile (totalAmount / filledAmount / pendingSettle distinguent les phases). Pour l’historique des ordres fermés, utilisez /limit-order/history/order/list-by-user?wallet=… (par portefeuille, paginé par nextPageId) ; pour le journal complet des événements d’un ordre spécifique, utilisez /limit-order/history/event/list-by-pda?pda=….

Squelette CPI Rust

Ordre des comptes restants pour SwapV2 :
Si le swap n’a jamais besoin de l’extension, omettez-la ; sinon, c’est le premier compte restant.

Pièges courants

  • Extrémités de tick hors espacement → TickAndSpacingNotMatch. Toujours aligner via TickUtil.getPriceAndTick (singulier TickUtil).
  • Pas assez de tick arrays fournis dans SwapV2 → NotEnoughTickArrayAccount. Prenez la liste de swapInternal(...).accounts.
  • Position pleine plage sans l’extension bitmap → le PDA d’extension doit être inscriptible ; le SDK gère cela automatiquement.
  • Confondre sqrt_price_x64 avec price → une confusion d’un facteur 2 ici est particulièrement douloureuse. En cas de doute, laissez le SDK le calculer à partir d’un prix lisible par l’homme.
  • Collecter les récompenses trop tôt → chaque collecte est un DecreaseLiquidity à liquidité zéro et coûte une transaction. Regroupez via harvestAllRewards sur plusieurs positions, et rappelez-vous que son execute a besoin de { sequentially: true }.
  • Fermer les comptes NFT vous-même → ClosePosition brûle le NFT et ferme son ATA. Il ferme également un mint NFT Token-2022 ; un mint SPL Token classique reste à zéro d’approvisionnement car ce programme ne peut pas fermer les mints. Ne fermez pas les comptes pris en charge séparément ou l’instruction reviendra.
  • Ouvrir un ordre limité à un tick non espacé → TickAndSpacingNotMatch. Toujours quantiser via l’aide getOrderTick exportée.
  • Appeler decreaseLimitOrder sur un ordre entièrement rempli → InvalidOrderPhase. Utilisez settleLimitOrder puis closeLimitOrder à la place.
  • S’attendre à un drapeau enableDynamicFee → il n’y en a pas. Omettre dynamicFeeConfig crée simplement un pool à frais statiques, silencieusement et sans erreur. Si vous vouliez des frais dynamiques, passez la PublicKey du compte de configuration, choisie dans /main/clmm-dynamic-config.

Où aller ensuite

Sources :