1
0
mirror of https://github.com/kremalicious/metamask-extension.git synced 2024-12-23 09:52:26 +01:00

Adds insufficient gas error to edit-gas-display (#11524)

This commit is contained in:
Dan J Miller 2021-07-30 20:16:31 -02:30 committed by GitHub
parent a1f8a65519
commit f1140087b7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 122 additions and 4 deletions

View File

@ -19,6 +19,7 @@ import {
import { areDappSuggestedAndTxParamGasFeesTheSame } from '../../../helpers/utils/confirm-tx.util'; import { areDappSuggestedAndTxParamGasFeesTheSame } from '../../../helpers/utils/confirm-tx.util';
import InfoTooltip from '../../ui/info-tooltip'; import InfoTooltip from '../../ui/info-tooltip';
import ErrorMessage from '../../ui/error-message';
import TransactionTotalBanner from '../transaction-total-banner/transaction-total-banner.component'; import TransactionTotalBanner from '../transaction-total-banner/transaction-total-banner.component';
import RadioGroup from '../../ui/radio-group/radio-group.component'; import RadioGroup from '../../ui/radio-group/radio-group.component';
import AdvancedGasControls from '../advanced-gas-controls/advanced-gas-controls.component'; import AdvancedGasControls from '../advanced-gas-controls/advanced-gas-controls.component';
@ -59,6 +60,7 @@ export default function EditGasDisplay({
gasErrors, gasErrors,
onManualChange, onManualChange,
minimumGasLimit, minimumGasLimit,
balanceError,
}) { }) {
const t = useContext(I18nContext); const t = useContext(I18nContext);
@ -73,6 +75,12 @@ export default function EditGasDisplay({
); );
const networkSupports1559 = useSelector(isEIP1559Network); const networkSupports1559 = useSelector(isEIP1559Network);
const showTopError = balanceError;
let errorKey;
if (balanceError) {
errorKey = 'insufficientFunds';
}
return ( return (
<div className="edit-gas-display"> <div className="edit-gas-display">
@ -85,6 +93,11 @@ export default function EditGasDisplay({
/> />
</div> </div>
)} )}
{showTopError && (
<div className="edit-gas-display__warning">
<ErrorMessage errorKey={errorKey} />
</div>
)}
{requireDappAcknowledgement && ( {requireDappAcknowledgement && (
<div className="edit-gas-display__dapp-acknowledgement-warning"> <div className="edit-gas-display__dapp-acknowledgement-warning">
<ActionableMessage <ActionableMessage
@ -255,4 +268,5 @@ EditGasDisplay.propTypes = {
gasErrors: PropTypes.object, gasErrors: PropTypes.object,
onManualChange: PropTypes.func, onManualChange: PropTypes.func,
minimumGasLimit: PropTypes.number, minimumGasLimit: PropTypes.number,
balanceError: PropTypes.bool,
}; };

View File

@ -61,4 +61,8 @@
color: $primary-1; color: $primary-1;
} }
} }
&__warning {
margin-bottom: 24px;
}
} }

View File

