Files
assetx/webapp/hooks/useLendingWithdraw.ts
default 2ee4553b71 init: 初始化 AssetX 项目仓库
包含 webapp(Next.js 用户端)、webapp-back(Go 后端)、
antdesign(管理后台)、landingpage(营销落地页)、
数据库 SQL 和配置文件。
2026-03-27 11:26:43 +00:00

98 lines
2.8 KiB
TypeScript

import { useState, useCallback, useEffect } from 'react'
import { useAccount, useWriteContract, useWaitForTransactionReceipt } from 'wagmi'
import { parseUnits } from 'viem'
import { abis, getContractAddress } from '@/lib/contracts'
import { useTokenList } from './useTokenList'
import { handleContractCatchError, isValidAmount, parseContractError } from '@/lib/errors'
import { WITHDRAW_GAS_LIMIT } from '@/lib/constants'
type WithdrawStatus = 'idle' | 'withdrawing' | 'success' | 'error'
export function useLendingWithdraw() {
const { address, chainId } = useAccount()
const { bySymbol } = useTokenList()
const usdcToken = bySymbol['USDC']
const [status, setStatus] = useState<WithdrawStatus>('idle')
const [error, setError] = useState<string | null>(null)
const {
writeContractAsync: withdrawWrite,
data: withdrawHash,
isPending: isWithdrawPending,
reset: resetWithdraw,
} = useWriteContract()
const {
isLoading: isWithdrawConfirming,
isSuccess: isWithdrawSuccess,
isError: isWithdrawError,
error: withdrawReceiptError,
} = useWaitForTransactionReceipt({ hash: withdrawHash })
const executeWithdraw = useCallback(async (amount: string) => {
if (status !== 'idle') return false
if (!address || !chainId || !usdcToken || !amount) {
setError('Missing required parameters')
return false
}
if (!isValidAmount(amount)) {
setError('Invalid amount')
return false
}
try {
setError(null)
setStatus('withdrawing')
const lendingProxyAddress = getContractAddress('lendingProxy', chainId)
if (!lendingProxyAddress) {
throw new Error('Contract not deployed on this chain')
}
const usdcDecimals = usdcToken.onChainDecimals ?? usdcToken.decimals
const amountInWei = parseUnits(amount, usdcDecimals)
await withdrawWrite({
address: lendingProxyAddress,
abi: abis.lendingProxy,
functionName: 'withdraw',
args: [amountInWei],
gas: WITHDRAW_GAS_LIMIT,
})
return true
} catch (err: unknown) {
handleContractCatchError(err, 'Withdraw failed', setError, setStatus as (s: string) => void)
return false
}
}, [address, chainId, withdrawWrite, usdcToken, status])
useEffect(() => {
if (isWithdrawSuccess && status === 'withdrawing') {
setStatus('success')
}
}, [isWithdrawSuccess, status])
useEffect(() => {
if (isWithdrawError && status === 'withdrawing') {
setError(parseContractError(withdrawReceiptError))
setStatus('error')
}
}, [isWithdrawError, status, withdrawReceiptError])
const reset = useCallback(() => {
setStatus('idle')
setError(null)
resetWithdraw()
}, [resetWithdraw])
return {
status,
error,
isLoading: isWithdrawPending || isWithdrawConfirming,
withdrawHash,
executeWithdraw,
reset,
}
}