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.
Redeem shares in one transaction by pairing prepareWithdrawTxData with Privy’s wallet connection hooks. This pattern keeps signer UX inside Privy while letting the Amplify SDK handle calldata.
Overview
- Fetch the target vault (for example with
fetchVaults and React Query).
- Prepare withdrawal calldata with slippage protection.
- Submit the transaction via Privy’s
sendTransaction.
- Track optimistic state and surface any
APIError details.
Prerequisites
- React 18+
- @privy-io/react-auth >= 3
- @paxoslabs/amplify-sdk
- Vault metadata available in your component (e.g., from
fetchVaults)
Withdraw Hook
import { useCallback, useMemo, useState } from "react";
import { encodeFunctionData } from "viem";
import {
prepareApproveWithdrawTxData,
prepareWithdrawTxData,
type YieldType,
} from "@paxoslabs/amplify-sdk";
import { usePrivy, useWallets } from "@privy-io/react-auth";
interface WithdrawParams {
yieldType: YieldType;
offerAmount: string;
wantAssetAddress: `0x${string}`;
chainId: number;
slippage?: number;
}
export function usePrivyWithdraw() {
const { sendTransaction } = usePrivy();
const { wallets } = useWallets();
const wallet = useMemo(() => wallets.find(Boolean), [wallets]);
const [txHash, setTxHash] = useState<`0x${string}` | null>(null);
const [status, setStatus] = useState<
"idle" | "approving" | "withdrawing" | "success"
>("idle");
const [error, setError] = useState<Error | null>(null);
const run = useCallback(
async ({
yieldType,
offerAmount,
wantAssetAddress,
chainId,
slippage = 75,
}: WithdrawParams) => {
if (!wallet) {
throw new Error("Connect a Privy wallet before withdrawing.");
}
setError(null);
setTxHash(null);
try {
// Step 1: Approve withdrawal
setStatus("approving");
const approval = await prepareApproveWithdrawTxData({
chainId,
wantAssetAddress,
yieldType,
});
await sendTransaction({
chainId,
to: approval.address,
data: encodeFunctionData({
abi: approval.abi,
functionName: approval.functionName,
args: approval.args,
}),
});
// Step 2: Execute withdrawal
setStatus("withdrawing");
const tx = await prepareWithdrawTxData({
yieldType,
wantAssetAddress,
offerAmount,
chainId,
});
const { abi, functionName, args } = tx;
const hash = await sendTransaction({
chainId: tx.chainId,
to: tx.address,
data: encodeFunctionData({ abi, functionName, args }),
});
setTxHash(hash as `0x${string}`);
setStatus("success");
} catch (err) {
const message = err instanceof Error ? err : new Error(String(err));
setError(message);
setStatus("idle");
throw err;
}
},
[wallet, sendTransaction]
);
return { run, status, error, txHash };
}
Component Usage
import { useMemo } from "react";
import { useWallets } from "@privy-io/react-auth";
import { useQuery } from "@tanstack/react-query";
import { fetchSupportedAssets, YieldType } from "@paxoslabs/amplify-sdk";
import { mainnet } from "viem/chains";
import { usePrivyWithdraw } from "./usePrivyWithdraw";
export function PrivyWithdrawButton() {
const { wallets } = useWallets();
const wallet = useMemo(() => wallets.find(Boolean), [wallets]);
const { run, status, error, txHash } = usePrivyWithdraw();
const { data: supportedAssets } = useQuery({
queryKey: ["amplify-assets", mainnet.id],
queryFn: () =>
fetchSupportedAssets({
yieldType: YieldType.PRIME,
}),
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 run({
yieldType: YieldType.PRIME,
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>
);
}
prepareWithdrawTxData throws APIError when the vault or asset is
unsupported. Log the endpoint and statusCode to help users fall back to
alternate flows.