mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-12-23 09:52:26 +01:00
rely upon gas fee controller for gas price estimates (#11511)
This commit is contained in:
parent
3fada25dfc
commit
dc25a24de3
@ -162,6 +162,9 @@ export default class NetworkController extends EventEmitter {
|
|||||||
*/
|
*/
|
||||||
async getEIP1559Compatibility() {
|
async getEIP1559Compatibility() {
|
||||||
const { EIPS } = this.networkDetails.getState();
|
const { EIPS } = this.networkDetails.getState();
|
||||||
|
if (process.env.SHOW_EIP_1559_UI === false) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
if (EIPS[1559] !== undefined) {
|
if (EIPS[1559] !== undefined) {
|
||||||
return EIPS[1559];
|
return EIPS[1559];
|
||||||
}
|
}
|
||||||
|
@ -196,11 +196,17 @@ export default class MetamaskController extends EventEmitter {
|
|||||||
getCurrentAccountEIP1559Compatibility: this.getCurrentAccountEIP1559Compatibility.bind(
|
getCurrentAccountEIP1559Compatibility: this.getCurrentAccountEIP1559Compatibility.bind(
|
||||||
this,
|
this,
|
||||||
),
|
),
|
||||||
getCurrentNetworkLegacyGasAPICompatibility: () =>
|
legacyAPIEndpoint: `https://gas-api.metaswap.codefi.network/networks/<chain_id>/gasPrices`,
|
||||||
this.networkController.getCurrentChainId() === MAINNET_CHAIN_ID,
|
EIP1559APIEndpoint: `https://gas-api.metaswap.codefi.network/networks/<chain_id>/suggestedGasFees`,
|
||||||
getChainId: this.networkController.getCurrentChainId.bind(
|
getCurrentNetworkLegacyGasAPICompatibility: () => {
|
||||||
this.networkController,
|
const chainId = this.networkController.getCurrentChainId();
|
||||||
),
|
return process.env.IN_TEST || chainId === MAINNET_CHAIN_ID;
|
||||||
|
},
|
||||||
|
getChainId: () => {
|
||||||
|
return process.env.IN_TEST
|
||||||
|
? MAINNET_CHAIN_ID
|
||||||
|
: this.networkController.getCurrentChainId();
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
this.appStateController = new AppStateController({
|
this.appStateController = new AppStateController({
|
||||||
|
@ -1,22 +1,23 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import sinon from 'sinon';
|
import sinon from 'sinon';
|
||||||
import { shallowWithContext } from '../../../../../test/lib/render-helpers';
|
import { shallowWithContext } from '../../../../../test/lib/render-helpers';
|
||||||
|
import { getGasFeeEstimatesAndStartPolling } from '../../../../store/actions';
|
||||||
|
|
||||||
import PageContainer from '../../../ui/page-container';
|
import PageContainer from '../../../ui/page-container';
|
||||||
|
|
||||||
import { Tab } from '../../../ui/tabs';
|
import { Tab } from '../../../ui/tabs';
|
||||||
import GasModalPageContainer from './gas-modal-page-container.component';
|
import GasModalPageContainer from './gas-modal-page-container.component';
|
||||||
|
|
||||||
const mockBasicGasEstimates = {
|
jest.mock('../../../../store/actions', () => ({
|
||||||
average: '20',
|
disconnectGasFeeEstimatePoller: jest.fn(),
|
||||||
};
|
getGasFeeEstimatesAndStartPolling: jest
|
||||||
|
.fn()
|
||||||
|
.mockImplementation(() => Promise.resolve()),
|
||||||
|
}));
|
||||||
|
|
||||||
const propsMethodSpies = {
|
const propsMethodSpies = {
|
||||||
cancelAndClose: sinon.spy(),
|
cancelAndClose: sinon.spy(),
|
||||||
onSubmit: sinon.spy(),
|
onSubmit: sinon.spy(),
|
||||||
fetchBasicGasEstimates: sinon
|
|
||||||
.stub()
|
|
||||||
.returns(Promise.resolve(mockBasicGasEstimates)),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const mockGasPriceButtonGroupProps = {
|
const mockGasPriceButtonGroupProps = {
|
||||||
@ -67,7 +68,6 @@ describe('GasModalPageContainer Component', () => {
|
|||||||
<GasModalPageContainer
|
<GasModalPageContainer
|
||||||
cancelAndClose={propsMethodSpies.cancelAndClose}
|
cancelAndClose={propsMethodSpies.cancelAndClose}
|
||||||
onSubmit={propsMethodSpies.onSubmit}
|
onSubmit={propsMethodSpies.onSubmit}
|
||||||
fetchBasicGasEstimates={propsMethodSpies.fetchBasicGasEstimates}
|
|
||||||
updateCustomGasPrice={() => 'mockupdateCustomGasPrice'}
|
updateCustomGasPrice={() => 'mockupdateCustomGasPrice'}
|
||||||
updateCustomGasLimit={() => 'mockupdateCustomGasLimit'}
|
updateCustomGasLimit={() => 'mockupdateCustomGasLimit'}
|
||||||
gasPriceButtonGroupProps={mockGasPriceButtonGroupProps}
|
gasPriceButtonGroupProps={mockGasPriceButtonGroupProps}
|
||||||
@ -83,18 +83,15 @@ describe('GasModalPageContainer Component', () => {
|
|||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
propsMethodSpies.cancelAndClose.resetHistory();
|
propsMethodSpies.cancelAndClose.resetHistory();
|
||||||
|
jest.clearAllMocks();
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('componentDidMount', () => {
|
describe('componentDidMount', () => {
|
||||||
it('should call props.fetchBasicGasEstimates', () => {
|
it('should call getGasFeeEstimatesAndStartPolling', () => {
|
||||||
propsMethodSpies.fetchBasicGasEstimates.resetHistory();
|
jest.clearAllMocks();
|
||||||
expect(propsMethodSpies.fetchBasicGasEstimates.callCount).toStrictEqual(
|
expect(getGasFeeEstimatesAndStartPolling).not.toHaveBeenCalled();
|
||||||
0,
|
|
||||||
);
|
|
||||||
wrapper.instance().componentDidMount();
|
wrapper.instance().componentDidMount();
|
||||||
expect(propsMethodSpies.fetchBasicGasEstimates.callCount).toStrictEqual(
|
expect(getGasFeeEstimatesAndStartPolling).toHaveBeenCalled();
|
||||||
1,
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -120,20 +117,18 @@ describe('GasModalPageContainer Component', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should pass the correct renderTabs property to PageContainer', () => {
|
it('should pass the correct renderTabs property to PageContainer', () => {
|
||||||
sinon.stub(GP, 'renderTabs').returns('mockTabs');
|
jest
|
||||||
|
.spyOn(GasModalPageContainer.prototype, 'renderTabs')
|
||||||
|
.mockImplementation(() => 'mockTabs');
|
||||||
const renderTabsWrapperTester = shallowWithContext(
|
const renderTabsWrapperTester = shallowWithContext(
|
||||||
<GasModalPageContainer
|
<GasModalPageContainer customPriceIsExcessive={false} />,
|
||||||
fetchBasicGasEstimates={propsMethodSpies.fetchBasicGasEstimates}
|
|
||||||
fetchGasEstimates={propsMethodSpies.fetchGasEstimates}
|
|
||||||
customPriceIsExcessive={false}
|
|
||||||
/>,
|
|
||||||
{ context: { t: (str1, str2) => (str2 ? str1 + str2 : str1) } },
|
{ context: { t: (str1, str2) => (str2 ? str1 + str2 : str1) } },
|
||||||
);
|
);
|
||||||
const { tabsComponent } = renderTabsWrapperTester
|
const { tabsComponent } = renderTabsWrapperTester
|
||||||
.find(PageContainer)
|
.find(PageContainer)
|
||||||
.props();
|
.props();
|
||||||
expect(tabsComponent).toStrictEqual('mockTabs');
|
expect(tabsComponent).toStrictEqual('mockTabs');
|
||||||
GasModalPageContainer.prototype.renderTabs.restore();
|
GasModalPageContainer.prototype.renderTabs.mockClear();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -195,7 +190,6 @@ describe('GasModalPageContainer Component', () => {
|
|||||||
<GasModalPageContainer
|
<GasModalPageContainer
|
||||||
cancelAndClose={propsMethodSpies.cancelAndClose}
|
cancelAndClose={propsMethodSpies.cancelAndClose}
|
||||||
onSubmit={propsMethodSpies.onSubmit}
|
onSubmit={propsMethodSpies.onSubmit}
|
||||||
fetchBasicGasEstimates={propsMethodSpies.fetchBasicGasEstimates}
|
|
||||||
updateCustomGasPrice={() => 'mockupdateCustomGasPrice'}
|
updateCustomGasPrice={() => 'mockupdateCustomGasPrice'}
|
||||||
updateCustomGasLimit={() => 'mockupdateCustomGasLimit'}
|
updateCustomGasLimit={() => 'mockupdateCustomGasLimit'}
|
||||||
gasPriceButtonGroupProps={mockGasPriceButtonGroupProps}
|
gasPriceButtonGroupProps={mockGasPriceButtonGroupProps}
|
||||||
|
@ -2,6 +2,10 @@ import React, { Component } from 'react';
|
|||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import PageContainer from '../../../ui/page-container';
|
import PageContainer from '../../../ui/page-container';
|
||||||
import { Tabs, Tab } from '../../../ui/tabs';
|
import { Tabs, Tab } from '../../../ui/tabs';
|
||||||
|
import {
|
||||||
|
disconnectGasFeeEstimatePoller,
|
||||||
|
getGasFeeEstimatesAndStartPolling,
|
||||||
|
} from '../../../../store/actions';
|
||||||
import AdvancedTabContent from './advanced-tab-content';
|
import AdvancedTabContent from './advanced-tab-content';
|
||||||
import BasicTabContent from './basic-tab-content';
|
import BasicTabContent from './basic-tab-content';
|
||||||
|
|
||||||
@ -17,7 +21,6 @@ export default class GasModalPageContainer extends Component {
|
|||||||
updateCustomGasPrice: PropTypes.func,
|
updateCustomGasPrice: PropTypes.func,
|
||||||
updateCustomGasLimit: PropTypes.func,
|
updateCustomGasLimit: PropTypes.func,
|
||||||
insufficientBalance: PropTypes.bool,
|
insufficientBalance: PropTypes.bool,
|
||||||
fetchBasicGasEstimates: PropTypes.func,
|
|
||||||
gasPriceButtonGroupProps: PropTypes.object,
|
gasPriceButtonGroupProps: PropTypes.object,
|
||||||
infoRowProps: PropTypes.shape({
|
infoRowProps: PropTypes.shape({
|
||||||
originalTotalFiat: PropTypes.string,
|
originalTotalFiat: PropTypes.string,
|
||||||
@ -38,8 +41,29 @@ export default class GasModalPageContainer extends Component {
|
|||||||
customPriceIsExcessive: PropTypes.bool.isRequired,
|
customPriceIsExcessive: PropTypes.bool.isRequired,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.state = {
|
||||||
|
pollingToken: undefined,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
this.props.fetchBasicGasEstimates();
|
this._isMounted = true;
|
||||||
|
getGasFeeEstimatesAndStartPolling().then((pollingToken) => {
|
||||||
|
if (this._isMounted) {
|
||||||
|
this.setState({ pollingToken });
|
||||||
|
} else {
|
||||||
|
disconnectGasFeeEstimatePoller(pollingToken);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillUnmount() {
|
||||||
|
this._isMounted = false;
|
||||||
|
if (this.state.pollingToken) {
|
||||||
|
disconnectGasFeeEstimatePoller(this.state.pollingToken);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
renderBasicTabContent(gasPriceButtonGroupProps) {
|
renderBasicTabContent(gasPriceButtonGroupProps) {
|
||||||
|
@ -10,7 +10,6 @@ import {
|
|||||||
setCustomGasPrice,
|
setCustomGasPrice,
|
||||||
setCustomGasLimit,
|
setCustomGasLimit,
|
||||||
resetCustomData,
|
resetCustomData,
|
||||||
fetchBasicGasEstimates,
|
|
||||||
} from '../../../../ducks/gas/gas.duck';
|
} from '../../../../ducks/gas/gas.duck';
|
||||||
import {
|
import {
|
||||||
getSendMaxModeState,
|
getSendMaxModeState,
|
||||||
@ -225,7 +224,6 @@ const mapDispatchToProps = (dispatch) => {
|
|||||||
return dispatch(createSpeedUpTransaction(txId, customGasSettings));
|
return dispatch(createSpeedUpTransaction(txId, customGasSettings));
|
||||||
},
|
},
|
||||||
hideSidebar: () => dispatch(hideSidebar()),
|
hideSidebar: () => dispatch(hideSidebar()),
|
||||||
fetchBasicGasEstimates: () => dispatch(fetchBasicGasEstimates()),
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -4,11 +4,6 @@
|
|||||||
// untangling is having the constants separate.
|
// untangling is having the constants separate.
|
||||||
|
|
||||||
// Actions
|
// Actions
|
||||||
export const BASIC_GAS_ESTIMATE_STATUS =
|
|
||||||
'metamask/gas/BASIC_GAS_ESTIMATE_STATUS';
|
|
||||||
export const RESET_CUSTOM_DATA = 'metamask/gas/RESET_CUSTOM_DATA';
|
export const RESET_CUSTOM_DATA = 'metamask/gas/RESET_CUSTOM_DATA';
|
||||||
export const SET_BASIC_GAS_ESTIMATE_DATA =
|
|
||||||
'metamask/gas/SET_BASIC_GAS_ESTIMATE_DATA';
|
|
||||||
export const SET_CUSTOM_GAS_LIMIT = 'metamask/gas/SET_CUSTOM_GAS_LIMIT';
|
export const SET_CUSTOM_GAS_LIMIT = 'metamask/gas/SET_CUSTOM_GAS_LIMIT';
|
||||||
export const SET_CUSTOM_GAS_PRICE = 'metamask/gas/SET_CUSTOM_GAS_PRICE';
|
export const SET_CUSTOM_GAS_PRICE = 'metamask/gas/SET_CUSTOM_GAS_PRICE';
|
||||||
export const SET_ESTIMATE_SOURCE = 'metamask/gas/SET_ESTIMATE_SOURCE';
|
|
||||||
|
@ -1,36 +1,14 @@
|
|||||||
import nock from 'nock';
|
|
||||||
import sinon from 'sinon';
|
import sinon from 'sinon';
|
||||||
import BN from 'bn.js';
|
|
||||||
|
|
||||||
import GasReducer, {
|
import GasReducer, { setCustomGasPrice, setCustomGasLimit } from './gas.duck';
|
||||||
setBasicEstimateStatus,
|
|
||||||
setBasicGasEstimateData,
|
|
||||||
setCustomGasPrice,
|
|
||||||
setCustomGasLimit,
|
|
||||||
fetchBasicGasEstimates,
|
|
||||||
} from './gas.duck';
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
BASIC_GAS_ESTIMATE_STATUS,
|
|
||||||
SET_BASIC_GAS_ESTIMATE_DATA,
|
|
||||||
SET_CUSTOM_GAS_PRICE,
|
SET_CUSTOM_GAS_PRICE,
|
||||||
SET_CUSTOM_GAS_LIMIT,
|
SET_CUSTOM_GAS_LIMIT,
|
||||||
SET_ESTIMATE_SOURCE,
|
|
||||||
} from './gas-action-constants';
|
} from './gas-action-constants';
|
||||||
|
|
||||||
jest.mock('../../helpers/utils/storage-helpers.js', () => ({
|
|
||||||
getStorageItem: jest.fn(),
|
|
||||||
setStorageItem: jest.fn(),
|
|
||||||
}));
|
|
||||||
|
|
||||||
describe('Gas Duck', () => {
|
describe('Gas Duck', () => {
|
||||||
let tempDateNow;
|
let tempDateNow;
|
||||||
const mockGasPriceApiResponse = {
|
|
||||||
SafeGasPrice: 10,
|
|
||||||
ProposeGasPrice: 20,
|
|
||||||
FastGasPrice: 30,
|
|
||||||
};
|
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
tempDateNow = global.Date.now;
|
tempDateNow = global.Date.now;
|
||||||
|
|
||||||
@ -51,22 +29,6 @@ describe('Gas Duck', () => {
|
|||||||
price: null,
|
price: null,
|
||||||
limit: null,
|
limit: null,
|
||||||
},
|
},
|
||||||
basicEstimates: {
|
|
||||||
average: null,
|
|
||||||
fast: null,
|
|
||||||
safeLow: null,
|
|
||||||
},
|
|
||||||
basicEstimateStatus: 'LOADING',
|
|
||||||
estimateSource: '',
|
|
||||||
};
|
|
||||||
|
|
||||||
const providerState = {
|
|
||||||
chainId: '0x1',
|
|
||||||
nickname: '',
|
|
||||||
rpcPrefs: {},
|
|
||||||
rpcUrl: '',
|
|
||||||
ticker: 'ETH',
|
|
||||||
type: 'mainnet',
|
|
||||||
};
|
};
|
||||||
|
|
||||||
describe('GasReducer()', () => {
|
describe('GasReducer()', () => {
|
||||||
@ -83,27 +45,6 @@ describe('Gas Duck', () => {
|
|||||||
).toStrictEqual(mockState);
|
).toStrictEqual(mockState);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should set basicEstimateStatus to LOADING when receiving a BASIC_GAS_ESTIMATE_STATUS action with value LOADING', () => {
|
|
||||||
expect(
|
|
||||||
GasReducer(mockState, {
|
|
||||||
type: BASIC_GAS_ESTIMATE_STATUS,
|
|
||||||
value: 'LOADING',
|
|
||||||
}),
|
|
||||||
).toStrictEqual({ basicEstimateStatus: 'LOADING', ...mockState });
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should set basicEstimates when receiving a SET_BASIC_GAS_ESTIMATE_DATA action', () => {
|
|
||||||
expect(
|
|
||||||
GasReducer(mockState, {
|
|
||||||
type: SET_BASIC_GAS_ESTIMATE_DATA,
|
|
||||||
value: { someProp: 'someData123' },
|
|
||||||
}),
|
|
||||||
).toStrictEqual({
|
|
||||||
basicEstimates: { someProp: 'someData123' },
|
|
||||||
...mockState,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should set customData.price when receiving a SET_CUSTOM_GAS_PRICE action', () => {
|
it('should set customData.price when receiving a SET_CUSTOM_GAS_PRICE action', () => {
|
||||||
expect(
|
expect(
|
||||||
GasReducer(mockState, {
|
GasReducer(mockState, {
|
||||||
@ -123,100 +64,6 @@ describe('Gas Duck', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should set estimateSource to Metaswaps when receiving a SET_ESTIMATE_SOURCE action with value Metaswaps', () => {
|
|
||||||
expect(
|
|
||||||
GasReducer(mockState, { type: SET_ESTIMATE_SOURCE, value: 'Metaswaps' }),
|
|
||||||
).toStrictEqual({ estimateSource: 'Metaswaps', ...mockState });
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('basicEstimateStatus', () => {
|
|
||||||
it('should create the correct action', () => {
|
|
||||||
expect(setBasicEstimateStatus('LOADING')).toStrictEqual({
|
|
||||||
type: BASIC_GAS_ESTIMATE_STATUS,
|
|
||||||
value: 'LOADING',
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('fetchBasicGasEstimates', () => {
|
|
||||||
it('should call fetch with the expected params', async () => {
|
|
||||||
const mockDistpatch = sinon.spy();
|
|
||||||
const windowFetchSpy = sinon.spy(window, 'fetch');
|
|
||||||
|
|
||||||
nock('https://api.metaswap.codefi.network')
|
|
||||||
.get('/gasPrices')
|
|
||||||
.reply(200, mockGasPriceApiResponse);
|
|
||||||
|
|
||||||
await fetchBasicGasEstimates()(mockDistpatch, () => ({
|
|
||||||
gas: { ...initState },
|
|
||||||
metamask: { provider: { ...providerState } },
|
|
||||||
}));
|
|
||||||
|
|
||||||
expect(mockDistpatch.getCall(0).args).toStrictEqual([
|
|
||||||
{ type: 'metamask/gas/BASIC_GAS_ESTIMATE_STATUS', value: 'LOADING' },
|
|
||||||
]);
|
|
||||||
|
|
||||||
expect(
|
|
||||||
windowFetchSpy
|
|
||||||
.getCall(0)
|
|
||||||
.args[0].startsWith('https://api.metaswap.codefi.network/gasPrices'),
|
|
||||||
).toStrictEqual(true);
|
|
||||||
|
|
||||||
expect(mockDistpatch.getCall(2).args).toStrictEqual([
|
|
||||||
{ type: 'metamask/gas/SET_ESTIMATE_SOURCE', value: 'MetaSwaps' },
|
|
||||||
]);
|
|
||||||
|
|
||||||
expect(mockDistpatch.getCall(4).args).toStrictEqual([
|
|
||||||
{ type: 'metamask/gas/BASIC_GAS_ESTIMATE_STATUS', value: 'READY' },
|
|
||||||
]);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should call fetch with the expected params for test network', async () => {
|
|
||||||
global.eth = { gasPrice: sinon.fake.returns(new BN(48199313, 10)) };
|
|
||||||
|
|
||||||
const mockDistpatch = sinon.spy();
|
|
||||||
const providerStateForTestNetwork = {
|
|
||||||
chainId: '0x5',
|
|
||||||
nickname: '',
|
|
||||||
rpcPrefs: {},
|
|
||||||
rpcUrl: '',
|
|
||||||
ticker: 'ETH',
|
|
||||||
type: 'goerli',
|
|
||||||
};
|
|
||||||
|
|
||||||
await fetchBasicGasEstimates()(mockDistpatch, () => ({
|
|
||||||
gas: { ...initState, basicPriceAEstimatesLastRetrieved: 1000000 },
|
|
||||||
metamask: { provider: { ...providerStateForTestNetwork } },
|
|
||||||
}));
|
|
||||||
expect(mockDistpatch.getCall(0).args).toStrictEqual([
|
|
||||||
{ type: 'metamask/gas/BASIC_GAS_ESTIMATE_STATUS', value: 'LOADING' },
|
|
||||||
]);
|
|
||||||
expect(mockDistpatch.getCall(1).args).toStrictEqual([
|
|
||||||
{ type: 'metamask/gas/SET_ESTIMATE_SOURCE', value: 'eth_gasprice' },
|
|
||||||
]);
|
|
||||||
expect(mockDistpatch.getCall(2).args).toStrictEqual([
|
|
||||||
{
|
|
||||||
type: SET_BASIC_GAS_ESTIMATE_DATA,
|
|
||||||
value: {
|
|
||||||
average: 0.0482,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
expect(mockDistpatch.getCall(3).args).toStrictEqual([
|
|
||||||
{ type: 'metamask/gas/BASIC_GAS_ESTIMATE_STATUS', value: 'READY' },
|
|
||||||
]);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('setBasicGasEstimateData', () => {
|
|
||||||
it('should create the correct action', () => {
|
|
||||||
expect(setBasicGasEstimateData('mockBasicEstimatData')).toStrictEqual({
|
|
||||||
type: SET_BASIC_GAS_ESTIMATE_DATA,
|
|
||||||
value: 'mockBasicEstimatData',
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('setCustomGasPrice', () => {
|
describe('setCustomGasPrice', () => {
|
||||||
it('should create the correct action', () => {
|
it('should create the correct action', () => {
|
||||||
expect(setCustomGasPrice('mockCustomGasPrice')).toStrictEqual({
|
expect(setCustomGasPrice('mockCustomGasPrice')).toStrictEqual({
|
||||||
|
@ -1,62 +1,20 @@
|
|||||||
import { cloneDeep } from 'lodash';
|
import { cloneDeep } from 'lodash';
|
||||||
import BigNumber from 'bignumber.js';
|
|
||||||
import {
|
import {
|
||||||
getStorageItem,
|
|
||||||
setStorageItem,
|
|
||||||
} from '../../helpers/utils/storage-helpers';
|
|
||||||
import {
|
|
||||||
decGWEIToHexWEI,
|
|
||||||
getValueFromWeiHex,
|
|
||||||
} from '../../helpers/utils/conversions.util';
|
|
||||||
import { getIsMainnet, getCurrentChainId } from '../../selectors';
|
|
||||||
import fetchWithCache from '../../helpers/utils/fetch-with-cache';
|
|
||||||
import {
|
|
||||||
BASIC_GAS_ESTIMATE_STATUS,
|
|
||||||
RESET_CUSTOM_DATA,
|
RESET_CUSTOM_DATA,
|
||||||
SET_BASIC_GAS_ESTIMATE_DATA,
|
|
||||||
SET_CUSTOM_GAS_LIMIT,
|
SET_CUSTOM_GAS_LIMIT,
|
||||||
SET_CUSTOM_GAS_PRICE,
|
SET_CUSTOM_GAS_PRICE,
|
||||||
SET_ESTIMATE_SOURCE,
|
|
||||||
} from './gas-action-constants';
|
} from './gas-action-constants';
|
||||||
|
|
||||||
export const BASIC_ESTIMATE_STATES = {
|
|
||||||
LOADING: 'LOADING',
|
|
||||||
FAILED: 'FAILED',
|
|
||||||
READY: 'READY',
|
|
||||||
};
|
|
||||||
|
|
||||||
export const GAS_SOURCE = {
|
|
||||||
METASWAPS: 'MetaSwaps',
|
|
||||||
ETHGASPRICE: 'eth_gasprice',
|
|
||||||
};
|
|
||||||
|
|
||||||
const initState = {
|
const initState = {
|
||||||
customData: {
|
customData: {
|
||||||
price: null,
|
price: null,
|
||||||
limit: null,
|
limit: null,
|
||||||
},
|
},
|
||||||
basicEstimates: {
|
|
||||||
safeLow: null,
|
|
||||||
average: null,
|
|
||||||
fast: null,
|
|
||||||
},
|
|
||||||
basicEstimateStatus: BASIC_ESTIMATE_STATES.LOADING,
|
|
||||||
estimateSource: '',
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Reducer
|
// Reducer
|
||||||
export default function reducer(state = initState, action) {
|
export default function reducer(state = initState, action) {
|
||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
case BASIC_GAS_ESTIMATE_STATUS:
|
|
||||||
return {
|
|
||||||
...state,
|
|
||||||
basicEstimateStatus: action.value,
|
|
||||||
};
|
|
||||||
case SET_BASIC_GAS_ESTIMATE_DATA:
|
|
||||||
return {
|
|
||||||
...state,
|
|
||||||
basicEstimates: action.value,
|
|
||||||
};
|
|
||||||
case SET_CUSTOM_GAS_PRICE:
|
case SET_CUSTOM_GAS_PRICE:
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
@ -78,138 +36,11 @@ export default function reducer(state = initState, action) {
|
|||||||
...state,
|
...state,
|
||||||
customData: cloneDeep(initState.customData),
|
customData: cloneDeep(initState.customData),
|
||||||
};
|
};
|
||||||
case SET_ESTIMATE_SOURCE:
|
|
||||||
return {
|
|
||||||
...state,
|
|
||||||
estimateSource: action.value,
|
|
||||||
};
|
|
||||||
default:
|
default:
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Action Creators
|
|
||||||
export function setBasicEstimateStatus(status) {
|
|
||||||
return {
|
|
||||||
type: BASIC_GAS_ESTIMATE_STATUS,
|
|
||||||
value: status,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
async function basicGasPriceQuery() {
|
|
||||||
const url = `https://api.metaswap.codefi.network/gasPrices`;
|
|
||||||
return await fetchWithCache(
|
|
||||||
url,
|
|
||||||
{
|
|
||||||
referrer: url,
|
|
||||||
referrerPolicy: 'no-referrer-when-downgrade',
|
|
||||||
method: 'GET',
|
|
||||||
mode: 'cors',
|
|
||||||
},
|
|
||||||
{ cacheRefreshTime: 75000 },
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function fetchBasicGasEstimates() {
|
|
||||||
return async (dispatch, getState) => {
|
|
||||||
const isMainnet = getIsMainnet(getState());
|
|
||||||
|
|
||||||
dispatch(setBasicEstimateStatus(BASIC_ESTIMATE_STATES.LOADING));
|
|
||||||
let basicEstimates;
|
|
||||||
try {
|
|
||||||
dispatch(setEstimateSource(GAS_SOURCE.ETHGASPRICE));
|
|
||||||
if (isMainnet || process.env.IN_TEST) {
|
|
||||||
try {
|
|
||||||
basicEstimates = await fetchExternalBasicGasEstimates();
|
|
||||||
dispatch(setEstimateSource(GAS_SOURCE.METASWAPS));
|
|
||||||
} catch (error) {
|
|
||||||
basicEstimates = await fetchEthGasPriceEstimates(getState());
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
basicEstimates = await fetchEthGasPriceEstimates(getState());
|
|
||||||
}
|
|
||||||
dispatch(setBasicGasEstimateData(basicEstimates));
|
|
||||||
dispatch(setBasicEstimateStatus(BASIC_ESTIMATE_STATES.READY));
|
|
||||||
} catch (error) {
|
|
||||||
dispatch(setBasicEstimateStatus(BASIC_ESTIMATE_STATES.FAILED));
|
|
||||||
}
|
|
||||||
|
|
||||||
return basicEstimates;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
async function fetchExternalBasicGasEstimates() {
|
|
||||||
const {
|
|
||||||
SafeGasPrice,
|
|
||||||
ProposeGasPrice,
|
|
||||||
FastGasPrice,
|
|
||||||
} = await basicGasPriceQuery();
|
|
||||||
|
|
||||||
const [safeLow, average, fast] = [
|
|
||||||
SafeGasPrice,
|
|
||||||
ProposeGasPrice,
|
|
||||||
FastGasPrice,
|
|
||||||
].map((price) => new BigNumber(price, 10).toNumber());
|
|
||||||
|
|
||||||
const basicEstimates = {
|
|
||||||
safeLow,
|
|
||||||
average,
|
|
||||||
fast,
|
|
||||||
};
|
|
||||||
|
|
||||||
return basicEstimates;
|
|
||||||
}
|
|
||||||
|
|
||||||
async function fetchEthGasPriceEstimates(state) {
|
|
||||||
const chainId = getCurrentChainId(state);
|
|
||||||
const [cachedTimeLastRetrieved, cachedBasicEstimates] = await Promise.all([
|
|
||||||
getStorageItem(`${chainId}_BASIC_PRICE_ESTIMATES_LAST_RETRIEVED`),
|
|
||||||
getStorageItem(`${chainId}_BASIC_PRICE_ESTIMATES`),
|
|
||||||
]);
|
|
||||||
const timeLastRetrieved = cachedTimeLastRetrieved || 0;
|
|
||||||
if (cachedBasicEstimates && Date.now() - timeLastRetrieved < 75000) {
|
|
||||||
return cachedBasicEstimates;
|
|
||||||
}
|
|
||||||
const gasPrice = await global.eth.gasPrice();
|
|
||||||
const averageGasPriceInDecGWEI = getValueFromWeiHex({
|
|
||||||
value: gasPrice.toString(16),
|
|
||||||
numberOfDecimals: 4,
|
|
||||||
toDenomination: 'GWEI',
|
|
||||||
});
|
|
||||||
const basicEstimates = {
|
|
||||||
average: Number(averageGasPriceInDecGWEI),
|
|
||||||
};
|
|
||||||
const timeRetrieved = Date.now();
|
|
||||||
|
|
||||||
await Promise.all([
|
|
||||||
setStorageItem(`${chainId}_BASIC_PRICE_ESTIMATES`, basicEstimates),
|
|
||||||
setStorageItem(
|
|
||||||
`${chainId}_BASIC_PRICE_ESTIMATES_LAST_RETRIEVED`,
|
|
||||||
timeRetrieved,
|
|
||||||
),
|
|
||||||
]);
|
|
||||||
|
|
||||||
return basicEstimates;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function setCustomGasPriceForRetry(newPrice) {
|
|
||||||
return async (dispatch) => {
|
|
||||||
if (newPrice === '0x0') {
|
|
||||||
const { fast } = await fetchExternalBasicGasEstimates();
|
|
||||||
dispatch(setCustomGasPrice(decGWEIToHexWEI(fast)));
|
|
||||||
} else {
|
|
||||||
dispatch(setCustomGasPrice(newPrice));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function setBasicGasEstimateData(basicGasEstimateData) {
|
|
||||||
return {
|
|
||||||
type: SET_BASIC_GAS_ESTIMATE_DATA,
|
|
||||||
value: basicGasEstimateData,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function setCustomGasPrice(newPrice) {
|
export function setCustomGasPrice(newPrice) {
|
||||||
return {
|
return {
|
||||||
type: SET_CUSTOM_GAS_PRICE,
|
type: SET_CUSTOM_GAS_PRICE,
|
||||||
@ -227,10 +58,3 @@ export function setCustomGasLimit(newLimit) {
|
|||||||
export function resetCustomData() {
|
export function resetCustomData() {
|
||||||
return { type: RESET_CUSTOM_DATA };
|
return { type: RESET_CUSTOM_DATA };
|
||||||
}
|
}
|
||||||
|
|
||||||
export function setEstimateSource(estimateSource) {
|
|
||||||
return {
|
|
||||||
type: SET_ESTIMATE_SOURCE,
|
|
||||||
value: estimateSource,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
@ -50,15 +50,7 @@ import {
|
|||||||
updateTokenType,
|
updateTokenType,
|
||||||
updateTransaction,
|
updateTransaction,
|
||||||
} from '../../store/actions';
|
} from '../../store/actions';
|
||||||
import {
|
import { setCustomGasLimit } from '../gas/gas.duck';
|
||||||
fetchBasicGasEstimates,
|
|
||||||
setCustomGasLimit,
|
|
||||||
BASIC_ESTIMATE_STATES,
|
|
||||||
} from '../gas/gas.duck';
|
|
||||||
import {
|
|
||||||
SET_BASIC_GAS_ESTIMATE_DATA,
|
|
||||||
BASIC_GAS_ESTIMATE_STATUS,
|
|
||||||
} from '../gas/gas-action-constants';
|
|
||||||
import {
|
import {
|
||||||
QR_CODE_DETECTED,
|
QR_CODE_DETECTED,
|
||||||
SELECTED_ACCOUNT_CHANGED,
|
SELECTED_ACCOUNT_CHANGED,
|
||||||
@ -77,13 +69,18 @@ import {
|
|||||||
isOriginContractAddress,
|
isOriginContractAddress,
|
||||||
isValidDomainName,
|
isValidDomainName,
|
||||||
} from '../../helpers/utils/util';
|
} from '../../helpers/utils/util';
|
||||||
import { getTokens, getUnapprovedTxs } from '../metamask/metamask';
|
import {
|
||||||
|
getGasEstimateType,
|
||||||
|
getTokens,
|
||||||
|
getUnapprovedTxs,
|
||||||
|
} from '../metamask/metamask';
|
||||||
import { resetEnsResolution } from '../ens';
|
import { resetEnsResolution } from '../ens';
|
||||||
import {
|
import {
|
||||||
isBurnAddress,
|
isBurnAddress,
|
||||||
isValidHexAddress,
|
isValidHexAddress,
|
||||||
} from '../../../shared/modules/hexstring-utils';
|
} from '../../../shared/modules/hexstring-utils';
|
||||||
import { CHAIN_ID_TO_GAS_LIMIT_BUFFER_MAP } from '../../../shared/constants/network';
|
import { CHAIN_ID_TO_GAS_LIMIT_BUFFER_MAP } from '../../../shared/constants/network';
|
||||||
|
import { ETH, GWEI } from '../../helpers/constants/common';
|
||||||
|
|
||||||
// typedefs
|
// typedefs
|
||||||
/**
|
/**
|
||||||
@ -186,8 +183,19 @@ async function estimateGasLimitForSend({
|
|||||||
let isSimpleSendOnNonStandardNetwork = false;
|
let isSimpleSendOnNonStandardNetwork = false;
|
||||||
|
|
||||||
// blockGasLimit may be a falsy, but defined, value when we receive it from
|
// blockGasLimit may be a falsy, but defined, value when we receive it from
|
||||||
// state, so we use logical or to fall back to MIN_GAS_LIMIT_HEX.
|
// state, so we use logical or to fall back to MIN_GAS_LIMIT_HEX. Some
|
||||||
const blockGasLimit = options.blockGasLimit || MIN_GAS_LIMIT_HEX;
|
// network implementations check the gas parameter supplied to
|
||||||
|
// eth_estimateGas for validity. For this reason, we set token sends
|
||||||
|
// blockGasLimit default to a higher number. Note that the current gasLimit
|
||||||
|
// on a BLOCK is 15,000,000 and will be 30,000,000 on mainnet after London.
|
||||||
|
// Meanwhile, MIN_GAS_LIMIT_HEX is 0x5208.
|
||||||
|
let blockGasLimit = MIN_GAS_LIMIT_HEX;
|
||||||
|
if (options.blockGasLimit) {
|
||||||
|
blockGasLimit = options.blockGasLimit;
|
||||||
|
} else if (sendToken) {
|
||||||
|
blockGasLimit = GAS_LIMITS.BASE_TOKEN_ESTIMATE;
|
||||||
|
}
|
||||||
|
|
||||||
// The parameters below will be sent to our background process to estimate
|
// The parameters below will be sent to our background process to estimate
|
||||||
// how much gas will be used for a transaction. That background process is
|
// how much gas will be used for a transaction. That background process is
|
||||||
// located in tx-gas-utils.js in the transaction controller folder.
|
// located in tx-gas-utils.js in the transaction controller folder.
|
||||||
@ -342,7 +350,7 @@ export const computeEstimatedGasLimit = createAsyncThunk(
|
|||||||
if (send.stage !== SEND_STAGES.EDIT) {
|
if (send.stage !== SEND_STAGES.EDIT) {
|
||||||
const gasLimit = await estimateGasLimitForSend({
|
const gasLimit = await estimateGasLimitForSend({
|
||||||
gasPrice: send.gas.gasPrice,
|
gasPrice: send.gas.gasPrice,
|
||||||
blockGasLimit: metamask.blockGasLimit,
|
blockGasLimit: metamask.currentBlockGasLimit,
|
||||||
selectedAddress: metamask.selectedAddress,
|
selectedAddress: metamask.selectedAddress,
|
||||||
sendToken: send.asset.details,
|
sendToken: send.asset.details,
|
||||||
to: send.recipient.address?.toLowerCase(),
|
to: send.recipient.address?.toLowerCase(),
|
||||||
@ -360,6 +368,29 @@ export const computeEstimatedGasLimit = createAsyncThunk(
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method is used to keep the original logic from the gas.duck.js file
|
||||||
|
* after receiving a gasPrice from eth_gasPrice. First, the returned gasPrice
|
||||||
|
* was converted to GWEI, then it was converted to a Number, then in the send
|
||||||
|
* duck (here) we would use getGasPriceInHexWei to get back to hexWei. Now that
|
||||||
|
* we receive a GWEI estimate from the controller, we still need to do this
|
||||||
|
* weird conversion to get the proper rounding.
|
||||||
|
* @param {T} gasPriceEstimate
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
function getRoundedGasPrice(gasPriceEstimate) {
|
||||||
|
const gasPriceInDecGwei = conversionUtil(gasPriceEstimate, {
|
||||||
|
numberOfDecimals: 4,
|
||||||
|
toDenomination: GWEI,
|
||||||
|
fromNumericBase: 'dec',
|
||||||
|
toNumericBase: 'dec',
|
||||||
|
fromCurrency: ETH,
|
||||||
|
fromDenomination: GWEI,
|
||||||
|
});
|
||||||
|
const gasPriceAsNumber = Number(gasPriceInDecGwei);
|
||||||
|
return getGasPriceInHexWei(gasPriceAsNumber);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Responsible for initializing required state for the send slice.
|
* Responsible for initializing required state for the send slice.
|
||||||
* This method is dispatched from the send page in the componentDidMount
|
* This method is dispatched from the send page in the componentDidMount
|
||||||
@ -395,48 +426,31 @@ export const initializeSendState = createAsyncThunk(
|
|||||||
|
|
||||||
// Default gasPrice to 1 gwei if all estimation fails
|
// Default gasPrice to 1 gwei if all estimation fails
|
||||||
let gasPrice = '0x1';
|
let gasPrice = '0x1';
|
||||||
let basicEstimateStatus = BASIC_ESTIMATE_STATES.LOADING;
|
|
||||||
let gasEstimatePollToken = null;
|
let gasEstimatePollToken = null;
|
||||||
|
|
||||||
if (Boolean(process.env.SHOW_EIP_1559_UI) === false) {
|
// Instruct the background process that polling for gas prices should begin
|
||||||
// Initiate gas slices work to fetch gasPrice estimates. We need to get the
|
gasEstimatePollToken = await getGasFeeEstimatesAndStartPolling();
|
||||||
// new state after this is set to determine if initialization can proceed.
|
const {
|
||||||
await thunkApi.dispatch(fetchBasicGasEstimates());
|
metamask: { gasFeeEstimates, gasEstimateType },
|
||||||
const {
|
} = thunkApi.getState();
|
||||||
gas: { basicEstimates, basicEstimateStatus: apiBasicEstimateStatus },
|
|
||||||
} = thunkApi.getState();
|
|
||||||
|
|
||||||
basicEstimateStatus = apiBasicEstimateStatus;
|
if (gasEstimateType === GAS_ESTIMATE_TYPES.LEGACY) {
|
||||||
|
gasPrice = getGasPriceInHexWei(gasFeeEstimates.medium);
|
||||||
if (basicEstimateStatus === BASIC_ESTIMATE_STATES.READY) {
|
} else if (gasEstimateType === GAS_ESTIMATE_TYPES.ETH_GASPRICE) {
|
||||||
gasPrice = getGasPriceInHexWei(basicEstimates.average);
|
gasPrice = getRoundedGasPrice(gasFeeEstimates.gasPrice);
|
||||||
}
|
} else if (gasEstimateType === GAS_ESTIMATE_TYPES.FEE_MARKET) {
|
||||||
} else {
|
gasPrice = getGasPriceInHexWei(
|
||||||
// Instruct the background process that polling for gas prices should begin
|
gasFeeEstimates.medium.suggestedMaxFeePerGas,
|
||||||
gasEstimatePollToken = await getGasFeeEstimatesAndStartPolling();
|
);
|
||||||
const {
|
|
||||||
metamask: { gasFeeEstimates, gasEstimateType },
|
|
||||||
} = thunkApi.getState();
|
|
||||||
|
|
||||||
if (gasEstimateType === GAS_ESTIMATE_TYPES.LEGACY) {
|
|
||||||
gasPrice = getGasPriceInHexWei(gasFeeEstimates.medium);
|
|
||||||
} else if (gasEstimateType === GAS_ESTIMATE_TYPES.ETH_GASPRICE) {
|
|
||||||
gasPrice = getGasPriceInHexWei(gasFeeEstimates.gasPrice);
|
|
||||||
} else if (gasEstimateType === GAS_ESTIMATE_TYPES.FEE_MARKET) {
|
|
||||||
gasPrice = getGasPriceInHexWei(
|
|
||||||
gasFeeEstimates.medium.suggestedMaxFeePerGas,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
basicEstimateStatus = BASIC_ESTIMATE_STATES.READY;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set a basic gasLimit in the event that other estimation fails
|
// Set a basic gasLimit in the event that other estimation fails
|
||||||
let gasLimit =
|
let gasLimit =
|
||||||
asset.type === ASSET_TYPES.TOKEN
|
asset.type === ASSET_TYPES.TOKEN
|
||||||
? GAS_LIMITS.BASE_TOKEN_ESTIMATE
|
? GAS_LIMITS.BASE_TOKEN_ESTIMATE
|
||||||
: GAS_LIMITS.SIMPLE;
|
: GAS_LIMITS.SIMPLE;
|
||||||
if (
|
if (
|
||||||
basicEstimateStatus === BASIC_ESTIMATE_STATES.READY &&
|
gasEstimateType !== GAS_ESTIMATE_TYPES.NONE &&
|
||||||
stage !== SEND_STAGES.EDIT &&
|
stage !== SEND_STAGES.EDIT &&
|
||||||
recipient.address
|
recipient.address
|
||||||
) {
|
) {
|
||||||
@ -444,7 +458,7 @@ export const initializeSendState = createAsyncThunk(
|
|||||||
// required gas. If this value isn't nullish, set it as the new gasLimit
|
// required gas. If this value isn't nullish, set it as the new gasLimit
|
||||||
const estimatedGasLimit = await estimateGasLimitForSend({
|
const estimatedGasLimit = await estimateGasLimitForSend({
|
||||||
gasPrice,
|
gasPrice,
|
||||||
blockGasLimit: metamask.blockGasLimit,
|
blockGasLimit: metamask.currentBlockGasLimit,
|
||||||
selectedAddress: fromAddress,
|
selectedAddress: fromAddress,
|
||||||
sendToken: asset.details,
|
sendToken: asset.details,
|
||||||
to: recipient.address.toLowerCase(),
|
to: recipient.address.toLowerCase(),
|
||||||
@ -508,9 +522,12 @@ export const initialState = {
|
|||||||
isCustomGasSet: false,
|
isCustomGasSet: false,
|
||||||
// maximum gas needed for tx
|
// maximum gas needed for tx
|
||||||
gasLimit: '0x0',
|
gasLimit: '0x0',
|
||||||
// price in gwei to pay per gas
|
// price in wei to pay per gas
|
||||||
gasPrice: '0x0',
|
gasPrice: '0x0',
|
||||||
// maximum total price in gwei to pay
|
// expected price in wei necessary to pay per gas used for a transaction
|
||||||
|
// to be included in a reasonable timeframe. Comes from GasFeeController.
|
||||||
|
gasPriceEstimate: '0x0',
|
||||||
|
// maximum total price in wei to pay
|
||||||
gasTotal: '0x0',
|
gasTotal: '0x0',
|
||||||
// minimum supported gasLimit
|
// minimum supported gasLimit
|
||||||
minimumGasLimit: GAS_LIMITS.SIMPLE,
|
minimumGasLimit: GAS_LIMITS.SIMPLE,
|
||||||
@ -761,7 +778,9 @@ const slice = createSlice({
|
|||||||
// We keep a copy of txParams in state that could be submitted to the
|
// We keep a copy of txParams in state that could be submitted to the
|
||||||
// network if the form state is valid.
|
// network if the form state is valid.
|
||||||
if (state.status === SEND_STATUSES.VALID) {
|
if (state.status === SEND_STATUSES.VALID) {
|
||||||
state.draftTransaction.txParams.from = state.account.address;
|
if (state.stage !== SEND_STAGES.EDIT) {
|
||||||
|
state.draftTransaction.txParams.from = state.account.address;
|
||||||
|
}
|
||||||
switch (state.asset.type) {
|
switch (state.asset.type) {
|
||||||
case ASSET_TYPES.TOKEN:
|
case ASSET_TYPES.TOKEN:
|
||||||
// When sending a token the to address is the contract address of
|
// When sending a token the to address is the contract address of
|
||||||
@ -926,7 +945,7 @@ const slice = createSlice({
|
|||||||
break;
|
break;
|
||||||
case state.asset.type === ASSET_TYPES.TOKEN &&
|
case state.asset.type === ASSET_TYPES.TOKEN &&
|
||||||
state.asset.details.isERC721 === true:
|
state.asset.details.isERC721 === true:
|
||||||
state.state = SEND_STATUSES.INVALID;
|
state.status = SEND_STATUSES.INVALID;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
state.status = SEND_STATUSES.VALID;
|
state.status = SEND_STATUSES.VALID;
|
||||||
@ -1063,58 +1082,36 @@ const slice = createSlice({
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.addCase(SET_BASIC_GAS_ESTIMATE_DATA, (state, action) => {
|
|
||||||
// When we receive a new gasPrice via the gas duck we need to update
|
|
||||||
// the gasPrice in our slice. We call into the caseReducer
|
|
||||||
// updateGasPrice to also tap into the appropriate follow up checks
|
|
||||||
// and gasTotal calculation.
|
|
||||||
if (Boolean(process.env.SHOW_EIP_1559_UI) === false) {
|
|
||||||
slice.caseReducers.updateGasPrice(state, {
|
|
||||||
payload: getGasPriceInHexWei(action.value.average),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.addCase(BASIC_GAS_ESTIMATE_STATUS, (state, action) => {
|
|
||||||
// When we fetch gas prices we should temporarily set the form invalid
|
|
||||||
// Once the price updates we get that value in the
|
|
||||||
// SET_BASIC_GAS_ESTIMATE_DATA extraReducer above. Finally as long as
|
|
||||||
// the state is 'READY' we will revalidate the form.
|
|
||||||
switch (action.value) {
|
|
||||||
case BASIC_ESTIMATE_STATES.FAILED:
|
|
||||||
state.status = SEND_STATUSES.INVALID;
|
|
||||||
state.gas.isGasEstimateLoading = true;
|
|
||||||
break;
|
|
||||||
case BASIC_ESTIMATE_STATES.LOADING:
|
|
||||||
state.status = SEND_STATUSES.INVALID;
|
|
||||||
state.gas.isGasEstimateLoading = true;
|
|
||||||
break;
|
|
||||||
case BASIC_ESTIMATE_STATES.READY:
|
|
||||||
default:
|
|
||||||
state.gas.isGasEstimateLoading = false;
|
|
||||||
slice.caseReducers.validateSendState(state);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.addCase(GAS_FEE_ESTIMATES_UPDATED, (state, action) => {
|
.addCase(GAS_FEE_ESTIMATES_UPDATED, (state, action) => {
|
||||||
// When the gasFeeController updates its gas fee estimates we need to
|
// When the gasFeeController updates its gas fee estimates we need to
|
||||||
// update and validate state based on those new values
|
// update and validate state based on those new values
|
||||||
if (process.env.SHOW_EIP_1559_UI) {
|
const { gasFeeEstimates, gasEstimateType } = action.payload;
|
||||||
const { gasFeeEstimates, gasEstimateType } = action.payload;
|
let payload = null;
|
||||||
let payload = null;
|
if (gasEstimateType === GAS_ESTIMATE_TYPES.FEE_MARKET) {
|
||||||
if (gasEstimateType === GAS_ESTIMATE_TYPES.FEE_MARKET) {
|
payload = getGasPriceInHexWei(
|
||||||
payload = getGasPriceInHexWei(
|
gasFeeEstimates.medium.suggestedMaxFeePerGas,
|
||||||
gasFeeEstimates.medium.suggestedMaxFeePerGas,
|
);
|
||||||
);
|
} else if (gasEstimateType === GAS_ESTIMATE_TYPES.LEGACY) {
|
||||||
} else if (gasEstimateType === GAS_ESTIMATE_TYPES.LEGACY) {
|
payload = getGasPriceInHexWei(gasFeeEstimates.medium);
|
||||||
payload = getGasPriceInHexWei(gasFeeEstimates.medium);
|
} else if (gasEstimateType === GAS_ESTIMATE_TYPES.ETH_GASPRICE) {
|
||||||
} else if (gasEstimateType === GAS_ESTIMATE_TYPES.ETH_GASPRICE) {
|
payload = getRoundedGasPrice(gasFeeEstimates.gasPrice);
|
||||||
payload = getGasPriceInHexWei(gasFeeEstimates.gasPrice);
|
|
||||||
}
|
|
||||||
if (payload) {
|
|
||||||
slice.caseReducers.updateGasPrice(state, {
|
|
||||||
payload,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
// If a new gasPrice can be derived, and either the gasPriceEstimate
|
||||||
|
// was '0x0' or the gasPrice selected matches the previous estimate,
|
||||||
|
// update the gasPrice. This will ensure that we only update the
|
||||||
|
// gasPrice if the user is using our previous estimated value.
|
||||||
|
if (
|
||||||
|
payload &&
|
||||||
|
(state.gas.gasPriceEstimate === '0x0' ||
|
||||||
|
state.gas.gasPrice === state.gas.gasPriceEstimate)
|
||||||
|
) {
|
||||||
|
slice.caseReducers.updateGasPrice(state, {
|
||||||
|
payload,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Record the latest gasPriceEstimate for future comparisons
|
||||||
|
state.gas.gasPriceEstimate = payload ?? state.gas.gasPriceEstimate;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@ -1487,6 +1484,7 @@ export function getMinimumGasLimitForSend(state) {
|
|||||||
|
|
||||||
export function getGasInputMode(state) {
|
export function getGasInputMode(state) {
|
||||||
const isMainnet = getIsMainnet(state);
|
const isMainnet = getIsMainnet(state);
|
||||||
|
const gasEstimateType = getGasEstimateType(state);
|
||||||
const showAdvancedGasFields = getAdvancedInlineGasShown(state);
|
const showAdvancedGasFields = getAdvancedInlineGasShown(state);
|
||||||
if (state[name].gas.isCustomGasSet) {
|
if (state[name].gas.isCustomGasSet) {
|
||||||
return GAS_INPUT_MODES.CUSTOM;
|
return GAS_INPUT_MODES.CUSTOM;
|
||||||
@ -1494,6 +1492,16 @@ export function getGasInputMode(state) {
|
|||||||
if ((!isMainnet && !process.env.IN_TEST) || showAdvancedGasFields) {
|
if ((!isMainnet && !process.env.IN_TEST) || showAdvancedGasFields) {
|
||||||
return GAS_INPUT_MODES.INLINE;
|
return GAS_INPUT_MODES.INLINE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We get eth_gasPrice estimation if the legacy API fails but we need to
|
||||||
|
// instruct the UI to render the INLINE inputs in this case, only on
|
||||||
|
// mainnet or IN_TEST.
|
||||||
|
if (
|
||||||
|
(isMainnet || process.env.IN_TEST) &&
|
||||||
|
gasEstimateType === GAS_ESTIMATE_TYPES.ETH_GASPRICE
|
||||||
|
) {
|
||||||
|
return GAS_INPUT_MODES.INLINE;
|
||||||
|
}
|
||||||
return GAS_INPUT_MODES.BASIC;
|
return GAS_INPUT_MODES.BASIC;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,9 +10,8 @@ import {
|
|||||||
KNOWN_RECIPIENT_ADDRESS_WARNING,
|
KNOWN_RECIPIENT_ADDRESS_WARNING,
|
||||||
NEGATIVE_ETH_ERROR,
|
NEGATIVE_ETH_ERROR,
|
||||||
} from '../../pages/send/send.constants';
|
} from '../../pages/send/send.constants';
|
||||||
import { BASIC_ESTIMATE_STATES } from '../gas/gas.duck';
|
|
||||||
import { RINKEBY_CHAIN_ID } from '../../../shared/constants/network';
|
import { RINKEBY_CHAIN_ID } from '../../../shared/constants/network';
|
||||||
import { GAS_LIMITS } from '../../../shared/constants/gas';
|
import { GAS_ESTIMATE_TYPES, GAS_LIMITS } from '../../../shared/constants/gas';
|
||||||
import { TRANSACTION_TYPES } from '../../../shared/constants/transaction';
|
import { TRANSACTION_TYPES } from '../../../shared/constants/transaction';
|
||||||
import sendReducer, {
|
import sendReducer, {
|
||||||
initialState,
|
initialState,
|
||||||
@ -953,6 +952,11 @@ describe('Send Slice', () => {
|
|||||||
it('should dispatch async action thunk first with pending, then finally fulfilling from minimal state', async () => {
|
it('should dispatch async action thunk first with pending, then finally fulfilling from minimal state', async () => {
|
||||||
getState = jest.fn().mockReturnValue({
|
getState = jest.fn().mockReturnValue({
|
||||||
metamask: {
|
metamask: {
|
||||||
|
gasEstimateType: GAS_ESTIMATE_TYPES.NONE,
|
||||||
|
gasFeeEstimates: {},
|
||||||
|
networkDetails: {
|
||||||
|
EIPS: {},
|
||||||
|
},
|
||||||
accounts: {
|
accounts: {
|
||||||
'0xAddress': {
|
'0xAddress': {
|
||||||
address: '0xAddress',
|
address: '0xAddress',
|
||||||
@ -970,6 +974,7 @@ describe('Send Slice', () => {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
send: initialState,
|
send: initialState,
|
||||||
|
|
||||||
gas: {
|
gas: {
|
||||||
basicEstimateStatus: 'LOADING',
|
basicEstimateStatus: 'LOADING',
|
||||||
basicEstimatesStatus: {
|
basicEstimatesStatus: {
|
||||||
@ -983,12 +988,12 @@ describe('Send Slice', () => {
|
|||||||
const action = initializeSendState();
|
const action = initializeSendState();
|
||||||
await action(dispatchSpy, getState, undefined);
|
await action(dispatchSpy, getState, undefined);
|
||||||
|
|
||||||
expect(dispatchSpy).toHaveBeenCalledTimes(4);
|
expect(dispatchSpy).toHaveBeenCalledTimes(3);
|
||||||
|
|
||||||
expect(dispatchSpy.mock.calls[0][0].type).toStrictEqual(
|
expect(dispatchSpy.mock.calls[0][0].type).toStrictEqual(
|
||||||
'send/initializeSendState/pending',
|
'send/initializeSendState/pending',
|
||||||
);
|
);
|
||||||
expect(dispatchSpy.mock.calls[3][0].type).toStrictEqual(
|
expect(dispatchSpy.mock.calls[2][0].type).toStrictEqual(
|
||||||
'send/initializeSendState/fulfilled',
|
'send/initializeSendState/fulfilled',
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@ -1000,6 +1005,7 @@ describe('Send Slice', () => {
|
|||||||
...initialState,
|
...initialState,
|
||||||
gas: {
|
gas: {
|
||||||
gasPrice: '0x0',
|
gasPrice: '0x0',
|
||||||
|
gasPriceEstimate: '0x0',
|
||||||
gasLimit: '0x5208',
|
gasLimit: '0x5208',
|
||||||
gasTotal: '0x0',
|
gasTotal: '0x0',
|
||||||
minimumGasLimit: '0x5208',
|
minimumGasLimit: '0x5208',
|
||||||
@ -1007,9 +1013,12 @@ describe('Send Slice', () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const action = {
|
const action = {
|
||||||
type: 'metamask/gas/SET_BASIC_GAS_ESTIMATE_DATA',
|
type: 'GAS_FEE_ESTIMATES_UPDATED',
|
||||||
value: {
|
payload: {
|
||||||
average: '1',
|
gasEstimateType: GAS_ESTIMATE_TYPES.LEGACY,
|
||||||
|
gasFeeEstimates: {
|
||||||
|
medium: '1',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1020,40 +1029,6 @@ describe('Send Slice', () => {
|
|||||||
expect(result.gas.gasTotal).toStrictEqual('0x1319718a5000');
|
expect(result.gas.gasTotal).toStrictEqual('0x1319718a5000');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('BASIC_GAS_ESTIMATE_STATUS', () => {
|
|
||||||
it('should invalidate the send status when status is LOADING', () => {
|
|
||||||
const validSendStatusState = {
|
|
||||||
...initialState,
|
|
||||||
status: SEND_STATUSES.VALID,
|
|
||||||
};
|
|
||||||
|
|
||||||
const action = {
|
|
||||||
type: 'metamask/gas/BASIC_GAS_ESTIMATE_STATUS',
|
|
||||||
value: BASIC_ESTIMATE_STATES.LOADING,
|
|
||||||
};
|
|
||||||
|
|
||||||
const result = sendReducer(validSendStatusState, action);
|
|
||||||
|
|
||||||
expect(result.status).not.toStrictEqual(validSendStatusState.status);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should invalidate the send status when status is FAILED and use INLINE gas input mode', () => {
|
|
||||||
const validSendStatusState = {
|
|
||||||
...initialState,
|
|
||||||
status: SEND_STATUSES.VALID,
|
|
||||||
};
|
|
||||||
|
|
||||||
const action = {
|
|
||||||
type: 'metamask/gas/BASIC_GAS_ESTIMATE_STATUS',
|
|
||||||
value: BASIC_ESTIMATE_STATES.FAILED,
|
|
||||||
};
|
|
||||||
|
|
||||||
const result = sendReducer(validSendStatusState, action);
|
|
||||||
|
|
||||||
expect(result.status).not.toStrictEqual(validSendStatusState.status);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Action Creators', () => {
|
describe('Action Creators', () => {
|
||||||
|
@ -5,10 +5,7 @@ import { isBalanceSufficient } from '../pages/send/send.utils';
|
|||||||
import { getSelectedAccount, getIsMainnet } from '../selectors';
|
import { getSelectedAccount, getIsMainnet } from '../selectors';
|
||||||
import { getConversionRate } from '../ducks/metamask/metamask';
|
import { getConversionRate } from '../ducks/metamask/metamask';
|
||||||
|
|
||||||
import {
|
import { setCustomGasLimit, setCustomGasPrice } from '../ducks/gas/gas.duck';
|
||||||
setCustomGasLimit,
|
|
||||||
setCustomGasPriceForRetry,
|
|
||||||
} from '../ducks/gas/gas.duck';
|
|
||||||
import { GAS_LIMITS } from '../../shared/constants/gas';
|
import { GAS_LIMITS } from '../../shared/constants/gas';
|
||||||
import { isLegacyTransaction } from '../../shared/modules/transaction.utils';
|
import { isLegacyTransaction } from '../../shared/modules/transaction.utils';
|
||||||
import { getMaximumGasTotalInHexWei } from '../../shared/modules/gas.utils';
|
import { getMaximumGasTotalInHexWei } from '../../shared/modules/gas.utils';
|
||||||
@ -51,7 +48,7 @@ export function useCancelTransaction(transactionGroup) {
|
|||||||
// To support the current process of cancelling or speeding up
|
// To support the current process of cancelling or speeding up
|
||||||
// a transaction, we have to inform the custom gas state of the new
|
// a transaction, we have to inform the custom gas state of the new
|
||||||
// gasPrice/gasLimit to start at.
|
// gasPrice/gasLimit to start at.
|
||||||
dispatch(setCustomGasPriceForRetry(customGasSettings.gasPrice));
|
dispatch(setCustomGasPrice(customGasSettings.gasPrice));
|
||||||
dispatch(setCustomGasLimit(GAS_LIMITS.SIMPLE));
|
dispatch(setCustomGasLimit(GAS_LIMITS.SIMPLE));
|
||||||
}
|
}
|
||||||
const tx = {
|
const tx = {
|
||||||
|
@ -44,11 +44,17 @@ export function useGasFeeEstimates() {
|
|||||||
const gasFeeEstimates = useSelector(getGasFeeEstimates);
|
const gasFeeEstimates = useSelector(getGasFeeEstimates);
|
||||||
const estimatedGasFeeTimeBounds = useSelector(getEstimatedGasFeeTimeBounds);
|
const estimatedGasFeeTimeBounds = useSelector(getEstimatedGasFeeTimeBounds);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
let active = true;
|
||||||
let pollToken;
|
let pollToken;
|
||||||
getGasFeeEstimatesAndStartPolling().then((newPollToken) => {
|
getGasFeeEstimatesAndStartPolling().then((newPollToken) => {
|
||||||
pollToken = newPollToken;
|
if (active) {
|
||||||
|
pollToken = newPollToken;
|
||||||
|
} else {
|
||||||
|
disconnectGasFeeEstimatePoller(newPollToken);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
return () => {
|
return () => {
|
||||||
|
active = false;
|
||||||
if (pollToken) {
|
if (pollToken) {
|
||||||
disconnectGasFeeEstimatePoller(pollToken);
|
disconnectGasFeeEstimatePoller(pollToken);
|
||||||
}
|
}
|
||||||
|
@ -2,11 +2,7 @@ import { useDispatch, useSelector } from 'react-redux';
|
|||||||
|
|
||||||
import { useCallback, useState } from 'react';
|
import { useCallback, useState } from 'react';
|
||||||
import { showSidebar } from '../store/actions';
|
import { showSidebar } from '../store/actions';
|
||||||
import {
|
import { setCustomGasLimit, setCustomGasPrice } from '../ducks/gas/gas.duck';
|
||||||
fetchBasicGasEstimates,
|
|
||||||
setCustomGasPriceForRetry,
|
|
||||||
setCustomGasLimit,
|
|
||||||
} from '../ducks/gas/gas.duck';
|
|
||||||
import { getIsMainnet } from '../selectors';
|
import { getIsMainnet } from '../selectors';
|
||||||
import { isLegacyTransaction } from '../../shared/modules/transaction.utils';
|
import { isLegacyTransaction } from '../../shared/modules/transaction.utils';
|
||||||
import { useMetricEvent } from './useMetricEvent';
|
import { useMetricEvent } from './useMetricEvent';
|
||||||
@ -29,6 +25,7 @@ import { useIncrementedGasFees } from './useIncrementedGasFees';
|
|||||||
export function useRetryTransaction(transactionGroup) {
|
export function useRetryTransaction(transactionGroup) {
|
||||||
const { primaryTransaction } = transactionGroup;
|
const { primaryTransaction } = transactionGroup;
|
||||||
const isMainnet = useSelector(getIsMainnet);
|
const isMainnet = useSelector(getIsMainnet);
|
||||||
|
|
||||||
const hideBasic = !(isMainnet || process.env.IN_TEST);
|
const hideBasic = !(isMainnet || process.env.IN_TEST);
|
||||||
const customGasSettings = useIncrementedGasFees(transactionGroup);
|
const customGasSettings = useIncrementedGasFees(transactionGroup);
|
||||||
const trackMetricsEvent = useMetricEvent({
|
const trackMetricsEvent = useMetricEvent({
|
||||||
@ -51,12 +48,11 @@ export function useRetryTransaction(transactionGroup) {
|
|||||||
if (process.env.SHOW_EIP_1559_UI) {
|
if (process.env.SHOW_EIP_1559_UI) {
|
||||||
setShowRetryEditGasPopover(true);
|
setShowRetryEditGasPopover(true);
|
||||||
} else {
|
} else {
|
||||||
await dispatch(fetchBasicGasEstimates);
|
|
||||||
if (isLegacyTransaction(primaryTransaction)) {
|
if (isLegacyTransaction(primaryTransaction)) {
|
||||||
// To support the current process of cancelling or speeding up
|
// To support the current process of cancelling or speeding up
|
||||||
// a transaction, we have to inform the custom gas state of the new
|
// a transaction, we have to inform the custom gas state of the new
|
||||||
// gasPrice to start at.
|
// gasPrice to start at.
|
||||||
dispatch(setCustomGasPriceForRetry(customGasSettings.gasPrice));
|
dispatch(setCustomGasPrice(customGasSettings.gasPrice));
|
||||||
dispatch(setCustomGasLimit(primaryTransaction.txParams.gas));
|
dispatch(setCustomGasLimit(primaryTransaction.txParams.gas));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,6 +8,10 @@ import * as methodDataHook from './useMethodData';
|
|||||||
import * as metricEventHook from './useMetricEvent';
|
import * as metricEventHook from './useMetricEvent';
|
||||||
import { useRetryTransaction } from './useRetryTransaction';
|
import { useRetryTransaction } from './useRetryTransaction';
|
||||||
|
|
||||||
|
jest.mock('./useGasFeeEstimates', () => ({
|
||||||
|
useGasFeeEstimates: jest.fn(),
|
||||||
|
}));
|
||||||
|
|
||||||
describe('useRetryTransaction', () => {
|
describe('useRetryTransaction', () => {
|
||||||
describe('when transaction meets retry enabled criteria', () => {
|
describe('when transaction meets retry enabled criteria', () => {
|
||||||
let useSelector;
|
let useSelector;
|
||||||
|
@ -16,8 +16,9 @@ export default class ConfirmSendEther extends Component {
|
|||||||
|
|
||||||
handleEdit({ txData }) {
|
handleEdit({ txData }) {
|
||||||
const { editTransaction, history } = this.props;
|
const { editTransaction, history } = this.props;
|
||||||
editTransaction(txData);
|
editTransaction(txData).then(() => {
|
||||||
history.push(SEND_ROUTE);
|
history.push(SEND_ROUTE);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
shouldHideData() {
|
shouldHideData() {
|
||||||
|
@ -17,9 +17,9 @@ const mapStateToProps = (state) => {
|
|||||||
|
|
||||||
const mapDispatchToProps = (dispatch) => {
|
const mapDispatchToProps = (dispatch) => {
|
||||||
return {
|
return {
|
||||||
editTransaction: (txData) => {
|
editTransaction: async (txData) => {
|
||||||
const { id } = txData;
|
const { id } = txData;
|
||||||
dispatch(editTransaction(ASSET_TYPES.NATIVE, id.toString()));
|
await dispatch(editTransaction(ASSET_TYPES.NATIVE, id.toString()));
|
||||||
dispatch(clearConfirmTransaction());
|
dispatch(clearConfirmTransaction());
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -25,6 +25,10 @@ import {
|
|||||||
ENCRYPTION_PUBLIC_KEY_REQUEST_PATH,
|
ENCRYPTION_PUBLIC_KEY_REQUEST_PATH,
|
||||||
DEFAULT_ROUTE,
|
DEFAULT_ROUTE,
|
||||||
} from '../../helpers/constants/routes';
|
} from '../../helpers/constants/routes';
|
||||||
|
import {
|
||||||
|
disconnectGasFeeEstimatePoller,
|
||||||
|
getGasFeeEstimatesAndStartPolling,
|
||||||
|
} from '../../store/actions';
|
||||||
import ConfTx from './conf-tx';
|
import ConfTx from './conf-tx';
|
||||||
|
|
||||||
export default class ConfirmTransaction extends Component {
|
export default class ConfirmTransaction extends Component {
|
||||||
@ -38,7 +42,6 @@ export default class ConfirmTransaction extends Component {
|
|||||||
sendTo: PropTypes.string,
|
sendTo: PropTypes.string,
|
||||||
setTransactionToConfirm: PropTypes.func,
|
setTransactionToConfirm: PropTypes.func,
|
||||||
clearConfirmTransaction: PropTypes.func,
|
clearConfirmTransaction: PropTypes.func,
|
||||||
fetchBasicGasEstimates: PropTypes.func,
|
|
||||||
mostRecentOverviewPage: PropTypes.string.isRequired,
|
mostRecentOverviewPage: PropTypes.string.isRequired,
|
||||||
transaction: PropTypes.object,
|
transaction: PropTypes.object,
|
||||||
getContractMethodData: PropTypes.func,
|
getContractMethodData: PropTypes.func,
|
||||||
@ -49,14 +52,19 @@ export default class ConfirmTransaction extends Component {
|
|||||||
setDefaultHomeActiveTabName: PropTypes.func,
|
setDefaultHomeActiveTabName: PropTypes.func,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.state = {};
|
||||||
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
|
this._isMounted = true;
|
||||||
const {
|
const {
|
||||||
totalUnapprovedCount = 0,
|
totalUnapprovedCount = 0,
|
||||||
sendTo,
|
sendTo,
|
||||||
history,
|
history,
|
||||||
mostRecentOverviewPage,
|
mostRecentOverviewPage,
|
||||||
transaction: { txParams: { data, to } = {} } = {},
|
transaction: { txParams: { data, to } = {} } = {},
|
||||||
fetchBasicGasEstimates,
|
|
||||||
getContractMethodData,
|
getContractMethodData,
|
||||||
transactionId,
|
transactionId,
|
||||||
paramsTransactionId,
|
paramsTransactionId,
|
||||||
@ -64,12 +72,19 @@ export default class ConfirmTransaction extends Component {
|
|||||||
isTokenMethodAction,
|
isTokenMethodAction,
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
|
getGasFeeEstimatesAndStartPolling().then((pollingToken) => {
|
||||||
|
if (this._isMounted) {
|
||||||
|
this.setState({ pollingToken });
|
||||||
|
} else {
|
||||||
|
disconnectGasFeeEstimatePoller(pollingToken);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
if (!totalUnapprovedCount && !sendTo) {
|
if (!totalUnapprovedCount && !sendTo) {
|
||||||
history.replace(mostRecentOverviewPage);
|
history.replace(mostRecentOverviewPage);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
fetchBasicGasEstimates();
|
|
||||||
getContractMethodData(data);
|
getContractMethodData(data);
|
||||||
if (isTokenMethodAction) {
|
if (isTokenMethodAction) {
|
||||||
getTokenParams(to);
|
getTokenParams(to);
|
||||||
@ -80,6 +95,13 @@ export default class ConfirmTransaction extends Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
componentWillUnmount() {
|
||||||
|
this._isMounted = false;
|
||||||
|
if (this.state.pollingToken) {
|
||||||
|
disconnectGasFeeEstimatePoller(this.state.pollingToken);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
componentDidUpdate(prevProps) {
|
componentDidUpdate(prevProps) {
|
||||||
const {
|
const {
|
||||||
setTransactionToConfirm,
|
setTransactionToConfirm,
|
||||||
|
@ -6,7 +6,6 @@ import {
|
|||||||
clearConfirmTransaction,
|
clearConfirmTransaction,
|
||||||
} from '../../ducks/confirm-transaction/confirm-transaction.duck';
|
} from '../../ducks/confirm-transaction/confirm-transaction.duck';
|
||||||
import { isTokenMethodAction } from '../../helpers/utils/transactions.util';
|
import { isTokenMethodAction } from '../../helpers/utils/transactions.util';
|
||||||
import { fetchBasicGasEstimates } from '../../ducks/gas/gas.duck';
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
getContractMethodData,
|
getContractMethodData,
|
||||||
@ -54,7 +53,6 @@ const mapDispatchToProps = (dispatch) => {
|
|||||||
dispatch(setTransactionToConfirm(transactionId));
|
dispatch(setTransactionToConfirm(transactionId));
|
||||||
},
|
},
|
||||||
clearConfirmTransaction: () => dispatch(clearConfirmTransaction()),
|
clearConfirmTransaction: () => dispatch(clearConfirmTransaction()),
|
||||||
fetchBasicGasEstimates: () => dispatch(fetchBasicGasEstimates()),
|
|
||||||
getContractMethodData: (data) => dispatch(getContractMethodData(data)),
|
getContractMethodData: (data) => dispatch(getContractMethodData(data)),
|
||||||
getTokenParams: (tokenAddress) => dispatch(getTokenParams(tokenAddress)),
|
getTokenParams: (tokenAddress) => dispatch(getTokenParams(tokenAddress)),
|
||||||
setDefaultHomeActiveTabName: (tabName) =>
|
setDefaultHomeActiveTabName: (tabName) =>
|
||||||
|
@ -5,6 +5,7 @@ import thunk from 'redux-thunk';
|
|||||||
import { fireEvent } from '@testing-library/react';
|
import { fireEvent } from '@testing-library/react';
|
||||||
import { initialState, SEND_STATUSES } from '../../../../../ducks/send';
|
import { initialState, SEND_STATUSES } from '../../../../../ducks/send';
|
||||||
import { renderWithProvider } from '../../../../../../test/jest';
|
import { renderWithProvider } from '../../../../../../test/jest';
|
||||||
|
import { GAS_ESTIMATE_TYPES } from '../../../../../../shared/constants/gas';
|
||||||
import AmountMaxButton from './amount-max-button';
|
import AmountMaxButton from './amount-max-button';
|
||||||
|
|
||||||
const middleware = [thunk];
|
const middleware = [thunk];
|
||||||
@ -15,8 +16,13 @@ describe('AmountMaxButton Component', () => {
|
|||||||
const { getByText } = renderWithProvider(
|
const { getByText } = renderWithProvider(
|
||||||
<AmountMaxButton />,
|
<AmountMaxButton />,
|
||||||
configureMockStore(middleware)({
|
configureMockStore(middleware)({
|
||||||
|
metamask: {
|
||||||
|
gasEstimateType: GAS_ESTIMATE_TYPES.NONE,
|
||||||
|
networkDetails: {
|
||||||
|
EIPS: {},
|
||||||
|
},
|
||||||
|
},
|
||||||
send: initialState,
|
send: initialState,
|
||||||
gas: { basicEstimateStatus: 'LOADING' },
|
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
expect(getByText('Max')).toBeTruthy();
|
expect(getByText('Max')).toBeTruthy();
|
||||||
@ -24,8 +30,13 @@ describe('AmountMaxButton Component', () => {
|
|||||||
|
|
||||||
it('should dispatch action to set mode to MAX', () => {
|
it('should dispatch action to set mode to MAX', () => {
|
||||||
const store = configureMockStore(middleware)({
|
const store = configureMockStore(middleware)({
|
||||||
|
metamask: {
|
||||||
|
gasEstimateType: GAS_ESTIMATE_TYPES.ETH_GASPRICE,
|
||||||
|
networkDetails: {
|
||||||
|
EIPS: {},
|
||||||
|
},
|
||||||
|
},
|
||||||
send: { ...initialState, status: SEND_STATUSES.VALID },
|
send: { ...initialState, status: SEND_STATUSES.VALID },
|
||||||
gas: { basicEstimateStatus: 'READY' },
|
|
||||||
});
|
});
|
||||||
const { getByText } = renderWithProvider(<AmountMaxButton />, store);
|
const { getByText } = renderWithProvider(<AmountMaxButton />, store);
|
||||||
|
|
||||||
@ -40,12 +51,17 @@ describe('AmountMaxButton Component', () => {
|
|||||||
|
|
||||||
it('should dispatch action to set amount mode to INPUT', () => {
|
it('should dispatch action to set amount mode to INPUT', () => {
|
||||||
const store = configureMockStore(middleware)({
|
const store = configureMockStore(middleware)({
|
||||||
|
metamask: {
|
||||||
|
gasEstimateType: GAS_ESTIMATE_TYPES.ETH_GASPRICE,
|
||||||
|
networkDetails: {
|
||||||
|
EIPS: {},
|
||||||
|
},
|
||||||
|
},
|
||||||
send: {
|
send: {
|
||||||
...initialState,
|
...initialState,
|
||||||
status: SEND_STATUSES.VALID,
|
status: SEND_STATUSES.VALID,
|
||||||
amount: { ...initialState.amount, mode: 'MAX' },
|
amount: { ...initialState.amount, mode: 'MAX' },
|
||||||
},
|
},
|
||||||
gas: { basicEstimateStatus: 'READY' },
|
|
||||||
});
|
});
|
||||||
const { getByText } = renderWithProvider(<AmountMaxButton />, store);
|
const { getByText } = renderWithProvider(<AmountMaxButton />, store);
|
||||||
|
|
||||||
|
@ -8,6 +8,7 @@ import { initialState, SEND_STAGES } from '../../ducks/send';
|
|||||||
import { ensInitialState } from '../../ducks/ens';
|
import { ensInitialState } from '../../ducks/ens';
|
||||||
import { renderWithProvider } from '../../../test/jest';
|
import { renderWithProvider } from '../../../test/jest';
|
||||||
import { RINKEBY_CHAIN_ID } from '../../../shared/constants/network';
|
import { RINKEBY_CHAIN_ID } from '../../../shared/constants/network';
|
||||||
|
import { GAS_ESTIMATE_TYPES } from '../../../shared/constants/gas';
|
||||||
import Send from './send';
|
import Send from './send';
|
||||||
|
|
||||||
const middleware = [thunk];
|
const middleware = [thunk];
|
||||||
@ -37,12 +38,19 @@ const baseStore = {
|
|||||||
send: initialState,
|
send: initialState,
|
||||||
ENS: ensInitialState,
|
ENS: ensInitialState,
|
||||||
gas: {
|
gas: {
|
||||||
basicEstimateStatus: 'READY',
|
|
||||||
basicEstimates: { slow: '0x0', average: '0x1', fast: '0x2' },
|
|
||||||
customData: { limit: null, price: null },
|
customData: { limit: null, price: null },
|
||||||
},
|
},
|
||||||
history: { mostRecentOverviewPage: 'activity' },
|
history: { mostRecentOverviewPage: 'activity' },
|
||||||
metamask: {
|
metamask: {
|
||||||
|
gasEstimateType: GAS_ESTIMATE_TYPES.LEGACY,
|
||||||
|
gasFeeEstimates: {
|
||||||
|
low: '0',
|
||||||
|
medium: '1',
|
||||||
|
fast: '2',
|
||||||
|
},
|
||||||
|
networkDetails: {
|
||||||
|
EIPS: {},
|
||||||
|
},
|
||||||
tokens: [],
|
tokens: [],
|
||||||
preferences: {
|
preferences: {
|
||||||
useNativeCurrencyAsPrimaryCurrency: false,
|
useNativeCurrencyAsPrimaryCurrency: false,
|
||||||
@ -82,12 +90,6 @@ describe('Send Page', () => {
|
|||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
type: 'send/initializeSendState/pending',
|
type: 'send/initializeSendState/pending',
|
||||||
}),
|
}),
|
||||||
expect.objectContaining({
|
|
||||||
type: 'metamask/gas/BASIC_GAS_ESTIMATE_STATUS',
|
|
||||||
}),
|
|
||||||
expect.objectContaining({
|
|
||||||
type: 'metamask/gas/SET_ESTIMATE_SOURCE',
|
|
||||||
}),
|
|
||||||
]),
|
]),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@ -105,12 +107,6 @@ describe('Send Page', () => {
|
|||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
type: 'send/initializeSendState/pending',
|
type: 'send/initializeSendState/pending',
|
||||||
}),
|
}),
|
||||||
expect.objectContaining({
|
|
||||||
type: 'metamask/gas/BASIC_GAS_ESTIMATE_STATUS',
|
|
||||||
}),
|
|
||||||
expect.objectContaining({
|
|
||||||
type: 'metamask/gas/SET_ESTIMATE_SOURCE',
|
|
||||||
}),
|
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
type: 'UI_MODAL_OPEN',
|
type: 'UI_MODAL_OPEN',
|
||||||
payload: { name: 'QR_SCANNER' },
|
payload: { name: 'QR_SCANNER' },
|
||||||
|
@ -8,10 +8,17 @@ import { decEthToConvertedCurrency as ethTotalToConvertedCurrency } from '../hel
|
|||||||
import { formatETHFee } from '../helpers/utils/formatters';
|
import { formatETHFee } from '../helpers/utils/formatters';
|
||||||
import { calcGasTotal } from '../pages/send/send.utils';
|
import { calcGasTotal } from '../pages/send/send.utils';
|
||||||
|
|
||||||
import { GAS_ESTIMATE_TYPES } from '../helpers/constants/common';
|
|
||||||
import { getGasPrice } from '../ducks/send';
|
import { getGasPrice } from '../ducks/send';
|
||||||
import { BASIC_ESTIMATE_STATES, GAS_SOURCE } from '../ducks/gas/gas.duck';
|
import {
|
||||||
import { GAS_LIMITS } from '../../shared/constants/gas';
|
GAS_ESTIMATE_TYPES as GAS_FEE_CONTROLLER_ESTIMATE_TYPES,
|
||||||
|
GAS_LIMITS,
|
||||||
|
} from '../../shared/constants/gas';
|
||||||
|
import {
|
||||||
|
getGasEstimateType,
|
||||||
|
getGasFeeEstimates,
|
||||||
|
isEIP1559Network,
|
||||||
|
} from '../ducks/metamask/metamask';
|
||||||
|
import { GAS_ESTIMATE_TYPES } from '../helpers/constants/common';
|
||||||
import { getCurrentCurrency, getIsMainnet, getShouldShowFiat } from '.';
|
import { getCurrentCurrency, getIsMainnet, getShouldShowFiat } from '.';
|
||||||
|
|
||||||
const NUMBER_OF_DECIMALS_SM_BTNS = 5;
|
const NUMBER_OF_DECIMALS_SM_BTNS = 5;
|
||||||
@ -25,13 +32,12 @@ export function getCustomGasPrice(state) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function getBasicGasEstimateLoadingStatus(state) {
|
export function getBasicGasEstimateLoadingStatus(state) {
|
||||||
return state.gas.basicEstimateStatus === 'LOADING';
|
return getIsGasEstimatesFetched(state) === false;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getAveragePriceEstimateInHexWEI(state) {
|
export function getAveragePriceEstimateInHexWEI(state) {
|
||||||
const averagePriceEstimate = state.gas.basicEstimates
|
const averagePriceEstimate = getAverageEstimate(state);
|
||||||
? state.gas.basicEstimates.average
|
|
||||||
: '0x0';
|
|
||||||
return getGasPriceInHexWei(averagePriceEstimate);
|
return getGasPriceInHexWei(averagePriceEstimate);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -51,23 +57,31 @@ export function getDefaultActiveButtonIndex(
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function getSafeLowEstimate(state) {
|
export function getSafeLowEstimate(state) {
|
||||||
const {
|
const gasFeeEstimates = getGasFeeEstimates(state);
|
||||||
gas: {
|
const gasEstimateType = getGasEstimateType(state);
|
||||||
basicEstimates: { safeLow },
|
|
||||||
},
|
|
||||||
} = state;
|
|
||||||
|
|
||||||
return safeLow;
|
return gasEstimateType === GAS_FEE_CONTROLLER_ESTIMATE_TYPES.LEGACY
|
||||||
|
? gasFeeEstimates?.low
|
||||||
|
: null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getAverageEstimate(state) {
|
||||||
|
const gasFeeEstimates = getGasFeeEstimates(state);
|
||||||
|
const gasEstimateType = getGasEstimateType(state);
|
||||||
|
|
||||||
|
return gasEstimateType === GAS_FEE_CONTROLLER_ESTIMATE_TYPES.LEGACY
|
||||||
|
? gasFeeEstimates?.medium
|
||||||
|
: null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getFastPriceEstimate(state) {
|
export function getFastPriceEstimate(state) {
|
||||||
const {
|
const gasFeeEstimates = getGasFeeEstimates(state);
|
||||||
gas: {
|
|
||||||
basicEstimates: { fast },
|
|
||||||
},
|
|
||||||
} = state;
|
|
||||||
|
|
||||||
return fast;
|
const gasEstimateType = getGasEstimateType(state);
|
||||||
|
|
||||||
|
return gasEstimateType === GAS_FEE_CONTROLLER_ESTIMATE_TYPES.LEGACY
|
||||||
|
? gasFeeEstimates?.high
|
||||||
|
: null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isCustomPriceSafe(state) {
|
export function isCustomPriceSafe(state) {
|
||||||
@ -97,7 +111,7 @@ export function isCustomPriceSafe(state) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function isCustomPriceSafeForCustomNetwork(state) {
|
export function isCustomPriceSafeForCustomNetwork(state) {
|
||||||
const estimatedPrice = state.gas.basicEstimates.average;
|
const estimatedPrice = getAverageEstimate(state);
|
||||||
|
|
||||||
const customGasPrice = getCustomGasPrice(state);
|
const customGasPrice = getCustomGasPrice(state);
|
||||||
|
|
||||||
@ -219,61 +233,56 @@ export function getRenderableGasButtonData(
|
|||||||
currentCurrency,
|
currentCurrency,
|
||||||
nativeCurrency,
|
nativeCurrency,
|
||||||
) {
|
) {
|
||||||
const { safeLow, average, fast } = estimates;
|
const { low, medium, high } = estimates;
|
||||||
|
|
||||||
const slowEstimateData = {
|
const slowEstimateData = {
|
||||||
gasEstimateType: GAS_ESTIMATE_TYPES.SLOW,
|
gasEstimateType: GAS_ESTIMATE_TYPES.SLOW,
|
||||||
feeInPrimaryCurrency: getRenderableEthFee(
|
feeInPrimaryCurrency: getRenderableEthFee(low, gasLimit, 9, nativeCurrency),
|
||||||
safeLow,
|
|
||||||
gasLimit,
|
|
||||||
9,
|
|
||||||
nativeCurrency,
|
|
||||||
),
|
|
||||||
feeInSecondaryCurrency: showFiat
|
feeInSecondaryCurrency: showFiat
|
||||||
? getRenderableConvertedCurrencyFee(
|
? getRenderableConvertedCurrencyFee(
|
||||||
safeLow,
|
low,
|
||||||
gasLimit,
|
gasLimit,
|
||||||
currentCurrency,
|
currentCurrency,
|
||||||
conversionRate,
|
conversionRate,
|
||||||
)
|
)
|
||||||
: '',
|
: '',
|
||||||
priceInHexWei: getGasPriceInHexWei(safeLow),
|
priceInHexWei: getGasPriceInHexWei(low),
|
||||||
};
|
};
|
||||||
const averageEstimateData = {
|
const averageEstimateData = {
|
||||||
gasEstimateType: GAS_ESTIMATE_TYPES.AVERAGE,
|
gasEstimateType: GAS_ESTIMATE_TYPES.AVERAGE,
|
||||||
feeInPrimaryCurrency: getRenderableEthFee(
|
feeInPrimaryCurrency: getRenderableEthFee(
|
||||||
average,
|
medium,
|
||||||
gasLimit,
|
gasLimit,
|
||||||
9,
|
9,
|
||||||
nativeCurrency,
|
nativeCurrency,
|
||||||
),
|
),
|
||||||
feeInSecondaryCurrency: showFiat
|
feeInSecondaryCurrency: showFiat
|
||||||
? getRenderableConvertedCurrencyFee(
|
? getRenderableConvertedCurrencyFee(
|
||||||
average,
|
medium,
|
||||||
gasLimit,
|
gasLimit,
|
||||||
currentCurrency,
|
currentCurrency,
|
||||||
conversionRate,
|
conversionRate,
|
||||||
)
|
)
|
||||||
: '',
|
: '',
|
||||||
priceInHexWei: getGasPriceInHexWei(average),
|
priceInHexWei: getGasPriceInHexWei(medium),
|
||||||
};
|
};
|
||||||
const fastEstimateData = {
|
const fastEstimateData = {
|
||||||
gasEstimateType: GAS_ESTIMATE_TYPES.FAST,
|
gasEstimateType: GAS_ESTIMATE_TYPES.FAST,
|
||||||
feeInPrimaryCurrency: getRenderableEthFee(
|
feeInPrimaryCurrency: getRenderableEthFee(
|
||||||
fast,
|
high,
|
||||||
gasLimit,
|
gasLimit,
|
||||||
9,
|
9,
|
||||||
nativeCurrency,
|
nativeCurrency,
|
||||||
),
|
),
|
||||||
feeInSecondaryCurrency: showFiat
|
feeInSecondaryCurrency: showFiat
|
||||||
? getRenderableConvertedCurrencyFee(
|
? getRenderableConvertedCurrencyFee(
|
||||||
fast,
|
high,
|
||||||
gasLimit,
|
gasLimit,
|
||||||
currentCurrency,
|
currentCurrency,
|
||||||
conversionRate,
|
conversionRate,
|
||||||
)
|
)
|
||||||
: '',
|
: '',
|
||||||
priceInHexWei: getGasPriceInHexWei(fast),
|
priceInHexWei: getGasPriceInHexWei(high),
|
||||||
};
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@ -297,7 +306,7 @@ export function getRenderableBasicEstimateData(state, gasLimit) {
|
|||||||
averageEstimateData,
|
averageEstimateData,
|
||||||
fastEstimateData,
|
fastEstimateData,
|
||||||
} = getRenderableGasButtonData(
|
} = getRenderableGasButtonData(
|
||||||
state.gas.basicEstimates,
|
getGasFeeEstimates(state),
|
||||||
gasLimit,
|
gasLimit,
|
||||||
showFiat,
|
showFiat,
|
||||||
conversionRate,
|
conversionRate,
|
||||||
@ -308,7 +317,7 @@ export function getRenderableBasicEstimateData(state, gasLimit) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function getRenderableEstimateDataForSmallButtonsFromGWEI(state) {
|
export function getRenderableEstimateDataForSmallButtonsFromGWEI(state) {
|
||||||
if (getBasicGasEstimateLoadingStatus(state)) {
|
if (getIsGasEstimatesFetched(state) === false) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
const showFiat = getShouldShowFiat(state);
|
const showFiat = getShouldShowFiat(state);
|
||||||
@ -316,94 +325,88 @@ export function getRenderableEstimateDataForSmallButtonsFromGWEI(state) {
|
|||||||
state.send.gas.gasLimit || getCustomGasLimit(state) || GAS_LIMITS.SIMPLE;
|
state.send.gas.gasLimit || getCustomGasLimit(state) || GAS_LIMITS.SIMPLE;
|
||||||
const { conversionRate } = state.metamask;
|
const { conversionRate } = state.metamask;
|
||||||
const currentCurrency = getCurrentCurrency(state);
|
const currentCurrency = getCurrentCurrency(state);
|
||||||
const {
|
const gasFeeEstimates = getGasFeeEstimates(state);
|
||||||
gas: {
|
|
||||||
basicEstimates: { safeLow, average, fast },
|
|
||||||
},
|
|
||||||
} = state;
|
|
||||||
|
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
gasEstimateType: GAS_ESTIMATE_TYPES.SLOW,
|
gasEstimateType: GAS_ESTIMATE_TYPES.SLOW,
|
||||||
feeInSecondaryCurrency: showFiat
|
feeInSecondaryCurrency: showFiat
|
||||||
? getRenderableConvertedCurrencyFee(
|
? getRenderableConvertedCurrencyFee(
|
||||||
safeLow,
|
gasFeeEstimates.low,
|
||||||
gasLimit,
|
gasLimit,
|
||||||
currentCurrency,
|
currentCurrency,
|
||||||
conversionRate,
|
conversionRate,
|
||||||
)
|
)
|
||||||
: '',
|
: '',
|
||||||
feeInPrimaryCurrency: getRenderableEthFee(
|
feeInPrimaryCurrency: getRenderableEthFee(
|
||||||
safeLow,
|
gasFeeEstimates.low,
|
||||||
gasLimit,
|
gasLimit,
|
||||||
NUMBER_OF_DECIMALS_SM_BTNS,
|
NUMBER_OF_DECIMALS_SM_BTNS,
|
||||||
),
|
),
|
||||||
priceInHexWei: getGasPriceInHexWei(safeLow, true),
|
priceInHexWei: getGasPriceInHexWei(gasFeeEstimates.low, true),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
gasEstimateType: GAS_ESTIMATE_TYPES.AVERAGE,
|
gasEstimateType: GAS_ESTIMATE_TYPES.AVERAGE,
|
||||||
feeInSecondaryCurrency: showFiat
|
feeInSecondaryCurrency: showFiat
|
||||||
? getRenderableConvertedCurrencyFee(
|
? getRenderableConvertedCurrencyFee(
|
||||||
average,
|
gasFeeEstimates.medium,
|
||||||
gasLimit,
|
gasLimit,
|
||||||
currentCurrency,
|
currentCurrency,
|
||||||
conversionRate,
|
conversionRate,
|
||||||
)
|
)
|
||||||
: '',
|
: '',
|
||||||
feeInPrimaryCurrency: getRenderableEthFee(
|
feeInPrimaryCurrency: getRenderableEthFee(
|
||||||
average,
|
gasFeeEstimates.medium,
|
||||||
gasLimit,
|
gasLimit,
|
||||||
NUMBER_OF_DECIMALS_SM_BTNS,
|
NUMBER_OF_DECIMALS_SM_BTNS,
|
||||||
),
|
),
|
||||||
priceInHexWei: getGasPriceInHexWei(average, true),
|
priceInHexWei: getGasPriceInHexWei(gasFeeEstimates.medium, true),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
gasEstimateType: GAS_ESTIMATE_TYPES.FAST,
|
gasEstimateType: GAS_ESTIMATE_TYPES.FAST,
|
||||||
feeInSecondaryCurrency: showFiat
|
feeInSecondaryCurrency: showFiat
|
||||||
? getRenderableConvertedCurrencyFee(
|
? getRenderableConvertedCurrencyFee(
|
||||||
fast,
|
gasFeeEstimates.high,
|
||||||
gasLimit,
|
gasLimit,
|
||||||
currentCurrency,
|
currentCurrency,
|
||||||
conversionRate,
|
conversionRate,
|
||||||
)
|
)
|
||||||
: '',
|
: '',
|
||||||
feeInPrimaryCurrency: getRenderableEthFee(
|
feeInPrimaryCurrency: getRenderableEthFee(
|
||||||
fast,
|
gasFeeEstimates.high,
|
||||||
gasLimit,
|
gasLimit,
|
||||||
NUMBER_OF_DECIMALS_SM_BTNS,
|
NUMBER_OF_DECIMALS_SM_BTNS,
|
||||||
),
|
),
|
||||||
priceInHexWei: getGasPriceInHexWei(fast, true),
|
priceInHexWei: getGasPriceInHexWei(gasFeeEstimates.high, true),
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getIsEthGasPriceFetched(state) {
|
export function getIsEthGasPriceFetched(state) {
|
||||||
const gasState = state.gas;
|
const gasEstimateType = getGasEstimateType(state);
|
||||||
return Boolean(
|
return (
|
||||||
gasState.estimateSource === GAS_SOURCE.ETHGASPRICE &&
|
gasEstimateType === GAS_FEE_CONTROLLER_ESTIMATE_TYPES.ETH_GASPRICE &&
|
||||||
gasState.basicEstimateStatus === BASIC_ESTIMATE_STATES.READY &&
|
getIsMainnet(state)
|
||||||
getIsMainnet(state),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getIsCustomNetworkGasPriceFetched(state) {
|
export function getIsCustomNetworkGasPriceFetched(state) {
|
||||||
const gasState = state.gas;
|
const gasEstimateType = getGasEstimateType(state);
|
||||||
return Boolean(
|
return (
|
||||||
gasState.estimateSource === GAS_SOURCE.ETHGASPRICE &&
|
gasEstimateType === GAS_FEE_CONTROLLER_ESTIMATE_TYPES.ETH_GASPRICE &&
|
||||||
gasState.basicEstimateStatus === BASIC_ESTIMATE_STATES.READY &&
|
!getIsMainnet(state)
|
||||||
!getIsMainnet(state),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getNoGasPriceFetched(state) {
|
export function getNoGasPriceFetched(state) {
|
||||||
const gasState = state.gas;
|
const gasEstimateType = getGasEstimateType(state);
|
||||||
return Boolean(gasState.basicEstimateStatus === BASIC_ESTIMATE_STATES.FAILED);
|
return gasEstimateType === GAS_FEE_CONTROLLER_ESTIMATE_TYPES.NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getIsGasEstimatesFetched(state) {
|
export function getIsGasEstimatesFetched(state) {
|
||||||
const gasState = state.gas;
|
const gasEstimateType = getGasEstimateType(state);
|
||||||
return Boolean(
|
if (isEIP1559Network(state)) {
|
||||||
gasState.estimateSource === GAS_SOURCE.METASWAPS &&
|
return false;
|
||||||
gasState.basicEstimateStatus === BASIC_ESTIMATE_STATES.READY,
|
}
|
||||||
);
|
return gasEstimateType !== GAS_FEE_CONTROLLER_ESTIMATE_TYPES.NONE;
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { GAS_LIMITS } from '../../shared/constants/gas';
|
import { GAS_ESTIMATE_TYPES, GAS_LIMITS } from '../../shared/constants/gas';
|
||||||
import {
|
import {
|
||||||
getCustomGasLimit,
|
getCustomGasLimit,
|
||||||
getCustomGasPrice,
|
getCustomGasPrice,
|
||||||
@ -18,36 +18,68 @@ describe('custom-gas selectors', () => {
|
|||||||
describe('isCustomGasPriceSafe()', () => {
|
describe('isCustomGasPriceSafe()', () => {
|
||||||
it('should return true for gas.customData.price 0x77359400', () => {
|
it('should return true for gas.customData.price 0x77359400', () => {
|
||||||
const mockState = {
|
const mockState = {
|
||||||
|
metamask: {
|
||||||
|
gasEstimateType: GAS_ESTIMATE_TYPES.LEGACY,
|
||||||
|
gasFeeEstimates: {
|
||||||
|
low: '1',
|
||||||
|
},
|
||||||
|
networkDetails: {
|
||||||
|
EIPS: {},
|
||||||
|
},
|
||||||
|
},
|
||||||
gas: {
|
gas: {
|
||||||
customData: { price: '0x77359400' },
|
customData: { price: '0x77359400' },
|
||||||
basicEstimates: { safeLow: 1 },
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
expect(isCustomPriceSafe(mockState)).toStrictEqual(true);
|
expect(isCustomPriceSafe(mockState)).toStrictEqual(true);
|
||||||
});
|
});
|
||||||
it('should return true for gas.customData.price null', () => {
|
it('should return true for gas.customData.price null', () => {
|
||||||
const mockState = {
|
const mockState = {
|
||||||
|
metamask: {
|
||||||
|
gasEstimateType: GAS_ESTIMATE_TYPES.LEGACY,
|
||||||
|
gasFeeEstimates: {
|
||||||
|
low: '1',
|
||||||
|
},
|
||||||
|
networkDetails: {
|
||||||
|
EIPS: {},
|
||||||
|
},
|
||||||
|
},
|
||||||
gas: {
|
gas: {
|
||||||
customData: { price: null },
|
customData: { price: null },
|
||||||
basicEstimates: { safeLow: 1 },
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
expect(isCustomPriceSafe(mockState)).toStrictEqual(true);
|
expect(isCustomPriceSafe(mockState)).toStrictEqual(true);
|
||||||
});
|
});
|
||||||
it('should return true gas.customData.price undefined', () => {
|
it('should return true gas.customData.price undefined', () => {
|
||||||
const mockState = {
|
const mockState = {
|
||||||
|
metamask: {
|
||||||
|
gasEstimateType: GAS_ESTIMATE_TYPES.LEGACY,
|
||||||
|
gasFeeEstimates: {
|
||||||
|
low: '1',
|
||||||
|
},
|
||||||
|
networkDetails: {
|
||||||
|
EIPS: {},
|
||||||
|
},
|
||||||
|
},
|
||||||
gas: {
|
gas: {
|
||||||
customData: { price: undefined },
|
customData: { price: undefined },
|
||||||
basicEstimates: { safeLow: 1 },
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
expect(isCustomPriceSafe(mockState)).toStrictEqual(true);
|
expect(isCustomPriceSafe(mockState)).toStrictEqual(true);
|
||||||
});
|
});
|
||||||
it('should return false gas.basicEstimates.safeLow undefined', () => {
|
it('should return false gas.basicEstimates.safeLow undefined', () => {
|
||||||
const mockState = {
|
const mockState = {
|
||||||
|
metamask: {
|
||||||
|
gasEstimateType: GAS_ESTIMATE_TYPES.NONE,
|
||||||
|
gasFeeEstimates: {
|
||||||
|
low: undefined,
|
||||||
|
},
|
||||||
|
networkDetails: {
|
||||||
|
EIPS: {},
|
||||||
|
},
|
||||||
|
},
|
||||||
gas: {
|
gas: {
|
||||||
customData: { price: '0x77359400' },
|
customData: { price: '0x77359400' },
|
||||||
basicEstimates: { safeLow: undefined },
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
expect(isCustomPriceSafe(mockState)).toStrictEqual(false);
|
expect(isCustomPriceSafe(mockState)).toStrictEqual(false);
|
||||||
@ -57,60 +89,117 @@ describe('custom-gas selectors', () => {
|
|||||||
describe('isCustomPriceExcessive()', () => {
|
describe('isCustomPriceExcessive()', () => {
|
||||||
it('should return false for gas.customData.price null', () => {
|
it('should return false for gas.customData.price null', () => {
|
||||||
const mockState = {
|
const mockState = {
|
||||||
|
metamask: {
|
||||||
|
gasEstimateType: GAS_ESTIMATE_TYPES.LEGACY,
|
||||||
|
gasFeeEstimates: {
|
||||||
|
high: '150',
|
||||||
|
},
|
||||||
|
networkDetails: {
|
||||||
|
EIPS: {},
|
||||||
|
},
|
||||||
|
},
|
||||||
gas: {
|
gas: {
|
||||||
customData: { price: null },
|
customData: { price: null },
|
||||||
basicEstimates: { fast: 150 },
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
expect(isCustomPriceExcessive(mockState)).toStrictEqual(false);
|
expect(isCustomPriceExcessive(mockState)).toStrictEqual(false);
|
||||||
});
|
});
|
||||||
it('should return false gas.basicEstimates.fast undefined', () => {
|
it('should return false gas.basicEstimates.fast undefined', () => {
|
||||||
const mockState = {
|
const mockState = {
|
||||||
|
metamask: {
|
||||||
|
gasEstimateType: GAS_ESTIMATE_TYPES.LEGACY,
|
||||||
|
gasFeeEstimates: {
|
||||||
|
high: undefined,
|
||||||
|
},
|
||||||
|
networkDetails: {
|
||||||
|
EIPS: {},
|
||||||
|
},
|
||||||
|
},
|
||||||
gas: {
|
gas: {
|
||||||
customData: { price: '0x77359400' },
|
customData: { price: '0x77359400' },
|
||||||
basicEstimates: { fast: undefined },
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
expect(isCustomPriceExcessive(mockState)).toStrictEqual(false);
|
expect(isCustomPriceExcessive(mockState)).toStrictEqual(false);
|
||||||
});
|
});
|
||||||
it('should return false gas.basicEstimates.price 0x205d0bae00 (139)', () => {
|
it('should return false gas.basicEstimates.price 0x205d0bae00 (139)', () => {
|
||||||
const mockState = {
|
const mockState = {
|
||||||
|
metamask: {
|
||||||
|
gasEstimateType: GAS_ESTIMATE_TYPES.LEGACY,
|
||||||
|
gasFeeEstimates: {
|
||||||
|
high: '139',
|
||||||
|
},
|
||||||
|
networkDetails: {
|
||||||
|
EIPS: {},
|
||||||
|
},
|
||||||
|
},
|
||||||
gas: {
|
gas: {
|
||||||
customData: { price: '0x205d0bae00' },
|
customData: { price: '0x205d0bae00' },
|
||||||
basicEstimates: { fast: 139 },
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
expect(isCustomPriceExcessive(mockState)).toStrictEqual(false);
|
expect(isCustomPriceExcessive(mockState)).toStrictEqual(false);
|
||||||
});
|
});
|
||||||
it('should return false gas.basicEstimates.price 0x1bf08eb000 (120)', () => {
|
it('should return false gas.basicEstimates.price 0x1bf08eb000 (120)', () => {
|
||||||
const mockState = {
|
const mockState = {
|
||||||
|
metamask: {
|
||||||
|
gasEstimateType: GAS_ESTIMATE_TYPES.LEGACY,
|
||||||
|
gasFeeEstimates: {
|
||||||
|
high: '139',
|
||||||
|
},
|
||||||
|
networkDetails: {
|
||||||
|
EIPS: {},
|
||||||
|
},
|
||||||
|
},
|
||||||
gas: {
|
gas: {
|
||||||
customData: { price: '0x1bf08eb000' },
|
customData: { price: '0x1bf08eb000' },
|
||||||
basicEstimates: { fast: 139 },
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
expect(isCustomPriceExcessive(mockState)).toStrictEqual(false);
|
expect(isCustomPriceExcessive(mockState)).toStrictEqual(false);
|
||||||
});
|
});
|
||||||
it('should return false gas.basicEstimates.price 0x28bed01600 (175)', () => {
|
it('should return false gas.basicEstimates.price 0x28bed01600 (175)', () => {
|
||||||
const mockState = {
|
const mockState = {
|
||||||
|
metamask: {
|
||||||
|
gasEstimateType: GAS_ESTIMATE_TYPES.LEGACY,
|
||||||
|
gasFeeEstimates: {
|
||||||
|
high: '139',
|
||||||
|
},
|
||||||
|
networkDetails: {
|
||||||
|
EIPS: {},
|
||||||
|
},
|
||||||
|
},
|
||||||
gas: {
|
gas: {
|
||||||
customData: { price: '0x28bed01600' },
|
customData: { price: '0x28bed01600' },
|
||||||
basicEstimates: { fast: 139 },
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
expect(isCustomPriceExcessive(mockState)).toStrictEqual(false);
|
expect(isCustomPriceExcessive(mockState)).toStrictEqual(false);
|
||||||
});
|
});
|
||||||
it('should return true gas.basicEstimates.price 0x30e4f9b400 (210)', () => {
|
it('should return true gas.basicEstimates.price 0x30e4f9b400 (210)', () => {
|
||||||
const mockState = {
|
const mockState = {
|
||||||
|
metamask: {
|
||||||
|
gasEstimateType: GAS_ESTIMATE_TYPES.LEGACY,
|
||||||
|
gasFeeEstimates: {
|
||||||
|
high: '139',
|
||||||
|
},
|
||||||
|
networkDetails: {
|
||||||
|
EIPS: {},
|
||||||
|
},
|
||||||
|
},
|
||||||
gas: {
|
gas: {
|
||||||
customData: { price: '0x30e4f9b400' },
|
customData: { price: '0x30e4f9b400' },
|
||||||
basicEstimates: { fast: 139 },
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
expect(isCustomPriceExcessive(mockState)).toStrictEqual(true);
|
expect(isCustomPriceExcessive(mockState)).toStrictEqual(true);
|
||||||
});
|
});
|
||||||
it('should return false gas.basicEstimates.price 0x28bed01600 (175) (checkSend=true)', () => {
|
it('should return false gas.basicEstimates.price 0x28bed01600 (175) (checkSend=true)', () => {
|
||||||
const mockState = {
|
const mockState = {
|
||||||
|
metamask: {
|
||||||
|
gasEstimateType: GAS_ESTIMATE_TYPES.LEGACY,
|
||||||
|
gasFeeEstimates: {
|
||||||
|
high: '139',
|
||||||
|
},
|
||||||
|
networkDetails: {
|
||||||
|
EIPS: {},
|
||||||
|
},
|
||||||
|
},
|
||||||
send: {
|
send: {
|
||||||
gas: {
|
gas: {
|
||||||
gasPrice: '0x28bed0160',
|
gasPrice: '0x28bed0160',
|
||||||
@ -118,13 +207,21 @@ describe('custom-gas selectors', () => {
|
|||||||
},
|
},
|
||||||
gas: {
|
gas: {
|
||||||
customData: { price: null },
|
customData: { price: null },
|
||||||
basicEstimates: { fast: 139 },
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
expect(isCustomPriceExcessive(mockState, true)).toStrictEqual(false);
|
expect(isCustomPriceExcessive(mockState, true)).toStrictEqual(false);
|
||||||
});
|
});
|
||||||
it('should return true gas.basicEstimates.price 0x30e4f9b400 (210) (checkSend=true)', () => {
|
it('should return true gas.basicEstimates.price 0x30e4f9b400 (210) (checkSend=true)', () => {
|
||||||
const mockState = {
|
const mockState = {
|
||||||
|
metamask: {
|
||||||
|
gasEstimateType: GAS_ESTIMATE_TYPES.LEGACY,
|
||||||
|
gasFeeEstimates: {
|
||||||
|
high: '139',
|
||||||
|
},
|
||||||
|
networkDetails: {
|
||||||
|
EIPS: {},
|
||||||
|
},
|
||||||
|
},
|
||||||
send: {
|
send: {
|
||||||
gas: {
|
gas: {
|
||||||
gasPrice: '0x30e4f9b400',
|
gasPrice: '0x30e4f9b400',
|
||||||
@ -132,7 +229,6 @@ describe('custom-gas selectors', () => {
|
|||||||
},
|
},
|
||||||
gas: {
|
gas: {
|
||||||
customData: { price: null },
|
customData: { price: null },
|
||||||
basicEstimates: { fast: 139 },
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
expect(isCustomPriceExcessive(mockState, true)).toStrictEqual(true);
|
expect(isCustomPriceExcessive(mockState, true)).toStrictEqual(true);
|
||||||
@ -171,6 +267,15 @@ describe('custom-gas selectors', () => {
|
|||||||
],
|
],
|
||||||
mockState: {
|
mockState: {
|
||||||
metamask: {
|
metamask: {
|
||||||
|
gasEstimateType: GAS_ESTIMATE_TYPES.LEGACY,
|
||||||
|
gasFeeEstimates: {
|
||||||
|
low: '2.5',
|
||||||
|
medium: '4',
|
||||||
|
high: '5',
|
||||||
|
},
|
||||||
|
networkDetails: {
|
||||||
|
EIPS: {},
|
||||||
|
},
|
||||||
conversionRate: 255.71,
|
conversionRate: 255.71,
|
||||||
currentCurrency: 'usd',
|
currentCurrency: 'usd',
|
||||||
preferences: {
|
preferences: {
|
||||||
@ -181,19 +286,6 @@ describe('custom-gas selectors', () => {
|
|||||||
chainId: '0x1',
|
chainId: '0x1',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
gas: {
|
|
||||||
basicEstimates: {
|
|
||||||
blockTime: 14.16326530612245,
|
|
||||||
safeLow: 2.5,
|
|
||||||
safeLowWait: 6.6,
|
|
||||||
average: 4,
|
|
||||||
avgWait: 5.3,
|
|
||||||
fast: 5,
|
|
||||||
fastWait: 3.3,
|
|
||||||
fastest: 10,
|
|
||||||
fastestWait: 0.5,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -219,6 +311,15 @@ describe('custom-gas selectors', () => {
|
|||||||
],
|
],
|
||||||
mockState: {
|
mockState: {
|
||||||
metamask: {
|
metamask: {
|
||||||
|
gasEstimateType: GAS_ESTIMATE_TYPES.LEGACY,
|
||||||
|
gasFeeEstimates: {
|
||||||
|
low: '5',
|
||||||
|
medium: '7',
|
||||||
|
high: '10',
|
||||||
|
},
|
||||||
|
networkDetails: {
|
||||||
|
EIPS: {},
|
||||||
|
},
|
||||||
conversionRate: 2557.1,
|
conversionRate: 2557.1,
|
||||||
currentCurrency: 'usd',
|
currentCurrency: 'usd',
|
||||||
preferences: {
|
preferences: {
|
||||||
@ -234,19 +335,6 @@ describe('custom-gas selectors', () => {
|
|||||||
gasLimit: GAS_LIMITS.SIMPLE,
|
gasLimit: GAS_LIMITS.SIMPLE,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
gas: {
|
|
||||||
basicEstimates: {
|
|
||||||
blockTime: 14.16326530612245,
|
|
||||||
safeLow: 5,
|
|
||||||
safeLowWait: 13.2,
|
|
||||||
average: 7,
|
|
||||||
avgWait: 10.1,
|
|
||||||
fast: 10,
|
|
||||||
fastWait: 6.6,
|
|
||||||
fastest: 20,
|
|
||||||
fastestWait: 1.0,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -272,6 +360,15 @@ describe('custom-gas selectors', () => {
|
|||||||
],
|
],
|
||||||
mockState: {
|
mockState: {
|
||||||
metamask: {
|
metamask: {
|
||||||
|
gasEstimateType: GAS_ESTIMATE_TYPES.LEGACY,
|
||||||
|
gasFeeEstimates: {
|
||||||
|
low: '5',
|
||||||
|
medium: '7',
|
||||||
|
high: '10',
|
||||||
|
},
|
||||||
|
networkDetails: {
|
||||||
|
EIPS: {},
|
||||||
|
},
|
||||||
conversionRate: 2557.1,
|
conversionRate: 2557.1,
|
||||||
currentCurrency: 'usd',
|
currentCurrency: 'usd',
|
||||||
preferences: {
|
preferences: {
|
||||||
@ -287,19 +384,6 @@ describe('custom-gas selectors', () => {
|
|||||||
gasLimit: GAS_LIMITS.SIMPLE,
|
gasLimit: GAS_LIMITS.SIMPLE,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
gas: {
|
|
||||||
basicEstimates: {
|
|
||||||
blockTime: 14.16326530612245,
|
|
||||||
safeLow: 5,
|
|
||||||
safeLowWait: 13.2,
|
|
||||||
average: 7,
|
|
||||||
avgWait: 10.1,
|
|
||||||
fast: 10,
|
|
||||||
fastWait: 6.6,
|
|
||||||
fastest: 20,
|
|
||||||
fastestWait: 1.0,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -325,6 +409,15 @@ describe('custom-gas selectors', () => {
|
|||||||
],
|
],
|
||||||
mockState: {
|
mockState: {
|
||||||
metamask: {
|
metamask: {
|
||||||
|
gasEstimateType: GAS_ESTIMATE_TYPES.LEGACY,
|
||||||
|
gasFeeEstimates: {
|
||||||
|
low: '5',
|
||||||
|
medium: '7',
|
||||||
|
high: '10',
|
||||||
|
},
|
||||||
|
networkDetails: {
|
||||||
|
EIPS: {},
|
||||||
|
},
|
||||||
conversionRate: 2557.1,
|
conversionRate: 2557.1,
|
||||||
currentCurrency: 'usd',
|
currentCurrency: 'usd',
|
||||||
preferences: {
|
preferences: {
|
||||||
@ -340,13 +433,6 @@ describe('custom-gas selectors', () => {
|
|||||||
gasLimit: GAS_LIMITS.SIMPLE,
|
gasLimit: GAS_LIMITS.SIMPLE,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
gas: {
|
|
||||||
basicEstimates: {
|
|
||||||
safeLow: 5,
|
|
||||||
average: 7,
|
|
||||||
fast: 10,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -372,6 +458,15 @@ describe('custom-gas selectors', () => {
|
|||||||
],
|
],
|
||||||
mockState: {
|
mockState: {
|
||||||
metamask: {
|
metamask: {
|
||||||
|
gasEstimateType: GAS_ESTIMATE_TYPES.LEGACY,
|
||||||
|
gasFeeEstimates: {
|
||||||
|
low: '5',
|
||||||
|
medium: '7',
|
||||||
|
high: '10',
|
||||||
|
},
|
||||||
|
networkDetails: {
|
||||||
|
EIPS: {},
|
||||||
|
},
|
||||||
conversionRate: 2557.1,
|
conversionRate: 2557.1,
|
||||||
currentCurrency: 'usd',
|
currentCurrency: 'usd',
|
||||||
preferences: {
|
preferences: {
|
||||||
@ -387,13 +482,6 @@ describe('custom-gas selectors', () => {
|
|||||||
gasLimit: GAS_LIMITS.SIMPLE,
|
gasLimit: GAS_LIMITS.SIMPLE,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
gas: {
|
|
||||||
basicEstimates: {
|
|
||||||
safeLow: 5,
|
|
||||||
average: 7,
|
|
||||||
fast: 10,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
@ -435,6 +523,15 @@ describe('custom-gas selectors', () => {
|
|||||||
],
|
],
|
||||||
mockState: {
|
mockState: {
|
||||||
metamask: {
|
metamask: {
|
||||||
|
gasEstimateType: GAS_ESTIMATE_TYPES.LEGACY,
|
||||||
|
gasFeeEstimates: {
|
||||||
|
low: '25',
|
||||||
|
medium: '30',
|
||||||
|
high: '50',
|
||||||
|
},
|
||||||
|
networkDetails: {
|
||||||
|
EIPS: {},
|
||||||
|
},
|
||||||
conversionRate: 255.71,
|
conversionRate: 255.71,
|
||||||
currentCurrency: 'usd',
|
currentCurrency: 'usd',
|
||||||
preferences: {
|
preferences: {
|
||||||
@ -450,13 +547,6 @@ describe('custom-gas selectors', () => {
|
|||||||
gasLimit: GAS_LIMITS.SIMPLE,
|
gasLimit: GAS_LIMITS.SIMPLE,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
gas: {
|
|
||||||
basicEstimates: {
|
|
||||||
safeLow: 25,
|
|
||||||
average: 30,
|
|
||||||
fast: 50,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -482,6 +572,15 @@ describe('custom-gas selectors', () => {
|
|||||||
],
|
],
|
||||||
mockState: {
|
mockState: {
|
||||||
metamask: {
|
metamask: {
|
||||||
|
gasEstimateType: GAS_ESTIMATE_TYPES.LEGACY,
|
||||||
|
gasFeeEstimates: {
|
||||||
|
low: '50',
|
||||||
|
medium: '75',
|
||||||
|
high: '100',
|
||||||
|
},
|
||||||
|
networkDetails: {
|
||||||
|
EIPS: {},
|
||||||
|
},
|
||||||
conversionRate: 2557.1,
|
conversionRate: 2557.1,
|
||||||
currentCurrency: 'usd',
|
currentCurrency: 'usd',
|
||||||
preferences: {
|
preferences: {
|
||||||
@ -497,19 +596,6 @@ describe('custom-gas selectors', () => {
|
|||||||
gasLimit: GAS_LIMITS.SIMPLE,
|
gasLimit: GAS_LIMITS.SIMPLE,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
gas: {
|
|
||||||
basicEstimates: {
|
|
||||||
blockTime: 14.16326530612245,
|
|
||||||
safeLow: 50,
|
|
||||||
safeLowWait: 13.2,
|
|
||||||
average: 75,
|
|
||||||
avgWait: 9.6,
|
|
||||||
fast: 100,
|
|
||||||
fastWait: 6.6,
|
|
||||||
fastest: 200,
|
|
||||||
fastestWait: 1.0,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -535,6 +621,15 @@ describe('custom-gas selectors', () => {
|
|||||||
],
|
],
|
||||||
mockState: {
|
mockState: {
|
||||||
metamask: {
|
metamask: {
|
||||||
|
gasEstimateType: GAS_ESTIMATE_TYPES.LEGACY,
|
||||||
|
gasFeeEstimates: {
|
||||||
|
low: '50',
|
||||||
|
medium: '75',
|
||||||
|
high: '100',
|
||||||
|
},
|
||||||
|
networkDetails: {
|
||||||
|
EIPS: {},
|
||||||
|
},
|
||||||
conversionRate: 2557.1,
|
conversionRate: 2557.1,
|
||||||
currentCurrency: 'usd',
|
currentCurrency: 'usd',
|
||||||
preferences: {
|
preferences: {
|
||||||
@ -550,19 +645,6 @@ describe('custom-gas selectors', () => {
|
|||||||
gasLimit: GAS_LIMITS.SIMPLE,
|
gasLimit: GAS_LIMITS.SIMPLE,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
gas: {
|
|
||||||
basicEstimates: {
|
|
||||||
blockTime: 14.16326530612245,
|
|
||||||
safeLow: 50,
|
|
||||||
safeLowWait: 13.2,
|
|
||||||
average: 75,
|
|
||||||
avgWait: 9.6,
|
|
||||||
fast: 100,
|
|
||||||
fastWait: 6.6,
|
|
||||||
fastest: 200,
|
|
||||||
fastestWait: 1.0,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -588,6 +670,15 @@ describe('custom-gas selectors', () => {
|
|||||||
],
|
],
|
||||||
mockState: {
|
mockState: {
|
||||||
metamask: {
|
metamask: {
|
||||||
|
gasEstimateType: GAS_ESTIMATE_TYPES.LEGACY,
|
||||||
|
gasFeeEstimates: {
|
||||||
|
low: '50',
|
||||||
|
medium: '75',
|
||||||
|
high: '100',
|
||||||
|
},
|
||||||
|
networkDetails: {
|
||||||
|
EIPS: {},
|
||||||
|
},
|
||||||
conversionRate: 2557.1,
|
conversionRate: 2557.1,
|
||||||
currentCurrency: 'usd',
|
currentCurrency: 'usd',
|
||||||
preferences: {
|
preferences: {
|
||||||
@ -603,13 +694,6 @@ describe('custom-gas selectors', () => {
|
|||||||
gasLimit: GAS_LIMITS.SIMPLE,
|
gasLimit: GAS_LIMITS.SIMPLE,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
gas: {
|
|
||||||
basicEstimates: {
|
|
||||||
safeLow: 50,
|
|
||||||
average: 75,
|
|
||||||
fast: 100,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -635,6 +719,15 @@ describe('custom-gas selectors', () => {
|
|||||||
],
|
],
|
||||||
mockState: {
|
mockState: {
|
||||||
metamask: {
|
metamask: {
|
||||||
|
gasEstimateType: GAS_ESTIMATE_TYPES.LEGACY,
|
||||||
|
gasFeeEstimates: {
|
||||||
|
low: '50',
|
||||||
|
medium: '75',
|
||||||
|
high: '100',
|
||||||
|
},
|
||||||
|
networkDetails: {
|
||||||
|
EIPS: {},
|
||||||
|
},
|
||||||
conversionRate: 2557.1,
|
conversionRate: 2557.1,
|
||||||
currentCurrency: 'usd',
|
currentCurrency: 'usd',
|
||||||
preferences: {
|
preferences: {
|
||||||
@ -650,13 +743,6 @@ describe('custom-gas selectors', () => {
|
|||||||
gasLimit: GAS_LIMITS.SIMPLE,
|
gasLimit: GAS_LIMITS.SIMPLE,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
gas: {
|
|
||||||
basicEstimates: {
|
|
||||||
safeLow: 50,
|
|
||||||
average: 75,
|
|
||||||
fast: 100,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
Loading…
x
Reference in New Issue
Block a user