mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-11-22 01:47:00 +01:00
Adding validations for advance gas fee input fields (#12879)
This commit is contained in:
parent
d78cfebd43
commit
2af45a656f
@ -810,12 +810,25 @@
|
||||
"editGasLimitOutOfBounds": {
|
||||
"message": "Gas limit must be at least $1"
|
||||
},
|
||||
"editGasLimitOutOfBoundsV2": {
|
||||
"message": "Gas limit must be greater than $1 and less than $2",
|
||||
"description": "$1 is the minimum limit for gas and $2 is the maximum limit"
|
||||
},
|
||||
"editGasLimitTooltip": {
|
||||
"message": "Gas limit is the maximum units of gas you are willing to use. Units of gas are a multiplier to “Max priority fee” and “Max fee”."
|
||||
},
|
||||
"editGasLow": {
|
||||
"message": "Low"
|
||||
},
|
||||
"editGasMaxBaseFeeHigh": {
|
||||
"message": "Max base fee is higher than necessary"
|
||||
},
|
||||
"editGasMaxBaseFeeImbalance": {
|
||||
"message": "Max base fee cannot be lower than priority fee"
|
||||
},
|
||||
"editGasMaxBaseFeeLow": {
|
||||
"message": "Max base fee is low for current network conditions"
|
||||
},
|
||||
"editGasMaxFeeHigh": {
|
||||
"message": "Max fee is higher than necessary"
|
||||
},
|
||||
@ -831,12 +844,21 @@
|
||||
"editGasMaxPriorityFeeBelowMinimum": {
|
||||
"message": "Max priority fee must be greater than 0 GWEI"
|
||||
},
|
||||
"editGasMaxPriorityFeeBelowMinimumV2": {
|
||||
"message": "Priority fee must be at least 1 GWEI"
|
||||
},
|
||||
"editGasMaxPriorityFeeHigh": {
|
||||
"message": "Max priority fee is higher than necessary. You may pay more than needed."
|
||||
},
|
||||
"editGasMaxPriorityFeeHighV2": {
|
||||
"message": "Priority fee is higher than necessary. You may pay more than needed"
|
||||
},
|
||||
"editGasMaxPriorityFeeLow": {
|
||||
"message": "Max priority fee is low for current network conditions"
|
||||
},
|
||||
"editGasMaxPriorityFeeLowV2": {
|
||||
"message": "Priority fee is low for current network conditions"
|
||||
},
|
||||
"editGasMaxPriorityFeeTooltip": {
|
||||
"message": "Max priority fee (aka “miner tip”) goes directly to miners and incentivizes them to prioritize your transaction. You’ll most often pay your max setting"
|
||||
},
|
||||
|
@ -1,25 +1,38 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
|
||||
import { useGasFeeContext } from '../../../../contexts/gasFee';
|
||||
import { bnGreaterThan, bnLessThan } from '../../../../helpers/utils/util';
|
||||
import { TYPOGRAPHY } from '../../../../helpers/constants/design-system';
|
||||
import { useI18nContext } from '../../../../hooks/useI18nContext';
|
||||
import Box from '../../../ui/box';
|
||||
import { MAX_GAS_LIMIT_DEC } from '../../../../pages/send/send.constants';
|
||||
import Button from '../../../ui/button';
|
||||
import FormField from '../../../ui/form-field';
|
||||
import I18nValue from '../../../ui/i18n-value';
|
||||
import Typography from '../../../ui/typography';
|
||||
|
||||
import { useAdvanceGasFeePopoverContext } from '../context';
|
||||
import { useAdvancedGasFeePopoverContext } from '../context';
|
||||
|
||||
const validateGasLimit = (gasLimit, minimumGasLimitDec) => {
|
||||
return bnLessThan(gasLimit, minimumGasLimitDec) ||
|
||||
bnGreaterThan(gasLimit, MAX_GAS_LIMIT_DEC)
|
||||
? 'editGasLimitOutOfBoundsV2'
|
||||
: null;
|
||||
};
|
||||
|
||||
const AdvancedGasFeeGasLimit = () => {
|
||||
const t = useI18nContext();
|
||||
const {
|
||||
setDirty,
|
||||
setGasLimit: setGasLimitInContext,
|
||||
} = useAdvanceGasFeePopoverContext();
|
||||
const { gasLimit: gasLimitInTransaction } = useGasFeeContext();
|
||||
setHasError,
|
||||
} = useAdvancedGasFeePopoverContext();
|
||||
const {
|
||||
gasLimit: gasLimitInTransaction,
|
||||
minimumGasLimitDec,
|
||||
} = useGasFeeContext();
|
||||
const [isEditing, setEditing] = useState(false);
|
||||
const [gasLimit, setGasLimit] = useState(gasLimitInTransaction);
|
||||
const [gasLimitError, setGasLimitError] = useState();
|
||||
|
||||
const updateGasLimit = (value) => {
|
||||
setGasLimit(value);
|
||||
@ -28,11 +41,19 @@ const AdvancedGasFeeGasLimit = () => {
|
||||
|
||||
useEffect(() => {
|
||||
setGasLimitInContext(gasLimit);
|
||||
}, [gasLimit, setGasLimitInContext]);
|
||||
const error = validateGasLimit(gasLimit, minimumGasLimitDec);
|
||||
setGasLimitError(error);
|
||||
setHasError(Boolean(error));
|
||||
}, [gasLimit, minimumGasLimitDec, setGasLimitInContext, setHasError]);
|
||||
|
||||
if (isEditing) {
|
||||
return (
|
||||
<FormField
|
||||
error={
|
||||
gasLimitError
|
||||
? t(gasLimitError, [minimumGasLimitDec - 1, MAX_GAS_LIMIT_DEC])
|
||||
: ''
|
||||
}
|
||||
onChange={updateGasLimit}
|
||||
titleText={t('gasLimitV2')}
|
||||
value={gasLimit}
|
||||
@ -42,24 +63,22 @@ const AdvancedGasFeeGasLimit = () => {
|
||||
}
|
||||
|
||||
return (
|
||||
<Typography tag={TYPOGRAPHY.Paragraph} variant={TYPOGRAPHY.H7}>
|
||||
<Box
|
||||
display="flex"
|
||||
alignItems="center"
|
||||
className="advanced-gas-fee-gas-limit"
|
||||
<Typography
|
||||
tag={TYPOGRAPHY.Paragraph}
|
||||
variant={TYPOGRAPHY.H7}
|
||||
className="advanced-gas-fee-gas-limit"
|
||||
>
|
||||
<strong>
|
||||
<I18nValue messageKey="gasLimitV2" />
|
||||
</strong>
|
||||
<span>{gasLimit}</span>
|
||||
<Button
|
||||
className="advanced-gas-fee-gas-limit__edit-link"
|
||||
onClick={() => setEditing(true)}
|
||||
type="link"
|
||||
>
|
||||
<strong>
|
||||
<I18nValue messageKey="gasLimitV2" />
|
||||
</strong>
|
||||
<span>{gasLimit}</span>
|
||||
<Button
|
||||
className="advanced-gas-fee-gas-limit__edit-link"
|
||||
onClick={() => setEditing(true)}
|
||||
type="link"
|
||||
>
|
||||
<I18nValue messageKey="edit" />
|
||||
</Button>
|
||||
</Box>
|
||||
<I18nValue messageKey="edit" />
|
||||
</Button>
|
||||
</Typography>
|
||||
);
|
||||
};
|
||||
|
@ -8,7 +8,7 @@ import mockState from '../../../../../test/data/mock-state.json';
|
||||
import { GasFeeContextProvider } from '../../../../contexts/gasFee';
|
||||
import configureStore from '../../../../store/store';
|
||||
|
||||
import { AdvanceGasFeePopoverContextProvider } from '../context';
|
||||
import { AdvancedGasFeePopoverContextProvider } from '../context';
|
||||
import AdvancedGasFeeGasLimit from './advanced-gas-fee-gas-limit';
|
||||
|
||||
jest.mock('../../../../store/actions', () => ({
|
||||
@ -20,7 +20,7 @@ jest.mock('../../../../store/actions', () => ({
|
||||
removePollingTokenFromAppState: jest.fn(),
|
||||
}));
|
||||
|
||||
const render = (txProps) => {
|
||||
const render = (contextProps) => {
|
||||
const store = configureStore({
|
||||
metamask: {
|
||||
...mockState.metamask,
|
||||
@ -42,12 +42,12 @@ const render = (txProps) => {
|
||||
transaction={{
|
||||
userFeeLevel: 'custom',
|
||||
txParams: { gas: '0x5208' },
|
||||
...txProps,
|
||||
}}
|
||||
{...contextProps}
|
||||
>
|
||||
<AdvanceGasFeePopoverContextProvider>
|
||||
<AdvancedGasFeePopoverContextProvider>
|
||||
<AdvancedGasFeeGasLimit />
|
||||
</AdvanceGasFeePopoverContextProvider>
|
||||
</AdvancedGasFeePopoverContextProvider>
|
||||
</GasFeeContextProvider>,
|
||||
store,
|
||||
);
|
||||
@ -65,4 +65,46 @@ describe('AdvancedGasFeeGasLimit', () => {
|
||||
fireEvent.click(screen.queryByText('Edit'));
|
||||
expect(document.getElementsByTagName('input')[0]).toHaveValue(21000);
|
||||
});
|
||||
|
||||
it('should show error if gas limit is not in range', () => {
|
||||
render();
|
||||
fireEvent.click(screen.queryByText('Edit'));
|
||||
fireEvent.change(document.getElementsByTagName('input')[0], {
|
||||
target: { value: 20000 },
|
||||
});
|
||||
expect(
|
||||
screen.queryByText(
|
||||
'Gas limit must be greater than 20999 and less than 7920027',
|
||||
),
|
||||
).toBeInTheDocument();
|
||||
fireEvent.change(document.getElementsByTagName('input')[0], {
|
||||
target: { value: 8000000 },
|
||||
});
|
||||
expect(
|
||||
screen.queryByText(
|
||||
'Gas limit must be greater than 20999 and less than 7920027',
|
||||
),
|
||||
).toBeInTheDocument();
|
||||
fireEvent.change(document.getElementsByTagName('input')[0], {
|
||||
target: { value: 7000000 },
|
||||
});
|
||||
expect(
|
||||
screen.queryByText(
|
||||
'Gas limit must be greater than 20999 and less than 7920027',
|
||||
),
|
||||
).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should validate gas limit against minimumGasLimit it is passed to context', () => {
|
||||
render({ minimumGasLimit: '0x7530' });
|
||||
fireEvent.click(screen.queryByText('Edit'));
|
||||
fireEvent.change(document.getElementsByTagName('input')[0], {
|
||||
target: { value: 25000 },
|
||||
});
|
||||
expect(
|
||||
screen.queryByText(
|
||||
'Gas limit must be greater than 29999 and less than 7920027',
|
||||
),
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
@ -1,4 +1,6 @@
|
||||
.advanced-gas-fee-gas-limit {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
white-space: nowrap;
|
||||
|
||||
> * {
|
||||
|
@ -6,7 +6,7 @@ import PriorityFeeInput from './priority-fee-input';
|
||||
|
||||
const AdvancedGasFeeInputs = () => {
|
||||
return (
|
||||
<Box className="advanced-gas-fee-inputs" margin={4}>
|
||||
<Box className="advanced-gas-fee-inputs" margin={[4, 0]}>
|
||||
<BaseFeeInput />
|
||||
<div className="advanced-gas-fee-inputs__separator" />
|
||||
<PriorityFeeInput />
|
||||
|
@ -1,12 +1,14 @@
|
||||
import React, { useCallback, useEffect, useState } from 'react';
|
||||
import { useSelector } from 'react-redux';
|
||||
|
||||
import { HIGH_FEE_WARNING_MULTIPLIER } from '../../../../../pages/send/send.constants';
|
||||
import { PRIORITY_LEVELS } from '../../../../../../shared/constants/gas';
|
||||
import {
|
||||
divideCurrencies,
|
||||
multiplyCurrencies,
|
||||
} from '../../../../../../shared/modules/conversion.utils';
|
||||
import { PRIMARY, SECONDARY } from '../../../../../helpers/constants/common';
|
||||
import { bnGreaterThan, bnLessThan } from '../../../../../helpers/utils/util';
|
||||
import { decGWEIToHexWEI } from '../../../../../helpers/utils/conversions.util';
|
||||
import { getAdvancedGasFeeValues } from '../../../../../selectors';
|
||||
import { useGasFeeContext } from '../../../../../contexts/gasFee';
|
||||
@ -18,7 +20,7 @@ import Box from '../../../../ui/box';
|
||||
import FormField from '../../../../ui/form-field';
|
||||
import I18nValue from '../../../../ui/i18n-value';
|
||||
|
||||
import { useAdvanceGasFeePopoverContext } from '../../context';
|
||||
import { useAdvancedGasFeePopoverContext } from '../../context';
|
||||
import AdvancedGasFeeInputSubtext from '../../advanced-gas-fee-input-subtext';
|
||||
|
||||
const divideCurrencyValues = (value, baseFee) => {
|
||||
@ -39,11 +41,40 @@ const multiplyCurrencyValues = (baseFee, value, numberOfDecimals) =>
|
||||
multiplierBase: 10,
|
||||
}).toNumber();
|
||||
|
||||
const validateBaseFee = (value, gasFeeEstimates, maxPriorityFeePerGas) => {
|
||||
if (bnGreaterThan(maxPriorityFeePerGas, value)) {
|
||||
return 'editGasMaxBaseFeeImbalance';
|
||||
}
|
||||
if (
|
||||
gasFeeEstimates?.low &&
|
||||
bnLessThan(value, gasFeeEstimates.low.suggestedMaxFeePerGas)
|
||||
) {
|
||||
return 'editGasMaxBaseFeeLow';
|
||||
}
|
||||
if (
|
||||
gasFeeEstimates?.high &&
|
||||
bnGreaterThan(
|
||||
value,
|
||||
gasFeeEstimates.high.suggestedMaxFeePerGas * HIGH_FEE_WARNING_MULTIPLIER,
|
||||
)
|
||||
) {
|
||||
return 'editGasMaxBaseFeeHigh';
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
const BaseFeeInput = () => {
|
||||
const t = useI18nContext();
|
||||
const { gasFeeEstimates, estimateUsed, maxFeePerGas } = useGasFeeContext();
|
||||
const { setDirty, setMaxFeePerGas } = useAdvanceGasFeePopoverContext();
|
||||
const {
|
||||
setDirty,
|
||||
setHasError,
|
||||
setMaxFeePerGas,
|
||||
maxPriorityFeePerGas,
|
||||
} = useAdvancedGasFeePopoverContext();
|
||||
|
||||
const { estimatedBaseFee } = gasFeeEstimates;
|
||||
const [baseFeeError, setBaseFeeError] = useState();
|
||||
const {
|
||||
numberOfDecimals: numberOfDecimalsPrimary,
|
||||
} = useUserPreferencedCurrency(PRIMARY);
|
||||
@ -116,11 +147,26 @@ const BaseFeeInput = () => {
|
||||
|
||||
useEffect(() => {
|
||||
setMaxFeePerGas(maxBaseFeeGWEI);
|
||||
}, [maxBaseFeeGWEI, setMaxFeePerGas]);
|
||||
const error = validateBaseFee(
|
||||
maxBaseFeeGWEI,
|
||||
gasFeeEstimates,
|
||||
maxPriorityFeePerGas,
|
||||
);
|
||||
setBaseFeeError(error);
|
||||
setHasError(Boolean(error));
|
||||
}, [
|
||||
gasFeeEstimates,
|
||||
maxBaseFeeGWEI,
|
||||
maxPriorityFeePerGas,
|
||||
setHasError,
|
||||
setBaseFeeError,
|
||||
setMaxFeePerGas,
|
||||
]);
|
||||
|
||||
return (
|
||||
<Box className="base-fee-input">
|
||||
<FormField
|
||||
error={baseFeeError ? t(baseFeeError) : ''}
|
||||
onChange={updateBaseFee}
|
||||
titleText={t('maxBaseFee')}
|
||||
titleUnit={editingInGwei ? 'GWEI' : `(${t('multiplier')})`}
|
||||
|
@ -8,7 +8,7 @@ import mockState from '../../../../../../test/data/mock-state.json';
|
||||
import { GasFeeContextProvider } from '../../../../../contexts/gasFee';
|
||||
import configureStore from '../../../../../store/store';
|
||||
|
||||
import { AdvanceGasFeePopoverContextProvider } from '../../context';
|
||||
import { AdvancedGasFeePopoverContextProvider } from '../../context';
|
||||
import BaseFeeInput from './base-fee-input';
|
||||
|
||||
jest.mock('../../../../../store/actions', () => ({
|
||||
@ -44,9 +44,9 @@ const render = (txProps) => {
|
||||
...txProps,
|
||||
}}
|
||||
>
|
||||
<AdvanceGasFeePopoverContextProvider>
|
||||
<AdvancedGasFeePopoverContextProvider>
|
||||
<BaseFeeInput />
|
||||
</AdvanceGasFeePopoverContextProvider>
|
||||
</AdvancedGasFeePopoverContextProvider>
|
||||
</GasFeeContextProvider>,
|
||||
store,
|
||||
);
|
||||
@ -115,4 +115,58 @@ describe('BaseFeeInput', () => {
|
||||
});
|
||||
expect(screen.queryByText('50')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should show error if base fee is less than suggested low value', () => {
|
||||
render({
|
||||
txParams: {
|
||||
maxFeePerGas: '0x174876E800',
|
||||
},
|
||||
});
|
||||
fireEvent.change(document.getElementsByTagName('input')[0], {
|
||||
target: { value: 3 },
|
||||
});
|
||||
expect(
|
||||
screen.queryByText('Max base fee is low for current network conditions'),
|
||||
).not.toBeInTheDocument();
|
||||
fireEvent.change(document.getElementsByTagName('input')[0], {
|
||||
target: { value: 0.01 },
|
||||
});
|
||||
expect(
|
||||
screen.queryByText('Max base fee is low for current network conditions'),
|
||||
).toBeInTheDocument();
|
||||
fireEvent.click(screen.queryByText('Edit in GWEI'));
|
||||
fireEvent.change(document.getElementsByTagName('input')[0], {
|
||||
target: { value: 10 },
|
||||
});
|
||||
expect(
|
||||
screen.queryByText('Max base fee is low for current network conditions'),
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should show error if base if is more than suggested high value', () => {
|
||||
render({
|
||||
txParams: {
|
||||
maxFeePerGas: '0x174876E800',
|
||||
},
|
||||
});
|
||||
fireEvent.change(document.getElementsByTagName('input')[0], {
|
||||
target: { value: 3 },
|
||||
});
|
||||
expect(
|
||||
screen.queryByText('Max base fee is higher than necessary'),
|
||||
).not.toBeInTheDocument();
|
||||
fireEvent.change(document.getElementsByTagName('input')[0], {
|
||||
target: { value: 10 },
|
||||
});
|
||||
fireEvent.click(screen.queryByText('Edit in GWEI'));
|
||||
expect(
|
||||
screen.queryByText('Max base fee is higher than necessary'),
|
||||
).toBeInTheDocument();
|
||||
fireEvent.change(document.getElementsByTagName('input')[0], {
|
||||
target: { value: 500 },
|
||||
});
|
||||
expect(
|
||||
screen.queryByText('Max base fee is higher than necessary'),
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
@ -1,6 +1,7 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { useSelector } from 'react-redux';
|
||||
|
||||
import { HIGH_FEE_WARNING_MULTIPLIER } from '../../../../../pages/send/send.constants';
|
||||
import { PRIORITY_LEVELS } from '../../../../../../shared/constants/gas';
|
||||
import { SECONDARY } from '../../../../../helpers/constants/common';
|
||||
import { decGWEIToHexWEI } from '../../../../../helpers/utils/conversions.util';
|
||||
@ -10,18 +11,48 @@ import { useGasFeeContext } from '../../../../../contexts/gasFee';
|
||||
import { useI18nContext } from '../../../../../hooks/useI18nContext';
|
||||
import { useUserPreferencedCurrency } from '../../../../../hooks/useUserPreferencedCurrency';
|
||||
import FormField from '../../../../ui/form-field';
|
||||
import { bnGreaterThan, bnLessThan } from '../../../../../helpers/utils/util';
|
||||
|
||||
import { useAdvanceGasFeePopoverContext } from '../../context';
|
||||
import { useAdvancedGasFeePopoverContext } from '../../context';
|
||||
import AdvancedGasFeeInputSubtext from '../../advanced-gas-fee-input-subtext';
|
||||
|
||||
const validatePriorityFee = (value, gasFeeEstimates) => {
|
||||
if (value < 1) {
|
||||
return 'editGasMaxPriorityFeeBelowMinimumV2';
|
||||
}
|
||||
if (
|
||||
gasFeeEstimates?.low &&
|
||||
bnLessThan(value, gasFeeEstimates.low.suggestedMaxPriorityFeePerGas)
|
||||
) {
|
||||
return 'editGasMaxPriorityFeeLowV2';
|
||||
}
|
||||
if (
|
||||
gasFeeEstimates?.high &&
|
||||
bnGreaterThan(
|
||||
value,
|
||||
gasFeeEstimates.high.suggestedMaxPriorityFeePerGas *
|
||||
HIGH_FEE_WARNING_MULTIPLIER,
|
||||
)
|
||||
) {
|
||||
return 'editGasMaxPriorityFeeHighV2';
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
const PriorityFeeInput = () => {
|
||||
const t = useI18nContext();
|
||||
const advancedGasFeeValues = useSelector(getAdvancedGasFeeValues);
|
||||
const {
|
||||
setDirty,
|
||||
setHasError,
|
||||
setMaxPriorityFeePerGas,
|
||||
} = useAdvanceGasFeePopoverContext();
|
||||
const { estimateUsed, maxPriorityFeePerGas } = useGasFeeContext();
|
||||
} = useAdvancedGasFeePopoverContext();
|
||||
const {
|
||||
estimateUsed,
|
||||
gasFeeEstimates,
|
||||
maxPriorityFeePerGas,
|
||||
} = useGasFeeContext();
|
||||
const [priorityFeeError, setPriorityFeeError] = useState();
|
||||
|
||||
const [priorityFee, setPriorityFee] = useState(() => {
|
||||
if (
|
||||
@ -46,11 +77,21 @@ const PriorityFeeInput = () => {
|
||||
|
||||
useEffect(() => {
|
||||
setMaxPriorityFeePerGas(priorityFee);
|
||||
}, [priorityFee, setMaxPriorityFeePerGas]);
|
||||
const error = validatePriorityFee(priorityFee, gasFeeEstimates);
|
||||
setPriorityFeeError(error);
|
||||
setHasError(Boolean(error));
|
||||
}, [
|
||||
gasFeeEstimates,
|
||||
priorityFee,
|
||||
setHasError,
|
||||
setMaxPriorityFeePerGas,
|
||||
setPriorityFeeError,
|
||||
]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<FormField
|
||||
error={priorityFeeError ? t(priorityFeeError) : ''}
|
||||
onChange={updatePriorityFee}
|
||||
titleText={t('priorityFeeProperCase')}
|
||||
titleUnit="(GWEI)"
|
||||
|
@ -7,7 +7,7 @@ import mockState from '../../../../../../test/data/mock-state.json';
|
||||
import { GasFeeContextProvider } from '../../../../../contexts/gasFee';
|
||||
import configureStore from '../../../../../store/store';
|
||||
|
||||
import { AdvanceGasFeePopoverContextProvider } from '../../context';
|
||||
import { AdvancedGasFeePopoverContextProvider } from '../../context';
|
||||
import PriorityfeeInput from './priority-fee-input';
|
||||
|
||||
jest.mock('../../../../../store/actions', () => ({
|
||||
@ -43,9 +43,9 @@ const render = (txProps) => {
|
||||
...txProps,
|
||||
}}
|
||||
>
|
||||
<AdvanceGasFeePopoverContextProvider>
|
||||
<AdvancedGasFeePopoverContextProvider>
|
||||
<PriorityfeeInput />
|
||||
</AdvanceGasFeePopoverContextProvider>
|
||||
</AdvancedGasFeePopoverContextProvider>
|
||||
</GasFeeContextProvider>,
|
||||
store,
|
||||
);
|
||||
|
@ -5,7 +5,7 @@ import { useTransactionModalContext } from '../../../contexts/transaction-modal'
|
||||
import Box from '../../ui/box';
|
||||
import Popover from '../../ui/popover';
|
||||
|
||||
import { AdvanceGasFeePopoverContextProvider } from './context';
|
||||
import { AdvancedGasFeePopoverContextProvider } from './context';
|
||||
import AdvancedGasFeeInputs from './advanced-gas-fee-inputs';
|
||||
import AdvancedGasFeeGasLimit from './advanced-gas-fee-gas-limit';
|
||||
import AdvancedGasFeeSaveButton from './advanced-gas-fee-save';
|
||||
@ -21,7 +21,7 @@ const AdvancedGasFeePopover = () => {
|
||||
if (currentModal !== 'advancedGasFee') return null;
|
||||
|
||||
return (
|
||||
<AdvanceGasFeePopoverContextProvider>
|
||||
<AdvancedGasFeePopoverContextProvider>
|
||||
<Popover
|
||||
className="advanced-gas-fee-popover"
|
||||
title={t('advancedGasFeeModalTitle')}
|
||||
@ -35,7 +35,7 @@ const AdvancedGasFeePopover = () => {
|
||||
<AdvancedGasFeeGasLimit />
|
||||
</Box>
|
||||
</Popover>
|
||||
</AdvanceGasFeePopoverContextProvider>
|
||||
</AdvancedGasFeePopoverContextProvider>
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -64,7 +64,7 @@ describe('AdvancedGasFeePopover', () => {
|
||||
it('should enable save button as input value is changed', () => {
|
||||
render();
|
||||
fireEvent.change(document.getElementsByTagName('input')[0], {
|
||||
target: { value: 4 },
|
||||
target: { value: 3 },
|
||||
});
|
||||
expect(screen.queryByRole('button', { name: 'Save' })).not.toBeDisabled();
|
||||
});
|
||||
|
@ -6,7 +6,7 @@ import { useGasFeeContext } from '../../../../contexts/gasFee';
|
||||
import Button from '../../../ui/button';
|
||||
import I18nValue from '../../../ui/i18n-value';
|
||||
|
||||
import { useAdvanceGasFeePopoverContext } from '../context';
|
||||
import { useAdvancedGasFeePopoverContext } from '../context';
|
||||
import { decGWEIToHexWEI } from '../../../../../shared/modules/conversion.utils';
|
||||
|
||||
const AdvancedGasFeeSaveButton = () => {
|
||||
@ -15,9 +15,10 @@ const AdvancedGasFeeSaveButton = () => {
|
||||
const {
|
||||
isDirty,
|
||||
gasLimit,
|
||||
hasError,
|
||||
maxFeePerGas,
|
||||
maxPriorityFeePerGas,
|
||||
} = useAdvanceGasFeePopoverContext();
|
||||
} = useAdvancedGasFeePopoverContext();
|
||||
|
||||
const onSave = () => {
|
||||
updateTransaction({
|
||||
@ -30,7 +31,7 @@ const AdvancedGasFeeSaveButton = () => {
|
||||
};
|
||||
|
||||
return (
|
||||
<Button type="primary" disabled={!isDirty} onClick={onSave}>
|
||||
<Button type="primary" disabled={!isDirty || hasError} onClick={onSave}>
|
||||
<I18nValue messageKey="save" />
|
||||
</Button>
|
||||
);
|
||||
|
@ -1,36 +1,39 @@
|
||||
import React, { createContext, useContext, useState } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
export const AdvanceGasFeePopoverContext = createContext({});
|
||||
export const AdvancedGasFeePopoverContext = createContext({});
|
||||
|
||||
export const AdvanceGasFeePopoverContextProvider = ({ children }) => {
|
||||
export const AdvancedGasFeePopoverContextProvider = ({ children }) => {
|
||||
const [gasLimit, setGasLimit] = useState();
|
||||
const [maxFeePerGas, setMaxFeePerGas] = useState();
|
||||
const [maxPriorityFeePerGas, setMaxPriorityFeePerGas] = useState();
|
||||
const [isDirty, setDirty] = useState();
|
||||
const [hasError, setHasError] = useState(false);
|
||||
|
||||
return (
|
||||
<AdvanceGasFeePopoverContext.Provider
|
||||
<AdvancedGasFeePopoverContext.Provider
|
||||
value={{
|
||||
gasLimit,
|
||||
hasError,
|
||||
isDirty,
|
||||
maxFeePerGas,
|
||||
maxPriorityFeePerGas,
|
||||
setDirty,
|
||||
setGasLimit,
|
||||
setHasError,
|
||||
setMaxPriorityFeePerGas,
|
||||
setMaxFeePerGas,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</AdvanceGasFeePopoverContext.Provider>
|
||||
</AdvancedGasFeePopoverContext.Provider>
|
||||
);
|
||||
};
|
||||
|
||||
export function useAdvanceGasFeePopoverContext() {
|
||||
return useContext(AdvanceGasFeePopoverContext);
|
||||
export function useAdvancedGasFeePopoverContext() {
|
||||
return useContext(AdvancedGasFeePopoverContext);
|
||||
}
|
||||
|
||||
AdvanceGasFeePopoverContextProvider.propTypes = {
|
||||
AdvancedGasFeePopoverContextProvider.propTypes = {
|
||||
children: PropTypes.node.isRequired,
|
||||
};
|
@ -1 +1 @@
|
||||
export * from './advanceGasFeePopover';
|
||||
export * from './advancedGasFeePopover';
|
||||
|
@ -15,7 +15,7 @@
|
||||
background-color: $primary-2;
|
||||
}
|
||||
|
||||
&-selected {
|
||||
&--selected {
|
||||
background-color: $ui-1;
|
||||
}
|
||||
|
||||
|
@ -23,6 +23,21 @@ import { useMaxPriorityFeePerGasInput } from './useMaxPriorityFeePerGasInput';
|
||||
import { useGasEstimates } from './useGasEstimates';
|
||||
import { useTransactionFunctions } from './useTransactionFunctions';
|
||||
|
||||
/**
|
||||
* In EIP_1559_V2 implementation as used by useGasfeeInputContext() the use of this hook is evolved.
|
||||
* It is no longer used to keep transient state of advance gas fee inputs.
|
||||
* Transient state of inputs is maintained locally in /ui/components/app/advance-gas-fee-popover component.
|
||||
*
|
||||
* This hook is used now as source of shared data about transaction, it shares details of gas fee in transaction,
|
||||
* estimate used, is EIP-1559 supported and other details. It also have methods to update transaction.
|
||||
*
|
||||
* Transaction is used as single source of truth and as transaction is updated the fields shared by hook are
|
||||
* also updated using useEffect hook.
|
||||
*
|
||||
* It will be useful to plan a task to create a new hook of this shared information from this hook.
|
||||
* Methods like setEstimateToUse, onManualChange are deprecated in context of EIP_1559_V2 implementation.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} GasFeeInputReturnType
|
||||
* @property {DecGweiString} [maxFeePerGas] - the maxFeePerGas input value.
|
||||
@ -318,24 +333,10 @@ export function useGasFeeInputs(
|
||||
gasWarnings,
|
||||
hasGasErrors,
|
||||
hasSimulationError,
|
||||
minimumGasLimitDec: hexToDecimal(minimumGasLimit),
|
||||
supportsEIP1559,
|
||||
supportsEIP1559V2,
|
||||
updateTransaction,
|
||||
updateTransactionUsingGasFeeEstimates,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* In EIP_1559_V2 implementation as used by useGasfeeInputContext() the use of this hook is evolved.
|
||||
* It is no longer used to keep transient state of advance gas fee inputs.
|
||||
* Transient state of inputs is maintained locally in /ui/components/app/advance-gas-fee-popover component.
|
||||
*
|
||||
* This hook is used now as source of shared data about transaction, it shares details of gas fee in transaction,
|
||||
* estimate used, is EIP-1559 supported and other details. It also have methods to update transaction.
|
||||
*
|
||||
* Transaction is used as single source of truth and as transaction is updated the fields shared by hook are
|
||||
* also updated using useEffect hook.
|
||||
*
|
||||
* It will be useful to plan a task to create a new hook of this shared information from this hook.
|
||||
* Methods like setEstimateToUse, onManualChange are deprecated in context of EIP_1559_V2 implementation.
|
||||
*/
|
||||
|
@ -7,8 +7,10 @@ import { addHexPrefix } from '../../../app/scripts/lib/util';
|
||||
const MIN_GAS_PRICE_DEC = '0';
|
||||
const MIN_GAS_PRICE_HEX = parseInt(MIN_GAS_PRICE_DEC, 10).toString(16);
|
||||
const MIN_GAS_LIMIT_DEC = '21000';
|
||||
const MAX_GAS_LIMIT_DEC = '7920027';
|
||||
const MIN_GAS_LIMIT_HEX = parseInt(MIN_GAS_LIMIT_DEC, 10).toString(16);
|
||||
|
||||
const HIGH_FEE_WARNING_MULTIPLIER = 1.5;
|
||||
const MIN_GAS_PRICE_GWEI = addHexPrefix(
|
||||
conversionUtil(MIN_GAS_PRICE_HEX, {
|
||||
fromDenomination: 'WEI',
|
||||
@ -45,6 +47,8 @@ const ENS_UNKNOWN_ERROR = 'ensUnknownError';
|
||||
const ENS_REGISTRATION_ERROR = 'ensRegistrationError';
|
||||
|
||||
export {
|
||||
MAX_GAS_LIMIT_DEC,
|
||||
HIGH_FEE_WARNING_MULTIPLIER,
|
||||
INSUFFICIENT_FUNDS_ERROR,
|
||||
INSUFFICIENT_TOKENS_ERROR,
|
||||
INVALID_RECIPIENT_ADDRESS_ERROR,
|
||||
|
Loading…
Reference in New Issue
Block a user