Skip to content

Commit

Permalink
Merge branch 'develop' into @matthew/fix-backups-e2e
Browse files Browse the repository at this point in the history
  • Loading branch information
walmat committed Dec 20, 2024
2 parents 99578d9 + 011df97 commit d8822cd
Show file tree
Hide file tree
Showing 12 changed files with 136 additions and 49 deletions.
49 changes: 32 additions & 17 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 @@ -422,28 +423,29 @@ export function useSearchCurrencyLists() {
}
);

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;
}
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
26 changes: 25 additions & 1 deletion src/components/Discover/DiscoverSearch.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import deviceUtils from '@/utils/deviceUtils';
import CurrencySelectionList from '@/components/CurrencySelectionList';
import { Row } from '@/components/layout';
import { useDiscoverScreenContext } from '@/components/Discover/DiscoverScreenContext';
import { analytics } from '@/analytics';
import { analytics, analyticsV2 } from '@/analytics';
import { PROFILES, useExperimentalFlag } from '@/config';
import { useAccountSettings, useSearchCurrencyList, usePrevious, useHardwareBackOnFocus } from '@/hooks';
import { useNavigation } from '@/navigation';
Expand All @@ -25,6 +25,7 @@ import { useTheme } from '@/theme';
import { EnrichedExchangeAsset } from '@/components/ExchangeAssetList';
import { useBackendNetworksStore } from '@/state/backendNetworks/backendNetworks';
import { ChainId, Network } from '@/state/backendNetworks/types';
import { useTimeoutEffect } from '@/hooks/useTimeout';

export const SearchContainer = styled(Row)({
height: '100%',
Expand Down Expand Up @@ -270,6 +271,29 @@ export default function DiscoverSearch() {
});
}, [sectionListRef, isSearching]);

useTimeoutEffect(
() => {
const assets = currencyList
.filter(a => a.key !== 'profiles')
.map(asset => asset.data)
.flat();
if (assets.length === 0) return;
const params = {
screen: 'discover' as const,
no_icon: 0,
no_price: 0,
total_tokens: assets.length,
query: searchQueryForSearch,
};
for (const asset of assets) {
if (!asset.icon_url) params.no_icon += 1;
if (!isNaN(asset.price?.value)) params.no_price += 1;
}
analyticsV2.track(analyticsV2.event.tokenList, params);
},
{ timeout: 3000, enabled: !isLoading }
);

