Yield.xyz supports Ethereum, Base, Solana, and 50+ other chains across EVM and non-EVM networks. Testnet support includes Stellar-Testnet, Base-Sepolia, Ethereum-Sepolia, and Solana Devnet. For the complete and up-to-date list, see the Yield.xyz Supported Networks documentation.
This guide uses Base network with testnet wallets connected to mainnet
yield opportunities, giving you a realistic experience without using real funds.
Completed the React Quickstart to set up Crossmint providers and wallet creation
A wallet funded with USDC testnet tokens (get test USDC from Circle’s Faucet)
Since this guide uses testnet tokens, deposits will not actually earn yield. For production, use mainnet USDC and ensure your Crossmint wallet is configured for mainnet.Need help launching in production or getting access to Yield.xyz? Contact sales.
1
Get a Yield.xyz API Key
Request an API key from Yield.xyz and add it to your environment:
.env.local
Copy
Ask AI
NEXT_PUBLIC_YIELD_API_KEY=YOUR_YIELD_XYZ_API_KEY
2
Create the Yield API utilities
Create a file with all the Yield.xyz API functions and types:
Fetch Yields: Retrieve available USDC yield opportunities on Base
Enter Yield: Deposit USDC into a yield-generating position
Exit Yield: Withdraw USDC from an active yield position
Get Yield Balance: Check the current balance in a yield position
Get Active Positions: Retrieve all active yield positions for a wallet
yield-api.ts
Copy
Ask AI
const YIELD_API_URL = "https://api.yield.xyz";const YIELD_NETWORK = "base"; // Hardcoded to Base network// Typesexport interface YieldOpportunity { id: string; network: string; providerId: string; metadata: { name: string; description?: string }; rewardRate: { total: number; rateType: "APY" | "APR" }; status: { enter: boolean; exit: boolean };}export interface YieldAction { id: string; intent: "enter" | "exit"; yieldId: string; amount: string; amountUsd: string; status: "CREATED" | "PROCESSING" | "SUCCESS" | "FAILED"; createdAt: string;}// Fetch available yield opportunitiesexport async function fetchYields(): Promise<YieldOpportunity[]> { const response = await fetch( `${YIELD_API_URL}/v1/yields?network=${YIELD_NETWORK}&token=USDC&limit=10`, { headers: { "Content-Type": "application/json", "X-API-KEY": process.env.NEXT_PUBLIC_YIELD_API_KEY!, }, } ); if (!response.ok) { throw new Error("Failed to fetch yields"); } const data = await response.json(); return data.data || data.items || [];}// Enter a yield position (deposit)export async function enterYield( yieldId: string, address: string, amount: string) { const response = await fetch(`${YIELD_API_URL}/v1/actions/enter`, { method: "POST", headers: { "Content-Type": "application/json", "X-API-KEY": process.env.NEXT_PUBLIC_YIELD_API_KEY!, }, body: JSON.stringify({ yieldId, address, arguments: { amount }, // Human-readable (e.g., "100" for 100 USDC) }), }); if (!response.ok) { throw new Error("Failed to create deposit"); } return response.json();}// Exit a yield position (withdraw)export async function exitYield( yieldId: string, address: string, amount?: string) { const response = await fetch(`${YIELD_API_URL}/v1/actions/exit`, { method: "POST", headers: { "Content-Type": "application/json", "X-API-KEY": process.env.NEXT_PUBLIC_YIELD_API_KEY!, }, body: JSON.stringify({ yieldId, address, arguments: amount ? { amount } : { useMaxAmount: true }, }), }); if (!response.ok) { throw new Error("Failed to create withdrawal"); } return response.json();}// Get balance for a yield positionexport async function getYieldBalance( yieldId: string, address: string): Promise<string> { const response = await fetch( `${YIELD_API_URL}/v1/yields/${yieldId}/balances?address=${address}`, { headers: { "Content-Type": "application/json", "X-API-KEY": process.env.NEXT_PUBLIC_YIELD_API_KEY!, }, } ); if (!response.ok) { return "0"; } const data = await response.json(); const activeBalance = data.balances?.find((b: any) => b.type === "active"); return activeBalance?.amount || "0";}// Get user's active positionsexport async function getActivePositions( address: string): Promise<YieldAction[]> { const response = await fetch( `${YIELD_API_URL}/v1/actions?address=${address}&limit=20`, { headers: { "Content-Type": "application/json", "X-API-KEY": process.env.NEXT_PUBLIC_YIELD_API_KEY!, }, } ); if (!response.ok) { return []; } const { items = [] } = await response.json(); // Group by yieldId and filter to active positions (no exit after enter) const byYield = new Map<string, YieldAction[]>(); for (const action of items) { const list = byYield.get(action.yieldId) || []; list.push(action); byYield.set(action.yieldId, list); } const active: YieldAction[] = []; for (const [, actions] of byYield) { const sorted = actions.sort( (a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime() ); const lastEnter = sorted.find((a) => a.intent === "enter"); const hasExit = sorted.some( (a) => a.intent === "exit" && lastEnter && new Date(a.createdAt) > new Date(lastEnter.createdAt) ); if (lastEnter && !hasExit) active.push(lastEnter); } return active;}
3
Build a yield component with deposit and withdraw
Create a component that displays yields, handles deposits, and shows active positions: