# 委托权限

委托权限是一项强大的功能，它允许一个账户（委托人）授权另一个账户（受托人）代表其发送特定类型的交易。这对于需要为用户执行操作但又不想直接访问用户主私钥的应用程序尤其有用。例如，您可以将权限委托给特定于应用程序的密钥，以转移某些资产或与智能合约进行交互，通过限制该密钥的权限范围来增强安全性。

本指南将引导您完成授予、使用和撤销委托的全过程。


## 授予委托

要授权另一个账户，您可以使用 `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（例如 `fg: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` 交易。
