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.
لافتة الإصدار. جميع الأمثلة تستهدف @raydium-io/raydium-sdk-v2@0.2.42-alpha على Solana mainnet-beta، تم التحقق منها في 2026-04. يرسل SDK v3 / v5 / v6 داخليًا بناءً على مالك برنامج المزرعة؛ الأمثلة أدناه تفترض مزرعة v6. انظر reference/program-addresses للحصول على معرفات البرنامج الثلاثة.
الإعداد
تعكس الأمثلة هنا الملفات في raydium-sdk-V2-demo/src/farm. يتبع التمهيد config.ts.template من مستودع العرض التوضيحي:
import { Connection, Keypair, clusterApiUrl, PublicKey } from "@solana/web3.js";
import { Raydium, TxVersion } from "@raydium-io/raydium-sdk-v2";
import BN from "bn.js";
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",
disableFeatureCheck: true,
blockhashCommitment: "finalized",
});
export const txVersion = TxVersion.V0;
جلب مزرعة حسب المعرّف
const farmId = new PublicKey("<FARM_ID>");
const farm = await raydium.farm.getFarmById({ farmId });
console.log("Staking mint:", farm.symbolMint.toBase58());
console.log("Total staked:", farm.totalStaked.toString());
console.log("Rewards:");
for (const r of farm.rewardInfos) {
console.log(
" -", r.mint.toBase58(),
"rate(1e-" + r.decimals + "/s):", r.perSecond.toString(),
"open:", new Date(r.openTime * 1000).toISOString(),
"end: ", new Date(r.endTime * 1000).toISOString(),
);
}
يسحب getFarmById FarmState خارج السلسلة، ويفك التشفير حسب إصدار البرنامج، ويوحد معدل الإصدار ذي النقطة الثابتة إلى Decimal عادي في الثانية.
حجز أرصدة LP
المصدر: src/farm/stake.ts
const amount = new BN(1_000_000_000); // 1 LP (assuming 9 decimals)
const { execute } = await raydium.farm.deposit({
farmInfo: farm,
amount,
txVersion: TxVersion.V0,
});
const { txId } = await execute({ sendAndConfirm: true });
console.log("Deposit tx:", txId);
يتعامل SDK مع تسوية المكافآت المعلقة مسبقًا، لذا إذا كان لدى هذا المحفظة حصة بالفعل في هذه المزرعة، ستدفع التعليمات المكافآت المتراكمة إلى ATAs الخاصة بالمستخدم في نفس المعاملة.
المطالبة فقط (الحصاد)
المصدر: src/farm/harvest.ts
const { execute } = await raydium.farm.harvestAllRewards({
farmInfoList: [farm],
txVersion: TxVersion.V0,
});
await execute({ sendAndConfirm: true });
يقبل harvestAllRewards قائمة — لواجهات المستخدم التي تعرض عرض المحفظة، ركّز النداء. يتم المطالبة بكل مزرعة في تعليمة منفصلة ضمن معاملة واحدة (خاضعة لحد حجم 1232 بايت؛ لأكثر من ~6 مزارع، قسّمها إلى معاملات متعددة).
للمزرعة الواحدة على v6، يمكنك أيضًا استخدام مسار Harvest الصريح:
const { execute } = await raydium.farm.withdraw({
farmInfo: farm,
amount: new BN(0), // 0 = harvest-only path, even on v6
txVersion: TxVersion.V0,
});
await execute({ sendAndConfirm: true });
على v3 و v5، يتطلب idiom amount: 0؛ يرسل SDK بشكل صحيح.
إلغاء الحجز
المصدر: src/farm/unstake.ts
const amount = new BN(500_000_000); // 0.5 LP
const { execute } = await raydium.farm.withdraw({
farmInfo: farm,
amount,
txVersion: TxVersion.V0,
});
await execute({ sendAndConfirm: true });
إنشاء مزرعة v6
المصدر: src/farm/createAmmFarm.ts و editAmmFarm.ts
import { CurveCalculator } from "@raydium-io/raydium-sdk-v2"; // optional, for APR planning
const stakingMint = new PublicKey("<LP_MINT>"); // e.g. a CPMM LP mint
const rewardMint = new PublicKey("<REWARD_MINT>"); // e.g. your project's token
const now = Math.floor(Date.now() / 1000);
const openTime = now + 60 * 60; // start in 1h
const duration = 60 * 60 * 24 * 30; // 30 days
const endTime = openTime + duration;
const totalBudget = new BN(1_000_000).mul(new BN(10).pow(new BN(9))); // 1M reward tokens (9 dec)
const perSecond = totalBudget.div(new BN(duration)); // integer, SDK lifts to Q64.64
const { execute, extInfo } = await raydium.farm.create({
programId: /* v6 program ID, from reference/program-addresses */,
poolInfo: { lpMint: { address: stakingMint, decimals: 9, programId: /* SPL Token */ } as any },
rewardInfos: [
{
mint: rewardMint,
openTime: new BN(openTime),
endTime: new BN(endTime),
perSecond,
rewardSender: owner.publicKey, // who pays the initial budget
mintProgramId: /* SPL Token or Token-2022 */,
},
],
txVersion: TxVersion.V0,
});
const { txId } = await execute({ sendAndConfirm: true });
console.log("Farm:", extInfo.farmId.toBase58(), "createTx:", txId);
نقاط رئيسية:
perSecond هو معدل الإصدار الصحيح في الثانية. يقوم SDK بحزمه في Q64.64 قبل الإرسال. للمعدل الكسري، قم بالقياس وضبط المدة.
- يجب أن تكون الميزانية الكاملة (
perSecond × duration) موجودة في ATA المكافآت الخاصة بك — create ينقلها إلى خزان المكافآت بشكل ذري.
- يمكنك تحديد ما يصل إلى 5 مكافآت في استدعاء
create واحد. تنمو قائمة الحساب بـ (reward_mint, reward_vault, sender_ata, token_program) لكل تدفق إضافي؛ ابق على دراية بحد حجم المعاملة 1232 بايت. لـ 4+ مكافآت، أنشئ بـ 1–2 واستخدم AddReward في المعاملات اللاحقة.
زيادة تدفق مكافآت موجود
const additionalDays = 30;
const extraSeconds = 60 * 60 * 24 * additionalDays;
const extraBudget = perSecond.mul(new BN(extraSeconds));
const { execute } = await raydium.farm.setRewards({
farmInfo: farm,
rewardInfos: [
{
rewardMint: rewardMint,
newEndTime: new BN(farm.rewardInfos[0].endTime + extraSeconds),
newPerSecond: perSecond, // keep same rate
payer: owner.publicKey,
},
],
txVersion: TxVersion.V0,
});
await execute({ sendAndConfirm: true });
تمدد setRewards end_time وتحويل ميزانية الدلتا. لا يمكن للتعليمة تقصير تدفق، أو خفض per_second على تدفق مباشر، أو تغيير عملة المكافآت. لمبادلة العملات، انتظر end_time واستخدم AddReward على فتحة محررة (إن وجدت)، أو أنشئ مزرعة جديدة.
إعادة تشغيل تدفق منتهي
const { execute } = await raydium.farm.restartRewards({
farmInfo: farm,
newRewardInfo: {
rewardMint: rewardMint,
openTime: new BN(Math.floor(Date.now() / 1000) + 60 * 60),
endTime: new BN(Math.floor(Date.now() / 1000) + 60 * 60 + 60 * 60 * 24 * 14),
perSecond: new BN("1000000000"),
payer: owner.publicKey,
},
txVersion: TxVersion.V0,
});
await execute({ sendAndConfirm: true });
صالح فقط عندما يكون reward_state == 2 (انتهى) للفتحة المستهدفة. يجب أن يكون المتصل هو reward_sender للفتحة (v6) أو مالك المزرعة (v5).
Rust CPI
بخلاف AMM v4، يأتي برنامج المزرعة v6 مع صندوق Anchor (raydium_farm_v6) منشور جنبًا إلى جنب مع مصادر الواجهة الأمامية و SDK. رسم تخطيطي دقيق لـ Deposit:
use anchor_lang::prelude::*;
use raydium_farm_v6::{self, cpi::accounts::Deposit as RaydiumDeposit};
#[derive(Accounts)]
pub struct ProxyFarmDeposit<'info> {
/// CHECK:
pub farm_program: UncheckedAccount<'info>,
#[account(mut)] pub user: Signer<'info>,
#[account(mut)] /// CHECK:
pub user_ledger: UncheckedAccount<'info>,
#[account(mut)] /// CHECK:
pub farm_state: UncheckedAccount<'info>,
/// CHECK:
pub farm_authority: UncheckedAccount<'info>,
#[account(mut)] /// CHECK:
pub staking_vault: UncheckedAccount<'info>,
#[account(mut)] /// CHECK:
pub user_staking_ata: UncheckedAccount<'info>,
// Followed in remaining_accounts by (reward_vault_i, user_reward_ata_i) pairs
// for each live reward stream on the farm.
pub token_program: UncheckedAccount<'info>,
pub system_program: Program<'info, System>,
}
pub fn proxy_deposit<'info>(
ctx: Context<'_, '_, '_, 'info, ProxyFarmDeposit<'info>>,
amount: u64,
) -> Result<()> {
let cpi_ctx = CpiContext::new(
ctx.accounts.farm_program.to_account_info(),
RaydiumDeposit {
user: ctx.accounts.user.to_account_info(),
user_ledger: ctx.accounts.user_ledger.to_account_info(),
farm_state: ctx.accounts.farm_state.to_account_info(),
farm_authority: ctx.accounts.farm_authority.to_account_info(),
staking_vault: ctx.accounts.staking_vault.to_account_info(),
user_staking_ata: ctx.accounts.user_staking_ata.to_account_info(),
token_program: ctx.accounts.token_program.to_account_info(),
system_program: ctx.accounts.system_program.to_account_info(),
},
).with_remaining_accounts(ctx.remaining_accounts.to_vec());
raydium_farm_v6::cpi::deposit(cpi_ctx, amount)
}
يجب أن تطابق شريحة remaining_accounts فتحات المكافآت النشطة للمزرعة 1-إلى-1 (أزواج من reward_vault_i، user_reward_ata_i بترتيب الفهرس). قد يؤدي حذف أو سوء ترتيب هذه إلى محاسبة صامتة خاطئة — سيحول البرنامج المبلغ الخاطئ.
الأخطاء الشائعة
- نسيان المطالبة قبل سحب الأموال. غير مؤذ —
Withdraw يسوي المكافآت المعلقة أولاً. لكن إذا عرضت واجهة المستخدم “المطالبة” بشكل منفصل عن “السحب”، قد يعتقد المستخدم أن هناك شيئًا آخر للمطالبة به بعد Withdraw. لا يوجد؛ تم دفع كل شيء تراكم حتى هذه النقطة.
total_staked = 0 أثناء الانبعاثات. يتم مصادرة الانبعاثات المتراكمة أثناء عدم حجز أي شيء (تقوم صيغة تحديث reward_per_share بالقسمة على 0 والبرنامج يتخطى التحديث). بالنسبة للبرامج ذات open_time المجدول، شغّل “حصة بذرة” في open_time لتجنب هذا.
- رسوم نقل Token-2022. على مزارع v6 مع عملات مكافآت Token-2022، تنطبق رسوم النقل عند الإصدار (الخزان → المستخدم). عامل هذا في عروض APR.
per_second صغير على v5. معدل v5’s u64 يعني أن أي per_second < 1 وحدة رمز في الثانية (على عملات بـ ≥9 علامات عشرية هذا غالبًا هو المعدل المطلوب) لا يمكن التعبير عنه — معدل التدفق يقرب إلى 0 والمزرعة لا تصدر شيئًا. استخدم v6.
أين تذهب بعد ذلك
المصادر: