Commit 744db498 authored by Moody Salem's avatar Moody Salem

do not show duplicate token results, and stop searching as soon as possible

parent 54f59e02
...@@ -3,13 +3,18 @@ import { useMemo } from 'react' ...@@ -3,13 +3,18 @@ import { useMemo } from 'react'
import { isAddress } from '../../utils' import { isAddress } from '../../utils'
import { Token } from '@uniswap/sdk-core' import { Token } from '@uniswap/sdk-core'
export function filterTokens<T extends Token | TokenInfo>(tokens: T[], search: string): T[] { const alwaysTrue = () => true
if (search.length === 0) return tokens
/**
* Create a filter function to apply to a token for whether it matches a particular search query
* @param search the search query to apply to the token
*/
export function createTokenFilterFunction<T extends Token | TokenInfo>(search: string): (tokens: T) => boolean {
const searchingAddress = isAddress(search) const searchingAddress = isAddress(search)
if (searchingAddress) { if (searchingAddress) {
return tokens.filter((token) => token.address === searchingAddress) const lower = searchingAddress.toLowerCase()
return (t: T) => ('isToken' in t ? searchingAddress === t.address : lower === t.address.toLowerCase())
} }
const lowerSearchParts = search const lowerSearchParts = search
...@@ -17,9 +22,7 @@ export function filterTokens<T extends Token | TokenInfo>(tokens: T[], search: s ...@@ -17,9 +22,7 @@ export function filterTokens<T extends Token | TokenInfo>(tokens: T[], search: s
.split(/\s+/) .split(/\s+/)
.filter((s) => s.length > 0) .filter((s) => s.length > 0)
if (lowerSearchParts.length === 0) { if (lowerSearchParts.length === 0) return alwaysTrue
return tokens
}
const matchesSearch = (s: string): boolean => { const matchesSearch = (s: string): boolean => {
const sParts = s const sParts = s
...@@ -30,10 +33,11 @@ export function filterTokens<T extends Token | TokenInfo>(tokens: T[], search: s ...@@ -30,10 +33,11 @@ export function filterTokens<T extends Token | TokenInfo>(tokens: T[], search: s
return lowerSearchParts.every((p) => p.length === 0 || sParts.some((sp) => sp.startsWith(p) || sp.endsWith(p))) return lowerSearchParts.every((p) => p.length === 0 || sParts.some((sp) => sp.startsWith(p) || sp.endsWith(p)))
} }
return tokens.filter((token) => { return ({ name, symbol }: T): boolean => Boolean((symbol && matchesSearch(symbol)) || (name && matchesSearch(name)))
const { symbol, name } = token }
return (symbol && matchesSearch(symbol)) || (name && matchesSearch(name))
}) export function filterTokens<T extends Token | TokenInfo>(tokens: T[], search: string): T[] {
return tokens.filter(createTokenFilterFunction(search))
} }
export function useSortedTokensByQuery(tokens: Token[] | undefined, searchQuery: string): Token[] { export function useSortedTokensByQuery(tokens: Token[] | undefined, searchQuery: string): Token[] {
......
...@@ -2,7 +2,7 @@ import { parseBytes32String } from '@ethersproject/strings' ...@@ -2,7 +2,7 @@ import { parseBytes32String } from '@ethersproject/strings'
import { Currency, currencyEquals, ETHER, Token } from '@uniswap/sdk-core' import { Currency, currencyEquals, ETHER, Token } from '@uniswap/sdk-core'
import { arrayify } from 'ethers/lib/utils' import { arrayify } from 'ethers/lib/utils'
import { useMemo } from 'react' import { useMemo } from 'react'
import { filterTokens } from '../components/SearchModal/filtering' import { createTokenFilterFunction } from '../components/SearchModal/filtering'
import { useAllLists, useCombinedActiveList, useInactiveListUrls } from '../state/lists/hooks' import { useAllLists, useCombinedActiveList, useInactiveListUrls } from '../state/lists/hooks'
import { WrappedTokenInfo } from '../state/lists/wrappedTokenInfo' import { WrappedTokenInfo } from '../state/lists/wrappedTokenInfo'
import { NEVER_RELOAD, useSingleCallResult } from '../state/multicall/hooks' import { NEVER_RELOAD, useSingleCallResult } from '../state/multicall/hooks'
...@@ -61,21 +61,28 @@ export function useSearchInactiveTokenLists(search: string | undefined, minResul ...@@ -61,21 +61,28 @@ export function useSearchInactiveTokenLists(search: string | undefined, minResul
const lists = useAllLists() const lists = useAllLists()
const inactiveUrls = useInactiveListUrls() const inactiveUrls = useInactiveListUrls()
const { chainId } = useActiveWeb3React() const { chainId } = useActiveWeb3React()
const activeTokens = useAllTokens()
return useMemo(() => { return useMemo(() => {
if (!search || search.trim().length === 0) return [] if (!search || search.trim().length === 0) return []
let result: WrappedTokenInfo[] = [] const tokenFilter = createTokenFilterFunction(search)
const result: WrappedTokenInfo[] = []
const addressSet: { [address: string]: true } = {}
for (const url of inactiveUrls) { for (const url of inactiveUrls) {
const list = lists[url].current const list = lists[url].current
if (!list) continue if (!list) continue
const matching = filterTokens( for (const tokenInfo of list.tokens) {
list.tokens.filter((token) => token.chainId === chainId), if (tokenInfo.chainId === chainId && tokenFilter(tokenInfo)) {
search const wrapped = new WrappedTokenInfo(tokenInfo, list)
) if (!(wrapped.address in activeTokens) && !addressSet[wrapped.address]) {
result = [...result, ...matching.map((tokenInfo) => new WrappedTokenInfo(tokenInfo, list))] addressSet[wrapped.address] = true
if (result.length >= minResults) return result result.push(wrapped)
if (result.length >= minResults) return result
}
}
}
} }
return result return result
}, [chainId, inactiveUrls, lists, minResults, search]) }, [activeTokens, chainId, inactiveUrls, lists, minResults, search])
} }
export function useIsTokenActive(token: Token | undefined | null): boolean { export function useIsTokenActive(token: Token | undefined | null): boolean {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment