mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-12-23 01:39:44 +01:00
EIP-1559 V2: Adding default settings to advanced gas modal (#12911)
This commit is contained in:
parent
3a11800cb1
commit
8c77e37d2a
@ -170,6 +170,12 @@
|
||||
"advancedBaseGasFeeToolTip": {
|
||||
"message": "When your transaction gets included in the block, any difference between your max base fee and the actual base fee will be refunded. Total amount is calculated as max base fee (in GWEI) * gas limit."
|
||||
},
|
||||
"advancedGasFeeDefaultOptIn": {
|
||||
"message": "Save these $1 as my default for \"Advanced\""
|
||||
},
|
||||
"advancedGasFeeDefaultOptOut": {
|
||||
"message": "Always use these values and advanced setting as default."
|
||||
},
|
||||
"advancedGasFeeModalTitle": {
|
||||
"message": "Advanced gas fee"
|
||||
},
|
||||
@ -1851,6 +1857,9 @@
|
||||
"newTransactionFee": {
|
||||
"message": "New Transaction Fee"
|
||||
},
|
||||
"newValues": {
|
||||
"message": "new values"
|
||||
},
|
||||
"next": {
|
||||
"message": "Next"
|
||||
},
|
||||
|
@ -0,0 +1,80 @@
|
||||
import React from 'react';
|
||||
import { useSelector, useDispatch } from 'react-redux';
|
||||
|
||||
import Box from '../../../ui/box';
|
||||
import Typography from '../../../ui/typography';
|
||||
import CheckBox from '../../../ui/check-box';
|
||||
import I18nValue from '../../../ui/i18n-value';
|
||||
import {
|
||||
COLORS,
|
||||
DISPLAY,
|
||||
FLEX_DIRECTION,
|
||||
TYPOGRAPHY,
|
||||
} from '../../../../helpers/constants/design-system';
|
||||
import { getAdvancedGasFeeValues } from '../../../../selectors';
|
||||
import { setAdvancedGasFee } from '../../../../store/actions';
|
||||
|
||||
import { useAdvancedGasFeePopoverContext } from '../context';
|
||||
import { useI18nContext } from '../../../../hooks/useI18nContext';
|
||||
|
||||
const AdvancedGasFeeDefaults = () => {
|
||||
const t = useI18nContext();
|
||||
const dispatch = useDispatch();
|
||||
|
||||
const {
|
||||
hasErrors,
|
||||
baseFeeMultiplier,
|
||||
maxPriorityFeePerGas,
|
||||
} = useAdvancedGasFeePopoverContext();
|
||||
const advancedGasFeeValues = useSelector(getAdvancedGasFeeValues);
|
||||
|
||||
const updateDefaultSettings = (value) => {
|
||||
if (value) {
|
||||
dispatch(
|
||||
setAdvancedGasFee({
|
||||
maxBaseFee: baseFeeMultiplier,
|
||||
priorityFee: maxPriorityFeePerGas,
|
||||
}),
|
||||
);
|
||||
} else {
|
||||
dispatch(setAdvancedGasFee(null));
|
||||
}
|
||||
};
|
||||
const isDefaultSettingsSelected =
|
||||
Boolean(advancedGasFeeValues) &&
|
||||
advancedGasFeeValues.maxBaseFee === baseFeeMultiplier &&
|
||||
advancedGasFeeValues.priorityFee === maxPriorityFeePerGas;
|
||||
|
||||
const handleUpdateDefaultSettings = () =>
|
||||
updateDefaultSettings(!isDefaultSettingsSelected);
|
||||
|
||||
return (
|
||||
<Box
|
||||
display={DISPLAY.FLEX}
|
||||
flexDirection={FLEX_DIRECTION.ROW}
|
||||
marginRight={4}
|
||||
className="advanced-gas-fee-defaults"
|
||||
>
|
||||
<CheckBox
|
||||
checked={isDefaultSettingsSelected}
|
||||
className="advanced-gas-fee-defaults__checkbox"
|
||||
onClick={handleUpdateDefaultSettings}
|
||||
disabled={hasErrors}
|
||||
/>
|
||||
<Typography variant={TYPOGRAPHY.H7} color={COLORS.UI4} margin={0}>
|
||||
{!isDefaultSettingsSelected && Boolean(advancedGasFeeValues) ? (
|
||||
<I18nValue
|
||||
messageKey="advancedGasFeeDefaultOptIn"
|
||||
options={[
|
||||
<strong key="default-value-change">{t('newValues')}</strong>,
|
||||
]}
|
||||
/>
|
||||
) : (
|
||||
<I18nValue messageKey="advancedGasFeeDefaultOptOut" />
|
||||
)}
|
||||
</Typography>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
export default AdvancedGasFeeDefaults;
|
@ -0,0 +1,132 @@
|
||||
import React from 'react';
|
||||
import { fireEvent, screen } from '@testing-library/react';
|
||||
|
||||
import { GAS_ESTIMATE_TYPES } from '../../../../../shared/constants/gas';
|
||||
import { renderWithProvider } from '../../../../../test/lib/render-helpers';
|
||||
import mockEstimates from '../../../../../test/data/mock-estimates.json';
|
||||
import mockState from '../../../../../test/data/mock-state.json';
|
||||
|
||||
import { AdvancedGasFeePopoverContextProvider } from '../context';
|
||||
import { GasFeeContextProvider } from '../../../../contexts/gasFee';
|
||||
import configureStore from '../../../../store/store';
|
||||
|
||||
import AdvancedGasFeeInputs from '../advanced-gas-fee-inputs';
|
||||
import AdvancedGasFeeDefaults from './advanced-gas-fee-defaults';
|
||||
|
||||
jest.mock('../../../../store/actions', () => ({
|
||||
disconnectGasFeeEstimatePoller: jest.fn(),
|
||||
getGasFeeEstimatesAndStartPolling: jest
|
||||
.fn()
|
||||
.mockImplementation(() => Promise.resolve()),
|
||||
addPollingTokenToAppState: jest.fn(),
|
||||
removePollingTokenFromAppState: jest.fn(),
|
||||
}));
|
||||
|
||||
const render = (defaultGasParams) => {
|
||||
const store = configureStore({
|
||||
metamask: {
|
||||
...mockState.metamask,
|
||||
...defaultGasParams,
|
||||
accounts: {
|
||||
[mockState.metamask.selectedAddress]: {
|
||||
address: mockState.metamask.selectedAddress,
|
||||
balance: '0x1F4',
|
||||
},
|
||||
},
|
||||
featureFlags: { advancedInlineGas: true },
|
||||
gasFeeEstimates:
|
||||
mockEstimates[GAS_ESTIMATE_TYPES.FEE_MARKET].gasFeeEstimates,
|
||||
},
|
||||
});
|
||||
return renderWithProvider(
|
||||
<GasFeeContextProvider
|
||||
transaction={{
|
||||
userFeeLevel: 'custom',
|
||||
txParams: {
|
||||
maxFeePerGas: '0x174876E800',
|
||||
maxPriorityFeePerGas: '0x77359400',
|
||||
},
|
||||
}}
|
||||
>
|
||||
<AdvancedGasFeePopoverContextProvider>
|
||||
<AdvancedGasFeeInputs />
|
||||
<AdvancedGasFeeDefaults />
|
||||
</AdvancedGasFeePopoverContextProvider>
|
||||
</GasFeeContextProvider>,
|
||||
store,
|
||||
);
|
||||
};
|
||||
describe('AdvancedGasFeeDefaults', () => {
|
||||
it('should renders correct message when the default is not set', () => {
|
||||
render({ advancedGasFee: null });
|
||||
expect(
|
||||
screen.queryByText(
|
||||
'Always use these values and advanced setting as default.',
|
||||
),
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
it('should renders correct message when the default values are set', () => {
|
||||
render({
|
||||
advancedGasFee: { maxBaseFee: 2, priorityFee: 2 },
|
||||
});
|
||||
expect(
|
||||
screen.queryByText(
|
||||
'Always use these values and advanced setting as default.',
|
||||
),
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
it('should renders correct message when checkbox is selected and default values are saved', () => {
|
||||
render({
|
||||
advancedGasFee: null,
|
||||
});
|
||||
expect(
|
||||
screen.queryByText(
|
||||
'Always use these values and advanced setting as default.',
|
||||
),
|
||||
).toBeInTheDocument();
|
||||
fireEvent.change(document.getElementsByTagName('input')[0], {
|
||||
target: { value: 3 },
|
||||
});
|
||||
fireEvent.change(document.getElementsByTagName('input')[1], {
|
||||
target: { value: 4 },
|
||||
});
|
||||
});
|
||||
it('should renders correct message when the default values are set and the maxBaseFee values are updated', () => {
|
||||
render({
|
||||
advancedGasFee: { maxBaseFee: 2, priorityFee: 2 },
|
||||
});
|
||||
expect(document.getElementsByTagName('input')[2]).toBeChecked();
|
||||
expect(
|
||||
screen.queryByText(
|
||||
'Always use these values and advanced setting as default.',
|
||||
),
|
||||
).toBeInTheDocument();
|
||||
fireEvent.change(document.getElementsByTagName('input')[0], {
|
||||
target: { value: 4 },
|
||||
});
|
||||
expect(document.getElementsByTagName('input')[0]).toHaveValue(4);
|
||||
expect(screen.queryByText('new values')).toBeInTheDocument();
|
||||
expect(
|
||||
screen.queryByText('Save these as my default for "Advanced"'),
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
it('should renders correct message when the default values are set and the priorityFee values are updated', () => {
|
||||
render({
|
||||
advancedGasFee: { maxBaseFee: 2, priorityFee: 2 },
|
||||
});
|
||||
expect(document.getElementsByTagName('input')[2]).toBeChecked();
|
||||
expect(
|
||||
screen.queryByText(
|
||||
'Always use these values and advanced setting as default.',
|
||||
),
|
||||
).toBeInTheDocument();
|
||||
fireEvent.change(document.getElementsByTagName('input')[1], {
|
||||
target: { value: 4 },
|
||||
});
|
||||
expect(document.getElementsByTagName('input')[1]).toHaveValue(4);
|
||||
expect(screen.queryByText('new values')).toBeInTheDocument();
|
||||
expect(
|
||||
screen.queryByText('Save these as my default for "Advanced"'),
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
});
|
@ -0,0 +1 @@
|
||||
export { default } from './advanced-gas-fee-defaults';
|
@ -0,0 +1,6 @@
|
||||
.advanced-gas-fee-defaults {
|
||||
& &__checkbox {
|
||||
font-size: $font-size-h4;
|
||||
margin: 0 8px 0 8px;
|
||||
}
|
||||
}
|
@ -63,6 +63,7 @@ const AdvancedGasFeeGasLimit = () => {
|
||||
tag={TYPOGRAPHY.Paragraph}
|
||||
variant={TYPOGRAPHY.H7}
|
||||
className="advanced-gas-fee-gas-limit"
|
||||
margin={[0, 2]}
|
||||
>
|
||||
<strong>
|
||||
<I18nValue messageKey="gasLimitV2" />
|
||||
|
@ -6,7 +6,7 @@ import PriorityFeeInput from './priority-fee-input';
|
||||
|
||||
const AdvancedGasFeeInputs = () => {
|
||||
return (
|
||||
<Box className="advanced-gas-fee-inputs" margin={[4, 0]}>
|
||||
<Box className="advanced-gas-fee-inputs">
|
||||
<BaseFeeInput />
|
||||
<div className="advanced-gas-fee-inputs__separator" />
|
||||
<PriorityFeeInput />
|
||||
|
@ -10,7 +10,6 @@ import {
|
||||
import { PRIMARY, SECONDARY } from '../../../../../helpers/constants/common';
|
||||
import { bnGreaterThan, bnLessThan } from '../../../../../helpers/utils/util';
|
||||
import { decGWEIToHexWEI } from '../../../../../helpers/utils/conversions.util';
|
||||
|
||||
import { getAdvancedGasFeeValues } from '../../../../../selectors';
|
||||
import { useGasFeeContext } from '../../../../../contexts/gasFee';
|
||||
import { useI18nContext } from '../../../../../hooks/useI18nContext';
|
||||
@ -77,11 +76,13 @@ const validateBaseFee = (
|
||||
|
||||
const BaseFeeInput = () => {
|
||||
const t = useI18nContext();
|
||||
|
||||
const { gasFeeEstimates, estimateUsed, maxFeePerGas } = useGasFeeContext();
|
||||
const {
|
||||
maxPriorityFeePerGas,
|
||||
setErrorValue,
|
||||
setMaxFeePerGas,
|
||||
setBaseFeeMultiplier,
|
||||
} = useAdvancedGasFeePopoverContext();
|
||||
|
||||
const {
|
||||
@ -177,6 +178,7 @@ const BaseFeeInput = () => {
|
||||
if (baseFeeTrend !== 'level' && baseFeeTrend !== feeTrend) {
|
||||
setFeeTrend(baseFeeTrend);
|
||||
}
|
||||
setBaseFeeMultiplier(maxBaseFeeMultiplier);
|
||||
}, [
|
||||
feeTrend,
|
||||
editingInGwei,
|
||||
@ -184,14 +186,16 @@ const BaseFeeInput = () => {
|
||||
gasFeeEstimates,
|
||||
maxBaseFeeGWEI,
|
||||
maxPriorityFeePerGas,
|
||||
maxBaseFeeMultiplier,
|
||||
setBaseFeeError,
|
||||
setErrorValue,
|
||||
setMaxFeePerGas,
|
||||
setFeeTrend,
|
||||
setBaseFeeMultiplier,
|
||||
]);
|
||||
|
||||
return (
|
||||
<Box className="base-fee-input">
|
||||
<Box className="base-fee-input" margin={[0, 2]}>
|
||||
<FormField
|
||||
error={baseFeeError ? t(baseFeeError) : ''}
|
||||
onChange={updateBaseFee}
|
||||
|
@ -9,6 +9,6 @@
|
||||
|
||||
&__separator {
|
||||
border-top: 1px solid $ui-grey;
|
||||
margin: 24px 0 16px 0;
|
||||
margin: 16px 0;
|
||||
}
|
||||
}
|
||||
|
@ -11,6 +11,7 @@ import { useGasFeeContext } from '../../../../../contexts/gasFee';
|
||||
import { useI18nContext } from '../../../../../hooks/useI18nContext';
|
||||
import { useUserPreferencedCurrency } from '../../../../../hooks/useUserPreferencedCurrency';
|
||||
import FormField from '../../../../ui/form-field';
|
||||
import Box from '../../../../ui/box';
|
||||
import { bnGreaterThan, bnLessThan } from '../../../../../helpers/utils/util';
|
||||
|
||||
import { useAdvancedGasFeePopoverContext } from '../../context';
|
||||
@ -103,7 +104,7 @@ const PriorityFeeInput = () => {
|
||||
]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Box margin={[0, 2]}>
|
||||
<FormField
|
||||
error={priorityFeeError ? t(priorityFeeError) : ''}
|
||||
onChange={updatePriorityFee}
|
||||
@ -119,7 +120,7 @@ const PriorityFeeInput = () => {
|
||||
historical={renderFeeRange(historicalPriorityFeeRange)}
|
||||
feeTrend={feeTrend}
|
||||
/>
|
||||
</>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -9,6 +9,7 @@ import { AdvancedGasFeePopoverContextProvider } from './context';
|
||||
import AdvancedGasFeeInputs from './advanced-gas-fee-inputs';
|
||||
import AdvancedGasFeeGasLimit from './advanced-gas-fee-gas-limit';
|
||||
import AdvancedGasFeeSaveButton from './advanced-gas-fee-save';
|
||||
import AdvancedGasFeeDefaults from './advanced-gas-fee-defaults';
|
||||
|
||||
const AdvancedGasFeePopover = () => {
|
||||
const t = useI18nContext();
|
||||
@ -29,9 +30,11 @@ const AdvancedGasFeePopover = () => {
|
||||
onClose={closeAllModals}
|
||||
footer={<AdvancedGasFeeSaveButton />}
|
||||
>
|
||||
<Box className="advanced-gas-fee-popover__wrapper" margin={4}>
|
||||
<Box margin={4}>
|
||||
<AdvancedGasFeeInputs />
|
||||
<div className="advanced-gas-fee-popover__separator" />
|
||||
<AdvancedGasFeeDefaults />
|
||||
<div className="advanced-gas-fee-popover__separator" />
|
||||
<AdvancedGasFeeGasLimit />
|
||||
</Box>
|
||||
</Popover>
|
||||
|
@ -20,6 +20,7 @@ export const AdvancedGasFeePopoverContextProvider = ({ children }) => {
|
||||
},
|
||||
[errors, setErrors],
|
||||
);
|
||||
const [baseFeeMultiplier, setBaseFeeMultiplier] = useState();
|
||||
|
||||
return (
|
||||
<AdvancedGasFeePopoverContext.Provider
|
||||
@ -29,9 +30,11 @@ export const AdvancedGasFeePopoverContextProvider = ({ children }) => {
|
||||
maxFeePerGas,
|
||||
maxPriorityFeePerGas,
|
||||
setErrorValue,
|
||||
baseFeeMultiplier,
|
||||
setGasLimit,
|
||||
setMaxPriorityFeePerGas,
|
||||
setMaxFeePerGas,
|
||||
setBaseFeeMultiplier,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
|
@ -1,14 +1,21 @@
|
||||
.advanced-gas-fee-popover {
|
||||
&__wrapper {
|
||||
border-top: 1px solid $ui-grey;
|
||||
}
|
||||
|
||||
&__separator {
|
||||
border-top: 1px solid $ui-grey;
|
||||
margin: 24px 0 16px 0;
|
||||
margin: 16px 0;
|
||||
}
|
||||
|
||||
.form-field__heading-title > h6 {
|
||||
font-size: $font-size-h7;
|
||||
}
|
||||
|
||||
.popover-header {
|
||||
border-radius: 0;
|
||||
border-top-left-radius: 10px;
|
||||
border-top-right-radius: 10px;
|
||||
border-bottom: 1px solid $ui-grey;
|
||||
}
|
||||
|
||||
.popover-footer {
|
||||
border-top: none;
|
||||
}
|
||||
}
|
||||
|
@ -62,9 +62,10 @@
|
||||
@import 'whats-new-popup/index';
|
||||
@import 'loading-network-screen/index';
|
||||
@import 'flask/experimental-area/index';
|
||||
@import 'transaction-decoding/index';
|
||||
@import 'advanced-gas-fee-popover/index';
|
||||
@import 'advanced-gas-fee-popover/advanced-gas-fee-gas-limit/index';
|
||||
@import 'advanced-gas-fee-popover/advanced-gas-fee-inputs/index';
|
||||
@import 'advanced-gas-fee-popover/advanced-gas-fee-inputs/base-fee-input/index';
|
||||
@import 'advanced-gas-fee-popover/advanced-gas-fee-input-subtext/index';
|
||||
@import 'transaction-decoding/index';
|
||||
@import 'advanced-gas-fee-popover/advanced-gas-fee-defaults/index';
|
||||
|
Loading…
Reference in New Issue
Block a user