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:
parent
a1f8a65519
commit
f1140087b7
@ -19,6 +19,7 @@ import {
|
||||
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';
|
||||
@ -59,6 +60,7 @@ export default function EditGasDisplay({
|
||||
gasErrors,
|
||||
onManualChange,
|
||||
minimumGasLimit,
|
||||
balanceError,
|
||||
}) {
|
||||
const t = useContext(I18nContext);
|
||||
|
||||
@ -73,6 +75,12 @@ export default function EditGasDisplay({
|
||||
);
|
||||
|
||||
const networkSupports1559 = useSelector(isEIP1559Network);
|
||||
const showTopError = balanceError;
|
||||
|
||||
let errorKey;
|
||||
if (balanceError) {
|
||||
errorKey = 'insufficientFunds';
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="edit-gas-display">
|
||||
@ -85,6 +93,11 @@ export default function EditGasDisplay({
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
{showTopError && (
|
||||
<div className="edit-gas-display__warning">
|
||||
<ErrorMessage errorKey={errorKey} />
|
||||
</div>
|
||||
)}
|
||||
{requireDappAcknowledgement && (
|
||||
<div className="edit-gas-display__dapp-acknowledgement-warning">
|
||||
<ActionableMessage
|
||||
@ -255,4 +268,5 @@ EditGasDisplay.propTypes = {
|
||||
gasErrors: PropTypes.object,
|
||||
onManualChange: PropTypes.func,
|
||||
minimumGasLimit: PropTypes.number,
|
||||
balanceError: PropTypes.bool,
|
||||
};
|
||||
|
@ -61,4 +61,8 @@
|
||||
color: $primary-1;
|
||||
}
|
||||
}
|
||||
|
||||
&__warning {
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,5 @@
|
||||
import React, { useCallback, useContext, useState } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
import { useGasFeeInputs } from '../../../hooks/useGasFeeInputs';
|
||||
import { useShouldAnimateGasEstimations } from '../../../hooks/useShouldAnimateGasEstimations';
|
||||
@ -83,6 +82,7 @@ export default function EditGasPopover({
|
||||
hasGasErrors,
|
||||
gasErrors,
|
||||
onManualChange,
|
||||
balanceError,
|
||||
} = useGasFeeInputs(defaultEstimateToUse, transaction, minimumGasLimit, mode);
|
||||
|
||||
const [showAdvancedForm, setShowAdvancedForm] = useState(
|
||||
@ -182,6 +182,7 @@ export default function EditGasPopover({
|
||||
<Popover
|
||||
title={title}
|
||||
onClose={closePopover}
|
||||
className="edit-gas-popover__wrapper"
|
||||
onBack={
|
||||
showEducationContent ? () => setShowEducationContent(false) : undefined
|
||||
}
|
||||
@ -191,7 +192,7 @@ export default function EditGasPopover({
|
||||
<Button
|
||||
type="primary"
|
||||
onClick={onSubmit}
|
||||
disabled={hasGasErrors || isGasEstimatesLoading}
|
||||
disabled={hasGasErrors || isGasEstimatesLoading || balanceError}
|
||||
>
|
||||
{footerButtonText}
|
||||
</Button>
|
||||
@ -238,6 +239,7 @@ export default function EditGasPopover({
|
||||
gasErrors={gasErrors}
|
||||
onManualChange={onManualChange}
|
||||
minimumGasLimit={minimumGasLimitDec}
|
||||
balanceError={balanceError}
|
||||
{...editGasDisplayProps}
|
||||
/>
|
||||
</>
|
||||
|
7
ui/components/app/edit-gas-popover/index.scss
Normal file
7
ui/components/app/edit-gas-popover/index.scss
Normal file
@ -0,0 +1,7 @@
|
||||
.edit-gas-popover {
|
||||
&__wrapper {
|
||||
@media screen and (min-width: 576px) {
|
||||
max-height: 84vh;
|
||||
}
|
||||
}
|
||||
}
|
@ -11,6 +11,7 @@ import {
|
||||
import {
|
||||
multiplyCurrencies,
|
||||
conversionLessThan,
|
||||
conversionGreaterThan,
|
||||
} from '../../shared/modules/conversion.utils';
|
||||
import {
|
||||
getMaximumGasTotalInHexWei,
|
||||
@ -22,9 +23,14 @@ import {
|
||||
decGWEIToHexWEI,
|
||||
decimalToHex,
|
||||
hexToDecimal,
|
||||
addHexes,
|
||||
} from '../helpers/utils/conversions.util';
|
||||
import { getShouldShowFiat } from '../selectors';
|
||||
import { GAS_FORM_ERRORS } from '../helpers/constants/gas';
|
||||
import {
|
||||
getShouldShowFiat,
|
||||
getSelectedAccount,
|
||||
txDataSelector,
|
||||
} from '../selectors';
|
||||
import { useCurrencyDisplay } from './useCurrencyDisplay';
|
||||
import { useGasFeeEstimates } from './useGasFeeEstimates';
|
||||
import { useUserPreferencedCurrency } from './useUserPreferencedCurrency';
|
||||
@ -165,6 +171,9 @@ export function useGasFeeInputs(
|
||||
minimumGasLimit,
|
||||
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
|
||||
// default our fiat values to empty strings if showing fiat is not wanted or
|
||||
// possible.
|
||||
@ -413,6 +422,16 @@ export function useGasFeeInputs(
|
||||
...gasWarnings,
|
||||
};
|
||||
|
||||
const minimumTxCostInHexWei = addHexes(
|
||||
minimumCostInHexWei,
|
||||
txData?.txParams?.value,
|
||||
);
|
||||
|
||||
const balanceError = conversionGreaterThan(
|
||||
{ value: minimumTxCostInHexWei, fromNumericBase: 'hex' },
|
||||
{ value: ethBalance, fromNumericBase: 'hex' },
|
||||
);
|
||||
|
||||
return {
|
||||
maxFeePerGas: maxFeePerGasToUse,
|
||||
maxFeePerGasFiat: showFiat ? maxFeePerGasFiat : '',
|
||||
@ -443,5 +462,6 @@ export function useGasFeeInputs(
|
||||
setMaxFeePerGas(maxFeePerGasToUse);
|
||||
setMaxPriorityFeePerGas(maxPriorityFeePerGasToUse);
|
||||
},
|
||||
balanceError,
|
||||
};
|
||||
}
|
||||
|
@ -7,7 +7,12 @@ import {
|
||||
getNativeCurrency,
|
||||
} from '../ducks/metamask/metamask';
|
||||
import { ETH, PRIMARY } from '../helpers/constants/common';
|
||||
import { getCurrentCurrency, getShouldShowFiat } from '../selectors';
|
||||
import {
|
||||
getCurrentCurrency,
|
||||
getShouldShowFiat,
|
||||
txDataSelector,
|
||||
getSelectedAccount,
|
||||
} from '../selectors';
|
||||
import { useGasFeeEstimates } from './useGasFeeEstimates';
|
||||
import { useGasFeeInputs } from './useGasFeeInputs';
|
||||
import { useUserPreferencedCurrency } from './useUserPreferencedCurrency';
|
||||
@ -71,6 +76,32 @@ const FEE_MARKET_ESTIMATE_RETURN_VALUE = {
|
||||
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) => {
|
||||
if (selector === getConversionRate) {
|
||||
return MOCK_ETH_USD_CONVERSION_RATE;
|
||||
@ -84,6 +115,18 @@ const generateUseSelectorRouter = () => (selector) => {
|
||||
if (selector === getShouldShowFiat) {
|
||||
return true;
|
||||
}
|
||||
if (selector === txDataSelector) {
|
||||
return {
|
||||
txParams: {
|
||||
value: '0x5555',
|
||||
},
|
||||
};
|
||||
}
|
||||
if (selector === getSelectedAccount) {
|
||||
return {
|
||||
balance: '0x440aa47cc2556',
|
||||
};
|
||||
}
|
||||
return undefined;
|
||||
};
|
||||
|
||||
@ -234,4 +277,32 @@ describe('useGasFeeInputs', () => {
|
||||
// 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);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user