> ## Documentation Index
> Fetch the complete documentation index at: https://docs.li.fi/llms.txt
> Use this file to discover all available pages before exploring further.

# Discover and Deposit

> End-to-end recipe: find the best yield vaults for a token using the Earn Data API, then deposit via Composer in a single transaction.

This recipe walks through a complete LI.FI Earn integration: use the Earn Data API to find the highest-yielding vaults for a specific token, display them to a user, and then execute a deposit via Composer.

<Note>
  **Two layers, one flow.** This recipe uses the **Earn Data API** for discovery and **Composer** for execution. The Earn Data API tells you *where* to deposit. Composer handles *how*.
</Note>

***

## Step 1: Find the Best USDC Vaults on Base

Query the Earn Data API for USDC vaults on Base, sorted by APY:

<CodeGroup>
  ```bash curl theme={"system"}
  curl -X GET 'https://earn.li.fi/v1/vaults?chainId=8453&asset=USDC&sortBy=apy&minTvlUsd=100000&limit=5'
  ```

  ```ts TypeScript theme={"system"}
  const discoverVaults = async (chainId: number, asset: string) => {
    const params = new URLSearchParams({
      chainId: String(chainId),
      asset,
      sortBy: 'apy',
      minTvlUsd: '100000', // Only vaults with $100k+ TVL
      limit: '5',
    });

    const response = await fetch(`https://earn.li.fi/v1/vaults?${params}`);
    const { data } = await response.json();
    return data;
  };

  const vaults = await discoverVaults(8453, 'USDC');
  ```
</CodeGroup>

***

## Step 2: Filter for Depositable Vaults

Not all vaults support deposits via Composer. Filter using the `isTransactional` flag:

```ts TypeScript theme={"system"}
const depositableVaults = vaults.filter((vault) => vault.isTransactional);

// Display to user
depositableVaults.forEach((vault) => {
  console.log(`${vault.name} (${vault.protocol.name})`);
  console.log(`  APY: ${(vault.analytics.apy.total * 100).toFixed(2)}%`);
  console.log(`  TVL: $${Number(vault.analytics.tvl.usd).toLocaleString()}`);
  console.log(`  30d avg APY: ${(vault.analytics.apy30d * 100).toFixed(2)}%`);
  console.log(`  Deposit token: ${vault.address}`);
});
```

<Tip>
  Use `apy30d` alongside `apy.total` to give users a sense of yield stability. A vault with a high current APY but low 30-day average may be experiencing a temporary spike.
</Tip>

***

## Step 3: Get a Composer Quote

When the user selects a vault, use its contract address as the `toToken` in a Composer quote request. This is the handoff from Earn to Composer.

<CodeGroup>
  ```bash curl theme={"system"}
  # User selected the first vault, deposit 100 USDC
  curl -X GET 'https://li.quest/v1/quote?fromChain=8453&toChain=8453&fromToken=0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913&toToken=0x7BfA7C4f149E7415b73bdeDfe609237e29CBF34A&fromAddress=0xYOUR_WALLET_ADDRESS&toAddress=0xYOUR_WALLET_ADDRESS&fromAmount=100000000'
  ```

  ```ts TypeScript theme={"system"}
  const depositIntoVault = async (
    vault: any,
    fromToken: string,
    fromAmount: string,
    userAddress: string
  ) => {
    const params = new URLSearchParams({
      fromChain: String(vault.chainId),
      toChain: String(vault.chainId),
      fromToken,
      toToken: vault.address, // Vault contract address triggers Composer deposit
      fromAddress: userAddress,
      toAddress: userAddress,
      fromAmount,
    });

    const response = await fetch(`https://li.quest/v1/quote?${params}`);
    return response.json();
  };

  // Deposit 100 USDC into the top vault
  const selectedVault = depositableVaults[0];
  const quote = await depositIntoVault(
    selectedVault,
    '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913', // USDC on Base
    '100000000', // 100 USDC (6 decimals)
    '0xYOUR_WALLET_ADDRESS'
  );

  console.log('Estimated output:', quote.estimate);
  console.log('Transaction to sign:', quote.transactionRequest);
  ```
</CodeGroup>

<Note>
  The Composer quote endpoint is `https://li.quest/v1/quote`. This is the Composer layer of LI.FI Earn, not the Earn Data API. See the [Composer API Integration Guide](/composer/guides/api-integration) for full details on parameters, token approvals, and transaction submission.
</Note>

***

## Step 4: Execute the Transaction

