Skip to main content
Portal’s Flutter SDK provides token delegation capabilities through the portal.delegations API. This enables approving token spending, revoking approvals, checking delegation status, and transferring tokens as a delegate on both EVM and Solana chains.

Overview

The delegations functionality allows you to:
  • Approve other addresses to spend tokens on behalf of your wallet
  • Revoke existing delegations to remove spending permissions
  • Check status of active delegations and balances
  • Transfer tokens as a delegate from another address

Prerequisites

Before using delegation operations, ensure you have:
All examples below assume Portal has already been initialized with await portal.initialize(apiKey: 'YOUR_API_KEY'). See Getting Started for details.

Approving Delegations

Use approve to grant another address permission to spend tokens on your behalf. This method works for both EVM and Solana chains.

EVM Approval

import 'package:portal_flutter/portal_flutter.dart';

final portal = Portal();

try {
  // Approve a delegate to spend USDC on your behalf
  final response = await portal.delegations.approve(
    chain: 'eip155:11155111', // Sepolia testnet
    token: 'USDC',
    delegateAddress: '0xa944e86eb36f039becd1843132347eb5b8501562',
    amount: '0.01',
  );

  // Sign and send the transaction
  final tx = response.transactions!.first!;
  final txResponse = await portal.request(
    chainId: 'eip155:11155111',
    method: 'eth_sendTransaction',
    params: [
      {'from': tx.from, 'to': tx.to, 'data': tx.data, 'value': tx.value}
    ],
  );
  print('Tx hash: ${txResponse.result}');
} catch (e) {
  print('Error approving EVM delegation: $e');
}
Each delegation response includes a metadata field with additional details such as chainId, tokenSymbol, tokenAddress, and delegateAddress. Access it via response.metadata?.chainId for approve/revoke, or response.metadata.chainId for transferFrom.

Solana Approval

import 'package:portal_flutter/portal_flutter.dart';

final portal = Portal();

try {
  // Approve a delegate to spend USDC on your behalf
  final response = await portal.delegations.approve(
    chain: 'solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1', // Solana Devnet
    token: 'USDC',
    delegateAddress: '7smgSuU5mjP7QY5yWGdaTfgKn8hUWwvQgfvgcZB3HmJi',
    amount: '0.01',
  );

  // Sign and send the transaction
  final encodedTx = response.encodedTransactions!.first!;
  final txResponse = await portal.request(
    chainId: 'solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1',
    method: 'sol_signAndSendTransaction',
    params: [encodedTx],
  );
  print('Tx hash: ${txResponse.result}');
} catch (e) {
  print('Error approving Solana delegation: $e');
}

Checking Delegation Status

Use getStatus to check current delegations and token balances for a specific delegate address.

EVM Status Check

import 'package:portal_flutter/portal_flutter.dart';

final portal = Portal();

try {
  final response = await portal.delegations.getStatus(
    chain: 'eip155:11155111',
    token: 'USDC',
    delegateAddress: '0xa944e86eb36f039becd1843132347eb5b8501562',
  );

  print('Chain ID: ${response.chainId}');
  print('Token: ${response.token}');
  print('Token Address: ${response.tokenAddress}');
  if (response.balance != null) print('Balance: ${response.balance}');
  if (response.balanceRaw != null) print('Balance Raw: ${response.balanceRaw}');
  print('Delegations: ${response.delegations.length}');

  for (final delegation in response.delegations) {
    print('  - Address: ${delegation!.address}, Amount: ${delegation.delegateAmount} (Raw: ${delegation.delegateAmountRaw})');
  }
} catch (e) {
  print('Error getting EVM delegation status: $e');
}

Solana Status Check

import 'package:portal_flutter/portal_flutter.dart';

final portal = Portal();

try {
  final response = await portal.delegations.getStatus(
    chain: 'solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1',
    token: 'USDC',
    delegateAddress: '7smgSuU5mjP7QY5yWGdaTfgKn8hUWwvQgfvgcZB3HmJi',
  );

  print('Chain ID: ${response.chainId}');
  print('Token: ${response.token}');
  if (response.tokenAccount != null) print('Token Account: ${response.tokenAccount}');
  print('Delegations: ${response.delegations.length}');

  for (final delegation in response.delegations) {
    print('  - Address: ${delegation!.address}, Amount: ${delegation.delegateAmount} (Raw: ${delegation.delegateAmountRaw})');
  }
} catch (e) {
  print('Error getting Solana delegation status: $e');
}

