# 委派權限

委派權限是一項強大的功能，它允許一個帳戶（委派人）授權另一個帳戶（受派人）代表其發送特定類型的交易。這對於需要為使用者執行操作，但又不想直接存取使用者主私鑰的應用程式特別有用。例如，您可以將權限委派給特定於應用程式的金鑰，以轉移某些資產或與智慧合約互動，透過限制金鑰的權限範圍來增強安全性。

本指南將引導您完成授予、使用和撤銷委派的過程。


## 授予委派

若要授權另一個帳戶，您需要使用 `delegate` 方法。您必須指定要委派給誰，以及他們被允許發送哪些特定交易類型。每項權限還可以設定限制，例如可以涉及哪些代幣或資產。

### 參數

<x-field-group>
  <x-field data-name="from" data-type="WalletObject" data-required="true">
    <x-field-desc markdown>委派人（授予權限的帳戶）的錢包物件。</x-field-desc>
  </x-field>
  <x-field data-name="to" data-type="WalletObject" data-required="true">
    <x-field-desc markdown>受派人（接收權限的帳戶）的錢包物件。</x-field-desc>
  </x-field>
  <x-field data-name="privileges" data-type="Array<object>" data-required="true">
    <x-field-desc markdown>一個要授予的權限物件陣列。每個物件都定義了一個特定的授權。</x-field-desc>
    <x-field data-name="typeUrl" data-type="string" data-required="true">
      <x-field-desc markdown>被允許的交易的類型 URL（例如：`ocap:t:transfer_v2`）。</x-field-desc>
    </x-field>
    <x-field data-name="limit" data-type="object" data-required="false">
      <x-field-desc markdown>對權限的選用限制，例如限制於特定的代幣或資產。</x-field-desc>
      <x-field data-name="tokens" data-type="Array<string>" data-required="false" data-desc="此權限適用的代幣地址陣列。"></x-field>
      <x-field data-name="assets" data-type="Array<string>" data-required="false" data-desc="此權限適用的資產地址陣列。"></x-field>
    </x-field>
  </x-field>
</x-field-group>

### 返回值

<x-field data-name="result" data-type="Promise<[string, string]>" data-desc="一個解析為包含交易雜湊和新建立的委派地址的陣列的 Promise。"></x-field>

### 範例

以下是如何將 `transfer` 權限從一個帳戶委派給另一個帳戶。

```javascript 授予轉帳權限 icon=logos:javascript
import Client from '@ocap/client';
import { fromRandom } from '@ocap/wallet';
import { typeUrls } from '@ocap/proto';

const client = new Client('https://beta.abtnetwork.io/api');

// 授予權限的帳戶
const delegatorWallet = fromRandom();

// 接收權限的帳戶
const delegateeWallet = fromRandom();

async function grantPermission() {
  try {
    // 首先，確保委派人帳戶中有資金。
    // 在實際應用中，您需要從水龍頭或其他帳戶轉帳資金到 delegatorWallet.address
    console.log(`Delegator address: ${delegatorWallet.address}`);
    console.log(`Delegatee address: ${delegateeWallet.address}`);
    console.log('Please fund the delegator account before proceeding.');

    const privileges = [
      {
        typeUrl: typeUrls.TransferV2Tx,
        // 未指定限制，允許轉移任何代幣/資產
        limit: { tokens: [], assets: [] },
      },
    ];

    const [hash, delegateAddress] = await client.delegate({
      from: delegatorWallet,
      to: delegateeWallet,
      privileges: privileges,
    });

    console.log('Delegation successful!');
    console.log('Transaction Hash:', hash);
    console.log('Delegate Address:', delegateAddress);
  } catch (error) {
    console.error('Error delegating permissions:', error);
  }
}

grantPermission();
```


## 作為受派人發送交易

一旦獲得委派，受派人錢包可以透過在交易參數中指定 `delegator` 的地址來發送已授權的交易。該交易由受派人簽署，但代表委派人執行，交易費用從委派人的帳戶中支付。

### 範例

```javascript 作為受派人發送轉帳 icon=logos:javascript
// 假設前一個範例中的 grantPermission() 函數已成功執行

// 轉帳的接收人
const recipientWallet = fromRandom();

async function sendDelegatedTransaction() {
  try {
    const hash = await client.transfer({
      to: recipientWallet.address,
      token: 1, // 轉移 1 個鏈的原生代幣
      wallet: delegateeWallet, // 由受派人簽署
      delegator: delegatorWallet.address, // 代表委派人執行
    });

    console.log('Delegated transfer successful!');
    console.log('Transaction Hash:', hash);
    console.log(`Check transaction at: https://beta.abtnetwork.io/explorer/txs/${hash}`);
  } catch (error) {
    console.error('Error sending delegated transaction:', error);
  }
}

// 請確保在委派上鏈確認後再呼叫此函數。
// sendDelegatedTransaction();
```


## 撤銷委派

委派人可以隨時使用 `revokeDelegate` 方法撤銷任何已授予的權限。您需要為指定的受派人指定要撤銷哪些交易類型。

### 參數

<x-field-group>
  <x-field data-name="from" data-type="WalletObject" data-required="true">
    <x-field-desc markdown>最初授予權限的委派人的錢包物件。</x-field-desc>
  </x-field>
  <x-field data-name="to" data-type="WalletObject" data-required="true">
    <x-field-desc markdown>其權限將被撤銷的受派人的錢包物件。</x-field-desc>
  </x-field>
  <x-field data-name="privileges" data-type="Array<string>" data-required="true">
    <x-field-desc markdown>一個要撤銷的交易 `typeUrl` 字串陣列。</x-field-desc>
  </x-field>
</x-field-group>

### 返回值

<x-field data-name="hash" data-type="Promise<string>" data-desc="一個解析為撤銷操作的交易雜湊的 Promise。"></x-field>

### 範例

```javascript 撤銷轉帳權限 icon=logos:javascript
// 假設 delegatorWallet 和 delegateeWallet 與前述範例中相同

async function revokePermission() {
  try {
    const hash = await client.revokeDelegate({
      from: delegatorWallet,
      to: delegateeWallet,
      privileges: [typeUrls.TransferV2Tx], // 要撤銷的權限列表
    });

    console.log('Revocation successful!');
    console.log('Transaction Hash:', hash);
    console.log(`Check transaction at: https://beta.abtnetwork.io/explorer/txs/${hash}`);
  } catch (error) {
    console.error('Error revoking delegation:', error);
  }
}

// revokePermission();
```

此交易確認後，`delegateeWallet` 將無法再代表 `delegatorWallet` 發送 `transfer` 交易。
