mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-12-23 09:52:26 +01:00
EIP-1559 - Improve gas timing logic to show more accurate verbiage (#11668)
This commit is contained in:
parent
714170c7b8
commit
e283c03c4e
@ -1122,6 +1122,11 @@ export default class MetamaskController extends EventEmitter {
|
||||
this.gasFeeController.disconnectPoller,
|
||||
this.gasFeeController,
|
||||
),
|
||||
|
||||
getGasFeeTimeEstimate: nodeify(
|
||||
this.gasFeeController.getTimeEstimate,
|
||||
this.gasFeeController,
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -15,7 +15,6 @@ import {
|
||||
COLORS,
|
||||
TYPOGRAPHY,
|
||||
FONT_WEIGHT,
|
||||
TEXT_ALIGN,
|
||||
} from '../../../helpers/constants/design-system';
|
||||
import { areDappSuggestedAndTxParamGasFeesTheSame } from '../../../helpers/utils/confirm-tx.util';
|
||||
|
||||
@ -52,7 +51,6 @@ export default function EditGasDisplay({
|
||||
setEstimateToUse,
|
||||
estimatedMinimumFiat,
|
||||
estimatedMaximumFiat,
|
||||
hasGasErrors,
|
||||
dappSuggestedGasFeeAcknowledged,
|
||||
setDappSuggestedGasFeeAcknowledged,
|
||||
showAdvancedForm,
|
||||
@ -134,7 +132,12 @@ export default function EditGasDisplay({
|
||||
</Typography>,
|
||||
])
|
||||
}
|
||||
timing={<GasTiming maxPriorityFeePerGas={maxPriorityFeePerGas} />}
|
||||
timing={
|
||||
<GasTiming
|
||||
maxFeePerGas={maxFeePerGas}
|
||||
maxPriorityFeePerGas={maxPriorityFeePerGas}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
{requireDappAcknowledgement && (
|
||||
<Button
|
||||
@ -144,22 +147,6 @@ export default function EditGasDisplay({
|
||||
{t('gasDisplayAcknowledgeDappButtonText')}
|
||||
</Button>
|
||||
)}
|
||||
{hasGasErrors && (
|
||||
<div className="edit-gas-display__error">
|
||||
<Typography
|
||||
color={COLORS.ERROR1}
|
||||
variant={TYPOGRAPHY.H7}
|
||||
align={TEXT_ALIGN.CENTER}
|
||||
fontWeight={FONT_WEIGHT.BOLD}
|
||||
>
|
||||
{t('editGasTooLow')}{' '}
|
||||
<InfoTooltip
|
||||
position="top"
|
||||
contentText={t('editGasTooLowTooltip')}
|
||||
/>
|
||||
</Typography>
|
||||
</div>
|
||||
)}
|
||||
{networkSupports1559 &&
|
||||
!requireDappAcknowledgement &&
|
||||
![EDIT_GAS_MODES.SPEED_UP, EDIT_GAS_MODES.CANCEL].includes(mode) && (
|
||||
@ -259,7 +246,6 @@ EditGasDisplay.propTypes = {
|
||||
setEstimateToUse: PropTypes.func,
|
||||
estimatedMinimumFiat: PropTypes.string,
|
||||
estimatedMaximumFiat: PropTypes.string,
|
||||
hasGasErrors: PropTypes.boolean,
|
||||
dappSuggestedGasFeeAcknowledged: PropTypes.boolean,
|
||||
setDappSuggestedGasFeeAcknowledged: PropTypes.func,
|
||||
showAdvancedForm: PropTypes.bool,
|
||||
|
@ -21,14 +21,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
&__error .info-tooltip {
|
||||
display: inline-block;
|
||||
|
||||
path {
|
||||
fill: $error-1;
|
||||
}
|
||||
}
|
||||
|
||||
&__dapp-acknowledgement-warning {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
@ -235,7 +235,6 @@ export default function EditGasPopover({
|
||||
onEducationClick={() => setShowEducationContent(true)}
|
||||
mode={mode}
|
||||
transaction={transaction}
|
||||
hasGasErrors={hasGasErrors}
|
||||
gasErrors={gasErrors}
|
||||
onManualChange={onManualChange}
|
||||
minimumGasLimit={minimumGasLimitDec}
|
||||
|
@ -1,35 +1,86 @@
|
||||
import React, { useContext } from 'react';
|
||||
import React, { useContext, useEffect, useState } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import classNames from 'classnames';
|
||||
|
||||
import { GAS_ESTIMATE_TYPES } from '../../../../shared/constants/gas';
|
||||
|
||||
import { useGasFeeEstimates } from '../../../hooks/useGasFeeEstimates';
|
||||
import { usePrevious } from '../../../hooks/usePrevious';
|
||||
import { I18nContext } from '../../../contexts/i18n';
|
||||
|
||||
import Typography from '../../ui/typography/typography';
|
||||
import { TYPOGRAPHY } from '../../../helpers/constants/design-system';
|
||||
import {
|
||||
TYPOGRAPHY,
|
||||
FONT_WEIGHT,
|
||||
} from '../../../helpers/constants/design-system';
|
||||
import InfoTooltip from '../../ui/info-tooltip/info-tooltip';
|
||||
|
||||
import { getGasTimeEstimate } from '../../../store/actions';
|
||||
|
||||
// Once we reach this second threshold, we switch to minutes as a unit
|
||||
const SECOND_CUTOFF = 90;
|
||||
|
||||
export default function GasTiming({ maxPriorityFeePerGas }) {
|
||||
// Shows "seconds" as unit of time if under SECOND_CUTOFF, otherwise "minutes"
|
||||
const toHumanReadableTime = (milliseconds = 1, t) => {
|
||||
const seconds = Math.ceil(milliseconds / 1000);
|
||||
if (seconds <= SECOND_CUTOFF) {
|
||||
return t('gasTimingSeconds', [seconds]);
|
||||
}
|
||||
return t('gasTimingMinutes', [Math.ceil(seconds / 60)]);
|
||||
};
|
||||
export default function GasTiming({
|
||||
maxFeePerGas = 0,
|
||||
maxPriorityFeePerGas = 0,
|
||||
}) {
|
||||
const {
|
||||
gasFeeEstimates,
|
||||
isGasEstimatesLoading,
|
||||
gasEstimateType,
|
||||
} = useGasFeeEstimates();
|
||||
|
||||
const t = useContext(I18nContext);
|
||||
const [customEstimatedTime, setCustomEstimatedTime] = useState(null);
|
||||
|
||||
// Shows "seconds" as unit of time if under SECOND_CUTOFF, otherwise "minutes"
|
||||
const toHumanReadableTime = (milliseconds = 1) => {
|
||||
const seconds = Math.ceil(milliseconds / 1000);
|
||||
if (seconds <= SECOND_CUTOFF) {
|
||||
return t('gasTimingSeconds', [seconds]);
|
||||
// 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
|
||||
// the time to show
|
||||
const isUnknownLow =
|
||||
gasFeeEstimates?.low &&
|
||||
Number(maxPriorityFeePerGas) <
|
||||
Number(gasFeeEstimates.low.suggestedMaxPriorityFeePerGas);
|
||||
|
||||
const previousMaxFeePerGas = usePrevious(maxFeePerGas);
|
||||
const previousMaxPriorityFeePerGas = usePrevious(maxPriorityFeePerGas);
|
||||
const previousIsUnknownLow = usePrevious(isUnknownLow);
|
||||
|
||||
useEffect(() => {
|
||||
const priority = maxPriorityFeePerGas;
|
||||
const fee = maxFeePerGas;
|
||||
|
||||
if (
|
||||
isUnknownLow ||
|
||||
priority !== previousMaxPriorityFeePerGas ||
|
||||
fee !== previousMaxFeePerGas
|
||||
) {
|
||||
getGasTimeEstimate(priority, fee).then((result) => {
|
||||
if (maxFeePerGas === fee && maxPriorityFeePerGas === priority) {
|
||||
setCustomEstimatedTime(result);
|
||||
}
|
||||
});
|
||||
}
|
||||
return t('gasTimingMinutes', [Math.ceil(seconds / 60)]);
|
||||
};
|
||||
|
||||
if (isUnknownLow !== false && previousIsUnknownLow === true) {
|
||||
setCustomEstimatedTime(null);
|
||||
}
|
||||
}, [
|
||||
maxPriorityFeePerGas,
|
||||
maxFeePerGas,
|
||||
isUnknownLow,
|
||||
previousMaxFeePerGas,
|
||||
previousMaxPriorityFeePerGas,
|
||||
previousIsUnknownLow,
|
||||
]);
|
||||
|
||||
const t = useContext(I18nContext);
|
||||
|
||||
// Don't show anything if we don't have enough information
|
||||
if (
|
||||
@ -39,39 +90,69 @@ export default function GasTiming({ maxPriorityFeePerGas }) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const { low, medium, high } = gasFeeEstimates;
|
||||
const { low = {}, medium = {}, high = {} } = gasFeeEstimates;
|
||||
|
||||
let text = '';
|
||||
let attitude = '';
|
||||
let attitude = 'positive';
|
||||
let fontWeight = FONT_WEIGHT.NORMAL;
|
||||
|
||||
// Anything medium or faster is positive
|
||||
if (
|
||||
Number(maxPriorityFeePerGas) >= Number(medium.suggestedMaxPriorityFeePerGas)
|
||||
) {
|
||||
attitude = 'positive';
|
||||
|
||||
// High+ is very likely, medium is likely
|
||||
if (
|
||||
Number(maxPriorityFeePerGas) < Number(high.suggestedMaxPriorityFeePerGas)
|
||||
) {
|
||||
// Medium
|
||||
text = t('gasTimingPositive', [
|
||||
toHumanReadableTime(medium.maxWaitTimeEstimate),
|
||||
toHumanReadableTime(low.maxWaitTimeEstimate, t),
|
||||
]);
|
||||
} else {
|
||||
// High
|
||||
text = t('gasTimingVeryPositive', [
|
||||
toHumanReadableTime(high.maxWaitTimeEstimate),
|
||||
toHumanReadableTime(high.minWaitTimeEstimate, t),
|
||||
]);
|
||||
}
|
||||
} else {
|
||||
attitude = 'negative';
|
||||
text = t('gasTimingNegative', [
|
||||
toHumanReadableTime(low.maxWaitTimeEstimate),
|
||||
]);
|
||||
|
||||
// If the user has chosen a value less than our low estimate,
|
||||
// calculate a potential wait time
|
||||
if (isUnknownLow) {
|
||||
// If we didn't get any useful information, show the
|
||||
// "unknown processing time" message
|
||||
if (
|
||||
!customEstimatedTime ||
|
||||
customEstimatedTime === 'unknown' ||
|
||||
customEstimatedTime?.upperTimeBound === 'unknown'
|
||||
) {
|
||||
fontWeight = FONT_WEIGHT.BOLD;
|
||||
text = (
|
||||
<>
|
||||
{t('editGasTooLow')}{' '}
|
||||
<InfoTooltip
|
||||
position="top"
|
||||
contentText={t('editGasTooLowTooltip')}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
} else {
|
||||
text = t('gasTimingNegative', [
|
||||
toHumanReadableTime(Number(customEstimatedTime?.upperTimeBound), t),
|
||||
]);
|
||||
}
|
||||
} else {
|
||||
text = t('gasTimingNegative', [
|
||||
toHumanReadableTime(low.maxWaitTimeEstimate, t),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<Typography
|
||||
variant={TYPOGRAPHY.H7}
|
||||
fontWeight={fontWeight}
|
||||
className={classNames('gas-timing', {
|
||||
[`gas-timing--${attitude}`]: attitude,
|
||||
})}
|
||||
@ -83,4 +164,5 @@ export default function GasTiming({ maxPriorityFeePerGas }) {
|
||||
|
||||
GasTiming.propTypes = {
|
||||
maxPriorityFeePerGas: PropTypes.string.isRequired,
|
||||
maxFeePerGas: PropTypes.string.isRequired,
|
||||
};
|
||||
|
@ -16,5 +16,9 @@
|
||||
.info-tooltip {
|
||||
display: inline-block;
|
||||
margin-inline-start: 4px;
|
||||
|
||||
path {
|
||||
fill: $error-1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -447,6 +447,7 @@ export default class ConfirmTransactionBase extends Component {
|
||||
subTitle={
|
||||
<GasTiming
|
||||
maxPriorityFeePerGas={txData.txParams.maxPriorityFeePerGas}
|
||||
maxFeePerGas={txData.txParams.maxFeePerGas}
|
||||
/>
|
||||
}
|
||||
/>,
|
||||
|
@ -2791,6 +2791,13 @@ export function disconnectGasFeeEstimatePoller(pollToken) {
|
||||
return promisifiedBackground.disconnectGasFeeEstimatePoller(pollToken);
|
||||
}
|
||||
|
||||
export function getGasTimeEstimate(maxPriorityFeePerGas, maxFeePerGas) {
|
||||
return promisifiedBackground.getGasTimeEstimate(
|
||||
maxPriorityFeePerGas,
|
||||
maxFeePerGas,
|
||||
);
|
||||
}
|
||||
|
||||
// MetaMetrics
|
||||
/**
|
||||
* @typedef {import('../../shared/constants/metametrics').MetaMetricsEventPayload} MetaMetricsEventPayload
|
||||
|
Loading…
x
Reference in New Issue
Block a user