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

## High-Level Methods

Use `approveAndSubmit`, `revokeAndSubmit`, and `transferAndSubmit` when you want one call for the whole flow: build the delegation transaction(s), then sign and broadcast each one in order and collect the resulting hashes. `Portal` installs a working signer on `portal.delegations` for you, so the common case needs no configuration at all.

<Warning>
  `approveAndSubmit`, `revokeAndSubmit`, and `transferAndSubmit` broadcast each transaction and return as soon as it is accepted by the network. They **do not wait for on-chain confirmation**. A hash in `DelegationSubmitResult.hashes` means the transaction was submitted, not that it succeeded — an approval can still revert. If your flow depends on the delegation being active, wait for the receipt yourself, or poll `getStatus` before proceeding.

  This is different from [Yield.xyz](./yield-xyz), where you wait for each transaction to confirm before moving on to the next step. Do not carry that assumption over to delegations.
</Warning>

### Signatures

```kotlin theme={null}
fun setSignAndSendTransaction(fn: DelegationSignAndSend)

suspend fun approveAndSubmit(
    request: ApproveDelegationRequest,
    options: DelegationSubmitOptions = DelegationSubmitOptions()
): Result<DelegationSubmitResult>

suspend fun revokeAndSubmit(
    request: RevokeDelegationRequest,
    options: DelegationSubmitOptions = DelegationSubmitOptions()
): Result<DelegationSubmitResult>

suspend fun transferAndSubmit(
    request: TransferFromRequest,
    options: DelegationSubmitOptions = DelegationSubmitOptions()
): Result<DelegationSubmitResult>
```

`options` is defaulted, so `portal.delegations.approveAndSubmit(request)` is a complete call. All three return `Result<DelegationSubmitResult>` — handle failures via `onSuccess` / `onFailure` (or `fold`), since errors are returned in the `Result` rather than thrown.

