Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/develop' into @christian/remote-…
Browse files Browse the repository at this point in the history
…rainbow-store
  • Loading branch information
christianbaroni committed Dec 21, 2024
2 parents 8b11f97 + 0f4f232 commit b8c4a3c
Show file tree
Hide file tree
Showing 91 changed files with 2,656 additions and 2,918 deletions.
74 changes: 0 additions & 74 deletions scripts/add_network.sh

This file was deleted.

32 changes: 21 additions & 11 deletions src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import '@/languages';
import * as Sentry from '@sentry/react-native';
import React, { useCallback, useEffect, useState } from 'react';
import React, { useCallback, useEffect, useState, memo } from 'react';
import { AppRegistry, Dimensions, LogBox, StyleSheet, View } from 'react-native';
import { Toaster } from 'sonner-native';
import { MobileWalletProtocolProvider } from '@coinbase/mobile-wallet-protocol-host';
Expand All @@ -9,9 +9,8 @@ import { useApplicationSetup } from '@/hooks/useApplicationSetup';
import { GestureHandlerRootView } from 'react-native-gesture-handler';
import { SafeAreaProvider, useSafeAreaInsets } from 'react-native-safe-area-context';
import { enableScreens } from 'react-native-screens';
import { connect, Provider as ReduxProvider } from 'react-redux';
import { connect, Provider as ReduxProvider, shallowEqual } from 'react-redux';
import { RecoilRoot } from 'recoil';
import PortalConsumer from '@/components/PortalConsumer';
import ErrorBoundary from '@/components/error-boundary/ErrorBoundary';
import { OfflineToast } from '@/components/toasts';
import { designSystemPlaygroundEnabled, reactNativeDisableYellowBox, showNetworkRequests, showNetworkResponses } from '@/config/debug';
Expand All @@ -24,7 +23,6 @@ import store, { AppDispatch, type AppState } from '@/redux/store';
import { MainThemeProvider } from '@/theme/ThemeContext';
import { SharedValuesProvider } from '@/helpers/SharedValuesContext';
import { InitialRouteContext } from '@/navigation/initialRoute';
import { Portal } from '@/react-native-cool-modals/Portal';
import { NotificationsHandler } from '@/notifications/NotificationsHandler';
import { analyticsV2 } from '@/analytics';
import { getOrCreateDeviceId } from '@/analytics/utils';
Expand All @@ -39,6 +37,7 @@ import { RootStackParamList } from '@/navigation/types';
import { IS_ANDROID, IS_DEV } from '@/env';
import { prefetchDefaultFavorites } from '@/resources/favorites';
import Routes from '@/navigation/Routes';
import { BackupsSync } from '@/state/sync/BackupsSync';
import { BackendNetworks } from '@/components/BackendNetworks';
import { AbsolutePortalRoot } from './components/AbsolutePortal';

Expand Down Expand Up @@ -68,28 +67,39 @@ function App({ walletReady }: AppProps) {
}, []);

return (
<Portal>
<>
<View style={[sx.container, { paddingBottom: IS_ANDROID ? bottom : 0 }]}>
{initialRoute && (
<InitialRouteContext.Provider value={initialRoute}>
<Routes ref={handleNavigatorRef} />
<PortalConsumer />
<AbsolutePortalRoot />
</InitialRouteContext.Provider>
)}
<OfflineToast />
<Toaster />
</View>
<NotificationsHandler walletReady={walletReady} />
<DeeplinkHandler initialRoute={initialRoute} walletReady={walletReady} />
<BackupsSync />
<BackendNetworks />
</Portal>
<AbsolutePortalRoot />
</>
);
}

const AppWithRedux = connect<AppProps, AppDispatch, AppProps, AppState>(state => ({
walletReady: state.appState.walletReady,
}))(App);
const AppWithRedux = connect<AppProps, AppDispatch, AppProps, AppState>(
state => ({
walletReady: state.appState.walletReady,
}),
null,
null,
{
areStatesEqual: (next, prev) => {
// Only update if walletReady actually changed
return next.appState.walletReady === prev.appState.walletReady;
},
areOwnPropsEqual: shallowEqual,
}
)(memo(App));

function Root() {
const [initializing, setInitializing] = useState(true);
Expand Down
53 changes: 34 additions & 19 deletions src/__swaps__/screens/Swap/hooks/useSearchCurrencyLists.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,14 @@ import { useFavorites } from '@/resources/favorites';
import { useSwapsStore } from '@/state/swaps/swapsStore';
import { isAddress } from '@ethersproject/address';
import { rankings } from 'match-sorter';
import { useCallback, useMemo, useState } from 'react';
import { useCallback, useEffect, useMemo, useState } from 'react';
import { runOnJS, useAnimatedReaction } from 'react-native-reanimated';
import { useDebouncedCallback } from 'use-debounce';
import { TokenToBuyListItem } from '../components/TokenList/TokenToBuyList';
import { useSwapContext } from '../providers/swap-provider';
import { RecentSwap } from '@/__swaps__/types/swap';
import { useTokenDiscovery } from '../resources/search';
import { analyticsV2 } from '@/analytics';

export type AssetToBuySectionId = 'bridge' | 'recent' | 'favorites' | 'verified' | 'unverified' | 'other_networks' | 'popular';

Expand Down Expand Up @@ -321,7 +322,7 @@ export function useSearchCurrencyLists() {
const { data: verifiedAssets, isLoading: isLoadingVerifiedAssets } = useTokenSearch(
{
list: 'verifiedAssets',
chainId: isAddress(query) ? state.toChainId : undefined,
chainId: state.toChainId,
keys: isAddress(query) ? ['address'] : ['name', 'symbol'],
threshold: isAddress(query) ? 'CASE_SENSITIVE_EQUAL' : 'CONTAINS',
query: query.length > 0 ? query : undefined,
Expand Down Expand Up @@ -417,33 +418,34 @@ export function useSearchCurrencyLists() {
{
enabled: memoizedData.enableUnverifiedSearch,
select: (data: TokenSearchResult) => {
return getExactMatches(data, query).slice(0, MAX_UNVERIFIED_RESULTS);
return isAddress(query) ? getExactMatches(data, query).slice(0, MAX_UNVERIFIED_RESULTS) : data.slice(0, MAX_UNVERIFIED_RESULTS);
},
}
);

return useMemo(() => {
const searchCurrencyLists = useMemo(() => {
const toChainId = selectedOutputChainId.value ?? ChainId.mainnet;
const bridgeResult = memoizedData.filteredBridgeAsset ?? undefined;
const crosschainMatches = query === '' ? undefined : verifiedAssets?.filter(asset => asset.chainId !== toChainId);
const verifiedResults = query === '' ? verifiedAssets : verifiedAssets?.filter(asset => asset.chainId === toChainId);
const unverifiedResults = memoizedData.enableUnverifiedSearch ? unverifiedAssets : undefined;

return {
results: buildListSectionsData({
combinedData: {
bridgeAsset: bridgeResult,
crosschainExactMatches: crosschainMatches,
unverifiedAssets: unverifiedResults,
verifiedAssets: verifiedResults,
recentSwaps: recentsForChain,
popularAssets: popularAssetsForChain,
},
favoritesList,
filteredBridgeAssetAddress: memoizedData.filteredBridgeAsset?.address,
}),
isLoading: isLoadingVerifiedAssets || isLoadingUnverifiedAssets || isLoadingPopularAssets,
};
const results = buildListSectionsData({
combinedData: {
bridgeAsset: bridgeResult,
crosschainExactMatches: crosschainMatches,
unverifiedAssets: unverifiedResults,
verifiedAssets: verifiedResults,
recentSwaps: recentsForChain,
popularAssets: popularAssetsForChain,
},
favoritesList,
filteredBridgeAssetAddress: memoizedData.filteredBridgeAsset?.address,
});

const isLoading = isLoadingVerifiedAssets || isLoadingUnverifiedAssets || isLoadingPopularAssets;

return { results, isLoading };
}, [
favoritesList,
isLoadingUnverifiedAssets,
Expand All @@ -458,4 +460,17 @@ export function useSearchCurrencyLists() {
recentsForChain,
popularAssetsForChain,
]);

useEffect(() => {
if (searchCurrencyLists.isLoading) return;
const params = { screen: 'swap' as const, total_tokens: 0, no_icon: 0, query };
for (const assetOrHeader of searchCurrencyLists.results) {
if (assetOrHeader.listItemType === 'header') continue;
if (!assetOrHeader.icon_url) params.no_icon += 1;
params.total_tokens += 1;
}
analyticsV2.track(analyticsV2.event.tokenList, params);
}, [searchCurrencyLists.results, searchCurrencyLists.isLoading, query]);

return searchCurrencyLists;
}
2 changes: 1 addition & 1 deletion src/__swaps__/screens/Swap/resources/search/discovery.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { useQuery } from '@tanstack/react-query';
import { parseTokenSearch } from './utils';

const tokenSearchHttp = new RainbowFetchClient({
baseURL: 'https://token-search.rainbow.me/v3/discovery',
baseURL: 'https://token-search.rainbow.me/v3/trending/swaps',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
Expand Down
19 changes: 14 additions & 5 deletions src/__swaps__/screens/Swap/resources/search/search.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { parseTokenSearch } from './utils';
const ALL_VERIFIED_TOKENS_PARAM = '/?list=verifiedAssets';

const tokenSearchHttp = new RainbowFetchClient({
baseURL: 'https://token-search.rainbow.me/v2',
baseURL: 'https://token-search.rainbow.me/v3/tokens',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
Expand All @@ -30,13 +30,19 @@ export type TokenSearchArgs = {
list: TokenSearchListId;
threshold?: TokenSearchThreshold;
query?: string;
shouldPersist?: boolean;
};

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

const tokenSearchQueryKey = ({ chainId, fromChainId, keys, list, threshold, query }: TokenSearchArgs) =>
createQueryKey('TokenSearch', { chainId, fromChainId, keys, list, threshold, query }, { persisterVersion: 2 });
const tokenSearchQueryKey = ({ chainId, fromChainId, keys, list, threshold, query, shouldPersist }: TokenSearchArgs) => {
return createQueryKey(
'TokenSearch',
{ chainId, fromChainId, keys, list, threshold, query },
{ persisterVersion: shouldPersist ? 3 : undefined }
);
};

type TokenSearchQueryKey = ReturnType<typeof tokenSearchQueryKey>;

Expand Down Expand Up @@ -77,6 +83,7 @@ async function tokenSearchQueryFunction({
return parseTokenSearch(tokenSearch.data.data, chainId);
}

// search for address on other chains
const allVerifiedTokens = await tokenSearchHttp.get<{ data: SearchAsset[] }>(ALL_VERIFIED_TOKENS_PARAM);

const addressQuery = query.trim().toLowerCase();
Expand Down Expand Up @@ -104,8 +111,9 @@ export async function fetchTokenSearch(
{ chainId, fromChainId, keys, list, threshold, query }: TokenSearchArgs,
config: QueryConfigWithSelect<TokenSearchResult, Error, TokenSearchResult, TokenSearchQueryKey> = {}
) {
const shouldPersist = query === undefined;
return await queryClient.fetchQuery(
tokenSearchQueryKey({ chainId, fromChainId, keys, list, threshold, query }),
tokenSearchQueryKey({ chainId, fromChainId, keys, list, threshold, query, shouldPersist }),
tokenSearchQueryFunction,
config
);
Expand All @@ -130,7 +138,8 @@ export function useTokenSearch(
{ chainId, fromChainId, keys, list, threshold, query }: TokenSearchArgs,
config: QueryConfigWithSelect<TokenSearchResult, Error, TokenSearchResult, TokenSearchQueryKey> = {}
) {
return useQuery(tokenSearchQueryKey({ chainId, fromChainId, keys, list, threshold, query }), tokenSearchQueryFunction, {
const shouldPersist = query === undefined;
return useQuery(tokenSearchQueryKey({ chainId, fromChainId, keys, list, threshold, query, shouldPersist }), tokenSearchQueryFunction, {
...config,
keepPreviousData: true,
});
Expand Down
11 changes: 11 additions & 0 deletions src/analytics/event.ts
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,9 @@ export const event = {
tokenDetailsErc20: 'token_details.erc20',
tokenDetailsNFT: 'token_details.nft',

// token lists (wallet, swap, send)
tokenList: 'token_list',

// trending tokens
viewTrendingToken: 'trending_tokens.view_trending_token',
viewRankedCategory: 'trending_tokens.view_ranked_category',
Expand Down Expand Up @@ -717,6 +720,14 @@ export type EventProperties = {
available_data: { description: boolean; image_url: boolean; floorPrice: boolean };
};

[event.tokenList]: {
screen: 'wallet' | 'swap' | 'send' | 'discover';
total_tokens: number;
no_icon: number;
no_price?: number;
query?: string; // query is only sent for the swap screen
};

[event.viewTrendingToken]: {
address: TrendingToken['address'];
chainId: TrendingToken['chainId'];
Expand Down
6 changes: 3 additions & 3 deletions src/components/AbsolutePortal.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React, { PropsWithChildren, ReactNode, useEffect, useState } from 'react';
import { View } from 'react-native';
import { StyleProp, ViewStyle, View } from 'react-native';

const absolutePortal = {
nodes: [] as ReactNode[],
Expand All @@ -24,15 +24,15 @@ const absolutePortal = {
},
};

export const AbsolutePortalRoot = () => {
export const AbsolutePortalRoot = ({ style }: { style?: StyleProp<ViewStyle> }) => {
const [nodes, setNodes] = useState(absolutePortal.nodes);

useEffect(() => {
const unsubscribe = absolutePortal.subscribe(setNodes);
return () => unsubscribe();
}, []);

return <View style={{ position: 'absolute', top: 0, left: 0, right: 0, bottom: 0, pointerEvents: 'box-none' }}>{nodes}</View>;
return <View style={[style, { position: 'absolute', top: 0, left: 0, right: 0, bottom: 0, pointerEvents: 'box-none' }]}>{nodes}</View>;
};

export const AbsolutePortal = ({ children }: PropsWithChildren) => {
Expand Down
3 changes: 2 additions & 1 deletion src/components/Discover/DiscoverHome.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -70,10 +70,11 @@ export default function DiscoverHome() {
<GasCard />
{isProfilesEnabled && <ENSSearchCard />}
</Inline>
<Separator color="separatorTertiary" thickness={1} />
{trendingTokensEnabled && (
<>
<Separator color="separatorSecondary" thickness={1} />
<TrendingTokens />
<Separator color="separatorTertiary" thickness={1} />
</>
)}
<RemoteCardCarousel />
Expand Down
Loading

0 comments on commit b8c4a3c

Please sign in to comment.