> ## Documentation Index
> Fetch the complete documentation index at: https://docs.baanx.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Implementation Guide

> Complete step-by-step guide to implementing wallet delegation

## Overview

Implementing delegation requires coordination between your **backend** (API calls) and **frontend** (wallet interaction). This guide walks through all four steps with complete code examples.

<Note>
  **Architecture Note**: Steps 1, 3, and 4 are backend API calls. Step 2 happens entirely in your frontend with Web3 libraries and wallet providers.
</Note>

## Prerequisites

Before implementing delegation, ensure you have:

<AccordionGroup>
  <Accordion title="User Account Requirements" icon="user-check">
    * User must have completed [registration](/guides/user/registration) including consent acceptance
    * User must have accepted terms of service and data processing consent
    * User must have completed identity verification (KYC)
    * See [Consent Management](/guides/consent/overview) for compliance tracking
  </Accordion>

  <Accordion title="API Authentication" icon="key">
    * Client public key (`x-client-key` header)
    * User access token (OAuth2 Bearer token)
    * Valid API credentials from your dashboard
  </Accordion>

  <Accordion title="Frontend Requirements" icon="browser">
    * Web3 library installed (ethers.js, web3.js, or @solana/web3.js)
    * Wallet provider support (MetaMask, WalletConnect, Phantom)
    * User has wallet installed and funded with desired currency
  </Accordion>

  <Accordion title="Smart Contract Information" icon="file-contract">
    * Token contract addresses for each network (USDC/USDT)
    * Platform spender addresses for approvals
    * Chain IDs for each supported network
    * **Obtain dynamically:** Call `GET /v1/delegation/chain/config` to retrieve all addresses and chain IDs before Step 1
  </Accordion>
</AccordionGroup>

## Step 1: Request Delegation Token

Call your backend to generate a single-use delegation token from the API.

### Backend Implementation

<CodeGroup>
  ```typescript TypeScript theme={null}
  interface DelegationTokenResponse {
    token: string;
    nonce: string;
  }

  async function requestDelegationToken(
    userAccessToken: string
  ): Promise<{ token: string; nonce: string }> {
    const response = await fetch('https://api.yourplatform.com/v1/delegation/token', {
      method: 'GET',
      headers: {
        'x-client-key': process.env.CLIENT_PUBLIC_KEY!,
        'Authorization': `Bearer ${userAccessToken}`,
        'Content-Type': 'application/json'
      }
    });

    if (!response.ok) {
      throw new Error(`Failed to get delegation token: ${response.statusText}`);
    }

    const data: DelegationTokenResponse = await response.json();
    return { token: data.token, nonce: data.nonce };
  }
  ```

  ```python Python theme={null}
  from typing import Dict
  import httpx
  import os

  async def request_delegation_token(user_access_token: str) -> str:
      async with httpx.AsyncClient() as client:
          response = await client.get(
              'https://api.yourplatform.com/v1/delegation/token',
              headers={
                  'x-client-key': os.getenv('CLIENT_PUBLIC_KEY'),
                  'Authorization': f'Bearer {user_access_token}',
                  'Content-Type': 'application/json'
              }
          )
          response.raise_for_status()
          data = response.json()
          return data['token']
  ```

  ```javascript JavaScript theme={null}
  async function requestDelegationToken(userAccessToken) {
    const response = await fetch('https://api.yourplatform.com/v1/delegation/token', {
      method: 'GET',
      headers: {
        'x-client-key': process.env.CLIENT_PUBLIC_KEY,
        'Authorization': `Bearer ${userAccessToken}`,
        'Content-Type': 'application/json'
      }
    });

    if (!response.ok) {
      throw new Error(`Failed to get delegation token: ${response.statusText}`);
    }

    const data = await response.json();
    return data.token;
  }
  ```

  ```bash cURL theme={null}
  curl -X GET "https://api.yourplatform.com/v1/delegation/token" \
    -H "x-client-key: YOUR_PUBLIC_KEY" \
    -H "Authorization: Bearer USER_ACCESS_TOKEN"
  ```
</CodeGroup>

**API Reference:** [`GET /v1/delegation/token`](/api-reference/delegation/token)

### Response

```json theme={null}
{
  "token": "100a99cf-f4d3-4fa1-9be9-2e9828b20ebc",
  "nonce": "5f8a9b2c4d3e1a7b9c6d8e2f"
}
```

### Token Characteristics

* **Single-use only**: Becomes invalid after use in Step 3
* **\~10 minute lifetime**: Complete the flow before expiration
* **Temporary storage**: Store in session/state, not database
* **Pass to frontend**: Required for Step 3 submission

<Warning>
  Do not reuse delegation tokens. Generate a new token for each delegation attempt.
</Warning>

## Step 2: Frontend Wallet Interaction

This step happens entirely in your frontend application. The API does not provide this functionality.

<Note>
  **Important**: This is client-side code that runs in the browser. You'll need to implement this using Web3 libraries and wallet provider integrations.
</Note>

### Architecture Overview

```mermaid theme={null}
sequenceDiagram
    participant User
    participant Frontend
    participant Wallet
    participant Blockchain

    User->>Frontend: Click "Delegate Wallet"
    Frontend->>Wallet: Request connection
    Wallet->>User: Prompt to connect
    User->>Wallet: Approve connection
    Wallet->>Frontend: Return address
    Frontend->>Wallet: Request approval transaction
    Wallet->>User: Show transaction details
    User->>Wallet: Sign transaction
    Wallet->>Blockchain: Submit transaction
    Blockchain->>Wallet: Confirmation
    Frontend->>Wallet: Request signature for proof
    Wallet->>User: Prompt to sign message
    User->>Wallet: Sign message
    Wallet->>Frontend: Return signature
    Frontend->>Frontend: Collect all data for Step 3
```

### Required Tasks

Your frontend must complete these tasks:

<Steps>
  <Step title="Connect User's Wallet">
    Use Web3 provider to connect to user's wallet application
  </Step>

  <Step title="Request Network Switch">
    Ensure user is on correct blockchain network (if needed)
  </Step>

  <Step title="Request Approval Transaction">
    Call token contract's approval function with spending limit
  </Step>

  <Step title="Wait for Confirmation">
    Monitor blockchain for transaction confirmation
  </Step>

  <Step title="Request Message Signature">
    Have user sign a message to prove wallet ownership
  </Step>

  <Step title="Collect Transaction Data">
    Gather all required fields for Step 3 submission
  </Step>
</Steps>

### Frontend Implementation (EVM Example)

<CodeGroup>
  ```typescript TypeScript (ethers.js v6) theme={null}
  import { BrowserProvider, Contract, parseUnits } from 'ethers';

  interface DelegationData {
    address: string;
    network: 'linea' | 'ethereum';
    currency: 'usdc' | 'usdt';
    amount: string;
    txHash: string;
    sigHash: string;
    sigMessage: string;
    token: string;
  }

  const ERC20_ABI = [
    'function approve(address spender, uint256 amount) returns (bool)'
  ];

  async function performWalletDelegation(
    delegationToken: string,
    network: 'linea' | 'ethereum',
    currency: 'usdc' | 'usdt',
    amount: string,
    tokenAddress: string,
    spenderAddress: string
  ): Promise<DelegationData> {

    if (!window.ethereum) {
      throw new Error('No Web3 wallet detected');
    }

    const provider = new BrowserProvider(window.ethereum);

    await provider.send('eth_requestAccounts', []);

    const signer = await provider.getSigner();
    const address = await signer.getAddress();

    const tokenContract = new Contract(tokenAddress, ERC20_ABI, signer);

    const amountWei = parseUnits(amount, 6);

    console.log(`Requesting approval for ${amount} ${currency.toUpperCase()}`);
    const tx = await tokenContract.approve(spenderAddress, amountWei);

    console.log('Waiting for transaction confirmation...');
    const receipt = await tx.wait();

    if (!receipt || receipt.status !== 1) {
      throw new Error('Transaction failed');
    }

    const txHash = receipt.hash;
    console.log('Transaction confirmed:', txHash);

    const chainId = (await provider.getNetwork()).chainId;
    const nonce = Math.random().toString(36).substring(7);
    const issuedAt = new Date().toISOString();
    const expirationTime = new Date(Date.now() + 30 * 60000).toISOString();

    const siweMessage =
  `yourplatform.com wants you to sign in with your Ethereum account:
  ${address}

  Prove wallet ownership for delegation

  URI: https://yourplatform.com
  Version: 1
  Chain ID: ${chainId}
  Nonce: ${nonce}
  Issued At: ${issuedAt}
  Expiration Time: ${expirationTime}`;

    console.log('Requesting signature for proof...');
    const sigHash = await signer.signMessage(siweMessage);

    return {
      address,
      network,
      currency,
      amount,
      txHash,
      sigHash,
      sigMessage: siweMessage,
      token: delegationToken
    };
  }
  ```

  ```typescript TypeScript (wagmi + viem) theme={null}
  import { useAccount, useWriteContract, useWaitForTransactionReceipt, useSignMessage } from 'wagmi';
  import { parseUnits } from 'viem';

  const ERC20_ABI = [
    {
      name: 'approve',
      type: 'function',
      stateMutability: 'nonpayable',
      inputs: [
        { name: 'spender', type: 'address' },
        { name: 'amount', type: 'uint256' }
      ],
      outputs: [{ type: 'bool' }]
    }
  ] as const;

  function useDelegation() {
    const { address } = useAccount();
    const { writeContractAsync } = useWriteContract();
    const { signMessageAsync } = useSignMessage();

    async function delegateWallet(
      tokenAddress: `0x${string}`,
      spenderAddress: `0x${string}`,
      amount: string,
      delegationToken: string,
      network: 'linea' | 'ethereum',
      currency: 'usdc' | 'usdt'
    ) {
      if (!address) throw new Error('Wallet not connected');

      const amountWei = parseUnits(amount, 6);

      const txHash = await writeContractAsync({
        address: tokenAddress,
        abi: ERC20_ABI,
        functionName: 'approve',
        args: [spenderAddress, amountWei]
      });

      const nonce = Math.random().toString(36).substring(7);
      const issuedAt = new Date().toISOString();
      const expirationTime = new Date(Date.now() + 30 * 60000).toISOString();

      const siweMessage =
  `yourplatform.com wants you to sign in with your Ethereum account:
  ${address}

  Prove wallet ownership for delegation

  URI: https://yourplatform.com
  Version: 1
  Chain ID: ${network === 'linea' ? 59144 : 1}
  Nonce: ${nonce}
  Issued At: ${issuedAt}
  Expiration Time: ${expirationTime}`;

      const sigHash = await signMessageAsync({ message: siweMessage });

      return {
        address,
        network,
        currency,
        amount,
        txHash,
        sigHash,
        sigMessage: siweMessage,
        token: delegationToken
      };
    }

    return { delegateWallet };
  }
  ```

  ```javascript JavaScript (web3.js) theme={null}
  async function performWalletDelegation(
    delegationToken,
    network,
    currency,
    amount,
    tokenAddress,
    spenderAddress
  ) {
    if (!window.ethereum) {
      throw new Error('No Web3 wallet detected');
    }

    const Web3 = require('web3');
    const web3 = new Web3(window.ethereum);

    await window.ethereum.request({ method: 'eth_requestAccounts' });

    const accounts = await web3.eth.getAccounts();
    const address = accounts[0];

    const tokenContract = new web3.eth.Contract(
      [{
        name: 'approve',
        type: 'function',
        inputs: [
          { name: 'spender', type: 'address' },
          { name: 'amount', type: 'uint256' }
        ]
      }],
      tokenAddress
    );

    const amountWei = web3.utils.toWei(amount, 'mwei');

    const tx = await tokenContract.methods
      .approve(spenderAddress, amountWei)
      .send({ from: address });

    const txHash = tx.transactionHash;

    const chainId = await web3.eth.getChainId();
    const nonce = Math.random().toString(36).substring(7);
    const issuedAt = new Date().toISOString();
    const expirationTime = new Date(Date.now() + 30 * 60000).toISOString();

    const siweMessage =
  `yourplatform.com wants you to sign in with your Ethereum account:
  ${address}

  Prove wallet ownership for delegation

  URI: https://yourplatform.com
  Version: 1
  Chain ID: ${chainId}
  Nonce: ${nonce}
  Issued At: ${issuedAt}
  Expiration Time: ${expirationTime}`;

    const sigHash = await web3.eth.personal.sign(siweMessage, address);

    return {
      address,
      network,
      currency,
      amount,
      txHash,
      sigHash,
      sigMessage: siweMessage,
      token: delegationToken
    };
  }
  ```
</CodeGroup>

### Frontend Implementation (Solana Example)

<CodeGroup>
  ```typescript TypeScript (Solana) theme={null}
  import { Connection, PublicKey, Transaction } from '@solana/web3.js';
  import {
    createApproveInstruction,
    getAssociatedTokenAddress,
    TOKEN_PROGRAM_ID
  } from '@solana/spl-token';
  import { useWallet } from '@solana/wallet-adapter-react';

  interface SolanaDelegationData {
    address: string;
    network: 'solana';
    currency: 'usdc' | 'usdt';
    amount: string;
    txHash: string;
    sigHash: string;
    sigMessage: string;
    token: string;
  }

  async function performSolanaWalletDelegation(
    wallet: any,
    delegationToken: string,
    currency: 'usdc' | 'usdt',
    amount: string,
    mintAddress: string,
    delegateAddress: string
  ): Promise<SolanaDelegationData> {

    if (!wallet.connected || !wallet.publicKey) {
      throw new Error('Wallet not connected');
    }

    const connection = new Connection('https://api.mainnet-beta.solana.com');
    const userPublicKey = wallet.publicKey;

    const tokenAccount = await getAssociatedTokenAddress(
      new PublicKey(mintAddress),
      userPublicKey
    );

    const amountBN = BigInt(parseFloat(amount) * 1_000_000);

    const approveInstruction = createApproveInstruction(
      tokenAccount,
      new PublicKey(delegateAddress),
      userPublicKey,
      amountBN,
      [],
      TOKEN_PROGRAM_ID
    );

    const transaction = new Transaction().add(approveInstruction);
    transaction.feePayer = userPublicKey;

    const { blockhash } = await connection.getLatestBlockhash();
    transaction.recentBlockhash = blockhash;

    const signedTx = await wallet.signTransaction(transaction);
    const txHash = await connection.sendRawTransaction(signedTx.serialize());

    await connection.confirmTransaction(txHash);

    const message = 'Prove wallet ownership for delegation';
    const messageBytes = new TextEncoder().encode(message);

    const signature = await wallet.signMessage(messageBytes);
    const sigHash = Buffer.from(signature).toString('base64');

    return {
      address: userPublicKey.toBase58(),
      network: 'solana',
      currency,
      amount,
      txHash,
      sigHash,
      sigMessage: message,
      token: delegationToken
    };
  }
  ```
</CodeGroup>

### UI/UX Recommendations

