diff --git a/src/__swaps__/screens/Swap/hooks/useSearchCurrencyLists.ts b/src/__swaps__/screens/Swap/hooks/useSearchCurrencyLists.ts index 42031846014..62d09cba7f2 100644 --- a/src/__swaps__/screens/Swap/hooks/useSearchCurrencyLists.ts +++ b/src/__swaps__/screens/Swap/hooks/useSearchCurrencyLists.ts @@ -27,6 +27,14 @@ export interface AssetToBuySection { const MAX_UNVERIFIED_RESULTS = 8; const MAX_VERIFIED_RESULTS = 48; +const mergeAssetsFavoriteStatus = ({ + assets, + favoritesList, +}: { + assets: SearchAsset[] | undefined; + favoritesList: SearchAsset[] | undefined; +}): SearchAsset[] => assets?.map(asset => ({ ...asset, favorite: favoritesList?.some(fav => fav.address === asset.address) })) || []; + const filterAssetsFromBridge = ({ assets, filteredBridgeAssetAddress, @@ -35,16 +43,43 @@ const filterAssetsFromBridge = ({ filteredBridgeAssetAddress: string | undefined; }): SearchAsset[] => assets?.filter(curatedAsset => !isLowerCaseMatch(curatedAsset?.address, filteredBridgeAssetAddress)) || []; -const filterAssetsFromFavoritesAndBridge = ({ +const filterAssetsFromRecentSwaps = ({ + assets, + recentSwaps, +}: { + assets: SearchAsset[] | undefined; + recentSwaps: RecentSwap[] | undefined; +}): SearchAsset[] => (assets || []).filter(asset => !recentSwaps?.some(recent => recent.address === asset.address)); + +const filterAssetsFromBridgeAndRecent = ({ + assets, + recentSwaps, + filteredBridgeAssetAddress, +}: { + assets: SearchAsset[] | undefined; + recentSwaps: RecentSwap[] | undefined; + filteredBridgeAssetAddress: string | undefined; +}): SearchAsset[] => + filterAssetsFromRecentSwaps({ + assets: filterAssetsFromBridge({ assets, filteredBridgeAssetAddress }), + recentSwaps: recentSwaps, + }); + +const filterAssetsFromFavoritesAndBridgeAndRecent = ({ assets, favoritesList, filteredBridgeAssetAddress, + recentSwaps, }: { assets: SearchAsset[] | undefined; favoritesList: SearchAsset[] | undefined; filteredBridgeAssetAddress: string | undefined; + recentSwaps: RecentSwap[] | undefined; }): SearchAsset[] => - filterAssetsFromBridge({ assets, filteredBridgeAssetAddress })?.filter( + filterAssetsFromRecentSwaps({ + assets: filterAssetsFromBridge({ assets, filteredBridgeAssetAddress }), + recentSwaps: recentSwaps, + })?.filter( curatedAsset => !favoritesList?.some(({ address }) => curatedAsset.address === address || curatedAsset.mainnetAddress === address) ) || []; @@ -79,49 +114,65 @@ const buildListSectionsData = ({ }; if (combinedData.bridgeAsset) { - addSection('bridge', [combinedData.bridgeAsset]); + addSection( + 'bridge', + mergeAssetsFavoriteStatus({ + assets: [combinedData.bridgeAsset], + favoritesList, + }) + ); } if (combinedData.recentSwaps?.length) { - const filteredRecents = filterAssetsFromFavoritesAndBridge({ + const filteredRecents = filterAssetsFromBridge({ assets: combinedData.recentSwaps, - favoritesList, filteredBridgeAssetAddress, }); - addSection('recent', filteredRecents); + + addSection( + 'recent', + mergeAssetsFavoriteStatus({ + assets: filteredRecents, + favoritesList, + }) + ); } if (favoritesList?.length) { - const filteredFavorites = filterAssetsFromBridge({ + const filteredFavorites = filterAssetsFromBridgeAndRecent({ assets: favoritesList, filteredBridgeAssetAddress, + recentSwaps: combinedData.recentSwaps, }); addSection('favorites', filteredFavorites); } if (combinedData.verifiedAssets?.length) { - const filteredVerified = filterAssetsFromFavoritesAndBridge({ + const filteredVerified = filterAssetsFromFavoritesAndBridgeAndRecent({ assets: combinedData.verifiedAssets, favoritesList, filteredBridgeAssetAddress, + recentSwaps: combinedData.recentSwaps, }); addSection('verified', filteredVerified); } if (!formattedData.length && combinedData.crosschainExactMatches?.length) { - const filteredCrosschain = filterAssetsFromFavoritesAndBridge({ + const filteredCrosschain = filterAssetsFromFavoritesAndBridgeAndRecent({ assets: combinedData.crosschainExactMatches, favoritesList, filteredBridgeAssetAddress, + recentSwaps: combinedData.recentSwaps, }); addSection('other_networks', filteredCrosschain); } if (combinedData.unverifiedAssets?.length) { - const filteredUnverified = filterAssetsFromFavoritesAndBridge({ + const filteredUnverified = filterAssetsFromFavoritesAndBridgeAndRecent({ assets: combinedData.unverifiedAssets, favoritesList, filteredBridgeAssetAddress, + recentSwaps: combinedData.recentSwaps, }); addSection('unverified', filteredUnverified); } @@ -236,10 +287,6 @@ export function useSearchCurrencyLists() { })) as SearchAsset[]; }, [favorites, state.toChainId]); - const recentsForChain = useMemo(() => { - return getRecentSwapsByChain(state.toChainId); - }, [getRecentSwapsByChain, state.toChainId]); - const memoizedData = useMemo(() => { const queryIsAddress = isAddress(query); const keys: TokenSearchAssetKey[] = queryIsAddress ? ['address'] : ['name', 'symbol']; @@ -256,23 +303,22 @@ export function useSearchCurrencyLists() { : null; const filteredBridgeAsset = bridgeAsset && filterBridgeAsset({ asset: bridgeAsset, filter: query }) ? bridgeAsset : null; - const isBridgeAssetUserFavorite = - bridgeAsset && - unfilteredFavorites.some(asset => asset.mainnetAddress === bridgeAsset.mainnetAddress || asset.address === bridgeAsset.address); return { queryIsAddress, keys, threshold, enableUnverifiedSearch, - filteredBridgeAsset: filteredBridgeAsset - ? { - ...filteredBridgeAsset, - favorite: isBridgeAssetUserFavorite, - } - : null, + filteredBridgeAsset, }; - }, [assetToSell, query, selectedOutputChainId, state, verifiedAssets, unfilteredFavorites]); + }, [assetToSell, query, selectedOutputChainId, state, verifiedAssets]); + + const recentsForChain = useMemo(() => { + return filterList(getRecentSwapsByChain(state.toChainId), query, memoizedData.keys, { + threshold: memoizedData.queryIsAddress ? rankings.CASE_SENSITIVE_EQUAL : rankings.CONTAINS, + sorter: matchItems => matchItems.sort((a, b) => b.item.swappedAt - a.item.swappedAt), + }); + }, [getRecentSwapsByChain, state.toChainId, query, memoizedData.keys, memoizedData.queryIsAddress]); const favoritesList = useMemo(() => { if (query === '') { diff --git a/src/migrations/types.ts b/src/migrations/types.ts index 6fd5aba3819..3a07a2d9bf7 100644 --- a/src/migrations/types.ts +++ b/src/migrations/types.ts @@ -20,7 +20,6 @@ export enum MigrationName { migrateRemotePromoSheetsToZustand = 'migration_migrateRemotePromoSheetsToZustand', migrateFavoritesV2 = 'migration_migrateFavoritesV2', migrateFavoritesV3 = 'migration_migrateFavoritesV3', - removeDuplicateRecentSwaps = 'migration_removeDuplicateRecentSwaps', } export type Migration = { diff --git a/src/state/swaps/swapsStore.ts b/src/state/swaps/swapsStore.ts index 5f57a35eb74..ac5fb83d92f 100644 --- a/src/state/swaps/swapsStore.ts +++ b/src/state/swaps/swapsStore.ts @@ -162,8 +162,7 @@ export const swapsStore = createRainbowStore( getRecentSwapsByChain: (chainId: ChainId) => { const { recentSwaps } = get(); - const chainSwaps = recentSwaps.get(chainId) || []; - return chainSwaps.sort((a, b) => b.swappedAt - a.swappedAt); + return recentSwaps.get(chainId) || []; }, addRecentSwap(asset) { const { recentSwaps, latestSwapAt } = get(); @@ -178,7 +177,10 @@ export const swapsStore = createRainbowStore( recentSwaps.set(chainId, updatedSwaps); latestSwapAt.set(chainId, now); - set({ recentSwaps: new Map(recentSwaps) }); + set({ + recentSwaps: new Map(recentSwaps), + latestSwapAt: new Map(latestSwapAt), + }); }, }), {