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.
三个程序,三个数据结构。 农场 v3、v5 和 v6 是独立的程序,各有自己的状态布局。本页并行文档化它们各自的结构。实际上大多数新集成都针对 v6;对于大多数集成方来说,v3 和 v5 是只读的(质押早已发生,这些池已处于风险管理阶段)。
账户清单(每个农场,所有版本)
| 账户 | 所有者 | 用途 |
|---|
FarmState | 农场程序(v3/v5/v6) | 根状态:质押 mint、总质押量、奖励流。 |
farm_authority | 农场程序 | 拥有质押金库和奖励金库的 PDA。 |
staking_vault | SPL Token | 持有质押的 LP(或其他质押 mint)。 |
reward_vault_{i} | SPL Token | 持有奖励流 i 的未分发预算。每个流一个。 |
UserStake(v3/v5)/ UserLedger(v6) | 农场程序 | 每个 (farm, user) 的账本:质押金额 + 每个流的单位奖励快照。 |
SDK 通过 raydium.farm.getFarmById 返回完整集合。对于任意第三方农场,API 端点 GET https://api-v3.raydium.io/main/farms/info?ids=<FARM_ID> 也会返回它们。
FarmState 布局 — v6
v6 是当前版本,其账户结构最具通用性。
// programs/farm_v6/src/state/farm.rs (abridged)
pub struct FarmState {
pub state: u64, // bitfield: 0 = live, 1 = paused, ...
pub nonce: u64, // bump for farm_authority
pub creator: Pubkey, // original creator (can add rewards / transfer admin)
pub staking_mint: Pubkey,
pub staking_vault: Pubkey,
pub staking_token_program: Pubkey, // SPL Token or Token-2022
pub lp_mint_decimals: u8,
pub reward_period_len: u64, // minimum duration between SetRewards edits
pub reward_period_min: u64,
pub total_staked: u64,
pub reward_info_count: u8,
pub _reserved: [u8; ...],
pub reward_infos: [RewardInfo; 5], // up to 5 reward streams
}
pub struct RewardInfo {
pub reward_state: u8, // 0 = unused, 1 = running, 2 = ended
pub open_time: u64, // start_time
pub end_time: u64,
pub last_update_time: u64,
pub emission_per_second_x64: u128, // Q64.64 fixed-point rate
pub reward_total_emissioned: u64, // sum of emissions so far
pub reward_claimed: u64, // sum paid out to stakers
pub reward_vault: Pubkey,
pub reward_mint: Pubkey,
pub reward_sender: Pubkey, // who deposited the budget; can top up
pub reward_token_program: Pubkey, // SPL or Token-2022
pub reward_per_share_x64: u128, // Q64.64 counter
}
集成方相关的字段:
staking_mint、staking_vault — 被质押的资产及其位置。
total_staked — 当前总量。计算 APR 必需:reward_per_second × 86400 / total_staked。
reward_infos[i].emission_per_second_x64 — Q64.64 格式的速率。除以 2^64 得真实的每秒代币数。
reward_infos[i].open_time / end_time — 用于 UI 显示”还剩 X 天”。
reward_infos[i].reward_per_share_x64 — UserLedger 用来计算债务的计数器。
FarmState 布局 — v5
pub struct FarmStateV5 {
pub state: u64,
pub nonce: u64,
pub lp_vault: Pubkey, // aka staking_vault
pub reward_vaults: [Pubkey; 2],
pub owner: Pubkey,
pub reward_mints: [Pubkey; 2],
pub reward_total_emissioned: [u64; 2],
pub reward_claimed: [u64; 2],
pub reward_per_second: [u64; 2], // integer, not fixed-point
pub reward_open_time: [u64; 2],
pub reward_end_time: [u64; 2],
pub reward_per_share: [u128; 2], // Q56.8 or similar; check program source
pub total_staked: u64,
pub last_slot: u64, // v5 updates per-slot on mainnet
pub _reserved: [u8; 256],
}
与 v6 的区别:
- 按区块而非按秒。 v5 的更新循环按区块而非挂钟时间运行。SDK 会将其规范化为”每秒”用于 UI,但链上单位是区块。
- 整数发放速率。
reward_per_second 是 u64。这使可表达的最小速率限制在每秒 1 单位,对于 9 位小数 mint 的低发放流来说过粗糙。v6 用 Q64.64 速率解决了这个问题。
- 没有
reward_sender。在 v5 上,owner 是隐含的发送方;只有 owner 能够充值。
FarmState 布局 — v3
pub struct FarmStateV3 {
pub state: u64,
pub nonce: u64,
pub lp_vault: Pubkey,
pub reward_vault: Pubkey, // single reward
pub owner: Pubkey,
pub reward_mint: Pubkey,
pub reward_total_emissioned: u64,
pub reward_claimed: u64,
pub reward_per_slot: u64,
pub reward_per_share: u128,
pub total_staked: u64,
pub last_slot: u64,
pub _reserved: [u8; 256],
}
单一奖励。基于区块。最古老的程序版本,为预先于 v5 的 RAY-USDC 和 SOL-USDC 农场保留。
UserLedger(v6)/ UserStake(v5/v3)
每个用户的状态,每个 (farm, user) 对应一个账户。Seeded PDA:
// v6
const [ledgerPda] = PublicKey.findProgramAddressSync(
[farmId.toBuffer(), user.toBuffer(), Buffer.from("user_stake_info_v2")],
FARM_V6_PROGRAM_ID,
);
// v5
const [stakePda] = PublicKey.findProgramAddressSync(
[farmId.toBuffer(), user.toBuffer(), Buffer.from("user_stake_info")],
FARM_V5_PROGRAM_ID,
);
// v3
const [stakePda] = PublicKey.findProgramAddressSync(
[farmId.toBuffer(), user.toBuffer(), Buffer.from("staker_info")],
FARM_V3_PROGRAM_ID,
);
(种子字符串是 SDK 实际使用的值;程序版本过去有所变化。对于任何安全关键的内容,请根据 v6 源代码进行验证。)
// v6
pub struct UserLedger {
pub version: u64,
pub farm_id: Pubkey,
pub owner: Pubkey,
pub deposited: u64, // current stake
pub reward_debts: [u128; 5], // snapshot of reward_per_share_x64 × deposited
}
每个流的债务是概述中描述的会计偏移量:
pending_for_stream_i = deposited × reward_per_share_x64[i] / 2^64 − reward_debts[i]
每次 Deposit、Withdraw 或 Harvest 之后,债务被重置为当前的 deposited × reward_per_share_x64[i] / 2^64。
权限 PDA
// v6
const [farmAuthorityV6] = PublicKey.findProgramAddressSync(
[farmId.toBuffer()],
FARM_V6_PROGRAM_ID,
);
// v5
const [farmAuthorityV5] = PublicKey.findProgramAddressSync(
[farmId.toBuffer()],
FARM_V5_PROGRAM_ID,
);
// v3
const [farmAuthorityV3] = PublicKey.findProgramAddressSync(
[farmId.toBuffer()],
FARM_V3_PROGRAM_ID,
);
所有三个版本都通过单一种子为每个农场派生农场权限。这个 PDA 是质押金库和每个奖励金库上的权限。它对农场进行的每笔转账都进行签名。
质押和奖励金库是标准的 SPL Token 账户,其 owner 是农场权限 PDA。地址存储在 FarmState 上 — 不要重新派生;从状态中读取。质押 mint 上的冻结权限对于 v5/v6 必须被禁用(程序会检查)。
Token-2022 说明:
- v3:仅 SPL Token。
- v5:仅 SPL Token。
- v6:在质押和奖励 mint 上都支持 Token-2022,由
staking_token_program / reward_token_program 字段限制。Token-2022 奖励 mint 上的转账费在发放时收取(金库 → 用户)。
观察和 APR
农场不在链上存储 APR。计算方法:
annualized_rewards_value_usd = reward_per_second × 86400 × 365 × reward_usd_price
tvl_usd = total_staked / 10^decimals × staking_mint_usd_price
apr = annualized_rewards_value_usd / tvl_usd
消费者通常通过 LP 所属的池(通过 api-v3.raydium.io/pools/info/ids)来获取 staking_mint_usd_price,并从任何价格预言机获取 reward_usd_price。
后续阅读
资源: