> ## Documentation Index
> Fetch the complete documentation index at: https://docs.powfi.alephium.org/llms.txt
> Use this file to discover all available pages before exploring further.

# Staking

> Staking liquide xALPH : staker de l'ALPH, unstaker avec un déblocage linéaire, et coffres du collecteur de frais du protocole.

export const VersionBanner = ({network = 'mainnet', products = [], lang = 'en'}) => {
  const SDK_VERSION = '1.0.2';
  const ADDRESSES = {
    mainnet: {
      cpmm: {
        Router: 'ze15rnAwTyVCPnDhN7J8An3SvNeWBsZHAVMeBx1ehXeP',
        TokenPairFactory: '24CXRLvj1QiDH6riwr1EPERG7BcduHKZtktygbq97MfYb'
      },
      clmm: {
        PoolFactory: '24gqd4DMQXVzjm5QDAGxUtYupx3WM2PSu3vZUseuBCV9h',
        PositionManager: 'vFyKSqnJHS9MicrojBcLgztyRFqhS4hB349Ci3LJCELw'
      },
      staking: {
        XAlphToken: '225WevmFp5ZgzPsyVJTvyp2v2uyKrvp329HfrVmzffnWj',
        RewardFeeCollector: '22CE7vG6u64zjjsLZLxeJqQuPDydjPvbP9iG1d861j2G7'
      }
    },
    testnet: {
      cpmm: {
        Router: 'xaueT8kPMvpnaFJEfHv6CJLgqsSPpoNmHjF1QgTxoF9R',
        TokenPairFactory: '29hdd9b9Gp7oXuamwHKfUqBaRXP487HoeTcutS3RhZJEj'
      },
      clmm: {
        PoolFactory: 'z2QFT7qBQrfm8UwAYG3VHWoHs7B56ZDFNdSCcDu5j53m',
        PositionManager: '21p6egW8d6FEyVVuH17WqvHCARsCsD61GcBmeCr75XdGT'
      },
      staking: {
        XAlphToken: '23psDicimC5VdpM56wrgqgCzQzcyXWGCkQGSYWbtZAPRq',
        RewardFeeCollector: '29qQ1LPJ5uqawRviXLVDMeo19JUygRrNNTQy5RUBh817D'
      }
    }
  };
  const EXPLORERS = {
    mainnet: 'https://explorer.alephium.org/addresses/',
    testnet: 'https://testnet.alephium.org/addresses/'
  };
  const LABELS = {
    en: {
      sdk: 'SDK',
      network: 'Network',
      contracts: 'Contracts',
      all: 'All addresses',
      allNetworks: 'mainnet · testnet · devnet',
      devnet: 'Local deployment (addresses vary per devnet)'
    },
    zh: {
      sdk: 'SDK 版本',
      network: '网络',
      contracts: '合约',
      all: '全部地址',
      allNetworks: 'mainnet · testnet · devnet',
      devnet: '本地部署（每个 devnet 的地址不同）'
    },
    fr: {
      sdk: 'SDK',
      network: 'Réseau',
      contracts: 'Contrats',
      all: 'Toutes les adresses',
      allNetworks: 'mainnet · testnet · devnet',
      devnet: 'Déploiement local (adresses propres à chaque devnet)'
    }
  };
  const t = LABELS[lang] ?? LABELS.en;
  const contractsPage = lang === 'en' ? '/reference/contracts' : `/${lang}/reference/contracts`;
  const short = a => `${a.slice(0, 6)}…${a.slice(-4)}`;
  const entries = [];
  const addrs = ADDRESSES[network];
  if (addrs) {
    for (const p of products) {
      for (const [name, address] of Object.entries(addrs[p] ?? ({}))) entries.push({
        name,
        address
      });
    }
  }
  let contractsCell;
  if (network === 'devnet' && products.length > 0) {
    contractsCell = <span>{t.devnet}</span>;
  } else if (entries.length > 0) {
    contractsCell = entries.map(({name, address}, i) => <span key={name}>
        {i > 0 && <span className="mx-1 opacity-50">·</span>}
        {name}{' '}
        <a href={EXPLORERS[network] + address} target="_blank" rel="noreferrer" title={address}>
          <code>{short(address)}</code>
        </a>
      </span>);
  }
  const row = (label, value) => <div className="flex flex-wrap gap-x-2">
      <span className="font-semibold min-w-[5.5rem]">{label}</span>
      <span className="flex-1 min-w-0 break-words">{value}</span>
    </div>;
  return <div className="not-prose mb-6 rounded-xl border border-zinc-950/10 dark:border-white/10 bg-zinc-50 dark:bg-white/5 px-4 py-3 text-sm leading-6 text-zinc-700 dark:text-zinc-300">
      {row(t.sdk, <code>@alephium/powfi-sdk@{SDK_VERSION}</code>)}
      {row(t.network, network === 'all' ? t.allNetworks : network)}
      {contractsCell && row(t.contracts, <span>
            {contractsCell}
            <span className="mx-1 opacity-50">·</span>
            <a href={contractsPage}>{t.all} →</a>
          </span>)}
    </div>;
};

