> ## 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.

# Примеры кода Stable AMM

> Как определить пул Stable AMM через API, выполнить своп через модуль Liquidity (он нативно поддерживает пулы version=5) и использовать вспомогательные функции для стабильной кривой.

<Info>
  **Эта страница переведена с помощью ИИ. За эталон принимается английская версия.**

  [Открыть английскую версию →](/products/stable/code-demos)
</Info>

<Info>
  **Баннер версии.**

  * SDK: `@raydium-io/raydium-sdk-v2@0.2.42-alpha`
  * Кластер: Solana `mainnet-beta`
  * ID программы Stable AMM: `5quBtoiQqxF9Jv6KYKctB59NT3gtJD2Y65kdnB1Uev3h` (см. [`reference/program-addresses`](/ru/reference/program-addresses))
  * Последняя проверка: 2026-04

  Модуль `liquidity` SDK нативно поддерживает пулы Stable AMM. Стабильные пулы отображаются как **`version: 5`** (или `pooltype: "StablePool"`) на `ApiV3PoolInfoStandardItem`; те же вспомогательные функции `addLiquidity` / `removeLiquidity` / swap работают для них, как и для пулов AMM v4 (`version: 4`) с постоянным произведением — SDK определяет вариант и автоматически генерирует правильные инструкции. Математика стабильной кривой находится в `src/raydium/liquidity/stable.ts`.
</Info>

## Настройка

```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",
  // Опционально: загрузите макет модели стабильной кривой, если вы намерены вызывать
  // вспомогательные функции цитирования из `liquidity/stable.ts` напрямую. Своп / добавление / удаление
  // на уровне пула делают это лениво для вас, поэтому большинство вызывающих могут пропустить этот шаг.
});

// Один раз: предварительно загрузите макет данных модели на цепи, используемый
// вспомогательными функциями стабильной кривой. Требуется только если вы вызываете getStablePrice / getDxByDyBaseIn /
// getDyByDxBaseIn напрямую. addLiquidity / removeLiquidity / swap этого не требуют.
await raydium.liquidity.initLayout();
```

## Определение пула Stable

Два эквивалентных сигнала на `ApiV3PoolInfoStandardItem`:

```ts theme={null}
const isStable =
  pool.version === 5 ||
  pool.pooltype.includes("StablePool"); // SDK использует эту проверку строки внутри

// Альтернативно, по ID программы:
const STABLE_AMM_PROGRAM_ID = "5quBtoiQqxF9Jv6KYKctB59NT3gtJD2Y65kdnB1Uev3h";
const isStableByProgram = pool.programId === STABLE_AMM_PROGRAM_ID;
```

Как AMM v4 (`version: 4`, постоянное произведение), так и Stable AMM (`version: 5`) проходят через один и тот же API `LiquidityModule` на SDK. Внутри модуль отправляет на:

* `InstructionType.AmmV4AddLiquidity` / `AmmV4RemoveLiquidity` для пулов v4
* `InstructionType.AmmV5AddLiquidity` / `AmmV5RemoveLiquidity` для пулов v5 (Stable)

`programId` пула (возвращаемый с ключами пула) сообщает SDK, в какую программу выполнить CPI; вам не нужно жестко кодировать его.

## Поиск пула по паре монет

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

// Две распространённые монеты для использования в качестве примера
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("Для этой пары монет не существует пула Stable");
}

console.log("ID пула Stable:", stablePool.id);
console.log("ID программы пула Stable:", stablePool.programId);
console.log("TVL:", stablePool.tvl);
```

Если пара монет имеет как пул v4 (постоянное произведение), так и пул v5 (stable), ответ включает оба — выберите тот, который нужен вашему потоку, или передайте их программе [AMM Routing](/ru/products/routing) и позвольте ей выбрать лучший маршрут.

## Своп через пул Stable

Поток `LiquidityModule.swap` имеет ту же форму, что и для пулов v4 — просто передайте ему объект пула 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%

// Вычислите ожидаемый выход, используя вспомогательные функции стабильной кривой SDK внутри.
const { amountOut, minAmountOut } = raydium.liquidity.computeAmountOut({
  poolInfo: stablePool,
  amountIn: inputAmount,
  mintIn:  stablePool.mintA.address,
  mintOut: stablePool.mintB.address,
  slippage,
});

console.log("Ожидаемый выход:", amountOut.toSignificant());
console.log("Минимальный выход:", minAmountOut.toSignificant());

// Создайте и подпишите транзакцию своп.
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:", txId);
```

SDK читает `programId` пула из ключей пула и отправляет в программу Stable AMM. Специальный аргумент `programId` не требуется.

