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

# Earn with Yield.xyz

> Learn how to discover, enter, manage, and exit yield opportunities.

Portal's Android SDK provides comprehensive yield opportunities capabilities through the `portal.yield.yieldxyz` API. This guide covers discovering yield opportunities, entering positions, managing existing positions, and exiting yield opportunities.

## Overview

The yield functionality allows users to:

* **Discover** available yield opportunities across different protocols and networks
* **Enter** yield positions by depositing tokens into yield opportunities
* **Manage** existing positions (claim rewards, voting, etc.)
* **Exit** yield positions to withdraw aggregated tokens and rewards
* **Track** yield balances and historical yield actions

## Prerequisites

Before using yield operations, ensure you have:

* A properly initialized Portal client
* An active wallet with the required token(s) on the target network (see [Create a wallet](./create-a-wallet))
* Yield.xyz integration enabled in your Portal Dashboard (see [Yield.xyz Integration](../../../resources/integrations/yield-xyz))

## Discovering Yield Opportunities

Use the `discover` method to find available yield opportunities.

For complete API documentation, see the [Yield.xyz API reference](https://docs.yield.xyz/reference/yieldscontroller_getyields).

```kotlin theme={null}
val request = YieldXyzGetYieldsRequest(
    offset = 0,
    limit = 10,
    network = "eip155:11155111", // Sepolia network
    // ... other parameters
)

val result = portal.yield.yieldxyz.discover(request)

if (result.isSuccess) {
    val response = result.getOrThrow()
    val rawResponse = response.data?.rawResponse
    val yieldOpportunities = rawResponse?.items

    // Process and display yield opportunities
}
```

<Tip>
  Popular, high-quality USDC yield options with no lockups or limits:

  * USDC Aave V3 Lending:
    * `base-usdc-aave-v3-lending`
  * USDC Fluid Vault:
    * `base-usdc-fusdc-0xf42f5795d9ac7e9d757db633d693cd548cfd9169-4626-vault`
  * USDC Spark Savings Vault:
    * `ethereum-usdc-spusdc-0x28b3a8fb53b741a8fd78c0fb9a6b2393d896a43d-4626-vault`
</Tip>

## Entering Yield Positions

To enter a yield position, first discover the specific yield, then use the `enter` method.

For complete API documentation, see the [Yield.xyz enter yield reference](https://docs.yield.xyz/reference/actionscontroller_enteryield).

For the example below, we will use the yield opportunity with the ID `"ethereum-sepolia-link-aave-v3-lending"`. Fund your Portal client with the required `LINK` token to enter the position.

```kotlin theme={null}
val userAddress = portal.getAddress(PortalNamespace.EIP155) ?: return

val enterRequest = YieldXyzEnterRequest(
    yieldId = "ethereum-sepolia-link-aave-v3-lending",
    address = userAddress,
    arguments = EnterYieldArguments(
        amount = "1", // 1 LINK token
    )
)

val enterResult = portal.yield.yieldxyz.enter(enterRequest)
if (enterResult.isSuccess) {
    val enterResponse = enterResult.getOrThrow()
    val rawResponse = enterResponse.data?.rawResponse
    val transactions = rawResponse?.transactions

    // Process transactions, this is described in the "Transaction Processing" section below
    processTransactions(transactions)
}
```

## Checking Yield Balances

Retrieve current yield positions and balances.

For complete API documentation, see the [Yield.xyz get balances reference](https://docs.yield.xyz/reference/yieldscontroller_getaggregatebalances).

```kotlin theme={null}
val userAddress = portal.getAddress(PortalNamespace.EIP155) ?: return

val balanceRequest = YieldXyzGetBalancesRequest(
    queries = listOf(
        YieldBalanceQuery(
            address = userAddress,
            network = "eip155:11155111" // Sepolia testnet
        )
    )
)

val balanceResult = portal.yield.yieldxyz.getBalances(balanceRequest)
if (balanceResult.isSuccess) {
    val response = balanceResult.getOrThrow()
    val rawResponse = response.data?.rawResponse
    val yieldPositions = rawResponse?.items

    // Process and display yield positions information
}
```

<Note>
  We recommend always specifying a `yieldId` on each balance query. When `yieldId` is provided, Yield.xyz can resolve balances directly, so you don't need to call the `track` endpoint after entering or exiting positions.

  ```kotlin theme={null}
  val balanceRequest = YieldXyzGetBalancesRequest(
      queries = listOf(
          YieldBalanceQuery(
              address = userAddress,
              network = "eip155:11155111",
              yieldId = "ethereum-sepolia-link-aave-v3-lending"
          )
      )
  )
  ```
</Note>

## Exiting Yield Positions

Use the `exit` method to withdraw from yield positions.

For complete API documentation, see the [Yield.xyz exit yield reference](https://docs.yield.xyz/reference/actionscontroller_exityield).

```kotlin theme={null}
val userAddress = portal.getAddress(PortalNamespace.EIP155) ?: return

val exitRequest = YieldXyzExitRequest(
    yieldId = "ethereum-sepolia-link-aave-v3-lending",
    address = userAddress,
    arguments = YieldXyzEnterArguments(amount = "0.001")
)

val exitResult = portal.yield.yieldxyz.exit(exitRequest)
if (exitResult.isSuccess) {
    val exitResponse = exitResult.getOrThrow()
    val rawResponse = exitResponse.data?.rawResponse
    val transactions = rawResponse?.transactions

    // Process transactions, this is described in the "Transaction Processing" section below
    processTransactions(transactions)
}
```

## Managing Yield Positions

If your Portal client has entered into a yield balance, they may have a yield balance that has an available `pendingActions`. You can use the `manage` method to perform actions on existing yield positions. For example, if the balance has a `pendingAction` of `WITHDRAW` or `CLAIM_REWARDS`, you can use the `manage` method to withdraw or claim rewards from the yield balance.

For complete API documentation, see the [Yield.xyz manage yield reference](https://docs.yield.xyz/reference/actionscontroller_manageyield).

```kotlin theme={null}
val userAddress = portal.getAddress(PortalNamespace.EIP155) ?: return

val manageRequest = YieldXyzManageYieldRequest(
    yieldId = "ethereum-sepolia-link-aave-v3-lending",
    address = userAddress,
    action = YieldActionType.WITHDRAW, // Replace with the balance's `pendingAction` item's `type` value.
    passthrough = "eyJhZGRyZXNzZXMiOnsiYWRkcmVzcyI6ImNvc21vczF5ZXk..." // Replace with the balance's `pendingAction` item's `passthrough` value.
)

val manageResult = portal.yield.yieldxyz.manage(manageRequest)
if (manageResult.isSuccess) {
    val manageResponse = manageResult.getOrThrow()
    val rawResponse = manageResponse.data?.rawResponse
    val transactions = rawResponse?.transactions

    // Process transactions, this is described in the "Transaction Processing" section below
    processTransactions(transactions)
}
```

## Getting Historical Actions

Retrieve the history of yield actions for an address.

For complete API documentation, see the [Yield.xyz get actions reference](https://docs.yield.xyz/reference/actionscontroller_getactions).

```kotlin theme={null}
val userAddress = portal.getAddress(PortalNamespace.EIP155) ?: return

val request = YieldXyzGetHistoricalActionsRequest(address = userAddress)
val result = portal.yield.yieldxyz.getHistoricalActions(request)

if (result.isSuccess) {
    val response = result.getOrThrow()
    val rawResponse = response.data?.rawResponse
    val pastActions = rawResponse?.items

    // Process and display past yield actions
}
```

## Transaction Processing

Yield operations can require multiple transactions. Process them sequentially, submit each, track it, and wait for on-chain confirmation (e.g. using `eth_getTransactionReceipt`) before proceeding to the next.

For complete API documentation, see the [Yield.xyz submit transaction hash reference](https://docs.yield.xyz/reference/transactionscontroller_submittransactionhash) and [get transaction details reference](https://docs.yield.xyz/reference/transactionscontroller_gettransaction).

<Tip>
  For account abstraction enabled Portal clients, use `eth_getUserOperationReceipt` instead of `eth_getTransactionReceipt` to wait for confirmation, since signing returns a *user operation hash*, not a transaction hash.

  If you don't specify a `yieldId` on your balance queries, you'll need to call `track` after each transaction so Yield.xyz can attribute the position. Pass the **transaction hash** (extracted from `response.result.receipt.transactionHash` for AA clients), not the user operation hash.
</Tip>

```kotlin theme={null}
fun processTransactions(transactions: List<YieldActionTransaction>?) {
    val sorted = transactions?.sortedBy { it.stepIndex } ?: emptyList()
    for (tx in sorted) {
        if (tx.unsignedTransaction != null && tx.status == YieldActionTransactionStatus.CREATED) {
            val ok = runBlocking { signAndSubmitAndConfirm(tx) }
            if (!ok) break
        }
    }
}

suspend fun signAndSubmitAndConfirm(transaction: YieldActionTransaction): Boolean {
    val unsignedTxJson = transaction.unsignedTransaction as? String ?: return false

    val gson = Gson()
    val type = object : TypeToken<Map<String, Any>>() {}.type
    val txParams = gson.fromJson<Map<String, Any>>(unsignedTxJson, type)

    val ethTransaction = EthTransactionParam(
        from = txParams["from"] as? String ?: "",
        to = txParams["to"] as? String ?: "",
        value = txParams["value"] as? String ?: "0x0",
        data = txParams["data"] as? String ?: "0x",
        gas = null, // Let Portal handle gas estimation`
        gasPrice = null,
        maxFeePerGas = null,
        maxPriorityFeePerGas = null
    )

    val send = portal.request(
        chainId = transaction.network,
        method = PortalRequestMethod.eth_sendTransaction,
        params = listOf(ethTransaction)
    )

    val txHash = send.result as? String ?: return false

    portal.yield.yieldxyz.track(transaction.id, txHash)

    return waitForReceipt(txHash, transaction.network)
}

suspend fun waitForReceipt(txHash: String, chainId: String, maxAttempts: Int = 30, delayMs: Long = 2000): Boolean {
    repeat(maxAttempts) {
        kotlinx.coroutines.delay(delayMs)

        val receiptResp = portal.request(
            chainId = chainId,
            method = PortalRequestMethod.eth_getTransactionReceipt,
            params = listOf(txHash)
        )

        val receipt = receiptResp.result as? Map<String, Any>
        val status = receipt?.get("status") as? String
        if (status == "0x1") return true // Was mined
        if (status == "0x0") return false // Was not mined yet
    }
    return false
}
```

## Best Practices

1. **Always check yield availability** before attempting to enter positions
2. **Process transactions sequentially** as yield operations often require multiple steps and are dependent on previous transactions being mined successfully
3. **Handle network errors gracefully** and provide user feedback
4. **Monitor transaction status** and provide progress updates to users
5. **Validate user balances** before initiating yield operations

## Supported Networks

The yield functionality supports various networks including:

* Monad (`eip155:143`)
* Monad Testnet (`eip155:10143`)
* Arbitrum (`eip155:42161`)
* Avalanche C (`eip155:43114`)
* Base (`eip155:8453`)
* Base Sepolia (`eip155:84532`)
* Celo (`eip155:42220`)
* Core (`eip155:1116`)
* Ethereum (`eip155:1`)
* Ethereum Sepolia (`eip155:11155111`)
* Fantom (`eip155:250`)
* Gnosis (`eip155:100`)
* Harmony (`eip155:1666600000`)
* Hyperevm (`eip155:999`)
* Katana (`eip155:747474`)
* Linea (`eip155:59144`)
* Moonriver (`eip155:1285`)
* Optimism (`eip155:10`)
* Optimism Sepolia (`eip155:11155420`)
* Plasma (`eip155:9745`)
* Polygon (`eip155:137`)
* Polygon Amoy (`eip155:80002`)
* Sonic (`eip155:146`)
* Unichain (`eip155:130`)
* Viction (`eip155:88`)
* zkSync (`eip155:324`)
* Solana (`solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp`)
* Solana Devnet (`solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1`)
* Stellar (`stellar:pubnet`)
* Stellar Testnet (`stellar:testnet`)
* Tron (`tron:mainnet`)

## Next Steps

* Learn about [managing wallet lifecycle states](./manage-wallet-lifecycle-states)
* Explore [transaction simulation](./evaluate-a-transaction)
* Check out [Portal API methods](./portal-api-methods)
