@lifi/widget
Version:
LI.FI Widget for cross-chain bridging and swapping. It will drive your multi-chain strategy and attract new users from everywhere.
99 lines (88 loc) • 3.16 kB
text/typescript
import { useMemo } from 'react'
import { useWidgetConfig } from '../providers/WidgetProvider/WidgetProvider.js'
import type { FormType } from '../stores/form/types.js'
import { isSearchMatch, processTokenBalances } from '../utils/tokenList.js'
import { useAccountsBalancesData } from './useAccountsBalancesData.js'
import { useTokenBalancesQueries } from './useTokenBalancesQueries.js'
import { useTokens } from './useTokens.js'
export const useTokenBalances = (
selectedChainId?: number,
formType?: FormType,
isAllNetworks?: boolean,
search?: string
) => {
const {
allTokens,
isLoading: isTokensLoading,
isSearchLoading,
} = useTokens(formType, search, isAllNetworks ? undefined : selectedChainId)
const { data: accountsWithAllTokens, isLoading: isAccountsLoading } =
useAccountsBalancesData(selectedChainId, formType, isAllNetworks, allTokens)
const isBalanceLoadingEnabled =
Boolean(accountsWithAllTokens) && !isAccountsLoading
const { data: allTokensWithBalances, isLoading: isBalanceQueriesLoading } =
useTokenBalancesQueries(accountsWithAllTokens, isBalanceLoadingEnabled)
const { tokens: configTokens } = useWidgetConfig()
const isBalanceLoading =
(isBalanceQueriesLoading || isAccountsLoading) &&
!allTokensWithBalances?.length
const displayedTokensList = useMemo(() => {
const tokensByChain = isAllNetworks
? Object.values(allTokens ?? {}).flat()
: selectedChainId
? allTokens?.[selectedChainId]
: undefined
return tokensByChain?.filter((t) => isSearchMatch(t, search)) ?? []
}, [allTokens, isAllNetworks, selectedChainId, search])
const displayedTokensWithBalances = useMemo(() => {
const balancesByChain = isAllNetworks
? allTokensWithBalances
: selectedChainId
? allTokensWithBalances?.filter((t) => t.chainId === selectedChainId)
: undefined
const displayedTokensSet = new Set(
displayedTokensList?.map(
(t) => `${t.chainId}-${t.address.toLowerCase()}`
) || []
)
return balancesByChain?.filter((token) => {
const tokenKey = `${token.chainId}-${token.address.toLowerCase()}`
// Check if token is in displayed list and has amount
const isInDisplayedList = displayedTokensSet.has(tokenKey) && token.amount
// Check if it matches search (for cached appended tokens)
const matchesSearch = isSearchMatch(token, search)
return isInDisplayedList || matchesSearch
})
}, [
allTokensWithBalances,
displayedTokensList,
search,
selectedChainId,
isAllNetworks,
])
const { processedTokens, withCategories } = useMemo(() => {
return processTokenBalances(
isBalanceLoading,
isAllNetworks || !!search,
configTokens,
selectedChainId,
displayedTokensList,
displayedTokensWithBalances
)
}, [
isBalanceLoading,
isAllNetworks,
configTokens,
selectedChainId,
displayedTokensList,
displayedTokensWithBalances,
search,
])
return {
tokens: processedTokens ?? [],
withCategories,
isTokensLoading,
isSearchLoading,
isBalanceLoading,
}
}