> For the complete documentation index, see [llms.txt](https://docs.yield.fi/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.yield.fi/earn-with-yieldfi/integration-sdk/examples-and-guides/contract-integration.md).

# Contract Integration

Examples for integrating with YieldFi v3 smart contracts. The v3 contracts use a Manager contract for deposits/redemptions and Vault contracts (ERC-4626) for vault tokens.

### Getting V3 Contract ABIs

V3 contract ABIs are included in the SDK package:

```typescript
import ManagerV3ABI from "yieldfi-sdk/abis/v3/Manager.json";
import VaultABI from "yieldfi-sdk/abis/v3/Vault.json";
```

Or import from the abis directory in your project:

```typescript
import ManagerV3ABI from "./abis/v3/Manager.json";
import VaultABI from "./abis/v3/Vault.json";
```

### Deposit to Vault

Deposit assets to a v3 vault using the Manager contract.

<pre class="language-typescript"><code class="lang-typescript">import {
  connectManagerV3,
  connectVault,
  getContractAddresses,
  Chain,
} from "yieldfi-sdk";
import { ethers } from "ethers";
import ManagerV3ABI from "yieldfi-sdk/abis/v3/Manager.json";

// Request Redemption (V3)

<strong>//Request redemption from a v3 vault. Shares are locked in a queue until processed.
</strong>
<strong>//### Using Wagmi
</strong>
import { connectManagerV3, getContractAddresses, Chain } from "yieldfi-sdk";
import { ethers } from "ethers";
import { useAccount, useWalletClient } from "wagmi";
import ManagerV3ABI from "yieldfi-sdk/abis/v3/Manager.json";

function RedemptionButton() {
  const { address } = useAccount();
  const { data: walletClient } = useWalletClient();

  const requestRedemption = async (
    vaultAddress: string,
    shares: bigint,
    receiver?: string
  ) => {
    if (!walletClient || !address) {
      throw new Error("Wallet not connected");
    }

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

    const contracts = getContractAddresses(Chain.ETHEREUM);
    const managerV3 = connectManagerV3(contracts.manager, ManagerV3ABI, signer);

    // Request redemption (shares are locked, not burned)
    const redeemTx = await managerV3.requestRedemption(
      vaultAddress,
      shares,
      address, // Owner
      receiver || address // Receiver (defaults to owner)
    );

    const receipt = await redeemTx.wait();
    console.log(`Redemption requested: ${receipt.hash}`);
    return receipt;
  };

  return (
    &#x3C;button
      onClick={() =>
        requestRedemption(
          "0x5bE91d34FeFbB7554497a74e25dC6df96bFef5DB",
          ethers.parseUnits("100", 18)
        )
      }
    >
      Request Redemption
    &#x3C;/button>
  );
}
</code></pre>

#### Using Browser Provider

```typescript
import { connectManagerV3, getContractAddresses, Chain } from "yieldfi-sdk";
import { ethers } from "ethers";
import ManagerV3ABI from "yieldfi-sdk/abis/v3/Manager.json";

async function requestRedemptionV3(
  vaultAddress: string,
  shares: bigint,
  receiver?: string
) {
  if (!window.ethereum) {
    throw new Error("No wallet found");
  }

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

  const contracts = getContractAddresses(Chain.ETHEREUM);
  const managerV3 = connectManagerV3(contracts.manager, ManagerV3ABI, signer);

  // Request redemption (shares are locked, not burned)
  const redeemTx = await managerV3.requestRedemption(
    vaultAddress,
    shares,
    userAddress, // Owner
    receiver || userAddress // Receiver (defaults to owner)
  );

  const receipt = await redeemTx.wait();
  console.log(`Redemption requested: ${receipt.hash}`);
  return receipt;
}

// Usage
requestRedemptionV3(
  "0x5bE91d34FeFbB7554497a74e25dC6df96bFef5DB",
  ethers.parseUnits("100", 18)
);
```

### Check Vault Balance (V3)

Check vault token balance and convert between shares and assets.

#### Using Wagmi

```typescript
import { connectVault } from "yieldfi-sdk";
import { ethers } from "ethers";
import { useAccount, useWalletClient } from "wagmi";
import VaultABI from "yieldfi-sdk/abis/v3/Vault.json";

function VaultBalance() {
  const { address } = useAccount();
  const { data: walletClient } = useWalletClient();

  const checkVaultBalance = async (vaultAddress: string) => {
    if (!walletClient || !address) {
      throw new Error("Wallet not connected");
    }

    const provider = new ethers.BrowserProvider(walletClient);
    const vault = connectVault(vaultAddress, VaultABI, provider);

    // Get user's share balance
    const shares = await vault.balanceOf(address);
    console.log(`Shares: ${ethers.formatUnits(shares, 18)}`);

    // Get total assets and supply
    const totalAssets = await vault.totalAssets();
    const totalSupply = await vault.totalSupply();
    console.log(`Total Assets: ${ethers.formatUnits(totalAssets, 6)}`);
    console.log(`Total Supply: ${ethers.formatUnits(totalSupply, 18)}`);

    // Convert shares to assets (ERC-4626 method)
    const assets = await vault.convertToAssets(shares);
    console.log(`Your Assets: ${ethers.formatUnits(assets, 6)}`);

    // Get asset address
    const assetAddress = await vault.asset();
    console.log(`Asset Address: ${assetAddress}`);

    // Get vault info
    const name = await vault.name();
    const symbol = await vault.symbol();
    const decimals = await vault.decimals();
    console.log(`Vault: ${name} (${symbol}) - ${decimals} decimals`);

    return {
      shares,
      assets,
      totalAssets,
      totalSupply,
      assetAddress,
    };
  };

  return (
    <button
      onClick={() =>
        checkVaultBalance("0x5bE91d34FeFbB7554497a74e25dC6df96bFef5DB")
      }
    >
      Check Balance
    </button>
  );
}
```

#### Using Browser Provider

```typescript
import { connectVault } from "yieldfi-sdk";
import { ethers } from "ethers";
import VaultABI from "yieldfi-sdk/abis/v3/Vault.json";

async function checkVaultBalance(vaultAddress: string) {
  if (!window.ethereum) {
    throw new Error("No wallet found");
  }

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

  // Connect to Vault contract (ERC-4626)
  const vault = connectVault(vaultAddress, VaultABI, provider);

  // Get user's share balance
  const shares = await vault.balanceOf(userAddress);
  console.log(`Shares: ${ethers.formatUnits(shares, 18)}`);

  // Get total assets and supply
  const totalAssets = await vault.totalAssets();
  const totalSupply = await vault.totalSupply();
  console.log(`Total Assets: ${ethers.formatUnits(totalAssets, 6)}`);
  console.log(`Total Supply: ${ethers.formatUnits(totalSupply, 18)}`);

  // Convert shares to assets (ERC-4626 method)
  const assets = await vault.convertToAssets(shares);
  console.log(`Your Assets: ${ethers.formatUnits(assets, 6)}`);

  // Get asset address
  const assetAddress = await vault.asset();
  console.log(`Asset Address: ${assetAddress}`);

  // Get vault info
  const name = await vault.name();
  const symbol = await vault.symbol();
  const decimals = await vault.decimals();
  console.log(`Vault: ${name} (${symbol}) - ${decimals} decimals`);

  return {
    shares,
    assets,
    totalAssets,
    totalSupply,
    assetAddress,
  };
}

// Usage
checkVaultBalance("0x5bE91d34FeFbB7554497a74e25dC6df96bFef5DB");
```

### Check Redemption Queue (V3)

Check redemption queue status and entries.

#### Using Wagmi

```typescript
import { connectManagerV3, getContractAddresses, Chain } from "yieldfi-sdk";
import { ethers } from "ethers";
import { useWalletClient } from "wagmi";
import ManagerV3ABI from "yieldfi-sdk/abis/v3/Manager.json";

function RedemptionQueue() {
  const { data: walletClient } = useWalletClient();

  const checkRedemptionQueue = async (vaultAddress: string) => {
    if (!walletClient) {
      throw new Error("Wallet not connected");
    }

    const provider = new ethers.BrowserProvider(walletClient);
    const contracts = getContractAddresses(Chain.ETHEREUM);
    const managerV3 = connectManagerV3(contracts.manager, ManagerV3ABI, provider);

    // Get queue length
    const queueLength = await managerV3.getRedemptionQueueLength(vaultAddress);
    console.log(`Redemption Queue Length: ${queueLength}`);

    // Get standard debt (total locked shares)
    const standardDebt = await managerV3.getStandardDebt(vaultAddress);
    console.log(`Standard Debt (Locked Shares): ${ethers.formatUnits(standardDebt, 18)}`);

    // Get next queue index
    const nextIndex = await managerV3.nextQueueIndex(vaultAddress);
    console.log(`Next Queue Index: ${nextIndex}`);

    // Get a specific queue entry
    if (queueLength > 0n) {
      const queueEntry = await managerV3.getRedemptionQueueEntry(vaultAddress, 0);
      console.log(`Queue Entry 0:`);
      console.log(`  Owner: ${queueEntry.owner}`);
      console.log(`  Receiver: ${queueEntry.receiver}`);
      console.log(`  Locked Shares: ${ethers.formatUnits(queueEntry.lockedShares, 18)}`);
      console.log(`  NAV at Request: ${ethers.formatUnits(queueEntry.navAtRequest, 18)}`);
      console.log(`  Timestamp: ${new Date(Number(queueEntry.timestamp) * 1000).toLocaleString()}`);
    }

    return {
      queueLength,
      standardDebt,
      nextIndex,
    };
  };

  return (
    <button
      onClick={() =>
        checkRedemptionQueue("0x5bE91d34FeFbB7554497a74e25dC6df96bFef5DB")
      }
    >
      Check Queue
    </button>
  );
}
```

#### Using Browser Provider

```typescript
import { connectManagerV3, getContractAddresses, Chain } from "yieldfi-sdk";
import { ethers } from "ethers";
import ManagerV3ABI from "yieldfi-sdk/abis/v3/Manager.json";

async function checkRedemptionQueue(vaultAddress: string) {
  if (!window.ethereum) {
    throw new Error("No wallet found");
  }

  const provider = new ethers.BrowserProvider(window.ethereum);
  const contracts = getContractAddresses(Chain.ETHEREUM);
  const managerV3 = connectManagerV3(contracts.manager, ManagerV3ABI, provider);

  // Get queue length
  const queueLength = await managerV3.getRedemptionQueueLength(vaultAddress);
  console.log(`Redemption Queue Length: ${queueLength}`);

  // Get standard debt (total locked shares)
  const standardDebt = await managerV3.getStandardDebt(vaultAddress);
  console.log(`Standard Debt (Locked Shares): ${ethers.formatUnits(standardDebt, 18)}`);

  // Get next queue index
  const nextIndex = await managerV3.nextQueueIndex(vaultAddress);
  console.log(`Next Queue Index: ${nextIndex}`);

  // Get a specific queue entry
  if (queueLength > 0n) {
    const queueEntry = await managerV3.getRedemptionQueueEntry(vaultAddress, 0);
    console.log(`Queue Entry 0:`);
    console.log(`  Owner: ${queueEntry.owner}`);
    console.log(`  Receiver: ${queueEntry.receiver}`);
    console.log(`  Locked Shares: ${ethers.formatUnits(queueEntry.lockedShares, 18)}`);
    console.log(`  NAV at Request: ${ethers.formatUnits(queueEntry.navAtRequest, 18)}`);
    console.log(`  Timestamp: ${new Date(Number(queueEntry.timestamp) * 1000).toLocaleString()}`);
  }

  return {
    queueLength,
    standardDebt,
    nextIndex,
  };
}

// Usage
checkRedemptionQueue("0x5bE91d34FeFbB7554497a74e25dC6df96bFef5DB");
```

### Cancel Redemption (V3)

Cancel a pending redemption request.

#### Using Wagmi

```typescript
import { connectManagerV3, getContractAddresses, Chain } from "yieldfi-sdk";
import { ethers } from "ethers";
import { useAccount, useWalletClient } from "wagmi";
import ManagerV3ABI from "yieldfi-sdk/abis/v3/Manager.json";

function CancelRedemptionButton() {
  const { address } = useAccount();
  const { data: walletClient } = useWalletClient();

  const cancelRedemption = async (vaultAddress: string, queueIndex: bigint) => {
    if (!walletClient || !address) {
      throw new Error("Wallet not connected");
    }

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

    const contracts = getContractAddresses(Chain.ETHEREUM);
    const managerV3 = connectManagerV3(contracts.manager, ManagerV3ABI, signer);

    // Cancel redemption (unlocks shares)
    const cancelTx = await managerV3.cancelRedemption(vaultAddress, queueIndex);
    const receipt = await cancelTx.wait();

    console.log(`Redemption cancelled: ${receipt.hash}`);
    return receipt;
  };

  return (
    <button onClick={() => cancelRedemption(vaultAddress, queueIndex)}>
      Cancel Redemption
    </button>
  );
}
```

#### Using Browser Provider

```typescript
import { connectManagerV3, getContractAddresses, Chain } from "yieldfi-sdk";
import { ethers } from "ethers";
import ManagerV3ABI from "yieldfi-sdk/abis/v3/Manager.json";

async function cancelRedemption(vaultAddress: string, queueIndex: bigint) {
  if (!window.ethereum) {
    throw new Error("No wallet found");
  }

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

  const contracts = getContractAddresses(Chain.ETHEREUM);
  const managerV3 = connectManagerV3(contracts.manager, ManagerV3ABI, signer);

  // Cancel redemption (unlocks shares)
  const cancelTx = await managerV3.cancelRedemption(vaultAddress, queueIndex);
  const receipt = await cancelTx.wait();

  console.log(`Redemption cancelled: ${receipt.hash}`);
  return receipt;
}

// Usage
cancelRedemption(
  "0x5bE91d34FeFbB7554497a74e25dC6df96bFef5DB",
  0n // Queue index
);
```

### Process Redemption (V3) - Admin/Operator Only

Process a redemption from the queue. This is typically called by vault operators.

#### Using Wagmi

```typescript
import { connectManagerV3, getContractAddresses, Chain } from "yieldfi-sdk";
import { ethers } from "ethers";
import { useAccount, useWalletClient } from "wagmi";
import ManagerV3ABI from "yieldfi-sdk/abis/v3/Manager.json";

function ProcessRedemptionButton() {
  const { address } = useAccount();
  const { data: walletClient } = useWalletClient();

  const processRedemption = async (
    vaultAddress: string,
    queueIndex: bigint,
    gasFeeShares: bigint = 0n
  ) => {
    if (!walletClient || !address) {
      throw new Error("Wallet not connected");
    }

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

    const contracts = getContractAddresses(Chain.ETHEREUM);
    const managerV3 = connectManagerV3(contracts.manager, ManagerV3ABI, signer);

    // Process redemption (burns locked shares, transfers assets)
    const processTx = await managerV3.processRedemption(
      vaultAddress,
      queueIndex,
      gasFeeShares
    );

    const receipt = await processTx.wait();
    console.log(`Redemption processed: ${receipt.hash}`);
    return receipt;
  };

  return (
    <button
      onClick={() => processRedemption(vaultAddress, queueIndex, 0n)}
    >
      Process Redemption
    </button>
  );
}
```

#### Using Browser Provider

```typescript
import { connectManagerV3, getContractAddresses, Chain } from "yieldfi-sdk";
import { ethers } from "ethers";
import ManagerV3ABI from "yieldfi-sdk/abis/v3/Manager.json";

async function processRedemption(
  vaultAddress: string,
  queueIndex: bigint,
  gasFeeShares: bigint = 0n
) {
  if (!window.ethereum) {
    throw new Error("No wallet found");
  }

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

  const contracts = getContractAddresses(Chain.ETHEREUM);
  const managerV3 = connectManagerV3(contracts.manager, ManagerV3ABI, signer);

  // Process redemption (burns locked shares, transfers assets)
  const processTx = await managerV3.processRedemption(
    vaultAddress,
    queueIndex,
    gasFeeShares
  );

  const receipt = await processTx.wait();
  console.log(`Redemption processed: ${receipt.hash}`);
  return receipt;
}

// Usage (operator only)
processRedemption(
  "0x5bE91d34FeFbB7554497a74e25dC6df96bFef5DB",
  0n, // Queue index
  0n // No gas fee
);
```

### Complete V3 Integration Example

Complete example showing deposit, balance check, and redemption flow using wagmi:

```typescript
import {
  connectManagerV3,
  connectVault,
  getContractAddresses,
  Chain,
} from "yieldfi-sdk";
import { ethers } from "ethers";
import { useAccount, useWalletClient } from "wagmi";
import ManagerV3ABI from "yieldfi-sdk/abis/v3/Manager.json";
import VaultABI from "yieldfi-sdk/abis/v3/Vault.json";

function VaultOperations() {
  const { address } = useAccount();
  const { data: walletClient } = useWalletClient();

  const completeV3VaultFlow = async (
    vaultAddress: string,
    assetAddress: string
  ) => {
    if (!walletClient || !address) {
      throw new Error("Wallet not connected");
    }

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

    const contracts = getContractAddresses(Chain.ETHEREUM);

    // Connect to contracts
    const managerV3 = connectManagerV3(contracts.manager, ManagerV3ABI, signer);
    const vault = connectVault(vaultAddress, VaultABI, provider);
    const assetToken = new ethers.Contract(
      assetAddress,
      [
        "function approve(address spender, uint256 amount) returns (bool)",
        "function balanceOf(address account) view returns (uint256)",
        "function decimals() view returns (uint8)",
      ],
      signer
    );

    // 1. Check current vault balance
    const currentShares = await vault.balanceOf(address);
    const currentAssets = await vault.convertToAssets(currentShares);
    console.log(`Current Vault Balance:`);
    console.log(`  Shares: ${ethers.formatUnits(currentShares, 18)}`);
    console.log(`  Assets: ${ethers.formatUnits(currentAssets, 6)}`);

    // 2. Deposit assets
    const depositAmount = ethers.parseUnits("100", 6); // 100 USDC
    const assetBalance = await assetToken.balanceOf(address);

    if (assetBalance < depositAmount) {
      console.log("Insufficient asset balance");
      return;
    }

    // Calculate minimum shares with slippage protection
    const previewShares = await vault.previewDeposit(depositAmount);
    const minShares = (previewShares * 95n) / 100n; // 5% slippage tolerance

    // Approve and deposit
    const approveTx = await assetToken.approve(managerV3.target, depositAmount);
    await approveTx.wait();

    const depositTx = await managerV3.deposit(
      vaultAddress,
      assetAddress,
      depositAmount,
      address,
      minShares,
      ethers.ZeroHash // referralCode
    );
    await depositTx.wait();
    console.log(`Deposit successful: ${depositTx.hash}`);

    // 3. Check new balance
    const newShares = await vault.balanceOf(address);
    const newAssets = await vault.convertToAssets(newShares);
    console.log(`New Vault Balance:`);
    console.log(`  Shares: ${ethers.formatUnits(newShares, 18)}`);
    console.log(`  Assets: ${ethers.formatUnits(newAssets, 6)}`);

    // 4. Request redemption (redeem half)
    const redeemShares = newShares / 2n;
    const redeemTx = await managerV3.requestRedemption(
      vaultAddress,
      redeemShares,
      address,
      address
    );
    await redeemTx.wait();
    console.log(`Redemption requested: ${redeemTx.hash}`);

    // 5. Check redemption queue
    const queueLength = await managerV3.getRedemptionQueueLength(vaultAddress);
    console.log(`Redemption Queue Length: ${queueLength}`);

    // 6. Check updated balance (shares are locked, not burned)
    const lockedShares = await vault.lockedShares(address);
    const activeShares = await vault.balanceOf(address);
    console.log(`Active Shares: ${ethers.formatUnits(activeShares, 18)}`);
    console.log(`Locked Shares: ${ethers.formatUnits(lockedShares, 18)}`);

    // 7. Cancel redemption (optional)
    if (queueLength > 0n) {
      const cancelTx = await managerV3.cancelRedemption(
        vaultAddress,
        queueLength - 1n
      );
      await cancelTx.wait();
      console.log(`Redemption cancelled: ${cancelTx.hash}`);
    }
  };

  return (
    <div>
      <button
        onClick={() =>
          completeV3VaultFlow(
            "0x5bE91d34FeFbB7554497a74e25dC6df96bFef5DB",
            "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"
          )
        }
      >
        Complete Vault Flow
      </button>
    </div>
  );
}
```

#### Using Browser Provider Directly

```typescript
import {
  connectManagerV3,
  connectVault,
  getContractAddresses,
  Chain,
} from "yieldfi-sdk";
import { ethers } from "ethers";
import ManagerV3ABI from "yieldfi-sdk/abis/v3/Manager.json";
import VaultABI from "yieldfi-sdk/abis/v3/Vault.json";

async function completeV3VaultFlow() {
  if (!window.ethereum) {
    throw new Error("No wallet found");
  }

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

  const contracts = getContractAddresses(Chain.ETHEREUM);
  const vaultAddress = "0x5bE91d34FeFbB7554497a74e25dC6df96bFef5DB";
  const assetAddress = "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"; // USDC

  // Connect to contracts
  const managerV3 = connectManagerV3(contracts.manager, ManagerV3ABI, signer);
  const vault = connectVault(vaultAddress, VaultABI, provider);
  const assetToken = new ethers.Contract(
    assetAddress,
    [
      "function approve(address spender, uint256 amount) returns (bool)",
      "function balanceOf(address account) view returns (uint256)",
    ],
    signer
  );

  // 1. Check current vault balance
  const currentShares = await vault.balanceOf(userAddress);
  const currentAssets = await vault.convertToAssets(currentShares);
  console.log(`Current Vault Balance:`);
  console.log(`  Shares: ${ethers.formatUnits(currentShares, 18)}`);
  console.log(`  Assets: ${ethers.formatUnits(currentAssets, 6)}`);

  // 2. Deposit assets
  const depositAmount = ethers.parseUnits("100", 6);
  const assetBalance = await assetToken.balanceOf(userAddress);

  if (assetBalance < depositAmount) {
    console.log("Insufficient asset balance");
    return;
  }

  // Calculate minimum shares with slippage protection
  const previewShares = await vault.previewDeposit(depositAmount);
  const minShares = (previewShares * 95n) / 100n; // 5% slippage tolerance

  // Approve and deposit
  await assetToken.approve(managerV3.target, depositAmount);
  const depositTx = await managerV3.deposit(
    vaultAddress,
    assetAddress,
    depositAmount,
    userAddress,
    minShares,
    ethers.ZeroHash
  );
  await depositTx.wait();
  console.log(`Deposit successful: ${depositTx.hash}`);

  // 3. Check new balance
  const newShares = await vault.balanceOf(userAddress);
  const newAssets = await vault.convertToAssets(newShares);
  console.log(`New Vault Balance:`);
  console.log(`  Shares: ${ethers.formatUnits(newShares, 18)}`);
  console.log(`  Assets: ${ethers.formatUnits(newAssets, 6)}`);

  // 4. Request redemption
  const redeemShares = newShares / 2n;
  const redeemTx = await managerV3.requestRedemption(
    vaultAddress,
    redeemShares,
    userAddress,
    userAddress
  );
  await redeemTx.wait();
  console.log(`Redemption requested: ${redeemTx.hash}`);

  // 5. Check redemption queue
  const queueLength = await managerV3.getRedemptionQueueLength(vaultAddress);
  console.log(`Redemption Queue Length: ${queueLength}`);

  // 6. Check locked shares
  const lockedShares = await vault.lockedShares(userAddress);
  const activeShares = await vault.balanceOf(userAddress);
  console.log(`Active Shares: ${ethers.formatUnits(activeShares, 18)}`);
  console.log(`Locked Shares: ${ethers.formatUnits(lockedShares, 18)}`);
}

completeV3VaultFlow();
```

### V3 Contract Features

#### Manager V3 Contract

* **Deposit**: Deposit assets to vaults with slippage protection (`minShares`)
* **Request Redemption**: Request redemption (shares are locked, not burned)
* **Cancel Redemption**: Cancel pending redemption requests
* **Process Redemption**: Process redemptions from queue (operator only)
* **Redemption Queue**: Query queue entries and status

#### Vault Contract (ERC-4626)

* **Standard ERC-4626**: Full ERC-4626 vault interface
* **Share Locking**: Shares can be locked for redemption requests
* **Asset Conversion**: `convertToAssets()` and `convertToShares()` methods
* **Preview Functions**: Preview deposit/redeem amounts

### Getting Contract Addresses

```typescript
import { getContractAddresses, Chain } from "yieldfi-sdk";

const contracts = getContractAddresses(Chain.ETHEREUM);
console.log(`Manager V3: ${contracts.manager}`);

// Vault addresses are specific to each vault
// Get them from the Vault API or registry
```

### Type Safety

The SDK provides full TypeScript types for v3 contracts:

```typescript
import type { ManagerV3, VaultContract } from "yieldfi-sdk";
import { Contract } from "ethers";
import { useWalletClient } from "wagmi";

function TypedContractExample() {
  const { data: walletClient } = useWalletClient();

  const useTypedContracts = async () => {
    if (!walletClient) return;

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

    const managerV3 = new Contract(
      contracts.manager,
      ManagerV3ABI,
      signer
    ) as unknown as ManagerV3;

    const vault = new Contract(
      vaultAddress,
      VaultABI,
      provider
    ) as unknown as VaultContract;

    // Full type safety and IntelliSense
    await managerV3.deposit(/* ... */);
    await vault.balanceOf(/* ... */);
  };
}
```

### Wallet Integration Best Practices

#### Always Check Wallet Connection

```typescript
if (!window.ethereum) {
  throw new Error("Please install a wallet like MetaMask");
}

// Or with wagmi
const { isConnected } = useAccount();
if (!isConnected) {
  throw new Error("Please connect your wallet");
}
```

#### Handle User Rejection

```typescript
try {
  const tx = await managerV3.deposit(/* ... */);
  await tx.wait();
} catch (error: any) {
  if (error.code === 4001) {
    // User rejected the transaction
    console.log("Transaction rejected by user");
  } else {
    throw error;
  }
}
```

#### Request Account Access

```typescript
// Request account access if needed
await window.ethereum.request({ method: "eth_requestAccounts" });

// Or with wagmi, use useConnect hook
const { connect } = useConnect();
```
