> ## Documentation Index
> Fetch the complete documentation index at: https://docs.raydium.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Demostraciones de código de Stable AMM

> Cómo identificar un pool de Stable AMM desde la API, hacer swap a través de él mediante el módulo Liquidity (maneja pools version=5 de forma nativa), y usar los ayudantes de curva estable fuera de cadena.

<Info>
  **Esta página fue traducida automáticamente por IA. La versión en inglés es la fuente autorizada.**

  [Ver versión en inglés →](/products/stable/code-demos)
</Info>

<Info>
  **Banner de versión.**

  * SDK: `@raydium-io/raydium-sdk-v2@0.2.42-alpha`
  * Cluster: Solana `mainnet-beta`
  * ID del programa Stable AMM: `5quBtoiQqxF9Jv6KYKctB59NT3gtJD2Y65kdnB1Uev3h` (ver [`reference/program-addresses`](/es/reference/program-addresses))
  * Última verificación: 2026-04

  El módulo `liquidity` del SDK maneja pools de Stable AMM de forma nativa. Los pools estables aparecen como **`version: 5`** (o `pooltype: "StablePool"`) en `ApiV3PoolInfoStandardItem`; los mismos ayudantes `addLiquidity` / `removeLiquidity` / swap funcionan para ellos que para pools de producto constante AMM v4 (`version: 4`) — el SDK detecta la variante y emite las instrucciones correctas automáticamente. Las matemáticas de curva estable fuera de cadena se encuentran en `src/raydium/liquidity/stable.ts`.
</Info>

## Configuración

```bash theme={null}
npm install @raydium-io/raydium-sdk-v2 @solana/web3.js @solana/spl-token
```

```ts theme={null}
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",
  // Opcional: carga el layout del modelo de curva estable si tienes intención de llamar
  // a ayudantes de cotización desde `liquidity/stable.ts` directamente. El swap / add / remove
  // a nivel de pool lo hacen de forma perezosa para ti, así que la mayoría de llamadores
  // pueden omitir este paso.
});

// Una sola vez: precarga el layout de datos del modelo en cadena utilizado por los
// ayudantes de curva estable fuera de cadena. Solo es necesario si llamas a getStablePrice / getDxByDyBaseIn /
// getDyByDxBaseIn directamente. addLiquidity / removeLiquidity / swap no lo necesitan.
await raydium.liquidity.initLayout();
```

## Identificar un pool estable

Dos señales equivalentes en `ApiV3PoolInfoStandardItem`:

```ts theme={null}
const isStable =
  pool.version === 5 ||
  pool.pooltype.includes("StablePool"); // el SDK usa esta verificación de cadena internamente

// Alternativamente, por ID del programa:
const STABLE_AMM_PROGRAM_ID = "5quBtoiQqxF9Jv6KYKctB59NT3gtJD2Y65kdnB1Uev3h";
const isStableByProgram = pool.programId === STABLE_AMM_PROGRAM_ID;
```

Tanto AMM v4 (`version: 4`, producto constante) como Stable AMM (`version: 5`) fluyen a través de la misma API `LiquidityModule` en el SDK. Internamente el módulo se distribuye a:

* `InstructionType.AmmV4AddLiquidity` / `AmmV4RemoveLiquidity` para pools v4
* `InstructionType.AmmV5AddLiquidity` / `AmmV5RemoveLiquidity` para pools v5 (Stable)

El `programId` del pool (devuelto con las claves del pool) le dice al SDK en qué programa hacer CPI; no necesitas codificarlo de forma fija.

## Encontrar un pool por par de mints

```ts theme={null}
import { PublicKey } from "@solana/web3.js";

// Dos mints comunes para usar como ejemplo
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 existe pool Stable para este par de mints");
}

console.log("ID del pool estable:", stablePool.id);
console.log("ID del programa del pool estable:", stablePool.programId);
console.log("TVL:", stablePool.tvl);
```

Si el par de mints tiene tanto un pool v4 (producto constante) como un pool v5 (estable), la respuesta incluye ambos — elige el que tu flujo necesita, o entrégalos al programa [AMM Routing](/es/products/routing) y deja que elija la mejor ruta.

## Hacer swap a través de un pool estable

El flujo `LiquidityModule.swap` tiene la misma forma que para pools v4 — simplemente entrégale un objeto pool v5:

```ts theme={null}
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%

// Calcula la salida esperada usando los ayudantes de curva estable del SDK internamente.
const { amountOut, minAmountOut } = raydium.liquidity.computeAmountOut({
  poolInfo: stablePool,
  amountIn: inputAmount,
  mintIn:  stablePool.mintA.address,
  mintOut: stablePool.mintB.address,
  slippage,
});

console.log("Salida esperada:", amountOut.toSignificant());
console.log("Salida mínima:", minAmountOut.toSignificant());

// Construye y firma la transacción 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("Tx de swap estable:", txId);
```

El SDK lee el `programId` del pool desde las claves del pool y se distribuye al programa Stable AMM. No se necesita ningún argumento `programId` especial.

## Agregar y remover liquidez

`addLiquidity` y `removeLiquidity` funcionan de forma idéntica en pools v4 y v5:

