Portal’s Enclave MPC API provides comprehensive yield opportunities capabilities through the Yield.xyz integration. This guide covers discovering yield opportunities, entering positions, managing existing positions, and exiting yield opportunities.
Overview
The yield functionality allows you 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:
Discovering Yield Opportunities
Use the GET /api/v3/clients/me/integrations/yield-xyz/yields endpoint to find available yield opportunities.
For complete API documentation, see the Client API reference.
curl --request GET \
--url 'https://api.portalhq.io/api/v3/clients/me/integrations/yield-xyz/yields?limit=10' \
--header 'Authorization: Bearer [clientApiKey|clientSessionToken]'
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 POST /api/v3/clients/me/integrations/yield-xyz/actions/enter endpoint to create the action and get transactions. You’ll then sign and submit these transactions using the Enclave MPC API.
For complete API documentation, see the Client API 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 (here is the correct LINK token on Sepolia testnet Etherscan).
Step 1: Create the Enter Action
curl --request POST \
--url https://api.portalhq.io/api/v3/clients/me/integrations/yield-xyz/actions/enter \
--header 'Authorization: Bearer [clientApiKey|clientSessionToken]' \
--header 'Content-Type: application/json' \
--data '{
"address": "0xYourAddress",
"arguments": {
"amount": "1"
},
"yieldId": "ethereum-sepolia-link-aave-v3-lending"
}'
Take note of the transactionId and unsignedTransaction fields in the response’s data.rawResponse.transactions array items. You will need to use these to track the transaction.
Step 2: Process and Sign Transactions
The response will include an array of transactions. Process them sequentially, sign each using the Enclave MPC API, track it, and wait for on-chain confirmation before proceeding to the next.
# Example: Signing the first transaction from the enter action response
curl --request POST \
--url https://mpc-client.portalhq.io/v1/sign \
--header 'Authorization: Bearer [clientApiKey|clientSessionToken]' \
--header 'Content-Type: application/json' \
--data '{
"share": "[share]",
"method": "eth_sendTransaction",
"params": { "from":"0xFromAddress", "to":"0xToAddress", "data":"0xData" },
"rpcUrl": "https://api.portalhq.io/rpc/v1/eip155/11155111",
"chainId": "eip155:11155111"
}'
Step 3: Track Transaction
After signing and broadcasting, submit the transaction hash to Yield.xyz:
curl --request PUT \
--url https://api.portalhq.io/api/v3/clients/me/integrations/yield-xyz/transactions/[transactionId]/submit-hash \
--header 'Authorization: Bearer [clientApiKey|clientSessionToken]' \
--header 'Content-Type: application/json' \
--data '{
"hash": "[transactionHash]"
}'
Learn more about processing these transactions sequentially in the
section below.
Checking Yield Balances
Retrieve current yield positions and balances using the POST /api/v3/clients/me/integrations/yield-xyz/yields/balances endpoint.
For complete API documentation, see the Client API reference.
curl --request POST \
--url https://api.portalhq.io/api/v3/clients/me/integrations/yield-xyz/yields/balances \
--header 'Authorization: Bearer [clientApiKey|clientSessionToken]' \
--header 'Content-Type: application/json' \
--data '{
"queries": [
{
"address": "0xYourAddress",
"network": "eip155:11155111"
}
]
}'
Exiting Yield Positions
Use the POST /api/v3/clients/me/integrations/yield-xyz/actions/exit endpoint to create an exit action, then sign and submit the resulting transactions.
For complete API documentation, see the Client API reference.
# Step 1: Create exit action
curl --request POST \
--url https://api.portalhq.io/api/v3/clients/me/integrations/yield-xyz/actions/exit \
--header 'Authorization: Bearer [clientApiKey|clientSessionToken]' \
--header 'Content-Type: application/json' \
--data '{
"yieldId": "ethereum-sepolia-link-aave-v3-lending",
"address": "0xYourAddress",
"arguments": {
"amount": "0.001"
}
}'
# Step 2: Sign and submit transactions (same process as entering)
# Process each transaction from the response sequentially using the Enclave MPC API sign endpoint
Managing Yield Positions
If your Portal client has entered into a yield balance, they may have a yield balance with available pendingActions. You can use the POST /api/v3/clients/me/integrations/yield-xyz/actions/manage endpoint 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 Client API reference.
# First, get the balance to find pendingActions
curl --request POST \
--url https://api.portalhq.io/api/v3/clients/me/integrations/yield-xyz/yields/balances \
--header 'Authorization: Bearer [clientApiKey|clientSessionToken]' \
--header 'Content-Type: application/json' \
--data '{
"queries": [
{
"address": "0xYourAddress",
"network": "eip155:11155111"
}
]
}'
// Example response:
{
"data": {
"rawResponse": {
"items": [
{
"yieldId": "ethereum-sepolia-link-aave-v3-lending",
"balances": [
{
"address": "0xYourAddress",
"amount": "0.001000027202065699",
"amountRaw": "1000027202065699",
"type": "active",
"token": {
"address": "0x3FfAf50D4F4E96eB78f2407c090b72e86eCaed24",
"symbol": "aEthLINK",
"name": "Aave Ethereum LINK",
"decimals": 18,
"logoURI": "https://assets.stakek.it/tokens/alink.svg",
"network": "eip155:11155111",
"isPoints": false
},
"pendingActions": [
{
"intent": "manage",
"type": "WITHDRAW",
// 👇 This is the "passthrough" value from the balance's pendingAction item that we will use to create the manage action.
"passthrough": "eyJhZGRyZXNzZXMiOnsiYWRkcmVzcyI6IjB4ZD...",
"arguments": null
}
],
"amountUsd": "0.000000",
"isEarning": true
}
]
}
],
"errors": []
}
}
}
# Then create the manage action using the pendingAction's type and passthrough
curl --request POST \
--url https://api.portalhq.io/api/v3/clients/me/integrations/yield-xyz/actions/manage \
--header 'Authorization: Bearer [clientApiKey|clientSessionToken]' \
--header 'Content-Type: application/json' \
--data '{
"action": "WITHDRAW",
"address": "0xYourAddress",
"passthrough": "eyJhZGRyZXNzZXMiOnsiYWRkcmVzcyI6IjB4ZD...",
"yieldId": "ethereum-sepolia-link-aave-v3-lending"
}'
# Finally, sign and submit transactions (same process as entering/exiting)
Getting Historical Actions
Retrieve the history of yield actions for an address using the GET /api/v3/clients/me/integrations/yield-xyz/actions endpoint.
For complete API documentation, see the Client API reference.
curl --request GET \
--url 'https://api.portalhq.io/api/v3/clients/me/integrations/yield-xyz/actions?address=0xYourAddress' \
--header 'Authorization: Bearer [clientApiKey|clientSessionToken]'
Transaction Processing
Yield operations can require multiple transactions. Process them sequentially, sign each using the Enclave MPC API, track it, and wait for on-chain confirmation (e.g. using eth_getTransactionReceipt) before proceeding to the next.
For complete API documentation, see the Client API reference and get transaction details reference.
For account abstraction enabled Portal clients, use eth_getUserOperationReceipt instead of eth_getTransactionReceipt since signing returns a user operation hash, not a transaction hash.Extract the transaction hash from response.result.receipt.transactionHash and use that transaction hash when calling the PUT /api/v3/clients/me/integrations/yield-xyz/transactions/[transactionId]/submit-hash endpoint.
Example Transaction Processing Flow
Here’s a complete example of processing transactions from an enter action:
# 1. Create the enter action and get transactions
ENTER_RESPONSE=$(curl --request POST \
--url https://api.portalhq.io/api/v3/clients/me/integrations/yield-xyz/actions/enter \
--header 'Authorization: Bearer [clientApiKey|clientSessionToken]' \
--header 'Content-Type: application/json' \
--data '{
"address": "0xYourAddress",
"arguments": {
"amount": "1"
},
"yieldId": "ethereum-sepolia-link-aave-v3-lending"
}')
# Extract transactions from response (parse JSON)
# Sort by stepIndex and process in order
# 2. For each transaction with status "CREATED" and an unsignedTransaction:
# a. Parse the unsignedTransaction JSON
# b. Sign and submit using Enclave MPC API
curl --request POST \
--url https://mpc-client.portalhq.io/v1/sign \
--header 'Authorization: Bearer [clientApiKey|clientSessionToken]' \
--header 'Content-Type: application/json' \
--data '{
"share": "[share]",
"method": "eth_sendTransaction",
"params": { "from":"0xFromAddress", "to":"0xToAddress", "data":"0xData" },
"rpcUrl": "https://api.portalhq.io/rpc/v1/eip155/11155111",
"chainId": "eip155:11155111"
}'
# 3. Extract transaction hash from response and track it
curl --request PUT \
--url https://api.portalhq.io/api/v3/clients/me/integrations/yield-xyz/transactions/[transactionId]/submit-hash \
--header 'Authorization: Bearer [clientApiKey|clientSessionToken]' \
--header 'Content-Type: application/json' \
--data '{
"hash": "0x..."
}'
# 4. Wait for transaction confirmation
# Poll eth_getTransactionReceipt using a RPC request. Below we use Alchemy's RPC endpoint for Sepolia as an example.
curl --request POST \
--url https://eth-sepolia.g.alchemy.com/v2/[alchemyApiKey] \
--header 'Content-Type: application/json' \
--data '{
"id": 1,
"jsonrpc": "2.0",
"method": "eth_getTransactionReceipt",
"params": [
"0xTransactionHash"
]
}'
# 5. Repeat steps 2-4 for each subsequent transaction
The unsignedTransaction field in the Yield.xyz response is a JSON string. Parse it and extract the transaction parameters before passing to the Enclave MPC API sign endpoint. Remove the gas parameters if you want Portal to estimate the gas for you.
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
- Track all transactions using the Yield.xyz submit-hash endpoint to maintain accurate state
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