@ -1,6 +1,5 @@
import React, { useCallback, useContext, useState } from 'react'; import React, { useCallback, useContext, useState } from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { useDispatch, useSelector } from 'react-redux'; import { useDispatch, useSelector } from 'react-redux';
import { useGasFeeInputs } from '../../../hooks/useGasFeeInputs'; import { useGasFeeInputs } from '../../../hooks/useGasFeeInputs';
import { useShouldAnimateGasEstimations } from '../../../hooks/useShouldAnimateGasEstimations'; import { useShouldAnimateGasEstimations } from '../../../hooks/useShouldAnimateGasEstimations';
@ -83,6 +82,7 @@ export default function EditGasPopover({
hasGasErrors, hasGasErrors,
gasErrors, gasErrors,
onManualChange, onManualChange,
balanceError,
} = useGasFeeInputs(defaultEstimateToUse, transaction, minimumGasLimit, mode); } = useGasFeeInputs(defaultEstimateToUse, transaction, minimumGasLimit, mode);
const [showAdvancedForm, setShowAdvancedForm] = useState( const [showAdvancedForm, setShowAdvancedForm] = useState(
@ -182,6 +182,7 @@ export default function EditGasPopover({
<Popover <Popover
title={title} title={title}
onClose={closePopover} onClose={closePopover}
className="edit-gas-popover__wrapper"
onBack={ onBack={
showEducationContent ? () => setShowEducationContent(false) : undefined showEducationContent ? () => setShowEducationContent(false) : undefined
} }
@ -191,7 +192,7 @@ export default function EditGasPopover({
<Button <Button
type="primary" type="primary"
onClick={onSubmit} onClick={onSubmit}
disabled={hasGasErrors || isGasEstimatesLoading} disabled={hasGasErrors || isGasEstimatesLoading || balanceError}
> >
{footerButtonText} {footerButtonText}
</Button> </Button>
@ -238,6 +239,7 @@ export default function EditGasPopover({
gasErrors={gasErrors} gasErrors={gasErrors}
onManualChange={onManualChange} onManualChange={onManualChange}
minimumGasLimit={minimumGasLimitDec} minimumGasLimit={minimumGasLimitDec}
balanceError={balanceError}
{...editGasDisplayProps} {...editGasDisplayProps}
/> />
</> </>

View File

@ -0,0 +1,7 @@
.edit-gas-popover {
&__wrapper {
@media screen and (min-width: 576px) {
max-height: 84vh;
}
}
}

View File

@ -11,6 +11,7 @@ import {
import { import {
multiplyCurrencies, multiplyCurrencies,
conversionLessThan, conversionLessThan,
conversionGreaterThan,
} from '../../shared/modules/conversion.utils'; } from '../../shared/modules/conversion.utils';
import { import {
getMaximumGasTotalInHexWei, getMaximumGasTotalInHexWei,
@ -22,9 +23,14 @@ import {
decGWEIToHexWEI, decGWEIToHexWEI,
decimalToHex, decimalToHex,
hexToDecimal, hexToDecimal,
addHexes,
} from '../helpers/utils/conversions.util'; } from '../helpers/utils/conversions.util';
import { getShouldShowFiat } from '../selectors';
import { GAS_FORM_ERRORS } from '../helpers/constants/gas'; import { GAS_FORM_ERRORS } from '../helpers/constants/gas';
import {
getShouldShowFiat,
getSelectedAccount,
txDataSelector,
} from '../selectors';
import { useCurrencyDisplay } from './useCurrencyDisplay'; import { useCurrencyDisplay } from './useCurrencyDisplay';
import { useGasFeeEstimates } from './useGasFeeEstimates'; import { useGasFeeEstimates } from './useGasFeeEstimates';
import { useUserPreferencedCurrency } from './useUserPreferencedCurrency'; import { useUserPreferencedCurrency } from './useUserPreferencedCurrency';
@ -165,6 +171,9 @@ export function useGasFeeInputs(
minimumGasLimit, minimumGasLimit,
editGasMode, editGasMode,
) { ) {
const { balance: ethBalance } = useSelector(getSelectedAccount);
const txData = useSelector(txDataSelector);
// We need to know whether to show fiat conversions or not, so that we can // We need to know whether to show fiat conversions or not, so that we can
// default our fiat values to empty strings if showing fiat is not wanted or // default our fiat values to empty strings if showing fiat is not wanted or
// possible. // possible.
@ -413,6 +422,16 @@ export function useGasFeeInputs(
...gasWarnings, ...gasWarnings,
}; };
const minimumTxCostInHexWei = addHexes(
minimumCostInHexWei,
txData?.txParams?.value,
);
const balanceError = conversionGreaterThan(
{ value: minimumTxCostInHexWei, fromNumericBase: 'hex' },
{ value: ethBalance, fromNumericBase: 'hex' },
);
return { return {
maxFeePerGas: maxFeePerGasToUse, maxFeePerGas: maxFeePerGasToUse,
maxFeePerGasFiat: showFiat ? maxFeePerGasFiat : '', maxFeePerGasFiat: showFiat ? maxFeePerGasFiat : '',
@ -443,5 +462,6 @@ export function useGasFeeInputs(
setMaxFeePerGas(maxFeePerGasToUse); setMaxFeePerGas(maxFeePerGasToUse);
setMaxPriorityFeePerGas(maxPriorityFeePerGasToUse); setMaxPriorityFeePerGas(maxPriorityFeePerGasToUse);
}, },
balanceError,
}; };
} }

View File

@ -7,7 +7,12 @@ import {
getNativeCurrency, getNativeCurrency,
} from '../ducks/metamask/metamask'; } from '../ducks/metamask/metamask';
import { ETH, PRIMARY } from '../helpers/constants/common'; import { ETH, PRIMARY } from '../helpers/constants/common';
import { getCurrentCurrency, getShouldShowFiat } from '../selectors'; import {
getCurrentCurrency,
getShouldShowFiat,
txDataSelector,
getSelectedAccount,
} from '../selectors';
import { useGasFeeEstimates } from './useGasFeeEstimates'; import { useGasFeeEstimates } from './useGasFeeEstimates';
import { useGasFeeInputs } from './useGasFeeInputs'; import { useGasFeeInputs } from './useGasFeeInputs';
import { useUserPreferencedCurrency } from './useUserPreferencedCurrency'; import { useUserPreferencedCurrency } from './useUserPreferencedCurrency';
@ -71,6 +76,32 @@ const FEE_MARKET_ESTIMATE_RETURN_VALUE = {
estimatedGasFeeTimeBounds: {}, estimatedGasFeeTimeBounds: {},
}; };
const HIGH_FEE_MARKET_ESTIMATE_RETURN_VALUE = {
gasEstimateType: GAS_ESTIMATE_TYPES.FEE_MARKET,
gasFeeEstimates: {
low: {
minWaitTimeEstimate: 180000,
maxWaitTimeEstimate: 300000,
suggestedMaxPriorityFeePerGas: '3',
suggestedMaxFeePerGas: '53000',
},
medium: {
minWaitTimeEstimate: 15000,
maxWaitTimeEstimate: 60000,
suggestedMaxPriorityFeePerGas: '7',
suggestedMaxFeePerGas: '70000',
},
high: {
minWaitTimeEstimate: 0,
maxWaitTimeEstimate: 15000,
suggestedMaxPriorityFeePerGas: '10',
suggestedMaxFeePerGas: '100000',
},
estimatedBaseFee: '50000',
},
estimatedGasFeeTimeBounds: {},
};
const generateUseSelectorRouter = () => (selector) => { const generateUseSelectorRouter = () => (selector) => {
if (selector === getConversionRate) { if (selector === getConversionRate) {
return MOCK_ETH_USD_CONVERSION_RATE; return MOCK_ETH_USD_CONVERSION_RATE;
@ -84,6 +115,18 @@ const generateUseSelectorRouter = () => (selector) => {
if (selector === getShouldShowFiat) { if (selector === getShouldShowFiat) {
return true; return true;
} }
if (selector === txDataSelector) {
return {
txParams: {
value: '0x5555',
},
};
}
if (selector === getSelectedAccount) {
return {
balance: '0x440aa47cc2556',
};
}
return undefined; return undefined;
}; };
@ -234,4 +277,32 @@ describe('useGasFeeInputs', () => {
// expect(result.current.estimatedMinimumFiat).toBe(`$${totalMaxFiat}`); // expect(result.current.estimatedMinimumFiat).toBe(`$${totalMaxFiat}`);
}); });
}); });
describe('when balance is sufficient for minimum transaction cost', () => {
beforeEach(() => {
useGasFeeEstimates.mockImplementation(
() => FEE_MARKET_ESTIMATE_RETURN_VALUE,
);
useSelector.mockImplementation(generateUseSelectorRouter());
});
it('should return false', () => {
const { result } = renderHook(() => useGasFeeInputs());
expect(result.current.balanceError).toBe(false);
});
});
describe('when balance is insufficient for minimum transaction cost', () => {
beforeEach(() => {
useGasFeeEstimates.mockImplementation(
() => HIGH_FEE_MARKET_ESTIMATE_RETURN_VALUE,
);
useSelector.mockImplementation(generateUseSelectorRouter());
});
it('should return true', () => {
const { result } = renderHook(() => useGasFeeInputs());
expect(result.current.balanceError).toBe(true);
});
});
}); });