<Tabs>
  <Tab title="Transaction Preview">
    Show users exactly what they're approving before signing:

    ```jsx theme={null}
    <div className="delegation-preview">
      <h3>Approve Wallet Delegation</h3>
      <div className="details">
        <div className="detail-row">
          <span>Network:</span>
          <span>{network.toUpperCase()}</span>
        </div>
        <div className="detail-row">
          <span>Currency:</span>
          <span>{currency.toUpperCase()}</span>
        </div>
        <div className="detail-row">
          <span>Spending Limit:</span>
          <span>{amount} {currency.toUpperCase()}</span>
        </div>
        <div className="detail-row">
          <span>Platform:</span>
          <span>YourPlatform</span>
        </div>
      </div>
      <p className="info">
        This allows YourPlatform to spend up to {amount} {currency.toUpperCase()}
        from your wallet for card purchases.
      </p>
      <div className="actions">
        <button onClick={onCancel}>Cancel</button>
        <button onClick={onApprove}>Approve in Wallet</button>
      </div>
    </div>
    ```
  </Tab>

  <Tab title="Progress Indicator">
    Keep users informed during the multi-step process:

    ```jsx theme={null}
    <div className="progress-steps">
      <div className="step completed">
        <span className="icon">✅</span>
        <span>Get Token</span>
      </div>
      <div className="step active">
        <span className="icon">🔄</span>
        <span>Connect Wallet</span>
        <div className="sub-steps">
          <div className="sub-step completed">✅ Connect wallet</div>
          <div className="sub-step active">⏳ Approve transaction</div>
          <div className="sub-step">⏸️ Sign message</div>
        </div>
      </div>
      <div className="step pending">
        <span className="icon">⏸️</span>
        <span>Finalize</span>
      </div>
    </div>
    ```
  </Tab>

  <Tab title="Error Handling">
    Handle common user scenarios gracefully:

    ```typescript theme={null}
    try {
      const data = await performWalletDelegation(...);
      // Proceed to Step 3
    } catch (error: any) {
      if (error.code === 4001) {
        showError('Transaction rejected. Click "Retry" when ready to approve.');
      } else if (error.message.includes('insufficient funds')) {
        showError('Insufficient balance for gas fees. Please add funds to your wallet.');
      } else if (error.message.includes('wrong network')) {
        showError('Please switch to the correct network in your wallet.');
      } else {
        showError(`Transaction failed: ${error.message}`);
      }
    }
    ```
  </Tab>
</Tabs>

## Step 3: Submit Delegation Proof

Call your backend to submit the delegation proof and finalize wallet registration.

<Note>
  Use the blockchain-specific endpoint: [`/v1/delegation/evm/post-approval`](/api-reference/delegation/evm-post-approval) for EVM chains (Linea/Ethereum) or [`/v1/delegation/solana/post-approval`](/api-reference/delegation/solana-post-approval) for Solana.
</Note>

### Backend Implementation (EVM)

<CodeGroup>
  ```typescript TypeScript theme={null}
  interface EVMDelegationProof {
    address: string;
    network: 'linea' | 'ethereum';
    currency: 'usdc' | 'usdt';
    amount: string;
    txHash: string;
    sigHash: string;
    sigMessage: string;
    token: string;
  }

  async function submitEVMDelegation(
    userAccessToken: string,
    proof: EVMDelegationProof
  ): Promise<boolean> {
    const response = await fetch(
      'https://api.yourplatform.com/v1/delegation/evm/post-approval',
      {
        method: 'POST',
        headers: {
          'x-client-key': process.env.CLIENT_PUBLIC_KEY!,
          'Authorization': `Bearer ${userAccessToken}`,
          'Content-Type': 'application/json'
        },
        body: JSON.stringify(proof)
      }
    );

    if (!response.ok) {
      const error = await response.json();
      throw new Error(`Delegation failed: ${error.message || response.statusText}`);
    }

    const data = await response.json();
    return data.success;
  }
  ```

  ```python Python theme={null}
  from typing import Dict, Any
  import httpx
  import os

  async def submit_evm_delegation(
      user_access_token: str,
      proof: Dict[str, Any]
  ) -> bool:
      async with httpx.AsyncClient() as client:
          response = await client.post(
              'https://api.yourplatform.com/v1/delegation/evm/post-approval',
              headers={
                  'x-client-key': os.getenv('CLIENT_PUBLIC_KEY'),
                  'Authorization': f'Bearer {user_access_token}',
                  'Content-Type': 'application/json'
              },
              json=proof
          )
          response.raise_for_status()
          data = response.json()
          return data.get('success', False)
  ```

  ```bash cURL theme={null}
  curl -X POST "https://api.yourplatform.com/v1/delegation/evm/post-approval" \
    -H "x-client-key: YOUR_PUBLIC_KEY" \
    -H "Authorization: Bearer USER_ACCESS_TOKEN" \
    -H "Content-Type: application/json" \
    -d '{
      "address": "0x3a11a86cf218c448be519728cd3ac5c741fb3424",
      "network": "linea",
      "currency": "usdc",
      "amount": "5000",
      "txHash": "0xb92de09d893e8162b0861c0f7321f68df02212efbc58f208839ae3f176d89638",
      "sigHash": "0x2039b9765a4df76e8bae80f3bbc640e8ae6acc81f7a5cc96fe91ccc1844b6f7d...",
      "sigMessage": "yourplatform.com wants you to sign in...",
      "token": "100a99cf-f4d3-4fa1-9be9-2e9828b20ebc"
    }'
  ```
