Skip to main content
Cette page est traduite automatiquement par IA. La version anglaise fait foi.Voir la version anglaise →
Bannière de version. Toutes les démonstrations ciblent @raydium-io/raydium-sdk-v2@0.2.42-alpha sur Solana mainnet-beta, vérifiées en avril 2026. Les ID de programme proviennent de reference/program-addresses via le SDK.

Configuration

Chaque démonstration de cette page correspond à un fichier dans raydium-sdk-V2-demo/src/clmm ; le lien GitHub se trouve à côté de chaque section. L’amorçage suit le fichier 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 automatiquement les tick arrays que la plage touche et regroupe les instructions InitTickArray si certaines ne sont pas initialisées.

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, appelez decreaseLiquidity avec liquidity = new BN(0). L’effet secondaire de l’instruction est de régler tokens_fees_owed_{0,1} et de les transférer. Pour fermer complètement la position après avoir annulé la liquidité et les frais, passez closePosition: true lors de l’appel final decreaseLiquidity. Le SDK ajoute ClosePosition et brûle le NFT.
Les positions à é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 comme 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 modification du SDK. Confirmez que votre version du SDK supporte explicitement le chemin de fermeture gelé avant d’activer la création de positions à é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 maintient 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 instructions CollectReward (et toute UpdateRewardInfos), et les divise entre les transactions si nécessaire.

Swap

Source : src/clmm/swap.ts
computeAmountOutFormat parcourt la carte des ticks hors chaîne en utilisant la même logique que le programme on-chain et retourne :
  • le montant attendu en sortie,
  • le montant minimum en sortie après slippage,
  • la liste des comptes tick-array que le swap réel touchera (remainingAccounts).
Passez toujours remainingAccounts retourné par la simulation : si vous en passez trop peu, le swap revient en arrière à mi-parcours avec TickArrayNotFound ; si vous en passez des obsolètes, vous gaspillez du calcul.

Créer un pool CLMM personnalisable

createCustomizablePool est le nouveau 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 même forme que createPool plus trois ajouts :
createPool continue de fonctionner pour le chemin par défaut sans frais dynamiques et sans ordres limites. Utilisez createCustomizablePool chaque fois que vous avez besoin de l’un des trois nouveaux paramètres. Voir products/clmm/instructions pour la liste des comptes on-chain.

Ordres limites

Un ordre limite 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 limite

Le SDK dérive la PDA LimitOrderState de (pool, owner, tick, nonce), incrémente le LimitOrderNonce par (pool, owner), 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 l’appeler lui-même ; limit_order_admin (un gardien opérationnel hors chaîne) peut aussi 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 à la fois 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 Rust CPI

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 espacementInvalidTickIndex. Alignez toujours via TickUtils.getPriceAndTick.
  • Pas assez de tick arrays fournis dans SwapV2TickArrayNotFound. Utilisez computeAmountOutFormat pour obtenir la liste complète.
  • Position pleine plage sans l’extension bitmap → la 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 coûte une transaction. Regroupez via harvestAllRewards sur plusieurs positions.
  • Fermer les comptes NFT vous-mêmeClosePosition brûle le NFT et ferme son ATA. Il ferme aussi 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 limite à un tick non espacéInvalidTickIndex. Quantifiez toujours via TickUtils.getPriceAndTick.
  • Appeler decreaseLimitOrder sur un ordre entièrement rempliInvalidOrderPhase. Utilisez plutôt settleLimitOrder puis closeLimitOrder.
  • Oublier dynamicFeeConfigId tout en passant enableDynamicFee: true → le retour CreateCustomizablePool est InvalidDynamicFeeConfigParams. Soit désactivez les frais dynamiques, soit choisissez une config dans /main/clmm-dynamic-config.

Où aller ensuite

Sources :