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

# Exemples de code pour Farm / Staking

> Exemples TypeScript pour créer une farm, mettre en stake des LP, collecter les récompenses et augmenter les budgets de récompenses contre le programme farm v6 de Raydium.

<Info>
  **Cette page est traduite automatiquement par IA. La version anglaise fait foi.**

  [Voir la version anglaise →](/products/farm-staking/code-demos)
</Info>

<Info>
  **Banneau de version.** Tous les exemples ciblent `@raydium-io/raydium-sdk-v2@0.2.42-alpha` sur Solana mainnet-beta, vérifié en 2026-04. Le SDK dispatche v3 / v5 / v6 en interne selon le propriétaire du programme de la farm ; les exemples ci-dessous supposent une farm v6. Consultez [`reference/program-addresses`](/fr/reference/program-addresses) pour les trois identifiants de programme.
</Info>

## Installation

Les exemples ici reflètent les fichiers dans [`raydium-sdk-V2-demo/src/farm`](https://github.com/raydium-io/raydium-sdk-V2-demo/tree/master/src/farm). L'initialisation suit le [`config.ts.template`](https://github.com/raydium-io/raydium-sdk-V2-demo/blob/master/src/config.ts.template) du dépôt de démonstration :

```ts theme={null}
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;
```

## Récupérer une farm par ID

```ts theme={null}
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` récupère `FarmState` hors-chaîne, décode selon la version du programme, et normalise le taux d'émission à virgule fixe en un simple `Decimal` par seconde.

## Mettre en stake des tokens LP

Source : [`src/farm/stake.ts`](https://github.com/raydium-io/raydium-sdk-V2-demo/blob/master/src/farm/stake.ts)

```ts theme={null}
const amount = new BN(1_000_000_000);   // 1 LP (en supposant 9 décimales)

const { execute } = await raydium.farm.deposit({
  farmInfo: farm,
  amount,
  txVersion: TxVersion.V0,
});

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

Le SDK gère le pré-règlement de toute récompense en attente, donc si ce portefeuille a déjà des stakes dans cette farm, l'instruction versera les récompenses accumulées aux ATAs de l'utilisateur dans la même transaction.

## Récolte uniquement (harvest)

Source : [`src/farm/harvest.ts`](https://github.com/raydium-io/raydium-sdk-V2-demo/blob/master/src/farm/harvest.ts)

```ts theme={null}
const { execute } = await raydium.farm.harvestAllRewards({
  farmInfoList: [farm],
  txVersion: TxVersion.V0,
});

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

`harvestAllRewards` accepte une liste — pour les UIs montrant une vue de portefeuille, regroupez l'appel. Chaque farm est récoltée dans une instruction séparée au sein d'une transaction (soumis à la limite de 1232 octets ; pour plus de \~6 farms, divisez en plusieurs transactions).

Pour une seule farm sur v6, vous pouvez aussi utiliser le chemin `Harvest` explicite :

```ts theme={null}
const { execute } = await raydium.farm.withdraw({
  farmInfo: farm,
  amount: new BN(0),        // 0 = chemin harvest-only, même sur v6
  txVersion: TxVersion.V0,
});
await execute({ sendAndConfirm: true });
```

Sur v3 et v5, l'idiome `amount: 0` est requis ; le SDK le dispatche correctement.

## Retirer les stakes

Source : [`src/farm/unstake.ts`](https://github.com/raydium-io/raydium-sdk-V2-demo/blob/master/src/farm/unstake.ts)

```ts theme={null}
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 });
```

## Créer une farm v6

Source : [`src/farm/createAmmFarm.ts`](https://github.com/raydium-io/raydium-sdk-V2-demo/blob/master/src/farm/createAmmFarm.ts) et [`editAmmFarm.ts`](https://github.com/raydium-io/raydium-sdk-V2-demo/blob/master/src/farm/editAmmFarm.ts)

```ts theme={null}
import { CurveCalculator } from "@raydium-io/raydium-sdk-v2"; // optionnel, pour la planification du APR

const stakingMint = new PublicKey("<LP_MINT>");       // par exemple, un mint LP CPMM
const rewardMint  = new PublicKey("<REWARD_MINT>");   // par exemple, le token de votre projet

const now      = Math.floor(Date.now() / 1000);
const openTime = now + 60 * 60;                       // démarrer dans 1h
const duration = 60 * 60 * 24 * 30;                   // 30 jours
const endTime  = openTime + duration;

const totalBudget = new BN(1_000_000).mul(new BN(10).pow(new BN(9))); // 1M tokens de récompense (9 déc)
const perSecond   = totalBudget.div(new BN(duration));                // entier, le SDK élève à Q64.64

const { execute, extInfo } = await raydium.farm.create({
  programId: /* ID du programme v6, depuis 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,    // qui paie le budget initial
      mintProgramId:  /* SPL Token ou Token-2022 */,
    },
  ],
  txVersion: TxVersion.V0,
});

const { txId } = await execute({ sendAndConfirm: true });
console.log("Farm:", extInfo.farmId.toBase58(), "createTx:", txId);
```

Points clés :

* `perSecond` est le taux d'émission entier par seconde. Le SDK le compresse en Q64.64 avant l'envoi. Pour un taux fractionnaire, ajustez l'échelle et la durée.
* Le budget complet (`perSecond × duration`) doit être présent dans votre ATA de récompense — `create` le déplace dans le coffre de récompenses atomiquement.
* Vous pouvez mettre en place jusqu'à 5 récompenses en un seul appel `create`. La liste des comptes augmente de `(reward_mint, reward_vault, sender_ata, token_program)` par flux supplémentaire ; restez conscient de la limite de taille de transaction de 1232 octets. Pour 4+ récompenses, créez avec 1–2 et utilisez `AddReward` dans les transactions de suivi.

## Augmenter un flux de récompense existant

```ts theme={null}
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,                   // conserver le même taux
      payer:        owner.publicKey,
    },
  ],
  txVersion: TxVersion.V0,
});

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

`setRewards` prolonge `end_time` et transfère le budget delta. L'instruction ne peut pas raccourcir un flux, ne peut pas diminuer `per_second` sur un flux actif, et ne peut pas changer le mint de récompense. Pour changer les mints, attendez `end_time` et utilisez `AddReward` sur un emplacement libéré (s'il y en a un), ou créez une nouvelle farm.

## Redémarrer un flux terminé

```ts theme={null}
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 });
```

Valide uniquement quand l'état `reward_state == 2` (terminé) de l'emplacement cible. L'appelant doit être le `reward_sender` de l'emplacement (v6) ou le propriétaire de la farm (v5).

## CPI Rust

Contrairement à AMM v4, le programme farm v6 est livré avec une caisse Anchor (`raydium_farm_v6`) publiée aux côtés des sources frontend et SDK. Un esquisse minimal de `Deposit` :

```rust theme={null}
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>,
    // Suivi dans remaining_accounts par des paires (reward_vault_i, user_reward_ata_i)
    // pour chaque flux de récompense actif sur la 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)
}
```

La tranche `remaining_accounts` doit correspondre exactement aux emplacements de récompense actifs de la farm, 1 pour 1 (paires de `reward_vault_i`, `user_reward_ata_i` dans l'ordre des index). Omettre ou mélanger ces éléments produit une mauvaise comptabilité silencieuse — le programme transférera le mauvais montant.

## Pièges

* **Oublier de récolter avant de retirer.** Inoffensif — `Withdraw` règle d'abord les récompenses en attente. Mais si votre UI montre « récolter » séparément de « retirer », l'utilisateur peut penser qu'il y a encore quelque chose à récolter après un `Withdraw`. Ce n'est pas le cas ; tout ce qui s'est accumulé jusqu'à ce point a été versé.
* **`total_staked = 0` pendant les émissions.** Les émissions accumulées alors que rien n'était en stake sont perdues (la formule de mise à jour `reward_per_share` divise par 0 et le programme saute la mise à jour). Pour les programmes avec `open_time` programmé, exécutez un « seed stake » à open\_time pour éviter cela.
* **Frais de transfert Token-2022.** Sur les farms v6 avec mints de récompense Token-2022, le frais de transfert s'applique lors de l'émission (coffre → utilisateur). Tenez compte de cela dans les devis de APR.
* **Petit `per_second` sur v5.** Le taux `u64` de v5 signifie que tout `per_second < 1` unité token par seconde (sur les mints avec ≥9 décimales, c'est souvent le taux souhaité) ne peut pas être exprimé — le taux du flux s'arrondit à 0 et la farm n'émet rien. Utilisez v6.

## Prochaines étapes

* [`products/farm-staking/instructions`](/fr/products/farm-staking/instructions) — référence d'instruction sous-jacente.
* [`products/clmm/fees`](/fr/products/clmm/fees) — comparaison avec les flux de récompense natifs de CLMM.
* [`user-flows/migrate-amm-v4-to-cpmm`](/fr/user-flows/migrate-amm-v4-to-cpmm) — souvent associé à la création d'une nouvelle farm CPMM.

Sources :

* [Raydium SDK v2](https://github.com/raydium-io/raydium-sdk-V2)
* Farm v6 IDL fourni dans [`raydium-io/raydium-sdk-V2`](https://github.com/raydium-io/raydium-sdk-V2) sous `src/raydium/farm/`.
