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

# Viem Deposit Example

> Complete code example for depositing into vaults using viem

Complete deposit flow example using viem (vanilla TypeScript) and the Earn SDK.

## Overview

This example demonstrates how to:

* Check deposit approval status before depositing
* Approve deposit tokens when needed
* Execute deposit transactions with slippage protection
* Handle errors gracefully
* Use automatic vault discovery based on yield type and deposit token

## Prerequisites

Before running this example, ensure you have:

* **Node.js >= 20** installed
* **viem >= 2.0.0** installed
* **@paxoslabs/earn-sdk** installed
* Ethereum RPC URL (Alchemy, Infura, or similar)
* Private key for testing (use testnet or small amounts on mainnet)
* ETH for gas fees
* Deposit tokens (e.g., USDC)

<Warning>
  **Security**: Never commit private keys to version control. Use environment
  variables or secure key management solutions in production.
</Warning>

## Complete Code Example

```typescript theme={null}
/**
 * Viem Deposit Example
 *
 * Demonstrates complete deposit flow using viem (vanilla TypeScript):
 * 1. Check if approval is needed
 * 2. Approve deposit token if needed
 * 3. Execute deposit transaction
 */

import {
  isDepositSpendApproved,
  prepareApproveDepositToken,
  prepareDepositTransactionData,
} from "@paxoslabs/earn-sdk";
import type { Address } from "viem";
import { createPublicClient, createWalletClient, http } from "viem";
import { privateKeyToAccount } from "viem/accounts";
import { mainnet } from "viem/chains";

/**
 * Configuration for the deposit
 */
const config = {
  yieldType: "PRIME" as const, // Yield type: PRIME, TBILL, or LENDING
  depositToken: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48" as Address, // USDC on Ethereum
  depositAmount: "1000.0", // $1000 USDC (decimal string format)
  chainId: 1, // Ethereum mainnet
  slippage: 100, // 1% slippage tolerance (100 basis points). Defaults to 10 basis points
  // Replace with your private key for testing
  privateKey: process.env.PRIVATE_KEY || "0x...",
  // Replace with your RPC URL
  rpcUrl:
    process.env.RPC_URL || "https://eth-mainnet.g.alchemy.com/v2/YOUR_KEY",
};

/**
 * Execute complete deposit flow
 */
async function deposit() {
  console.log("=".repeat(60));
  console.log("Earn SDK Deposit Example (Viem)");
  console.log("=".repeat(60));
  console.log();

  // Step 1: Setup wallet client
  // Create account from private key
  const account = privateKeyToAccount(config.privateKey as `0x${string}`);

  // Create public client for reading blockchain data
  const publicClient = createPublicClient({
    chain: mainnet,
    transport: http(config.rpcUrl),
  });

  // Create wallet client for signing transactions
  const walletClient = createWalletClient({
    account,
    chain: mainnet,
    transport: http(config.rpcUrl),
  });

  console.log(`Wallet address: ${account.address}`);
  console.log(`Yield type: ${config.yieldType}`);
  console.log(`Deposit amount: ${config.depositAmount} USDC`);
  console.log(`Chain: ${mainnet.name} (${config.chainId})`);
  console.log();

  try {
    // Step 2: Check approval status
    console.log("Step 1: Checking approval status...");
    const isApproved = await isDepositSpendApproved({
      yieldType: config.yieldType,
      depositToken: config.depositToken,
      depositAmount: config.depositAmount,
      recipientAddress: account.address,
      chainId: config.chainId,
    });

    if (isApproved) {
      console.log("✓ Tokens already approved");
    } else {
      console.log("✗ Approval required");
    }
    console.log();

    // Step 3: Approve tokens if needed
    if (!isApproved) {
      console.log("Step 2: Preparing approval transaction...");

      // Prepare approval transaction data
      const approvalTx = await prepareApproveDepositToken({
        yieldType: config.yieldType,
        depositToken: config.depositToken,
        depositAmount: config.depositAmount,
        chainId: config.chainId,
      });

      console.log(`Approval target: ${approvalTx.address}`);
      console.log(`Approval amount: ${approvalTx.args[1]}`);
      console.log();

      // Execute approval transaction
      console.log("Executing approval transaction...");
      const approvalHash = await walletClient.writeContract(approvalTx);
      console.log(`Approval tx hash: ${approvalHash}`);
      console.log();

      // Wait for approval confirmation
      console.log("Waiting for approval confirmation...");
      const approvalReceipt = await publicClient.waitForTransactionReceipt({
        hash: approvalHash,
      });

      if (approvalReceipt.status === "success") {
        console.log(
          `✓ Approval confirmed in block ${approvalReceipt.blockNumber}`
        );
      } else {
        throw new Error("Approval transaction failed");
      }
      console.log();
    } else {
      console.log("Step 2: Skipping approval (already approved)");
      console.log();
    }

    // Step 4: Prepare deposit transaction
    console.log("Step 3: Preparing deposit transaction...");
    const depositTx = await prepareDepositTransactionData({
      yieldType: config.yieldType,
      recipientAddress: account.address,
      depositToken: config.depositToken,
      depositAmount: config.depositAmount,
      chainId: config.chainId,
      slippage: config.slippage, // Slippage protection
    });

    console.log(`Deposit contract: ${depositTx.address}`);
    console.log(`Deposit token: ${depositTx.args[0]}`);
    console.log(`Deposit amount: ${depositTx.args[1]}`);
    console.log(`Minimum shares: ${depositTx.args[2]}`); // Calculated based on slippage
    console.log();

    // Execute deposit transaction
    console.log("Executing deposit transaction...");
    const depositHash = await walletClient.writeContract(depositTx);
    console.log(`Deposit tx hash: ${depositHash}`);
    console.log();

    // Wait for deposit confirmation
    console.log("Waiting for deposit confirmation...");
    const depositReceipt = await publicClient.waitForTransactionReceipt({
      hash: depositHash,
    });

    if (depositReceipt.status === "success") {
      console.log(`✓ Deposit confirmed in block ${depositReceipt.blockNumber}`);
    } else {
      throw new Error("Deposit transaction failed");
    }
    console.log();

    // Success!
    console.log("=".repeat(60));
    console.log("✓ Deposit completed successfully!");
    console.log("=".repeat(60));
    console.log();
    console.log(`Transaction hash: ${depositReceipt.transactionHash}`);
    console.log(
      `View on Etherscan: https://etherscan.io/tx/${depositReceipt.transactionHash}`
    );

    return depositReceipt;
  } catch (error) {
    // Error handling
    console.error();
    console.error("=".repeat(60));
    console.error("✗ Deposit failed");
    console.error("=".repeat(60));

    if (error instanceof Error) {
      console.error(`Error: ${error.message}`);
    } else {
      console.error("Unknown error:", error);
    }

    throw error;
  }
}

// Execute deposit if run directly
deposit()
  .then(() => {
    process.exit(0);
  })
  .catch((error) => {
    console.error(error);
    process.exit(1);
  });
```

## What This Code Does

### 1. Setup Phase

* Creates viem wallet client from private key
* Creates public client for reading blockchain data
* Configures connection to Ethereum mainnet via RPC

### 2. Approval Check Phase

* Calls `isDepositSpendApproved()` to verify if tokens are already approved
* Checks allowance for the Teller contract to spend your deposit tokens

### 3. Approval Phase (if needed)

* Prepares approval transaction using `prepareApproveDepositToken()`
* Executes approval transaction with `walletClient.writeContract()`
* Waits for approval confirmation before proceeding

### 4. Deposit Phase

* Prepares deposit transaction using `prepareDepositTxData()`
* Automatically calculates minimum shares based on slippage tolerance
* Executes deposit transaction
* Waits for confirmation and reports success

## Key Features

### Automatic Vault Resolution

The SDK automatically finds the correct vault based on:

* **Yield type**: `PRIME`, `TBILL`, or `LENDING`
* **Deposit token address**: e.g., USDC (`0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48`)
* **Chain ID**: e.g., Ethereum mainnet (`1`)

No need to manually specify vault addresses or search for vault configurations!

### Slippage Protection

<Snippet file="v0.1.0/snippets/slippage-explanation.mdx" />

This example uses 1% slippage tolerance (100 basis points):

```typescript theme={null}
const depositTx = await prepareDepositTransactionData({
  // ... other params
  slippage: 100, // 1% = 100 basis points
});
```

### Approval-First Workflow

<Snippet file="v0.1.0/snippets/approval-workflow.mdx" />

## Configuration Options

### Change Deposit Amount

```typescript theme={null}
const config = {
  // ...
  depositAmount: "5000.0", // Change to $5000 USDC
};
```

### Change Yield Type

```typescript theme={null}
const config = {
  yieldType: "TBILL", // Switch to T-Bill vault
  // ...
};
```

### Change Slippage Tolerance

```typescript theme={null}
const config = {
  // ...
  slippage: 50, // 0.5% slippage (50 basis points)
};
```

### Use Different Token

```typescript theme={null}
const config = {
  depositToken: "0x6B175474E89094C44Da98b954EedeAC495271d0F", // DAI
  // ...
};
```

## Expected Output

```
============================================================
Earn SDK Deposit Example (Viem)
============================================================

