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

# 质押

> xALPH 流动性质押：质押 ALPH、线性解锁的解除质押，以及协议费用收集金库。

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="zh" />

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

质押 ALPH 会铸造 **xALPH**，这是一种流动性代币，随着协议奖励存入，它以 ALPH 计的价值会不断增长。解除质押会销毁 xALPH 并开启一个**解除质押金库**，在 `unstakeDuration` 内线性释放 ALPH。

<Card title="指南：质押与解除质押 ALPH" icon="coins" href="/zh/guides/xalph-staking" horizontal />

## 设置

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

| 网络 | `unstakeDuration` | `maxActiveUnstakeRequestsPerUser` |
| - | - | - |
| mainnet | 30 天（`2_592_000_000n` 毫秒） | `16n` |
| testnet | 30 天 | `16n` |
| devnet | 1 分钟（`60_000n` 毫秒） | `16n` |

这些值与合约参数一致。链上实际值见 `getXAlphTokenState()`（`fields.unstakeDuration`、`fields.maxActiveUnstakeRequestsPerUser`）。

## xALPH 代币

### `getXAlphTokenState()`

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

常用字段：

| 字段 | 含义 |
| - | - |
| `totalDepositedAlph` | 支撑全部 xALPH 的 ALPH |
| `totalXAlphSupply` | 流通中的 xALPH |
| `unstakeDuration` | 解锁期（毫秒），ALPH 在此期间线性解锁 |
| `lastUnstakeVaultIndex` | 解除质押金库的全局计数器 |

兑换率：**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()` 返回带类型的 `XAlphTokenInstance`。`getConfig().xAlphTokenId` 是 xALPH 的代币 ID。

## 质押

### `stakeAlph(amount)`

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

质押 `amount` attoALPH，按当前兑换率向签名器铸造 xALPH。附加 `amount + MINIMAL_CONTRACT_DEPOSIT` 的 ALPH。推荐人记录为 xALPH 代币合约本身。

### `stakeAlphWithReferral(amount, referral)`

同上，但使用自定义的 `referral` 地址。合约不校验 referral，也不向它发送任何东西，只把它记录在 `Staked(to, referral, alphAmount, xAlphAmount)` 事件中。想对推荐的质押获得分润的渠道商，必须[先联系团队](/zh/guides/referral-staking)。

### `donateReward(amount)`

把 `amount` ALPH 作为奖励存给所有 xALPH 持有者，**不铸造 xALPH**，从而提高兑换率。

## 解除质押

解除质押是线性解锁的。调用 `startUnstake` 后，可领取的 ALPH 随时间增长，经过 `unstakeDuration` 后全部可领取。随时可以调用 `claimUnstaked` 领取已解锁的部分。

### `startUnstake(amount)`

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

销毁 `amount` 个 xALPH，并为签名器创建一个新的解除质押金库，存放等值的 ALPH。每个用户最多同时持有 `maxActiveUnstakeRequestsPerUser` 个活跃金库。

### `getActiveUnstakeVaultIndexes(address)`

返回 `bigint[]`：用户待处理或可领取的请求所对应的金库索引。

### `getAlphUnstakeVaultState(address, vaultIndex)`

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

可领取的 ALPH 为 `totalUnstakeAmount × min(已过时间, unstakeDuration) / unstakeDuration − withdrawnAmount`，因此请求在 `unstakeStartTime + unstakeDuration` 时全部解锁。`getAlphUnstakeVault(address, vaultIndex)` 返回带类型的合约实例。

### `getClaimableAmount(address, vaultIndex)`

某个金库当前可领取的 ALPH。从请求开始时的 `0n` 线性增长。

### `claimUnstaked(vaultIndex, amount)`

从金库向签名器提取 `amount` ALPH。`amount` 必须大于 0 且不超过可领取数量。

### `cancelUnstake(vaultIndex)`

关闭一个请求。已解锁的 ALPH 直接发给签名器，其余部分按当前汇率重新质押，以 xALPH 返还。`UnstakeCancelled` 事件会报告 `xAlphAmount`、`claimedAlphAmount` 和 `restakedAlphAmount`。

## 奖励如何到达 xALPH

CPMM 和 CLMM 池的协议费用流入 `RewardFeeCollector`，由 Powfi 团队收取并兑换成 ALPH。随后 `distributeRewards` 分配 `totalDepositedAlph × rewardRate / 10000 × 经过时间 / 1 年`（年化率），上限为收集器持有的 ALPH。先扣除国库份额，再从剩余部分扣除销毁份额，其余存入 xALPH，从而提高兑换率。

`distributeRewards` 没有调用权限限制，也不会自动执行。除了会立即提高兑换率的 `donateReward` 之外，只有有人调用它时，xALPH 兑换率才会上涨。

| 方法 | 说明 |
| - | - |
| `distributeRewards(contractId)` | 分配待发奖励。传入 `getConfig().feeCollectorId`。 |
| `getVault(token)` / `getDistributorVaultId(token)` | 费用收集器中某种代币的金库（CPMM 用 LP 代币 ID，即池 ID，作为键） |
| `getVaultState(token)` | `{ address, id, state, balances }` |

## 其他访问方法

| 方法 | 返回 |
| - | - |
| `getConfig()` / `setConfig(config)` | `StakingConfig` |
| `getRewardFeeCollector(contractId)` | `RewardFeeCollectorInstance` |

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

## 辅助函数

`decodeU256List(hex)` 和 `decodeContractIdList(hex)` 用于解码质押合约返回的打包字节向量（每 32 字节一段）。


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