Skip to content

Commit

Permalink
Price Impact Warning (#5635)
Browse files Browse the repository at this point in the history
* price impact warning done

* i18n stuff

* i18n stuff but intro bug

* fix i18n and fix bug with sliderXPosition in positive dir

* add missing return statement

* add time estimates, and add colors depending on high/severe

* fix exchange rate bubble pushing the swap warning component down

* fix exchange rate bubble pushing the swap warning component down

* fix position

* add unknown price warning

* added quote errors to price warning component

* change colors for warnings
  • Loading branch information
walmat committed Apr 18, 2024
1 parent 98d30c2 commit b87d6a2
Show file tree
Hide file tree
Showing 8 changed files with 369 additions and 9 deletions.
7 changes: 6 additions & 1 deletion src/__swaps__/screens/Swap/Swap.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { SwapInputAsset } from '@/__swaps__/screens/Swap/components/controls/Swa
import { SwapOutputAsset } from '@/__swaps__/screens/Swap/components/controls/SwapOutputAsset';
import { SwapNavbar } from '@/__swaps__/screens/Swap/components/SwapNavbar';
import { SwapAmountInputs } from '@/__swaps__/screens/Swap/components/controls/SwapAmountInputs';
import { SwapWarning } from './components/SwapWarning';

/** README
* This prototype is largely driven by Reanimated and Gesture Handler, which
Expand Down Expand Up @@ -63,7 +64,11 @@ export function SwapScreen() {
<SwapInputAsset />
<FlipButton />
<SwapOutputAsset />
<ExchangeRateBubble />
<Box alignItems="center" justifyContent="center" style={{ position: 'relative' }}>
<ExchangeRateBubble />
<SwapWarning />
</Box>

<SwapAmountInputs />
</Box>
<SwapNavbar />
Expand Down
3 changes: 1 addition & 2 deletions src/__swaps__/screens/Swap/components/ExchangeRateBubble.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import { useSwapContext } from '@/__swaps__/screens/Swap/providers/swap-provider
export const ExchangeRateBubble = () => {
const { isDarkMode } = useColorMode();
const { AnimatedSwapStyles, SwapInputController } = useSwapContext();

const [exchangeRateIndex, setExchangeRateIndex] = useState<number>(0);

const assetToSellPrice = useSharedValue(0);
Expand Down Expand Up @@ -149,7 +148,7 @@ export const ExchangeRateBubble = () => {
justifyContent="center"
paddingHorizontal="24px"
paddingVertical="12px"
style={[AnimatedSwapStyles.hideWhenInputsExpanded, { alignSelf: 'center' }]}
style={[AnimatedSwapStyles.hideWhenInputsExpandedOrPriceImpact, { alignSelf: 'center', position: 'absolute', top: 4 }]}
>
<Box
as={Animated.View}
Expand Down
107 changes: 107 additions & 0 deletions src/__swaps__/screens/Swap/components/SwapWarning.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
import React from 'react';
import * as i18n from '@/languages';
import Animated, { useAnimatedStyle, useDerivedValue } from 'react-native-reanimated';
import { AnimatedText, Box, Inline, useForegroundColor } from '@/design-system';
import { useSwapContext } from '@/__swaps__/screens/Swap/providers/swap-provider';
import { SwapWarningType } from '@/__swaps__/screens/Swap/hooks/useSwapWarning';

export const SwapWarning = () => {
const { AnimatedSwapStyles, SwapWarning } = useSwapContext();

const red = useForegroundColor('red');
const orange = useForegroundColor('orange');

const colorMap = {
[SwapWarningType.severe]: red,
[SwapWarningType.unknown]: red,
[SwapWarningType.long_wait]: orange,
[SwapWarningType.none]: orange,
[SwapWarningType.high]: orange,

// swap quote errors
[SwapWarningType.no_quote_available]: red,
[SwapWarningType.insufficient_liquidity]: red,
[SwapWarningType.fee_on_transfer]: red,
[SwapWarningType.no_route_found]: red,
};

const warningMessagesPrefix: Record<SwapWarningType, { title: string; subtext: string; addDisplayToTitle?: boolean }> = {
[SwapWarningType.none]: {
title: '',
subtext: '',
},
[SwapWarningType.high]: {
title: `􀇿 ${i18n.t(i18n.l.exchange.price_impact.you_are_losing)}`,
subtext: i18n.t(i18n.l.exchange.price_impact.small_market_try_smaller_amount),
addDisplayToTitle: true,
},
[SwapWarningType.unknown]: {
title: `􀇿 ${SwapWarning.swapWarning.value.display}`,
subtext: i18n.t(i18n.l.exchange.price_impact.unknown_price.description),
},
[SwapWarningType.severe]: {
title: `􀇿 ${i18n.t(i18n.l.exchange.price_impact.you_are_losing)}`,
subtext: i18n.t(i18n.l.exchange.price_impact.small_market_try_smaller_amount),
addDisplayToTitle: true,
},
[SwapWarningType.long_wait]: {
title: `􀇿 ${i18n.t(i18n.l.exchange.price_impact.long_wait.title)}`,
subtext: `${i18n.t(i18n.l.exchange.price_impact.long_wait.description)}`,
addDisplayToTitle: true,
},

// swap quote errors
[SwapWarningType.no_quote_available]: {
title: `􀇿 ${i18n.t(i18n.l.exchange.quote_errors.no_quote_available)}`,
subtext: '',
},
[SwapWarningType.insufficient_liquidity]: {
title: `􀇿 ${i18n.t(i18n.l.exchange.quote_errors.insufficient_liquidity)}`,
subtext: '',
},
[SwapWarningType.fee_on_transfer]: {
title: `􀇿 ${i18n.t(i18n.l.exchange.quote_errors.fee_on_transfer)}`,
subtext: '',
},
[SwapWarningType.no_route_found]: {
title: `􀇿 ${i18n.t(i18n.l.exchange.quote_errors.no_route_found)}`,
subtext: '',
},
};

const warningTitle = useDerivedValue(() => {
const potentialTitle = warningMessagesPrefix[SwapWarning.swapWarning.value.type].title;
const addDisplayToTitle = warningMessagesPrefix[SwapWarning.swapWarning.value.type].addDisplayToTitle;
return addDisplayToTitle ? `${potentialTitle} ${SwapWarning.swapWarning.value.display}` : potentialTitle;
});

const warningSubtext = useDerivedValue(() => {
return warningMessagesPrefix[SwapWarning.swapWarning.value.type].subtext;
});

const warningStyles = useAnimatedStyle(() => ({
color: colorMap[SwapWarning.swapWarning.value.type],
}));

const warningSubtextStyles = useAnimatedStyle(() => ({
display: warningSubtext.value.trim() !== '' ? 'flex' : 'none',
}));

return (
<Box
as={Animated.View}
alignItems="center"
justifyContent="center"
paddingHorizontal="24px"
paddingVertical="12px"
style={[AnimatedSwapStyles.hideWhenInputsExpandedOrNoPriceImpact, { alignSelf: 'center', position: 'absolute', top: 8 }]}
>
<Box as={Animated.View} alignItems="center" height={{ custom: 33 }} gap={6} justifyContent="center" paddingHorizontal="10px">
<Inline alignHorizontal="center" alignVertical="center" horizontalSpace="4px" wrap={false}>
<AnimatedText style={warningStyles} align="center" size="15pt" weight="heavy" text={warningTitle} />
</Inline>
<AnimatedText style={warningSubtextStyles} color="labelQuaternary" align="center" size="13pt" weight="bold" text={warningSubtext} />
</Box>
</Box>
);
};
31 changes: 27 additions & 4 deletions src/__swaps__/screens/Swap/hooks/useAnimatedSwapStyles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,18 @@ import {
} from '@/__swaps__/screens/Swap/constants';
import { opacityWorklet } from '@/__swaps__/utils/swaps';
import { useSwapInputsController } from '@/__swaps__/screens/Swap/hooks/useSwapInputsController';
import { SwapWarningType, useSwapWarning } from '@/__swaps__/screens/Swap/hooks/useSwapWarning';
import { spinnerExitConfig } from '@/__swaps__/components/animations/AnimatedSpinner';

export function useAnimatedSwapStyles({
SwapInputController,
SwapWarning,
inputProgress,
outputProgress,
isFetching,
}: {
SwapInputController: ReturnType<typeof useSwapInputsController>;
SwapWarning: ReturnType<typeof useSwapWarning>;
inputProgress: SharedValue<number>;
outputProgress: SharedValue<number>;
isFetching: SharedValue<boolean>;
Expand All @@ -45,10 +48,29 @@ export function useAnimatedSwapStyles({
};
});

const hideWhenInputsExpanded = useAnimatedStyle(() => {
const hideWhenInputsExpandedOrNoPriceImpact = useAnimatedStyle(() => {
return {
opacity: inputProgress.value > 0 || outputProgress.value > 0 ? withTiming(0, fadeConfig) : withTiming(1, fadeConfig),
pointerEvents: inputProgress.value > 0 || outputProgress.value > 0 ? 'none' : 'auto',
opacity:
SwapWarning.swapWarning.value.type === SwapWarningType.none || inputProgress.value > 0 || outputProgress.value > 0
? withTiming(0, fadeConfig)
: withTiming(1, fadeConfig),
pointerEvents:
SwapWarning.swapWarning.value.type === SwapWarningType.none || inputProgress.value > 0 || outputProgress.value > 0
? 'none'
: 'auto',
};
});

const hideWhenInputsExpandedOrPriceImpact = useAnimatedStyle(() => {
return {
opacity:
SwapWarning.swapWarning.value.type !== SwapWarningType.none || inputProgress.value > 0 || outputProgress.value > 0
? withTiming(0, fadeConfig)
: withTiming(1, fadeConfig),
pointerEvents:
SwapWarning.swapWarning.value.type !== SwapWarningType.none || inputProgress.value > 0 || outputProgress.value > 0
? 'none'
: 'auto',
};
});

Expand Down Expand Up @@ -163,7 +185,8 @@ export function useAnimatedSwapStyles({
return {
flipButtonStyle,
focusedSearchStyle,
hideWhenInputsExpanded,
hideWhenInputsExpandedOrPriceImpact,
hideWhenInputsExpandedOrNoPriceImpact,
inputStyle,
inputTokenListStyle,
keyboardStyle,
Expand Down
5 changes: 4 additions & 1 deletion src/__swaps__/screens/Swap/hooks/useSwapInputsController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -413,6 +413,9 @@ export function useSwapInputsController({
quoteParams.swapType === SwapType.crossChain ? await getCrosschainQuote(quoteParams) : await getQuote(quoteParams)
) as Quote | CrosschainQuote | QuoteError;

quote.value = quoteResponse;
logger.debug(`[useSwapInputsController] quote response`, { quoteResponse });

// todo - show quote error
if (!quoteResponse || (quoteResponse as QuoteError)?.error) {
logger.debug(`[useSwapInputsController] quote error`, { error: quoteResponse });
Expand Down Expand Up @@ -501,7 +504,6 @@ export function useSwapInputsController({
// TODO: Need to convert big number to native value properly here...
// example: "fee": "3672850000000000",
fee.value = isWrapOrUnwrapEth ? '0' : data.feeInEth.toString();
quote.value = data;

inputValues.modify(values => {
return {
Expand Down Expand Up @@ -1050,6 +1052,7 @@ export function useSwapInputsController({
assetToSellIconUrl,
assetToBuySymbol,
assetToBuyIconUrl,
quote,
source,
slippage,
flashbots,
Expand Down
Loading

0 comments on commit b87d6a2

Please sign in to comment.