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.
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
import { useCallback, useEffect, useState } from "react";
import { useWaitForTransactionReceipt, useWriteContract } from "wagmi";
import {
prepareApproveWithdrawTxData,
prepareWithdrawTxData,
type YieldType,
} from "@paxoslabs/amplify-sdk";
import type { Address } from "viem";
interface WithdrawParams {
yieldType: YieldType;
offerAmount: string;
wantAssetAddress: Address;
chainId: number;
userAddress: Address;
slippage?: number;
}
export function useWithdraw() {
const [error, setError] = useState<Error | null>(null);
const [status, setStatus] = useState<
"idle" | "approving" | "submitting" | "confirming" | "success"
>("idle");
// Wagmi hooks for writing contracts
const {
writeContractAsync,
data: hash,
isPending: isSubmitting,
} = useWriteContract();
// Wait for transaction confirmation
const { isLoading: isConfirming } = useWaitForTransactionReceipt({
hash,
confirmations: 1,
query: { enabled: Boolean(hash) },
});
/**
* Execute withdraw transaction
*/
const withdraw = useCallback(
async ({
yieldType,
offerAmount,
wantAssetAddress,
chainId,
userAddress,
slippage = 75,
}: WithdrawParams) => {
setError(null);
try {
// Step 1: Approve withdrawal
setStatus("approving");
const approval = await prepareApproveWithdrawTxData({
chainId,
wantAssetAddress,
yieldType,
});
await writeContractAsync({
...approval,
account: userAddress,
});
// Step 2: Execute withdrawal
setStatus("submitting");
const tx = await prepareWithdrawTxData({
yieldType,
offerAmount,
wantAssetAddress,
chainId,
});
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 {
withdraw,
status,
hash,
error,
isIdle: status === "idle",
isSubmitting,
isConfirming,
isSuccess: status === "success",
};
}
Component Usage
import { useAccount } from "wagmi";
import { useQuery } from "@tanstack/react-query";
import { fetchSupportedAssets, YieldType } from "@paxoslabs/amplify-sdk";
import { mainnet } from "viem/chains";
import { useWithdraw } from "./useWithdraw";
export function WithdrawForm() {
const { address, chainId } = useAccount();
const { withdraw, status, error, hash } = useWithdraw();
const { data: supportedAssets } = useQuery({
queryKey: ["amplify-assets", chainId],
queryFn: () =>
fetchSupportedAssets({ yieldType: YieldType.PRIME }),
enabled: Boolean(address),
});
const asset = supportedAssets?.[0];
if (!address) {
return <p>Connect a wallet to redeem shares.</p>;
}
if (!asset) {
return <p>Loading supported assets…</p>;
}
async function handleWithdraw() {
await withdraw({
yieldType: YieldType.PRIME,
offerAmount: "5.0",
wantAssetAddress: asset.address as `0x${string}`,
chainId: mainnet.id,
userAddress: address,
slippage: 75,
});
}
return (
<section>
<button
disabled={status === "approving" || status === "submitting" || status === "confirming"}
onClick={handleWithdraw}
>
{status === "approving"
? "Approving…"
: 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>
);
}
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.