</CodeGroup>

### Backend Implementation (Solana)

<CodeGroup>
  ```typescript TypeScript theme={null}
  interface SolanaDelegationProof {
    address: string;
    network: 'solana';
    currency: 'usdc' | 'usdt';
    amount: string;
    txHash: string;
    sigHash: string;
    sigMessage: string;
    token: string;
  }

  async function submitSolanaDelegation(
    userAccessToken: string,
    proof: SolanaDelegationProof
  ): Promise<boolean> {
    const response = await fetch(
      'https://api.yourplatform.com/v1/delegation/solana/post-approval',
      {
        method: 'POST',
        headers: {
          'x-client-key': process.env.CLIENT_PUBLIC_KEY!,
          'Authorization': `Bearer ${userAccessToken}`,
          'Content-Type': 'application/json'
        },
        body: JSON.stringify(proof)
      }
    );

    if (!response.ok) {
      const error = await response.json();
      throw new Error(`Delegation failed: ${error.message || response.statusText}`);
    }

    const data = await response.json();
    return data.success;
  }
  ```

  ```python Python theme={null}
  async def submit_solana_delegation(
      user_access_token: str,
      proof: Dict[str, Any]
  ) -> bool:
      async with httpx.AsyncClient() as client:
          response = await client.post(
              'https://api.yourplatform.com/v1/delegation/solana/post-approval',
              headers={
                  'x-client-key': os.getenv('CLIENT_PUBLIC_KEY'),
                  'Authorization': f'Bearer {user_access_token}',
                  'Content-Type': 'application/json'
              },
              json=proof
          )
          response.raise_for_status()
          data = response.json()
          return data.get('success', False)
  ```

  ```bash cURL theme={null}
  curl -X POST "https://api.yourplatform.com/v1/delegation/solana/post-approval" \
    -H "x-client-key: YOUR_PUBLIC_KEY" \
    -H "Authorization: Bearer USER_ACCESS_TOKEN" \
    -H "Content-Type: application/json" \
    -d '{
      "address": "DYw8jCTfwHNRJhhmFcbXvVDTqWMEVFBX6ZKUmG5CNSKK",
      "network": "solana",
      "currency": "usdc",
      "amount": "5000",
      "txHash": "5VERv8NMvzbJMEkV8xnrLkEaWRtSz9CosKDYjCJjBRnbJLgp...",
      "sigHash": "2Uhj5WqpLvZmJqKGx3WKvSC5K1m4YCp1eK3jcGY7GgRq...",
      "sigMessage": "Prove wallet ownership for delegation",
      "token": "100a99cf-f4d3-4fa1-9be9-2e9828b20ebc"
    }'
  ```
</CodeGroup>

**API Reference:** [`POST /v1/delegation/evm/post-approval`](/api-reference/delegation/evm-post-approval)

### Response

```json theme={null}
{
  "success": true
}
```

### What Happens

