# 質押代幣與資產

「質押」是將代幣或資產 (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 質押代幣與一個資產 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` 的元組 (tuple)。此地址對於未來所有與此特定質押相關的互動（例如撤銷或削減）至關重要。

---


## 如何撤銷質押

撤銷質押是由質押者發起以取回其鎖定代幣和資產的過程。此交易不會立即返還資金；而是將其標記為可供領取，但需遵守任何鏈上的鎖定期。

### 參數

<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 撤銷質押 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('重要：請儲存此雜湊值，以便稍後領取您的質押。');
    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 領取已質押物品 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('您的代幣和資產已返還至您的帳戶。');
  } 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 削減質押 icon=logos:javascript
// 假設 'stakeAddress' 是待削減質押的地址，
// 且 'slasherWallet' 是一個授權削減者的錢包。

async function slashExistingStake(stakeAddress) {
  try {
    const slashTxHash = await client.slashStake({
      from: stakeAddress,
      reason: '驗證者連續錯過 10 個區塊的簽署。',
      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) 指南。