<VersionBanner network="mainnet" products={['staking']} lang="fr" />

```ts theme={null}
powfi.staking // StakingModule
```

Staker de l'ALPH minte du **xALPH**, un jeton liquide dont la valeur en ALPH augmente à mesure que les récompenses du protocole sont déposées. L'unstake détruit du xALPH et ouvre un **coffre d'unstake** qui libère l'ALPH linéairement sur `unstakeDuration`.

<Card title="Guide : staker et unstaker de l'ALPH" icon="coins" href="/fr/guides/xalph-staking" horizontal />

## Paramètres

```ts theme={null}
powfi.staking.getSettings()
// { unstakeDuration, maxActiveUnstakeRequestsPerUser }
```

| Réseau | `unstakeDuration` | `maxActiveUnstakeRequestsPerUser` |
| - | - | - |
| mainnet | 30 jours (`2_592_000_000n` ms) | `16n` |
| testnet | 30 jours | `16n` |
| devnet | 1 minute (`60_000n` ms) | `16n` |

Ces valeurs reflètent les paramètres des contrats. Les valeurs réelles se trouvent dans `getXAlphTokenState()` (`fields.unstakeDuration`, `fields.maxActiveUnstakeRequestsPerUser`).

## Jeton xALPH

### `getXAlphTokenState()`

```ts theme={null}
getXAlphTokenState(): Promise<XAlphTokenTypes.State>
```

Champs utiles :

