Skip to main content
Portal’s iOS 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)
  • Yield.xyz integration enabled in your Portal Dashboard (see Yield.xyz Integration)

Discovering Yield Opportunities

Use the discover method to find available yield opportunities. For complete API documentation, see the Yield.xyz API reference.
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

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

Checking Yield Balances

Retrieve current yield positions and balances. For complete API documentation, see the Yield.xyz get balances reference.
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.

Exiting Yield Positions

Use the exit method to withdraw from yield positions. For complete API documentation, see the Yield.xyz exit yield reference.

High-Level Methods

Use deposit and withdraw when you want one call for the full flow: resolve the yield, build the action, sign and send each transaction in order, wait for confirmation between steps, and report each hash back to Yield.xyz. Both are async throws and take the same parameter shape — YieldWithdrawParams and YieldWithdrawResult are type aliases for the deposit types.

Signatures

Convenience overloads drop the options argument entirely:

Essential parameters

YieldDepositParams: There is no address parameter. The wallet address is resolved from your Portal instance for whichever chain the yield resolves to. If no wallet exists for that chain, the call throws YieldXyzError.addressUnavailable. YieldActionTarget is an enum with two cases, so you cannot accidentally supply both forms or neither:
.chainAndToken requires full CAIP-2. A bare "1" throws YieldXyzError.invalidChainId. This differs from Li.Fi’s tradeAsset, which forwards whatever chain format you give it — the two APIs shipped in the same release but do not accept the same values.
YieldSubmitOptions:
These are seconds, not milliseconds. The Android SDK uses pollIntervalMs and timeoutMs for the same concepts, so a value copied across platforms will be wrong by a factor of 1000.
There is no per-call signer or confirmation override on iOS — signing always goes through the Portal MPC signer.

Return value

YieldDepositResult:

Handling Results

A non-empty hashes array does not mean success. Hashes are recorded as transactions are submitted, before their outcome is known. Always branch on status.

Example (deposit with progress)

Example (targeting by chain and token)

chain and token on the result are populated only when you target this way.

Example (withdraw)

withdraw takes identical parameter shapes:

Errors

deposit, withdraw, and getValidators throw YieldXyzError: All cases conform to LocalizedError, so errorDescription gives a readable message.

Get Validators

Fetches the validator addresses for a native-staking yield. These are used for approval flows and for populating arguments.validatorAddress.
Available on both the namespace and the provider — portal.yield.getValidators(yieldId:) is a passthrough to portal.yield.yieldxyz.getValidators(yieldId:).
Only address is non-optional on YieldXyzValidator. Everything else — name, logoURI, website, rewardRate, provider, commission, tvlUsd, votingPower, preferred, minimumStake, status, and the rest — depends on the protocol and may be absent. Throws YieldXyzError.noValidators when the response contains no validators, and YieldXyzError.apiError when the backend returns an error payload.

Low-level additions

Two API methods back the high-level flow and are available directly on portal.api.yieldxyz:
getYieldDefaults returns data as a dictionary keyed "{caip2}:{TOKEN}" — for example "eip155:1:USDC". That key is exactly what .chainAndToken resolves against, so this is how you discover valid chain and token pairs. Pass includeOpportunities: true to populate each entry’s opportunity field.
Unlike the other Yield.xyz responses, the defaults payload is not wrapped in rawResponse — read it from data directly.
YieldXyzEnterArguments also gained a builder helper for replacing just the amount:

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.

Getting Historical Actions

Retrieve the history of yield actions for an address. For complete API documentation, see the Yield.xyz get actions reference.

Transaction Processing (low-level enter / exit / manage)

If you use deposit or withdraw, skip this section — the SDK already sequences transactions, waits for confirmation between steps, and reports hashes to Yield.xyz. This section applies to manual flows built on enter, exit, or manage.
When deposit and withdraw sign an EVM transaction they rebuild it from the yield action’s unsignedTransaction, copying to, from, value, data and the fee fields (gasLimit/gas, maxFeePerGas, maxPriorityFeePerGas, gasPrice) but deliberately omitting nonce, so the MPC signer fetches the pending nonce at signing time. If you sign manually, drop the planning nonce the same way — reusing it across a multi-transaction action causes nonce collisions.
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 and get transaction details reference.
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.

Enum Handling

Unknown Values

Yield.xyz aggregates many protocols and onboards new ones regularly. Before 7.3.0, a response containing an enum value the SDK did not recognize failed to decode and the entire call threw — a single new value from an upstream provider could break discover or getBalances outright. As of 7.3.0, unrecognized values decode to .unknown instead of failing. Your app keeps working when Yield.xyz onboards a new protocol, action type, or reward schedule, without waiting for an SDK upgrade. If you arrived here from a compiler error, this is the fix:
Prefer an explicit case .unknown over default:. With default:, the next case Portal adds falls into it silently; with an explicit .unknown, you get a compiler error and a chance to handle the new value deliberately.

Affected enums

Thirteen public enums gained .unknown in 7.3.0, grouped here by the type that declares them so you can find the one your compiler flagged: From YieldXyzGetYieldsResponse: YieldXyzRateType, YieldXyzSource, YieldXyzRewardSchedule, YieldXyzRewardClaiming, YieldXyzArgumentFieldName, YieldXyzArgumentFieldType From YieldXyzEnterYieldResponse: YieldXyzActionIntent, YieldXyzActionType, YieldXyzActionExecutionPattern, YieldXyzActionStatus, YieldXyzActionTransactionStatus, YieldXyzActionTransactionType From YieldXyzGetYieldsRequest: YieldXyzMechanicsType All thirteen conform to a new public protocol, YieldXyzUnknownTolerantEnum, which supplies the tolerant Codable decoding and an unknownValue fallback. You never implement or reference it directly — it exists so these enums share one decoding path, and it may show up in autocomplete or a stack trace. The reach extends past discover. YieldXyzActionIntent, YieldXyzActionType, YieldXyzActionExecutionPattern, and YieldXyzActionStatus are all fields on YieldOpportunityDetails, which is returned by the high-level deposit and withdraw methods. Code reading result.yieldOpportunityDetails.status is affected — note that these four fields are optional, so an exhaustive switch needs to handle nil as well as .unknown:

Handling .unknown in your code

  1. Treat .unknown as “display it, don’t act on it”. Render a neutral label rather than hiding the row, so users still see their position.
  2. Don’t branch business logic on .unknown. If a decision depends on knowing the exact source or status, read the raw response value rather than inferring from the enum.
  3. Log occurrences along with the yieldId. A rising .unknown rate is a signal to upgrade the SDK.

New lending source

YieldXyzSource gained a lending case in 7.3.0. You encounter this enum on each entry of a discovered opportunity’s rewardRate.components array, as component.yieldSource. The full case list as of 7.3.0:
The raw string values match the case names exactly — .protocol_incentive encodes as "protocol_incentive" — so no case has a separate raw value to map.
lending and lending_interest are separate cases and Yield.xyz uses both. Treat them as distinct values rather than assuming one supersedes the other.

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