mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-12-23 09:52:26 +01:00
Fix speed-up/cancel: don't update existing transaction data (#14355)
* Fix speed-up/cancel: don't update existing transaction data * Move retryTxMeta state management to useGasFeeInputs.js * Handle initial retryTxMeta set if no transaction is passed to useGasFeeInputs * Ensure previousGas is use on retry transaction if it is available in useGasFeeInputs * Remove update transaction mock and correctly test gas fee increase scenarios now that updateTransaction used in cancel-speedup is defined on the front end
This commit is contained in:
parent
54ac00027b
commit
78f68b3dab
@ -1,5 +1,6 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { act, screen } from '@testing-library/react';
|
import { act, screen } from '@testing-library/react';
|
||||||
|
import BigNumber from 'bignumber.js';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
EDIT_GAS_MODES,
|
EDIT_GAS_MODES,
|
||||||
@ -10,9 +11,47 @@ import mockEstimates from '../../../../test/data/mock-estimates.json';
|
|||||||
import mockState from '../../../../test/data/mock-state.json';
|
import mockState from '../../../../test/data/mock-state.json';
|
||||||
import { GasFeeContextProvider } from '../../../contexts/gasFee';
|
import { GasFeeContextProvider } from '../../../contexts/gasFee';
|
||||||
import configureStore from '../../../store/store';
|
import configureStore from '../../../store/store';
|
||||||
|
import {
|
||||||
|
hexWEIToDecETH,
|
||||||
|
decGWEIToHexWEI,
|
||||||
|
} from '../../../helpers/utils/conversions.util';
|
||||||
|
|
||||||
import CancelSpeedupPopover from './cancel-speedup-popover';
|
import CancelSpeedupPopover from './cancel-speedup-popover';
|
||||||
|
|
||||||
|
const MAXFEEPERGAS_ABOVE_MOCK_MEDIUM_HEX = '0x174876e800';
|
||||||
|
const MAXGASCOST_ABOVE_MOCK_MEDIUM_BN = new BigNumber(
|
||||||
|
MAXFEEPERGAS_ABOVE_MOCK_MEDIUM_HEX,
|
||||||
|
16,
|
||||||
|
).times(21000, 10);
|
||||||
|
const MAXGASCOST_ABOVE_MOCK_MEDIUM_BN_PLUS_TEN_PCT_HEX = MAXGASCOST_ABOVE_MOCK_MEDIUM_BN.times(
|
||||||
|
1.1,
|
||||||
|
10,
|
||||||
|
).toString(16);
|
||||||
|
|
||||||
|
const EXPECTED_ETH_FEE_1 = hexWEIToDecETH(
|
||||||
|
MAXGASCOST_ABOVE_MOCK_MEDIUM_BN_PLUS_TEN_PCT_HEX,
|
||||||
|
);
|
||||||
|
|
||||||
|
const MOCK_SUGGESTED_MEDIUM_MAXFEEPERGAS_DEC_GWEI =
|
||||||
|
mockEstimates[GAS_ESTIMATE_TYPES.FEE_MARKET].gasFeeEstimates.medium
|
||||||
|
.suggestedMaxFeePerGas;
|
||||||
|
const MOCK_SUGGESTED_MEDIUM_MAXFEEPERGAS_BN_WEI = new BigNumber(
|
||||||
|
decGWEIToHexWEI(MOCK_SUGGESTED_MEDIUM_MAXFEEPERGAS_DEC_GWEI),
|
||||||
|
16,
|
||||||
|
);
|
||||||
|
const MAXFEEPERGAS_BELOW_MOCK_MEDIUM_HEX = MOCK_SUGGESTED_MEDIUM_MAXFEEPERGAS_BN_WEI.div(
|
||||||
|
10,
|
||||||
|
10,
|
||||||
|
).toString(16);
|
||||||
|
|
||||||
|
const EXPECTED_ETH_FEE_2 = hexWEIToDecETH(
|
||||||
|
MOCK_SUGGESTED_MEDIUM_MAXFEEPERGAS_BN_WEI.times(21000, 10).toString(16),
|
||||||
|
);
|
||||||
|
|
||||||
|
const MOCK_SUGGESTED_MEDIUM_MAXFEEPERGAS_HEX_WEI = MOCK_SUGGESTED_MEDIUM_MAXFEEPERGAS_BN_WEI.toString(
|
||||||
|
16,
|
||||||
|
);
|
||||||
|
|
||||||
jest.mock('../../../store/actions', () => ({
|
jest.mock('../../../store/actions', () => ({
|
||||||
disconnectGasFeeEstimatePoller: jest.fn(),
|
disconnectGasFeeEstimatePoller: jest.fn(),
|
||||||
getGasFeeTimeEstimate: jest.fn().mockImplementation(() => Promise.resolve()),
|
getGasFeeTimeEstimate: jest.fn().mockImplementation(() => Promise.resolve()),
|
||||||
@ -21,7 +60,6 @@ jest.mock('../../../store/actions', () => ({
|
|||||||
.mockImplementation(() => Promise.resolve()),
|
.mockImplementation(() => Promise.resolve()),
|
||||||
addPollingTokenToAppState: jest.fn(),
|
addPollingTokenToAppState: jest.fn(),
|
||||||
removePollingTokenFromAppState: jest.fn(),
|
removePollingTokenFromAppState: jest.fn(),
|
||||||
updateTransaction: () => ({ type: 'UPDATE_TRANSACTION_PARAMS' }),
|
|
||||||
updateTransactionGasFees: () => ({ type: 'UPDATE_TRANSACTION_PARAMS' }),
|
updateTransactionGasFees: () => ({ type: 'UPDATE_TRANSACTION_PARAMS' }),
|
||||||
updatePreviousGasParams: () => ({ type: 'UPDATE_TRANSACTION_PARAMS' }),
|
updatePreviousGasParams: () => ({ type: 'UPDATE_TRANSACTION_PARAMS' }),
|
||||||
createTransactionEventFragment: jest.fn(),
|
createTransactionEventFragment: jest.fn(),
|
||||||
@ -34,7 +72,10 @@ jest.mock('../../../contexts/transaction-modal', () => ({
|
|||||||
}),
|
}),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const render = (props) => {
|
const render = (
|
||||||
|
props,
|
||||||
|
maxFeePerGas = MOCK_SUGGESTED_MEDIUM_MAXFEEPERGAS_HEX_WEI,
|
||||||
|
) => {
|
||||||
const store = configureStore({
|
const store = configureStore({
|
||||||
metamask: {
|
metamask: {
|
||||||
...mockState.metamask,
|
...mockState.metamask,
|
||||||
@ -56,7 +97,7 @@ const render = (props) => {
|
|||||||
userFeeLevel: 'tenPercentIncreased',
|
userFeeLevel: 'tenPercentIncreased',
|
||||||
txParams: {
|
txParams: {
|
||||||
gas: '0x5208',
|
gas: '0x5208',
|
||||||
maxFeePerGas: '0x59682f10',
|
maxFeePerGas,
|
||||||
maxPriorityFeePerGas: '0x59682f00',
|
maxPriorityFeePerGas: '0x59682f00',
|
||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
@ -80,12 +121,32 @@ describe('CancelSpeedupPopover', () => {
|
|||||||
expect(screen.queryByText('🚀Speed Up')).toBeInTheDocument();
|
expect(screen.queryByText('🚀Speed Up')).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should show correct gas values', async () => {
|
it('should show correct gas values, increased by 10%, when initial initial gas value is above estimated medium', async () => {
|
||||||
await act(async () =>
|
await act(async () =>
|
||||||
render({
|
render(
|
||||||
|
{
|
||||||
editGasMode: EDIT_GAS_MODES.SPEED_UP,
|
editGasMode: EDIT_GAS_MODES.SPEED_UP,
|
||||||
}),
|
},
|
||||||
|
MAXFEEPERGAS_ABOVE_MOCK_MEDIUM_HEX,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
expect(screen.queryAllByTitle('0.0000315 ETH').length).toBeGreaterThan(0);
|
expect(
|
||||||
|
screen.queryAllByTitle(`${EXPECTED_ETH_FEE_1} ETH`).length,
|
||||||
|
).toBeGreaterThan(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should show correct gas values, set to the estimated medium, when initial initial gas value is below estimated medium', async () => {
|
||||||
|
await act(async () =>
|
||||||
|
render(
|
||||||
|
{
|
||||||
|
editGasMode: EDIT_GAS_MODES.SPEED_UP,
|
||||||
|
},
|
||||||
|
`0x${MAXFEEPERGAS_BELOW_MOCK_MEDIUM_HEX}`,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(
|
||||||
|
screen.queryAllByTitle(`${EXPECTED_ETH_FEE_2} ETH`).length,
|
||||||
|
).toBeGreaterThan(0);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -1,7 +1,10 @@
|
|||||||
import { constant, times, uniq, zip } from 'lodash';
|
import { constant, times, uniq, zip } from 'lodash';
|
||||||
import BigNumber from 'bignumber.js';
|
import BigNumber from 'bignumber.js';
|
||||||
import { addHexPrefix } from 'ethereumjs-util';
|
import { addHexPrefix } from 'ethereumjs-util';
|
||||||
import { GAS_RECOMMENDATIONS } from '../../../shared/constants/gas';
|
import {
|
||||||
|
GAS_RECOMMENDATIONS,
|
||||||
|
EDIT_GAS_MODES,
|
||||||
|
} from '../../../shared/constants/gas';
|
||||||
import { multiplyCurrencies } from '../../../shared/modules/conversion.utils';
|
import { multiplyCurrencies } from '../../../shared/modules/conversion.utils';
|
||||||
import {
|
import {
|
||||||
bnGreaterThan,
|
bnGreaterThan,
|
||||||
@ -106,3 +109,16 @@ export function formatGasFeeOrFeeRange(
|
|||||||
|
|
||||||
return `${formattedRange} GWEI`;
|
return `${formattedRange} GWEI`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper method for determining whether an edit gas mode is either a speed up or cancel transaction
|
||||||
|
*
|
||||||
|
* @param {string | undefined} editGasMode - One of 'speed-up', 'cancel', 'modify-in-place', or 'swaps'
|
||||||
|
* @returns boolean
|
||||||
|
*/
|
||||||
|
export function editGasModeIsSpeedUpOrCancel(editGasMode) {
|
||||||
|
return (
|
||||||
|
editGasMode === EDIT_GAS_MODES.CANCEL ||
|
||||||
|
editGasMode === EDIT_GAS_MODES.SPEED_UP
|
||||||
|
);
|
||||||
|
}
|
||||||
|
@ -17,6 +17,7 @@ import { hexToDecimal } from '../../helpers/utils/conversions.util';
|
|||||||
import { isLegacyTransaction } from '../../helpers/utils/transactions.util';
|
import { isLegacyTransaction } from '../../helpers/utils/transactions.util';
|
||||||
import { useGasFeeEstimates } from '../useGasFeeEstimates';
|
import { useGasFeeEstimates } from '../useGasFeeEstimates';
|
||||||
|
|
||||||
|
import { editGasModeIsSpeedUpOrCancel } from '../../helpers/utils/gas';
|
||||||
import { useGasFeeErrors } from './useGasFeeErrors';
|
import { useGasFeeErrors } from './useGasFeeErrors';
|
||||||
import { useGasPriceInput } from './useGasPriceInput';
|
import { useGasPriceInput } from './useGasPriceInput';
|
||||||
import { useMaxFeePerGasInput } from './useMaxFeePerGasInput';
|
import { useMaxFeePerGasInput } from './useMaxFeePerGasInput';
|
||||||
@ -81,7 +82,7 @@ import { useTransactionFunctions } from './useTransactionFunctions';
|
|||||||
*
|
*
|
||||||
* @param {EstimateLevel} [defaultEstimateToUse] - which estimate
|
* @param {EstimateLevel} [defaultEstimateToUse] - which estimate
|
||||||
* level to default the 'estimateToUse' state variable to.
|
* level to default the 'estimateToUse' state variable to.
|
||||||
* @param {object} [transaction]
|
* @param {object} [_transaction]
|
||||||
* @param {string} [minimumGasLimit]
|
* @param {string} [minimumGasLimit]
|
||||||
* @param {EDIT_GAS_MODES[keyof EDIT_GAS_MODES]} editGasMode
|
* @param {EDIT_GAS_MODES[keyof EDIT_GAS_MODES]} editGasMode
|
||||||
* @returns {GasFeeInputReturnType & import(
|
* @returns {GasFeeInputReturnType & import(
|
||||||
@ -90,10 +91,28 @@ import { useTransactionFunctions } from './useTransactionFunctions';
|
|||||||
*/
|
*/
|
||||||
export function useGasFeeInputs(
|
export function useGasFeeInputs(
|
||||||
defaultEstimateToUse = GAS_RECOMMENDATIONS.MEDIUM,
|
defaultEstimateToUse = GAS_RECOMMENDATIONS.MEDIUM,
|
||||||
transaction,
|
_transaction,
|
||||||
minimumGasLimit = '0x5208',
|
minimumGasLimit = '0x5208',
|
||||||
editGasMode = EDIT_GAS_MODES.MODIFY_IN_PLACE,
|
editGasMode = EDIT_GAS_MODES.MODIFY_IN_PLACE,
|
||||||
) {
|
) {
|
||||||
|
const initialRetryTxMeta = {
|
||||||
|
txParams: _transaction?.txParams,
|
||||||
|
id: _transaction?.id,
|
||||||
|
userFeeLevel: _transaction?.userFeeLevel,
|
||||||
|
originalGasEstimate: _transaction?.originalGasEstimate,
|
||||||
|
userEditedGasLimit: _transaction?.userEditedGasLimit,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (_transaction?.previousGas) {
|
||||||
|
initialRetryTxMeta.previousGas = _transaction?.previousGas;
|
||||||
|
}
|
||||||
|
|
||||||
|
const [retryTxMeta, setRetryTxMeta] = useState(initialRetryTxMeta);
|
||||||
|
|
||||||
|
const transaction = editGasModeIsSpeedUpOrCancel(editGasMode)
|
||||||
|
? retryTxMeta
|
||||||
|
: _transaction;
|
||||||
|
|
||||||
const eip1559V2Enabled = useSelector(getEIP1559V2Enabled);
|
const eip1559V2Enabled = useSelector(getEIP1559V2Enabled);
|
||||||
|
|
||||||
const supportsEIP1559 =
|
const supportsEIP1559 =
|
||||||
@ -272,6 +291,7 @@ export function useGasFeeInputs(
|
|||||||
maxPriorityFeePerGas,
|
maxPriorityFeePerGas,
|
||||||
minimumGasLimit,
|
minimumGasLimit,
|
||||||
transaction,
|
transaction,
|
||||||
|
setRetryTxMeta,
|
||||||
});
|
});
|
||||||
|
|
||||||
// When a user selects an estimate level, it will wipe out what they have
|
// When a user selects an estimate level, it will wipe out what they have
|
||||||
|
@ -6,7 +6,10 @@ import {
|
|||||||
decimalToHex,
|
decimalToHex,
|
||||||
decGWEIToHexWEI,
|
decGWEIToHexWEI,
|
||||||
} from '../../helpers/utils/conversions.util';
|
} from '../../helpers/utils/conversions.util';
|
||||||
import { addTenPercentAndRound } from '../../helpers/utils/gas';
|
import {
|
||||||
|
addTenPercentAndRound,
|
||||||
|
editGasModeIsSpeedUpOrCancel,
|
||||||
|
} from '../../helpers/utils/gas';
|
||||||
import {
|
import {
|
||||||
createCancelTransaction,
|
createCancelTransaction,
|
||||||
createSpeedUpTransaction,
|
createSpeedUpTransaction,
|
||||||
@ -24,6 +27,7 @@ export const useTransactionFunctions = ({
|
|||||||
gasLimit: gasLimitValue,
|
gasLimit: gasLimitValue,
|
||||||
maxPriorityFeePerGas: maxPriorityFeePerGasValue,
|
maxPriorityFeePerGas: maxPriorityFeePerGasValue,
|
||||||
transaction,
|
transaction,
|
||||||
|
setRetryTxMeta,
|
||||||
}) => {
|
}) => {
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
|
|
||||||
@ -87,6 +91,8 @@ export const useTransactionFunctions = ({
|
|||||||
updateSwapsUserFeeLevel(estimateUsed || PRIORITY_LEVELS.CUSTOM),
|
updateSwapsUserFeeLevel(estimateUsed || PRIORITY_LEVELS.CUSTOM),
|
||||||
);
|
);
|
||||||
dispatch(updateCustomSwapsEIP1559GasParams(newGasSettings));
|
dispatch(updateCustomSwapsEIP1559GasParams(newGasSettings));
|
||||||
|
} else if (editGasModeIsSpeedUpOrCancel(editGasMode)) {
|
||||||
|
setRetryTxMeta(updatedTxMeta);
|
||||||
} else {
|
} else {
|
||||||
newGasSettings.userEditedGasLimit = updatedTxMeta.userEditedGasLimit;
|
newGasSettings.userEditedGasLimit = updatedTxMeta.userEditedGasLimit;
|
||||||
newGasSettings.userFeeLevel = updatedTxMeta.userFeeLevel;
|
newGasSettings.userFeeLevel = updatedTxMeta.userFeeLevel;
|
||||||
@ -110,6 +116,7 @@ export const useTransactionFunctions = ({
|
|||||||
getTxMeta,
|
getTxMeta,
|
||||||
maxPriorityFeePerGasValue,
|
maxPriorityFeePerGasValue,
|
||||||
transaction,
|
transaction,
|
||||||
|
setRetryTxMeta,
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user