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

# AMM v4 Code-Demos

> TypeScript-Beispiele für Swaps gegen und Liquiditätsbereitstellung in einem bestehenden AMM v4 Pool. Die Erstellung neuer Pools ist nicht im Umfang enthalten — verwenden Sie stattdessen CPMM.

<Info>
  **Diese Seite wurde mit KI automatisch übersetzt. Maßgeblich ist stets die englische Version.**

  [Englische Version ansehen →](/products/amm-v4/code-demos)
</Info>

<Info>
  **Versionsbanner.** Alle Demos zielen auf `@raydium-io/raydium-sdk-v2@0.2.42-alpha` gegen Solana mainnet-beta ab, verifiziert 2026-04. Programm-ID: `675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8` (siehe [`reference/program-addresses`](/de/reference/program-addresses)).
</Info>

<Info>
  **Erstellung neuer Pools wird hier nicht gezeigt.** Die Raydium-Benutzeroberfläche bietet keine AMM v4 Pool-Erstellung mehr — neue Paare verwenden standardmäßig [CPMM](/de/products/cpmm/code-demos). Das AMM v4-Programm selbst akzeptiert `Initialize2` on-chain; es ist nur nicht der empfohlene Weg. Die folgenden Demos behandeln die Live-Pool-Operationen, die jeder Integrator noch benötigt: Swap, Deposit, Withdraw.
</Info>

## Setup

```ts theme={null}
import { Connection, Keypair, clusterApiUrl } from "@solana/web3.js";
import { Raydium, TxVersion } from "@raydium-io/raydium-sdk-v2";
import fs from "node:fs";

const connection = new Connection(process.env.RPC_URL ?? clusterApiUrl("mainnet-beta"));
const owner = Keypair.fromSecretKey(
  new Uint8Array(JSON.parse(fs.readFileSync(process.env.KEYPAIR!, "utf8"))),
);
const raydium = await Raydium.load({ owner, connection, cluster: "mainnet" });
```

## Pool nach ID abrufen

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

const poolId = new PublicKey("<AMM_V4_POOL_ID>");

// Rufen Sie das SDK-normalisierte Pool-Objekt ab. Für AMM v4 enthält dies die OpenBook-
// Konten, die die Instruction Builder benötigen.
const data = await raydium.liquidity.getPoolInfoFromRpc({ poolId });
const { poolInfo, poolKeys, poolRpcData } = data;

console.log("Pair:", poolInfo.mintA.symbol, "/", poolInfo.mintB.symbol);
console.log("Version:", poolInfo.version);       // 4 für AMM v4
console.log("Market:", poolKeys.marketId.toBase58());
```

`poolKeys` ist die Struktur, die die Instruction Builder verwenden. Sie enthält jeden AMM v4 und OpenBook-Konto in der Reihenfolge, die das Programm erwartet.

## Swap (Base-In)

```ts theme={null}
import BN from "bn.js";

const amountIn = new BN(1_000_000);            // 1 USDC (6-Dezimal Quote)
const inputMint = new PublicKey(poolInfo.mintB.address);  // USDC
const slippage  = 0.005;

const computed = raydium.liquidity.computeAmountOut({
  poolInfo,
  amountIn,
  mintIn: inputMint,
  mintOut: new PublicKey(poolInfo.mintA.address),
  slippage,
});

const { execute } = await raydium.liquidity.swap({
  poolInfo,
  poolKeys,
  amountIn,
  amountOut: computed.minAmountOut,
  fixedSide: "in",
  inputMint,
  txVersion: TxVersion.V0,
});

const { txId } = await execute({ sendAndConfirm: true });
console.log("Swap tx:", txId);
```

Das SDK leitet AMM v4 Swaps durch die V2 Einstiegspunkte, die die OpenBook-Konten nicht enthalten. (Nach dem 2026-07 Upgrade werden die Market-Konten nicht einmal auf dem Legacy v1 Weg validiert.)

## Swap (Base-Out)

```ts theme={null}
const amountOut = new BN(1_000_000_000);       // 1 SOL (9-Dezimal Base)
const slippage  = 0.005;

const computed = raydium.liquidity.computeAmountIn({
  poolInfo,
  amountOut,
  mintOut: new PublicKey(poolInfo.mintA.address),
  mintIn: new PublicKey(poolInfo.mintB.address),
  slippage,
});

const { execute } = await raydium.liquidity.swap({
  poolInfo,
  poolKeys,
  amountIn: computed.maxAmountIn,
  amountOut,
  fixedSide: "out",
  inputMint: new PublicKey(poolInfo.mintB.address),
  txVersion: TxVersion.V0,
});

await execute({ sendAndConfirm: true });
```

## Liquidität hinzufügen

```ts theme={null}
const amountA = new BN(100_000_000);           // 0.1 SOL

