> For the complete documentation index, see [llms.txt](https://help.tokenpocket.pro/developer-en/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://help.tokenpocket.pro/developer-en/agentic-wallet/eip-7715-account-with-permissions/execute-transactions-with-permissions.md).

# Execute transactions with permissions

After the user grants authorization via `wallet_requestExecutionPermissions`, the **Session Account** (`to` address) can call `redeemDelegations` on the DelegationManager to perform on-chain operations on the user's behalf within permission constraints. This section explains how to construct and send redeem transactions.

### Prerequisites <a href="#prerequisites" id="prerequisites"></a>

1. A `PermissionResponse` has been obtained (including `context` and `delegationManager`).
2. The Session Account private key is available, and its address equals `to` in the authorization.
3. The execution chain matches the authorization `chainId`.

### Core Contract Interface (EIP-7710) <a href="#core-contract-interface-eip-7710" id="core-contract-interface-eip-7710"></a>

```solidity
function redeemDelegations(
  bytes[] calldata permissionContexts,
  bytes32[] calldata modes,
  bytes[] calldata executionCallDatas
) external;
```

| Parameter            | Description                                                                  |
| -------------------- | ---------------------------------------------------------------------------- |
| `permissionContexts` | `[grant.context]`                                                            |
| `modes`              | Execution mode; default for a single call is `0x0000...0000` (32 zero bytes) |
| `executionCallDatas` | Encoded `Execution` struct                                                   |

#### Execution Encoding <a href="#execution-encoding" id="execution-encoding"></a>

```solidity
struct Execution {
  address target;
  uint256 value;
  bytes callData;
}
```

Encoding method:

```typescript
function encodeSingleExecution(execution: {
  target: `0x${string}`;
  value: bigint;
  callData: `0x${string}`;
}) {
  const target = execution.target.slice(2).toLowerCase().padStart(40, "0");
  const value = execution.value.toString(16).padStart(64, "0");
  const data = execution.callData.slice(2);
  return `0x${target}${value}${data}` as `0x${string}`;
}
```

### Constructing Execution by Permission Type <a href="#constructing-execution-by-permission-type" id="constructing-execution-by-permission-type"></a>

#### ERC-20 Transfer <a href="#erc-20-transfer" id="erc-20-transfer"></a>

```typescript
import { encodeFunctionData, parseUnits } from "viem";

const tokenAddress = grant.permission.data.tokenAddress;
const amount = parseUnits("1", 18);

const execution = {
  target: tokenAddress,
  value: 0n,
  callData: encodeFunctionData({
    abi: [
      {
        type: "function",
        name: "transfer",
        inputs: [
          { name: "to", type: "address" },
          { name: "amount", type: "uint256" },
        ],
        outputs: [{ type: "bool" }],
        stateMutability: "nonpayable",
      },
    ],
    functionName: "transfer",
    args: [payeeAddress, amount],
  }),
};
```

#### Native Token Transfer <a href="#native-token-transfer" id="native-token-transfer"></a>

```typescript
const execution = {
  target: payeeAddress,
  value: parseUnits("0.001", 18),
  callData: "0x",
};
```

### Complete Redeem Example <a href="#complete-redeem-example" id="complete-redeem-example"></a>

Construct calldata with viem and send the transaction from the Session Account:

```typescript
import { createWalletClient, http, encodeFunctionData, parseUnits } from "viem";
import { privateKeyToAccount } from "viem/accounts";

const SINGLE_DEFAULT_MODE =
  "0x0000000000000000000000000000000000000000000000000000000000000000";

const DELEGATION_MANAGER_ABI = [
  {
    type: "function",
    name: "redeemDelegations",
    inputs: [
      { name: "permissionContexts", type: "bytes[]" },
      { name: "modes", type: "bytes32[]" },
      { name: "executionCallDatas", type: "bytes[]" },
    ],
    outputs: [],
    stateMutability: "nonpayable",
  },
];

function encodeSingleExecution(execution: {
  target: `0x${string}`;
  value: bigint;
  callData: `0x${string}`;
}) {
  const target = execution.target.slice(2).toLowerCase().padStart(40, "0");
  const value = execution.value.toString(16).padStart(64, "0");
  const data = execution.callData.slice(2);
  return `0x${target}${value}${data}` as `0x${string}`;
}

async function redeemErc20Transfer(
  grant: PermissionResponse,
  payee: `0x${string}`,
  humanAmount: string,
  rpcUrl: string,
) {
  const sessionAccount = privateKeyToAccount(
    process.env.SESSION_PRIVATE_KEY as `0x${string}`,
  );

  if (sessionAccount.address.toLowerCase() !== grant.to.toLowerCase()) {
    throw new Error("Session address does not match grant.to");
  }

  const decimals = 18; // read decimals from the actual ERC-20 contract
  const amount = parseUnits(humanAmount, decimals);
  const tokenAddress = grant.permission.data.tokenAddress as `0x${string}`;

  const executionCallData = encodeSingleExecution({
    target: tokenAddress,
    value: 0n,
    callData: encodeFunctionData({
      abi: [
        {
          type: "function",
          name: "transfer",
          inputs: [{ type: "address" }, { type: "uint256" }],
          outputs: [{ type: "bool" }],
          stateMutability: "nonpayable",
        },
      ],
      functionName: "transfer",
      args: [payee, amount],
    }),
  });

  const data = encodeFunctionData({
    abi: DELEGATION_MANAGER_ABI,
    functionName: "redeemDelegations",
    args: [[grant.context], [SINGLE_DEFAULT_MODE], [executionCallData]],
  });

  const chainId = parseInt(grant.chainId, 16);

  const client = createWalletClient({
    account: sessionAccount,
    chain: {
      id: chainId,
      name: `Chain ${chainId}`,
      nativeCurrency: { name: "Native", symbol: "Native", decimals: 18 },
      rpcUrls: { default: { http: [rpcUrl] } },
    },
    transport: http(rpcUrl),
  });

  return client.sendTransaction({
    to: grant.delegationManager,
    value: 0n,
    data,
  });
}
```

### Pre-Execution Checklist <a href="#pre-execution-checklist" id="pre-execution-checklist"></a>

| Check Item              | Description                                      |
| ----------------------- | ------------------------------------------------ |
| `to` address match      | Signer = `grant.to`                              |
| Chain ID match          | Use `wallet_switchEthereumChain` if needed       |
| Sufficient allowance    | periodic/stream rules + on-chain enforcer        |
| Valid `context`         | Not expired, not revoked                         |
| `dependencies` deployed | Redeem only after factory deployment is complete |
