fix: include user-added tokens in selector (#5319)
This commit is contained in:
parent
8cd32138ac
commit
ce51ffae75
@ -17,8 +17,9 @@ import { FixedSizeList } from 'react-window'
|
||||
import { Text } from 'rebass'
|
||||
import { useAllTokenBalances } from 'state/connection/hooks'
|
||||
import styled, { useTheme } from 'styled-components/macro'
|
||||
import { UserAddedToken } from 'types/tokens'
|
||||
|
||||
import { useActiveTokens, useIsUserAddedToken, useSearchInactiveTokenLists, useToken } from '../../hooks/Tokens'
|
||||
import { useAllTokens, useIsUserAddedToken, useSearchInactiveTokenLists, useToken } from '../../hooks/Tokens'
|
||||
import { CloseIcon, ThemedText } from '../../theme'
|
||||
import { isAddress } from '../../utils'
|
||||
import Column from '../Column'
|
||||
@ -66,15 +67,8 @@ export function CurrencySearch({
|
||||
|
||||
const [searchQuery, setSearchQuery] = useState<string>('')
|
||||
const debouncedQuery = useDebounce(searchQuery, 200)
|
||||
|
||||
// Only display 'imported' tokens when the search filter has input
|
||||
const defaultTokens = useActiveTokens(debouncedQuery.length > 0)
|
||||
|
||||
// if they input an address, use it
|
||||
const isAddressSearch = isAddress(debouncedQuery)
|
||||
|
||||
const searchToken = useToken(debouncedQuery)
|
||||
|
||||
const searchTokenIsAdded = useIsUserAddedToken(searchToken)
|
||||
|
||||
useEffect(() => {
|
||||
@ -87,13 +81,26 @@ export function CurrencySearch({
|
||||
}
|
||||
}, [isAddressSearch])
|
||||
|
||||
const defaultTokens = useAllTokens()
|
||||
const filteredTokens: Token[] = useMemo(() => {
|
||||
return Object.values(defaultTokens).filter(getTokenFilter(debouncedQuery))
|
||||
}, [defaultTokens, debouncedQuery])
|
||||
|
||||
const [balances, balancesAreLoading] = useAllTokenBalances()
|
||||
const sortedTokens: Token[] = useMemo(
|
||||
() => (!balancesAreLoading ? [...filteredTokens].sort(tokenComparator.bind(null, balances)) : []),
|
||||
() =>
|
||||
!balancesAreLoading
|
||||
? [...filteredTokens]
|
||||
.filter((token) => {
|
||||
// Filter out user-added tokens with no balance
|
||||
if (token instanceof UserAddedToken) {
|
||||
const balance = balances[token.address]
|
||||
return balance?.greaterThan(0)
|
||||
}
|
||||
return true
|
||||
})
|
||||
.sort(tokenComparator.bind(null, balances))
|
||||
: [],
|
||||
[balances, filteredTokens, balancesAreLoading]
|
||||
)
|
||||
const isLoading = Boolean(balancesAreLoading && !tokenLoaderTimerElapsed)
|
||||
|
@ -14,50 +14,38 @@ import { useUserAddedTokens, useUserAddedTokensOnChain } from '../state/user/hoo
|
||||
import { TokenAddressMap, useUnsupportedTokenList } from './../state/lists/hooks'
|
||||
|
||||
// reduce token map into standard address <-> Token mapping, optionally include user added tokens
|
||||
function useTokensFromMap(tokenMap: TokenAddressMap, includeUserAdded: boolean): { [address: string]: Token } {
|
||||
function useTokensFromMap(tokenMap: TokenAddressMap): { [address: string]: Token } {
|
||||
const { chainId } = useWeb3React()
|
||||
const userAddedTokens = useUserAddedTokens()
|
||||
|
||||
return useMemo(() => {
|
||||
if (!chainId) return {}
|
||||
|
||||
// reduce to just tokens
|
||||
const mapWithoutUrls = Object.keys(tokenMap[chainId] ?? {}).reduce<{ [address: string]: Token }>(
|
||||
(newMap, address) => {
|
||||
newMap[address] = tokenMap[chainId][address].token
|
||||
return newMap
|
||||
},
|
||||
{}
|
||||
)
|
||||
|
||||
if (includeUserAdded) {
|
||||
return (
|
||||
userAddedTokens
|
||||
// reduce into all ALL_TOKENS filtered by the current chain
|
||||
.reduce<{ [address: string]: Token }>(
|
||||
(tokenMap, token) => {
|
||||
tokenMap[token.address] = token
|
||||
return tokenMap
|
||||
},
|
||||
// must make a copy because reduce modifies the map, and we do not
|
||||
// want to make a copy in every iteration
|
||||
{ ...mapWithoutUrls }
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
return mapWithoutUrls
|
||||
}, [chainId, userAddedTokens, tokenMap, includeUserAdded])
|
||||
return Object.keys(tokenMap[chainId] ?? {}).reduce<{ [address: string]: Token }>((newMap, address) => {
|
||||
newMap[address] = tokenMap[chainId][address].token
|
||||
return newMap
|
||||
}, {})
|
||||
}, [chainId, tokenMap])
|
||||
}
|
||||
|
||||
export function useAllTokens(): { [address: string]: Token } {
|
||||
const allTokens = useCombinedActiveList()
|
||||
return useTokensFromMap(allTokens, true)
|
||||
}
|
||||
|
||||
export function useActiveTokens(includeUserAdded: boolean): { [address: string]: Token } {
|
||||
const allTokens = useCombinedActiveList()
|
||||
return useTokensFromMap(allTokens, includeUserAdded)
|
||||
const tokensFromMap = useTokensFromMap(allTokens)
|
||||
const userAddedTokens = useUserAddedTokens()
|
||||
return useMemo(() => {
|
||||
return (
|
||||
userAddedTokens
|
||||
// reduce into all ALL_TOKENS filtered by the current chain
|
||||
.reduce<{ [address: string]: Token }>(
|
||||
(tokenMap, token) => {
|
||||
tokenMap[token.address] = token
|
||||
return tokenMap
|
||||
},
|
||||
// must make a copy because reduce modifies the map, and we do not
|
||||
// want to make a copy in every iteration
|
||||
{ ...tokensFromMap }
|
||||
)
|
||||
)
|
||||
}, [tokensFromMap, userAddedTokens])
|
||||
}
|
||||
|
||||
type BridgeInfo = Record<
|
||||
@ -73,7 +61,7 @@ export function useUnsupportedTokens(): { [address: string]: Token } {
|
||||
const { chainId } = useWeb3React()
|
||||
const listsByUrl = useAllLists()
|
||||
const unsupportedTokensMap = useUnsupportedTokenList()
|
||||
const unsupportedTokens = useTokensFromMap(unsupportedTokensMap, false)
|
||||
const unsupportedTokens = useTokensFromMap(unsupportedTokensMap)
|
||||
|
||||
// checks the default L2 lists to see if `bridgeInfo` has an L1 address value that is unsupported
|
||||
const l2InferredBlockedTokens: typeof unsupportedTokens = useMemo(() => {
|
||||
|
@ -8,6 +8,7 @@ import JSBI from 'jsbi'
|
||||
import { useCallback, useMemo } from 'react'
|
||||
import { shallowEqual } from 'react-redux'
|
||||
import { useAppDispatch, useAppSelector } from 'state/hooks'
|
||||
import { UserAddedToken } from 'types/tokens'
|
||||
|
||||
import { V2_FACTORY_ADDRESSES } from '../../constants/addresses'
|
||||
import { BASES_TO_TRACK_LIQUIDITY_FOR, PINNED_PAIRS } from '../../constants/routing'
|
||||
@ -38,8 +39,8 @@ function serializeToken(token: Token): SerializedToken {
|
||||
}
|
||||
}
|
||||
|
||||
function deserializeToken(serializedToken: SerializedToken): Token {
|
||||
return new Token(
|
||||
function deserializeToken(serializedToken: SerializedToken, Class: typeof Token = Token): Token {
|
||||
return new Class(
|
||||
serializedToken.chainId,
|
||||
serializedToken.address,
|
||||
serializedToken.decimals,
|
||||
@ -238,7 +239,7 @@ export function useUserAddedTokensOnChain(chainId: number | undefined | null): T
|
||||
return useMemo(() => {
|
||||
if (!chainId) return []
|
||||
const tokenMap: Token[] = serializedTokensMap?.[chainId]
|
||||
? Object.values(serializedTokensMap[chainId]).map(deserializeToken)
|
||||
? Object.values(serializedTokensMap[chainId]).map((value) => deserializeToken(value, UserAddedToken))
|
||||
: []
|
||||
return tokenMap
|
||||
}, [serializedTokensMap, chainId])
|
||||
|
3
src/types/tokens.ts
Normal file
3
src/types/tokens.ts
Normal file
@ -0,0 +1,3 @@
|
||||
import { Token } from '@uniswap/sdk-core'
|
||||
|
||||
export class UserAddedToken extends Token {}
|
Loading…
Reference in New Issue
Block a user