Skip to main content
Cette page est traduite automatiquement par IA. La version anglaise fait foi.Voir la version anglaise →
Bannière 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 Rust CPI à la fin cible raydium-clmm sur master, qui épingle Anchor =0.32.1 — pas le 1.0.2 utilisé par la page CPMM ; les deux ne peuvent pas coexister dans une même crate. Les ID de programme proviennent de reference/program-addresses via le SDK.

Configuration

Chaque démonstration de 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 de 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 le lit uniquement quand 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 sortant (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 assistants 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, 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 limites

Un ordre limite gare l’entrée utilisateur à un seul tick et est rempli FIFO quand 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 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 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 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 espacement → TickAndSpacingNotMatch. Alignez toujours 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 → l’extension PDA 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 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é → TickAndSpacingNotMatch. Quantisez toujours via l’assistant getOrderTick exporté.
  • 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 :