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

> أمثلة TypeScript للمبادلة والمساهمة في السيولة في مجموعة AMM v4 موجودة. إنشاء مجموعة جديدة خارج النطاق — استخدم CPMM بدلاً من ذلك.

<Info>
  **هذه الصفحة مُترجَمة آليًا بواسطة الذكاء الاصطناعي. النسخة الإنجليزية هي المرجع المعتمد.**

  [عرض النسخة الإنجليزية →](/products/amm-v4/code-demos)
</Info>

<Info>
  **إصدار البرنامج.** جميع الأمثلة تستهدف `@raydium-io/raydium-sdk-v2@0.2.42-alpha` على Solana mainnet-beta، تم التحقق منها في 2026-04. معرّف البرنامج: `675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8` (انظر [`reference/program-addresses`](/ar/reference/program-addresses)).
</Info>

<Info>
  **إنشاء مجموعة جديدة غير موضح هنا.** واجهة Raydium لم تعد توفر إنشاء مجموعة AMM v4 — الأزواج الجديدة تنتقل افتراضيًا إلى [CPMM](/ar/products/cpmm/code-demos). برنامج AMM v4 نفسه لا يزال يقبل `Initialize2` على السلسلة؛ فقط أنه ليس المسار الموصى به. الأمثلة أدناه تغطي عمليات المجموعة المباشرة التي يحتاجها كل مدمج: swap و deposit و withdraw.
</Info>

## الإعداد

```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" });
```

## جلب مجموعة حسب المعرّف

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

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

// اسحب كائن المجموعة المعياري في SDK. بالنسبة لـ AMM v4 يتضمن حسابات OpenBook
// التي ستحتاجها منشئات التعليمات.
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 for AMM v4
console.log("Market:", poolKeys.marketId.toBase58());
```

`poolKeys` هو الهيكل الذي تستهلكه منشئات التعليمات. يحمل كل حساب AMM v4 و OpenBook بالترتيب الذي يتوقعه البرنامج.

## المبادلة (base-in)

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

const amountIn = new BN(1_000_000);            // 1 USDC (6-decimal 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);
```

SDK يوجه مبادلات AMM v4 عبر نقاط الدخول V2، التي لا تحمل حسابات OpenBook. (بعد ترقية 2026-07، لم تعد حسابات السوق مُتحققة حتى على المسار v1 القديم.)

## المبادلة (base-out)

```ts theme={null}
const amountOut = new BN(1_000_000_000);       // 1 SOL (9-decimal 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 });
```

## إضافة السيولة

```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"` يخبر SDK أنك قدمت `amountInA` الدقيق وأن `amountInB` يجب أن يكون على الأكثر `maxAnotherAmount`. يتم تسوية السيولة المباشرة للمجموعة قبل حساب النسبة المئوية بحيث تطابق نسبة الإيداع أحدث الاحتياطيات.

## إزالة السيولة

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

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

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

حدود الانزلاق الدنيا تحمي من تغيير حالة المجموعة بين الاقتباس المسبق ووقت الهبوط.

## ضبط وحدة الحساب / رسم الأولوية

مبادلات AMM v4 ثقيلة على الحساب لأن كل تعليمة تتحقق من حالة OpenBook الكاملة. عادة ما تستخدم المبادلة النموذجية 180k–250k CU اعتمادًا على عدد الطلبات المفتوحة التي تحتاج إلى تسوية في الطريق. مرر دائمًا حد وحدة الحساب:

```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
  },
});
```

إذا حذفت `computeBudgetConfig`، قد يستخدم SDK الافتراضي الخاص به؛ افحص `innerTransactions` للتأكد. انظر [`integration-guides/priority-fee-tuning`](/ar/integration-guides/priority-fee-tuning).

## CPI مباشر Rust

إذا كان يجب عليك CPI في AMM v4 من برنامج Anchor الخاص بك، ستحتاج إلى نمذجة قائمة حسابات `SwapBaseIn` حرفيًا. رسم بسيط:

```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 for SwapBaseIn is 9 on 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 لا يشحن صندوق Anchor لـ CPI. الرسم أعلاه يستخدم `Instruction` مُنشأ يدويًا.

<Note>
  الرسم CPI أعلاه يستخدم **تخطيط `SwapBaseIn` v1 القديم** (الوسم 9، 17 حساب) لقراءة/إعادة إنتاج المعاملات الموجودة. منذ ترقية 2026-07 يتم قبول حسابات السوق لكن يتم تجاهلها. **للكود الجديد، فضّل `SwapBaseInV2` / `SwapBaseOutV2`** (الوسوم 16 / 17)، التي تسقط حسابات السوق (`amm_open_orders`) بالكامل — مرر فقط 8 حسابات: `token_program`، `amm`، `amm_authority`، خزانتا المجموعة، حسابات الرموز للمستخدم، و `user_owner`.
</Note>

## الأخطاء الشائعة

* **عدد حسابات خاطئ على مبادلات v1.** `SwapBaseIn` / `SwapBaseOut` القديمة لا تزال تتطلب قائمة 17 حساب (أو 18 حساب) كاملة — عدم تطابق *العدد* يرجع مع `WrongAccountsNumber`. *محتويات* حسابات السوق لم تعد مُتحققة، لكن يجب عليك لا تزال احتلال فتحاتها. فضّل نقاط الدخول V2 لتجنب هذا.
* **قراءة أرصدة الخزانة الخام.** الاحتياطيات الآن خزانة فقط؛ اطرح الربح/الخسارة المتراكمة (`need_take_pnl_*`). اقتباس SDK أو `api-v3.raydium.io/pools/info/ids` يتعامل مع هذا لك.
* **استدعاء التعليمات المحذوفة.** `MonitorStep`، `MigrateToOpenBook`، `WithdrawSrm`، `SimulateInfo`، `AdminCancelOrders`، و `Initialize` / `PreInitialize` القديمة الآن ترجع. استخدم `Initialize2` لإنشاء المجموعة؛ لا يوجد crank للاستدعاء.
* **رموز Token-2022.** غير مدعومة. لا يمكن إنشاء مجموعة AMM v4 مقابل رمز Token-2022؛ أي زوج Token-2022 يجب أن يكون على CPMM أو CLMM.

## الخطوات التالية

* [`products/amm-v4/instructions`](/ar/products/amm-v4/instructions) — سطح مستوى التعليمات خلف هذه الأمثلة.
* [`user-flows/migrate-amm-v4-to-cpmm`](/ar/user-flows/migrate-amm-v4-to-cpmm) — إذا كنت مزود سيولة تفكر في الهجرة.
* [`integration-guides/priority-fee-tuning`](/ar/integration-guides/priority-fee-tuning) — حجم رسم الأولوية لمبادلات AMM v4 الثقيلة.

المصادر:

* [Raydium SDK v2](https://github.com/raydium-io/raydium-sdk-V2)
* [برنامج Raydium AMM](https://github.com/raydium-io/raydium-amm)
