Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update discover search to v3 endpoint #6394

Open
wants to merge 23 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
87b9e34
Remove slow search
jinchung Dec 16, 2024
4b50d28
Remove curated and rainbow token list usage from discover search curr…
jinchung Dec 16, 2024
64b7d25
Add support for useTokenSearchAllNetworks
jinchung Dec 16, 2024
8393345
Interim update to useSearchCurrencyLists
jinchung Dec 17, 2024
83d44a6
Make list param optional for discover search query to move towards co…
jinchung Dec 17, 2024
a2465a2
Update parsing of consolidated results from backend for verified, hig…
jinchung Dec 17, 2024
0364a8c
Remove now unused tokenSearch handler
jinchung Dec 17, 2024
edba22c
Temp: experiment with top search results logic for discover
jinchung Dec 19, 2024
bf4faf9
Experiment: add support for sorting against market cap
jinchung Dec 19, 2024
78b5c21
Consolidate multiple queries for chain ID into one query
jinchung Dec 23, 2024
8c0cff9
Add function for getting imported asset
jinchung Dec 30, 2024
74919de
Add separate query key and function for all networks request to simpl…
jinchung Dec 30, 2024
ff98d9e
Update RainbowToken search result to SearchAsset for imported asset r…
jinchung Dec 30, 2024
733cc00
Filter out favorites from all networks results
jinchung Dec 30, 2024
7dc37a9
Update relevance sorting logic
jinchung Dec 30, 2024
a05fae2
Add separate parse token method for deduping across networks without …
jinchung Jan 2, 2025
774f6a9
Default search list for Discover should be mainnet verified assets
jinchung Jan 5, 2025
920b9e0
Fix filtering out of favorite addresses
jinchung Jan 5, 2025
49aedf3
Require icon url for default discover search list
jinchung Jan 8, 2025
388f825
Add decimals based on network when consolidating token across networks
jinchung Jan 8, 2025
a45a21f
Sort tokens by relevance from for loop to map
jinchung Jan 8, 2025
fb0c111
Remove stacking of sorts as it is no longer necessary
jinchung Jan 8, 2025
219aed8
Fix chart expanded state using chain name instead of ID to index into…
jinchung Jan 8, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
112 changes: 107 additions & 5 deletions src/__swaps__/screens/Swap/resources/search/search.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,14 @@ import { SearchAsset, TokenSearchAssetKey, TokenSearchListId, TokenSearchThresho
import { RainbowError, logger } from '@/logger';
import { RainbowFetchClient } from '@/rainbow-fetch';
import { QueryConfigWithSelect, QueryFunctionArgs, QueryFunctionResult, createQueryKey, queryClient } from '@/react-query';
import { isAddress } from '@ethersproject/address';
import { getAddress, isAddress } from '@ethersproject/address';
import { getUniqueId } from '@/utils/ethereumUtils';
import { Contract } from '@ethersproject/contracts';
import { useQuery } from '@tanstack/react-query';
import qs from 'qs';
import { parseTokenSearch } from './utils';
import { parseTokenSearch, parseTokenSearchAcrossNetworks } from './utils';
import { getProvider } from '@/handlers/web3';
import { erc20ABI } from '@/references';

const ALL_VERIFIED_TOKENS_PARAM = '/?list=verifiedAssets';

Expand All @@ -27,12 +31,16 @@ export type TokenSearchArgs = {
chainId?: ChainId;
fromChainId?: ChainId | '';
keys?: TokenSearchAssetKey[];
list: TokenSearchListId;
list?: TokenSearchListId;
threshold?: TokenSearchThreshold;
query?: string;
shouldPersist?: boolean;
};

export type TokenSearchAllNetworksArgs = {
query: string;
};

// ///////////////////////////////////////////////
// Query Key

Expand All @@ -44,17 +52,64 @@ const tokenSearchQueryKey = ({ chainId, fromChainId, keys, list, threshold, quer
);
};

const tokenSearchAllNetworksQueryKey = ({ query }: TokenSearchAllNetworksArgs) => {
const shouldPersist = query === '';
return createQueryKey('TokenSearchAllNetworks', { query }, { persisterVersion: shouldPersist ? 1 : undefined });
};

type TokenSearchQueryKey = ReturnType<typeof tokenSearchQueryKey>;

type TokenSearchAllNetworksQueryKey = ReturnType<typeof tokenSearchAllNetworksQueryKey>;

// ///////////////////////////////////////////////
// Query Function
const getImportedAsset = async (searchQuery: string, chainId: number = ChainId.mainnet): Promise<SearchAsset[]> => {
if (isAddress(searchQuery)) {
const provider = getProvider({ chainId });
const tokenContract = new Contract(searchQuery, erc20ABI, provider);
try {
const [name, symbol, decimals, address] = await Promise.all([
tokenContract.name(),
tokenContract.symbol(),
tokenContract.decimals(),
getAddress(searchQuery),
]);
const uniqueId = getUniqueId(address, chainId);

return [
{
chainId,
address,
decimals,
highLiquidity: false,
isRainbowCurated: false,
isVerified: false,
mainnetAddress: address,
name,
networks: {
[chainId]: {
address,
decimals,
},
},
symbol,
uniqueId,
} as SearchAsset,
];
} catch (e) {
logger.warn('[getImportedAsset]: error getting imported token data', { error: (e as Error).message });
return [];
}
}
return [];
};

async function tokenSearchQueryFunction({
queryKey: [{ chainId, fromChainId, keys, list, threshold, query }],
}: QueryFunctionArgs<typeof tokenSearchQueryKey>) {
const queryParams: {
keys?: string;
list: TokenSearchListId;
list?: TokenSearchListId;
threshold?: TokenSearchThreshold;
query?: string;
fromChainId?: number | string;
Expand All @@ -73,7 +128,7 @@ async function tokenSearchQueryFunction({
}

const url = `${chainId ? `/${chainId}` : ''}/?${qs.stringify(queryParams)}`;
const isSearchingVerifiedAssets = queryParams.list === 'verifiedAssets';
const isSearchingVerifiedAssets = (queryParams.list && queryParams.list === 'verifiedAssets') || !queryParams.list;

try {
if (isAddressSearch && isSearchingVerifiedAssets) {
Expand Down Expand Up @@ -102,6 +157,43 @@ async function tokenSearchQueryFunction({
}
}

async function tokenSearchQueryFunctionAllNetworks({ queryKey: [{ query }] }: QueryFunctionArgs<typeof tokenSearchAllNetworksQueryKey>) {
const queryParams: {
list?: string;
query?: string;
} = {
query,
};

const isAddressSearch = query && isAddress(query);

const searchDefaultMainnetVerifiedList = query === '';
if (searchDefaultMainnetVerifiedList) {
queryParams.list = 'verifiedAssets';
}

const url = `${searchDefaultMainnetVerifiedList ? `/${ChainId.mainnet}` : ''}/?${qs.stringify(queryParams)}`;

try {
if (isAddressSearch) {
const tokenSearch = await tokenSearchHttp.get<{ data: SearchAsset[] }>(url);

if (tokenSearch && tokenSearch.data.data.length > 0) {
return parseTokenSearch(tokenSearch.data.data);
}

const result = await getImportedAsset(query);
return result;
} else {
const tokenSearch = await tokenSearchHttp.get<{ data: SearchAsset[] }>(url);
return parseTokenSearchAcrossNetworks(tokenSearch.data.data);
}
} catch (e) {
logger.error(new RainbowError('[tokenSearchQueryFunction]: Token search failed'), { url });
return [];
}
}

export type TokenSearchResult = QueryFunctionResult<typeof tokenSearchQueryFunction>;

// ///////////////////////////////////////////////
Expand Down Expand Up @@ -144,3 +236,13 @@ export function useTokenSearch(
keepPreviousData: true,
});
}

export function useTokenSearchAllNetworks(
{ query }: TokenSearchAllNetworksArgs,
config: QueryConfigWithSelect<TokenSearchResult, Error, TokenSearchResult, TokenSearchAllNetworksQueryKey> = {}
) {
return useQuery(tokenSearchAllNetworksQueryKey({ query }), tokenSearchQueryFunctionAllNetworks, {
...config,
keepPreviousData: true,
});
}
28 changes: 28 additions & 0 deletions src/__swaps__/screens/Swap/resources/search/utils.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { uniqBy } from 'lodash';
import { ChainId } from '@/state/backendNetworks/types';
import { SearchAsset } from '@/__swaps__/types/search';
import { Address } from 'viem';
Expand Down Expand Up @@ -49,3 +50,30 @@ export function parseTokenSearch(assets: SearchAsset[], chainId?: ChainId): Sear

return results;
}

export function parseTokenSearchAcrossNetworks(assets: SearchAsset[]): SearchAsset[] {
const results = assets.map(asset => {
const assetNetworks = asset.networks;
const networkKeys = Object.keys(assetNetworks);
const firstNetworkChainId = Number(networkKeys[0] || asset.chainId);

const mainnetInfo = assetNetworks[ChainId.mainnet];
const firstNetworkInfo = assetNetworks[firstNetworkChainId];
const chainId = mainnetInfo ? ChainId.mainnet : firstNetworkChainId;
const address = mainnetInfo ? mainnetInfo.address : firstNetworkInfo?.address || asset.address;
const decimals = mainnetInfo ? mainnetInfo.decimals : firstNetworkInfo?.decimals || asset.decimals;
const uniqueId = `${address}_${chainId}`;

return {
...asset,
address,
chainId,
decimals,
isNativeAsset: isNativeAsset(address, chainId),
mainnetAddress: mainnetInfo ? mainnetInfo.address : chainId === ChainId.mainnet ? address : ('' as Address),
uniqueId,
};
});
const uniqRes = uniqBy(results, 'address');
return uniqRes;
}
9 changes: 9 additions & 0 deletions src/__swaps__/types/search.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,14 @@ export type TokenSearchThreshold = 'CONTAINS' | 'CASE_SENSITIVE_EQUAL';

export type TokenSearchListId = 'highLiquidityAssets' | 'lowLiquidityAssets' | 'verifiedAssets';

interface Market {
market_cap: {
value: number;
};
volume_24h: number;
circulating_supply: number;
}

export type SearchAsset = {
address: AddressOrEth;
chainId: ChainId;
Expand All @@ -22,6 +30,7 @@ export type SearchAsset = {
isNativeAsset?: boolean;
isVerified: boolean;
mainnetAddress: AddressOrEth;
market?: Market;
name: string;
networks: {
[chainId in ChainId]?: {
Expand Down
4 changes: 2 additions & 2 deletions src/components/Discover/DiscoverSearch.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ export default function DiscoverSearch() {
const lastSearchQuery = usePrevious(searchQueryForSearch);

const [ensResults, setEnsResults] = useState<EnsSearchResult[]>([]);
const { swapCurrencyList, swapCurrencyListLoading } = useSearchCurrencyList(searchQueryForSearch, ChainId.mainnet);
const { swapCurrencyList, swapCurrencyListLoading } = useSearchCurrencyList(searchQueryForSearch);

const profilesEnabled = useExperimentalFlag(PROFILES);
const marginBottom = TAB_BAR_HEIGHT + safeAreaInsetValues.bottom + 16;
Expand All @@ -83,7 +83,7 @@ export default function DiscoverSearch() {
// 1. favorites
// 2. verified
// 3. profiles
// 4. unverified
// 4. unverified high liquidity
// 5. low liquidity
let list = swapCurrencyList;
const listKeys = swapCurrencyList.map(item => item.key);
Expand Down
2 changes: 1 addition & 1 deletion src/components/expanded-state/asset/ChartExpandedState.js
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ export default function ChartExpandedState({ asset }) {
chainId: asset.chainId,
network: asset.network,
address: asset.address,
mainnetAddress: asset?.networks?.[useBackendNetworksStore.getState().getChainsName()[ChainId.mainnet]]?.address,
mainnetAddress: asset?.networks?.[ChainId.mainnet]?.address,
}
: asset;
}, [asset, genericAsset, hasBalance]);
Expand Down
101 changes: 0 additions & 101 deletions src/handlers/tokenSearch.ts

This file was deleted.

Loading
Loading