Skip to main content
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]'

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.

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 until status is 0x1 (success) or 0x0 (failed)
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_getTransactionReceipt",
  "params": "[\"0x...\"]",
  "rpcUrl": "https://api.portalhq.io/rpc/v1/eip155/11155111",
  "chainId": "eip155:11155111"
}'

# 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

  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
  6. Track all transactions using the Yield.xyz submit-hash endpoint to maintain accurate state

Supported Networks

The yield functionality supports various networks including:
  • Monad Testnet (eip155:10143)
  • Ethereum Mainnet (eip155:1)
  • Ethereum Sepolia (eip155:11155111)
  • Polygon (eip155:137)
  • Polygon Amoy (eip155:80002)
  • Base (eip155:8453)
  • Base Sepolia (eip155:84532)
  • Arbitrum (eip155:42161)
  • Optimism (eip155:10)
  • Optimism Sepolia (eip155:11155420)
  • Solana (solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp)
  • Solana Devnet (solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1)

Next Steps