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.disconnectPoller,
|
||||||
this.gasFeeController,
|
this.gasFeeController,
|
||||||
),
|
),
|
||||||
|
|
||||||
|
getGasFeeTimeEstimate: nodeify(
|
||||||
|
this.gasFeeController.getTimeEstimate,
|
||||||
|
this.gasFeeController,
|
||||||
|
),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,7 +15,6 @@ import {
|
|||||||
COLORS,
|
COLORS,
|
||||||
TYPOGRAPHY,
|
TYPOGRAPHY,
|
||||||
FONT_WEIGHT,
|
FONT_WEIGHT,
|
||||||
TEXT_ALIGN,
|
|
||||||
} from '../../../helpers/constants/design-system';
|
} from '../../../helpers/constants/design-system';
|
||||||
import { areDappSuggestedAndTxParamGasFeesTheSame } from '../../../helpers/utils/confirm-tx.util';
|
import { areDappSuggestedAndTxParamGasFeesTheSame } from '../../../helpers/utils/confirm-tx.util';
|
||||||
|
|
||||||
@ -52,7 +51,6 @@ export default function EditGasDisplay({
|
|||||||
setEstimateToUse,
|
setEstimateToUse,
|
||||||
estimatedMinimumFiat,
|
estimatedMinimumFiat,
|
||||||
estimatedMaximumFiat,
|
estimatedMaximumFiat,
|
||||||
hasGasErrors,
|
|
||||||
dappSuggestedGasFeeAcknowledged,
|
dappSuggestedGasFeeAcknowledged,
|
||||||
setDappSuggestedGasFeeAcknowledged,
|
setDappSuggestedGasFeeAcknowledged,
|
||||||
showAdvancedForm,
|
showAdvancedForm,
|
||||||
@ -134,7 +132,12 @@ export default function EditGasDisplay({
|
|||||||
</Typography>,
|
</Typography>,
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
timing={<GasTiming maxPriorityFeePerGas={maxPriorityFeePerGas} />}
|
timing={
|
||||||
|
<GasTiming
|
||||||
|
maxFeePerGas={maxFeePerGas}
|
||||||
|
maxPriorityFeePerGas={maxPriorityFeePerGas}
|
||||||
|
/>
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
{requireDappAcknowledgement && (
|
{requireDappAcknowledgement && (
|
||||||
<Button
|
<Button
|
||||||
@ -144,22 +147,6 @@ export default function EditGasDisplay({
|
|||||||
{t('gasDisplayAcknowledgeDappButtonText')}
|
{t('gasDisplayAcknowledgeDappButtonText')}
|
||||||
</Button>
|
</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 &&
|
{networkSupports1559 &&
|
||||||
!requireDappAcknowledgement &&
|
!requireDappAcknowledgement &&
|
||||||
![EDIT_GAS_MODES.SPEED_UP, EDIT_GAS_MODES.CANCEL].includes(mode) && (
|
![EDIT_GAS_MODES.SPEED_UP, EDIT_GAS_MODES.CANCEL].includes(mode) && (
|
||||||
@ -259,7 +246,6 @@ EditGasDisplay.propTypes = {
|
|||||||
setEstimateToUse: PropTypes.func,
|
setEstimateToUse: PropTypes.func,
|
||||||
estimatedMinimumFiat: PropTypes.string,
|
estimatedMinimumFiat: PropTypes.string,
|
||||||
estimatedMaximumFiat: PropTypes.string,
|
estimatedMaximumFiat: PropTypes.string,
|
||||||
hasGasErrors: PropTypes.boolean,
|
|
||||||
dappSuggestedGasFeeAcknowledged: PropTypes.boolean,
|
dappSuggestedGasFeeAcknowledged: PropTypes.boolean,
|
||||||
setDappSuggestedGasFeeAcknowledged: PropTypes.func,
|
setDappSuggestedGasFeeAcknowledged: PropTypes.func,
|
||||||
showAdvancedForm: PropTypes.bool,
|
showAdvancedForm: PropTypes.bool,
|
||||||
|
@ -21,14 +21,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&__error .info-tooltip {
|
|
||||||
display: inline-block;
|
|
||||||
|
|
||||||
path {
|
|
||||||
fill: $error-1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&__dapp-acknowledgement-warning {
|
&__dapp-acknowledgement-warning {
|
||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
}
|
}
|
||||||
|
@ -235,7 +235,6 @@ export default function EditGasPopover({
|
|||||||
onEducationClick={() => setShowEducationContent(true)}
|
onEducationClick={() => setShowEducationContent(true)}
|
||||||
mode={mode}
|
mode={mode}
|
||||||
transaction={transaction}
|
transaction={transaction}
|
||||||
hasGasErrors={hasGasErrors}
|
|
||||||
gasErrors={gasErrors}
|
gasErrors={gasErrors}
|
||||||
onManualChange={onManualChange}
|
onManualChange={onManualChange}
|
||||||
minimumGasLimit={minimumGasLimitDec}
|
minimumGasLimit={minimumGasLimitDec}
|
||||||
|
@ -1,35 +1,86 @@
|
|||||||
import React, { useContext } from 'react';
|
import React, { useContext, useEffect, useState } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
|
|
||||||
import { GAS_ESTIMATE_TYPES } from '../../../../shared/constants/gas';
|
import { GAS_ESTIMATE_TYPES } from '../../../../shared/constants/gas';
|
||||||
|
|
||||||
import { useGasFeeEstimates } from '../../../hooks/useGasFeeEstimates';
|
import { useGasFeeEstimates } from '../../../hooks/useGasFeeEstimates';
|
||||||
|
import { usePrevious } from '../../../hooks/usePrevious';
|
||||||
import { I18nContext } from '../../../contexts/i18n';
|
import { I18nContext } from '../../../contexts/i18n';
|
||||||
|
|
||||||
import Typography from '../../ui/typography/typography';
|
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
|
// Once we reach this second threshold, we switch to minutes as a unit
|
||||||
const SECOND_CUTOFF = 90;
|
const SECOND_CUTOFF = 90;
|
||||||
|
|
||||||
export default function GasTiming({ maxPriorityFeePerGas }) {
|
|
||||||
const {
|
|
||||||
gasFeeEstimates,
|
|
||||||
isGasEstimatesLoading,
|
|
||||||
gasEstimateType,
|
|
||||||
} = useGasFeeEstimates();
|
|
||||||
|
|
||||||
const t = useContext(I18nContext);
|
|
||||||
|
|
||||||
// Shows "seconds" as unit of time if under SECOND_CUTOFF, otherwise "minutes"
|
// Shows "seconds" as unit of time if under SECOND_CUTOFF, otherwise "minutes"
|
||||||
const toHumanReadableTime = (milliseconds = 1) => {
|
const toHumanReadableTime = (milliseconds = 1, t) => {
|
||||||
const seconds = Math.ceil(milliseconds / 1000);
|
const seconds = Math.ceil(milliseconds / 1000);
|
||||||
if (seconds <= SECOND_CUTOFF) {
|
if (seconds <= SECOND_CUTOFF) {
|
||||||
return t('gasTimingSeconds', [seconds]);
|
return t('gasTimingSeconds', [seconds]);
|
||||||
}
|
}
|
||||||
return t('gasTimingMinutes', [Math.ceil(seconds / 60)]);
|
return t('gasTimingMinutes', [Math.ceil(seconds / 60)]);
|
||||||
};
|
};
|
||||||
|
export default function GasTiming({
|
||||||
|
maxFeePerGas = 0,
|
||||||
|
maxPriorityFeePerGas = 0,
|
||||||
|
}) {
|
||||||
|
const {
|
||||||
|
gasFeeEstimates,
|
||||||
|
isGasEstimatesLoading,
|
||||||
|
gasEstimateType,
|
||||||
|
} = useGasFeeEstimates();
|
||||||
|
|
||||||
|
const [customEstimatedTime, setCustomEstimatedTime] = useState(null);
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
// Don't show anything if we don't have enough information
|
||||||
if (
|
if (
|
||||||
@ -39,39 +90,69 @@ export default function GasTiming({ maxPriorityFeePerGas }) {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { low, medium, high } = gasFeeEstimates;
|
const { low = {}, medium = {}, high = {} } = gasFeeEstimates;
|
||||||
|
|
||||||
let text = '';
|
let text = '';
|
||||||
let attitude = '';
|
let attitude = 'positive';
|
||||||
|
let fontWeight = FONT_WEIGHT.NORMAL;
|
||||||
|
|
||||||
// Anything medium or faster is positive
|
// Anything medium or faster is positive
|
||||||
if (
|
if (
|
||||||
Number(maxPriorityFeePerGas) >= Number(medium.suggestedMaxPriorityFeePerGas)
|
Number(maxPriorityFeePerGas) >= Number(medium.suggestedMaxPriorityFeePerGas)
|
||||||
) {
|
) {
|
||||||
attitude = 'positive';
|
|
||||||
|
|
||||||
// High+ is very likely, medium is likely
|
// High+ is very likely, medium is likely
|
||||||
if (
|
if (
|
||||||
Number(maxPriorityFeePerGas) < Number(high.suggestedMaxPriorityFeePerGas)
|
Number(maxPriorityFeePerGas) < Number(high.suggestedMaxPriorityFeePerGas)
|
||||||
) {
|
) {
|
||||||
|
// Medium
|
||||||
text = t('gasTimingPositive', [
|
text = t('gasTimingPositive', [
|
||||||
toHumanReadableTime(medium.maxWaitTimeEstimate),
|
toHumanReadableTime(low.maxWaitTimeEstimate, t),
|
||||||
]);
|
]);
|
||||||
} else {
|
} else {
|
||||||
|
// High
|
||||||
text = t('gasTimingVeryPositive', [
|
text = t('gasTimingVeryPositive', [
|
||||||
toHumanReadableTime(high.maxWaitTimeEstimate),
|
toHumanReadableTime(high.minWaitTimeEstimate, t),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
attitude = 'negative';
|
attitude = 'negative';
|
||||||
|
|
||||||
|
// 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', [
|
text = t('gasTimingNegative', [
|
||||||
toHumanReadableTime(low.maxWaitTimeEstimate),
|
toHumanReadableTime(Number(customEstimatedTime?.upperTimeBound), t),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
text = t('gasTimingNegative', [
|
||||||
|
toHumanReadableTime(low.maxWaitTimeEstimate, t),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Typography
|
<Typography
|
||||||
variant={TYPOGRAPHY.H7}
|
variant={TYPOGRAPHY.H7}
|
||||||
|
fontWeight={fontWeight}
|
||||||
className={classNames('gas-timing', {
|
className={classNames('gas-timing', {
|
||||||
[`gas-timing--${attitude}`]: attitude,
|
[`gas-timing--${attitude}`]: attitude,
|
||||||
})}
|
})}
|
||||||
@ -83,4 +164,5 @@ export default function GasTiming({ maxPriorityFeePerGas }) {
|
|||||||
|
|
||||||
GasTiming.propTypes = {
|
GasTiming.propTypes = {
|
||||||
maxPriorityFeePerGas: PropTypes.string.isRequired,
|
maxPriorityFeePerGas: PropTypes.string.isRequired,
|
||||||
|
maxFeePerGas: PropTypes.string.isRequired,
|
||||||
};
|
};
|
||||||
|
@ -16,5 +16,9 @@
|
|||||||
.info-tooltip {
|
.info-tooltip {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
margin-inline-start: 4px;
|
margin-inline-start: 4px;
|
||||||
|
|
||||||
|
path {
|
||||||
|
fill: $error-1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -447,6 +447,7 @@ export default class ConfirmTransactionBase extends Component {
|
|||||||
subTitle={
|
subTitle={
|
||||||
<GasTiming
|
<GasTiming
|
||||||
maxPriorityFeePerGas={txData.txParams.maxPriorityFeePerGas}
|
maxPriorityFeePerGas={txData.txParams.maxPriorityFeePerGas}
|
||||||
|
maxFeePerGas={txData.txParams.maxFeePerGas}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
/>,
|
/>,
|
||||||
|
@ -2791,6 +2791,13 @@ export function disconnectGasFeeEstimatePoller(pollToken) {
|
|||||||
return promisifiedBackground.disconnectGasFeeEstimatePoller(pollToken);
|
return promisifiedBackground.disconnectGasFeeEstimatePoller(pollToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getGasTimeEstimate(maxPriorityFeePerGas, maxFeePerGas) {
|
||||||
|
return promisifiedBackground.getGasTimeEstimate(
|
||||||
|
maxPriorityFeePerGas,
|
||||||
|
maxFeePerGas,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// MetaMetrics
|
// MetaMetrics
|
||||||
/**
|
/**
|
||||||
* @typedef {import('../../shared/constants/metametrics').MetaMetricsEventPayload} MetaMetricsEventPayload
|
* @typedef {import('../../shared/constants/metametrics').MetaMetricsEventPayload} MetaMetricsEventPayload
|
||||||
|
Loading…
x
Reference in New Issue
Block a user