# 権限の委任

権限の委任は、あるアカウント（委任者）が別のアカウント（受任者）に対し、自身に代わって特定の種類のトランザクションを送信することを許可する強力な機能です。これは、ユーザーの主要な秘密鍵に直接アクセスすることなく、ユーザーのためにアクションを実行する必要があるアプリケーションにとって特に便利です。例えば、特定の資産の移転やスマートコントラクトとの対話を行う権限をアプリケーション専用の鍵に委任することで、その鍵の権限範囲を限定し、セキュリティを向上させることができます。

このガイドでは、委任の付与、使用、取り消しの手順を説明します。


## 委任の付与

別のアカウントを承認するには、`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` トランザクションを送信できなくなります。