```ts theme={null}
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%

// Calcula la cantidad B coincidente que la curva requiere para este tamaño 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("Tx de agregar liquidez:", txId);
```

Internamente el SDK emite `InstructionType.AmmV5AddLiquidity` porque `pooltype.includes("StablePool")` es verdadero. El flujo correspondiente de `removeLiquidity` es simétrico — proporciona `lpAmount` y las cantidades mínimas que aceptarás en cada lado.

## Ayudantes de cotización fuera de cadena (stable.ts)

Para cotización del lado del servidor o backtesting, el SDK expone las matemáticas subyacentes de curva estable:

```ts theme={null}
import {
  getStablePrice,
  getDxByDyBaseIn,
  getDyByDxBaseIn,
} from "@raydium-io/raydium-sdk-v2";

// Debes llamar a initLayout() una vez antes de usar estos (carga el PDA
// `ModelDataInfo` en cadena en el caché StableLayout del SDK).
await raydium.liquidity.initLayout();

const modelData = raydium.liquidity.stableLayout;

// Precio spot en las reservas actuales del pool.
const price = getStablePrice(modelData, /* x */, /* y */, /* withFee */);
console.log("Precio spot:", price);

// Cotización: dado dx de entrada, ¿cuánto dy de salida (sin comisión aplicada)?
const dyOut = getDyByDxBaseIn(modelData, /* x */, /* y */, /* dx */);

// Cotización: dado el objetivo dy de salida, ¿cuánto dx de entrada se necesita?
const dxIn  = getDxByDyBaseIn(modelData, /* x */, /* y */, /* dy */);
```

Estas son funciones puras — sin RPC, sin firma. El `ModelDataInfo` en cadena se obtiene una sola vez mediante `initLayout()` y se almacena en caché en `raydium.liquidity.stableLayout`. Pasa las reservas actuales (`x`, `y`) y los ayudantes calculan mediante búsqueda binaria en la tabla de búsqueda e interpolación lineal entre las dos filas `DataElement` circundantes. Ver [`products/stable/math`](/es/products/stable/math) para el algoritmo subyacente.

## Enrutamiento a través de AMM Routing (multi-salto / mejor precio)

Si no quieres elegir un venue por ti mismo, el programa [AMM Routing](/es/products/routing) considerará cada AMM de Raydium (v4 / CPMM / CLMM / Stable) y enrutará a través de la combinación que sea mejor:

```ts theme={null}
const route = await raydium.tradeV2.fetchRoutes({
  inputMint:  mintA,
  outputMint: mintB,
  amount:     new BN(1_000_000),
  slippage,
});

// route.routes[0].poolType te dice qué programas usa la mejor ruta;
// "Stable" aparece aquí siempre que un pool Stable sea parte de la ruta óptima.
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 });
```

Esta es la ruta recomendada para swaps de producción y agregadores — nunca necesitas decidir manualmente si existe un pool Stable o si es el mejor venue hoy.

## Recomendaciones

1. **Para swaps de usuario final**, prefiere el flujo de enrutamiento [`tradeV2`](/es/products/routing). Maneja cada tipo de pool de Raydium incluyendo Stable.
2. **Para operaciones específicas de pool** (agregar / remover LP en un pool Stable conocido), usa `LiquidityModule` directamente — detecta automáticamente pools v5.
3. **Para cotización fuera de cadena / análisis**, llama a `getStablePrice` / `getDyByDxBaseIn` / `getDxByDyBaseIn` después de `initLayout()`. Sin tráfico RPC por cotización después de que los datos del modelo estén en caché.
4. **No codifiques manualmente instrucciones `SwapBaseIn` sin procesar.** La [actualización 2026-06-22](/es/reference/changelog) eliminó las cuentas OpenBook muertas, así que el nuevo layout de swap toma **9 cuentas** (el antiguo layout de 18 cuentas aún se analiza para compatibilidad hacia atrás). `Deposit` ahora es 12 cuentas (antiguo 14 compatible), `Withdraw` 12 (antiguo 21/22 compatible), y `WithdrawPnl` 10 sin **ninguna** ruta de compatibilidad. Los ayudantes pre-construidos del SDK seleccionan el layout y orden correcto para ti; hacer el tuyo propio es propenso a errores. Ver [`products/stable/instructions`](/es/products/stable/instructions) para las tablas de cuentas completas.

## Dónde ir a continuación

* [Math](/es/products/stable/math) — cómo funciona la interpolación de tabla de búsqueda.
* [Instructions](/es/products/stable/instructions) — referencia completa de instrucciones.
* [AMM Routing](/es/products/routing) — enrutamiento multi-pool en AMM v4, CPMM, CLMM, Stable.

Fuentes:

* [`raydium-sdk-V2/src/raydium/liquidity/liquidity.ts`](https://github.com/raydium-io/raydium-sdk-V2/blob/master/src/raydium/liquidity/liquidity.ts) — punto de entrada del módulo; distribución v4 / v5.
* [`raydium-sdk-V2/src/raydium/liquidity/stable.ts`](https://github.com/raydium-io/raydium-sdk-V2/blob/master/src/raydium/liquidity/stable.ts) — `StableLayout`, `getStablePrice`, `getDxByDyBaseIn`, `getDyByDxBaseIn`.