const { anotherAmount, maxAnotherAmount } = raydium.liquidity.computePairAmount({
  poolInfo,
  amount: amountA,
  baseIn: true,
  slippage: 0.01,
});

const { execute } = await raydium.liquidity.addLiquidity({
  poolInfo,
  poolKeys,
  amountInA: amountA,
  amountInB: maxAnotherAmount,
  fixedSide: "a",
  txVersion: TxVersion.V0,
});

await execute({ sendAndConfirm: true });
```

`fixedSide: "a"` teilt dem SDK mit, dass Sie den genauen `amountInA` angegeben haben und `amountInB` höchstens `maxAnotherAmount` sein sollte. Die On-Book-Liquidität des Pools wird vor der Pro-Rata-Berechnung abgewickelt, sodass das Einzahlungsverhältnis den aktuellsten Reserven entspricht.

## Liquidität entfernen

```ts theme={null}
const lpAmount = new BN(50_000);               // LP zum Verbrennen

const { execute } = await raydium.liquidity.removeLiquidity({
  poolInfo,
  poolKeys,
  lpAmount,
  baseAmountMin: new BN(0),
  quoteAmountMin: new BN(0),
  txVersion: TxVersion.V0,
});

await execute({ sendAndConfirm: true });
```

Slippage-Minima schützen davor, dass sich der Pool-Status zwischen Ihrer Vorquote und der Landungszeit verschiebt.

## Compute-Unit / Priority-Fee-Abstimmung

AMM v4 Swaps sind rechenintensiv, da jede Instruction den vollständigen OpenBook-Status validiert. Ein typischer Swap verbraucht 180k–250k CU, je nachdem wie viele offene Orders auf dem Weg abgewickelt werden müssen. Geben Sie immer ein Compute-Unit-Limit an:

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

const { execute, innerTransactions } = await raydium.liquidity.swap({
  /* ...params... */
  computeBudgetConfig: {
    units: 400_000,
    microLamports: 50_000,       // Priority Fee
  },
});
```

Wenn Sie `computeBudgetConfig` weglassen, kann das SDK dennoch sein eigenes Standard verwenden; überprüfen Sie `innerTransactions` zur Bestätigung. Siehe [`integration-guides/priority-fee-tuning`](/de/integration-guides/priority-fee-tuning).

## Direkter Rust CPI

Wenn Sie von Ihrem eigenen Anchor-Programm aus in AMM v4 CPI aufrufen müssen, müssen Sie die Kontoliste von `SwapBaseIn` wörtlich modellieren. Eine minimale Skizze:

```rust theme={null}
use anchor_lang::prelude::*;
use anchor_lang::solana_program::program::invoke_signed;
use anchor_lang::solana_program::instruction::Instruction;

const AMM_V4_PROGRAM_ID: Pubkey = pubkey!("675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8");

#[derive(Accounts)]
pub struct ProxyAmmV4Swap<'info> {
    /// CHECK:
    pub token_program: UncheckedAccount<'info>,
    #[account(mut)] /// CHECK:
    pub amm:          UncheckedAccount<'info>,
    /// CHECK:
    pub amm_authority: UncheckedAccount<'info>,
    #[account(mut)] /// CHECK:
    pub amm_open_orders: UncheckedAccount<'info>,
    #[account(mut)] /// CHECK:
    pub amm_target_orders: UncheckedAccount<'info>,
    #[account(mut)] /// CHECK:
    pub pool_coin_token_account: UncheckedAccount<'info>,
    #[account(mut)] /// CHECK:
    pub pool_pc_token_account: UncheckedAccount<'info>,
    /// CHECK:
    pub market_program: UncheckedAccount<'info>,
    #[account(mut)] /// CHECK:
    pub market: UncheckedAccount<'info>,
    #[account(mut)] /// CHECK:
    pub market_bids: UncheckedAccount<'info>,
    #[account(mut)] /// CHECK:
    pub market_asks: UncheckedAccount<'info>,
    #[account(mut)] /// CHECK:
    pub market_event_queue: UncheckedAccount<'info>,
    #[account(mut)] /// CHECK:
    pub market_coin_vault: UncheckedAccount<'info>,
    #[account(mut)] /// CHECK:
    pub market_pc_vault: UncheckedAccount<'info>,
    /// CHECK:
    pub market_vault_signer: UncheckedAccount<'info>,
    #[account(mut)] /// CHECK:
    pub user_source: UncheckedAccount<'info>,
    #[account(mut)] /// CHECK:
    pub user_dest: UncheckedAccount<'info>,
    pub user_owner: Signer<'info>,
}

pub fn proxy_swap(
    ctx: Context<ProxyAmmV4Swap>,
    amount_in: u64,
    minimum_amount_out: u64,
) -> Result<()> {
    // Instruction Discriminator für SwapBaseIn ist 9 auf AMM v4.
    let mut data = vec![9u8];
    data.extend_from_slice(&amount_in.to_le_bytes());
    data.extend_from_slice(&minimum_amount_out.to_le_bytes());

    let ix = Instruction {
        program_id: AMM_V4_PROGRAM_ID,
        accounts: vec![
            AccountMeta::new_readonly(ctx.accounts.token_program.key(), false),
            AccountMeta::new(ctx.accounts.amm.key(), false),
            AccountMeta::new_readonly(ctx.accounts.amm_authority.key(), false),
            AccountMeta::new(ctx.accounts.amm_open_orders.key(), false),
            AccountMeta::new(ctx.accounts.amm_target_orders.key(), false),
            AccountMeta::new(ctx.accounts.pool_coin_token_account.key(), false),
            AccountMeta::new(ctx.accounts.pool_pc_token_account.key(), false),
            AccountMeta::new_readonly(ctx.accounts.market_program.key(), false),
            AccountMeta::new(ctx.accounts.market.key(), false),
            AccountMeta::new(ctx.accounts.market_bids.key(), false),
            AccountMeta::new(ctx.accounts.market_asks.key(), false),
            AccountMeta::new(ctx.accounts.market_event_queue.key(), false),
            AccountMeta::new(ctx.accounts.market_coin_vault.key(), false),
            AccountMeta::new(ctx.accounts.market_pc_vault.key(), false),
            AccountMeta::new_readonly(ctx.accounts.market_vault_signer.key(), false),
            AccountMeta::new(ctx.accounts.user_source.key(), false),
            AccountMeta::new(ctx.accounts.user_dest.key(), false),
            AccountMeta::new_readonly(ctx.accounts.user_owner.key(), true),
        ],
        data,
    };
    invoke_signed(&ix, &ctx.accounts.to_account_infos(), &[])?;
    Ok(())
}
```

