Passer au contenu principal
Cette page est traduite automatiquement par IA. La version anglaise fait foi.Voir la version anglaise →
Banneau de version.
  • SDK : @raydium-io/raydium-sdk-v2@0.2.42-alpha
  • Cluster : Solana mainnet-beta
  • ID du programme Stable AMM : 5quBtoiQqxF9Jv6KYKctB59NT3gtJD2Y65kdnB1Uev3h (voir reference/program-addresses)
  • Dernière vérification : 2026-04
Le module liquidity du SDK gère les pools Stable AMM nativement. Les pools stables apparaissent comme version: 5 (ou pooltype: "StablePool") sur ApiV3PoolInfoStandardItem ; les mêmes assistants addLiquidity / removeLiquidity / swap fonctionnent pour eux que pour les pools à produit constant AMM v4 (version: 4) — le SDK détecte la variante et émet automatiquement les instructions correctes. Les mathématiques de courbe stable hors chaîne se trouvent dans src/raydium/liquidity/stable.ts.

Configuration

npm install @raydium-io/raydium-sdk-v2 @solana/web3.js @solana/spl-token
import { Raydium, TxVersion } from "@raydium-io/raydium-sdk-v2";
import { Connection, Keypair, clusterApiUrl } from "@solana/web3.js";
import BN from "bn.js";
import bs58 from "bs58";

const connection = new Connection(clusterApiUrl("mainnet-beta"));
const owner = Keypair.fromSecretKey(bs58.decode(process.env.PRIVATE_KEY!));

const raydium = await Raydium.load({
  connection,
  owner,
  cluster: "mainnet",
  // Optionnel : charger la disposition du modèle de courbe stable si vous avez l'intention d'appeler directement
  // les assistants de cotation depuis `liquidity/stable.ts`. Les opérations swap / add / remove au niveau du pool
  // le font de manière paresseuse pour vous, donc la plupart des appelants peuvent ignorer cette étape.
});

// Une seule fois : précharger la disposition des données du modèle sur chaîne utilisée par les
// assistants de courbe stable hors chaîne. Nécessaire uniquement si vous appelez directement getStablePrice / getDxByDyBaseIn /
// getDyByDxBaseIn. addLiquidity / removeLiquidity / swap n'en ont pas besoin.
await raydium.liquidity.initLayout();

Identifier un pool Stable

Deux signaux équivalents sur ApiV3PoolInfoStandardItem :
const isStable =
  pool.version === 5 ||
  pool.pooltype.includes("StablePool"); // le SDK utilise cette vérification de chaîne en interne

// Alternativement, par ID de programme :
const STABLE_AMM_PROGRAM_ID = "5quBtoiQqxF9Jv6KYKctB59NT3gtJD2Y65kdnB1Uev3h";
const isStableByProgram = pool.programId === STABLE_AMM_PROGRAM_ID;
À la fois AMM v4 (version: 4, produit constant) et Stable AMM (version: 5) passent par la même API LiquidityModule sur le SDK. En interne, le module se dispatche vers :
  • InstructionType.AmmV4AddLiquidity / AmmV4RemoveLiquidity pour les pools v4
  • InstructionType.AmmV5AddLiquidity / AmmV5RemoveLiquidity pour les pools v5 (Stable)
Le programId du pool (retourné avec les clés du pool) indique au SDK dans quel programme faire un CPI ; vous n’avez pas besoin de le coder en dur.

Trouver un pool par paire de mints

import { PublicKey } from "@solana/web3.js";

// Deux mints courants à utiliser comme exemple
const mintA = new PublicKey("Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB"); // USDT
const mintB = new PublicKey("EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"); // USDC

const pools = await raydium.api.fetchPoolByMintPair({
  mint1: mintA.toBase58(),
  mint2: mintB.toBase58(),
});

const stablePool = pools.find(
  (p) => p.version === 5 || p.pooltype.includes("StablePool"),
);

if (!stablePool) {
  throw new Error("No Stable pool exists for this mint pair");
}

console.log("Stable pool id:", stablePool.id);
console.log("Stable pool programId:", stablePool.programId);
console.log("TVL:", stablePool.tvl);
Si la paire de mints a à la fois un pool v4 (produit constant) et un pool v5 (stable), la réponse inclut les deux — choisissez celui dont votre flux a besoin, ou confiez-les au programme AMM Routing et laissez-le choisir la meilleure route.

Effectuer un swap via un pool Stable

Le flux LiquidityModule.swap a la même forme que pour les pools v4 — il suffit de lui passer un objet pool v5 :
import { Percent, TokenAmount, toToken } from "@raydium-io/raydium-sdk-v2";

const inputAmount = new TokenAmount(toToken(stablePool.mintA), 1_000_000); // 1 USDT
const slippage = new Percent(50, 10_000); // 0.5%

// Calculer la sortie attendue en utilisant les assistants de courbe stable du SDK en interne.
const { amountOut, minAmountOut } = raydium.liquidity.computeAmountOut({
  poolInfo: stablePool,
  amountIn: inputAmount,
  mintIn:  stablePool.mintA.address,
  mintOut: stablePool.mintB.address,
  slippage,
});

console.log("Expected out:", amountOut.toSignificant());
console.log("Minimum out:", minAmountOut.toSignificant());

// Construire et signer la transaction de swap.
const { transaction, execute } = await raydium.liquidity.swap({
  poolInfo: stablePool,
  amountIn:    inputAmount.raw,
  amountOut:   minAmountOut.raw,
  fixedSide:   "in",
  txVersion:   TxVersion.V0,
});

const { txId } = await execute({ sendAndConfirm: true });
console.log("Stable swap tx:", txId);
Le SDK lit le programId du pool à partir des clés du pool et se dispatche dans le programme Stable AMM. Aucun argument programId spécial n’est nécessaire.

