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 thediscover method to find available yield opportunities.
For complete API documentation, see the Yield.xyz API reference.
Entering Yield Positions
To enter a yield position, first discover the specific yield, then use theenter 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 theexit method to withdraw from yield positions.
For complete API documentation, see the Yield.xyz exit yield reference.
High-Level Methods
Usedeposit 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 suspend and return Result<T>. YieldWithdrawParams and YieldWithdrawResult are type aliases for the deposit types, so the two methods take an identical shape.
Signatures
options is defaulted, so deposit(params) alone is valid. Both run on Dispatchers.IO.
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 fails with YieldXyzActionException.AddressUnavailable.
YieldActionTarget is a sealed class with two subtypes, so you cannot supply both forms or neither:
YieldSubmitOptions:
These are milliseconds. The iOS SDK uses
pollIntervalSeconds and timeoutSeconds for the same two concepts, so a value copied across platforms will be wrong by a factor of 1000.YieldSubmitStep members are lowercase (signing, submitted, confirming, confirmed), while YieldSubmitResultStatus members are uppercase (SUCCESS, PARTIAL_SUCCESS, FAILED). Both are written exactly as the SDK declares them.
There is no per-call signer or confirmation override — signing always goes through the Portal MPC signer.
Return value
YieldDepositResult:
Handling Results
when is exhaustive over the three states with no else.
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
Failures arrive inside the returnedResult as a YieldXyzActionException:
PortalNotInitialized, EmptyYieldId, NoTransactions, InvalidSignResponse, and InvalidUnsignedTransaction are object singletons — match them with is. The rest are data classes carrying detail.
Get Validators
Fetches the validator addresses for a native-staking yield. These are used for approval flows and for populatingarguments.validatorAddress.
portal.yield.getValidators(yieldId) is a passthrough to portal.yield.yieldxyz.getValidators(yieldId).
address is non-nullable 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.
Fails with YieldXyzActionException.NoValidators when the response contains no validators, and YieldXyzActionException.ApiError when the backend returns an error payload.
Low-level additions
Two API methods back the high-level flow and are available directly onportal.api.yieldxyz:
getYieldDefaults returns data as a map keyed "{caip2}:{TOKEN}" — for example "eip155:1:USDC". That key is exactly what ByChainAndToken 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.Managing Yield Positions
If your Portal client has entered into a yield balance, they may have a yield balance that has an availablependingActions. 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 usedeposit 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.
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.
Enum handling
Unknown values
Yield.xyz aggregates many protocols and onboards new ones regularly. Before 9.1.0, a response containing an enum value the SDK did not recognize decoded tonull rather than failing — Gson’s default enum adapter returns null for an unrecognized name, and that null was written into a non-null Kotlin field. The call still returned a successful Result, so there was nothing to catch in onFailure; the failure surfaced later, as a NullPointerException at the point where your code read the field. A single new value from an upstream provider could crash a screen rendering getBalances output, far from the call that fetched it.
As of 9.1.0, unrecognized values deserialize to UNKNOWN instead. Your app keeps working when Yield.xyz onboards a new protocol, action type, or reward schedule, without waiting for an SDK upgrade — and the value you have to handle now shows up at the call site, in the type system, rather than as a late crash.
If you arrived here from a compiler error, this is the fix:
YieldXyzSource members are lowercase (staking, lending, protocol_incentive, …) while UNKNOWN is uppercase. That is not a typo in these docs — it is how the SDK declares them, and the same mix appears in most of the enums listed below. Write UNKNOWN in uppercase even when every other member of the same enum is lowercase.
Affected enums
Thirteen public enums gainedUNKNOWN in 9.1.0, grouped here by the file that declares them so you can find the one your compiler flagged:
From YieldXyzGetYieldsResponse.kt: YieldXyzRateType, YieldXyzSource, YieldXyzRewardSchedule, YieldXyzRewardClaiming, YieldXyzArgumentFieldName, YieldXyzArgumentFieldType
From YieldXyzEnterYieldResponse.kt: YieldXyzActionIntent, YieldXyzActionType, YieldXyzActionExecutionPattern, YieldXyzActionStatus, YieldXyzActionTransactionStatus, YieldXyzActionTransactionType
From YieldXyzGetYieldsRequest.kt: YieldXyzMechanicsType
All thirteen live in io.portalhq.android.api.data.yieldxyz.
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 nullable, so an exhaustive when needs a null branch as well as an UNKNOWN branch:
Handling UNKNOWN in your code
- Treat
UNKNOWNas “display it, don’t act on it”. Render a neutral label rather than hiding the row, so users still see their position. - 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. - Log occurrences along with the
yieldId. A risingUNKNOWNrate is a signal to upgrade the SDK.
Custom Gson instances
Tolerance is implemented as a public Gson factory:YieldXyzApi registers it on its own Gson instance, so every SDK call is tolerant out of the box and you do not need to do anything. It matters only when you build your own Gson to deserialize Yield.xyz payloads — decoding a webhook body or a cached response, for example:
UNKNOWN constant; every other enum falls through to Gson’s default adapter, so registering it is safe on a shared Gson instance. Alongside unrecognized strings, it also maps JSON null and non-string tokens (numbers, booleans, objects, arrays) to UNKNOWN rather than leaving a non-null field null.
New lending source
YieldXyzSource gained a lending member in 9.1.0. You encounter this enum on each entry of a discovered opportunity’s rewardRate.components list, as component.yieldSource. The full member list as of 9.1.0:
@SerializedName annotation or a constructor value, so the wire strings are the member names exactly as written above — protocol_incentive on the wire is YieldXyzSource.protocol_incentive in Kotlin.
lending and lending_interest are separate members and Yield.xyz uses both. Treat them as distinct values rather than assuming one supersedes the other.Best Practices
- Always check yield availability before attempting to enter positions
- Process transactions sequentially as yield operations often require multiple steps and are dependent on previous transactions being mined successfully
- Handle network errors gracefully and provide user feedback
- Monitor transaction status and provide progress updates to users
- 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
- Explore transaction simulation
- Check out Portal API methods