## Добавление и удаление ликвидности

`addLiquidity` и `removeLiquidity` работают одинаково для пулов v4 и 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%

// Вычислите соответствующую сумму B, которую требует кривая для этого размера 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("Транзакция добавления ликвидности:", txId);
```

Внутри SDK генерирует `InstructionType.AmmV5AddLiquidity`, потому что `pooltype.includes("StablePool")` истинно. Соответствующий поток `removeLiquidity` симметричен — передайте `lpAmount` и минимальные суммы, которые вы примете с каждой стороны.

## Вспомогательные функции для цитирования вне цепи (stable.ts)

Для цитирования на стороне сервера или бэктестирования SDK предоставляет базовую математику стабильной кривой:

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

// Вы должны вызвать initLayout() один раз перед использованием этих функций (загружает
// PDA `ModelDataInfo` на цепи в кэш StableLayout SDK).
await raydium.liquidity.initLayout();

const modelData = raydium.liquidity.stableLayout;

// Спотовая цена при текущих резервах пула.
const price = getStablePrice(modelData, /* x */, /* y */, /* withFee */);
console.log("Спотовая цена:", price);

// Цитирование: при заданном dx входа, сколько dy выхода (без применения комиссии)?
const dyOut = getDyByDxBaseIn(modelData, /* x */, /* y */, /* dx */);

// Цитирование: при заданной цели dy выхода, сколько dx входа требуется?
const dxIn  = getDxByDyBaseIn(modelData, /* x */, /* y */, /* dy */);
```

Это чистые функции — без RPC, без подписания. `ModelDataInfo` на цепи загружается один раз `initLayout()` и кэшируется в `raydium.liquidity.stableLayout`. Передайте текущие резервы (`x`, `y`) и вспомогательные функции вычисляют путём двоичного поиска в таблице поиска и линейной интерполяции между двумя окружающими строками `DataElement`. См. [`products/stable/math`](/ru/products/stable/math) для базового алгоритма.

## Маршрутизация через AMM Routing (многоскачковые / лучшая цена)

Если вы не хотите выбирать площадку самостоятельно, программа [AMM Routing](/ru/products/routing) рассмотрит каждый Raydium AMM (v4 / CPMM / CLMM / Stable) и маршрутизирует через любую комбинацию, которая лучше всего:

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

// route.routes[0].poolType сообщает вам, какие программы использует лучший маршрут;
// "Stable" появляется здесь всякий раз, когда пул Stable является частью оптимального пути.
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 });
```

Это рекомендуемый путь для производственных свопов и агрегаторов — вам никогда не нужно вручную решать, существует ли пул Stable или является ли он лучшей площадкой сегодня.

## Рекомендации

1. **Для свопов конечных пользователей** предпочитайте поток маршрутизации [`tradeV2`](/ru/products/routing). Он обрабатывает каждый тип пула Raydium, включая Stable.
2. **Для операций, специфичных для пула** (добавление / удаление LP в известном пуле Stable), используйте `LiquidityModule` напрямую — он автоматически определяет пулы v5.
3. **Для цитирования вне цепи / аналитики** вызывайте `getStablePrice` / `getDyByDxBaseIn` / `getDxByDyBaseIn` после `initLayout()`. Нет трафика RPC за цитирование после кэширования данных модели.
4. **Не кодируйте вручную необработанные инструкции `SwapBaseIn`.** [Обновление от 2026-06-22](/ru/reference/changelog) удалило мёртвые учётные записи OpenBook, поэтому новый макет своп принимает **9 учётных записей** (старый макет из 18 учётных записей всё ещё парсится для обратной совместимости). `Deposit` теперь 12 учётных записей (старые 14 совместимы), `Withdraw` 12 (старые 21/22 совместимы), и `WithdrawPnl` 10 **без** пути совместимости. Предварительно созданные вспомогательные функции SDK выбирают правильный макет и порядок для вас; самостоятельное написание подвержено ошибкам. См. [`products/stable/instructions`](/ru/products/stable/instructions) для полных таблиц учётных записей.

## Что дальше

* [Math](/ru/products/stable/math) — как работает интерполяция таблицы поиска.
* [Instructions](/ru/products/stable/instructions) — полный справочник инструкций.
* [AMM Routing](/ru/products/routing) — маршрутизация между несколькими пулами через AMM v4, CPMM, CLMM, Stable.

Источники:

* [`raydium-sdk-V2/src/raydium/liquidity/liquidity.ts`](https://github.com/raydium-io/raydium-sdk-V2/blob/master/src/raydium/liquidity/liquidity.ts) — точка входа модуля; отправка 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`.
