1
0
mirror of https://github.com/kremalicious/metamask-extension.git synced 2024-10-22 19:26:13 +02:00
metamask-extension/ui/hooks/useGasFeeEstimates.test.js
Brad Decker e0953d9f68
Update send and confirm state management, and tx controller gas defaults, for EIP1559 (#11549)
wip

Documentation improvements for send slice support of EIP1559

Remove console.log in send duck

Property lookup safety improvement in selectors/confirm-transaction

Add code accidentally removed in rebase

Update addTxGasDefaults and _getDefaultGasFees to work with new estimate types, and ensure we correctly handle gas price estimates when on EIP1559 networks (#11615)

* Fix typo

Remove console.log in send duck

* Update addTxGasDefaults and _getDefaultGasFees to work correctly with all new gas fee estimate types

* Don't show gas timing support when not on eip1559 compatible network

* Hide gas timing component on transaction screen when on a non-1559 network

* Improve comments, tests and edge case handling

* Ensure eip1559 fees are applied and updated correctly when eip1559 estimate api fails

* Lint fix

Co-authored-by: Brad Decker <git@braddecker.dev>

Remove console.log

Handle possible gasEstimateType undefined

Remove unnecessary nonce field position change in confirm-page-container-content__details
2021-07-30 22:15:18 -02:30

239 lines
6.8 KiB
JavaScript

import { cleanup, renderHook } from '@testing-library/react-hooks';
import { useSelector } from 'react-redux';
import { GAS_ESTIMATE_TYPES } from '../../shared/constants/gas';
import createRandomId from '../../shared/modules/random-id';
import {
getGasEstimateType,
getGasFeeEstimates,
isEIP1559Network,
} from '../ducks/metamask/metamask';
import {
disconnectGasFeeEstimatePoller,
getGasFeeEstimatesAndStartPolling,
} from '../store/actions';
import { useGasFeeEstimates } from './useGasFeeEstimates';
jest.mock('../store/actions', () => ({
disconnectGasFeeEstimatePoller: jest.fn(),
getGasFeeEstimatesAndStartPolling: jest.fn(),
}));
jest.mock('react-redux', () => {
const actual = jest.requireActual('react-redux');
return {
...actual,
useSelector: jest.fn(),
};
});
const DEFAULT_OPTS = {
isEIP1559Network: false,
gasEstimateType: GAS_ESTIMATE_TYPES.LEGACY,
gasFeeEstimates: {
low: '10',
medium: '20',
high: '30',
},
};
const generateUseSelectorRouter = (opts = DEFAULT_OPTS) => (selector) => {
if (selector === isEIP1559Network) {
return opts.isEIP1559Network ?? DEFAULT_OPTS.isEIP1559Network;
}
if (selector === getGasEstimateType) {
return opts.gasEstimateType ?? DEFAULT_OPTS.gasEstimateType;
}
if (selector === getGasFeeEstimates) {
return opts.gasFeeEstimates ?? DEFAULT_OPTS.gasFeeEstimates;
}
return undefined;
};
describe('useGasFeeEstimates', () => {
let tokens = [];
beforeEach(() => {
jest.clearAllMocks();
tokens = [];
getGasFeeEstimatesAndStartPolling.mockImplementation(() => {
const token = createRandomId();
tokens.push(token);
return Promise.resolve(token);
});
disconnectGasFeeEstimatePoller.mockImplementation((token) => {
tokens = tokens.filter((tkn) => tkn !== token);
});
useSelector.mockImplementation(generateUseSelectorRouter());
});
it('registers with the controller', () => {
renderHook(() => useGasFeeEstimates());
expect(tokens).toHaveLength(1);
});
it('clears token with the controller on unmount', async () => {
renderHook(() => useGasFeeEstimates());
expect(tokens).toHaveLength(1);
const expectedToken = tokens[0];
await cleanup();
expect(getGasFeeEstimatesAndStartPolling).toHaveBeenCalledTimes(1);
expect(disconnectGasFeeEstimatePoller).toHaveBeenCalledWith(expectedToken);
expect(tokens).toHaveLength(0);
});
it('works with LEGACY gas prices', () => {
const {
result: { current },
} = renderHook(() => useGasFeeEstimates());
expect(current).toMatchObject({
gasFeeEstimates: DEFAULT_OPTS.gasFeeEstimates,
gasEstimateType: GAS_ESTIMATE_TYPES.LEGACY,
estimatedGasFeeTimeBounds: undefined,
isGasEstimatesLoading: false,
});
});
it('works with ETH_GASPRICE gas prices', () => {
const gasFeeEstimates = { gasPrice: '10' };
useSelector.mockImplementation(
generateUseSelectorRouter({
gasEstimateType: GAS_ESTIMATE_TYPES.ETH_GASPRICE,
gasFeeEstimates,
}),
);
const {
result: { current },
} = renderHook(() => useGasFeeEstimates());
expect(current).toMatchObject({
gasFeeEstimates,
gasEstimateType: GAS_ESTIMATE_TYPES.ETH_GASPRICE,
estimatedGasFeeTimeBounds: undefined,
isGasEstimatesLoading: false,
});
});
it('works with FEE_MARKET gas prices', () => {
const gasFeeEstimates = {
low: {
minWaitTimeEstimate: 180000,
maxWaitTimeEstimate: 300000,
suggestedMaxPriorityFeePerGas: '3',
suggestedMaxFeePerGas: '53',
},
medium: {
minWaitTimeEstimate: 15000,
maxWaitTimeEstimate: 60000,
suggestedMaxPriorityFeePerGas: '7',
suggestedMaxFeePerGas: '70',
},
high: {
minWaitTimeEstimate: 0,
maxWaitTimeEstimate: 15000,
suggestedMaxPriorityFeePerGas: '10',
suggestedMaxFeePerGas: '100',
},
estimatedBaseFee: '50',
};
useSelector.mockImplementation(
generateUseSelectorRouter({
isEIP1559Network: true,
gasEstimateType: GAS_ESTIMATE_TYPES.FEE_MARKET,
gasFeeEstimates,
}),
);
const {
result: { current },
} = renderHook(() => useGasFeeEstimates());
expect(current).toMatchObject({
gasFeeEstimates,
gasEstimateType: GAS_ESTIMATE_TYPES.FEE_MARKET,
estimatedGasFeeTimeBounds: undefined,
isGasEstimatesLoading: false,
});
});
it('indicates that gas estimates are loading when gasEstimateType is NONE', () => {
useSelector.mockImplementation(
generateUseSelectorRouter({
gasEstimateType: GAS_ESTIMATE_TYPES.NONE,
gasFeeEstimates: {},
}),
);
const {
result: { current },
} = renderHook(() => useGasFeeEstimates());
expect(current).toMatchObject({
gasFeeEstimates: {},
gasEstimateType: GAS_ESTIMATE_TYPES.NONE,
estimatedGasFeeTimeBounds: undefined,
isGasEstimatesLoading: true,
});
});
it('indicates that gas estimates are loading when gasEstimateType is not FEE_MARKET or ETH_GASPRICE, but network supports EIP-1559', () => {
useSelector.mockImplementation(
generateUseSelectorRouter({
isEIP1559Network: true,
gasEstimateType: GAS_ESTIMATE_TYPES.LEGACY,
gasFeeEstimates: {
gasPrice: '10',
},
}),
);
const {
result: { current },
} = renderHook(() => useGasFeeEstimates());
expect(current).toMatchObject({
gasFeeEstimates: { gasPrice: '10' },
gasEstimateType: GAS_ESTIMATE_TYPES.LEGACY,
estimatedGasFeeTimeBounds: undefined,
isGasEstimatesLoading: true,
});
});
it('indicates that gas estimates are loading when gasEstimateType is FEE_MARKET but network does not support EIP-1559', () => {
const gasFeeEstimates = {
low: {
minWaitTimeEstimate: 180000,
maxWaitTimeEstimate: 300000,
suggestedMaxPriorityFeePerGas: '3',
suggestedMaxFeePerGas: '53',
},
medium: {
minWaitTimeEstimate: 15000,
maxWaitTimeEstimate: 60000,
suggestedMaxPriorityFeePerGas: '7',
suggestedMaxFeePerGas: '70',
},
high: {
minWaitTimeEstimate: 0,
maxWaitTimeEstimate: 15000,
suggestedMaxPriorityFeePerGas: '10',
suggestedMaxFeePerGas: '100',
},
estimatedBaseFee: '50',
};
useSelector.mockImplementation(
generateUseSelectorRouter({
isEIP1559Network: false,
gasEstimateType: GAS_ESTIMATE_TYPES.FEE_MARKET,
gasFeeEstimates,
}),
);
const {
result: { current },
} = renderHook(() => useGasFeeEstimates());
expect(current).toMatchObject({
gasFeeEstimates,
gasEstimateType: GAS_ESTIMATE_TYPES.FEE_MARKET,
estimatedGasFeeTimeBounds: undefined,
isGasEstimatesLoading: true,
});
});
});