1. API validates address format (EVM vs Solana)
2. API validates transaction hash format
3. API verifies signature matches wallet address
4. API validates blockchain transaction exists and is confirmed
5. External wallet is registered and linked to user account
6. User can now make card purchases using delegated wallet funds

<Warning>
  If validation fails, you'll receive a 400 error with details about what went wrong. Common issues include invalid signature, unconfirmed transaction, or expired token.
</Warning>

## Step 4: Verify Registration

Confirm the wallet was successfully registered and view its details.

### Backend Implementation

<CodeGroup>
  ```typescript TypeScript theme={null}
  interface ExternalWallet {
    address: string;
    currency: string;
    balance: string;
    allowance: string;
    network: string;
  }

  async function verifyWalletRegistration(
    userAccessToken: string
  ): Promise<ExternalWallet[]> {
    const response = await fetch(
      'https://api.yourplatform.com/v1/wallet/external',
      {
        method: 'GET',
        headers: {
          'x-client-key': process.env.CLIENT_PUBLIC_KEY!,
          'Authorization': `Bearer ${userAccessToken}`
        }
      }
    );

    if (!response.ok) {
      throw new Error(`Failed to fetch wallets: ${response.statusText}`);
    }

    return await response.json();
  }
  ```

  ```python Python theme={null}
  from typing import List, Dict, Any

  async def verify_wallet_registration(
      user_access_token: str
  ) -> List[Dict[str, Any]]:
      async with httpx.AsyncClient() as client:
          response = await client.get(
              'https://api.yourplatform.com/v1/wallet/external',
              headers={
                  'x-client-key': os.getenv('CLIENT_PUBLIC_KEY'),
                  'Authorization': f'Bearer {user_access_token}'
              }
          )
          response.raise_for_status()
          return response.json()
  ```

  ```bash cURL theme={null}
  curl -X GET "https://api.yourplatform.com/v1/wallet/external" \
    -H "x-client-key: YOUR_PUBLIC_KEY" \
    -H "Authorization: Bearer USER_ACCESS_TOKEN"
  ```
</CodeGroup>

**API Reference:** [`GET /v1/wallet/external`](/api-reference/wallet/external)

### Response

```json theme={null}
[
  {
    "address": "0x3a11a86cf218c448be519728cd3ac5c741fb3424",
    "currency": "usdc",
    "balance": "5000.00",
    "allowance": "5000",
    "network": "linea"
  }
]
```

## Complete Flow Example

Here's a complete end-to-end implementation example:

<CodeGroup>
  ```typescript TypeScript (Complete Flow) theme={null}
  async function completeDelegationFlow(
    userAccessToken: string,
    network: 'linea' | 'ethereum' | 'solana',
    currency: 'usdc' | 'usdt',
    amount: string
  ): Promise<void> {
    try {
      console.log('Step 1: Requesting delegation token...');
      const { token: delegationToken, nonce } = await requestDelegationToken(userAccessToken);
      console.log('Token received:', delegationToken);
      console.log('Nonce received:', nonce);

      console.log('Step 2: Initiating wallet connection...');
      let delegationData;

      if (network === 'solana') {
        delegationData = await performSolanaWalletDelegation(
          wallet,
          delegationToken,
          currency,
          amount,
          SOLANA_MINT_ADDRESSES[currency],
          SOLANA_DELEGATE_ADDRESS
        );
      } else {
        delegationData = await performWalletDelegation(
          delegationToken,
          network,
          currency,
          amount,
          EVM_TOKEN_ADDRESSES[network][currency],
          EVM_SPENDER_ADDRESS
        );
      }

      console.log('Wallet interaction complete');

      console.log('Step 3: Submitting delegation proof...');
      if (network === 'solana') {
        await submitSolanaDelegation(userAccessToken, delegationData);
      } else {
        await submitEVMDelegation(userAccessToken, delegationData);
      }

      console.log('Delegation submitted successfully');

      console.log('Step 4: Verifying registration...');
      const wallets = await verifyWalletRegistration(userAccessToken);

      const newWallet = wallets.find(
        w => w.address.toLowerCase() === delegationData.address.toLowerCase()
      );

      if (newWallet) {
        console.log('✅ Delegation successful!');
        console.log('Wallet details:', newWallet);
        return newWallet;
      } else {
        throw new Error('Wallet not found after registration');
      }

    } catch (error) {
      console.error('Delegation failed:', error);
      throw error;
    }
  }
  ```
