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

Add analytics #5805

Merged
merged 13 commits into from
Jun 11, 2024
11 changes: 9 additions & 2 deletions src/__swaps__/screens/Swap/components/FlipButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,20 +12,27 @@ import { AnimatedBlurView } from '@/__swaps__/screens/Swap/components/AnimatedBl
import { useSwapContext } from '@/__swaps__/screens/Swap/providers/swap-provider';
import { TIMING_CONFIGS } from '@/components/animations/animationConfigs';
import { SwapAssetType } from '@/__swaps__/types/swap';
import { analyticsV2 } from '@/analytics';

export const FlipButton = () => {
const { isDarkMode } = useColorMode();

const { AnimatedSwapStyles, internalSelectedInputAsset, internalSelectedOutputAsset, setAsset } = useSwapContext();
const { AnimatedSwapStyles, internalSelectedInputAsset, internalSelectedOutputAsset, setAsset, SwapInputController } = useSwapContext();

const handleSwapAssets = useCallback(() => {
if (internalSelectedInputAsset.value && internalSelectedOutputAsset.value) {
const assetTypeToSet = SwapAssetType.outputAsset;
const assetToSet = internalSelectedInputAsset.value;

analyticsV2.track(analyticsV2.event.swapsFlippedAssets, {
inputAmount: SwapInputController.inputValues.value.inputAmount,
previousInputAsset: internalSelectedInputAsset.value,
previousOutputAsset: internalSelectedOutputAsset.value,
});

setAsset({ type: assetTypeToSet, asset: assetToSet });
}
}, [internalSelectedInputAsset, internalSelectedOutputAsset, /* lastTypedInput, */ setAsset]);
}, [SwapInputController.inputValues, internalSelectedInputAsset, internalSelectedOutputAsset, setAsset]);

