using 1559 V2 for cancel speed up flows (#13019)
parent
dbfdf3b0eb
commit
f5dcd12293
@ -0,0 +1,30 @@ |
||||
import { useSelector } from 'react-redux'; |
||||
import PropTypes from 'prop-types'; |
||||
import React from 'react'; |
||||
|
||||
import { getAppIsLoading } from '../../../selectors'; |
||||
import Spinner from '../../ui/spinner'; |
||||
|
||||
const AppLoadingSpinner = ({ className }) => { |
||||
const appIsLoading = useSelector(getAppIsLoading); |
||||
|
||||
if (!appIsLoading) { |
||||
return null; |
||||
} |
||||
|
||||
return ( |
||||
<div |
||||
className={`${className} app-loading-spinner`} |
||||
role="alert" |
||||
aria-busy="true" |
||||
> |
||||
<Spinner color="#F7C06C" className="app-loading-spinner__inner" /> |
||||
</div> |
||||
); |
||||
}; |
||||
|
||||
AppLoadingSpinner.propTypes = { |
||||
className: PropTypes.string, |
||||
}; |
||||
|
||||
export default AppLoadingSpinner; |
@ -0,0 +1,27 @@ |
||||
import React from 'react'; |
||||
import { screen } from '@testing-library/react'; |
||||
|
||||
import { renderWithProvider } from '../../../../test/lib/render-helpers'; |
||||
import configureStore from '../../../store/store'; |
||||
|
||||
import AppLoadingSpinner from './app-loading-spinner'; |
||||
|
||||
const render = (params) => { |
||||
const store = configureStore({ |
||||
...params, |
||||
}); |
||||
|
||||
return renderWithProvider(<AppLoadingSpinner />, store); |
||||
}; |
||||
|
||||
describe('AppLoadingSpinner', () => { |
||||
it('should return null if app state is not loading', () => { |
||||
render(); |
||||
expect(screen.queryByRole('alert')).not.toBeInTheDocument(); |
||||
}); |
||||
|
||||
it('should show spinner if app state is loading', () => { |
||||
render({ appState: { isLoading: true } }); |
||||
expect(screen.queryByRole('alert')).toBeInTheDocument(); |
||||
}); |
||||
}); |
@ -0,0 +1 @@ |
||||
export { default } from './app-loading-spinner'; |
@ -0,0 +1,13 @@ |
||||
.app-loading-spinner { |
||||
background-color: rgba(255, 255, 255, 0.75); |
||||
display: flex; |
||||
align-items: center; |
||||
justify-content: center; |
||||
position: absolute; |
||||
height: 100%; |
||||
width: 100%; |
||||
|
||||
&__inner { |
||||
width: 50px; |
||||
} |
||||
} |
@ -0,0 +1,159 @@ |
||||
import { useSelector } from 'react-redux'; |
||||
import React, { useEffect } from 'react'; |
||||
|
||||
import { |
||||
EDIT_GAS_MODES, |
||||
PRIORITY_LEVELS, |
||||
} from '../../../../shared/constants/gas'; |
||||
import { |
||||
ALIGN_ITEMS, |
||||
DISPLAY, |
||||
FLEX_DIRECTION, |
||||
TYPOGRAPHY, |
||||
} from '../../../helpers/constants/design-system'; |
||||
import { getAppIsLoading } from '../../../selectors'; |
||||
import { gasEstimateGreaterThanGasUsedPlusTenPercent } from '../../../helpers/utils/gas'; |
||||
import { useGasFeeContext } from '../../../contexts/gasFee'; |
||||
import { useI18nContext } from '../../../hooks/useI18nContext'; |
||||
import { useTransactionModalContext } from '../../../contexts/transaction-modal'; |
||||
import EditGasFeeButton from '../edit-gas-fee-button'; |
||||
import GasDetailsItem from '../gas-details-item'; |
||||
import Box from '../../ui/box'; |
||||
import Button from '../../ui/button'; |
||||
import I18nValue from '../../ui/i18n-value'; |
||||
import InfoTooltip from '../../ui/info-tooltip'; |
||||
import Popover from '../../ui/popover'; |
||||
import Typography from '../../ui/typography'; |
||||
import AppLoadingSpinner from '../app-loading-spinner'; |
||||
|
||||
const CancelSpeedupPopover = () => { |
||||
const { |
||||
cancelTransaction, |
||||
editGasMode, |
||||
gasFeeEstimates, |
||||
speedUpTransaction, |
||||
transaction, |
||||
updateTransaction, |
||||
updateTransactionToMinimumGasFee, |
||||
updateTransactionUsingEstimate, |
||||
} = useGasFeeContext(); |
||||
const t = useI18nContext(); |
||||
const { closeModal, currentModal } = useTransactionModalContext(); |
||||
const appIsLoading = useSelector(getAppIsLoading); |
||||
|
||||
useEffect(() => { |
||||
if ( |
||||
transaction.previousGas || |
||||
appIsLoading || |
||||
currentModal !== 'cancelSpeedUpTransaction' |
||||
) { |
||||
return; |
||||
} |
||||
// If gas used previously + 10% is less than medium estimated gas
|
||||
// estimate is set to medium, else estimate is set to minimum
|
||||
const gasUsedLessThanMedium = |
||||
gasFeeEstimates && |
||||
gasEstimateGreaterThanGasUsedPlusTenPercent( |
||||
transaction, |
||||
gasFeeEstimates, |
||||
PRIORITY_LEVELS.MEDIUM, |
||||
); |
||||
if (gasUsedLessThanMedium) { |
||||
updateTransactionUsingEstimate(PRIORITY_LEVELS.MEDIUM); |
||||
return; |
||||
} |
||||
updateTransactionToMinimumGasFee(); |
||||
}, [ |
||||
appIsLoading, |
||||
currentModal, |
||||
editGasMode, |
||||
gasFeeEstimates, |
||||
transaction, |
||||
updateTransaction, |
||||
updateTransactionToMinimumGasFee, |
||||
updateTransactionUsingEstimate, |
||||
]); |
||||
|
||||
if (currentModal !== 'cancelSpeedUpTransaction') { |
||||
return null; |
||||
} |
||||
|
||||
const submitTransactionChange = () => { |
||||
if (editGasMode === EDIT_GAS_MODES.CANCEL) { |
||||
cancelTransaction(); |
||||
} else { |
||||
speedUpTransaction(); |
||||
} |
||||
closeModal('cancelSpeedUpTransaction'); |
||||
}; |
||||
|
||||
return ( |
||||
<Popover |
||||
title={ |
||||
<> |
||||
{editGasMode === EDIT_GAS_MODES.CANCEL |
||||
? `❌${t('cancel')}` |
||||
: `🚀${t('speedUp')}`} |
||||
</> |
||||
} |
||||
onClose={() => closeModal('cancelSpeedUpTransaction')} |
||||
className="cancel-speedup-popover" |
||||
> |
||||
<AppLoadingSpinner className="cancel-speedup-popover__spinner" /> |
||||
<div className="cancel-speedup-popover__wrapper"> |
||||
<Typography |
||||
boxProps={{ alignItems: ALIGN_ITEMS.CENTER, display: DISPLAY.FLEX }} |
||||
variant={TYPOGRAPHY.H6} |
||||
margin={[0, 0, 2, 0]} |
||||
> |
||||
<I18nValue |
||||
messageKey="cancelSpeedUpLabel" |
||||
options={[ |
||||
<strong key="cancelSpeedupReplace"> |
||||
<I18nValue messageKey="replace" /> |
||||
</strong>, |
||||
]} |
||||
/> |
||||
<InfoTooltip |
||||
position="top" |
||||
contentText={ |
||||
<Box> |
||||
{t('cancelSpeedUpTransactionTooltip', [ |
||||
EDIT_GAS_MODES.CANCEL ? t('cancel') : t('speedUp'), |
||||
])} |
||||
<div> |
||||
<a |
||||
href="https://community.metamask.io/t/how-to-speed-up-or-cancel-transactions-on-metamask/3296" |
||||
target="_blank" |
||||
rel="noopener noreferrer" |
||||
> |
||||
{t('learnMoreUpperCase')} |
||||
</a> |
||||
</div> |
||||
</Box> |
||||
} |
||||
/> |
||||
</Typography> |
||||
<div className="cancel-speedup-popover__separator" /> |
||||
<Box |
||||
display={DISPLAY.FLEX} |
||||
alignItems={ALIGN_ITEMS.CENTER} |
||||
flexDirection={FLEX_DIRECTION.COLUMN} |
||||
marginTop={4} |
||||
> |
||||
<Box className="cancel-speedup-popover__edit-gas-button"> |
||||
<EditGasFeeButton /> |
||||
</Box> |
||||
<Box className="cancel-speedup-popover__gas-details"> |
||||
<GasDetailsItem /> |
||||
</Box> |
||||
</Box> |
||||
<Button type="primary" onClick={submitTransactionChange}> |
||||
<I18nValue messageKey="submit" /> |
||||
</Button> |
||||
</div> |
||||
</Popover> |
||||
); |
||||
}; |
||||
|
||||
export default CancelSpeedupPopover; |
@ -0,0 +1,88 @@ |
||||
import React from 'react'; |
||||
import { act, screen } from '@testing-library/react'; |
||||
|
||||
import { |
||||
EDIT_GAS_MODES, |
||||
GAS_ESTIMATE_TYPES, |
||||
} from '../../../../shared/constants/gas'; |
||||
import { renderWithProvider } from '../../../../test/lib/render-helpers'; |
||||
import mockEstimates from '../../../../test/data/mock-estimates.json'; |
||||
import mockState from '../../../../test/data/mock-state.json'; |
||||
import { GasFeeContextProvider } from '../../../contexts/gasFee'; |
||||
import configureStore from '../../../store/store'; |
||||
|
||||
import CancelSpeedupPopover from './cancel-speedup-popover'; |
||||
|
||||
jest.mock('../../../store/actions', () => ({ |
||||
disconnectGasFeeEstimatePoller: jest.fn(), |
||||
getGasFeeTimeEstimate: jest.fn().mockImplementation(() => Promise.resolve()), |
||||
getGasFeeEstimatesAndStartPolling: jest |
||||
.fn() |
||||
.mockImplementation(() => Promise.resolve()), |
||||
addPollingTokenToAppState: jest.fn(), |
||||
removePollingTokenFromAppState: jest.fn(), |
||||
updateTransaction: () => ({ type: 'UPDATE_TRANSACTION_PARAMS' }), |
||||
})); |
||||
|
||||
jest.mock('../../../contexts/transaction-modal', () => ({ |
||||
useTransactionModalContext: () => ({ |
||||
closeModal: () => undefined, |
||||
currentModal: 'cancelSpeedUpTransaction', |
||||
}), |
||||
})); |
||||
|
||||
const render = (props) => { |
||||
const store = configureStore({ |
||||
metamask: { |
||||
...mockState.metamask, |
||||
accounts: { |
||||
[mockState.metamask.selectedAddress]: { |
||||
address: mockState.metamask.selectedAddress, |
||||
balance: '0x1F4', |
||||
}, |
||||
}, |
||||
featureFlags: { advancedInlineGas: true }, |
||||
gasFeeEstimates: |
||||
mockEstimates[GAS_ESTIMATE_TYPES.FEE_MARKET].gasFeeEstimates, |
||||
}, |
||||
}); |
||||
|
||||
return renderWithProvider( |
||||
<GasFeeContextProvider |
||||
transaction={{ |
||||
userFeeLevel: 'minimum', |
||||
txParams: { |
||||
gas: '0x5208', |
||||
maxFeePerGas: '0x59682f10', |
||||
maxPriorityFeePerGas: '0x59682f00', |
||||
}, |
||||
}} |
||||
editGasMode={EDIT_GAS_MODES.CANCEL} |
||||
{...props} |
||||
> |
||||
<CancelSpeedupPopover /> |
||||
</GasFeeContextProvider>, |
||||
store, |
||||
); |
||||
}; |
||||
|
||||
describe('CancelSpeedupPopover', () => { |
||||
it('should have ❌Cancel in header if editGasMode is cancel', async () => { |
||||
await act(async () => render()); |
||||
expect(screen.queryByText('❌Cancel')).toBeInTheDocument(); |
||||
}); |
||||
|
||||
it('should have 🚀Speed Up in header if editGasMode is speedup', async () => { |
||||
await act(async () => render({ editGasMode: EDIT_GAS_MODES.SPEED_UP })); |
||||
expect(screen.queryByText('🚀Speed Up')).toBeInTheDocument(); |
||||
}); |
||||
|
||||
it('should show correct gas values', async () => { |
||||
await act(async () => |
||||
render({ |
||||
editGasMode: EDIT_GAS_MODES.SPEED_UP, |
||||
}), |
||||
); |
||||
expect(screen.queryAllByTitle('0.0000315 ETH').length).toBeGreaterThan(0); |
||||
}); |
||||
}); |
@ -0,0 +1 @@ |
||||
export { default } from './cancel-speedup-popover'; |
@ -0,0 +1,27 @@ |
||||
.cancel-speedup-popover { |
||||
&__wrapper { |
||||
padding: 0 16px 16px; |
||||
|
||||
.info-tooltip { |
||||
margin-left: 4px; |
||||
} |
||||
} |
||||
|
||||
&__edit-gas-button { |
||||
align-self: flex-end; |
||||
} |
||||
|
||||
&__gas-details { |
||||
padding-top: 10px; |
||||
} |
||||
|
||||
&__spinner { |
||||
margin-top: -30px; |
||||
height: calc(100% + 30px); |
||||
} |
||||
|
||||
&__separator { |
||||
border-bottom: 1px solid $ui-grey; |
||||
width: 100%; |
||||
} |
||||
} |
@ -0,0 +1,126 @@ |
||||
import { useEffect, useState } from 'react'; |
||||
import { useSelector } from 'react-redux'; |
||||
|
||||
import { |
||||
EDIT_GAS_MODES, |
||||
PRIORITY_LEVELS, |
||||
} from '../../../../../shared/constants/gas'; |
||||
import { getMaximumGasTotalInHexWei } from '../../../../../shared/modules/gas.utils'; |
||||
import { |
||||
decGWEIToHexWEI, |
||||
decimalToHex, |
||||
hexWEIToDecGWEI, |
||||
} from '../../../../helpers/utils/conversions.util'; |
||||
import { |
||||
addTenPercentAndRound, |
||||
gasEstimateGreaterThanGasUsedPlusTenPercent, |
||||
} from '../../../../helpers/utils/gas'; |
||||
import { getAdvancedGasFeeValues } from '../../../../selectors'; |
||||
import { useGasFeeContext } from '../../../../contexts/gasFee'; |
||||
import { useCustomTimeEstimate } from './useCustomTimeEstimate'; |
||||
|
||||
export const useGasItemFeeDetails = (priorityLevel) => { |
||||
const { |
||||
editGasMode, |
||||
estimateUsed, |
||||
gasFeeEstimates, |
||||
gasLimit, |
||||
maxFeePerGas: maxFeePerGasValue, |
||||
maxPriorityFeePerGas: maxPriorityFeePerGasValue, |
||||
transaction, |
||||
} = useGasFeeContext(); |
||||
const [estimateGreaterThanGasUse, setEstimateGreaterThanGasUse] = useState( |
||||
false, |
||||
); |
||||
const advancedGasFeeValues = useSelector(getAdvancedGasFeeValues); |
||||
|
||||
let maxFeePerGas; |
||||
let maxPriorityFeePerGas; |
||||
let minWaitTime; |
||||
|
||||
const { dappSuggestedGasFees } = transaction; |
||||
|
||||
if (gasFeeEstimates?.[priorityLevel]) { |
||||
maxFeePerGas = gasFeeEstimates[priorityLevel].suggestedMaxFeePerGas; |
||||
maxPriorityFeePerGas = |
||||
gasFeeEstimates[priorityLevel].suggestedMaxPriorityFeePerGas; |
||||
} else if ( |
||||
priorityLevel === PRIORITY_LEVELS.DAPP_SUGGESTED && |
||||
dappSuggestedGasFees |
||||
) { |
||||
maxFeePerGas = hexWEIToDecGWEI( |
||||
dappSuggestedGasFees.maxFeePerGas || dappSuggestedGasFees.gasPrice, |
||||
); |
||||
maxPriorityFeePerGas = hexWEIToDecGWEI( |
||||
dappSuggestedGasFees.maxPriorityFeePerGas || maxFeePerGas, |
||||
); |
||||
} else if (priorityLevel === PRIORITY_LEVELS.CUSTOM) { |
||||
if (estimateUsed === PRIORITY_LEVELS.CUSTOM) { |
||||
maxFeePerGas = maxFeePerGasValue; |
||||
maxPriorityFeePerGas = maxPriorityFeePerGasValue; |
||||
} else if (advancedGasFeeValues) { |
||||
maxFeePerGas = |
||||
gasFeeEstimates.estimatedBaseFee * |
||||
parseFloat(advancedGasFeeValues.maxBaseFee); |
||||
maxPriorityFeePerGas = advancedGasFeeValues.priorityFee; |
||||
} |
||||
} else if ( |
||||
priorityLevel === PRIORITY_LEVELS.MINIMUM && |
||||
transaction.previousGas |
||||
) { |
||||
maxFeePerGas = hexWEIToDecGWEI( |
||||
addTenPercentAndRound(transaction.previousGas?.maxFeePerGas), |
||||
); |
||||
maxPriorityFeePerGas = hexWEIToDecGWEI( |
||||
addTenPercentAndRound(transaction.previousGas?.maxPriorityFeePerGas), |
||||
); |
||||
} |
||||
|
||||
const { waitTimeEstimate } = useCustomTimeEstimate({ |
||||
gasFeeEstimates, |
||||
maxFeePerGas, |
||||
maxPriorityFeePerGas, |
||||
}); |
||||
|
||||
if (gasFeeEstimates[priorityLevel]) { |
||||
minWaitTime = |
||||
priorityLevel === PRIORITY_LEVELS.HIGH |
||||
? gasFeeEstimates?.high.minWaitTimeEstimate |
||||
: gasFeeEstimates?.low.maxWaitTimeEstimate; |
||||
} else { |
||||
minWaitTime = waitTimeEstimate; |
||||
} |
||||
|
||||
const hexMaximumTransactionFee = maxFeePerGas |
||||
? getMaximumGasTotalInHexWei({ |
||||
gasLimit: decimalToHex(gasLimit), |
||||
maxFeePerGas: decGWEIToHexWEI(maxFeePerGas), |
||||
}) |
||||
: null; |
||||
|
||||
useEffect(() => { |
||||
// For cancel and speed-up medium / high option is disabled if
|
||||
// gas used in transaction + 10% is greater tham estimate
|
||||
if ( |
||||
(editGasMode === EDIT_GAS_MODES.CANCEL || |
||||
editGasMode === EDIT_GAS_MODES.SPEED_UP) && |
||||
(priorityLevel === PRIORITY_LEVELS.MEDIUM || |
||||
priorityLevel === PRIORITY_LEVELS.HIGH) |
||||
) { |
||||
const estimateGreater = !gasEstimateGreaterThanGasUsedPlusTenPercent( |
||||
transaction, |
||||
gasFeeEstimates, |
||||
priorityLevel, |
||||
); |
||||
setEstimateGreaterThanGasUse(estimateGreater); |
||||
} |
||||
}, [editGasMode, gasFeeEstimates, priorityLevel, transaction]); |
||||
|
||||
return { |
||||
estimateGreaterThanGasUse, |
||||
maxFeePerGas, |
||||
maxPriorityFeePerGas, |
||||
minWaitTime, |
||||
hexMaximumTransactionFee, |
||||
}; |
||||
}; |
@ -0,0 +1,52 @@ |
||||
import BigNumber from 'bignumber.js'; |
||||
import { addHexPrefix } from 'ethereumjs-util'; |
||||
|
||||
import { multiplyCurrencies } from '../../../shared/modules/conversion.utils'; |
||||
import { bnGreaterThan } from './util'; |
||||
import { hexWEIToDecGWEI } from './conversions.util'; |
||||
|
||||
export const gasEstimateGreaterThanGasUsedPlusTenPercent = ( |
||||
transaction, |
||||
gasFeeEstimates, |
||||
estimate, |
||||
) => { |
||||
let { maxFeePerGas: maxFeePerGasInTransaction } = transaction.txParams; |
||||
maxFeePerGasInTransaction = new BigNumber( |
||||
hexWEIToDecGWEI(addTenPercentAndRound(maxFeePerGasInTransaction)), |
||||
); |
||||
|
||||
const maxFeePerGasFromEstimate = |
||||
gasFeeEstimates[estimate]?.suggestedMaxFeePerGas; |
||||
return bnGreaterThan(maxFeePerGasFromEstimate, maxFeePerGasInTransaction); |
||||
}; |
||||
|
||||
/** |
||||
* Simple helper to save on duplication to multiply the supplied wei hex string |
||||
* by 1.10 to get bare minimum new gas fee. |
||||
* |
||||
* @param {string | undefined} hexStringValue - hex value in wei to be incremented |
||||
* @returns {string | undefined} - hex value in WEI 10% higher than the param. |
||||
*/ |
||||
export function addTenPercent(hexStringValue, conversionOptions = {}) { |
||||
if (hexStringValue === undefined) return undefined; |
||||
return addHexPrefix( |
||||
multiplyCurrencies(hexStringValue, 1.1, { |
||||
toNumericBase: 'hex', |
||||
multiplicandBase: 16, |
||||
multiplierBase: 10, |
||||
numberOfDecimals: 0, |
||||
...conversionOptions, |
||||
}), |
||||
); |
||||
} |
||||
|
||||
/** |
||||
* Simple helper to save on duplication to multiply the supplied wei hex string |
||||
* by 1.10 to get bare minimum new gas fee. |
||||
* |
||||
* @param {string | undefined} hexStringValue - hex value in wei to be incremented |
||||
* @returns {string | undefined} - hex value in WEI 10% higher than the param. |
||||
*/ |
||||
export function addTenPercentAndRound(hexStringValue) { |
||||
return addTenPercent(hexStringValue, { numberOfDecimals: 0 }); |
||||
} |
@ -0,0 +1,52 @@ |
||||
import { PRIORITY_LEVELS } from '../../../shared/constants/gas'; |
||||
|
||||
import { |
||||
addTenPercent, |
||||
gasEstimateGreaterThanGasUsedPlusTenPercent, |
||||
} from './gas'; |
||||
|
||||
describe('Gas utils', () => { |
||||
describe('gasEstimateGreaterThanGasUsedPlusTenPercent', () => { |
||||
const compareGas = (estimateValues) => { |
||||
return gasEstimateGreaterThanGasUsedPlusTenPercent( |
||||
{ |
||||
txParams: { |
||||
maxFeePerGas: '0x59682f10', |
||||
maxPriorityFeePerGas: '0x59682f00', |
||||
}, |
||||
}, |
||||
{ |
||||
medium: estimateValues, |
||||
}, |
||||
PRIORITY_LEVELS.MEDIUM, |
||||
); |
||||
}; |
||||
|
||||
it('should return true if gas used in transaction + 10% is greater that estimate', () => { |
||||
const result = compareGas({ |
||||
suggestedMaxPriorityFeePerGas: '7', |
||||
suggestedMaxFeePerGas: '70', |
||||
}); |
||||
expect(result).toStrictEqual(true); |
||||
}); |
||||
|
||||
it('should return false if gas used in transaction + 10% is less that estimate', () => { |
||||
const result = compareGas({ |
||||
suggestedMaxPriorityFeePerGas: '.5', |
||||
suggestedMaxFeePerGas: '1', |
||||
}); |
||||
expect(result).toStrictEqual(false); |
||||
}); |
||||
}); |
||||
|
||||
describe('addTenPercent', () => { |
||||
it('should add 10% to hex value passed', () => { |
||||
const result = addTenPercent('0x59682f00'); |
||||
expect(result).toStrictEqual('0x62590080'); |
||||
}); |
||||
it('should return undefined if undefined value is passed', () => { |
||||
const result = addTenPercent(undefined); |
||||
expect(result).toBeUndefined(); |
||||
}); |
||||
}); |
||||
}); |
@ -0,0 +1,144 @@ |
||||
import React from 'react'; |
||||
import { Provider } from 'react-redux'; |
||||
import { renderHook } from '@testing-library/react-hooks'; |
||||
|
||||
import { |
||||
CUSTOM_GAS_ESTIMATE, |
||||
EDIT_GAS_MODES, |
||||
GAS_RECOMMENDATIONS, |
||||
} from '../../../shared/constants/gas'; |
||||
import mockState from '../../../test/data/mock-state.json'; |
||||
import * as Actions from '../../store/actions'; |
||||
import configureStore from '../../store/store'; |
||||
import { useGasFeeEstimates } from '../useGasFeeEstimates'; |
||||
import { FEE_MARKET_ESTIMATE_RETURN_VALUE } from './test-utils'; |
||||
import { useTransactionFunctions } from './useTransactionFunctions'; |
||||
|
||||
jest.mock('../useGasFeeEstimates', () => ({ |
||||
useGasFeeEstimates: jest.fn(), |
||||
})); |
||||
useGasFeeEstimates.mockImplementation(() => FEE_MARKET_ESTIMATE_RETURN_VALUE); |
||||
|
||||
jest.mock('../../selectors', () => ({ |
||||
checkNetworkAndAccountSupports1559: () => true, |
||||
})); |
||||
|
||||
const wrapper = ({ children }) => ( |
||||
<Provider store={configureStore(mockState)}>{children}</Provider> |
||||
); |
||||
|
||||
const renderUseTransactionFunctions = (props) => { |
||||
return renderHook( |
||||
() => |
||||
useTransactionFunctions({ |
||||
defaultEstimateToUse: GAS_RECOMMENDATIONS.MEDIUM, |
||||
editGasMode: EDIT_GAS_MODES.MODIFY_IN_PLACE, |
||||
estimatedBaseFee: '0x59682f10', |
||||
gasFeeEstimates: FEE_MARKET_ESTIMATE_RETURN_VALUE.gasFeeEstimates, |
||||
gasLimit: '21000', |
||||
maxPriorityFeePerGas: '0x59682f10', |
||||
transaction: { |
||||
userFeeLevel: CUSTOM_GAS_ESTIMATE, |
||||
txParams: { maxFeePerGas: '0x5028', maxPriorityFeePerGas: '0x5028' }, |
||||
}, |
||||
...props, |
||||
}), |
||||
{ wrapper }, |
||||
); |
||||
}; |
||||
|
||||
describe('useMaxPriorityFeePerGasInput', () => { |
||||
beforeEach(() => { |
||||
jest.clearAllMocks(); |
||||
}); |
||||
|
||||
it('should invoke action createCancelTransaction when cancelTransaction callback is invoked', () => { |
||||
const mock = jest |
||||
.spyOn(Actions, 'createCancelTransaction') |
||||
.mockImplementation(() => ({ type: '' })); |
||||
const { result } = renderUseTransactionFunctions(); |
||||
result.current.cancelTransaction(); |
||||
expect(mock).toHaveBeenCalledTimes(1); |
||||
}); |
||||
|
||||
it('should invoke action createSpeedUpTransaction when speedUpTransaction callback is invoked', () => { |
||||
const mock = jest |
||||
.spyOn(Actions, 'createSpeedUpTransaction') |
||||
.mockImplementation(() => ({ type: '' })); |
||||
const { result } = renderUseTransactionFunctions(); |
||||
result.current.speedUpTransaction(); |
||||
expect(mock).toHaveBeenCalledTimes(1); |
||||
}); |
||||
|
||||
it('should invoke action updateTransaction with 10% increased fee when updateTransactionToMinimumGasFee callback is invoked', () => { |
||||
const mock = jest |
||||
.spyOn(Actions, 'updateTransaction') |
||||
.mockImplementation(() => ({ type: '' })); |
||||
const { result } = renderUseTransactionFunctions(); |
||||
result.current.updateTransactionToMinimumGasFee(); |
||||
expect(mock).toHaveBeenCalledTimes(1); |
||||
expect(mock).toHaveBeenCalledWith({ |
||||
txParams: { |
||||
estimateSuggested: 'medium', |
||||
estimateUsed: 'minimum', |
||||
gas: '5208', |
||||
gasLimit: '5208', |
||||
maxFeePerGas: '0x582c', |
||||
maxPriorityFeePerGas: '0x582c', |
||||
}, |
||||
userFeeLevel: 'minimum', |
||||
}); |
||||
}); |
||||
|
||||
it('should invoke action updateTransaction with estimate gas values fee when updateTransactionUsingEstimate callback is invoked', () => { |
||||
const mock = jest |
||||
.spyOn(Actions, 'updateTransaction') |
||||
.mockImplementation(() => ({ type: '' })); |
||||
const { result } = renderUseTransactionFunctions(); |
||||
result.current.updateTransactionUsingEstimate(GAS_RECOMMENDATIONS.LOW); |
||||
expect(mock).toHaveBeenCalledTimes(1); |
||||
expect(mock).toHaveBeenCalledWith({ |
||||
txParams: { |
||||
estimateSuggested: 'medium', |
||||
estimateUsed: 'low', |
||||
gas: '5208', |
||||
gasLimit: '5208', |
||||
maxFeePerGas: 'c570bd200', |
||||
maxPriorityFeePerGas: 'b2d05e00', |
||||
}, |
||||
userFeeLevel: 'low', |
||||
}); |
||||
}); |
||||
|
||||
it('should invoke action updateTransaction with dappSuggestedValues values fee when updateTransactionUsingDAPPSuggestedValues callback is invoked', () => { |
||||
const mock = jest |
||||
.spyOn(Actions, 'updateTransaction') |
||||
.mockImplementation(() => ({ type: '' })); |
||||
const { result } = renderUseTransactionFunctions({ |
||||
transaction: { |
||||
userFeeLevel: CUSTOM_GAS_ESTIMATE, |
||||
dappSuggestedGasFees: { |
||||
maxFeePerGas: '0x5028', |
||||
maxPriorityFeePerGas: '0x5028', |
||||
}, |
||||
}, |
||||
}); |
||||
result.current.updateTransactionUsingDAPPSuggestedValues(); |
||||
expect(mock).toHaveBeenCalledTimes(1); |
||||
expect(mock).toHaveBeenCalledWith({ |
||||
dappSuggestedGasFees: { |
||||
maxFeePerGas: '0x5028', |
||||
maxPriorityFeePerGas: '0x5028', |
||||
}, |
||||
txParams: { |
||||
estimateSuggested: 'medium', |
||||
estimateUsed: 'dappSuggested', |
||||
gas: '5208', |
||||
gasLimit: '5208', |
||||
maxFeePerGas: '0x5028', |
||||
maxPriorityFeePerGas: '0x5028', |
||||
}, |
||||
userFeeLevel: 'dappSuggested', |
||||
}); |
||||
}); |
||||
}); |
Loading…
Reference in new issue