> ## 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 Withdraw Example

> Redeem vault shares immediately with viem and the Amplify SDK

Redeem vault shares in a single transaction using `prepareWithdrawTxData` and viem’s wallet client. This script fetches the target vault, prepares the calldata with a slippage safeguard, submits the transaction, and waits for confirmation.

## Overview

* Discover a vault that supports withdrawals.
* Prepare withdrawal calldata with slippage tolerance.
* Submit and confirm the transaction with viem.
* Handle failures by surfacing the `APIError` payload.

## Prerequisites

* **Node.js >= 20**
* **viem >= 2.0.0**
* **@paxoslabs/amplify-sdk** installed and initialized (`initAmplifySDK` elsewhere in your app)
* RPC URL (Alchemy, Infura, etc.)
* Private key with gas and vault shares to redeem

<Callout type="warning">
  Never commit private keys. Use environment variables or a secrets manager in
  production.
</Callout>

## Complete Code Example

```ts theme={null}
/**
 * Viem Withdrawal Example
 *
 * Demonstrates complete withdrawal flow using viem (vanilla TypeScript):
 * 1. Approve withdrawal
 * 2. Execute withdraw transaction
 */
import {
  fetchSupportedAssets,
  prepareApproveWithdrawTxData,
  prepareWithdrawTxData,
  YieldType,
} from "@paxoslabs/amplify-sdk";
import { createPublicClient, createWalletClient, http } from "viem";
import { privateKeyToAccount } from "viem/accounts";
import { mainnet } from "viem/chains";

const CONFIG = {
  chainId: 1,
  yieldType: YieldType.PRIME,
  offerAmount: "5.0", // decimal string of the earn token to exchange
  slippage: 75, // Optional: 0.75% slippage tolerance in basis points
  rpcUrl:
    process.env.RPC_URL ?? "https://eth-mainnet.g.alchemy.com/v2/YOUR_KEY",
  privateKey: process.env.PRIVATE_KEY ?? "0x...",
};

async function withdraw() {
  // Step 1: Setup wallet client
  const account = privateKeyToAccount(CONFIG.privateKey as `0x${string}`);

  const publicClient = createPublicClient({
    chain: mainnet,
    transport: http(CONFIG.rpcUrl),
  });

  const walletClient = createWalletClient({
    account,
    chain: mainnet,
    transport: http(CONFIG.rpcUrl),
  });

  // Fetch supported assets to get the want asset address
  const supportedAssets = await fetchSupportedAssets({
    yieldType: CONFIG.yieldType,
  });

  const asset = supportedAssets[0];
  if (!asset) {
    throw new Error("No supported assets found for the selected yield type.");
  }

  const wantAssetAddress = asset.address as `0x${string}`;

  try {
    // Step 2: Approve withdrawal
    console.log("Step 1: Preparing approval transaction...");
    const approvalTx = await prepareApproveWithdrawTxData({
      chainId: CONFIG.chainId,
      wantAssetAddress,
      yieldType: CONFIG.yieldType,
    });

    console.log(`Approval target: ${approvalTx.address}`);
    console.log();

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

    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();

    // Step 3: Prepare and execute withdrawal transaction
    console.log("Step 2: Preparing withdrawal transaction...");
    const tx = await prepareWithdrawTxData({
      yieldType: CONFIG.yieldType,
      wantAssetAddress,
      offerAmount: CONFIG.offerAmount,
      chainId: CONFIG.chainId,
    });

    console.log("Submitting transaction...");
    const withdrawalHash = await walletClient.writeContract({ ...tx, account });
    console.log(`Withdrawal sent: ${withdrawalHash}`);

    console.log("Waiting for confirmation...");
    const withdrawalReceipt = await publicClient.waitForTransactionReceipt({
      hash: withdrawalHash,
    });
    if (withdrawalReceipt.status !== "success") {
      throw new Error(`Withdrawal reverted in tx ${withdrawalHash}`);
    }

    console.log(
      `✓ Withdrawal confirmed in block ${withdrawalReceipt.blockNumber}`
    );
    return withdrawalReceipt;
  } catch (error) {
    console.error();
    console.error("=".repeat(60));
    console.error("✗ Withdrawal failed");
    console.error("=".repeat(60));

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

    throw error;
  }
}

withdraw()
  .then(() => {
    process.exit(0);
  })
  .catch((error) => {
    console.error(error);
    process.exit(1);
  });
```

<Callout type="info">
  `prepareWithdrawTxData` throws `APIError` when a vault, token, or chain is
  unsupported. Log the `endpoint` and `cause` fields to help users fall back to
  alternative flows when liquidity is unavailable.
</Callout>