const flipButtonInnerStyles = useAnimatedStyle(() => {
return {
Expand Down
28 changes: 16 additions & 12 deletions src/__swaps__/screens/Swap/components/GasButton.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { ChainId } from '@/__swaps__/types/chains';
import { weiToGwei } from '@/__swaps__/utils/ethereum';
import { OnPressMenuItemEventObject } from 'react-native-ios-context-menu';
import { getCachedCurrentBaseFee, useMeteorologySuggestions } from '@/__swaps__/utils/meteorology';
import { add } from '@/__swaps__/utils/numbers';
import { ContextMenu } from '@/components/context-menu';
Expand All @@ -8,15 +9,16 @@ import ContextMenuButton from '@/components/native-context-menu/contextMenu';
import { Box, Inline, Text, TextIcon, useColorMode, useForegroundColor } from '@/design-system';
import { IS_ANDROID } from '@/env';
import * as i18n from '@/languages';
import { useSwapsStore } from '@/state/swaps/swapsStore';
import { swapsStore } from '@/state/swaps/swapsStore';
import { gasUtils } from '@/utils';
import React, { ReactNode, useCallback, useMemo } from 'react';
import { StyleSheet } from 'react-native';
import { runOnJS, runOnUI } from 'react-native-reanimated';
import { ETH_COLOR, ETH_COLOR_DARK, THICK_BORDER_WIDTH } from '../constants';
import { formatNumber } from '../hooks/formatNumber';
import { GasSettings, useCustomGasSettings } from '../hooks/useCustomGas';
import { GasSpeed, setSelectedGasSpeed, useSelectedGas, useSelectedGasSpeed } from '../hooks/useSelectedGas';
import { GasSpeed } from '@/__swaps__/types/gas';
import { setSelectedGasSpeed, useSelectedGas, useSelectedGasSpeed } from '../hooks/useSelectedGas';
import { useSwapContext } from '../providers/swap-provider';
import { EstimatedSwapGasFee } from './EstimatedSwapGasFee';
import { GestureHandlerV1Button } from './GestureHandlerV1Button';
Expand All @@ -26,7 +28,7 @@ const { GAS_ICONS } = gasUtils;
const GAS_BUTTON_HIT_SLOP = 16;

function EstimatedGasFee() {
const chainId = useSwapsStore(s => s.inputAsset?.chainId || ChainId.mainnet);
const chainId = swapsStore(s => s.inputAsset?.chainId || ChainId.mainnet);
const gasSettings = useSelectedGas(chainId);

return (
Expand All @@ -40,7 +42,7 @@ function EstimatedGasFee() {
}

function SelectedGas() {
const chainId = useSwapsStore(s => s.inputAsset?.chainId || ChainId.mainnet);
const chainId = swapsStore(s => s.inputAsset?.chainId || ChainId.mainnet);
const selectedGasSpeed = useSelectedGasSpeed(chainId);

return (
Expand Down Expand Up @@ -83,30 +85,32 @@ function keys<const T extends string>(obj: Record<T, any> | undefined) {
const GasMenu = ({ backToReview = false, children }: { backToReview?: boolean; children: ReactNode }) => {
const { SwapNavigation } = useSwapContext();

const chainId = useSwapsStore(s => s.inputAsset?.chainId || ChainId.mainnet);
const chainId = swapsStore(s => s.inputAsset?.chainId || ChainId.mainnet);
const metereologySuggestions = useMeteorologySuggestions({ chainId });
const customGasSettings = useCustomGasSettings(chainId);

const menuOptions = useMemo(() => [...keys(metereologySuggestions.data), 'custom'] as const, [metereologySuggestions.data]);
const menuOptions = useMemo(() => [...keys(metereologySuggestions.data), GasSpeed.CUSTOM] as GasSpeed[], [metereologySuggestions.data]);

const handlePressSpeedOption = useCallback(
(selectedGasSpeed: GasSpeed) => {
setSelectedGasSpeed(chainId, selectedGasSpeed);

if (selectedGasSpeed === 'custom') {
if (selectedGasSpeed === GasSpeed.CUSTOM) {
runOnUI(SwapNavigation.handleShowGas)({ backToReview });
}
},
[SwapNavigation.handleShowGas, backToReview, chainId]
);

const handlePressMenuItem = useCallback(
({ nativeEvent: { actionKey } }: any) => handlePressSpeedOption(actionKey),
({ nativeEvent: { actionKey } }: OnPressMenuItemEventObject) => handlePressSpeedOption(actionKey as GasSpeed),
[handlePressSpeedOption]
);

const handlePressActionSheet = useCallback(
(buttonIndex: number) => handlePressSpeedOption(menuOptions[buttonIndex]),
(buttonIndex: number) => {
if (buttonIndex < 0) return;
handlePressSpeedOption(menuOptions[buttonIndex]);
},
[handlePressSpeedOption, menuOptions]
);

Expand All @@ -115,7 +119,7 @@ const GasMenu = ({ backToReview = false, children }: { backToReview?: boolean; c
if (IS_ANDROID) return gasOption;

const currentBaseFee = getCachedCurrentBaseFee(chainId);
const gasSettings = gasOption === 'custom' ? customGasSettings : metereologySuggestions.data?.[gasOption];
const gasSettings = gasOption === GasSpeed.CUSTOM ? customGasSettings : metereologySuggestions.data?.[gasOption];
const subtitle = getEstimatedFeeRangeInGwei(gasSettings, currentBaseFee);

return {
Expand Down Expand Up @@ -176,7 +180,7 @@ export function ReviewGasButton() {
const handleShowCustomGas = () => {
'worklet';

runOnJS(setSelectedGasSpeed)(internalSelectedInputAsset.value?.chainId || ChainId.mainnet, 'custom');
runOnJS(setSelectedGasSpeed)(internalSelectedInputAsset.value?.chainId || ChainId.mainnet, GasSpeed.CUSTOM);
SwapNavigation.handleShowGas({ backToReview: true });
};

Expand Down
5 changes: 3 additions & 2 deletions src/__swaps__/screens/Swap/components/GasPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import { formatNumber } from '../hooks/formatNumber';
import { GasSettings, getCustomGasSettings, setCustomGasSettings, useCustomGasStore } from '../hooks/useCustomGas';
import { setSelectedGasSpeed, useSelectedGasSpeed } from '../hooks/useSelectedGas';
import { EstimatedSwapGasFee } from './EstimatedSwapGasFee';
import { GasSpeed } from '@/__swaps__/types/gas';

const { GAS_TRENDS } = gasUtils;

Expand Down Expand Up @@ -334,12 +335,12 @@ function saveCustomGasSettings() {
const { inputAsset } = useSwapsStore.getState();
const chainId = inputAsset?.chainId || ChainId.mainnet;
if (!unsaved) {
if (getCustomGasSettings(chainId)) setSelectedGasSpeed(chainId, 'custom');
if (getCustomGasSettings(chainId)) setSelectedGasSpeed(chainId, GasSpeed.CUSTOM);
return;
}

setCustomGasSettings(chainId, unsaved);
setSelectedGasSpeed(chainId, 'custom');
setSelectedGasSpeed(chainId, GasSpeed.CUSTOM);
useGasPanelStore.setState(undefined);
}

Expand Down
22 changes: 8 additions & 14 deletions src/__swaps__/screens/Swap/components/SearchInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -77,21 +77,15 @@ export const SearchInput = ({
};
});

const onInputSearchQueryChange = useDebouncedCallback(
(text: string) => {
userAssetsStore.getState().setSearchQuery(text);
},
50,
{ leading: true, trailing: true }
);
const onInputSearchQueryChange = useDebouncedCallback((text: string) => userAssetsStore.getState().setSearchQuery(text), 50, {
leading: true,
trailing: true,
});

const onOutputSearchQueryChange = useDebouncedCallback(
(text: string) => {
useSwapsStore.setState({ outputSearchQuery: text });
},
100,
{ leading: false, trailing: true }
);
const onOutputSearchQueryChange = useDebouncedCallback((text: string) => useSwapsStore.setState({ outputSearchQuery: text }), 100, {
leading: false,
trailing: true,
});

const isSearchFocused = useDerivedValue(
() =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ import { OnPressMenuItemEventObject } from 'react-native-ios-context-menu';
import { userAssetsStore } from '@/state/assets/userAssets';
import { useSharedValueState } from '@/hooks/reanimated/useSharedValueState';
import { chainNameForChainIdWithMainnetSubstitution } from '@/__swaps__/utils/chains';
import { analyticsV2 } from '@/analytics';
import { swapsStore } from '@/state/swaps/swapsStore';

type ChainSelectionProps = {
allText?: string;
Expand Down Expand Up @@ -50,6 +52,12 @@ export const ChainSelection = memo(function ChainSelection({ allText, output }:

const handleSelectChain = useCallback(
({ nativeEvent: { actionKey } }: Omit<OnPressMenuItemEventObject, 'isUsingActionSheetFallback'>) => {
analyticsV2.track(analyticsV2.event.swapsChangedChainId, {
inputAsset: swapsStore.getState().inputAsset,
type: output ? 'output' : 'input',
chainId: Number(actionKey) as ChainId,
});

if (output) {
setSelectedOutputChainId(Number(actionKey) as ChainId);
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ import { userAssetsStore } from '@/state/assets/userAssets';
import { EXPANDED_INPUT_HEIGHT } from '../../constants';
import { DEVICE_WIDTH } from '@/utils/deviceUtils';
import { getStandardizedUniqueIdWorklet } from '@/__swaps__/utils/swaps';
import { swapsStore } from '@/state/swaps/swapsStore';
import { analyticsV2 } from '@/analytics';

interface SectionProp {
color: TextStyle['color'];
Expand Down Expand Up @@ -95,6 +97,16 @@ export const TokenToBuySection = ({ section }: { section: AssetToBuySection }) =
type: SwapAssetType.outputAsset,
asset: parsedAsset,
});

const { outputSearchQuery } = swapsStore.getState();

// track what search query the user had prior to selecting an asset
if (outputSearchQuery.trim().length) {
analyticsV2.track(analyticsV2.event.swapsSearchedForToken, {
query: outputSearchQuery,
type: 'output',
});
}
},
[internalSelectedInputAsset, internalSelectedOutputAsset, isFetching, isQuoteStale, setAsset]
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ import { EXPANDED_INPUT_HEIGHT } from '../../constants';
import { DEVICE_WIDTH } from '@/utils/deviceUtils';
import { getStandardizedUniqueIdWorklet } from '@/__swaps__/utils/swaps';
import { useDelayedMount } from '@/hooks/useDelayedMount';
import { swapsStore } from '@/state/swaps/swapsStore';
import { analyticsV2 } from '@/analytics';

export const TokenToSellList = () => {
const shouldMount = useDelayedMount();
Expand Down Expand Up @@ -43,6 +45,16 @@ const TokenToSellListComponent = () => {
type: SwapAssetType.inputAsset,
asset: token,
});

const { inputSearchQuery } = userAssetsStore.getState();

// track what search query the user had prior to selecting an asset
if (inputSearchQuery.trim().length) {
analyticsV2.track(analyticsV2.event.swapsSearchedForToken, {
query: inputSearchQuery,
type: 'input',
});
}
},
[internalSelectedInputAsset, internalSelectedOutputAsset, isFetching, isQuoteStale, setAsset]
);
Expand Down
16 changes: 8 additions & 8 deletions src/__swaps__/screens/Swap/hooks/useSelectedGas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,30 +3,30 @@ import { getCachedGasSuggestions, useMeteorologySuggestions } from '@/__swaps__/
import { createRainbowStore } from '@/state/internal/createRainbowStore';
import { useMemo } from 'react';
import { getCustomGasSettings, useCustomGasSettings } from './useCustomGas';
import { GasSpeed } from '@/__swaps__/types/gas';

export type GasSpeed = 'custom' | 'urgent' | 'fast' | 'normal';
const useSelectedGasSpeedStore = createRainbowStore<{ [c in ChainId]?: GasSpeed }>(() => ({}), {
version: 0,
storageKey: 'preferred gas speed',
});
export const useSelectedGasSpeed = (chainId: ChainId) =>
useSelectedGasSpeedStore(s => {
const speed = s[chainId] || 'fast';
if (speed === 'custom' && getCustomGasSettings(chainId) === undefined) return 'fast';
const speed = s[chainId] || GasSpeed.FAST;
if (speed === GasSpeed.CUSTOM && getCustomGasSettings(chainId) === undefined) return GasSpeed.FAST;
return speed;
});
export const setSelectedGasSpeed = (chainId: ChainId, speed: GasSpeed) => useSelectedGasSpeedStore.setState({ [chainId]: speed });
export const getSelectedGasSpeed = (chainId: ChainId) => useSelectedGasSpeedStore.getState()[chainId] || 'fast';
export const getSelectedGasSpeed = (chainId: ChainId) => useSelectedGasSpeedStore.getState()[chainId] || GasSpeed.FAST;

export function useGasSettings(chainId: ChainId, speed: GasSpeed) {
const userCustomGasSettings = useCustomGasSettings(chainId);
const { data: metereologySuggestions } = useMeteorologySuggestions({
chainId,
enabled: speed !== 'custom',
enabled: speed !== GasSpeed.CUSTOM,
});

return useMemo(() => {
if (speed === 'custom') return userCustomGasSettings;
if (speed === GasSpeed.CUSTOM) return userCustomGasSettings;
return metereologySuggestions?.[speed];
}, [speed, userCustomGasSettings, metereologySuggestions]);
}
Expand All @@ -45,11 +45,11 @@ export function getGasSettingsBySpeed(chainId: ChainId) {
}

export function getGasSettings(speed: GasSpeed, chainId: ChainId) {
if (speed === 'custom') return getCustomGasSettings(chainId);
if (speed === GasSpeed.CUSTOM) return getCustomGasSettings(chainId);
return getCachedGasSuggestions(chainId)?.[speed];
}

export function getSelectedGas(chainId: ChainId) {
const selectedGasSpeed = useSelectedGasSpeedStore.getState()[chainId] || 'fast';
const selectedGasSpeed = useSelectedGasSpeedStore.getState()[chainId] || GasSpeed.FAST;
return getGasSettings(selectedGasSpeed, chainId);
}
8 changes: 8 additions & 0 deletions src/__swaps__/screens/Swap/hooks/useSwapInputsController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ import {
} from '@/resources/assets/externalAssetsQuery';
import { ethereumUtils } from '@/utils';
import { queryClient } from '@/react-query';
import { userAssetsStore } from '@/state/assets/userAssets';
import { analyticsV2 } from '@/analytics';
import { divWorklet, equalWorklet, greaterThanWorklet, mulWorklet, toFixedWorklet } from '@/__swaps__/safe-math/SafeMath';

function getInitialInputValues(initialSelectedInputAsset: ExtendedAnimatedAssetWithColors | null) {
Expand Down Expand Up @@ -498,6 +500,12 @@ export function useSwapInputsController({
)
: undefined;

analyticsV2.track(analyticsV2.event.swapsReceivedQuote, {
inputAsset: internalSelectedInputAsset.value,
outputAsset: internalSelectedOutputAsset.value,
quote: quoteResponse,
});

runOnUI(() => {
setQuote({
data: quoteResponse,
Expand Down
Loading
Loading