Revoking Delegations

Use revoke to remove spending permissions from a delegate address.

EVM Revoke

import 'package:portal_flutter/portal_flutter.dart';

final portal = Portal();

try {
  final response = await portal.delegations.revoke(
    chain: 'eip155:11155111',
    token: 'USDC',
    delegateAddress: '0xa944e86eb36f039becd1843132347eb5b8501562',
  );

  // Sign and send the transaction
  final tx = response.transactions!.first!;
  final txResponse = await portal.request(
    chainId: 'eip155:11155111',
    method: 'eth_sendTransaction',
    params: [
      {'from': tx.from, 'to': tx.to, 'data': tx.data, 'value': tx.value}
    ],
  );
  print('Tx hash: ${txResponse.result}');
} catch (e) {
  print('Error revoking EVM delegation: $e');
}

Solana Revoke

import 'package:portal_flutter/portal_flutter.dart';

final portal = Portal();

try {
  final response = await portal.delegations.revoke(
    chain: 'solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1',
    token: 'USDC',
    delegateAddress: '7smgSuU5mjP7QY5yWGdaTfgKn8hUWwvQgfvgcZB3HmJi',
  );

  // Sign and send the transaction
  final encodedTx = response.encodedTransactions!.first!;
  final txResponse = await portal.request(
    chainId: 'solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1',
    method: 'sol_signAndSendTransaction',
    params: [encodedTx],
  );
  print('Tx hash: ${txResponse.result}');
} catch (e) {
  print('Error revoking Solana delegation: $e');
}
Always revoke unused delegations after completing operations to minimize security risks.

Transferring as a Delegate

Use transferFrom to transfer tokens from another address that has delegated spending permission to you.

EVM Transfer From

import 'package:portal_flutter/portal_flutter.dart';

final portal = Portal();

try {
  final response = await portal.delegations.transferFrom(
    chain: 'eip155:11155111',
    token: 'USDC',
    fromAddress: '0x099699ed181517d4ce0ba4487bea671d31bb1db5', // Token owner
    toAddress: '0xdFd8302f44727A6348F702fF7B594f127dE3A902',   // Recipient
    amount: '0.01',
  );

  // Sign and send the transaction
  final tx = response.transactions!.first!;
  final txResponse = await portal.request(
    chainId: 'eip155:11155111',
    method: 'eth_sendTransaction',
    params: [
      {'from': tx.from, 'to': tx.to, 'data': tx.data, 'value': tx.value}
    ],
  );
  print('Tx hash: ${txResponse.result}');
} catch (e) {
  print('Error transferring EVM delegation: $e');
}

Solana Transfer From

import 'package:portal_flutter/portal_flutter.dart';

final portal = Portal();

try {
  final response = await portal.delegations.transferFrom(
    chain: 'solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1',
    token: 'USDC',
    fromAddress: 'ARttPLesu9RiX6H111Pfdc9Y2DhGy1B8P8jyyrD8Cj5b', // Token owner
    toAddress: 'GPsPXxoQA51aTJJkNHtFDFYui5hN5UxcFPnheJEHa5Du',   // Recipient
    amount: '0.01',
  );

  // Sign and send the transaction
  final encodedTx = response.encodedTransactions!.first!;
  final txResponse = await portal.request(
    chainId: 'solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1',
    method: 'sol_signAndSendTransaction',
    params: [encodedTx],
  );
  print('Tx hash: ${txResponse.result}');
} catch (e) {
  print('Error transferring Solana delegation: $e');
}
Delegation Roles: fromAddress is the token owner who approved the delegation. Your wallet (the delegate) signs the transaction to transfer tokens from the owner to the toAddress recipient.

Supported Networks

Delegations work on all Portal-supported EVM and Solana chains:
  • EVM: Ethereum, Polygon, Base, Arbitrum, Optimism, and all other EVM-compatible chains
  • Solana: Solana Mainnet and Devnet
For a complete list, see Blockchain Support.

Next Steps