return (
<View key={currencyListDataKey} style={{ height: deviceUtils.dimensions.height - TOP_OFFSET - marginBottom }}>
<SearchContainer>
Expand Down
12 changes: 6 additions & 6 deletions src/components/Discover/TrendingTokens.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { DropdownMenu, MenuItem } from '@/components/DropdownMenu';
import { DropdownMenu } from '@/components/DropdownMenu';
import { globalColors, Text, TextIcon, useBackgroundColor, useColorMode } from '@/design-system';
import { useForegroundColor } from '@/design-system/color/useForegroundColor';

Expand All @@ -19,7 +19,6 @@ import { swapsStore } from '@/state/swaps/swapsStore';
import { sortFilters, timeFilters, useTrendingTokensStore } from '@/state/trendingTokens/trendingTokens';
import { colors } from '@/styles';
import { darkModeThemeColors } from '@/styles/colors';
import { useTheme } from '@/theme';
import { useCallback, useEffect, useMemo } from 'react';
import React, { Dimensions, FlatList, View } from 'react-native';
import LinearGradient from 'react-native-linear-gradient';
Expand Down Expand Up @@ -514,26 +513,27 @@ function NoResults() {

function NetworkFilter() {
const { isDarkMode } = useColorMode();
const { colors } = useTheme();

const selected = useSharedValue<ChainId | undefined>(undefined);
const chainId = useTrendingTokensStore(state => state.chainId);
const setChainId = useTrendingTokensStore(state => state.setChainId);

const { icon, label, lightenedNetworkColor } = useMemo(() => {
if (!chainId) return { icon: '􀤆', label: i18n.t(t.all), lightenedNetworkColor: undefined };
const lightenedNetworkColor = useBackendNetworksStore.getState().getColorsForChainId(chainId, isDarkMode);

return {
icon: (
<View style={{ marginRight: 2 }}>
<ChainImage chainId={chainId} size={16} />
</View>
),
label: useBackendNetworksStore.getState().getChainsLabel()[chainId],
lightenedNetworkColor: colors.networkColors[chainId]
? getMixedColor(colors.networkColors[chainId], globalColors.white100, isDarkMode ? 0.55 : 0.6)
lightenedNetworkColor: lightenedNetworkColor
? getMixedColor(lightenedNetworkColor, globalColors.white100, isDarkMode ? 0.55 : 0.6)
: undefined,
};
}, [chainId, colors.networkColors, isDarkMode]);
}, [chainId, isDarkMode]);

const setSelected = useCallback(
(chainId: ChainId | undefined) => {
Expand Down
5 changes: 3 additions & 2 deletions src/components/NetworkSwitcher.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -373,9 +373,10 @@ function AllNetworksSection({
}

function NetworkOption({ chainId, selected }: { chainId: ChainId; selected: SharedValue<ChainId | undefined> }) {
const { colors } = useTheme();
const { isDarkMode } = useColorMode();
const getColorsForChainId = useBackendNetworksStore(state => state.getColorsForChainId);
const chainName = useBackendNetworksStore.getState().getChainsLabel()[chainId];
const chainColor = colors.networkColors[chainId] ? colors.networkColors[chainId] : undefined;
const chainColor = getColorsForChainId(chainId, isDarkMode);
const isSelected = useDerivedValue(() => selected.value === chainId);
const { animatedStyle } = useNetworkOptionStyle(isSelected, chainColor);

Expand Down
7 changes: 3 additions & 4 deletions src/components/expanded-state/UniqueTokenExpandedState.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -417,18 +417,17 @@ const UniqueTokenExpandedState = ({ asset: passedAsset, external }: UniqueTokenE

const hideNftMarketplaceAction = isPoap || !slug;

const mountedAt = useRef(Date.now());
useTimeoutEffect(
() => {
({ elapsedTime }) => {
const { address, chainId } = getAddressAndChainIdFromUniqueId(uniqueId);
const { name, description, image_url } = asset;
analyticsV2.track(analyticsV2.event.tokenDetailsNFT, {
eventSentAfterMs: Date.now() - mountedAt.current,
eventSentAfterMs: elapsedTime,
token: { isPoap, isParty: !!isParty, isENS, address, chainId, name, image_url },
available_data: { description: !!description, image_url: !!image_url, floorPrice: !!offer?.floorPrice },
});
},
5 * 1000 // 5s
{ timeout: 5 * 1000 }
);
return (
<>
Expand Down
7 changes: 3 additions & 4 deletions src/components/expanded-state/asset/ChartExpandedState.js
Original file line number Diff line number Diff line change
Expand Up @@ -257,17 +257,16 @@ export default function ChartExpandedState({ asset }) {
[nativeCurrency]
);

const mountedAt = useRef(Date.now());
useTimeoutEffect(
() => {
({ elapsedTime }) => {
const { address, chainId, symbol, name, icon_url, price } = assetWithPrice;
analyticsV2.track(analyticsV2.event.tokenDetailsErc20, {
eventSentAfterMs: Date.now() - mountedAt.current,
eventSentAfterMs: elapsedTime,
token: { address, chainId, symbol, name, icon_url, price },
available_data: { chart: showChart, description: !!data?.description, iconUrl: !!icon_url },
});
},
5 * 1000 // 5s
{ timeout: 5 * 1000 }
);

return (
Expand Down
24 changes: 18 additions & 6 deletions src/hooks/useTimeout.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,20 +18,32 @@ export default function useTimeout(): [(func: () => void, ms?: number) => void,
return [start, stop, handle];
}

export function useTimeoutEffect(onTimeout: (cancelled: boolean) => void, delay: number) {
export function useTimeoutEffect(
onTimeout: (e: { cancelled: boolean; elapsedTime: number }) => void,
{ timeout, enabled = true }: { timeout: number; enabled?: boolean }
) {
const callback = useRef(onTimeout);
useLayoutEffect(() => {
callback.current = onTimeout;
}, [onTimeout]);

const timeoutRef = useRef<NodeJS.Timeout>();
useEffect(() => {
if (!enabled) return;
const startedAt = Date.now();
timeoutRef.current = setTimeout(() => callback.current(false), delay);
const timeout = timeoutRef.current;
timeoutRef.current = setTimeout(() => {
callback.current({
cancelled: false,
elapsedTime: Date.now() - startedAt,
});
}, timeout);
return () => {
clearTimeout(timeout);
if (Date.now() - startedAt < delay) callback.current(true);
if (!timeoutRef.current) return;
clearTimeout(timeoutRef.current);
const elapsedTime = Date.now() - startedAt;
if (elapsedTime < timeout) {
callback.current({ cancelled: true, elapsedTime });
}
};
}, [delay]);
}, [timeout, enabled]);
}
10 changes: 10 additions & 0 deletions src/hooks/useWalletSectionsData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,16 @@ export default function useWalletSectionsData({

const { isCoinListEdited } = useCoinListEdited();

useEffect(() => {
if (isLoadingUserAssets || type !== 'wallet') return;
const params = { screen: 'wallet' as const, no_icon: 0, no_price: 0, total_tokens: sortedAssets.length };
for (const asset of sortedAssets) {
if (!asset.icon_url) params.no_icon += 1;
if (!asset.price?.relative_change_24h) params.no_price += 1;
}
analyticsV2.track(analyticsV2.event.tokenList, params);
}, [isLoadingUserAssets, sortedAssets, type]);

const walletSections = useMemo(() => {
const accountInfo = {
hiddenAssets,
Expand Down
14 changes: 7 additions & 7 deletions src/screens/ExplainSheet.js
Original file line number Diff line number Diff line change
Expand Up @@ -733,7 +733,7 @@ export const explainers = (params, theme) => {
},
swap_refuel_add: {
logo: (
<DashedWrapper size={50} childXPosition={10} colors={[colors?.networkColors[chainId], colors?.appleBlue]}>
<DashedWrapper size={50} childXPosition={10} colors={[color, colors?.appleBlue]}>
<RainbowCoinIcon
size={30}
icon={params?.nativeAsset?.icon_url}
Expand Down Expand Up @@ -764,14 +764,14 @@ export const explainers = (params, theme) => {
networkName: params?.networkName,
gasToken: params?.gasToken,
}),
textColor: colors?.networkColors[chainId],
bgColor: colors?.networkColors[chainId] && colors?.alpha(colors?.networkColors[chainId], 0.05),
textColor: color,
bgColor: color && colors?.alpha(color, 0.05),
onPress: params?.onRefuel,
},
},
swap_refuel_deduct: {
logo: (
<DashedWrapper size={50} childXPosition={10} colors={[colors?.networkColors[chainId], colors?.appleBlue]}>
<DashedWrapper size={50} childXPosition={10} colors={[color, colors?.appleBlue]}>
<RainbowCoinIcon
size={30}
icon={params?.nativeAsset?.icon_url}
Expand Down Expand Up @@ -802,15 +802,15 @@ export const explainers = (params, theme) => {
networkName: params?.networkName,
gasToken: params?.gasToken,
}),
textColor: colors?.networkColors[chainId],
bgColor: colors?.networkColors[chainId] && colors?.alpha(colors?.networkColors[chainId], 0.05),
textColor: color,
bgColor: color && colors?.alpha(color, 0.05),
onPress: params?.onRefuel,
},
},
swap_refuel_notice: {
extraHeight: 50,
logo: (
<DashedWrapper size={50} childXPosition={10} colors={[colors?.networkColors[chainId], colors?.appleBlue]}>
<DashedWrapper size={50} childXPosition={10} colors={[color, colors?.appleBlue]}>
<RainbowCoinIcon
size={30}
icon={params?.nativeAsset?.icon_url}
Expand Down
13 changes: 12 additions & 1 deletion src/screens/SendSheet.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { SendAssetForm, SendAssetList, SendContactList, SendHeader } from '../co
import { SheetActionButton } from '../components/sheet';
import { getDefaultCheckboxes } from './SendConfirmationSheet';
import { WrappedAlert as Alert } from '@/helpers/alert';
import { analytics } from '@/analytics';
import { analytics, analyticsV2 } from '@/analytics';
import { PROFILES, useExperimentalFlag } from '@/config';
import { AssetTypes, NewTransaction, ParsedAddressAsset, TransactionStatus, UniqueAsset } from '@/entities';
import { isNativeAsset } from '@/handlers/assets';
Expand Down Expand Up @@ -129,6 +129,7 @@ type OnSubmitProps = {
export default function SendSheet() {
const { goBack, navigate } = useNavigation();
const sortedAssets = useUserAssetsStore(state => state.legacyUserAssets);
const isLoadingUserAssets = useUserAssetsStore(state => state.isLoadingUserAssets);
const {
gasFeeParamsBySpeed,
gasLimit,
Expand Down Expand Up @@ -894,6 +895,16 @@ export default function SendSheet() {
isUniqueAsset,
]);

useEffect(() => {
if (isLoadingUserAssets || !sortedAssets) return;
const params = { screen: 'send' as const, no_icon: 0, no_price: 0, total_tokens: sortedAssets.length };
for (const asset of sortedAssets) {
if (!asset.icon_url) params.no_icon += 1;
if (!asset.price?.relative_change_24h) params.no_price += 1;
}
analyticsV2.track(analyticsV2.event.tokenList, params);
}, [isLoadingUserAssets, sortedAssets]);

const sendContactListDataKey = useMemo(() => `${ensSuggestions?.[0]?.address || '_'}`, [ensSuggestions]);

const isEmptyWallet = !sortedAssets?.length && !sendableUniqueTokens?.length;
Expand Down
Loading

0 comments on commit d8822cd

Please sign in to comment.