# Delegate Permissions

Delegating permissions is a powerful feature that allows one account (the delegator) to authorize another account (the delegatee) to send specific types of transactions on its behalf. This is particularly useful for applications that need to perform actions for a user without having direct access to the user's primary private key. For example, you could delegate permission to an application-specific key to transfer certain assets or interact with a smart contract, enhancing security by limiting the scope of the key's authority.

This guide will walk you through granting, using, and revoking delegations.


## Granting Delegation

To authorize another account, you use the `delegate` method. You must specify who you are delegating to and which specific transaction types they are allowed to send. Each permission can also have limits, such as which tokens or assets can be involved.

### Parameters

<x-field-group>
  <x-field data-name="from" data-type="WalletObject" data-required="true">
    <x-field-desc markdown>The wallet object of the delegator (the account granting permissions).</x-field-desc>
  </x-field>
  <x-field data-name="to" data-type="WalletObject" data-required="true">
    <x-field-desc markdown>The wallet object of the delegatee (the account receiving permissions).</x-field-desc>
  </x-field>
  <x-field data-name="privileges" data-type="Array<object>" data-required="true">
    <x-field-desc markdown>An array of permission objects to grant. Each object defines a specific authorization.</x-field-desc>
    <x-field data-name="typeUrl" data-type="string" data-required="true">
      <x-field-desc markdown>The type URL of the transaction being permitted (e.g., `fg:t:transfer_v2`).</x-field-desc>
    </x-field>
    <x-field data-name="limit" data-type="object" data-required="false">
      <x-field-desc markdown>Optional limits on the permission, such as restricting it to specific tokens or assets.</x-field-desc>
      <x-field data-name="tokens" data-type="Array<string>" data-required="false" data-desc="An array of token addresses that this permission applies to."></x-field>
      <x-field data-name="assets" data-type="Array<string>" data-required="false" data-desc="An array of asset addresses that this permission applies to."></x-field>
    </x-field>
  </x-field>
</x-field-group>

### Returns

<x-field data-name="result" data-type="Promise<[string, string]>" data-desc="A promise that resolves to an array containing the transaction hash and the newly created delegate address."></x-field>

### Example

Here’s how to delegate the `transfer` permission from one account to another.

```javascript Granting transfer permission 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');

// The account granting permission
const delegatorWallet = fromRandom();

// The account receiving permission
const delegateeWallet = fromRandom();

async function grantPermission() {
  try {
    // First, ensure the delegator account has funds.
    // In a real application, you would transfer funds to delegatorWallet.address
    // from a faucet or another account.
    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,
        // No limits specified, allowing transfer of any token/asset
        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();
```


## Sending a Transaction as a Delegatee

Once delegated, the delegatee wallet can send the authorized transaction by specifying the `delegator`'s address in the transaction parameters. The transaction is signed by the delegatee, but executed on behalf of the delegator, and the transaction fees are paid from the delegator's account.

### Example

```javascript Sending a transfer as a delegatee icon=logos:javascript
// Assuming the grantPermission() function from the previous example was successful

// The recipient of the transfer
const recipientWallet = fromRandom();

async function sendDelegatedTransaction() {
  try {
    const hash = await client.transfer({
      to: recipientWallet.address,
      token: 1, // Transfer 1 of the chain's native token
      wallet: delegateeWallet, // Signed by the delegatee
      delegator: delegatorWallet.address, // Executed on behalf of the delegator
    });

    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);
  }
}

// Make sure to call this after the delegation is confirmed on-chain.
// sendDelegatedTransaction();
```


## Revoking Delegation

The delegator can revoke any granted permissions at any time using the `revokeDelegate` method. You need to specify which transaction types to revoke for a given delegatee.

### Parameters

<x-field-group>
  <x-field data-name="from" data-type="WalletObject" data-required="true">
    <x-field-desc markdown>The wallet object of the delegator who originally granted the permissions.</x-field-desc>
  </x-field>
  <x-field data-name="to" data-type="WalletObject" data-required="true">
    <x-field-desc markdown>The wallet object of the delegatee whose permissions are being revoked.</x-field-desc>
  </x-field>
  <x-field data-name="privileges" data-type="Array<string>" data-required="true">
    <x-field-desc markdown>An array of transaction `typeUrl` strings to revoke.</x-field-desc>
  </x-field>
</x-field-group>

### Returns

<x-field data-name="hash" data-type="Promise<string>" data-desc="A promise that resolves to the transaction hash for the revocation."></x-field>

### Example

```javascript Revoking transfer permission icon=logos:javascript
// Assuming the same delegatorWallet and delegateeWallet from previous examples

async function revokePermission() {
  try {
    const hash = await client.revokeDelegate({
      from: delegatorWallet,
      to: delegateeWallet,
      privileges: [typeUrls.TransferV2Tx], // The list of permissions to revoke
    });

    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();
```

After this transaction is confirmed, the `delegateeWallet` will no longer be able to send `transfer` transactions on behalf of the `delegatorWallet`.
