Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion app/component-library/components/Icons/Icon/assets/ai.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
33 changes: 0 additions & 33 deletions app/components/UI/Bridge/components/BridgeNetworkSelectorBase.tsx

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React, { useCallback, useRef } from 'react';
import { ScrollView } from 'react-native';
import { ScrollView } from 'react-native-gesture-handler'; // Must use this to make sure scroll works inside a bottom sheet on Android
import { useSelector, useDispatch } from 'react-redux';
import { Icon, IconName, IconSize } from '@metamask/design-system-react-native';
import { IconName as ComponentLibraryIconName } from '../../../../../component-library/components/Icons/Icon';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -602,6 +602,45 @@ describe('QuoteDetailsCard', () => {
});
});

it('does not navigate when price impact is below warning threshold', () => {
// priceImpact 0.04 < warning threshold 0.05 → priceImpactIsSafe = true → no navigation
const mockModule = jest.requireMock('../../hooks/useBridgeQuoteData');
mockModule.useBridgeQuoteData.mockImplementationOnce(() => ({
quoteFetchError: null,
activeQuote: {
...mockQuotes[0],
quote: {
...mockQuotes[0].quote,
priceData: { ...mockQuotes[0].quote.priceData, priceImpact: '0.04' },
gasIncluded: false,
gasIncluded7702: false,
},
},
destTokenAmount: '24.44',
isLoading: false,
formattedQuoteData: {
networkFee: '0.01',
estimatedTime: '1 min',
rate: '1 ETH = 24.4 USDC',
priceImpact: '0.04%',
slippage: '0.5%',
},
}));

const { getByTestId } = renderScreen(
QuoteDetailsCardTestScreen,
{ name: Routes.BRIDGE.ROOT },
{ state: testState },
);

fireEvent.press(getByTestId('price-impact-info-button'));

expect(mockNavigate).not.toHaveBeenCalledWith(Routes.BRIDGE.MODALS.ROOT, {
screen: Routes.BRIDGE.MODALS.PRICE_IMPACT_MODAL,
params: expect.anything(),
});
});

