Skip to main content
Version banner. All demos target @raydium-io/raydium-sdk-v2@0.2.64-alpha against Solana mainnet-beta, verified 2026-09-09 — every builder name, parameter name and parameter type below was checked against that release’s src/raydium/farm/ and against raydium-sdk-V2-demo/src/farm. The SDK dispatches v3 / v5 / v6 internally based on the farm’s program owner; examples below assume a v6 farm. See reference/program-addresses for the three program IDs.The farm module’s method names are not what you would guess: there is no getFarmById and no setRewards. Fetching goes through raydium.api.fetchFarmInfoById, and the reward-editing builders are addNewRewardToken / addNewRewardsToken and restartReward / restartRewards.

Setup

Demos here mirror files in raydium-sdk-V2-demo/src/farm. Bootstrap follows the demo repo’s config.ts.template:

Fetch a farm by id

There is no raydium.farm.getFarmById. Every farm demo starts from the API module, which returns the normalized FormatFarmInfoOut shape that deposit / withdraw / harvestAllRewards all take:
fetchFarmInfoById takes a comma-separated string of ids and returns an array, so one call can hydrate a whole portfolio. If you need the raw account keys rather than the display info, raydium.api.fetchFarmKeysById({ ids }) returns the vaults and authority PDAs; the SDK calls it internally for you inside every builder below.

Stake LP tokens

Source: src/farm/stake.ts
The SDK handles the pre-settle of any pending rewards, so if this wallet already has stake in this farm, the instruction will pay out accumulated rewards to the user’s ATAs in the same transaction.

Claim-only (harvest)

Source: src/farm/harvest.ts farmInfoList is a Record keyed by farm id, not an array, and the builder returns multiple transactions — so execute must be given sequentially: true:
The builder packs as many farms per transaction as the 1232-byte limit allows and splits the rest into follow-up transactions, which is why it returns txIds rather than a single txId. For a single farm, harvest with the amount: 0 idiom — this is what src/farm/harvest.ts does, on every version including v6:

Unstake

Source: src/farm/unstake.ts

Create a v6 farm

Source: src/farm/createAmmFarm.ts and editAmmFarm.ts create takes the pool info object for the pool whose LP mint is being staked (not a bare mint), and each entry of rewardInfos is a FarmRewardInfo: { mint: PublicKey, perSecond: string, openTime: number, endTime: number, rewardType: "Standard SPL" | "Option tokens" }. Times are plain seconds, and perSecond is a string, not a BN. programId defaults to the v6 program, so you rarely pass it.
Key points:
  • perSecond is the emission rate per second in the reward mint’s raw units, passed as a decimal string. The SDK packs it into the on-chain fixed-point representation before sending.
  • The full budget (perSecond × (endTime − openTime)) must be present in your reward ATA — create moves it into the reward vault atomically.
  • Token-2022 reward mints are not supported by the SDK’s farm builders at this SDK version; use a plain SPL mint for rewards.
  • You can seed up to 5 rewards in one create call. The account list grows by (reward_mint, reward_vault, sender_ata, token_program) per extra stream; stay aware of the 1232-byte transaction size limit. For 4+ rewards, create with 1–2 and use addNewRewardsToken in follow-up transactions.

Add a new reward stream

There is no raydium.farm.setRewards. The two builders that change a farm’s rewards are addNewRewardToken / addNewRewardsToken (occupy a free slot with a new mint) and restartReward / restartRewards (re-arm a slot whose stream has ended). Both take FarmRewardInfo objects in exactly the shape create uses.
The delta budget (perSecond × duration) is pulled from the payer’s ATA as part of the transaction. The underlying instruction cannot shorten a stream, cannot lower per_second on a live stream, and cannot change a slot’s reward mint — to swap mints, wait for end_time and use addNewRewardsToken on a freed slot, or create a new farm.
restartRewards and addNewRewardsToken each return a builder, so a single transaction can do both. src/farm/editAmmFarm.ts shows the pattern: editFarmBuilder.builder.addInstruction(addNewRewardBuildData.builder.AllTxData), then one versionBuild({ txVersion }).

Restart a finished stream

Source: src/farm/editAmmFarm.ts restartRewards takes newRewardInfos (plural, an array); restartReward is the single-item form and takes newRewardInfo. The mint field is mint, not rewardMint, and it must match a slot that already exists on the farm — the builder looks the slot up by mint and errors if it is absent.
restartRewards is v6-only — the builder reads the farm’s program id and throws for v3 / v5 farms. Valid only when the target slot’s reward_state == 2 (ended); the caller must be the slot’s reward_sender. Note openTime >= endTime is rejected client-side before any RPC is made.

Rust CPI

There is no raydium_farm_v6 Anchor crate. No crate by that name exists on crates.io, the Farm v6 program publishes no on-chain IDL (neither a legacy anchor:idl account nor an entry in the Program Metadata program), and no public source repository for it exists. An earlier revision of this page showed a raydium_farm_v6::cpi::deposit example; it did not compile against anything and has been removed.
Farm v6 was last deployed on 2024-05-13 and is not an Anchor program from an integrator’s point of view. If you need to compose with it from your own on-chain program, construct the Instruction by hand — derive the account list and instruction discriminators independently (from the SDK’s TypeScript layouts under raydium-sdk-V2/src/raydium/farm/, or by decoding real transactions), and invoke_signed it. See sdk-api/rust-cpi for that procedure. Whichever route you take, the remaining_accounts tail must match the farm’s active reward slots 1-for-1 (pairs of reward_vault_i, user_reward_ata_i in index order). Omitting or misordering these produces a silent mis-accounting — the program will transfer the wrong amount.

Pitfalls

  • Forgetting to claim before withdrawing. Harmless — Withdraw settles pending rewards first. But if your UI shows “claim” separately from “withdraw”, the user may think there is still something to claim after a Withdraw. There is not; everything accrued up to that point was paid out.
  • total_staked = 0 during emissions. Emissions accrued while nothing was staked are forfeited (the reward_per_share update formula divides by 0 and the program skips the update). For programs with scheduled open_time, run a “seed stake” at open_time to avoid this.
  • Token-2022 transfer fees. On v6 farms with Token-2022 reward mints, the transfer fee applies on emit (vault → user). Factor this into APR quotes.
  • Small per_second on v5. v5’s u64 rate means any per_second < 1 token-unit per second (on mints with ≥9 decimals this is often the desired rate) cannot be expressed — the stream rate rounds to 0 and the farm emits nothing. Use v6.

Where to go next

Sources: