This example demonstrates a complete deposit flow using wagmi React hooks and the unified deposit API.
This example uses the unified deposit API which automatically detects the optimal authorization method (permit vs approval).
Prerequisites
- Node.js 18+
- wagmi v2+ configured in your app
- Amplify API key from Paxos Labs
Installation
pnpm add @paxoslabs/amplify-sdk wagmi viem @tanstack/react-query
Complete Example
useDeposit Hook
// src/hooks/useDeposit.ts
import { useState, useCallback } from "react";
import { useAccount, useWriteContract, useSignTypedData } from "wagmi";
import {
prepareDepositAuthorization,
prepareDepositTxData,
prepareDepositWithPermitTxData,
DepositAuthMethod,
YieldType,
} from "@paxoslabs/amplify-sdk";
interface DepositParams {
amount: string;
depositToken: `0x${string}`;
yieldType: YieldType;
}
export function useDeposit() {
const { address, chainId } = useAccount();
const { writeContractAsync } = useWriteContract();
const { signTypedDataAsync } = useSignTypedData();
const [status, setStatus] = useState<string>("");
const [isLoading, setIsLoading] = useState(false);
const deposit = useCallback(
async ({ amount, depositToken, yieldType }: DepositParams) => {
if (!address || !chainId) {
throw new Error("Connect a wallet first");
}
setIsLoading(true);
try {
const params = {
yieldType,
depositToken,
depositAmount: amount,
recipientAddress: address,
chainId,
};
// Step 1: Get authorization method
setStatus("Checking authorization...");
const auth = await prepareDepositAuthorization(params);
// Step 2: Handle based on method
switch (auth.method) {
case DepositAuthMethod.PERMIT: {
setStatus("Please sign permit in your wallet...");
const signature = await signTypedDataAsync(auth.permitData);
setStatus("Submitting deposit...");
const permitTx = await prepareDepositWithPermitTxData({
...params,
signature,
deadline: BigInt(auth.permitData.message.deadline),
});
await writeContractAsync({
address: permitTx.address,
abi: permitTx.data.abi,
functionName: permitTx.data.functionName,
args: permitTx.data.args,
account: address,
});
break;
}
case DepositAuthMethod.APPROVAL: {
setStatus("Approving token spend...");
await writeContractAsync({
...auth.txData,
account: address,
});
setStatus("Submitting deposit...");
const depositTx = await prepareDepositTxData(params);
await writeContractAsync({
...depositTx,
account: address,
});
break;
}
case DepositAuthMethod.ALREADY_APPROVED: {
setStatus("Submitting deposit...");
const directTx = await prepareDepositTxData(params);
await writeContractAsync({
...directTx,
account: address,
});
break;
}
}
setStatus("Deposit successful!");
} catch (error) {
setStatus(`Error: ${error instanceof Error ? error.message : "Unknown"}`);
throw error;
} finally {
setIsLoading(false);
}
},
[address, chainId, writeContractAsync, signTypedDataAsync]
);
return { deposit, status, isLoading };
}
Deposit Component
// src/components/DepositForm.tsx
import { useState } from "react";
import { useAccount } from "wagmi";
import { YieldType } from "@paxoslabs/amplify-sdk";
import { useDeposit } from "../hooks/useDeposit";
const USDC_ADDRESS = "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48" as const;
export function DepositForm() {
const { isConnected } = useAccount();
const [amount, setAmount] = useState("100");
const { deposit, status, isLoading } = useDeposit();
if (!isConnected) {
return <p>Please connect your wallet</p>;
}
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
await deposit({
amount,
depositToken: USDC_ADDRESS,
yieldType: YieldType.PRIME,
});
};
return (
<form onSubmit={handleSubmit}>
<label>
Amount (USDC):
<input
type="number"
value={amount}
onChange={(e) => setAmount(e.target.value)}
disabled={isLoading}
min="0"
step="0.01"
/>
</label>
<button type="submit" disabled={isLoading}>
{isLoading ? "Processing..." : "Deposit"}
</button>
{status && <p>{status}</p>}
</form>
);
}
What This Code Does
- Uses wagmi hooks -
useAccount, useWriteContract, useSignTypedData
- Checks authorization method - Determines optimal path automatically
- Signs permits with wagmi - Uses
signTypedDataAsync for EIP-712
- Writes contracts with wagmi - Uses
writeContractAsync for transactions
- Tracks loading state - Disables form during processing
Key Features
- Native wagmi integration - Works with your existing wagmi setup
- Automatic chain handling - Uses connected chain from
useAccount
- Type-safe hooks - Full TypeScript support
- Composable architecture - Separate hook from UI component
Benefits of This Pattern
| Benefit | Description |
|---|
| Separation of concerns | Business logic in hook, UI in component |
| Reusability | Hook can be used across multiple components |
| Testability | Hook logic can be tested independently |
| Maintainability | Changes to flow logic don’t affect UI |
Troubleshooting
| Issue | Solution |
|---|
| ”SDK not initialized” | Call initAmplifySDK() at app startup |
| ”Connect a wallet first” | Check isConnected from useAccount |
| Transaction rejected | User cancelled in wallet, show retry option |
For more details, see Deposits.