init: 初始化 AssetX 项目仓库
包含 webapp(Next.js 用户端)、webapp-back(Go 后端)、 antdesign(管理后台)、landingpage(营销落地页)、 数据库 SQL 和配置文件。
This commit is contained in:
97
webapp/hooks/useLendingWithdraw.ts
Normal file
97
webapp/hooks/useLendingWithdraw.ts
Normal file
@@ -0,0 +1,97 @@
|
||||
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,
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user