Ajouter et retirer de la liquidité

addLiquidity et removeLiquidity fonctionnent de manière identique sur les pools v4 et v5 :
import { Percent, TokenAmount, toToken } from "@raydium-io/raydium-sdk-v2";

const amountInA = new TokenAmount(toToken(stablePool.mintA), 100_000_000); // 100 USDT
const slippage  = new Percent(50, 10_000); // 0.5%

// Calculer le montant B correspondant que la courbe exige pour cette taille de A.
const { anotherAmount, minAnotherAmount } = raydium.liquidity.computePairAmount({
  poolInfo: stablePool,
  amount:   amountInA.toSignificant(),
  baseIn:   true,
  slippage,
});

const { execute } = await raydium.liquidity.addLiquidity({
  poolInfo: stablePool,
  amountInA,
  amountInB:      anotherAmount,
  otherAmountMin: minAnotherAmount,
  fixedSide:      "a",
  txVersion:      TxVersion.V0,
});

const { txId } = await execute({ sendAndConfirm: true });
console.log("Add-liquidity tx:", txId);
En interne, le SDK émet InstructionType.AmmV5AddLiquidity car pooltype.includes("StablePool") est vrai. Le flux removeLiquidity correspondant est symétrique — fournissez le lpAmount et les montants minimums que vous accepterez de chaque côté.

Assistants de cotation hors chaîne (stable.ts)

Pour les cotations côté serveur ou les backtests, le SDK expose les mathématiques de courbe stable sous-jacentes :
import {
  getStablePrice,
  getDxByDyBaseIn,
  getDyByDxBaseIn,
} from "@raydium-io/raydium-sdk-v2";

// Vous devez appeler initLayout() une fois avant d'utiliser ceux-ci (charge le PDA
// `ModelDataInfo` sur chaîne dans le cache StableLayout du SDK).
await raydium.liquidity.initLayout();

const modelData = raydium.liquidity.stableLayout;

// Prix au comptant aux réserves actuelles du pool.
const price = getStablePrice(modelData, /* x */, /* y */, /* withFee */);
console.log("Spot price:", price);

// Cotation : étant donné dx en entrée, combien de dy en sortie (sans frais appliqués ici) ?
const dyOut = getDyByDxBaseIn(modelData, /* x */, /* y */, /* dx */);

// Cotation : étant donné la cible dy en sortie, combien de dx en entrée est nécessaire ?
const dxIn  = getDxByDyBaseIn(modelData, /* x */, /* y */, /* dy */);
Ce sont des fonctions pures — pas de RPC, pas de signature. Le ModelDataInfo sur chaîne est récupéré une seule fois par initLayout() et mis en cache dans raydium.liquidity.stableLayout. Passez les réserves actuelles (x, y) et les assistants calculent en effectuant une recherche binaire dans la table de consultation et en interpolant linéairement entre les deux lignes DataElement environnantes. Voir products/stable/math pour l’algorithme sous-jacent.

Routage via AMM Routing (multi-hop / meilleur prix)

Si vous ne voulez pas choisir un lieu vous-même, le programme AMM Routing considérera chaque AMM Raydium (v4 / CPMM / CLMM / Stable) et routera via la combinaison la meilleure :
const route = await raydium.tradeV2.fetchRoutes({
  inputMint:  mintA,
  outputMint: mintB,
  amount:     new BN(1_000_000),
  slippage,
});

// route.routes[0].poolType vous indique quels programmes la meilleure route utilise ;
// « Stable » apparaît ici chaque fois qu'un pool Stable fait partie du chemin optimal.
console.log(route.routes[0]);

const { execute } = await raydium.tradeV2.swap({
  inputMint:    mintA,
  outputMint:   mintB,
  inputAmount:  new BN(1_000_000),
  swapResult:   route.routes[0],
  slippage,
  txVersion:    TxVersion.V0,
});

const { txId } = await execute({ sendAndConfirm: true });
C’est le chemin recommandé pour les swaps en production et les agrégateurs — vous n’avez jamais besoin de décider manuellement si un pool Stable existe ou s’il est le meilleur lieu aujourd’hui.

Recommandations

  1. Pour les swaps des utilisateurs finaux, préférez le flux de routage tradeV2. Il gère tous les types de pools Raydium, y compris Stable.
  2. Pour les opérations spécifiques au pool (ajout / suppression de LP sur un pool Stable connu), utilisez directement le LiquidityModule — il détecte automatiquement les pools v5.
  3. Pour les cotations hors chaîne / l’analyse, appelez getStablePrice / getDyByDxBaseIn / getDxByDyBaseIn après initLayout(). Pas de trafic RPC par cotation après que les données du modèle soient mises en cache.
  4. Ne codez pas en dur les instructions SwapBaseIn brutes. La mise à jour du 2026-06-22 a supprimé les comptes OpenBook morts, donc la nouvelle disposition de swap prend 9 comptes (l’ancienne disposition de 18 comptes analyse toujours pour la compatibilité rétroactive). Deposit est maintenant 12 comptes (anciens 14 compatibles), Withdraw 12 (anciens 21/22 compatibles), et WithdrawPnl 10 sans aucun chemin de compatibilité. Les assistants pré-construits du SDK sélectionnent la disposition et l’ordre corrects pour vous ; rouler le vôtre est sujet aux erreurs. Voir products/stable/instructions pour les tableaux de comptes complets.

Où aller ensuite

  • Math — comment fonctionne l’interpolation de la table de consultation.
  • Instructions — référence complète des instructions.
  • AMM Routing — routage multi-pool sur AMM v4, CPMM, CLMM, Stable.
Sources :