// src/hooks/useDeposit.ts
import { useState, useCallback } from "react";
import { encodeFunctionData } from "viem";
import { mainnet } from "viem/chains";
import { usePrivy, useWallets } from "@privy-io/react-auth";
import {
prepareDepositAuthorization,
prepareDepositTxData,
prepareDepositWithPermitTxData,
DepositAuthMethod,
YieldType,
} from "@paxoslabs/amplify-sdk";
interface DepositParams {
amount: string;
depositToken: `0x${string}`;
yieldType: YieldType;
}
export function useDeposit() {
const { sendTransaction } = usePrivy();
const { wallets } = useWallets();
const [status, setStatus] = useState<string>("");
const [isLoading, setIsLoading] = useState(false);
const deposit = useCallback(
async ({ amount, depositToken, yieldType }: DepositParams) => {
const wallet = wallets[0];
if (!wallet) {
throw new Error("Connect a wallet first");
}
setIsLoading(true);
const owner = wallet.address as `0x${string}`;
try {
const params = {
yieldType,
depositToken,
depositAmount: amount,
recipientAddress: owner,
chainId: mainnet.id,
};
// 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 provider = await wallet.getEthereumProvider();
const signature = (await provider.request({
method: "eth_signTypedData_v4",
params: [
owner,
JSON.stringify({
domain: auth.permitData.domain,
types: auth.permitData.types,
primaryType: auth.permitData.primaryType,
message: auth.permitData.message,
}),
],
})) as `0x${string}`;
setStatus("Submitting deposit...");
const permitTx = await prepareDepositWithPermitTxData({
...params,
signature,
deadline: BigInt(auth.permitData.message.deadline),
});
const { abi: permitAbi, functionName: permitFn, args: permitArgs } = permitTx.data;
await sendTransaction({
chainId: permitTx.chainId,
to: permitTx.address,
data: encodeFunctionData({
abi: permitAbi,
functionName: permitFn,
args: permitArgs,
}),
});
break;
}
case DepositAuthMethod.APPROVAL: {
setStatus("Approving token spend...");
const { abi: approvalAbi, functionName: approvalFn, args: approvalArgs } = auth.txData;
await sendTransaction({
chainId: mainnet.id,
to: auth.txData.address,
data: encodeFunctionData({
abi: approvalAbi,
functionName: approvalFn,
args: approvalArgs,
}),
});
setStatus("Submitting deposit...");
const depositTx = await prepareDepositTxData(params);
const { abi: depositAbi, functionName: depositFn, args: depositArgs } = depositTx;
await sendTransaction({
chainId: depositTx.chainId,
to: depositTx.address,
data: encodeFunctionData({
abi: depositAbi,
functionName: depositFn,
args: depositArgs,
}),
});
break;
}
case DepositAuthMethod.ALREADY_APPROVED: {
setStatus("Submitting deposit...");
const directTx = await prepareDepositTxData(params);
const { abi, functionName, args } = directTx;
await sendTransaction({
chainId: directTx.chainId,
to: directTx.address,
data: encodeFunctionData({ abi, functionName, args }),
});
break;
}
}
setStatus("Deposit successful!");
} catch (error) {
setStatus(`Error: ${error instanceof Error ? error.message : "Unknown"}`);
throw error;
} finally {
setIsLoading(false);
}
},
[wallets, sendTransaction]
);
return { deposit, status, isLoading };
}