Documentation Index
Fetch the complete documentation index at: https://docs.yieldo.xyz/llms.txt
Use this file to discover all available pages before exploring further.
This guide walks through the complete deposit flow for integrating Yieldo into a frontend application.
Overview
User selects vault → Get quote → Approve token → Build tx → Send tx → Track status
The user only signs the approval (for ERC-20 deposits) and the deposit transaction itself. V3.2.0 does not require any EIP-712 intent signature — deposits are direct depositFor (same-chain) or depositForAvailable (cross-chain composer destination) calls.
Step 1: Select a Vault
Fetch available vaults and let the user choose one.
const response = await fetch('https://api.yieldo.xyz/v1/vaults');
const vaults = await response.json();
Step 2: Get a Quote
Once the user specifies a source chain, token, and amount, request a quote.
const quote = await fetch('https://api.yieldo.xyz/v1/quote', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
from_chain_id: 42161,
from_token: '0xaf88d065e77c8cC2239327C5EDb3A432268e5831',
from_amount: '1000000000',
vault_id: '8453:0xbeefe94c8ad530842bfe7d8b397938ffc1cb83b2',
user_address: userAddress,
}),
});
const quoteData = await quote.json();
The response contains:
estimate - Expected output amount, estimated shares, gas cost
approval - Token approval details (if needed)
route_options - Available bridge routes for cross-chain deposits (with bridge name, logo, estimated time, gas cost)
Step 3: Approve Token Spending
If quoteData.approval is not null, the user needs to approve the token first.
if (quoteData.approval) {
const tx = await walletClient.writeContract({
address: quoteData.approval.token_address,
abi: erc20Abi,
functionName: 'approve',
args: [quoteData.approval.spender_address, quoteData.approval.amount],
});
await publicClient.waitForTransactionReceipt({ hash: tx });
}
Tip: For native token deposits (e.g., ETH), the approval field will be null and you can skip this step.
Step 4: Build the Transaction
Submit the deposit details to get the final transaction. Optionally pass a preferred_bridge if the user selected a specific route.
const buildResponse = await fetch('https://api.yieldo.xyz/v1/quote/build', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
from_chain_id: 42161,
from_token: '0xaf88d065e77c8cC2239327C5EDb3A432268e5831',
from_amount: '1000000000',
vault_id: '8453:0xbeefe94c8ad530842bfe7d8b397938ffc1cb83b2',
user_address: userAddress,
preferred_bridge: 'across', // optional: user's selected route
partner_id: 'my-app', // optional: for attribution
partner_type: 2, // 0=direct, 1=kol, 2=wallet
}),
});
const buildData = await buildResponse.json();
Step 5: Send the Transaction
Send the transaction using the user’s wallet.
const txHash = await walletClient.sendTransaction({
to: buildData.transaction_request.to,
data: buildData.transaction_request.data,
value: BigInt(buildData.transaction_request.value),
chain: { id: buildData.transaction_request.chain_id },
gas: buildData.transaction_request.gas_limit
? BigInt(buildData.transaction_request.gas_limit)
: undefined,
});
Step 5b: Handle Two-Step Cross-Chain Deposits
For certain vault types (Midas, Veda, Custom, IPOR, Lido), the build response has two_step: true. LiFi Composer doesn’t natively understand these deposit interfaces, so we split the flow:
- Step 1 = bridge tokens to the user’s wallet on the destination chain (the main
transaction_request)
- Wait for LiFi to confirm the bridge is
DONE
- Step 2 = same-chain deposit on the destination, using
buildData.deposit_tx
if (buildData.two_step) {
// Step 1 already sent — poll until bridge completes
await pollStatus(txHash, buildData.tracking.from_chain_id, buildData.tracking.to_chain_id);
// Step 2: switch to destination chain + approve + deposit
const { deposit_tx } = buildData;
if (walletChainId !== deposit_tx.transaction_request.chain_id) {
await switchChain({ chainId: deposit_tx.transaction_request.chain_id });
}
if (deposit_tx.approval) {
const approveTx = await walletClient.writeContract({
address: deposit_tx.approval.token_address,
abi: erc20Abi,
functionName: 'approve',
args: [deposit_tx.approval.spender_address, BigInt(deposit_tx.approval.amount)],
});
await publicClient.waitForTransactionReceipt({ hash: approveTx });
}
const depositTxHash = await walletClient.sendTransaction({
to: deposit_tx.transaction_request.to,
data: deposit_tx.transaction_request.data,
value: BigInt(deposit_tx.transaction_request.value),
chain: { id: deposit_tx.transaction_request.chain_id },
});
}
The user’s tokens are always safe — they land in the user’s wallet after the bridge. Step 2 can be retried if anything fails.
Step 6: Track the Deposit
For cross-chain deposits, poll the status endpoint until the transfer completes.
async function pollStatus(txHash, fromChainId, toChainId) {
while (true) {
const res = await fetch(
`https://api.yieldo.xyz/v1/status?tx_hash=${txHash}&from_chain_id=${fromChainId}&to_chain_id=${toChainId}`
);
const status = await res.json();
if (status.status === 'DONE') {
console.log('Deposit complete!', status.receiving);
return status;
}
if (status.status === 'FAILED') {
throw new Error('Transfer failed');
}
await new Promise(r => setTimeout(r, 15000));
}
}
Complete Example
async function deposit(vaultId, fromChainId, fromToken, amount, userAddress) {
// 1. Get quote
const quote = await getQuote(fromChainId, fromToken, amount, vaultId, userAddress);
// 2. Approve if needed
if (quote.approval) {
await approveToken(quote.approval);
}
// 3. Build transaction
const build = await buildTransaction({
fromChainId, fromToken, amount, vaultId, userAddress,
});
// 4. Send transaction
const txHash = await sendTransaction(build.transaction_request);
// 5. Track (cross-chain only)
if (fromChainId !== quote.vault.chain_id) {
await pollStatus(txHash, fromChainId, quote.vault.chain_id);
}
return txHash;
}