# 质押通证和资产

质押是将通证或资产 (NFT) 锁定给特定接收者的过程，通常是为了保障网络安全、参与治理或赚取奖励。本指南使用 OCAP Client 详细介绍了整个质押生命周期的分步操作，包括创建质押、撤销质押、领回资产以及因惩罚性原因罚没质押。

此过程涉及几个关键方法：

* `stake()`：创建一个新的质押。
* `revokeStake()`：启动取回已质押物品的过程。
* `claimStake()`：完成取回操作，将物品返还至您的账户。
* `slashStake()`：允许授权方惩罚质押者。


## 如何质押

首先，您使用 `stake` 方法来锁定您的通证或资产。此操作会在链上创建一个新的、唯一的质押地址，该地址持有您质押的物品及管理这些物品的规则。

### 参数

<x-field-group>
  <x-field data-name="to" data-type="string" data-required="true" data-desc="接收质押的账户的 DID 地址。"></x-field>
  <x-field data-name="assets" data-type="string[]" data-required="false" data-desc="要质押的资产地址 (NFT) 数组。"></x-field>
  <x-field data-name="tokens" data-type="object[]" data-required="false" data-desc="要质押的通证对象数组。">
    <x-field data-name="address" data-type="string" data-required="true" data-desc="通证合约的地址。"></x-field>
    <x-field data-name="value" data-type="number" data-required="true" data-desc="要质押的通证数量。"></x-field>
  </x-field>
  <x-field data-name="wallet" data-type="WalletObject" data-required="true" data-desc="质押者的钱包对象。"></x-field>
  <x-field data-name="locked" data-type="boolean" data-default="false" data-required="false" data-desc="指示质押在创建时是否锁定的布尔值。"></x-field>
  <x-field data-name="slashers" data-type="string[]" data-required="false" data-desc="允许罚没此质押的 DID 地址数组。如果未提供，则默认为接收者的地址。"></x-field>
  <x-field data-name="message" data-type="string" data-required="false" data-desc="质押的可选备注或消息。"></x-field>
  <x-field data-name="nonce" data-type="string" data-required="false" data-desc="确保质押地址唯一的可选 nonce。"></x-field>
</x-field-group>

### 示例

```javascript Staking Tokens and an Asset icon=logos:javascript
// 假设 'client' 是一个已初始化的 GraphQLClient 实例
// 且 'stakerWallet' 是一个有效的钱包对象。
const receiverAddress = 'z29d5852576b8a8b6f3a8b4b74a3f4a3e2e1d'; // 质押接收者的地址

async function createStake() {
  try {
    const [txHash, stakeAddress] = await client.stake({
      to: receiverAddress,
      tokens: [{
        address: 'z35n6aTUTK8h5nAF43h21A1g84g3C3D7B5E', // 要质押的通证地址
        value: 100, // 要质押的通证数量
      }],
      assets: ['zNKtA1B2C3D4E5F6G7H8I9J0K1L2M3N4O5P6'], // 要质押的资产/NFT 地址
      message: 'Staking for validator rewards',
      wallet: stakerWallet,
    });

    console.log('Stake transaction sent:', txHash);
    console.log('New stake address created:', stakeAddress);
    return stakeAddress;
  } catch (error) {
    console.error('Error creating stake:', error);
  }
}
```

### 返回值

`stake` 方法返回一个包含交易哈希和新创建的 `stakeAddress` 的元组。此地址对于未来与此特定质押的所有交互（如撤销或罚没）至关重要。

---


## 如何撤销质押

撤销质押是由质押者发起的、用以取回其锁定的通证和资产的过程。此交易不会立即返还资金；相反，它会将资金标记为可供领回，但需遵守链上任何锁定期规定。

### 参数

<x-field-group>
  <x-field data-name="from" data-type="string" data-required="true" data-desc="要撤销的质押地址（从 'stake' 调用中获取）。"></x-field>
  <x-field data-name="assets" data-type="string[]" data-required="false" data-desc="要从质押中撤销的资产地址数组。"></x-field>
  <x-field data-name="tokens" data-type="object[]" data-required="false" data-desc="要撤销的通证对象数组。">
    <x-field data-name="address" data-type="string" data-required="true" data-desc="通证合约的地址。"></x-field>
    <x-field data-name="value" data-type="number" data-required="true" data-desc="要撤销的通证数量。"></x-field>
  </x-field>
  <x-field data-name="wallet" data-type="WalletObject" data-required="true" data-desc="质押者的钱包对象，必须是质押的原始创建者。"></x-field>
</x-field-group>

### 示例

```javascript Revoking a Stake icon=logos:javascript
// 假设 'stakeAddress' 是上一步返回的地址
// 且 'stakerWallet' 是用于创建质押的同一个钱包。

async function revokeExistingStake(stakeAddress) {
  try {
    const revokeTxHash = await client.revokeStake({
      from: stakeAddress,
      tokens: [{
        address: 'z35n6aTUTK8h5nAF43h21A1g84g3C3D7B5E',
        value: 100,
      }],
      assets: ['zNKtA1B2C3D4E5F6G7H8I9J0K1L2M3N4O5P6'],
      wallet: stakerWallet,
    });

    console.log('Revoke stake transaction sent:', revokeTxHash);
    console.log('IMPORTANT: Save this hash to claim your stake later.');
    return revokeTxHash;
  } catch (error) {
    console.error('Error revoking stake:', error);
  }
}
```

### 返回值

此函数返回撤销操作的交易哈希。该哈希作为凭证，并且是领回质押的最后一步所**必需**的。

---


## 如何领回已撤销的质押

质押成功撤销后，质押者必须发送一个 `claimStake` 交易，才能将通证和资产移回其账户。这标志着取回过程的最终完成。

### 参数

<x-field-group>
  <x-field data-name="from" data-type="string" data-required="true" data-desc="质押的地址。"></x-field>
  <x-field data-name="evidence" data-type="string" data-required="true" data-desc="来自 'revokeStake' 调用的交易哈希，作为撤销的凭证。"></x-field>
  <x-field data-name="wallet" data-type="WalletObject" data-required="true" data-desc="质押者的钱包对象。"></x-field>
</x-field-group>

### 示例

```javascript Claiming Staked Items icon=logos:javascript
// 假设 'stakeAddress' 和 'revokeTxHash' 来自前面的步骤，
// 且 'stakerWallet' 是质押者的钱包。

async function claimRevokedStake(stakeAddress, revokeTxHash) {
  try {
    const claimTxHash = await client.claimStake({
      from: stakeAddress,
      evidence: revokeTxHash,
      wallet: stakerWallet,
    });

    console.log('Claim stake transaction sent:', claimTxHash);
    console.log('Your tokens and assets have been returned to your account.');
  } catch (error) {
    console.error('Error claiming stake:', error);
  }
}
```

### 返回值

该方法返回最终的交易哈希。一旦此交易在链上确认，质押的物品将返还至 `wallet` 的地址。

---


## 如何罚没质押

罚没是一种惩罚性操作，可由指定的 `slasher`（通常是质押接收者）对质押者执行。这种情况通常发生在质押者违反某些规则时。被罚没的通证或资产将从质押中移除，并发送至指定的保险库。

### 参数

<x-field-group>
  <x-field data-name="from" data-type="string" data-required="true" data-desc="要罚没的质押地址。"></x-field>
  <x-field data-name="reason" data-type="string" data-required="true" data-desc="解释罚没原因的强制性消息。"></x-field>
  <x-field data-name="assets" data-type="string[]" data-required="false" data-desc="要从质押中罚没的资产地址数组。"></x-field>
  <x-field data-name="tokens" data-type="object[]" data-required="false" data-desc="要罚没的通证对象数组。">
    <x-field data-name="address" data-type="string" data-required="true" data-desc="通证合约的地址。"></x-field>
    <x-field data-name="value" data-type="number" data-required="true" data-desc="要罚没的通证数量。"></x-field>
  </x-field>
  <x-field data-name="wallet" data-type="WalletObject" data-required="true" data-desc="经授权的罚没者的钱包对象。"></x-field>
</x-field-group>

### 示例

```javascript Slashing a Stake icon=logos:javascript
// 假设 'stakeAddress' 是要罚没的质押地址，
// 且 'slasherWallet' 是经授权的罚没者的钱包。

async function slashExistingStake(stakeAddress) {
  try {
    const slashTxHash = await client.slashStake({
      from: stakeAddress,
      reason: 'Validator missed signing 10 consecutive blocks.',
      tokens: [{
        address: 'z35n6aTUTK8h5nAF43h21A1g84g3C3D7B5E',
        value: 10, // 罚没 10 个通证作为惩罚
      }],
      wallet: slasherWallet,
    });

    console.log('Slash stake transaction sent:', slashTxHash);
  } catch (error) {
    console.error('Error slashing stake:', error);
  }
}
```

### 返回值

此方法返回罚没操作的交易哈希。


## 总结

现在您已经了解了在 OCAP 区块链上进行质押的完整生命周期：使用 `stake` 创建质押，使用 `revokeStake` 和 `claimStake` 取回资金，以及使用 `slashStake` 惩罚恶意行为者。这一强大的机制是许多去中心化应用的基础。

要了解更多关于可以质押的物品的信息，请参阅[管理通证](./how-to-guides-manage-tokens.md)和[管理资产 (NFT)](./how-to-guides-manage-assets.md)指南。