| Champ | Signification |
| - | - |
| `totalDepositedAlph` | ALPH adossé à l'ensemble du xALPH |
| `totalXAlphSupply` | xALPH en circulation |
| `unstakeDuration` | Période de déblocage en ms (l'ALPH se débloque linéairement) |
| `lastUnstakeVaultIndex` | Compteur global des coffres d'unstake |

Taux de change : **1 xALPH = `totalDepositedAlph / totalXAlphSupply` ALPH**.

```ts theme={null}
const { fields } = await powfi.staking.getXAlphTokenState()
const alphPerXAlph = new Decimal(fields.totalDepositedAlph.toString()).div(fields.totalXAlphSupply.toString())
```

`getXAlphToken()` renvoie la `XAlphTokenInstance` typée. `getConfig().xAlphTokenId` est l'identifiant du jeton xALPH.

## Staker

### `stakeAlph(amount)`

```ts theme={null}
stakeAlph(amount: bigint): Promise<XAlphTokenTypes.SignExecuteMethodResult<'stake'>>
```

Stake `amount` attoALPH et minte du xALPH pour le signataire au taux actuel. Joint `amount + MINIMAL_CONTRACT_DEPOSIT` d'ALPH. Le contrat du jeton xALPH est enregistré comme parrain.

### `stakeAlphWithReferral(amount, referral)`

Identique, avec une adresse de parrainage `referral` personnalisée. Le contrat ne valide pas le parrain et ne lui envoie rien : il se contente de l'enregistrer dans l'événement `Staked(to, referral, alphAmount, xAlphAmount)`. Les partenaires qui veulent une commission sur les stakes parrainés doivent [contacter l'équipe au préalable](/fr/guides/referral-staking).

### `donateReward(amount)`

Dépose `amount` ALPH en récompense pour tous les détenteurs de xALPH **sans minter de xALPH**, ce qui augmente le taux de change.

## Unstaker

L'unstake se débloque linéairement. Après `startUnstake`, l'ALPH réclamable augmente avec le temps écoulé, et la totalité est disponible après `unstakeDuration`. Appelez `claimUnstaked` à tout moment pour retirer ce qui est déjà débloqué.

### `startUnstake(amount)`

```ts theme={null}
startUnstake(amount: bigint): Promise<XAlphTokenTypes.SignExecuteMethodResult<'startUnstake'>>
```

Détruit `amount` xALPH et crée un nouveau coffre d'unstake pour le signataire, contenant l'équivalent en ALPH. Chaque utilisateur peut détenir au plus `maxActiveUnstakeRequestsPerUser` coffres actifs.

### `getActiveUnstakeVaultIndexes(address)`

Renvoie un `bigint[]` avec les index des coffres des demandes en attente ou réclamables de l'utilisateur.

### `getAlphUnstakeVaultState(address, vaultIndex)`

```ts theme={null}
// fields: { unstakerAddress, totalUnstakeAmount, unstakeStartTime, unstakeDuration, withdrawnAmount, xalphToken }
```

L'ALPH réclamable vaut `totalUnstakeAmount × min(écoulé, unstakeDuration) / unstakeDuration − withdrawnAmount` : une demande est donc entièrement débloquée à `unstakeStartTime + unstakeDuration`. `getAlphUnstakeVault(address, vaultIndex)` renvoie l'instance de contrat typée.

### `getClaimableAmount(address, vaultIndex)`

ALPH actuellement réclamable dans un coffre. Il augmente linéairement à partir de `0n` au début de la demande.

### `claimUnstaked(vaultIndex, amount)`

Retire `amount` ALPH du coffre vers le signataire. `amount` doit être supérieur à 0 et au plus égal au montant réclamable.

### `cancelUnstake(vaultIndex)`

Clôt une demande. L'ALPH déjà débloqué est envoyé au signataire, et le reste est re-staké et rendu en xALPH au taux actuel. L'événement `UnstakeCancelled` indique `xAlphAmount`, `claimedAlphAmount` et `restakedAlphAmount`.

## Comment les récompenses parviennent au xALPH

Les frais de protocole des pools CPMM et CLMM arrivent dans le `RewardFeeCollector`. L'équipe Powfi les collecte et les convertit en ALPH. Ensuite, `distributeRewards` distribue `totalDepositedAlph × rewardRate / 10000 × temps écoulé / 1 an` (un taux annuel), plafonné par l'ALPH détenu par le collecteur. La part de la trésorerie est prélevée en premier, une part brûlée est prélevée sur le reste, et le solde est déposé dans le xALPH, ce qui fait monter le taux de change.

`distributeRewards` n'est pas restreinte, et rien ne l'appelle automatiquement. Hormis `donateReward`, qui fait monter le taux immédiatement, le taux du xALPH n'augmente que lorsque quelqu'un l'appelle.

| Méthode | Description |
| - | - |
| `distributeRewards(contractId)` | Distribue les récompenses en attente. Passez `getConfig().feeCollectorId`. |
| `getVault(token)` / `getDistributorVaultId(token)` | Coffre du collecteur de frais pour un jeton (pour le CPMM, indexé par l'identifiant du jeton LP, c'est-à-dire l'identifiant du pool) |
| `getVaultState(token)` | `{ address, id, state, balances }` |

## Autres accesseurs

| Méthode | Renvoie |
| - | - |
| `getConfig()` / `setConfig(config)` | `StakingConfig` |
| `getRewardFeeCollector(contractId)` | `RewardFeeCollectorInstance` |

```ts theme={null}
interface StakingConfig {
  groupIndex: number
  alphUnstakeVaultTemplateId: string
  xAlphTokenId: string
  xAlphTokenAddress: string
  feeCollectorId: string
}
```

## Helpers

`decodeU256List(hex)` et `decodeContractIdList(hex)` décodent les vecteurs d'octets compactés renvoyés par les contrats de staking (segments de 32 octets).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.