Adding edit gas fee modal (#12624)

Edit transaction screen changes for EIP-1559 V2
feature/default_network_editable
Jyoti Puri 3 years ago committed by GitHub
parent cce2dda8e4
commit 0daefe9ea0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 21
      app/_locales/en/messages.json
  2. 2
      ui/components/app/app-components.scss
  3. 9
      ui/components/app/confirm-page-container/confirm-page-container.component.js
  4. 49
      ui/components/app/edit-gas-fee-popover/edit-gas-fee-popover.js
  5. 93
      ui/components/app/edit-gas-fee-popover/edit-gas-fee-popover.test.js
  6. 84
      ui/components/app/edit-gas-fee-popover/edit-gas-item/edit-gas-item.js
  7. 93
      ui/components/app/edit-gas-fee-popover/edit-gas-item/edit-gas-item.test.js
  8. 1
      ui/components/app/edit-gas-fee-popover/edit-gas-item/index.js
  9. 56
      ui/components/app/edit-gas-fee-popover/edit-gas-item/index.scss
  10. 1
      ui/components/app/edit-gas-fee-popover/index.js
  11. 35
      ui/components/app/edit-gas-fee-popover/index.scss
  12. 4
      ui/components/app/gas-timing/gas-timing.component.js
  13. 23
      ui/components/app/transaction-detail/transaction-detail.component.js
  14. 8
      ui/helpers/constants/gas.js
  15. 16
      ui/helpers/utils/util.js
  16. 39
      ui/helpers/utils/util.test.js
  17. 34
      ui/hooks/gasFeeInput/useGasFeeInputs.js
  18. 1
      ui/hooks/gasFeeInput/useGasFeeInputs.test.js
  19. 49
      ui/hooks/gasFeeInput/useTransactionFunctions.js
  20. 6
      ui/pages/confirm-transaction-base/gas-details-item/gas-details-item.js
  21. 4
      ui/pages/confirm-transaction-base/low-priority-message/low-priority-message.js

@ -710,6 +710,9 @@
"editGasEducationModalTitle": {
"message": "How to choose?"
},
"editGasFeeModalTitle": {
"message": "Edit gas fee"
},
"editGasHigh": {
"message": "High"
},
@ -1011,6 +1014,9 @@
"message": "Gas limit must be at least $1",
"description": "$1 is the custom gas limit, in decimal."
},
"gasOption": {
"message": "Gas option"
},
"gasPrice": {
"message": "Gas Price (GWEI)"
},
@ -1032,10 +1038,18 @@
"gasPriceLabel": {
"message": "Gas price"
},
"gasTimingHoursShort": {
"message": "$1 hrs",
"description": "$1 represents a number of hours"
},
"gasTimingMinutes": {
"message": "$1 minutes",
"description": "$1 represents a number of minutes"
},
"gasTimingMinutesShort": {
"message": "$1 min",
"description": "$1 represents a number of minutes"
},
"gasTimingNegative": {
"message": "Maybe in $1",
"description": "$1 represents an amount of time"
@ -1048,6 +1062,10 @@
"message": "$1 seconds",
"description": "$1 represents a number of seconds"
},
"gasTimingSecondsShort": {
"message": "$1 sec",
"description": "$1 represents a number of seconds"
},
"gasTimingVeryPositive": {
"message": "Very likely in < $1",
"description": "$1 represents an amount of time"
@ -2793,6 +2811,9 @@
"thisWillCreate": {
"message": "This will create a new wallet and Secret Recovery Phrase"
},
"time": {
"message": "Time"
},
"tips": {
"message": "Tips"
},

@ -13,6 +13,8 @@
@import 'connected-status-indicator/index';
@import 'edit-gas-display/index';
@import 'edit-gas-display-education/index';
@import 'edit-gas-fee-popover/index';
@import 'edit-gas-fee-popover/edit-gas-item/index';
@import 'gas-customization/gas-modal-page-container/index';
@import 'gas-customization/gas-price-button-group/index';
@import 'gas-customization/index';

@ -8,12 +8,16 @@ import { GasFeeContextProvider } from '../../../contexts/gasFee';
import ErrorMessage from '../../ui/error-message';
import { TRANSACTION_TYPES } from '../../../../shared/constants/transaction';
import Dialog from '../../ui/dialog';
import EditGasFeePopover from '../edit-gas-fee-popover/edit-gas-fee-popover';
import {
ConfirmPageContainerHeader,
ConfirmPageContainerContent,
ConfirmPageContainerNavigation,
} from '.';
// eslint-disable-next-line prefer-destructuring
const EIP_1559_V2 = process.env.EIP_1559_V2;
export default class ConfirmPageContainer extends Component {
static contextTypes = {
t: PropTypes.func,
@ -225,13 +229,16 @@ export default class ConfirmPageContainer extends Component {
)}
</PageContainerFooter>
)}
{editingGas && (
{editingGas && !EIP_1559_V2 && (
<EditGasPopover
mode={EDIT_GAS_MODES.MODIFY_IN_PLACE}
onClose={handleCloseEditGas}
transaction={currentTransaction}
/>
)}
{editingGas && EIP_1559_V2 && (
<EditGasFeePopover onClose={handleCloseEditGas} />
)}
</div>
</GasFeeContextProvider>
);

@ -0,0 +1,49 @@
import React from 'react';
import PropTypes from 'prop-types';
import { useI18nContext } from '../../../hooks/useI18nContext';
import Popover from '../../ui/popover';
import I18nValue from '../../ui/i18n-value';
import LoadingHeartBeat from '../../ui/loading-heartbeat';
import EditGasItem from './edit-gas-item';
const EditGasFeePopover = ({ onClose }) => {
const t = useI18nContext();
return (
<Popover
title={t('editGasFeeModalTitle')}
onClose={onClose}
className="edit-gas-fee-popover"
>
<>
{process.env.IN_TEST === 'true' ? null : <LoadingHeartBeat />}
<div className="edit-gas-fee-popover__wrapper">
<div className="edit-gas-fee-popover__content">
<div className="edit-gas-fee-popover__content__header">
<span className="edit-gas-fee-popover__content__header-option">
<I18nValue messageKey="gasOption" />
</span>
<span className="edit-gas-fee-popover__content__header-time">
<I18nValue messageKey="time" />
</span>
<span className="edit-gas-fee-popover__content__header-max-fee">
<I18nValue messageKey="maxFee" />
</span>
</div>
<EditGasItem estimateType="low" onClose={onClose} />
<EditGasItem estimateType="medium" onClose={onClose} />
<EditGasItem estimateType="high" onClose={onClose} />
</div>
</div>
</>
</Popover>
);
};
EditGasFeePopover.propTypes = {
onClose: PropTypes.func,
};
export default EditGasFeePopover;

@ -0,0 +1,93 @@
import React from 'react';
import { screen } from '@testing-library/react';
import { renderWithProvider } from '../../../../test/lib/render-helpers';
import { ETH } from '../../../helpers/constants/common';
import configureStore from '../../../store/store';
import { GasFeeContextProvider } from '../../../contexts/gasFee';
import EditGasFeePopover from './edit-gas-fee-popover';
jest.mock('../../../store/actions', () => ({
disconnectGasFeeEstimatePoller: jest.fn(),
getGasFeeEstimatesAndStartPolling: jest
.fn()
.mockImplementation(() => Promise.resolve()),
addPollingTokenToAppState: jest.fn(),
}));
const MOCK_FEE_ESTIMATE = {
low: {
minWaitTimeEstimate: 360000,
maxWaitTimeEstimate: 300000,
suggestedMaxPriorityFeePerGas: '3',
suggestedMaxFeePerGas: '53',
},
medium: {
minWaitTimeEstimate: 30000,
maxWaitTimeEstimate: 60000,
suggestedMaxPriorityFeePerGas: '7',
suggestedMaxFeePerGas: '70',
},
high: {
minWaitTimeEstimate: 15000,
maxWaitTimeEstimate: 15000,
suggestedMaxPriorityFeePerGas: '10',
suggestedMaxFeePerGas: '100',
},
estimatedBaseFee: '50',
};
const renderComponent = () => {
const store = configureStore({
metamask: {
nativeCurrency: ETH,
provider: {},
cachedBalances: {},
accounts: {
'0xAddress': {
address: '0xAddress',
balance: '0x176e5b6f173ebe66',
},
},
selectedAddress: '0xAddress',
featureFlags: { advancedInlineGas: true },
gasFeeEstimates: MOCK_FEE_ESTIMATE,
},
});
return renderWithProvider(
<GasFeeContextProvider transaction={{ txParams: { gas: '0x5208' } }}>
<EditGasFeePopover />
</GasFeeContextProvider>,
store,
);
};
describe('EditGasFeePopover', () => {
it('should renders low / medium / high options', () => {
renderComponent();
expect(screen.queryByText('🐢')).toBeInTheDocument();
expect(screen.queryByText('🦊')).toBeInTheDocument();
expect(screen.queryByText('🦍')).toBeInTheDocument();
expect(screen.queryByText('Low')).toBeInTheDocument();
expect(screen.queryByText('Market')).toBeInTheDocument();
expect(screen.queryByText('Aggressive')).toBeInTheDocument();
});
it('should show time estimates', () => {
renderComponent();
console.log(document.body.innerHTML);
expect(screen.queryByText('6 min')).toBeInTheDocument();
expect(screen.queryByText('30 sec')).toBeInTheDocument();
expect(screen.queryByText('15 sec')).toBeInTheDocument();
});
it('should show gas fee estimates', () => {
renderComponent();
expect(screen.queryByTitle('0.001113 ETH')).toBeInTheDocument();
expect(screen.queryByTitle('0.00147 ETH')).toBeInTheDocument();
expect(screen.queryByTitle('0.0021 ETH')).toBeInTheDocument();
});
});

@ -0,0 +1,84 @@
import React from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';
import { getMaximumGasTotalInHexWei } from '../../../../../shared/modules/gas.utils';
import { PRIORITY_LEVEL_ICON_MAP } from '../../../../helpers/constants/gas';
import { PRIMARY } from '../../../../helpers/constants/common';
import {
decGWEIToHexWEI,
decimalToHex,
} from '../../../../helpers/utils/conversions.util';
import { toHumanReadableTime } from '../../../../helpers/utils/util';
import { useGasFeeContext } from '../../../../contexts/gasFee';
import { useI18nContext } from '../../../../hooks/useI18nContext';
import I18nValue from '../../../ui/i18n-value';
import InfoTooltip from '../../../ui/info-tooltip';
import UserPreferencedCurrencyDisplay from '../../user-preferenced-currency-display';
const EditGasItem = ({ estimateType, onClose }) => {
const {
estimateUsed,
gasFeeEstimates,
gasLimit,
setEstimateToUse,
updateTransaction,
} = useGasFeeContext();
const t = useI18nContext();
const { minWaitTimeEstimate, suggestedMaxFeePerGas } =
gasFeeEstimates[estimateType] || {};
const hexMaximumTransactionFee = suggestedMaxFeePerGas
? getMaximumGasTotalInHexWei({
gasLimit: decimalToHex(gasLimit),
maxFeePerGas: decGWEIToHexWEI(suggestedMaxFeePerGas),
})
: null;
const onOptionSelect = () => {
setEstimateToUse(estimateType);
updateTransaction(estimateType);
onClose();
};
return (
<div
className={classNames('edit-gas-item', {
'edit-gas-item--selected': estimateType === estimateUsed,
})}
role="button"
onClick={onOptionSelect}
>
<span className="edit-gas-item__name">
<span className="edit-gas-item__icon">
{PRIORITY_LEVEL_ICON_MAP[estimateType]}
</span>
<I18nValue messageKey={estimateType} />
</span>
<span
className={`edit-gas-item__time-estimate edit-gas-item__time-estimate-${estimateType}`}
>
{minWaitTimeEstimate && toHumanReadableTime(t, minWaitTimeEstimate)}
</span>
<span
className={`edit-gas-item__fee-estimate edit-gas-item__fee-estimate-${estimateType}`}
>
<UserPreferencedCurrencyDisplay
key="editGasSubTextFeeAmount"
type={PRIMARY}
value={hexMaximumTransactionFee}
/>
</span>
<span className="edit-gas-item__tooltip">
<InfoTooltip position="top" />
</span>
</div>
);
};
EditGasItem.propTypes = {
estimateType: PropTypes.string,
onClose: PropTypes.func,
};
export default EditGasItem;

@ -0,0 +1,93 @@
import React from 'react';
import { screen } from '@testing-library/react';
import { renderWithProvider } from '../../../../../test/lib/render-helpers';
import { ETH } from '../../../../helpers/constants/common';
import configureStore from '../../../../store/store';
import { GasFeeContextProvider } from '../../../../contexts/gasFee';
import EditGasItem from './edit-gas-item';
jest.mock('../../../../store/actions', () => ({
disconnectGasFeeEstimatePoller: jest.fn(),
getGasFeeEstimatesAndStartPolling: jest
.fn()
.mockImplementation(() => Promise.resolve()),
addPollingTokenToAppState: jest.fn(),
}));
const MOCK_FEE_ESTIMATE = {
low: {
minWaitTimeEstimate: 360000,
maxWaitTimeEstimate: 300000,
suggestedMaxPriorityFeePerGas: '3',
suggestedMaxFeePerGas: '53',
},
medium: {
minWaitTimeEstimate: 30000,
maxWaitTimeEstimate: 60000,
suggestedMaxPriorityFeePerGas: '7',
suggestedMaxFeePerGas: '70',
},
high: {
minWaitTimeEstimate: 15000,
maxWaitTimeEstimate: 15000,
suggestedMaxPriorityFeePerGas: '10',
suggestedMaxFeePerGas: '100',
},
estimatedBaseFee: '50',
};
const renderComponent = (props) => {
const store = configureStore({
metamask: {
nativeCurrency: ETH,
provider: {},
cachedBalances: {},
accounts: {
'0xAddress': {
address: '0xAddress',
balance: '0x176e5b6f173ebe66',
},
},
selectedAddress: '0xAddress',
featureFlags: { advancedInlineGas: true },
gasFeeEstimates: MOCK_FEE_ESTIMATE,
},
});
return renderWithProvider(
<GasFeeContextProvider transaction={{ txParams: { gas: '0x5208' } }}>
<EditGasItem estimateType="low" {...props} />
</GasFeeContextProvider>,
store,
);
};
describe('EditGasItem', () => {
it('should renders low gas estimate options for estimateType low', () => {
renderComponent({ estimateType: 'low' });
expect(screen.queryByText('🐢')).toBeInTheDocument();
expect(screen.queryByText('Low')).toBeInTheDocument();
expect(screen.queryByText('6 min')).toBeInTheDocument();
expect(screen.queryByTitle('0.001113 ETH')).toBeInTheDocument();
});
it('should renders market gas estimate options for estimateType medium', () => {
renderComponent({ estimateType: 'medium' });
expect(screen.queryByText('🦊')).toBeInTheDocument();
expect(screen.queryByText('Market')).toBeInTheDocument();
expect(screen.queryByText('30 sec')).toBeInTheDocument();
expect(screen.queryByTitle('0.00147 ETH')).toBeInTheDocument();
});
it('should renders aggressive gas estimate options for estimateType high', () => {
renderComponent({ estimateType: 'high' });
expect(screen.queryByText('🦍')).toBeInTheDocument();
expect(screen.queryByText('15 sec')).toBeInTheDocument();
expect(screen.queryByTitle('0.0021 ETH')).toBeInTheDocument();
});
});

@ -0,0 +1 @@
export { default } from './edit-gas-item';

@ -0,0 +1,56 @@
.edit-gas-item {
border-radius: 24px;
color: $ui-4;
cursor: pointer;
font-size: 12px;
margin: 12px 0;
padding: 4px 12px;
height: 32px;
&--selected {
background-color: $ui-1;
}
&__name {
display: inline-block;
color: $ui-black;
font-size: 12px;
font-weight: bold;
width: 40%;
}
&__icon {
margin-right: 4px;
}
&__time-estimate {
display: inline-block;
width: 20%;
}
&__fee-estimate {
display: inline-block;
width: 30%;
white-space: nowrap;
}
&__tooltip {
display: inline-block;
text-align: right;
width: 10%;
.info-tooltip {
display: inline-block;
}
}
&__time-estimate-low,
&__fee-estimate-high {
color: $secondary-1;
}
&__time-estimate-medium,
&__time-estimate-high {
color: $success-3;
}
}

@ -0,0 +1 @@
export { default } from './edit-gas-fee-popover';

@ -0,0 +1,35 @@
.edit-gas-fee-popover {
@media screen and (min-width: $break-large) {
max-height: 84vh;
}
&__wrapper {
border-top: 1px solid $ui-grey;
}
&__content {
padding: 16px 12px;
&__header {
color: $ui-4;
font-size: 10px;
font-weight: 700;
margin: 0 12px;
&-option {
display: inline-block;
width: 40%;
}
&-time {
display: inline-block;
width: 20%;
}
&-max-fee {
display: inline-block;
width: 30%;
}
}
}
}

@ -50,7 +50,7 @@ export default function GasTiming({
const [customEstimatedTime, setCustomEstimatedTime] = useState(null);
const t = useContext(I18nContext);
const { estimateToUse } = useGasFeeContext();
const { estimateUsed } = useGasFeeContext();
// If the user has chosen a value lower than the low gas fee estimate,
// We'll need to use the useEffect hook below to make a call to calculate
@ -155,7 +155,7 @@ export default function GasTiming({
]);
}
} else {
if (!EIP_1559_V2 || estimateToUse === 'low') {
if (!EIP_1559_V2 || estimateUsed === 'low') {
attitude = 'negative';
}
// If the user has chosen a value less than our low estimate,

@ -1,40 +1,29 @@
import React, { useContext } from 'react';
import React from 'react';
import PropTypes from 'prop-types';
import { I18nContext } from '../../../contexts/i18n';
import { useGasFeeContext } from '../../../contexts/gasFee';
import InfoTooltip from '../../ui/info-tooltip/info-tooltip';
import Typography from '../../ui/typography/typography';
import TransactionDetailItem from '../transaction-detail-item/transaction-detail-item.component';
import { COLORS } from '../../../helpers/constants/design-system';
const GasLevelIconMap = {
low: '🐢',
medium: '🦊',
high: '🦍',
dappSuggested: '🌐',
custom: '⚙',
};
import { PRIORITY_LEVEL_ICON_MAP } from '../../../helpers/constants/gas';
import { useI18nContext } from '../../../hooks/useI18nContext';
export default function TransactionDetail({ rows = [], onEdit }) {
// eslint-disable-next-line prefer-destructuring
const EIP_1559_V2 = process.env.EIP_1559_V2;
const t = useContext(I18nContext);
const t = useI18nContext();
const {
estimateToUse,
gasLimit,
gasPrice,
isUsingDappSuggestedGasFees,
estimateUsed,
maxFeePerGas,
maxPriorityFeePerGas,
transaction,
supportsEIP1559,
} = useGasFeeContext();
const estimateUsed = isUsingDappSuggestedGasFees
? 'dappSuggested'
: estimateToUse;
if (EIP_1559_V2 && estimateUsed) {
return (
@ -42,7 +31,7 @@ export default function TransactionDetail({ rows = [], onEdit }) {
<div className="transaction-detail-edit-V2">
<button onClick={onEdit}>
<span className="transaction-detail-edit-V2__icon">
{`${GasLevelIconMap[estimateUsed]} `}
{`${PRIORITY_LEVEL_ICON_MAP[estimateUsed]} `}
</span>
<span className="transaction-detail-edit-V2__label">
{t(estimateUsed)}

@ -31,3 +31,11 @@ export function getGasFormErrorText(type, t, { minimumGasLimit } = {}) {
return '';
}
}
export const PRIORITY_LEVEL_ICON_MAP = {
low: '🐢',
medium: '🦊',
high: '🦍',
dappSuggested: '🌐',
custom: '⚙',
};

@ -408,3 +408,19 @@ export function getURLHost(url) {
export function getURLHostName(url) {
return getURL(url)?.hostname || '';
}
// Once we reach this threshold, we switch to higher unit
const MINUTE_CUTOFF = 90 * 60;
const SECOND_CUTOFF = 90;
export const toHumanReadableTime = (t, milliseconds) => {
if (milliseconds === undefined || milliseconds === null) return '';
const seconds = Math.ceil(milliseconds / 1000);
if (seconds <= SECOND_CUTOFF) {
return t('gasTimingSecondsShort', [seconds]);
}
if (seconds <= MINUTE_CUTOFF) {
return t('gasTimingMinutesShort', [Math.ceil(seconds / 60)]);
}
return t('gasTimingHoursShort', [Math.ceil(seconds / 3600)]);
};

@ -301,4 +301,43 @@ describe('util', () => {
});
});
});
describe('toHumanReadableTime()', () => {
const t = (key, number) => {
switch (key) {
case 'gasTimingSecondsShort':
return `${number} sec`;
case 'gasTimingMinutesShort':
return `${number} min`;
case 'gasTimingHoursShort':
return `${number} hrs`;
default:
return '';
}
};
it('should return empty string if milliseconds passed is undefined', () => {
expect(util.toHumanReadableTime(t)).toStrictEqual('');
});
it('should return rounded value for time', () => {
expect(util.toHumanReadableTime(t, 6300)).toStrictEqual('7 sec');
});
it('should return value in seconds for milliseconds passed is < 9000', () => {
expect(util.toHumanReadableTime(t, 6000)).toStrictEqual('6 sec');
});
it('should return value in seconds for milliseconds passed is > 6000 and <= 9000', () => {
expect(util.toHumanReadableTime(t, 9000)).toStrictEqual('9 sec');
});
it('should return value in minutes for milliseconds passed is > 90000', () => {
expect(util.toHumanReadableTime(t, 90001)).toStrictEqual('2 min');
});
it('should return value in minutes for milliseconds passed is > 90000 and <= 5400000', () => {
expect(util.toHumanReadableTime(t, 5400000)).toStrictEqual('90 min');
});
it('should return value in hours for milliseconds passed is > 5400000', () => {
expect(util.toHumanReadableTime(t, 5400001)).toStrictEqual('2 hrs');
});
it('should return value in hours for milliseconds passed very high above 5400000', () => {
expect(util.toHumanReadableTime(t, 7200000)).toStrictEqual('2 hrs');
});
});
});

@ -21,6 +21,7 @@ import { useGasPriceInput } from './useGasPriceInput';
import { useMaxFeePerGasInput } from './useMaxFeePerGasInput';
import { useMaxPriorityFeePerGasInput } from './useMaxPriorityFeePerGasInput';
import { useGasEstimates } from './useGasEstimates';
import { useTransactionFunctions } from './useTransactionFunctions';
/**
* @typedef {Object} GasFeeInputReturnType
@ -100,14 +101,14 @@ export function useGasFeeInputs(
return defaultEstimateToUse;
});
const [
isUsingDappSuggestedGasFees,
setIsUsingDappSuggestedGasFees,
] = useState(() =>
Boolean(areDappSuggestedAndTxParamGasFeesTheSame(transaction)),
);
const [estimateUsed, setEstimateUsed] = useState(() => {
if (areDappSuggestedAndTxParamGasFeesTheSame(transaction)) {
return 'dappSuggested';
}
return estimateToUse;
});
const [gasLimit, setGasLimit] = useState(
const [gasLimit, setGasLimit] = useState(() =>
Number(hexToDecimal(transaction?.txParams?.gas ?? '0x0')),
);
@ -197,6 +198,17 @@ export function useGasFeeInputs(
}
}, [minimumGasLimit, gasErrors.gasLimit, transaction]);
const { updateTransaction } = useTransactionFunctions({
defaultEstimateToUse,
gasLimit,
gasPrice,
maxFeePerGas,
maxPriorityFeePerGas,
gasFeeEstimates,
supportsEIP1559,
transaction,
});
// When a user selects an estimate level, it will wipe out what they have
// previously put in the inputs. This returns the inputs to the estimated
// values at the level specified.
@ -208,7 +220,7 @@ export function useGasFeeInputs(
setMaxPriorityFeePerGas(null);
setGasPrice(null);
setGasPriceHasBeenManuallySet(false);
setIsUsingDappSuggestedGasFees(false);
setEstimateUsed(estimateLevel);
},
[
setInternalEstimateToUse,
@ -217,7 +229,7 @@ export function useGasFeeInputs(
setMaxPriorityFeePerGas,
setGasPrice,
setGasPriceHasBeenManuallySet,
setIsUsingDappSuggestedGasFees,
setEstimateUsed,
],
);
@ -230,6 +242,7 @@ export function useGasFeeInputs(
setMaxFeePerGas(maxFeePerGas);
setMaxPriorityFeePerGas(maxPriorityFeePerGas);
setGasPriceHasBeenManuallySet(true);
setEstimateUsed('custom');
}, [
setInternalEstimateToUse,
handleGasLimitOutOfBoundError,
@ -263,7 +276,7 @@ export function useGasFeeInputs(
estimatedMaximumNative,
estimatedMinimumNative,
isGasEstimatesLoading,
isUsingDappSuggestedGasFees,
estimateUsed,
gasFeeEstimates,
gasEstimateType,
estimatedGasFeeTimeBounds,
@ -276,5 +289,6 @@ export function useGasFeeInputs(
gasWarnings,
hasGasErrors,
supportsEIP1559,
updateTransaction,
};
}

@ -37,6 +37,7 @@ jest.mock('react-redux', () => {
return {
...actual,
useSelector: jest.fn(),
useDispatch: () => jest.fn(),
};
});

@ -0,0 +1,49 @@
import { useCallback } from 'react';
import { useDispatch } from 'react-redux';
import {
decGWEIToHexWEI,
decimalToHex,
} from '../../helpers/utils/conversions.util';
import { updateTransaction as updateTransactionFn } from '../../store/actions';
export const useTransactionFunctions = ({
defaultEstimateToUse,
gasLimit,
gasFeeEstimates,
transaction,
}) => {
const dispatch = useDispatch();
const updateTransaction = useCallback(
(estimateType) => {
const newGasSettings = {
gas: decimalToHex(gasLimit),
gasLimit: decimalToHex(gasLimit),
estimateSuggested: defaultEstimateToUse,
estimateUsed: estimateType,
};
newGasSettings.maxFeePerGas = decGWEIToHexWEI(
gasFeeEstimates[estimateType].suggestedMaxFeePerGas,
);
newGasSettings.maxPriorityFeePerGas = decGWEIToHexWEI(
gasFeeEstimates[estimateType].suggestedMaxPriorityFeePerGas,
);
const updatedTxMeta = {
...transaction,
userFeeLevel: estimateType || 'custom',
txParams: {
...transaction.txParams,
...newGasSettings,
},
};
dispatch(updateTransactionFn(updatedTxMeta));
},
[defaultEstimateToUse, dispatch, gasLimit, gasFeeEstimates, transaction],
);
return { updateTransaction };
};

@ -31,7 +31,7 @@ const GasDetailsItem = ({
useNativeCurrencyAsPrimaryCurrency,
}) => {
const t = useI18nContext();
const { estimateToUse } = useGasFeeContext();
const { estimateUsed } = useGasFeeContext();
return (
<TransactionDetailItem
@ -96,12 +96,12 @@ const GasDetailsItem = ({
key="editGasSubTextFeeLabel"
display="inline-flex"
className={classNames('gas-details-item__gasfee-label', {
'gas-details-item__gas-fee-warning': estimateToUse === 'high',
'gas-details-item__gas-fee-warning': estimateUsed === 'high',
})}
>
<Box marginRight={1}>
<b>
{estimateToUse === 'high' && '⚠ '}
{estimateUsed === 'high' && '⚠ '}
<I18nValue messageKey="editGasSubTextFeeLabel" />
</b>
</Box>

@ -5,10 +5,10 @@ import { useGasFeeContext } from '../../../contexts/gasFee';
import { useI18nContext } from '../../../hooks/useI18nContext';
const LowPriorityMessage = () => {
const { estimateToUse } = useGasFeeContext();
const { estimateUsed } = useGasFeeContext();
const t = useI18nContext();
if (estimateToUse !== 'low') return null;
if (estimateUsed !== 'low') return null;
return (
<div className="low-priority-message">
<ActionableMessage

Loading…
Cancel
Save