AMM v4 wird nicht mit einer Anchor-Crate für CPI ausgeliefert. Die obige Skizze verwendet eine manuell konstruierte `Instruction`.

<Note>
  Die CPI-Skizze oben verwendet das **Legacy v1 `SwapBaseIn` Layout** (Tag 9, 17 Konten) zum Lesen/Reproduzieren bestehender Transaktionen. Seit dem 2026-07 Upgrade werden die Market-Konten akzeptiert, aber ignoriert. **Für neuen Code bevorzugen Sie `SwapBaseInV2` / `SwapBaseOutV2`** (Tags 16 / 17), die die Market-Konten (und `amm_open_orders`) vollständig weglassen — übergeben Sie nur 8 Konten: `token_program`, `amm`, `amm_authority`, die beiden Pool-Vaults, die beiden Benutzer-Token-Konten und `user_owner`.
</Note>

## Fallstricke

* **Falsche Kontoanzahl bei v1 Swaps.** Das Legacy `SwapBaseIn` / `SwapBaseOut` erfordert immer noch die vollständige 17-Konto- (oder 18-Konto-) Liste — eine nicht übereinstimmende *Anzahl* führt zu `WrongAccountsNumber`. Der *Inhalt* der Market-Konten wird nicht mehr validiert, aber Sie müssen ihre Slots dennoch belegen. Bevorzugen Sie die V2 Einstiegspunkte, um dies zu vermeiden.
* **Rohe Vault-Salden lesen.** Reserven sind jetzt nur noch Vault-basiert; subtrahieren Sie aufgelaufene PnL (`need_take_pnl_*`). Das SDK-Quote oder `api-v3.raydium.io/pools/info/ids` kümmert sich darum für Sie.
* **Entfernte Instructions aufrufen.** `MonitorStep`, `MigrateToOpenBook`, `WithdrawSrm`, `SimulateInfo`, `AdminCancelOrders` und Legacy `Initialize` / `PreInitialize` werden jetzt zurückgewiesen. Verwenden Sie `Initialize2` für Pool-Erstellung; es gibt keinen Crank zum Aufrufen.
* **Token-2022 Mints.** Nicht unterstützt. Ein AMM v4 Pool kann nicht gegen einen Token-2022 Mint erstellt werden; jedes Token-2022 Paar sollte auf CPMM oder CLMM sein.

## Nächste Schritte

* [`products/amm-v4/instructions`](/de/products/amm-v4/instructions) — die Instruction-Ebene hinter diesen Demos.
* [`user-flows/migrate-amm-v4-to-cpmm`](/de/user-flows/migrate-amm-v4-to-cpmm) — wenn Sie ein LP sind und eine Migration erwägen.
* [`integration-guides/priority-fee-tuning`](/de/integration-guides/priority-fee-tuning) — Priority-Fee-Dimensionierung für schwere AMM v4 Swaps.

Quellen:

* [Raydium SDK v2](https://github.com/raydium-io/raydium-sdk-V2)
* [Raydium AMM Programm](https://github.com/raydium-io/raydium-amm)
