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

# Manage Token Delegations

> Learn how to approve, revoke, and manage token delegations using Portal's Android SDK.

Portal's Android 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:

* A properly initialized Portal client
* An active wallet with tokens on the target network (see [Create a wallet](./create-a-wallet))
* Understanding of [token delegations concepts](/resources/delegations)

<Warning>
  Delegations apply to ERC-20 tokens (EVM) and SPL Tokens (Solana) only. Native assets like ETH, MON, and SOL cannot be delegated — they have no on-chain `approve` / `transferFrom` (or SPL delegate) semantics. Calls using a native asset identifier will be rejected. See [Delegations](/resources/delegations#what-are-token-delegations) for the protocol-level reason and workarounds.
</Warning>

## 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

```kotlin theme={null}
lifecycleScope.launch {
    try {
        val request = ApproveDelegationRequest(
            chain = "eip155:11155111", // Sepolia testnet
            token = "USDC",
            delegateAddress = "0x1a3eda7eb7d13e60e638711c580490c19e164fee",
            amount = "0.01"
        )

        val result = portal.delegations.approve(request)

        result.onSuccess { response ->
            // Sign and send EVM transactions sequentially
            response.transactions?.let { transactions ->
                for ((index, tx) in transactions.withIndex()) {
                    val txDict = mutableMapOf<String, String>(
                        "from" to tx.from,
                        "to" to tx.to
                    )
                    tx.data?.let { txDict["data"] = it }
                    tx.value?.let { txDict["value"] = it }

                    val txResponse = portal.request(
                        chainId = "eip155:11155111",
                        method = PortalRequestMethod.eth_sendTransaction,
                        params = listOf(txDict)
                    )
                    println("Tx ${index + 1} hash: ${txResponse.result as? String}")
                }
            }
        }.onFailure { error ->
            println("Approve (EVM) failed: ${error.message}")
        }
    } catch (e: Exception) {
        println("Error approving EVM delegation: ${e.message}")
    }
}
```

### Solana Approval

```kotlin theme={null}
lifecycleScope.launch {
    try {
        val request = ApproveDelegationRequest(
            chain = "solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1", // Solana Devnet
            token = "USDC",
            delegateAddress = "8uzXpjP9zXRHqo6KGZaE6XrxnjarBsKTufVya7jHtyt5",
            amount = "0.01"
        )

        val result = portal.delegations.approve(request)

        result.onSuccess { response ->
            // Sign and send Solana transactions sequentially
            response.encodedTransactions?.let { encodedTxs ->
                for ((index, encodedTx) in encodedTxs.withIndex()) {
                    val txResponse = portal.request(
                        chainId = "solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1",
                        method = PortalRequestMethod.sol_signAndSendTransaction,
                        params = listOf(encodedTx)
                    )
                    println("Tx ${index + 1} hash: ${txResponse.result as? String}")
                }
            }
        }.onFailure { error ->
            println("Approve (SOL) failed: ${error.message}")
        }
    } catch (e: Exception) {
        println("Error approving Solana delegation: ${e.message}")
    }
}
```

***

## Checking Delegation Status

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

### EVM Status Check

```kotlin theme={null}
lifecycleScope.launch {
    try {
        val request = GetDelegationStatusRequest(
            chain = "eip155:11155111",
            token = "USDC",
            delegateAddress = "0x1a3eda7eb7d13e60e638711c580490c19e164fee"
        )

        val result = portal.delegations.getStatus(request)

        result.onSuccess { response ->
            println("Chain ID: ${response.chainId}")
            println("Token: ${response.token}")
            println("Token Address: ${response.tokenAddress}")
            response.balance?.let { println("Balance: $it") }
            println("Delegations: ${response.delegations.size}")

            response.delegations.forEach { delegation ->
                println("  - Address: ${delegation.address}, Amount: ${delegation.delegateAmount}")
            }
        }.onFailure { error ->
            println("Get Status (EVM) failed: ${error.message}")
        }
    } catch (e: Exception) {
        println("Error getting EVM delegation status: ${e.message}")
    }
}
```

### Solana Status Check

```kotlin theme={null}
lifecycleScope.launch {
    try {
        val request = GetDelegationStatusRequest(
            chain = "solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1",
            token = "USDC",
            delegateAddress = "8uzXpjP9zXRHqo6KGZaE6XrxnjarBsKTufVya7jHtyt5"
        )

        val result = portal.delegations.getStatus(request)

        result.onSuccess { response ->
            println("Chain ID: ${response.chainId}")
            println("Token: ${response.token}")
            println("Delegations: ${response.delegations.size}")

            response.delegations.forEach { delegation ->
                println("  - Address: ${delegation.address}, Amount: ${delegation.delegateAmount}")
            }
        }.onFailure { error ->
            println("Get Status (SOL) failed: ${error.message}")
        }
    } catch (e: Exception) {
        println("Error getting Solana delegation status: ${e.message}")
    }
}
```

***

## Revoking Delegations

Use `revoke` to remove spending permissions from a delegate address.

### EVM Revoke

```kotlin theme={null}
lifecycleScope.launch {
    try {
        val request = RevokeDelegationRequest(
            chain = "eip155:11155111",
            token = "USDC",
            delegateAddress = "0x1a3eda7eb7d13e60e638711c580490c19e164fee"
        )

        val result = portal.delegations.revoke(request)

        result.onSuccess { response ->
            // Sign and send EVM transactions sequentially
            response.transactions?.let { transactions ->
                for ((index, tx) in transactions.withIndex()) {
                    val txDict = mutableMapOf<String, String>(
                        "from" to tx.from,
                        "to" to tx.to
                    )
                    tx.data?.let { txDict["data"] = it }
                    tx.value?.let { txDict["value"] = it }

                    val txResponse = portal.request(
                        chainId = "eip155:11155111",
                        method = PortalRequestMethod.eth_sendTransaction,
                        params = listOf(txDict)
                    )
                    println("Tx ${index + 1} hash: ${txResponse.result as? String}")
                }
            }
        }.onFailure { error ->
            println("Revoke (EVM) failed: ${error.message}")
        }
    } catch (e: Exception) {
        println("Error revoking EVM delegation: ${e.message}")
    }
}
```

### Solana Revoke

```kotlin theme={null}
lifecycleScope.launch {
    try {
        val request = RevokeDelegationRequest(
            chain = "solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1",
            token = "USDC",
            delegateAddress = "8uzXpjP9zXRHqo6KGZaE6XrxnjarBsKTufVya7jHtyt5"
        )

        val result = portal.delegations.revoke(request)

        result.onSuccess { response ->
            // Sign and send Solana transactions sequentially
            response.encodedTransactions?.let { encodedTxs ->
                for ((index, encodedTx) in encodedTxs.withIndex()) {
                    val txResponse = portal.request(
                        chainId = "solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1",
                        method = PortalRequestMethod.sol_signAndSendTransaction,
                        params = listOf(encodedTx)
                    )
                    println("Tx ${index + 1} hash: ${txResponse.result as? String}")
                }
            }
        }.onFailure { error ->
            println("Revoke (SOL) failed: ${error.message}")
        }
    } catch (e: Exception) {
        println("Error revoking Solana delegation: ${e.message}")
    }
}
```

<Warning>
  Always revoke unused delegations after completing operations to minimize security risks.
</Warning>

***

## Transferring as a Delegate

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

### EVM Transfer From

```kotlin theme={null}
lifecycleScope.launch {
    try {
        val request = TransferFromRequest(
            chain = "eip155:11155111",
            token = "USDC",
            fromAddress = "0x06ccd61bc37775140b0b039b392aa823c7cbeedd", // Token owner
            toAddress = "0x5bd098a9368d142126e8b53a058b5c563714bc76",   // Recipient
            amount = "0.01"
        )

        val result = portal.delegations.transferFrom(request)

        result.onSuccess { response ->
            // Sign and send EVM transactions sequentially
            response.transactions?.let { transactions ->
                for ((index, tx) in transactions.withIndex()) {
                    val txDict = mutableMapOf<String, String>(
                        "from" to tx.from,
                        "to" to tx.to
                    )
                    tx.data?.let { txDict["data"] = it }
                    tx.value?.let { txDict["value"] = it }

                    val txResponse = portal.request(
                        chainId = "eip155:11155111",
                        method = PortalRequestMethod.eth_sendTransaction,
                        params = listOf(txDict)
                    )
                    println("Tx ${index + 1} hash: ${txResponse.result as? String}")
                }
            }
        }.onFailure { error ->
            println("TransferFrom (EVM) failed: ${error.message}")
        }
    } catch (e: Exception) {
        println("Error transferring EVM delegation: ${e.message}")
    }
}
```

### Solana Transfer From

```kotlin theme={null}
lifecycleScope.launch {
    try {
        val request = TransferFromRequest(
            chain = "solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1",
            token = "USDC",
            fromAddress = "5qf7h6aJ47nfYkmtDW52LtCgBKEppf8CU1CmNXUJvPDD", // Token owner
            toAddress = "CaeuusKjRDw2NctShW2gMhEcMxFYfHLUUGHh3Hui3Mae",     // Recipient
            amount = "0.01"
        )

        val result = portal.delegations.transferFrom(request)

        result.onSuccess { response ->
            // Sign and send Solana transactions sequentially
            response.encodedTransactions?.let { encodedTxs ->
                for ((index, encodedTx) in encodedTxs.withIndex()) {
                    val txResponse = portal.request(
                        chainId = "solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1",
                        method = PortalRequestMethod.sol_signAndSendTransaction,
                        params = listOf(encodedTx)
                    )
                    println("Tx ${index + 1} hash: ${txResponse.result as? String}")
                }
            }
        }.onFailure { error ->
            println("TransferFrom (SOL) failed: ${error.message}")
        }
    } catch (e: Exception) {
        println("Error transferring Solana delegation: ${e.message}")
    }
}
```

<Note>
  **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.
</Note>

***

## Supported Networks

Delegations work on all Portal-supported EVM and Solana chains:

* **EVM**: Ethereum, Polygon, Base, Arbitrum, Optimism, Monad, and all other EVM-compatible chains
* **Solana**: Solana Mainnet and Devnet

For a complete list, see [Blockchain Support](/resources/blockchain-support).

***

## Next Steps

* Learn about [signing transactions](./sign-a-transaction)
* Explore [Portal API methods](./portal-api-methods)
* Review [delegation concepts](/resources/delegations)
* Check out [wallet lifecycle management](./manage-wallet-lifecycle-states)
