1
0
mirror of https://github.com/kremalicious/metamask-extension.git synced 2024-12-23 09:52:26 +01:00
metamask-extension/ui/components/app/edit-gas-display/edit-gas-display.component.js
Brad Decker e0953d9f68
Update send and confirm state management, and tx controller gas defaults, for EIP1559 (#11549)
wip

Documentation improvements for send slice support of EIP1559

Remove console.log in send duck

Property lookup safety improvement in selectors/confirm-transaction

Add code accidentally removed in rebase

Update addTxGasDefaults and _getDefaultGasFees to work with new estimate types, and ensure we correctly handle gas price estimates when on EIP1559 networks (#11615)

* Fix typo

Remove console.log in send duck

* Update addTxGasDefaults and _getDefaultGasFees to work correctly with all new gas fee estimate types

* Don't show gas timing support when not on eip1559 compatible network

* Hide gas timing component on transaction screen when on a non-1559 network

* Improve comments, tests and edge case handling

* Ensure eip1559 fees are applied and updated correctly when eip1559 estimate api fails

* Lint fix

Co-authored-by: Brad Decker <git@braddecker.dev>

Remove console.log

Handle possible gasEstimateType undefined

Remove unnecessary nonce field position change in confirm-page-container-content__details
2021-07-30 22:15:18 -02:30

275 lines
8.8 KiB
JavaScript

import React, { useContext } from 'react';
import { useSelector } from 'react-redux';
import PropTypes from 'prop-types';
import {
GAS_RECOMMENDATIONS,
EDIT_GAS_MODES,
} from '../../../../shared/constants/gas';
import Button from '../../ui/button';
import Typography from '../../ui/typography/typography';
import { isEIP1559Network } from '../../../ducks/metamask/metamask';
import {
COLORS,
TYPOGRAPHY,
FONT_WEIGHT,
} from '../../../helpers/constants/design-system';
import { areDappSuggestedAndTxParamGasFeesTheSame } from '../../../helpers/utils/confirm-tx.util';
import InfoTooltip from '../../ui/info-tooltip';
import ErrorMessage from '../../ui/error-message';
import TransactionTotalBanner from '../transaction-total-banner/transaction-total-banner.component';
import RadioGroup from '../../ui/radio-group/radio-group.component';
import AdvancedGasControls from '../advanced-gas-controls/advanced-gas-controls.component';
import ActionableMessage from '../../ui/actionable-message/actionable-message';
import { I18nContext } from '../../../contexts/i18n';
import GasTiming from '../gas-timing';
export default function EditGasDisplay({
mode = EDIT_GAS_MODES.MODIFY_IN_PLACE,
showEducationButton = false,
onEducationClick,
transaction,
defaultEstimateToUse,
maxPriorityFeePerGas,
setMaxPriorityFeePerGas,
maxPriorityFeePerGasFiat,
maxFeePerGas,
setMaxFeePerGas,
maxFeePerGasFiat,
estimatedMaximumNative,
isGasEstimatesLoading,
gasFeeEstimates,
gasEstimateType,
gasPrice,
setGasPrice,
gasLimit,
setGasLimit,
estimateToUse,
setEstimateToUse,
estimatedMinimumFiat,
estimatedMaximumFiat,
dappSuggestedGasFeeAcknowledged,
setDappSuggestedGasFeeAcknowledged,
showAdvancedForm,
setShowAdvancedForm,
warning,
gasErrors,
onManualChange,
minimumGasLimit,
balanceError,
}) {
const t = useContext(I18nContext);
const supportsEIP1559 = useSelector(isEIP1559Network);
const dappSuggestedAndTxParamGasFeesAreTheSame = areDappSuggestedAndTxParamGasFeesTheSame(
transaction,
);
const requireDappAcknowledgement = Boolean(
transaction?.dappSuggestedGasFees &&
!dappSuggestedGasFeeAcknowledged &&
dappSuggestedAndTxParamGasFeesAreTheSame,
);
const networkSupports1559 = useSelector(isEIP1559Network);
const showTopError = balanceError;
let errorKey;
if (balanceError) {
errorKey = 'insufficientFunds';
}
return (
<div className="edit-gas-display">
<div className="edit-gas-display__content">
{warning && (
<div className="edit-gas-display__warning">
<ActionableMessage
className="actionable-message--warning"
message={warning}
/>
</div>
)}
{showTopError && (
<div className="edit-gas-display__warning">
<ErrorMessage errorKey={errorKey} />
</div>
)}
{requireDappAcknowledgement && (
<div className="edit-gas-display__dapp-acknowledgement-warning">
<ActionableMessage
className="actionable-message--warning"
message={t('gasDisplayDappWarning', [transaction.origin])}
iconFillColor="#f8c000"
useIcon
/>
</div>
)}
{mode === EDIT_GAS_MODES.SPEED_UP && (
<div className="edit-gas-display__top-tooltip">
<Typography
color={COLORS.BLACK}
variant={TYPOGRAPHY.H8}
fontWeight={FONT_WEIGHT.BOLD}
>
{t('speedUpTooltipText')}{' '}
<InfoTooltip
position="top"
contentText={t('speedUpExplanation')}
/>
</Typography>
</div>
)}
<TransactionTotalBanner
total={
networkSupports1559
? `~ ${estimatedMinimumFiat}`
: estimatedMaximumNative
}
detail={
networkSupports1559 &&
estimatedMaximumFiat !== undefined &&
t('editGasTotalBannerSubtitle', [
<Typography
fontWeight={FONT_WEIGHT.BOLD}
tag="span"
key="secondary"
>
{estimatedMaximumFiat}
</Typography>,
<Typography tag="span" key="primary">
{estimatedMaximumNative}
</Typography>,
])
}
timing={
<GasTiming
maxFeePerGas={maxFeePerGas}
maxPriorityFeePerGas={maxPriorityFeePerGas}
/>
}
/>
{requireDappAcknowledgement && (
<Button
className="edit-gas-display__dapp-acknowledgement-button"
onClick={() => setDappSuggestedGasFeeAcknowledged(true)}
>
{t('gasDisplayAcknowledgeDappButtonText')}
</Button>
)}
{networkSupports1559 &&
!requireDappAcknowledgement &&
![EDIT_GAS_MODES.SPEED_UP, EDIT_GAS_MODES.CANCEL].includes(mode) && (
<RadioGroup
name="gas-recommendation"
options={[
{
value: GAS_RECOMMENDATIONS.LOW,
label: t('editGasLow'),
recommended: defaultEstimateToUse === GAS_RECOMMENDATIONS.LOW,
},
{
value: GAS_RECOMMENDATIONS.MEDIUM,
label: t('editGasMedium'),
recommended:
defaultEstimateToUse === GAS_RECOMMENDATIONS.MEDIUM,
},
{
value: GAS_RECOMMENDATIONS.HIGH,
label: t('editGasHigh'),
recommended:
defaultEstimateToUse === GAS_RECOMMENDATIONS.HIGH,
},
]}
selectedValue={estimateToUse}
onChange={setEstimateToUse}
/>
)}
{!requireDappAcknowledgement && (
<button
className="edit-gas-display__advanced-button"
onClick={() => setShowAdvancedForm(!showAdvancedForm)}
>
{t('advancedOptions')}{' '}
{showAdvancedForm ? (
<i className="fa fa-caret-up"></i>
) : (
<i className="fa fa-caret-down"></i>
)}
</button>
)}
{!requireDappAcknowledgement && showAdvancedForm && (
<AdvancedGasControls
gasFeeEstimates={gasFeeEstimates}
gasEstimateType={gasEstimateType}
estimateToUse={estimateToUse}
isGasEstimatesLoading={isGasEstimatesLoading}
gasLimit={gasLimit}
setGasLimit={setGasLimit}
maxPriorityFee={maxPriorityFeePerGas}
setMaxPriorityFee={setMaxPriorityFeePerGas}
maxFee={maxFeePerGas}
setMaxFee={setMaxFeePerGas}
gasPrice={gasPrice}
setGasPrice={setGasPrice}
maxPriorityFeeFiat={maxPriorityFeePerGasFiat}
maxFeeFiat={maxFeePerGasFiat}
gasErrors={gasErrors}
onManualChange={onManualChange}
minimumGasLimit={minimumGasLimit}
networkSupportsEIP1559={supportsEIP1559}
/>
)}
</div>
{networkSupports1559 &&
!requireDappAcknowledgement &&
showEducationButton && (
<div className="edit-gas-display__education">
<button onClick={onEducationClick}>
{t('editGasEducationButtonText')}
</button>
</div>
)}
</div>
);
}
EditGasDisplay.propTypes = {
mode: PropTypes.oneOf(Object.values(EDIT_GAS_MODES)),
showEducationButton: PropTypes.bool,
onEducationClick: PropTypes.func,
defaultEstimateToUse: PropTypes.oneOf(Object.values(GAS_RECOMMENDATIONS)),
maxPriorityFeePerGas: PropTypes.string,
setMaxPriorityFeePerGas: PropTypes.func,
maxPriorityFeePerGasFiat: PropTypes.string,
maxFeePerGas: PropTypes.string,
setMaxFeePerGas: PropTypes.func,
maxFeePerGasFiat: PropTypes.string,
estimatedMaximumNative: PropTypes.string,
isGasEstimatesLoading: PropTypes.boolean,
gasFeeEstimates: PropTypes.object,
gasEstimateType: PropTypes.string,
gasPrice: PropTypes.string,
setGasPrice: PropTypes.func,
gasLimit: PropTypes.number,
setGasLimit: PropTypes.func,
estimateToUse: PropTypes.string,
setEstimateToUse: PropTypes.func,
estimatedMinimumFiat: PropTypes.string,
estimatedMaximumFiat: PropTypes.string,
dappSuggestedGasFeeAcknowledged: PropTypes.boolean,
setDappSuggestedGasFeeAcknowledged: PropTypes.func,
showAdvancedForm: PropTypes.bool,
setShowAdvancedForm: PropTypes.func,
warning: PropTypes.string,
transaction: PropTypes.object,
gasErrors: PropTypes.object,
onManualChange: PropTypes.func,
minimumGasLimit: PropTypes.number,
balanceError: PropTypes.bool,
};