it('opens rate tooltip modal when rate info icon is pressed', () => {
const { getByLabelText } = renderScreen(
QuoteDetailsCardTestScreen,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React, { useMemo } from 'react';
import { TouchableOpacity, Platform, UIManager, Pressable } from 'react-native';
import { TouchableOpacity, Platform, UIManager } from 'react-native';
import { useNavigation } from '@react-navigation/native';
import { strings } from '../../../../../../locales/i18n';
import { useTheme } from '../../../../../util/theme';
Expand All @@ -26,6 +26,7 @@ import {
selectSourceAmount,
selectDestToken,
selectSourceToken,
selectBridgeFeatureFlags,
} from '../../../../../core/redux/slices/bridge';
import { getNativeSourceToken } from '../../utils/tokenUtils';
import { formatMinimumReceived } from '../../utils/currencyUtils';
Expand Down Expand Up @@ -53,6 +54,7 @@ import { PriceImpactModalType } from '../PriceImpactModal/constants';
import { formatPriceImpact } from '../../utils/formatPriceImpact';
import KeyValueRowLabel from '../../../../../component-library/components-temp/KeyValueRow/KeyValueLabel/KeyValueLabel';
import { usePriceImpactViewData } from '../../hooks/usePriceImpactViewData';
import AppConstants from '../../../../../core/AppConstants';

if (
Platform.OS === 'android' &&
Expand All @@ -65,6 +67,7 @@ const QuoteDetailsCard: React.FC<QuoteDetailsCardProps> = ({
hasInsufficientBalance,
location,
}) => {
const bridgeFeatureFlags = useSelector(selectBridgeFeatureFlags);
const tw = useTailwind();
const theme = useTheme();
const navigation = useNavigation();
Expand All @@ -90,6 +93,13 @@ const QuoteDetailsCard: React.FC<QuoteDetailsCardProps> = ({
isQuoteLoading,
});

const priceImpactIsSafe =
!activeQuote?.quote.priceData?.priceImpact ||
Number(activeQuote.quote.priceData.priceImpact) <=
// @ts-expect-error TODO: remove comment after changes to core are published.
(bridgeFeatureFlags?.priceImpactThreshold?.warning ??
AppConstants.BRIDGE.PRICE_IMPACT_WARNING_THRESHOLD);

const nativeTokenName = useMemo(() => {
const chainId = sourceToken?.chainId;
if (!chainId) return undefined;
Expand Down Expand Up @@ -117,6 +127,10 @@ const QuoteDetailsCard: React.FC<QuoteDetailsCardProps> = ({
};

const handlePriceImpactPress = () => {
if (priceImpactIsSafe) {
return;
}

navigation.navigate(Routes.BRIDGE.MODALS.ROOT, {
screen: Routes.BRIDGE.MODALS.PRICE_IMPACT_MODAL,
params: {
Expand All @@ -133,7 +147,7 @@ const QuoteDetailsCard: React.FC<QuoteDetailsCardProps> = ({
activeQuote?.minToTokenAmount?.amount || '0',
);

const priceImactViewData = usePriceImpactViewData(
const priceImpactViewData = usePriceImpactViewData(
activeQuote?.quote.priceData?.priceImpact,
);

Expand Down Expand Up @@ -178,28 +192,33 @@ const QuoteDetailsCard: React.FC<QuoteDetailsCardProps> = ({
iconName: IconNameLegacy.Info,
}}
/>
<Box twClassName="flex-1 min-w-0">
<Text
variant={TextVariant.BodyMd}
color={TextColor.TextAlternative}
style={tw`text-right`}
numberOfLines={1}
ellipsizeMode="tail"
>
{formattedQuoteData?.rate}
</Text>
</Box>
<Pressable
style={tw`shrink-0`}
<TouchableOpacity
style={tw`flex-1 items-end`}
onPress={handleRatePress}
testID="rate-arrow-button"
activeOpacity={0.6}
>
<Icon
name={IconName.ArrowRight}
size={IconSize.Sm}
color={IconColor.IconAlternative}
/>
</Pressable>
<Box
flexDirection={BoxFlexDirection.Row}
alignItems={BoxAlignItems.Center}
gap={1}
>
<Text
variant={TextVariant.BodyMd}
color={TextColor.TextAlternative}
style={tw`text-right`}
numberOfLines={1}
ellipsizeMode="tail"
>
{formattedQuoteData?.rate}
</Text>
<Icon
name={IconName.ArrowRight}
size={IconSize.Sm}
color={IconColor.IconAlternative}
/>
</Box>
</TouchableOpacity>
</Box>
{shouldShowGasSponsored ? (
<KeyValueRow
Expand Down Expand Up @@ -372,32 +391,32 @@ const QuoteDetailsCard: React.FC<QuoteDetailsCardProps> = ({
}}
value={{
label: (
<Box
flexDirection={BoxFlexDirection.Row}
alignItems={BoxAlignItems.Center}
gap={1}
<TouchableOpacity
testID="price-impact-info-button"
onPress={handlePriceImpactPress}
activeOpacity={priceImpactIsSafe ? 1 : 0.6}
>
<TouchableOpacity
testID="price-impact-info-button"
onPress={handlePriceImpactPress}
activeOpacity={0.6}
<Box
flexDirection={BoxFlexDirection.Row}
alignItems={BoxAlignItems.Center}
gap={1}
>
{priceImactViewData.icon && (
{priceImpactViewData.icon && (
<Icon
name={priceImactViewData.icon.name}
name={priceImpactViewData.icon.name}
size={IconSize.Sm}
color={priceImactViewData.icon.color}
color={priceImpactViewData.icon.color}
twClassName="mt-[2px]"
/>
)}
</TouchableOpacity>
<Text
variant={TextVariant.BodyMd}
color={priceImactViewData.textColor}
>
{formatPriceImpact(formattedQuoteData.priceImpact)}
</Text>
</Box>
<Text
variant={TextVariant.BodyMd}
color={priceImpactViewData.textColor}
>
{formatPriceImpact(formattedQuoteData.priceImpact)}
</Text>
</Box>
</TouchableOpacity>
),
}}
/>
Expand Down
Loading
Loading