-
Notifications
You must be signed in to change notification settings - Fork 5.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
e2030c5
commit 920454a
Showing
4 changed files
with
19 additions
and
131 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1 @@ | ||
web/5.46.0 | ||
web/5.46.1 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,109 +1,24 @@ | ||
import { BACKEND_SUPPORTED_CHAINS, SupportedInterfaceChainId, chainIdToBackendChain } from 'constants/chains' | ||
import { ARB, NATIVE_CHAIN_ID, WRAPPED_NATIVE_CURRENCY } from 'constants/tokens' | ||
import { BACKEND_SUPPORTED_CHAINS } from 'constants/chains' | ||
import { useMemo } from 'react' | ||
import invariant from 'tiny-invariant' | ||
import { | ||
Chain, | ||
SearchTokensWebQuery, | ||
Token, | ||
useSearchTokensWebQuery, | ||
} from 'uniswap/src/data/graphql/uniswap-data-api/__generated__/types-and-hooks' | ||
|
||
const ARB_ADDRESS = ARB.address.toLowerCase() | ||
|
||
/* Returns the more relevant cross-chain token based on native status and search chain */ | ||
function dedupeCrosschainTokens(current: GqlSearchToken, existing: GqlSearchToken | undefined, searchChain: Chain) { | ||
if (!existing) { | ||
return current | ||
} | ||
invariant(current.project?.id === existing.project?.id, 'Cannot dedupe tokens within different tokenProjects') | ||
|
||
// Special case: always prefer Arbitrum ARB over Mainnet ARB | ||
if (current.address?.toLowerCase() === ARB_ADDRESS) { | ||
return current | ||
} | ||
if (existing.address?.toLowerCase() === ARB_ADDRESS) { | ||
return existing | ||
} | ||
|
||
// Always prioritize natives, and if both tokens are native, prefer native on current chain (i.e. Matic on Polygon over Matic on Mainnet ) | ||
if ( | ||
current.standard === NATIVE_CHAIN_ID && | ||
(existing.standard !== NATIVE_CHAIN_ID || current.chain === searchChain) | ||
) { | ||
return current | ||
} | ||
|
||
// Prefer tokens on the searched chain, otherwise prefer mainnet tokens | ||
if (current.chain === searchChain || (existing.chain !== searchChain && current.chain === Chain.Ethereum)) { | ||
return current | ||
} | ||
|
||
return existing | ||
} | ||
|
||
/* Places natives first, wrapped native on current chain next, then sorts by volume */ | ||
function searchTokenSortFunction( | ||
searchChain: Chain, | ||
wrappedNativeAddress: string | undefined, | ||
a: GqlSearchToken, | ||
b: GqlSearchToken, | ||
) { | ||
if (a.standard === NATIVE_CHAIN_ID) { | ||
if (b.standard === NATIVE_CHAIN_ID) { | ||
if (a.chain === searchChain) { | ||
return -1 | ||
} else if (b.chain === searchChain) { | ||
return 1 | ||
} else { | ||
return 0 | ||
} | ||
} else { | ||
return -1 | ||
} | ||
} else if (b.standard === NATIVE_CHAIN_ID) { | ||
return 1 | ||
} else if (wrappedNativeAddress && a.address === wrappedNativeAddress) { | ||
return -1 | ||
} else if (wrappedNativeAddress && b.address === wrappedNativeAddress) { | ||
return 1 | ||
} else { | ||
return (b.market?.volume24H?.value ?? 0) - (a.market?.volume24H?.value ?? 0) | ||
} | ||
// Filters out results that are undefined, or where the token's chain is not supported in explore. | ||
function isExploreSupportedToken(token: GqlSearchToken | undefined): token is Token { | ||
return token !== undefined && (BACKEND_SUPPORTED_CHAINS as ReadonlyArray<Chain>).includes(token.chain) | ||
} | ||
|
||
export function useSearchTokens(searchQuery: string | undefined, chainId: SupportedInterfaceChainId) { | ||
const { data, loading, error } = useSearchTokensWebQuery({ | ||
variables: { | ||
searchQuery: searchQuery ?? '', | ||
}, | ||
skip: !searchQuery, | ||
}) | ||
|
||
const sortedTokens = useMemo(() => { | ||
const searchChain = chainIdToBackendChain({ chainId, withFallback: true }) | ||
// Stores results, allowing overwriting cross-chain tokens w/ more 'relevant token' | ||
const selectionMap: { [projectId: string]: GqlSearchToken } = {} | ||
const filteredTokens = data?.searchTokens?.filter( | ||
(token): token is Token => | ||
token !== undefined && (BACKEND_SUPPORTED_CHAINS as ReadonlyArray<Chain>).includes(token.chain), | ||
) | ||
filteredTokens?.forEach((token) => { | ||
if (token.project?.id) { | ||
const existing = selectionMap[token.project.id] | ||
selectionMap[token.project.id] = dedupeCrosschainTokens(token, existing, searchChain) | ||
} | ||
}) | ||
return Object.values(selectionMap).sort( | ||
searchTokenSortFunction.bind(null, searchChain, WRAPPED_NATIVE_CURRENCY[chainId]?.address), | ||
) | ||
}, [data, chainId]) | ||
export function useSearchTokens(searchQuery: string = '') { | ||
const { data, loading, error } = useSearchTokensWebQuery({ variables: { searchQuery }, skip: searchQuery === '' }) | ||
|
||
return { | ||
data: sortedTokens, | ||
loading, | ||
error, | ||
} | ||
return useMemo(() => { | ||
const sortedTokens = data?.searchTokens?.filter(isExploreSupportedToken) ?? [] | ||
return { data: sortedTokens, loading, error } | ||
}, [data?.searchTokens, loading, error]) | ||
} | ||
|
||
export type GqlSearchToken = NonNullable<NonNullable<SearchTokensWebQuery['searchTokens']>[number]> |