import React, { Component } from 'react'; import PropTypes from 'prop-types'; import classnames from 'classnames'; import { debounce } from 'lodash'; import Tooltip from '../../../ui/tooltip'; export default class AdvancedGasInputs extends Component { static contextTypes = { t: PropTypes.func, }; static propTypes = { updateCustomGasPrice: PropTypes.func, updateCustomGasLimit: PropTypes.func, customGasPrice: PropTypes.number.isRequired, customGasLimit: PropTypes.number.isRequired, insufficientBalance: PropTypes.bool, customPriceIsSafe: PropTypes.bool, isSpeedUp: PropTypes.bool, customGasLimitMessage: PropTypes.string, minimumGasLimit: PropTypes.number, customPriceIsExcessive: PropTypes.bool, networkSupportsSettingGasFees: PropTypes.bool, }; static defaultProps = { customPriceIsExcessive: false, networkSupportsSettingGasFees: true, }; constructor(props) { super(props); this.state = { gasPrice: this.props.customGasPrice, gasLimit: this.props.customGasLimit, }; this.changeGasPrice = debounce(this.changeGasPrice, 500); this.changeGasLimit = debounce(this.changeGasLimit, 500); } componentDidUpdate(prevProps) { const { customGasPrice: prevCustomGasPrice, customGasLimit: prevCustomGasLimit, } = prevProps; const { customGasPrice, customGasLimit } = this.props; const { gasPrice, gasLimit } = this.state; if (customGasPrice !== prevCustomGasPrice && customGasPrice !== gasPrice) { this.setState({ gasPrice: customGasPrice }); } if (customGasLimit !== prevCustomGasLimit && customGasLimit !== gasLimit) { this.setState({ gasLimit: customGasLimit }); } } onChangeGasLimit = (e) => { this.setState({ gasLimit: e.target.value }); this.changeGasLimit({ target: { value: e.target.value } }); }; changeGasLimit = (e) => { this.props.updateCustomGasLimit(Number(e.target.value)); }; onChangeGasPrice = (e) => { this.setState({ gasPrice: e.target.value }); this.changeGasPrice({ target: { value: e.target.value } }); }; changeGasPrice = (e) => { this.props.updateCustomGasPrice(Number(e.target.value)); }; gasPriceError({ insufficientBalance, customPriceIsSafe, isSpeedUp, gasPrice, customPriceIsExcessive, }) { const { t } = this.context; if (insufficientBalance) { return { errorText: t('insufficientBalance'), errorType: 'error', }; } else if (isSpeedUp && gasPrice === 0) { return { errorText: t('zeroGasPriceOnSpeedUpError'), errorType: 'error', }; } else if (!customPriceIsSafe) { return { errorText: t('gasPriceExtremelyLow'), errorType: 'warning', }; } else if (customPriceIsExcessive) { return { errorText: t('gasPriceExcessiveInput'), errorType: 'error', }; } return {}; } gasLimitError({ insufficientBalance, gasLimit, minimumGasLimit }) { const { t } = this.context; if (insufficientBalance) { return { errorText: t('insufficientBalance'), errorType: 'error', }; } else if (gasLimit < minimumGasLimit) { return { errorText: t('gasLimitTooLowWithDynamicFee', [minimumGasLimit]), errorType: 'error', }; } return {}; } renderGasInput({ value, onChange, errorComponent, errorType, label, testId, customMessageComponent, tooltipTitle, disabled, }) { return (
{label}
!disabled && onChange({ target: { value: value + 1 } }) } >
!disabled && onChange({ target: { value: Math.max(value - 1, 0) } }) } >
{errorComponent || customMessageComponent}
); } render() { const { insufficientBalance, customPriceIsSafe, isSpeedUp, customGasLimitMessage, minimumGasLimit, customPriceIsExcessive, networkSupportsSettingGasFees, } = this.props; const { gasPrice, gasLimit } = this.state; if (!networkSupportsSettingGasFees) { return null; } const { errorText: gasPriceErrorText, errorType: gasPriceErrorType } = this.gasPriceError({ insufficientBalance, customPriceIsSafe, isSpeedUp, gasPrice, customPriceIsExcessive, }); const gasPriceErrorComponent = gasPriceErrorType ? (
{gasPriceErrorText}
) : null; const { errorText: gasLimitErrorText, errorType: gasLimitErrorType } = this.gasLimitError({ insufficientBalance, gasLimit, minimumGasLimit }); const gasLimitErrorComponent = gasLimitErrorType ? (
{gasLimitErrorText}
) : null; const gasLimitCustomMessageComponent = customGasLimitMessage ? (
{customGasLimitMessage}
) : null; return (
{this.renderGasInput({ label: this.context.t('gasPrice'), testId: 'gas-price', tooltipTitle: this.context.t('gasPriceInfoTooltipContent'), value: this.state.gasPrice, onChange: this.onChangeGasPrice, errorComponent: gasPriceErrorComponent, errorType: gasPriceErrorType, disabled: !networkSupportsSettingGasFees, })} {this.renderGasInput({ label: this.context.t('gasLimit'), testId: 'gas-limit', tooltipTitle: this.context.t('gasLimitInfoTooltipContent'), value: this.state.gasLimit, onChange: this.onChangeGasLimit, errorComponent: gasLimitErrorComponent, customMessageComponent: gasLimitCustomMessageComponent, errorType: gasLimitErrorType, disabled: !networkSupportsSettingGasFees, })}
); } }