The request types are the same ones the low-level methods take — see [EVM Approval](#evm-approval), [EVM Revoke](#evm-revoke), and [EVM Transfer From](#evm-transfer-from) below for their fields.

### Configuring the signer

A signer signs and broadcasts one transaction and returns its hash:

```kotlin theme={null}
typealias DelegationSignAndSend = suspend (transaction: DelegationTransaction, chainId: String) -> String
```

`DelegationTransaction` is a sealed class covering both ecosystems:

```kotlin theme={null}
sealed class DelegationTransaction {
    data class Evm(val transaction: ConstructedEipTransaction) : DelegationTransaction()
    data class Solana(val encodedTransaction: String) : DelegationTransaction()
}
```

`Solana.encodedTransaction` is base64-encoded. Because it is a sealed class, a `when` over it is exhaustive and needs no `else`.

`Portal` installs a default signer that routes `Evm` transactions to `eth_sendTransaction` and `Solana` transactions to `sol_signAndSendTransaction`:

```kotlin theme={null}
val delegations: Delegations by lazy {
    Delegations(this.api.delegations).also { d ->
        d.setSignAndSendTransaction(::signDelegationTransaction)
    }
}
```

So this works with zero setup:

```kotlin theme={null}
portal.delegations.approveAndSubmit(request)
```

Use `setSignAndSendTransaction(fn)` to replace the signer for the instance, or `DelegationSubmitOptions.signAndSendTransaction` to override it for a single call. The precedence is **per-call option → instance signer → `Portal` default**.

### Options and progress

`DelegationSubmitOptions` is the second argument to each submit method:

| Parameter                | Type                                    | Required | Description                                                                                                                     |
| ------------------------ | --------------------------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------- |
| `signAndSendTransaction` | `DelegationSignAndSend?`                | No       | Per-call signer override. Takes priority over the instance signer set with `setSignAndSendTransaction(fn)`. Defaults to `null`. |
| `onProgress`             | `((DelegationSubmitProgress) -> Unit)?` | No       | Called as each transaction is signed and submitted. Defaults to `null`.                                                         |

`DelegationSubmitProgress` carries:

| Field   | Type                   | Description                                                             |
| ------- | ---------------------- | ----------------------------------------------------------------------- |
| `step`  | `DelegationSubmitStep` | `SIGNING` or `SUBMITTED`.                                               |
| `index` | `Int`                  | The 0-based index of this transaction in the sequence.                  |
| `total` | `Int`                  | The total number of transactions in the sequence.                       |
| `hash`  | `String?`              | `null` on `SIGNING`, and the broadcast transaction hash on `SUBMITTED`. |

`DelegationSubmitStep` has exactly two members — `SIGNING` and `SUBMITTED`. There is no confirming or confirmed step, because nothing is awaited on-chain.

<Note>
  `DelegationSubmitStep` members are uppercase (`DelegationSubmitStep.SIGNING`), while `YieldSubmitStep` members are lowercase (`YieldSubmitStep.signing`). Both shipped in 9.1.0. Write each one the way its own type declares it.
</Note>

### Return value

`DelegationSubmitResult` carries only the hashes:

| Field    | Type           | Description                                              |
| -------- | -------------- | -------------------------------------------------------- |
| `hashes` | `List<String>` | One hash per broadcast transaction, in submission order. |

There is no status field, and no partial-success concept: a hash is present because the network accepted the transaction, and nothing beyond that has been checked.

### Example (approve and submit)

This builds the same approval as [EVM Approval](#evm-approval) below, but signs and broadcasts it for you.

```kotlin theme={null}
import io.portalhq.android.api.data.delegations.ApproveDelegationRequest
import io.portalhq.android.delegations.DelegationSubmitOptions
import io.portalhq.android.delegations.DelegationSubmitStep

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

    portal.delegations.approveAndSubmit(
        request = request,
        options = DelegationSubmitOptions(
            onProgress = { progress ->
                when (progress.step) {
                    DelegationSubmitStep.SIGNING ->
                        println("Signing ${progress.index + 1}/${progress.total}")
                    DelegationSubmitStep.SUBMITTED ->
                        println("Submitted: ${progress.hash}")
                }
            }
        )
    ).onSuccess { result ->
        // These are broadcast, not confirmed.
        println("Submitted hashes: ${result.hashes}")
    }.onFailure { error ->
        println("approveAndSubmit failed: ${error.message}")
    }
}
```

The `when` over `progress.step` is exhaustive with no `else` — there really are only two steps.

### Example (revoke and submit)

Same `RevokeDelegationRequest` as [EVM Revoke](#evm-revoke) below, submitted end to end.

```kotlin theme={null}
import io.portalhq.android.api.data.delegations.RevokeDelegationRequest

lifecycleScope.launch {
    val request = RevokeDelegationRequest(
        chain = "eip155:11155111",
        token = "USDC",
        delegateAddress = "0x1a3eda7eb7d13e60e638711c580490c19e164fee"
    )

    portal.delegations.revokeAndSubmit(request).onSuccess { result ->
        println("Revoke submitted: ${result.hashes}")
    }.onFailure { error ->
        println("revokeAndSubmit failed: ${error.message}")
    }
}
```

<Warning>
  Because the revoke is not confirmed when this call returns, the delegation may still be active for a short time afterwards. Poll `getStatus` if you need to show the user that it is gone.
</Warning>

### Example (transfer as a delegate)

Same `TransferFromRequest` as [EVM Transfer From](#evm-transfer-from) below. Your wallet must already be an approved delegate for `fromAddress`.

```kotlin theme={null}
import io.portalhq.android.api.data.delegations.TransferFromRequest

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

    portal.delegations.transferAndSubmit(request).onSuccess { result ->
        println("Transfer submitted: ${result.hashes}")
    }.onFailure { error ->
        println("transferAndSubmit failed: ${error.message}")
    }
}
```

### Example (custom signer)

Replace the default signer when you need to do something it does not, such as attaching a `signatureApprovalMemo` to every delegation transaction. A `when` over the sealed class is exhaustive and returns the hash directly:

```kotlin theme={null}
import io.portalhq.android.delegations.DelegationTransaction
import io.portalhq.android.provider.data.PortalRequestMethod
import io.portalhq.android.provider.data.RequestOptions

portal.delegations.setSignAndSendTransaction { transaction, chainId ->
    val (method, param) = when (transaction) {
        is DelegationTransaction.Evm ->
            PortalRequestMethod.eth_sendTransaction to transaction.transaction
        is DelegationTransaction.Solana ->
            PortalRequestMethod.sol_signAndSendTransaction to transaction.encodedTransaction
    }

    val response = portal.request(
        chainId = chainId,
        method = method,
        params = listOf(param),
        options = RequestOptions(signatureApprovalMemo = "Delegation transaction")
    )

    // Returning a blank hash makes the submit method fail with
    // DelegationsError.InvalidTransactionHash, tagged with the right index.
    response.result as? String ?: ""
}
```

To use a different signer for a single call, pass it in the options instead — it takes priority over the instance signer:

```kotlin theme={null}
import io.portalhq.android.api.data.delegations.ApproveDelegationRequest
import io.portalhq.android.delegations.DelegationSubmitOptions
import io.portalhq.android.delegations.DelegationTransaction
import io.portalhq.android.provider.data.PortalRequestMethod
import io.portalhq.android.provider.data.RequestOptions

lifecycleScope.launch {
    val request = ApproveDelegationRequest(
        chain = "eip155:11155111",
        token = "USDC",
        delegateAddress = "0x1a3eda7eb7d13e60e638711c580490c19e164fee",
        amount = "0.01"
    )

    portal.delegations.approveAndSubmit(
        request = request,
        options = DelegationSubmitOptions(
            signAndSendTransaction = { transaction, chainId ->
                val (method, param) = when (transaction) {
                    is DelegationTransaction.Evm ->
                        PortalRequestMethod.eth_sendTransaction to transaction.transaction
                    is DelegationTransaction.Solana ->
                        PortalRequestMethod.sol_signAndSendTransaction to transaction.encodedTransaction
                }

                portal.request(
                    chainId = chainId,
                    method = method,
                    params = listOf(param),
                    options = RequestOptions(signatureApprovalMemo = "One-off delegation approval")
                ).result as? String ?: ""
            }
        )
    ).onSuccess { result ->
        println("Submitted hashes: ${result.hashes}")
    }.onFailure { error ->
        println("approveAndSubmit failed: ${error.message}")
    }
}
```

### Errors

`DelegationsError` is a sealed class of `Exception` subclasses. They arrive inside a failed `Result`, so match them in `onFailure`:

| Case                     | When                                                                                                                                                |
| ------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------- |
| `NoSignerConfigured`     | No signer was available. This cannot happen on `portal.delegations`, which `Portal` wires for you — only when you construct `Delegations` yourself. |
| `NoTransactions`         | The delegation response contained no transactions to submit.                                                                                        |
| `InvalidTransactionHash` | The signer returned a value that is not a usable hash for that chain. The message names which transaction in the sequence it was.                   |

```kotlin theme={null}
import io.portalhq.android.api.data.delegations.ApproveDelegationRequest
import io.portalhq.android.delegations.DelegationsError

lifecycleScope.launch {
    val request = ApproveDelegationRequest(
        chain = "eip155:11155111",
        token = "USDC",
        delegateAddress = "0x1a3eda7eb7d13e60e638711c580490c19e164fee",
        amount = "0.01"
    )

    portal.delegations.approveAndSubmit(request).onSuccess { result ->
        println("Submitted hashes: ${result.hashes}")
    }.onFailure { error ->
        when (error) {
            is DelegationsError.NoTransactions ->
                println("The approval response contained no transactions to submit.")
            is DelegationsError.InvalidTransactionHash ->
                println("The signer returned an unusable hash: ${error.message}")
            is DelegationsError.NoSignerConfigured ->
                println("No signer configured on this Delegations instance.")
            else ->
                println("approveAndSubmit failed: ${error.message}")
        }
    }
}
```

The submit methods can also fail with the network and decoding errors the low-level methods return. Coroutine cancellation is never captured in the `Result` — it is rethrown, so structured concurrency still works when the calling scope is torn down.

***

## Low-Level Methods

The sections below are the manual path: `approve`, `revoke`, `transferFrom`, and `getStatus` return unsigned transactions and leave signing and broadcasting to you. Use them when you need to inspect, modify, batch, or route the transactions yourself. Otherwise prefer the high-level methods above.

## 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),
                        options = RequestOptions(signatureApprovalMemo = "Approve delegation")
                    )
                    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),
                        options = RequestOptions(signatureApprovalMemo = "Approve delegation")
                    )
                    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),
                        options = RequestOptions(signatureApprovalMemo = "Revoke delegation")
                    )
                    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),
                        options = RequestOptions(signatureApprovalMemo = "Revoke delegation")
                    )
                    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),
                        options = RequestOptions(signatureApprovalMemo = "Transfer delegated tokens")
                    )
                    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),
                        options = RequestOptions(signatureApprovalMemo = "Transfer delegated tokens")
                    )
                    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

* Submit delegations in one call with the [high-level methods](#high-level-methods)
* 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)
