Skip to content

Commit cf07474

Browse files
authored
Merge branch 'main' into fix/perps/fee-rounding
2 parents 1ea3320 + f8f3356 commit cf07474

File tree

38 files changed

+2543
-463
lines changed

38 files changed

+2543
-463
lines changed

app/components/Nav/Main/MainNavigator.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React, { useState, useEffect, useMemo, useCallback } from 'react';
1+
import React, { useState, useEffect, useMemo } from 'react';
22
import { Image, StyleSheet, Keyboard, Platform } from 'react-native';
33
import { createStackNavigator } from '@react-navigation/stack';
44
import { useSelector } from 'react-redux';
@@ -1192,7 +1192,7 @@ const MainNavigator = () => {
11921192
...GeneralSettings.navigationOptions,
11931193
}}
11941194
/>
1195-
{process.env.NODE_ENV !== 'production' && (
1195+
{process.env.METAMASK_ENVIRONMENT !== 'production' && (
11961196
<Stack.Screen
11971197
name={Routes.FEATURE_FLAG_OVERRIDE}
11981198
component={FeatureFlagOverride}

app/components/Nav/Main/MainNavigator.test.tsx

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,16 @@ jest.mock('@react-navigation/stack', () => ({
1313
}));
1414

1515
describe('MainNavigator', () => {
16+
const originalEnv = process.env.METAMASK_ENVIRONMENT;
17+
1618
beforeEach(() => {
1719
jest.clearAllMocks();
1820
});
1921

22+
afterEach(() => {
23+
process.env.METAMASK_ENVIRONMENT = originalEnv;
24+
});
25+
2026
it('matches rendered snapshot', () => {
2127
// Given the initial app state
2228
// When rendering the MainNavigator
@@ -60,4 +66,41 @@ describe('MainNavigator', () => {
6066
expect(sampleFeatureScreen).toBeDefined();
6167
expect(sampleFeatureScreen?.component.name).toBe('SampleFeatureFlow');
6268
});
69+
70+
it('includes FeatureFlagOverride screen when METAMASK_ENVIRONMENT is not production', () => {
71+
// Given a non-production environment
72+
process.env.METAMASK_ENVIRONMENT = 'dev';
73+
74+
// When rendering the MainNavigator
75+
const container = renderWithProvider(<MainNavigator />, {
76+
state: initialRootState,
77+
});
78+
79+
// Then it should contain the FeatureFlagOverride screen
80+
interface ScreenChild {
81+
name: string;
82+
component: { name: string };
83+
}
84+
const screenProps: ScreenChild[] = container.root.children
85+
.filter(
86+
(child): child is ReactTestInstance =>
87+
typeof child === 'object' &&
88+
'type' in child &&
89+
'props' in child &&
90+
child.type?.toString() === 'Screen',
91+
)
92+
.map((child) => ({
93+
name: child.props.name,
94+
component: child.props.component,
95+
}));
96+
97+
const featureFlagOverrideScreen = screenProps?.find(
98+
(screen) => screen?.name === Routes.FEATURE_FLAG_OVERRIDE,
99+
);
100+
101+
expect(featureFlagOverrideScreen).toBeDefined();
102+
expect(featureFlagOverrideScreen?.component.name).toBe(
103+
'FeatureFlagOverride',
104+
);
105+
});
63106
});

app/components/UI/Earn/Views/EarnInputView/EarnInputView.tsx

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -646,26 +646,27 @@ const EarnInputView = () => {
646646
// Call the original handler first
647647
handleCurrencySwitch();
648648

649-
if (shouldLogStablecoinEvent()) {
650-
trackEvent(
651-
createEventBuilder(MetaMetricsEvents.EARN_INPUT_CURRENCY_SWITCH_CLICKED)
652-
.addProperties({
653-
selected_provider: EVENT_PROVIDERS.CONSENSYS,
654-
text: 'Currency Switch Clicked',
655-
location: EVENT_LOCATIONS.EARN_INPUT_VIEW,
656-
currency_type: !isFiat ? 'fiat' : 'native',
657-
experience: earnToken?.experience?.type,
658-
})
659-
.build(),
660-
);
661-
}
649+
trackEvent(
650+
createEventBuilder(MetaMetricsEvents.EARN_INPUT_CURRENCY_SWITCH_CLICKED)
651+
.addProperties({
652+
selected_provider: EVENT_PROVIDERS.CONSENSYS,
653+
text: 'Currency Switch Clicked',
654+
location: EVENT_LOCATIONS.EARN_INPUT_VIEW,
655+
currency_type: !isFiat ? 'fiat' : 'native',
656+
experience: earnToken?.experience?.type,
657+
token_symbol: earnToken?.symbol,
658+
chain_id: earnToken?.chainId ? toHex(earnToken.chainId) : undefined,
659+
})
660+
.build(),
661+
);
662662
}, [
663-
shouldLogStablecoinEvent,
664663
handleCurrencySwitch,
665664
trackEvent,
666665
createEventBuilder,
667666
isFiat,
668667
earnToken?.experience?.type,
668+
earnToken?.symbol,
669+
earnToken?.chainId,
669670
]);
670671

671672
const getButtonLabel = () => {

app/components/UI/Earn/Views/EarnWithdrawInputView/EarnWithdrawInputView.tsx

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { toHex } from '@metamask/controller-utils';
12
import { Hex } from '@metamask/utils';
23
import {
34
useFocusEffect,
@@ -576,6 +577,10 @@ const EarnWithdrawInputView = () => {
576577
// We want to track the currency switching to. Not the current currency.
577578
currency_type: isFiat ? 'native' : 'fiat',
578579
experience: receiptToken?.experience?.type,
580+
token_symbol: receiptToken?.symbol,
581+
chain_id: receiptToken?.chainId
582+
? toHex(receiptToken.chainId)
583+
: undefined,
579584
})
580585
.build(),
581586
);
@@ -591,6 +596,10 @@ const EarnWithdrawInputView = () => {
591596
// We want to track the currency switching to. Not the current currency.
592597
currency_type: isFiat ? 'native' : 'fiat',
593598
experience: receiptToken?.experience?.type,
599+
token_symbol: receiptToken?.symbol,
600+
chain_id: receiptToken?.chainId
601+
? toHex(receiptToken.chainId)
602+
: undefined,
594603
})
595604
.build(),
596605
);
@@ -603,6 +612,8 @@ const EarnWithdrawInputView = () => {
603612
createEventBuilder,
604613
isFiat,
605614
receiptToken?.experience?.type,
615+
receiptToken?.symbol,
616+
receiptToken?.chainId,
606617
]);
607618

608619
const handleQuickAmountPressWithTracking = useCallback(

app/components/UI/Navbar/index.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1962,7 +1962,7 @@ export function getDepositNavbarOptions(
19621962
? () => (
19631963
<ButtonIcon
19641964
onPress={onConfigurationPress}
1965-
iconName={IconName.MoreHorizontal}
1965+
iconName={IconName.Setting}
19661966
size={ButtonIconSize.Lg}
19671967
testID="deposit-configuration-menu-button"
19681968
style={styles.headerLeftButton}

app/components/UI/Predict/components/PredictActivity/PredictActivity.test.tsx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,12 +88,11 @@ const renderComponent = (overrides?: Partial<PredictActivityItem>) => {
8888
};
8989

9090
describe('PredictActivity', () => {
91-
it('renders BUY activity with title, market, detail, amount and percent', () => {
91+
it('renders BUY activity with title, market, amount and percent', () => {
9292
renderComponent();
9393

9494
expect(screen.getByText('Buy')).toBeOnTheScreen();
9595
expect(screen.getByText(baseItem.marketTitle)).toBeOnTheScreen();
96-
expect(screen.getByText(baseItem.detail)).toBeOnTheScreen();
9796
expect(screen.getByText('-$1,234.50')).toBeOnTheScreen();
9897
expect(screen.getByText('+1.50%')).toBeOnTheScreen();
9998
});

app/components/UI/Predict/components/PredictActivity/PredictActivity.tsx

Lines changed: 14 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@ const PredictActivity: React.FC<PredictActivityProps> = ({ item }) => {
3232
const tw = useTailwind();
3333
const navigation = useNavigation();
3434
const isDebit = item.type === PredictActivityType.BUY;
35-
const isCredit = !isDebit;
3635
const signedAmount = `${isDebit ? '-' : '+'}${formatPrice(
3736
Math.abs(item.amountUsd),
3837
{
@@ -41,7 +40,6 @@ const PredictActivity: React.FC<PredictActivityProps> = ({ item }) => {
4140
},
4241
)}`;
4342

44-
const amountColor = isCredit ? 'text-success-default' : 'text-error-default';
4543
const percentColor =
4644
(item.percentChange ?? 0) >= 0
4745
? 'text-success-default'
@@ -64,42 +62,31 @@ const PredictActivity: React.FC<PredictActivityProps> = ({ item }) => {
6462
justifyContent={BoxJustifyContent.Between}
6563
twClassName="w-full p-2"
6664
>
67-
<Box twClassName="h-12 w-12 items-center justify-center rounded-full bg-muted mr-3 overflow-hidden">
68-
{item.icon ? (
69-
<Image
70-
source={{ uri: item.icon }}
71-
style={tw.style('w-full h-full')}
72-
accessibilityLabel="activity icon"
73-
/>
74-
) : (
75-
<Icon name={IconName.Activity} />
76-
)}
65+
<Box twClassName="pt-1">
66+
<Box twClassName="h-10 w-10 items-center justify-center rounded-full bg-muted mr-3 overflow-hidden">
67+
{item.icon ? (
68+
<Image
69+
source={{ uri: item.icon }}
70+
style={tw.style('w-full h-full')}
71+
accessibilityLabel="activity icon"
72+
/>
73+
) : (
74+
<Icon name={IconName.Activity} />
75+
)}
76+
</Box>
7777
</Box>
7878

7979
<Box twClassName="flex-1">
8080
<Text variant={TextVariant.BodyMd} numberOfLines={1}>
8181
{activityTitleByType[item.type]}
8282
</Text>
83-
<Text
84-
variant={TextVariant.BodySm}
85-
twClassName="text-alternative"
86-
numberOfLines={1}
87-
>
83+
<Text variant={TextVariant.BodySm} twClassName="text-alternative">
8884
{item.marketTitle}
8985
</Text>
90-
{item.type !== PredictActivityType.CLAIM ? (
91-
<Text
92-
variant={TextVariant.BodySm}
93-
twClassName="text-alternative"
94-
numberOfLines={1}
95-
>
96-
{item.detail}
97-
</Text>
98-
) : null}
9986
</Box>
10087

10188
<Box twClassName="items-end ml-3">
102-
<Text variant={TextVariant.BodyMd} twClassName={amountColor}>
89+
<Text variant={TextVariant.BodyMd} twClassName="text-alternative">
10390
{signedAmount}
10491
</Text>
10592
{item.percentChange !== undefined ? (

app/components/UI/Predict/providers/polymarket/utils.test.ts

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2085,13 +2085,13 @@ describe('polymarket utils', () => {
20852085
}
20862086
});
20872087

2088-
it('maps non-TRADE to claimWinnings entries and handles defaults', () => {
2088+
it('maps REDEEM with payout to claimWinnings entries', () => {
20892089
const input = [
20902090
{
20912091
type: 'REDEEM' as const,
20922092
side: '' as const,
20932093
timestamp: 3000,
2094-
usdcSize: 1.23,
2094+
usdcSize: 1.23, // Winning claim with actual payout
20952095
price: 0,
20962096
conditionId: '',
20972097
outcomeIndex: 0,
@@ -2102,11 +2102,32 @@ describe('polymarket utils', () => {
21022102
},
21032103
];
21042104
const result = parsePolymarketActivity(input);
2105+
expect(result).toHaveLength(1);
21052106
expect(result[0].entry.type).toBe('claimWinnings');
21062107
expect(result[0].entry.amount).toBe(1.23);
21072108
expect(result[0].id).toBe('0xhash3');
21082109
});
21092110

2111+
it('filters out REDEEM activities with no payout (lost positions)', () => {
2112+
const input = [
2113+
{
2114+
type: 'REDEEM' as const,
2115+
side: '' as const,
2116+
timestamp: 3000,
2117+
usdcSize: 0, // No payout - lost position
2118+
price: 0,
2119+
conditionId: '',
2120+
outcomeIndex: 0,
2121+
title: 'Lost Market',
2122+
outcome: '' as const,
2123+
icon: '',
2124+
transactionHash: '0xhash3',
2125+
},
2126+
];
2127+
const result = parsePolymarketActivity(input);
2128+
expect(result).toHaveLength(0);
2129+
});
2130+
21102131
it('generates fallback id and timestamp when missing', () => {
21112132
const input = [
21122133
{

0 commit comments

Comments
 (0)