Submit the transaction from the quote response. See the [Composer API Integration Guide](/composer/guides/api-integration#send-the-transaction) for the full execution flow including token approvals and status tracking.

```ts TypeScript theme={"system"}
// Using ethers.js v6
import { ethers } from 'ethers';

const provider = new ethers.BrowserProvider(window.ethereum);
const signer = await provider.getSigner();

// Send the transaction from the Composer quote
const tx = await signer.sendTransaction(quote.transactionRequest);
console.log('Transaction sent:', tx.hash);

const receipt = await tx.wait();
console.log('Confirmed in block:', receipt.blockNumber);
```

***

## Step 5: Verify the Position

After the deposit confirms, use the Earn portfolio endpoint to verify the user's new position:

<CodeGroup>
  ```bash curl theme={"system"}
  curl -X GET 'https://earn.li.fi/v1/portfolio/0xYOUR_WALLET_ADDRESS/positions'
  ```

  ```ts TypeScript theme={"system"}
  const response = await fetch(
    `https://earn.li.fi/v1/portfolio/0xYOUR_WALLET_ADDRESS/positions`
  );
  const { positions } = await response.json();

  // Find the position in the vault we just deposited into
  const newPosition = positions.find(
    (pos) => pos.address?.toLowerCase() === selectedVault.address.toLowerCase()
  );

  if (newPosition) {
    const usd = newPosition.balanceUsd ?? 'N/A';
    const protocol = newPosition.protocolName ?? 'unknown';
    console.log(`Position: $${usd} in ${protocol}`);
  }
  ```
</CodeGroup>

***

## Cross-Chain Deposits

Vaults are chain-specific, but Composer handles cross-chain deposits seamlessly. To deposit from a different chain, change `fromChain` and `fromToken` in the quote request:

```ts TypeScript theme={"system"}
// Deposit ETH from Ethereum into a USDC vault on Base
// Note: fromChain differs from vault's chain. Composer handles the bridge automatically.
const params = new URLSearchParams({
  fromChain: '1',        // Ethereum (where the user's funds are)
  toChain: '8453',       // Base (where the vault lives)
  fromToken: '0x0000000000000000000000000000000000000000', // ETH (native)
  toToken: selectedVault.address,                           // Vault contract address on Base
  fromAddress: '0xYOUR_WALLET_ADDRESS',
  toAddress: '0xYOUR_WALLET_ADDRESS',
  fromAmount: '100000000000000000', // 0.1 ETH
});

const response = await fetch(`https://li.quest/v1/quote?${params}`);
const crossChainQuote = await response.json();
// Composer routes: bridge ETH to Base, swap to USDC, deposit into vault, all in one transaction
```

Composer's routing engine automatically determines the optimal bridge and swap path. See [Cross-Chain Compose](/composer/guides/cross-chain-compose) for details.

***

## Full Example

Here is the complete flow in a single function:

```ts TypeScript theme={"system"}
const discoverAndDeposit = async (
  chainId: number,
  asset: string,
  fromToken: string,
  fromAmount: string,
  userAddress: string
) => {
  // 1. Discover vaults
  const vaultParams = new URLSearchParams({
    chainId: String(chainId),
    asset,
    sortBy: 'apy',
    minTvlUsd: '100000',
    limit: '5',
  });
  const { data: vaults } = await fetch(
    `https://earn.li.fi/v1/vaults?${vaultParams}`
  ).then((r) => r.json());

  // 2. Filter for depositable vaults
  const depositable = vaults.filter((v) => v.isTransactional);
  if (depositable.length === 0) throw new Error('No depositable vaults found');

  // 3. Pick the highest-APY vault
  const bestVault = depositable[0];
  console.log(
    `Best vault: ${bestVault.name} at ${(bestVault.analytics.apy.total * 100).toFixed(2)}% APY`
  );

  // 4. Get Composer quote
  const quoteParams = new URLSearchParams({
    fromChain: String(chainId),
    toChain: String(chainId),
    fromToken,
    toToken: bestVault.address,
    fromAddress: userAddress,
    toAddress: userAddress,
    fromAmount,
  });
  const quote = await fetch(
    `https://li.quest/v1/quote?${quoteParams}`
  ).then((r) => r.json());

  return { vault: bestVault, quote };
};

// Usage
const { vault, quote } = await discoverAndDeposit(
  8453,
  'USDC',
  '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913',
  '100000000', // 100 USDC
  '0xYOUR_WALLET_ADDRESS'
);
```

***

## Related

<CardGroup cols={2}>
  <Card title="Earn API Reference" icon="code" href="/earn/guides/api-integration">
    Full endpoint reference with all parameters
  </Card>

  <Card title="Composer Vault Deposits" icon="book" href="/composer/recipes/vault-deposits">
    More vault deposit recipes with protocol-specific examples
  </Card>

  <Card title="Composer API Guide" icon="code" href="/composer/guides/api-integration">
    Full Composer integration guide including approvals and status tracking
  </Card>

  <Card title="Cross-Chain Compose" icon="bridge" href="/composer/guides/cross-chain-compose">
    Cross-chain deposit patterns and bridge selection
  </Card>
</CardGroup>
