-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathuseTokenInput.tsx
More file actions
94 lines (86 loc) · 3.33 KB
/
Copy pathuseTokenInput.tsx
File metadata and controls
94 lines (86 loc) · 3.33 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
import { useQuery } from '@tanstack/react-query'
import { useEffect, useState } from 'react'
import { getAddress } from 'viem'
import { useAccount, usePublicClient } from 'wagmi'
import { useErc20Balance } from '@/src/hooks/useErc20Balance'
import { useTokens } from '@/src/hooks/useTokens'
import type { Token } from '@/src/types/token'
import { isNativeToken } from '@/src/utils/address'
export type UseTokenInputReturnType = ReturnType<typeof useTokenInput>
/**
* Token Input Hook
*
* Manages state and logic for token input components, handling:
* - Token amount and validation errors
* - Selected token state
* - Balance fetching for ERC20 and native tokens
*
* @param {Token} [token] - Optional initial token to select
* @returns {Object} Hook return object
* @returns {bigint} returns.amount - The current input amount as a bigint
* @returns {function} returns.setAmount - Function to update the amount
* @returns {string|null} returns.amountError - Error message for invalid amount
* @returns {function} returns.setAmountError - Function to update amount errors
* @returns {bigint} returns.balance - Current token balance (ERC20 or native)
* @returns {Error|null} returns.balanceError - Error from balance fetching
* @returns {boolean} returns.isLoadingBalance - Loading state for balance
* @returns {Token|undefined} returns.selectedToken - Currently selected token
* @returns {function} returns.setTokenSelected - Function to update selected token
*
* @example
* ```tsx
* const {
* amount,
* balance,
* selectedToken,
* setAmount,
* setTokenSelected
* } = useTokenInput(defaultToken);
* ```
*/
export function useTokenInput(token?: Token) {
const [amount, setAmount] = useState<bigint>(BigInt(0))
const [amountError, setAmountError] = useState<string | null>()
const [selectedToken, setTokenSelected] = useState<Token | undefined>(token)
useEffect(() => {
setTokenSelected(token)
}, [token])
const { address: userWallet } = useAccount()
const { tokensByChainId, isLoadingBalances: isLoadingPrice } = useTokens({
chainId: selectedToken?.chainId,
withBalance: true,
})
const priceUSD = selectedToken
? (tokensByChainId[selectedToken.chainId]?.find(
(t) => t.address.toLowerCase() === selectedToken.address.toLowerCase(),
)?.extensions?.priceUSD as string | undefined)
: undefined
const { balance, balanceError, isLoadingBalance } = useErc20Balance({
address: userWallet ? getAddress(userWallet) : undefined,
token: selectedToken,
})
const publicClient = usePublicClient({ chainId: selectedToken?.chainId })
const isNative = selectedToken?.address ? isNativeToken(selectedToken.address) : false
const {
data: nativeBalance,
error: nativeBalanceError,
isLoading: isLoadingNativeBalance,
} = useQuery({
queryKey: ['nativeBalance', selectedToken?.address, selectedToken?.chainId, userWallet],
queryFn: () => publicClient?.getBalance({ address: getAddress(userWallet ?? '') }),
enabled: isNative && !!userWallet,
})
return {
amount,
setAmount,
amountError,
setAmountError,
balance: isNative ? nativeBalance : balance,
balanceError: isNative ? nativeBalanceError : balanceError,
isLoadingBalance: isNative ? isLoadingNativeBalance : isLoadingBalance,
isLoadingPrice,
priceUSD,
selectedToken,
setTokenSelected,
}
}