import { useState } from "react";
import { parseUnits } from "viem";
import { useReadContract, useWriteContract } from "wagmi";
import { ERC20_ABI, ERC4626_ABI } from "../ABIs";
interface VaultInfo {
address: string;
asset: {
address: string;
symbol: string;
decimals: number;
};
}
export function useVaultOperations(
address: string | undefined,
vaultInfo: VaultInfo | null
) {
const [amount, setAmount] = useState("");
const [txStatus, setTxStatus] = useState("");
// Read asset balance
const { data: assetBalance } = useReadContract({
address: vaultInfo?.asset.address as `0x${string}`,
abi: ERC20_ABI,
functionName: "balanceOf",
args: address ? [address] : undefined,
query: { enabled: !!address && !!vaultInfo?.asset.address },
});
// Read vault share balance
const { data: vaultBalance } = useReadContract({
address: vaultInfo?.address as `0x${string}`,
abi: ERC4626_ABI,
functionName: "balanceOf",
args: address ? [address] : undefined,
query: { enabled: !!address && !!vaultInfo?.address },
});
// Read user's deposited assets (convert shares to assets)
const { data: depositedAssets } = useReadContract({
address: vaultInfo?.address as `0x${string}`,
abi: ERC4626_ABI,
functionName: "convertToAssets",
args: vaultBalance ? [vaultBalance] : undefined,
query: { enabled: !!vaultInfo?.address && !!vaultBalance },
});
// Read allowance
const { data: allowance } = useReadContract({
address: vaultInfo?.asset.address as `0x${string}`,
abi: ERC20_ABI,
functionName: "allowance",
args:
address && vaultInfo?.asset.address && vaultInfo?.address
? [address, vaultInfo.address]
: undefined,
query: {
enabled: !!address && !!vaultInfo?.asset.address && !!vaultInfo?.address,
},
});
const { writeContract: writeApprove, isPending: isApprovePending } =
useWriteContract();
const { writeContract: writeDeposit, isPending: isDepositPending } =
useWriteContract();
const { writeContract: writeWithdraw, isPending: isWithdrawPending } =
useWriteContract();
const handleApprove = async () => {
if (!vaultInfo?.asset.address || !vaultInfo?.address) return;
try {
await writeApprove({
address: vaultInfo.asset.address as `0x${string}`,
abi: ERC20_ABI,
functionName: "approve",
args: [vaultInfo.address, parseUnits(amount, vaultInfo.asset.decimals)],
});
} catch (error) {
console.error("Approval failed:", error);
throw error;
}
};
const handleDeposit = async (amount: string) => {
if (!vaultInfo?.address || !address) return;
try {
await writeDeposit({
address: vaultInfo.address as `0x${string}`,
abi: ERC4626_ABI,
functionName: "deposit",
args: [parseUnits(amount, vaultInfo.asset.decimals), address],
});
} catch (error) {
console.error("Deposit failed:", error);
throw error;
}
};
const handleWithdraw = async (amount: string) => {
if (!vaultInfo?.address || !address) return;
try {
await writeWithdraw({
address: vaultInfo.address as `0x${string}`,
abi: ERC4626_ABI,
functionName: "withdraw",
args: [parseUnits(amount, vaultInfo.asset.decimals), address, address],
});
} catch (error) {
console.error("Withdraw failed:", error);
throw error;
}
};
const needsApproval =
(allowance !== undefined &&
vaultInfo?.asset.decimals &&
parseUnits(amount || "0", vaultInfo.asset.decimals) >
(allowance as bigint)) ||
false;
return {
assetBalance: assetBalance
? formatUnits(assetBalance, vaultInfo?.asset.decimals || 18)
: "0",
vaultBalance: vaultBalance
? formatUnits(vaultBalance, vaultInfo?.asset.decimals || 18)
: "0",
allowance: allowance
? formatUnits(allowance, vaultInfo?.asset.decimals || 18)
: "0",
amount,
setAmount,
handleApprove,
handleDeposit,
handleWithdraw,
isApprovePending,
isDepositPending,
isWithdrawPending,
txStatus,
};
}