Skip to content

Commit cc420fe

Browse files
authored
fix: Remove emojis from gas modals (MetaMask#23907)
<!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** <!-- Write a short description of the changes included in this pull request, also include relevant motivation and context. Have in mind the following questions: 1. What is the reason for the change? 2. What is the improvement/solution? --> This PR aims to drop emoji usage on gas modals and speed row. It also adds filtering of `high` option in fee levels if they are same with `medium`. ## **Changelog** <!-- If this PR is not End-User-Facing and should not show up in the CHANGELOG, you can choose to either: 1. Write `CHANGELOG entry: null` 2. Label with `no-changelog` If this PR is End-User-Facing, please write a short User-Facing description in the past tense like: `CHANGELOG entry: Added a new tab for users to see their NFTs` `CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker` (This helps the Release Engineer do their job more quickly and accurately) --> CHANGELOG entry: Remove emojis from gas options ## **Related issues** Fixes: MetaMask/MetaMask-planning#6446 ## **Manual testing steps** ```gherkin Feature: my feature name Scenario: user [verb for user action] Given [describe expected initial app state] When user [verb for user action] Then [describe expected outcome] ``` ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <img width="542" height="1078" alt="Screenshot 2025-12-11 at 00 50 28" src="https://github.com/user-attachments/assets/260a534e-78b5-4897-b581-7077320497a8" /> ### **After** <img width="586" height="1122" alt="Screenshot 2025-12-11 at 00 50 13" src="https://github.com/user-attachments/assets/62f3ed56-419c-4a0b-ad43-d419fa963ed3" /> ## **Pre-merge author checklist** - [X] I’ve followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [X] I've completed the PR template to the best of my ability - [X] I’ve included tests if applicable - [X] I’ve documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [X] I’ve applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > Removes emojis from gas options/speed and skips the High option when its fees match Medium for fee market estimates. > > - **UI (gas options/speed)** > - Remove emojis from `GasOption` and `GasSpeed` displays; adjust styles (`leftSection` spacing) and keep selection indicator/value display. > - **Types/Constants** > - Drop `GasOptionIcon` enum and `GasOption.emoji` field. > - **Logic** > - In `useGasFeeEstimateLevelOptions`, omit `High` when its `maxFeePerGas` and `maxPriorityFeePerGas` equal `Medium` (FeeMarket). > - **Tests** > - Update tests to remove emoji assertions; add test ensuring `High` is excluded when equal to `Medium`. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit feaba63. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY -->
1 parent 24c34ce commit cc420fe

14 files changed

Lines changed: 119 additions & 112 deletions

app/components/Views/confirmations/components/gas/gas-option/gas-option.styles.ts

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,7 @@ const styleSheet = (params: { theme: Theme }) => {
3535
leftSection: {
3636
flexDirection: 'row',
3737
alignItems: 'center',
38-
},
39-
emoji: {
40-
fontSize: 24,
41-
marginRight: 12,
42-
marginLeft: 6,
38+
marginLeft: 8,
4339
},
4440
optionTextContainer: {
4541
justifyContent: 'center',

app/components/Views/confirmations/components/gas/gas-option/gas-option.test.tsx

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import { noop } from 'lodash';
44
import { GasOption } from './gas-option';
55

66
const mockGasOption = {
7-
emoji: '🚀',
87
estimatedTime: '',
98
isSelected: false,
109
key: 'fast',
@@ -21,7 +20,6 @@ describe('GasOption', () => {
2120
);
2221

2322
expect(getByTestId('gas-option-fast')).toBeOnTheScreen();
24-
expect(getByText('🚀')).toBeOnTheScreen();
2523
expect(getByText('Test gas option')).toBeOnTheScreen();
2624
expect(getByText('< 0.0001')).toBeOnTheScreen();
2725
expect(getByText('0.05')).toBeOnTheScreen();

app/components/Views/confirmations/components/gas/gas-option/gas-option.tsx

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import React from 'react';
2-
import { View, TouchableOpacity, Text as RNText } from 'react-native';
2+
import { View, TouchableOpacity } from 'react-native';
33

44
import { useStyles } from '../../../../../../component-library/hooks';
55
import Text, {
@@ -9,16 +9,8 @@ import { type GasOption as GasOptionType } from '../../../types/gas';
99
import styleSheet from './gas-option.styles';
1010

1111
export const GasOption = ({ option }: { option: GasOptionType }) => {
12-
const {
13-
onSelect,
14-
name,
15-
estimatedTime,
16-
valueInFiat,
17-
value,
18-
emoji,
19-
isSelected,
20-
key,
21-
} = option;
12+
const { onSelect, name, estimatedTime, valueInFiat, value, isSelected, key } =
13+
option;
2214

2315
const { styles } = useStyles(styleSheet, {});
2416

@@ -33,7 +25,6 @@ export const GasOption = ({ option }: { option: GasOptionType }) => {
3325
onPress={() => onSelect()}
3426
>
3527
<View style={styles.leftSection}>
36-
<RNText style={styles.emoji}>{emoji}</RNText>
3728
<View style={styles.optionTextContainer}>
3829
<Text variant={TextVariant.BodyMDMedium} style={styles.optionName}>
3930
{name}

app/components/Views/confirmations/components/gas/gas-speed/gas-speed.test.tsx

Lines changed: 8 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -30,33 +30,10 @@ describe('GasSpeed', () => {
3030
jest.clearAllMocks();
3131
});
3232

33-
it('renders null when transaction metadata has no userFeeLevel', () => {
34-
const stateWithoutUserFeeLevel = merge({}, transferTransactionStateMock, {
35-
engine: {
36-
backgroundState: {
37-
TransactionController: {
38-
transactions: [
39-
{
40-
id: '56f60ff0-2bef-11f0-80ce-2f66f7fbd577',
41-
userFeeLevel: undefined,
42-
},
43-
],
44-
},
45-
},
46-
},
47-
});
48-
49-
const { queryByText } = renderWithProvider(<GasSpeed />, {
50-
state: stateWithoutUserFeeLevel,
51-
});
52-
53-
expect(queryByText(/🐢|🦊|🦍|🌐|/)).toBeNull();
54-
});
55-
5633
it.each([
57-
[GasFeeEstimateLevel.Low, 'Low', /🐢.*Low.*~ 30 sec/],
58-
[GasFeeEstimateLevel.Medium, 'Medium', /🦊.*Market.*~ 20 sec/],
59-
[GasFeeEstimateLevel.High, 'High', /🦍.*Aggressive.*~ 10 sec/],
34+
[GasFeeEstimateLevel.Low, 'Low', /.*Low.*~ 30 sec/],
35+
[GasFeeEstimateLevel.Medium, 'Medium', /.*Market.*~ 20 sec/],
36+
[GasFeeEstimateLevel.High, 'High', /.*Aggressive.*~ 10 sec/],
6037
])(
6138
'renders correct content for %s gas fee estimate level',
6239
(userFeeLevel, _levelName, expectedPattern) => {
@@ -104,7 +81,7 @@ describe('GasSpeed', () => {
10481
state: stateWithDappSuggested,
10582
});
10683

107-
expect(getByText('🌐 Site suggested')).toBeTruthy();
84+
expect(getByText('Site suggested')).toBeTruthy();
10885
});
10986

11087
it('renders correct content for CUSTOM user fee level', () => {
@@ -126,7 +103,7 @@ describe('GasSpeed', () => {
126103
state: stateWithCustom,
127104
});
128105

129-
expect(getByText('⚙️ Advanced')).toBeTruthy();
106+
expect(getByText('Advanced')).toBeTruthy();
130107
});
131108

132109
it('does not show estimated time for gas price estimate when Medium level is selected', () => {
@@ -151,7 +128,7 @@ describe('GasSpeed', () => {
151128
state: stateWithGasPriceEstimate,
152129
});
153130

154-
expect(getByText('🦊 Market')).toBeTruthy();
131+
expect(getByText('Market')).toBeTruthy();
155132
expect(queryByText(/sec/)).toBeNull();
156133
});
157134

@@ -177,7 +154,7 @@ describe('GasSpeed', () => {
177154
state: stateWithFeeMarketEstimate,
178155
});
179156

180-
expect(getByText(/🦍.*Aggressive.*~ 10 sec/)).toBeTruthy();
157+
expect(getByText(/.*Aggressive.*~ 10 sec/)).toBeTruthy();
181158
});
182159

183160
it('handles unknown user fee level by defaulting to advanced', () => {
@@ -199,7 +176,7 @@ describe('GasSpeed', () => {
199176
state: stateWithUnknownFeeLevel,
200177
});
201178

202-
expect(getByText('⚙️ Advanced')).toBeTruthy();
179+
expect(getByText('Advanced')).toBeTruthy();
203180
});
204181

205182
it('calls useGasFeeEstimates with correct networkClientId', () => {

app/components/Views/confirmations/components/gas/gas-speed/gas-speed.tsx

Lines changed: 1 addition & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -9,26 +9,9 @@ import {
99
import Text from '../../../../../../component-library/components/Texts/Text/Text';
1010
import { strings } from '../../../../../../../locales/i18n';
1111
import { useTransactionMetadataRequest } from '../../../hooks/transactions/useTransactionMetadataRequest';
12-
import { GasOptionIcon } from '../../../constants/gas';
1312
import { useGasFeeEstimates } from '../../../hooks/gas/useGasFeeEstimates';
1413
import { toHumanSeconds } from '../../../utils/time';
1514

16-
const getEmoji = (userFeeLevel: UserFeeLevel | GasFeeEstimateLevel) => {
17-
switch (userFeeLevel) {
18-
case GasFeeEstimateLevel.Low:
19-
return GasOptionIcon.LOW;
20-
case GasFeeEstimateLevel.Medium:
21-
return GasOptionIcon.MEDIUM;
22-
case GasFeeEstimateLevel.High:
23-
return GasOptionIcon.HIGH;
24-
case UserFeeLevel.DAPP_SUGGESTED:
25-
return GasOptionIcon.SITE_SUGGESTED;
26-
case UserFeeLevel.CUSTOM:
27-
default:
28-
return GasOptionIcon.ADVANCED;
29-
}
30-
};
31-
3215
const getText = (userFeeLevel: UserFeeLevel | GasFeeEstimateLevel) => {
3316
switch (userFeeLevel) {
3417
case UserFeeLevel.DAPP_SUGGESTED:
@@ -86,14 +69,12 @@ export const GasSpeed = () => {
8669
transactionMeta.gasFeeEstimates?.type === GasFeeEstimateType.GasPrice &&
8770
userFeeLevel === GasFeeEstimateLevel.Medium;
8871

89-
const emoji = getEmoji(userFeeLevel);
9072
const text = getText(userFeeLevel);
9173
const estimatedTime = getEstimatedTime(
9274
userFeeLevel,
9375
networkGasFeeEstimates,
9476
isGasPriceEstimateSelected,
9577
);
9678

97-
// Intentionally no space between text and estimated time
98-
return <Text>{`${emoji} ${text}${estimatedTime}`}</Text>;
79+
return <Text>{`${text}${estimatedTime}`}</Text>;
9980
};

app/components/Views/confirmations/components/modals/estimates-modal/estimates-modal.test.tsx

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ jest.mock('../../../hooks/gas/useGasOptions', () => ({
1010
return {
1111
options: [
1212
{
13-
emoji: '🚀',
1413
estimatedTime: '',
1514
isSelected: false,
1615
key: 'fast',
@@ -44,9 +43,7 @@ describe('EstimatesModal', () => {
4443
// Header
4544
expect(getByText('Edit network fee')).toBeOnTheScreen();
4645

47-
// Gas option expected to be rendered
4846
expect(getByTestId('gas-option-fast')).toBeOnTheScreen();
49-
expect(getByText('🚀')).toBeOnTheScreen();
5047
expect(getByText('Test gas option')).toBeOnTheScreen();
5148
expect(getByText('< 0.0001')).toBeOnTheScreen();
5249
expect(getByText('0.05')).toBeOnTheScreen();

app/components/Views/confirmations/constants/gas.ts

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,4 @@ export enum GasModalType {
44
ADVANCED_GAS_PRICE = 'advancedGasPriceModal',
55
}
66

7-
export enum GasOptionIcon {
8-
ADVANCED = '⚙️',
9-
GAS_PRICE = '⛓️',
10-
HIGH = '🦍',
11-
LOW = '🐢',
12-
MEDIUM = '🦊',
13-
SITE_SUGGESTED = '🌐',
14-
}
15-
167
export const EMPTY_VALUE_STRING = '--';

app/components/Views/confirmations/hooks/gas/useAdvancedGasFeeOption.ts

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,7 @@ import {
99
import { strings } from '../../../../../../locales/i18n';
1010
import { useTransactionMetadataRequest } from '../transactions/useTransactionMetadataRequest';
1111
import { useFeeCalculations } from './useFeeCalculations';
12-
import {
13-
EMPTY_VALUE_STRING,
14-
GasModalType,
15-
GasOptionIcon,
16-
} from '../../constants/gas';
12+
import { EMPTY_VALUE_STRING, GasModalType } from '../../constants/gas';
1713
import { type GasOption } from '../../types/gas';
1814

1915
const HEX_ZERO = '0x0';
@@ -118,7 +114,6 @@ export const useAdvancedGasFeeOption = ({
118114
const memoizedGasOption = useMemo(
119115
() => [
120116
{
121-
emoji: GasOptionIcon.ADVANCED,
122117
estimatedTime: '',
123118
isSelected: isAdvancedGasFeeSelected,
124119
key: 'advanced',

app/components/Views/confirmations/hooks/gas/useDappSuggestedGasFeeOption.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import {
77
import { strings } from '../../../../../../locales/i18n';
88
import { updateTransactionGasFees } from '../../../../../util/transaction-controller';
99
import { type GasOption } from '../../types/gas';
10-
import { EMPTY_VALUE_STRING, GasOptionIcon } from '../../constants/gas';
10+
import { EMPTY_VALUE_STRING } from '../../constants/gas';
1111
import { MMM_ORIGIN } from '../../constants/confirmations';
1212
import { useTransactionMetadataRequest } from '../transactions/useTransactionMetadataRequest';
1313
import { useFeeCalculations } from './useFeeCalculations';
@@ -71,7 +71,6 @@ export const useDappSuggestedGasFeeOption = ({
7171
});
7272

7373
options.push({
74-
emoji: GasOptionIcon.SITE_SUGGESTED,
7574
estimatedTime: undefined,
7675
isSelected: isDappSuggestedGasFeeSelected,
7776
key: 'site_suggested',

app/components/Views/confirmations/hooks/gas/useGasFeeEstimateLevelOptions.test.ts

Lines changed: 82 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -176,31 +176,25 @@ describe('useGasFeeEstimateLevelOptions', () => {
176176

177177
expect(result.current.length).toEqual(3);
178178

179-
// Check low option
180179
const lowOption = result.current.find((option) => option.key === 'low');
181180
expect(lowOption).toBeDefined();
182181
expect(lowOption?.isSelected).toEqual(false);
183182
expect(lowOption?.value).toEqual('5');
184183
expect(lowOption?.valueInFiat).toEqual('$5');
185-
expect(lowOption?.emoji).toEqual('🐢');
186184

187-
// Check medium option
188185
const mediumOption = result.current.find(
189186
(option) => option.key === 'medium',
190187
);
191188
expect(mediumOption).toBeDefined();
192189
expect(mediumOption?.isSelected).toEqual(false);
193190
expect(mediumOption?.value).toEqual('10');
194191
expect(mediumOption?.valueInFiat).toEqual('$10');
195-
expect(mediumOption?.emoji).toEqual('🦊');
196192

197-
// Check high option
198193
const highOption = result.current.find((option) => option.key === 'high');
199194
expect(highOption).toBeDefined();
200195
expect(highOption?.isSelected).toEqual(true);
201196
expect(highOption?.value).toEqual('15');
202197
expect(highOption?.valueInFiat).toEqual('$15');
203-
expect(highOption?.emoji).toEqual('🦍');
204198

205199
expect(mockCalculateGasEstimate).toHaveBeenCalledWith(
206200
expect.objectContaining({
@@ -507,4 +501,86 @@ describe('useGasFeeEstimateLevelOptions', () => {
507501
});
508502
expect(mockHandleCloseModals).toHaveBeenCalled();
509503
});
504+
505+
it('excludes high option when medium and high have identical fees for FeeMarket estimates', () => {
506+
const mockHandleCloseModals = jest.fn();
507+
508+
const transactionWithFeeMarketEstimates = {
509+
...simpleSendTransaction,
510+
id: 'test-id',
511+
userFeeLevel: 'medium',
512+
txParams: {
513+
...simpleSendTransaction.txParams,
514+
type: TransactionEnvelopeType.feeMarket,
515+
},
516+
gasFeeEstimates: {
517+
type: GasFeeEstimateType.FeeMarket,
518+
low: {
519+
maxFeePerGas: '0x1',
520+
maxPriorityFeePerGas: '0x1',
521+
},
522+
medium: {
523+
maxFeePerGas: '0x2',
524+
maxPriorityFeePerGas: '0x2',
525+
},
526+
high: {
527+
maxFeePerGas: '0x2',
528+
maxPriorityFeePerGas: '0x2',
529+
},
530+
},
531+
} as unknown as TransactionMeta;
532+
533+
mockUseTransactionMetadataRequest.mockReturnValue(
534+
transactionWithFeeMarketEstimates,
535+
);
536+
537+
mockUseGasFeeEstimates.mockReturnValue({
538+
gasFeeEstimates: {
539+
low: {
540+
minWaitTimeEstimate: 60000,
541+
maxWaitTimeEstimate: 120000,
542+
suggestedMaxPriorityFeePerGas: '1',
543+
},
544+
medium: {
545+
minWaitTimeEstimate: 30000,
546+
maxWaitTimeEstimate: 60000,
547+
suggestedMaxPriorityFeePerGas: '2',
548+
},
549+
high: {
550+
minWaitTimeEstimate: 15000,
551+
maxWaitTimeEstimate: 30000,
552+
suggestedMaxPriorityFeePerGas: '2',
553+
},
554+
} as unknown as GasFeeEstimates,
555+
});
556+
557+
mockCalculateGasEstimate.mockImplementation(({ feePerGas }) => {
558+
const value = feePerGas === '0x1' ? '5' : '10';
559+
const valueInFiat = feePerGas === '0x1' ? '$5' : '$10';
560+
561+
return {
562+
currentCurrencyFee: valueInFiat,
563+
preciseNativeCurrencyFee: value,
564+
};
565+
});
566+
567+
const { result } = renderHook(() =>
568+
useGasFeeEstimateLevelOptions({
569+
handleCloseModals: mockHandleCloseModals,
570+
}),
571+
);
572+
573+
expect(result.current.length).toEqual(2);
574+
575+
const lowOption = result.current.find((option) => option.key === 'low');
576+
expect(lowOption).toBeDefined();
577+
578+
const mediumOption = result.current.find(
579+
(option) => option.key === 'medium',
580+
);
581+
expect(mediumOption).toBeDefined();
582+
583+
const highOption = result.current.find((option) => option.key === 'high');
584+
expect(highOption).toBeUndefined();
585+
});
510586
});

0 commit comments

Comments
 (0)