@openocean.finance/widget
Version:
Openocean Widget for cross-chain bridging and swapping. It will drive your multi-chain strategy and attract new users from everywhere.
135 lines (123 loc) • 4.16 kB
text/typescript
import { useQuery } from '@tanstack/react-query'
import { useMemo } from 'react'
import { useWidgetConfig } from '../providers/WidgetProvider/WidgetProvider.js'
import { OpenOceanService } from '../services/OpenOceanService.js'
import type { TokenAmount } from '../types/token.js'
import { useChains } from './useChains.js'
export const useTokens = (selectedChainId?: number) => {
const { tokens: configTokens } = useWidgetConfig()
const { data, isLoading } = useQuery({
queryKey: ['tokens', selectedChainId],
queryFn: async () => {
if (!selectedChainId) {
return { tokens: {} as Record<number, TokenAmount[]> }
}
const tokens = await OpenOceanService.getTokenList(
selectedChainId.toString()
)
return {
tokens: {
[selectedChainId]: tokens,
},
}
},
enabled: !!selectedChainId,
refetchInterval: 3_600_000,
staleTime: 3_600_000,
})
const {
chains,
isLoading: isSupportedChainsLoading,
getChainById,
} = useChains()
const filteredData = useMemo(() => {
if (isSupportedChainsLoading || !data) {
return
}
const chain = getChainById(selectedChainId, chains)
const chainAllowed = selectedChainId && chain
if (!chainAllowed) {
return
}
let filteredTokens = data.tokens?.[selectedChainId] || []
const includedTokens = configTokens?.include?.filter(
(token) => token.chainId === selectedChainId
)
if (includedTokens?.length) {
filteredTokens = [...includedTokens, ...filteredTokens]
}
if (configTokens?.allow?.length || configTokens?.deny?.length) {
const allowedTokensSet = new Set(
configTokens?.allow
?.filter((token) => token.chainId === selectedChainId)
.map((token) => token.address)
)
const deniedTokenAddressesSet = new Set(
configTokens?.deny
?.filter((token) => token.chainId === selectedChainId)
.map((token) => token.address)
)
if (allowedTokensSet.size || deniedTokenAddressesSet.size) {
filteredTokens = filteredTokens.filter(
(token) =>
(!allowedTokensSet.size || allowedTokensSet.has(token.address)) &&
!deniedTokenAddressesSet.has(token.address)
)
}
}
const filteredTokensMap = new Map(
filteredTokens.map((token) => [token.address, token])
)
const [popularTokens, featuredTokens] = (
['popular', 'featured'] as ('popular' | 'featured')[]
).map((tokenType) => {
const typedConfigTokens = configTokens?.[tokenType]?.filter(
(token) => token.chainId === selectedChainId
)
const populatedConfigTokens = typedConfigTokens?.map((token) => {
// Mark token as popular
token[tokenType] = true
// Check if this token exists in the filteredTokensMap and add priceUSD if it does
const matchingFilteredToken = filteredTokensMap.get(token.address)
if ((matchingFilteredToken as any)?.priceUSD) {
(token as any).priceUSD = (matchingFilteredToken as any).priceUSD
}
if (!token.logoURI && matchingFilteredToken) {
(token as any).logoURI = (matchingFilteredToken as any).logoURI
}
return token as TokenAmount
})
if (populatedConfigTokens?.length) {
const configTokenAddresses = new Set(
populatedConfigTokens?.map((token) => token.address)
)
filteredTokens = filteredTokens.filter(
(token) => !configTokenAddresses.has(token.address)
)
populatedConfigTokens.push(...filteredTokens)
filteredTokens = populatedConfigTokens
}
return populatedConfigTokens
})
return {
tokens: filteredTokens,
featuredTokens,
popularTokens,
chain,
}
}, [
chains,
configTokens,
data,
getChainById,
isSupportedChainsLoading,
selectedChainId,
])
return {
tokens: filteredData?.tokens,
featuredTokens: filteredData?.featuredTokens,
popularTokens: filteredData?.popularTokens,
chain: filteredData?.chain,
isLoading,
}
}