Wallet address: 0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb
Yield type: PRIME
Deposit amount: 1000.0 USDC
Chain: Ethereum (1)

Step 1: Checking approval status...
✗ Approval required

Step 2: Preparing approval transaction...
Approval target: 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48
Approval amount: 1000000000

Executing approval transaction...
Approval tx hash: 0x...

Waiting for approval confirmation...
✓ Approval confirmed in block 12345678

Step 3: Preparing deposit transaction...
Deposit contract: 0x2234567890123456789012345678901234567890
Deposit token: 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48
Deposit amount: 1000000000
Minimum shares: 990000000

Executing deposit transaction...
Deposit tx hash: 0x...

Waiting for deposit confirmation...
✓ Deposit confirmed in block 12345679

============================================================
✓ Deposit completed successfully!
============================================================

Transaction hash: 0x...
View on Etherscan: https://etherscan.io/tx/0x...
```

## Troubleshooting

### "Approval transaction failed"

**Possible causes**:

* Insufficient ETH for gas fees
* Incorrect deposit token address
* RPC URL not working or rate limited

**Solutions**:

1. Check your ETH balance: `await publicClient.getBalance({ address: account.address })`
2. Verify deposit token address is correct
3. Test RPC connection with a simple call

### "Deposit transaction failed"

**Possible causes**:

* Approval not successful or pending
* Insufficient deposit token balance
* Slippage tolerance too low (exchange rate changed)

**Solutions**:

1. Verify approval was confirmed before depositing
2. Check token balance: Use `publicClient.readContract()` with ERC20 `balanceOf`
3. Increase slippage tolerance if exchange rate moved

### "Vault not found"

**Possible causes**:

* Invalid yield type
* Deposit token not supported on this chain
* Incorrect chain ID

**Solutions**:

1. Verify yield type is `PRIME`, `TBILL`, or `LENDING`
2. Check that deposit token is supported using vault discovery API
3. Ensure chain ID matches the network you're connected to

### "API request timed out"

**Possible causes**:

* Network connectivity issues
* Earn API server not reachable
* API server overloaded

**Solutions**:

1. Check network connection
2. Verify API is running (default: `http://localhost:8500`)
3. Try again after a few seconds with exponential backoff

## Next Steps

* **React Integration**: See the [wagmi deposit example](/v0.1.0/intro/products/earn/developers/examples/wagmi-deposit) for React integration patterns
* **API Documentation**: Read the [deposits API documentation](/v0.1.0/intro/products/earn/developers/functions/deposit) for detailed parameter descriptions
* **Gas Optimization**: Learn about [permit-based deposits](/v0.1.0/intro/products/earn/developers/functions/deposit-with-permit) to save on gas fees
