> ## 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.

# Wagmi Withdraw Example

> Redeem Amplify vault shares in React using wagmi hooks

This React example pairs wagmi with `prepareWithdrawTxData` to offer immediate redemptions. The custom hook handles transaction preparation, submission, and receipt tracking so UI components can focus on user experience.

## Overview

* Fetch vault metadata (optionally cached with React Query or SWR).
* Prepare withdrawal calldata with slippage tolerance.
* Submit the transaction using wagmi’s `useWriteContract`.
* Surface transaction state with `useWaitForTransactionReceipt`.

## Prerequisites

* **React 18+**
* **wagmi >= 2.0.0** and **viem >= 2.0.0**
* **@paxoslabs/amplify-sdk** installed and initialized (`initAmplifySDK` called in a provider)
* React Query (optional) for data fetching
* Connected wallet with vault shares to redeem

## Withdrawal Hook

```tsx theme={null}
import { useCallback, useEffect, useState } from "react";
import { useWaitForTransactionReceipt, useWriteContract } from "wagmi";
import { prepareWithdrawTxData, type YieldType } from "@paxoslabs/amplify-sdk";
import type { Address } from "viem";

interface BulkWithdrawParams {
  yieldType: YieldType;
  shareAmount: string;
  wantAssetAddress: Address;
  chainId: number;
  userAddress: Address;
  slippage?: number;
}

export function useWithdraw() {
  const [error, setError] = useState<Error | null>(null);
  const [status, setStatus] = useState<
    "idle" | "preparing" | "submitting" | "confirming" | "success"
  >("idle");

  // Wagmi hooks for writing contracts
  const {
    writeContractAsync: writeApproval,
    data: approvalHash,
    isPending: isApprovingToken,
  } = useWriteContract();

  const {
    writeContractAsync,
    data: hash,
    isPending: isSubmitting,
  } = useWriteContract();

  // Wait for transaction confirmations
  const { isLoading: isWaitingForApproval } = useWaitForTransactionReceipt({
    hash: approvalHash,
  });

  const { isLoading: isConfirming } = useWaitForTransactionReceipt({
    hash,
    confirmations: 1,
    query: { enabled: Boolean(hash) },
  });

  /**
   * Approve deposit tokens
   */
  const approve = useCallback(
    async (params: ApproveParams) => {
      setError(null);

      try {
        // Prepare approval transaction
        const approvalTx = await prepareApproveWithdrawTxData({
          yieldType: params.yieldType,
          depositToken: params.depositToken,
          depositAmount: params.depositAmount,
          chainId: params.chainId,
        });

        // Execute approval using wagmi
        await writeApproval(approvalTx);

        // Update approval state after successful transaction
        setIsApproved(true);
      } catch (err) {
        const error = err instanceof Error ? err : new Error(String(err));
        setError(error);
        throw error;
      }
    },
    [writeApproval]
  );

  /**
   * Execute withdraw transaction
   */
  const withdraw = useCallback(
    async ({
      yieldType,
      shareAmount,
      wantAssetAddress,
      chainId,
      userAddress,
      slippage = 75,
    }: BulkWithdrawParams) => {
      setError(null);
      setStatus("preparing");

      try {
        const tx = await prepareWithdrawTxData({
          yieldType,
          shareAmount,
          wantAssetAddress,
          chainId,
          userAddress,
          slippage,
        });

        setStatus("submitting");
        const transactionHash = await writeContractAsync({
          ...tx,
          account: userAddress,
        });

        setStatus("confirming");
        return transactionHash;
      } catch (err) {
        const error = err instanceof Error ? err : new Error(String(err));
        setError(error);
        setStatus("idle");
        throw error;
      }
    },
    [writeContractAsync]
  );

  useEffect(() => {
    if (hash && !isSubmitting && !isConfirming) {
      setStatus("success");
    }
  }, [hash, isSubmitting, isConfirming]);

  return {
    bulkWithdraw,
    status,
    hash,
    error,
    isIdle: status === "idle",
    isSubmitting,
    isConfirming,
    isSuccess: status === "success",
  };
}
```

## Component Usage

```tsx theme={null}
import { useAccount } from "wagmi";
import { useQuery } from "@tanstack/react-query";
import { fetchVaults, YieldType } from "@paxoslabs/amplify-sdk";
import { mainnet } from "viem/chains";
import { useBulkWithdraw } from "./useBulkWithdraw";

export function WithdrawForm() {
  const { address, chainId } = useAccount();
  const { bulkWithdraw, status, error, hash } = useBulkWithdraw();

  const { data: vaults } = useQuery({
    queryKey: ["core-vaults", chainId],
    queryFn: () =>
      fetchVaults({ chainId: mainnet.id, yieldType: YieldType.CORE }),
    enabled: Boolean(address),
  });

  const vault = vaults?.[0];

  if (!address) {
    return <p>Connect a wallet to redeem shares.</p>;
  }

  if (!vault) {
    return <p>Loading vault metadata…</p>;
  }

  async function handleWithdraw() {
    await withdraw({
      yieldType: vault.yieldType,
      shareAmount: "5.0",
      wantAssetAddress: vault.depositTokenAddressId as `0x${string}`,
      chainId: vault.chainId,
      userAddress: address,
      slippage: 75,
    });
  }

  return (
    <section>
      <button
        disabled={status === "submitting" || status === "confirming"}
        onClick={handleBulkWithdraw}
      >
        {status === "submitting"
          ? "Submitting…"
          : status === "confirming"
          ? "Confirming…"
          : "Withdraw"}
      </button>

      {hash && (
        <p>
          Transaction hash:{" "}
          <a
            href={`https://etherscan.io/tx/${hash}`}
            target="_blank"
            rel="noreferrer"
          >
            {hash}
          </a>
        </p>
      )}
      {error && <p role="alert">Withdraw failed: {error.message}</p>}
    </section>
  );
}
```

<Callout type="info">
  `prepareWithdrawTxData` throws `APIError` when liquidity is
  unavailable or the vault is unsupported. Surface the `endpoint` and
  `statusCode` fields so users understand why the operation failed.
</Callout>
