Skip to main content
This guide demonstrates complete withdrawal flows to redeem vault shares for underlying tokens.
Withdrawals follow a two-step process:
  1. Approve - Authorize the vault to spend your shares
  2. Withdraw - Redeem shares for the underlying token

Prerequisites

  • Node.js 22+
  • Amplify API key from Paxos Labs
  • SDK initialized with initAmplifySDK()
  • Vault shares to redeem

Installation

pnpm add @paxoslabs/amplify-sdk @privy-io/react-auth viem @tanstack/react-query

Complete Examples

useWithdraw Hook

// src/hooks/useWithdraw.ts
import { , ,  } from "react";
import {  } from "viem";
import {
  ,
  ,
  type ,
} from "@paxoslabs/amplify-sdk";

declare const : () => { : (: any) => <string> };
declare const : () => { : <{ : string }> };

interface WithdrawParams {
  : ;
  : string;
  : `0x${string}`;
  : number;
  ?: number;
}

export function () {
  const {  } = ();
  const {  } = ();
  const  = (() => .(), []);

  const [, ] = <`0x${string}` | null>(null);
  const [, ] = <
    "idle" | "approving" | "withdrawing" | "success"
  >("idle");
  const [, ] = <Error | null>(null);

  const  = (
    async ({
      ,
      ,
      ,
      ,
       = 75,
    }: WithdrawParams) => {
      if (!) {
        throw new ("Connect a Privy wallet before withdrawing.");
      }

      (null);
      (null);

      try {
        // Step 1: Approve withdrawal
        ("approving");
        const  = await ({
          ,
          ,
          ,
        });

        await ({
          ,
          : .address,
          : ({
            : .abi,
            : .functionName,
            : .args,
          }),
        });

        // Step 2: Execute withdrawal
        ("withdrawing");
        const  = await ({
          ,
          ,
          ,
          ,
          ,
        });

        const { , ,  } = ;
        const  = await ({
          : .chainId,
          : .address,
          : ({ , ,  }),
        });

        ( as `0x${string}`);
        ("success");
      } catch () {
        const  =  instanceof  ?  : new (());
        ();
        ("idle");
        throw ;
      }
    },
    [, ]
  );

  return { , , ,  };
}

Withdraw Component

// src/components/WithdrawButton.tsx
import { useMemo } from "react";
import { useQuery } from "@tanstack/react-query";
import { fetchSupportedAssets, YieldType } from "@paxoslabs/amplify-sdk";
import { mainnet } from "viem/chains";
import { usePrivyWithdraw } from "../hooks/useWithdraw";

// @noErrors
declare const useWallets: () => { wallets: Array<{ address: string }> };

export function PrivyWithdrawButton() {
  const { wallets } = useWallets();
  const wallet = useMemo(() => wallets.find(Boolean), [wallets]);
  const { withdraw, status, error, txHash } = usePrivyWithdraw();

  const { data: supportedAssets } = useQuery({
    queryKey: ["amplify-assets", mainnet.id],
    queryFn: () =>
      fetchSupportedAssets({
        yieldType: YieldType.CORE,
      }),
    enabled: Boolean(wallet),
  });

  const asset = supportedAssets?.[0];

  if (!wallet) return <p>Connect with Privy to withdraw.</p>;
  if (!asset) return <p>Loading supported assets...</p>;

  async function handleClick() {
    await withdraw({
      yieldType: YieldType.CORE,
      offerAmount: "5.0",
      wantAssetAddress: asset.address as `0x${string}`,
      chainId: mainnet.id,
      slippage: 75,
    });
  }

  return (
    <section>
      <button onClick={handleClick} disabled={status !== "idle" && status !== "success"}>
        {status === "approving" && "Approving..."}
        {status === "withdrawing" && "Withdrawing..."}
        {status === "success" && "Withdraw Again"}
        {status === "idle" && "Withdraw"}
      </button>

      {txHash && (
        <p>
          Withdrawal sent:{" "}
          <a
            href={`https://etherscan.io/tx/${txHash}`}
            target="_blank"
            rel="noreferrer"
          >
            {txHash}
          </a>
        </p>
      )}

      {error && <p role="alert">Withdraw failed: {error.message}</p>}
    </section>
  );
}

What the Code Does

  1. Approves the vault - Authorizes the vault contract to spend your shares
  2. Prepares withdrawal - Builds transaction data with slippage protection
  3. Executes withdrawal - Redeems shares for underlying tokens
  4. Tracks status - Updates UI with current operation state

Customization

Slippage Tolerance

Slippage is specified in basis points (1 bp = 0.01%). Default is 75 (0.75%).
const  = await ({
  ...,
  : 100, // 1% slippage tolerance
});

Partial Withdrawals

Specify the exact amount of vault shares to redeem:
await ({
  ...,
  : "10.5", // Redeem 10.5 vault shares
});

Troubleshooting

IssueSolution
”SDK not initialized”Call initAmplifySDK() before using hooks
”Connect a wallet first”Ensure user has connected wallet
Insufficient sharesCheck vault share balance before withdrawing
Slippage exceededIncrease slippage tolerance or try smaller amount
Liquidity unavailableVault may have withdrawal limits, try later
prepareWithdrawTxData throws APIError when liquidity is unavailable or the vault is unsupported. Surface the endpoint and statusCode fields to help users understand failures.
For more details on the withdrawal API, see prepareWithdrawTxData.