</CodeGroup>

## Implementation Checklist

Use this checklist to ensure you've implemented all required components:

### Backend Requirements

* [ ] Implement delegation token request endpoint integration
* [ ] Implement blockchain-specific post-approval submission (EVM/Solana)
* [ ] Store delegation tokens securely (short-lived, single-use)
* [ ] Handle API errors gracefully with user feedback
* [ ] Implement wallet verification after delegation
* [ ] Add retry logic for failed API requests
* [ ] Log delegation attempts for debugging

### Frontend Requirements

* [ ] Implement wallet connection UI (MetaMask, WalletConnect, Phantom)
* [ ] Support multiple blockchain networks (Linea, Ethereum, Solana)
* [ ] Display approval transaction details before signing
* [ ] Show transaction confirmation and status
* [ ] Implement signature collection (SIWE for EVM chains)
* [ ] Handle wallet errors and rejections
* [ ] Display current allowance and balance information
* [ ] Implement loading states and progress indicators

### Smart Contract Integration

* [ ] Obtain correct token contract addresses for each network
* [ ] Obtain platform spender addresses for approvals
* [ ] Implement ERC20 approval flow for EVM chains
* [ ] Implement token account delegation for Solana
* [ ] Handle transaction confirmation and receipts
* [ ] Monitor blockchain for transaction success/failure
* [ ] Validate contract addresses before approval

## Troubleshooting

<AccordionGroup>
  <Accordion title="Token Expired Error">
    **Symptom**: API returns error about expired token in Step 3

    **Solution**: Generate a new token and restart from Step 1. Tokens are valid for \~10 minutes.
  </Accordion>

  <Accordion title="Transaction Not Found">
    **Symptom**: API can't find the blockchain transaction

    **Solutions**:

    * Wait longer for transaction confirmation (especially on Ethereum mainnet)
    * Verify transaction hash is correct
    * Check transaction status on block explorer
    * Ensure you're on the correct network
  </Accordion>

  <Accordion title="Invalid Signature">
    **Symptom**: API rejects signature in Step 3

    **Solutions**:

    * Ensure sigMessage format matches SIWE specification (for EVM)
    * Verify signature was created from the same wallet address
    * Check that message wasn't modified after signing
  </Accordion>

  <Accordion title="User Rejected Transaction">
    **Symptom**: Wallet throws error code 4001

    **Solution**: Allow user to retry without regenerating token. Keep the delegation token and retry Steps 2-3.
  </Accordion>

  <Accordion title="Wrong Network">
    **Symptom**: Wallet is on different network than requested

    **Solution**: Implement network switching in your frontend:

    ```typescript theme={null}
    await window.ethereum.request({
      method: 'wallet_switchEthereumChain',
      params: [{ chainId: '0xe708' }] // Linea: 0xe708 (59144)
    });
    ```
  </Accordion>
</AccordionGroup>

## Next Steps

<CardGroup cols={2}>
  <Card title="EVM Implementation" icon="ethereum" href="/guides/delegation/evm-chains">
    Dive deeper into EVM-specific implementation details
  </Card>

  <Card title="Solana Implementation" icon="circle-s" href="/guides/delegation/solana">
    Learn Solana-specific delegation patterns
  </Card>

  <Card title="Priority Management" icon="ranking-star" href="/guides/delegation/priority">
    Configure which wallets are charged first
  </Card>

  <Card title="Redelegation" icon="rotate" href="/guides/delegation/redelegation">
    Update existing delegations when needed
  </Card>
</CardGroup>
