mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-12-23 09:52:26 +01:00
Handling gas price fetch failure (#10767)
This commit is contained in:
parent
b73f543b23
commit
f1fc51667a
@ -684,6 +684,9 @@
|
|||||||
"estimatedProcessingTimes": {
|
"estimatedProcessingTimes": {
|
||||||
"message": "Estimated Processing Times"
|
"message": "Estimated Processing Times"
|
||||||
},
|
},
|
||||||
|
"ethGasPriceFetchWarning": {
|
||||||
|
"message": "Backup gas price is provided as the main gas estimation service is unavailable right now."
|
||||||
|
},
|
||||||
"eth_accounts": {
|
"eth_accounts": {
|
||||||
"message": "View the addresses of your permitted accounts (required)",
|
"message": "View the addresses of your permitted accounts (required)",
|
||||||
"description": "The description for the `eth_accounts` permission"
|
"description": "The description for the `eth_accounts` permission"
|
||||||
@ -780,6 +783,9 @@
|
|||||||
"gasPriceExtremelyLow": {
|
"gasPriceExtremelyLow": {
|
||||||
"message": "Gas Price Extremely Low"
|
"message": "Gas Price Extremely Low"
|
||||||
},
|
},
|
||||||
|
"gasPriceFetchFailed": {
|
||||||
|
"message": "Gas price estimation failed due to network error."
|
||||||
|
},
|
||||||
"gasPriceInfoTooltipContent": {
|
"gasPriceInfoTooltipContent": {
|
||||||
"message": "Gas price specifies the amount of Ether you are willing to pay for each unit of gas."
|
"message": "Gas price specifies the amount of Ether you are willing to pay for each unit of gas."
|
||||||
},
|
},
|
||||||
|
@ -22,6 +22,7 @@ export default class ConfirmPageContainerContent extends Component {
|
|||||||
titleComponent: PropTypes.node,
|
titleComponent: PropTypes.node,
|
||||||
warning: PropTypes.string,
|
warning: PropTypes.string,
|
||||||
origin: PropTypes.string.isRequired,
|
origin: PropTypes.string.isRequired,
|
||||||
|
ethGasPriceWarning: PropTypes.string,
|
||||||
// Footer
|
// Footer
|
||||||
onCancelAll: PropTypes.func,
|
onCancelAll: PropTypes.func,
|
||||||
onCancel: PropTypes.func,
|
onCancel: PropTypes.func,
|
||||||
@ -81,11 +82,15 @@ export default class ConfirmPageContainerContent extends Component {
|
|||||||
unapprovedTxCount,
|
unapprovedTxCount,
|
||||||
rejectNText,
|
rejectNText,
|
||||||
origin,
|
origin,
|
||||||
|
ethGasPriceWarning,
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="confirm-page-container-content">
|
<div className="confirm-page-container-content">
|
||||||
{warning && <ConfirmPageContainerWarning warning={warning} />}
|
{warning && <ConfirmPageContainerWarning warning={warning} />}
|
||||||
|
{ethGasPriceWarning && (
|
||||||
|
<ConfirmPageContainerWarning warning={ethGasPriceWarning} />
|
||||||
|
)}
|
||||||
<ConfirmPageContainerSummary
|
<ConfirmPageContainerSummary
|
||||||
className={classnames({
|
className={classnames({
|
||||||
'confirm-page-container-summary--border':
|
'confirm-page-container-summary--border':
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
.confirm-page-container-warning {
|
.confirm-page-container-warning {
|
||||||
background-color: #fffcdb;
|
background-color: #fffcdb;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
align-items: center;
|
||||||
border-bottom: 1px solid $geyser;
|
border-bottom: 1px solid $geyser;
|
||||||
padding: 12px 24px;
|
padding: 12px 24px;
|
||||||
|
@ -43,6 +43,7 @@ export default class ConfirmPageContainer extends Component {
|
|||||||
warning: PropTypes.string,
|
warning: PropTypes.string,
|
||||||
unapprovedTxCount: PropTypes.number,
|
unapprovedTxCount: PropTypes.number,
|
||||||
origin: PropTypes.string.isRequired,
|
origin: PropTypes.string.isRequired,
|
||||||
|
ethGasPriceWarning: PropTypes.string,
|
||||||
// Navigation
|
// Navigation
|
||||||
totalTx: PropTypes.number,
|
totalTx: PropTypes.number,
|
||||||
positionOfCurrentTx: PropTypes.number,
|
positionOfCurrentTx: PropTypes.number,
|
||||||
@ -103,6 +104,7 @@ export default class ConfirmPageContainer extends Component {
|
|||||||
hideSenderToRecipient,
|
hideSenderToRecipient,
|
||||||
showAccountInHeader,
|
showAccountInHeader,
|
||||||
origin,
|
origin,
|
||||||
|
ethGasPriceWarning,
|
||||||
} = this.props;
|
} = this.props;
|
||||||
const renderAssetImage = contentComponent || !identiconAddress;
|
const renderAssetImage = contentComponent || !identiconAddress;
|
||||||
|
|
||||||
@ -162,6 +164,7 @@ export default class ConfirmPageContainer extends Component {
|
|||||||
unapprovedTxCount={unapprovedTxCount}
|
unapprovedTxCount={unapprovedTxCount}
|
||||||
rejectNText={this.context.t('rejectTxsN', [unapprovedTxCount])}
|
rejectNText={this.context.t('rejectTxsN', [unapprovedTxCount])}
|
||||||
origin={origin}
|
origin={origin}
|
||||||
|
ethGasPriceWarning={ethGasPriceWarning}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{contentComponent && (
|
{contentComponent && (
|
||||||
|
@ -123,7 +123,16 @@ export default class GasModalPageContainer extends Component {
|
|||||||
infoRowProps: { newTotalFiat, newTotalEth, sendAmount, transactionFee },
|
infoRowProps: { newTotalFiat, newTotalEth, sendAmount, transactionFee },
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
let tabsToRender = [
|
let tabsToRender;
|
||||||
|
if (hideBasic) {
|
||||||
|
tabsToRender = [
|
||||||
|
{
|
||||||
|
name: this.context.t('advanced'),
|
||||||
|
content: this.renderAdvancedTabContent(),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
} else {
|
||||||
|
tabsToRender = [
|
||||||
{
|
{
|
||||||
name: this.context.t('basic'),
|
name: this.context.t('basic'),
|
||||||
content: this.renderBasicTabContent(gasPriceButtonGroupProps),
|
content: this.renderBasicTabContent(gasPriceButtonGroupProps),
|
||||||
@ -133,9 +142,6 @@ export default class GasModalPageContainer extends Component {
|
|||||||
content: this.renderAdvancedTabContent(),
|
content: this.renderAdvancedTabContent(),
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
if (hideBasic) {
|
|
||||||
tabsToRender = tabsToRender.slice(1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -3,8 +3,7 @@ import sinon from 'sinon';
|
|||||||
import BN from 'bn.js';
|
import BN from 'bn.js';
|
||||||
|
|
||||||
import GasReducer, {
|
import GasReducer, {
|
||||||
basicGasEstimatesLoadingStarted,
|
setBasicEstimateStatus,
|
||||||
basicGasEstimatesLoadingFinished,
|
|
||||||
setBasicGasEstimateData,
|
setBasicGasEstimateData,
|
||||||
setCustomGasPrice,
|
setCustomGasPrice,
|
||||||
setCustomGasLimit,
|
setCustomGasLimit,
|
||||||
@ -49,7 +48,8 @@ describe('Gas Duck', () => {
|
|||||||
fast: null,
|
fast: null,
|
||||||
safeLow: null,
|
safeLow: null,
|
||||||
},
|
},
|
||||||
basicEstimateIsLoading: true,
|
basicEstimateStatus: 'LOADING',
|
||||||
|
estimateSource: '',
|
||||||
};
|
};
|
||||||
|
|
||||||
const providerState = {
|
const providerState = {
|
||||||
@ -61,14 +61,12 @@ describe('Gas Duck', () => {
|
|||||||
type: 'mainnet',
|
type: 'mainnet',
|
||||||
};
|
};
|
||||||
|
|
||||||
const BASIC_GAS_ESTIMATE_LOADING_FINISHED =
|
const BASIC_GAS_ESTIMATE_STATUS = 'metamask/gas/BASIC_GAS_ESTIMATE_STATUS';
|
||||||
'metamask/gas/BASIC_GAS_ESTIMATE_LOADING_FINISHED';
|
|
||||||
const BASIC_GAS_ESTIMATE_LOADING_STARTED =
|
|
||||||
'metamask/gas/BASIC_GAS_ESTIMATE_LOADING_STARTED';
|
|
||||||
const SET_BASIC_GAS_ESTIMATE_DATA =
|
const SET_BASIC_GAS_ESTIMATE_DATA =
|
||||||
'metamask/gas/SET_BASIC_GAS_ESTIMATE_DATA';
|
'metamask/gas/SET_BASIC_GAS_ESTIMATE_DATA';
|
||||||
const SET_CUSTOM_GAS_LIMIT = 'metamask/gas/SET_CUSTOM_GAS_LIMIT';
|
const SET_CUSTOM_GAS_LIMIT = 'metamask/gas/SET_CUSTOM_GAS_LIMIT';
|
||||||
const SET_CUSTOM_GAS_PRICE = 'metamask/gas/SET_CUSTOM_GAS_PRICE';
|
const SET_CUSTOM_GAS_PRICE = 'metamask/gas/SET_CUSTOM_GAS_PRICE';
|
||||||
|
const SET_ESTIMATE_SOURCE = 'metamask/gas/SET_ESTIMATE_SOURCE';
|
||||||
|
|
||||||
describe('GasReducer()', () => {
|
describe('GasReducer()', () => {
|
||||||
it('should initialize state', () => {
|
it('should initialize state', () => {
|
||||||
@ -84,16 +82,13 @@ describe('Gas Duck', () => {
|
|||||||
).toStrictEqual(mockState);
|
).toStrictEqual(mockState);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should set basicEstimateIsLoading to true when receiving a BASIC_GAS_ESTIMATE_LOADING_STARTED action', () => {
|
it('should set basicEstimateStatus to LOADING when receiving a BASIC_GAS_ESTIMATE_STATUS action with value LOADING', () => {
|
||||||
expect(
|
expect(
|
||||||
GasReducer(mockState, { type: BASIC_GAS_ESTIMATE_LOADING_STARTED }),
|
GasReducer(mockState, {
|
||||||
).toStrictEqual({ basicEstimateIsLoading: true, ...mockState });
|
type: BASIC_GAS_ESTIMATE_STATUS,
|
||||||
});
|
value: 'LOADING',
|
||||||
|
}),
|
||||||
it('should set basicEstimateIsLoading to false when receiving a BASIC_GAS_ESTIMATE_LOADING_FINISHED action', () => {
|
).toStrictEqual({ basicEstimateStatus: 'LOADING', ...mockState });
|
||||||
expect(
|
|
||||||
GasReducer(mockState, { type: BASIC_GAS_ESTIMATE_LOADING_FINISHED }),
|
|
||||||
).toStrictEqual({ basicEstimateIsLoading: false, ...mockState });
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should set basicEstimates when receiving a SET_BASIC_GAS_ESTIMATE_DATA action', () => {
|
it('should set basicEstimates when receiving a SET_BASIC_GAS_ESTIMATE_DATA action', () => {
|
||||||
@ -127,18 +122,17 @@ describe('Gas Duck', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('basicGasEstimatesLoadingStarted', () => {
|
it('should set estimateSource to Metaswaps when receiving a SET_ESTIMATE_SOURCE action with value Metaswaps', () => {
|
||||||
it('should create the correct action', () => {
|
expect(
|
||||||
expect(basicGasEstimatesLoadingStarted()).toStrictEqual({
|
GasReducer(mockState, { type: SET_ESTIMATE_SOURCE, value: 'Metaswaps' }),
|
||||||
type: BASIC_GAS_ESTIMATE_LOADING_STARTED,
|
).toStrictEqual({ estimateSource: 'Metaswaps', ...mockState });
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('basicGasEstimatesLoadingFinished', () => {
|
describe('basicEstimateStatus', () => {
|
||||||
it('should create the correct action', () => {
|
it('should create the correct action', () => {
|
||||||
expect(basicGasEstimatesLoadingFinished()).toStrictEqual({
|
expect(setBasicEstimateStatus('LOADING')).toStrictEqual({
|
||||||
type: BASIC_GAS_ESTIMATE_LOADING_FINISHED,
|
type: BASIC_GAS_ESTIMATE_STATUS,
|
||||||
|
value: 'LOADING',
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -158,7 +152,7 @@ describe('Gas Duck', () => {
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
expect(mockDistpatch.getCall(0).args).toStrictEqual([
|
expect(mockDistpatch.getCall(0).args).toStrictEqual([
|
||||||
{ type: BASIC_GAS_ESTIMATE_LOADING_STARTED },
|
{ type: 'metamask/gas/BASIC_GAS_ESTIMATE_STATUS', value: 'LOADING' },
|
||||||
]);
|
]);
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
@ -168,7 +162,11 @@ describe('Gas Duck', () => {
|
|||||||
).toStrictEqual(true);
|
).toStrictEqual(true);
|
||||||
|
|
||||||
expect(mockDistpatch.getCall(2).args).toStrictEqual([
|
expect(mockDistpatch.getCall(2).args).toStrictEqual([
|
||||||
{ type: BASIC_GAS_ESTIMATE_LOADING_FINISHED },
|
{ type: 'metamask/gas/SET_ESTIMATE_SOURCE', value: 'MetaSwaps' },
|
||||||
|
]);
|
||||||
|
|
||||||
|
expect(mockDistpatch.getCall(4).args).toStrictEqual([
|
||||||
|
{ type: 'metamask/gas/BASIC_GAS_ESTIMATE_STATUS', value: 'READY' },
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -190,9 +188,12 @@ describe('Gas Duck', () => {
|
|||||||
metamask: { provider: { ...providerStateForTestNetwork } },
|
metamask: { provider: { ...providerStateForTestNetwork } },
|
||||||
}));
|
}));
|
||||||
expect(mockDistpatch.getCall(0).args).toStrictEqual([
|
expect(mockDistpatch.getCall(0).args).toStrictEqual([
|
||||||
{ type: BASIC_GAS_ESTIMATE_LOADING_STARTED },
|
{ type: 'metamask/gas/BASIC_GAS_ESTIMATE_STATUS', value: 'LOADING' },
|
||||||
]);
|
]);
|
||||||
expect(mockDistpatch.getCall(1).args).toStrictEqual([
|
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,
|
type: SET_BASIC_GAS_ESTIMATE_DATA,
|
||||||
value: {
|
value: {
|
||||||
@ -200,8 +201,8 @@ describe('Gas Duck', () => {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
expect(mockDistpatch.getCall(2).args).toStrictEqual([
|
expect(mockDistpatch.getCall(3).args).toStrictEqual([
|
||||||
{ type: BASIC_GAS_ESTIMATE_LOADING_FINISHED },
|
{ type: 'metamask/gas/BASIC_GAS_ESTIMATE_STATUS', value: 'READY' },
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -8,15 +8,24 @@ import {
|
|||||||
import { getIsMainnet, getCurrentChainId } from '../../selectors';
|
import { getIsMainnet, getCurrentChainId } from '../../selectors';
|
||||||
import fetchWithCache from '../../helpers/utils/fetch-with-cache';
|
import fetchWithCache from '../../helpers/utils/fetch-with-cache';
|
||||||
|
|
||||||
|
const BASIC_ESTIMATE_STATES = {
|
||||||
|
LOADING: 'LOADING',
|
||||||
|
FAILED: 'FAILED',
|
||||||
|
READY: 'READY',
|
||||||
|
};
|
||||||
|
|
||||||
|
const GAS_SOURCE = {
|
||||||
|
METASWAPS: 'MetaSwaps',
|
||||||
|
ETHGASPRICE: 'eth_gasprice',
|
||||||
|
};
|
||||||
|
|
||||||
// Actions
|
// Actions
|
||||||
const BASIC_GAS_ESTIMATE_LOADING_FINISHED =
|
const BASIC_GAS_ESTIMATE_STATUS = 'metamask/gas/BASIC_GAS_ESTIMATE_STATUS';
|
||||||
'metamask/gas/BASIC_GAS_ESTIMATE_LOADING_FINISHED';
|
|
||||||
const BASIC_GAS_ESTIMATE_LOADING_STARTED =
|
|
||||||
'metamask/gas/BASIC_GAS_ESTIMATE_LOADING_STARTED';
|
|
||||||
const RESET_CUSTOM_DATA = 'metamask/gas/RESET_CUSTOM_DATA';
|
const RESET_CUSTOM_DATA = 'metamask/gas/RESET_CUSTOM_DATA';
|
||||||
const SET_BASIC_GAS_ESTIMATE_DATA = 'metamask/gas/SET_BASIC_GAS_ESTIMATE_DATA';
|
const SET_BASIC_GAS_ESTIMATE_DATA = 'metamask/gas/SET_BASIC_GAS_ESTIMATE_DATA';
|
||||||
const SET_CUSTOM_GAS_LIMIT = 'metamask/gas/SET_CUSTOM_GAS_LIMIT';
|
const SET_CUSTOM_GAS_LIMIT = 'metamask/gas/SET_CUSTOM_GAS_LIMIT';
|
||||||
const SET_CUSTOM_GAS_PRICE = 'metamask/gas/SET_CUSTOM_GAS_PRICE';
|
const SET_CUSTOM_GAS_PRICE = 'metamask/gas/SET_CUSTOM_GAS_PRICE';
|
||||||
|
const SET_ESTIMATE_SOURCE = 'metamask/gas/SET_ESTIMATE_SOURCE';
|
||||||
|
|
||||||
const initState = {
|
const initState = {
|
||||||
customData: {
|
customData: {
|
||||||
@ -28,21 +37,17 @@ const initState = {
|
|||||||
average: null,
|
average: null,
|
||||||
fast: null,
|
fast: null,
|
||||||
},
|
},
|
||||||
basicEstimateIsLoading: true,
|
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_LOADING_STARTED:
|
case BASIC_GAS_ESTIMATE_STATUS:
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
basicEstimateIsLoading: true,
|
basicEstimateStatus: action.value,
|
||||||
};
|
|
||||||
case BASIC_GAS_ESTIMATE_LOADING_FINISHED:
|
|
||||||
return {
|
|
||||||
...state,
|
|
||||||
basicEstimateIsLoading: false,
|
|
||||||
};
|
};
|
||||||
case SET_BASIC_GAS_ESTIMATE_DATA:
|
case SET_BASIC_GAS_ESTIMATE_DATA:
|
||||||
return {
|
return {
|
||||||
@ -70,21 +75,21 @@ 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
|
// Action Creators
|
||||||
export function basicGasEstimatesLoadingStarted() {
|
export function setBasicEstimateStatus(status) {
|
||||||
return {
|
return {
|
||||||
type: BASIC_GAS_ESTIMATE_LOADING_STARTED,
|
type: BASIC_GAS_ESTIMATE_STATUS,
|
||||||
};
|
value: status,
|
||||||
}
|
|
||||||
|
|
||||||
export function basicGasEstimatesLoadingFinished() {
|
|
||||||
return {
|
|
||||||
type: BASIC_GAS_ESTIMATE_LOADING_FINISHED,
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -106,17 +111,25 @@ export function fetchBasicGasEstimates() {
|
|||||||
return async (dispatch, getState) => {
|
return async (dispatch, getState) => {
|
||||||
const isMainnet = getIsMainnet(getState());
|
const isMainnet = getIsMainnet(getState());
|
||||||
|
|
||||||
dispatch(basicGasEstimatesLoadingStarted());
|
dispatch(setBasicEstimateStatus(BASIC_ESTIMATE_STATES.LOADING));
|
||||||
|
|
||||||
let basicEstimates;
|
let basicEstimates;
|
||||||
|
try {
|
||||||
|
dispatch(setEstimateSource(GAS_SOURCE.ETHGASPRICE));
|
||||||
if (isMainnet || process.env.IN_TEST) {
|
if (isMainnet || process.env.IN_TEST) {
|
||||||
|
try {
|
||||||
basicEstimates = await fetchExternalBasicGasEstimates();
|
basicEstimates = await fetchExternalBasicGasEstimates();
|
||||||
|
dispatch(setEstimateSource(GAS_SOURCE.METASWAPS));
|
||||||
|
} catch (error) {
|
||||||
|
basicEstimates = await fetchEthGasPriceEstimates(getState());
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
basicEstimates = await fetchEthGasPriceEstimates(getState());
|
basicEstimates = await fetchEthGasPriceEstimates(getState());
|
||||||
}
|
}
|
||||||
|
|
||||||
dispatch(setBasicGasEstimateData(basicEstimates));
|
dispatch(setBasicGasEstimateData(basicEstimates));
|
||||||
dispatch(basicGasEstimatesLoadingFinished());
|
dispatch(setBasicEstimateStatus(BASIC_ESTIMATE_STATES.READY));
|
||||||
|
} catch (error) {
|
||||||
|
dispatch(setBasicEstimateStatus(BASIC_ESTIMATE_STATES.FAILED));
|
||||||
|
}
|
||||||
|
|
||||||
return basicEstimates;
|
return basicEstimates;
|
||||||
};
|
};
|
||||||
@ -211,3 +224,10 @@ 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,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
@ -2,3 +2,6 @@ export const INSUFFICIENT_FUNDS_ERROR_KEY = 'insufficientFunds';
|
|||||||
export const GAS_LIMIT_TOO_LOW_ERROR_KEY = 'gasLimitTooLow';
|
export const GAS_LIMIT_TOO_LOW_ERROR_KEY = 'gasLimitTooLow';
|
||||||
export const TRANSACTION_ERROR_KEY = 'transactionError';
|
export const TRANSACTION_ERROR_KEY = 'transactionError';
|
||||||
export const TRANSACTION_NO_CONTRACT_ERROR_KEY = 'transactionErrorNoContract';
|
export const TRANSACTION_NO_CONTRACT_ERROR_KEY = 'transactionErrorNoContract';
|
||||||
|
export const ETH_GAS_PRICE_FETCH_WARNING_KEY = 'ethGasPriceFetchWarning';
|
||||||
|
export const GAS_PRICE_FETCH_FAILURE_ERROR_KEY = 'gasPriceFetchFailed';
|
||||||
|
export const GAS_PRICE_EXCESSIVE_ERROR_KEY = 'gasPriceExcessive';
|
||||||
|
@ -24,6 +24,8 @@ import {
|
|||||||
getUseNonceField,
|
getUseNonceField,
|
||||||
getCustomNonceValue,
|
getCustomNonceValue,
|
||||||
getNextSuggestedNonce,
|
getNextSuggestedNonce,
|
||||||
|
getNoGasPriceFetched,
|
||||||
|
getIsEthGasPriceFetched,
|
||||||
} from '../../selectors';
|
} from '../../selectors';
|
||||||
import { currentNetworkTxListSelector } from '../../selectors/transactions';
|
import { currentNetworkTxListSelector } from '../../selectors/transactions';
|
||||||
import Loading from '../../components/ui/loading-screen';
|
import Loading from '../../components/ui/loading-screen';
|
||||||
@ -116,6 +118,8 @@ export default function ConfirmApprove() {
|
|||||||
const customData = customPermissionAmount
|
const customData = customPermissionAmount
|
||||||
? getCustomTxParamsData(data, { customPermissionAmount, decimals })
|
? getCustomTxParamsData(data, { customPermissionAmount, decimals })
|
||||||
: null;
|
: null;
|
||||||
|
const isEthGasPrice = useSelector(getIsEthGasPriceFetched);
|
||||||
|
const noGasPrice = useSelector(getNoGasPriceFetched);
|
||||||
|
|
||||||
return tokenSymbol === undefined ? (
|
return tokenSymbol === undefined ? (
|
||||||
<Loading />
|
<Loading />
|
||||||
@ -136,7 +140,13 @@ export default function ConfirmApprove() {
|
|||||||
tokenSymbol={tokenSymbol}
|
tokenSymbol={tokenSymbol}
|
||||||
tokenBalance={tokenBalance}
|
tokenBalance={tokenBalance}
|
||||||
showCustomizeGasModal={() =>
|
showCustomizeGasModal={() =>
|
||||||
dispatch(showModal({ name: 'CUSTOMIZE_GAS', txData }))
|
dispatch(
|
||||||
|
showModal({
|
||||||
|
name: 'CUSTOMIZE_GAS',
|
||||||
|
txData,
|
||||||
|
hideBasic: isEthGasPrice || noGasPrice,
|
||||||
|
}),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
showEditApprovalPermissionModal={({
|
showEditApprovalPermissionModal={({
|
||||||
/* eslint-disable no-shadow */
|
/* eslint-disable no-shadow */
|
||||||
|
@ -12,6 +12,8 @@ import {
|
|||||||
INSUFFICIENT_FUNDS_ERROR_KEY,
|
INSUFFICIENT_FUNDS_ERROR_KEY,
|
||||||
TRANSACTION_ERROR_KEY,
|
TRANSACTION_ERROR_KEY,
|
||||||
GAS_LIMIT_TOO_LOW_ERROR_KEY,
|
GAS_LIMIT_TOO_LOW_ERROR_KEY,
|
||||||
|
ETH_GAS_PRICE_FETCH_WARNING_KEY,
|
||||||
|
GAS_PRICE_FETCH_FAILURE_ERROR_KEY,
|
||||||
} from '../../helpers/constants/error-keys';
|
} from '../../helpers/constants/error-keys';
|
||||||
import UserPreferencedCurrencyDisplay from '../../components/app/user-preferenced-currency-display';
|
import UserPreferencedCurrencyDisplay from '../../components/app/user-preferenced-currency-display';
|
||||||
import { PRIMARY, SECONDARY } from '../../helpers/constants/common';
|
import { PRIMARY, SECONDARY } from '../../helpers/constants/common';
|
||||||
@ -23,6 +25,7 @@ import {
|
|||||||
TRANSACTION_STATUSES,
|
TRANSACTION_STATUSES,
|
||||||
} from '../../../../shared/constants/transaction';
|
} from '../../../../shared/constants/transaction';
|
||||||
import { getTransactionTypeTitle } from '../../helpers/utils/transactions.util';
|
import { getTransactionTypeTitle } from '../../helpers/utils/transactions.util';
|
||||||
|
import ErrorMessage from '../../components/ui/error-message';
|
||||||
|
|
||||||
export default class ConfirmTransactionBase extends Component {
|
export default class ConfirmTransactionBase extends Component {
|
||||||
static contextTypes = {
|
static contextTypes = {
|
||||||
@ -95,12 +98,15 @@ export default class ConfirmTransactionBase extends Component {
|
|||||||
showAccountInHeader: PropTypes.bool,
|
showAccountInHeader: PropTypes.bool,
|
||||||
mostRecentOverviewPage: PropTypes.string.isRequired,
|
mostRecentOverviewPage: PropTypes.string.isRequired,
|
||||||
isMainnet: PropTypes.bool,
|
isMainnet: PropTypes.bool,
|
||||||
|
isEthGasPrice: PropTypes.bool,
|
||||||
|
noGasPrice: PropTypes.bool,
|
||||||
};
|
};
|
||||||
|
|
||||||
state = {
|
state = {
|
||||||
submitting: false,
|
submitting: false,
|
||||||
submitError: null,
|
submitError: null,
|
||||||
submitWarning: '',
|
submitWarning: '',
|
||||||
|
ethGasPriceWarning: '',
|
||||||
};
|
};
|
||||||
|
|
||||||
componentDidUpdate(prevProps) {
|
componentDidUpdate(prevProps) {
|
||||||
@ -114,12 +120,14 @@ export default class ConfirmTransactionBase extends Component {
|
|||||||
customNonceValue,
|
customNonceValue,
|
||||||
toAddress,
|
toAddress,
|
||||||
tryReverseResolveAddress,
|
tryReverseResolveAddress,
|
||||||
|
isEthGasPrice,
|
||||||
} = this.props;
|
} = this.props;
|
||||||
const {
|
const {
|
||||||
customNonceValue: prevCustomNonceValue,
|
customNonceValue: prevCustomNonceValue,
|
||||||
nextNonce: prevNextNonce,
|
nextNonce: prevNextNonce,
|
||||||
toAddress: prevToAddress,
|
toAddress: prevToAddress,
|
||||||
transactionStatus: prevTxStatus,
|
transactionStatus: prevTxStatus,
|
||||||
|
isEthGasPrice: prevIsEthGasPrice,
|
||||||
} = prevProps;
|
} = prevProps;
|
||||||
const statusUpdated = transactionStatus !== prevTxStatus;
|
const statusUpdated = transactionStatus !== prevTxStatus;
|
||||||
const txDroppedOrConfirmed =
|
const txDroppedOrConfirmed =
|
||||||
@ -151,6 +159,18 @@ export default class ConfirmTransactionBase extends Component {
|
|||||||
if (toAddress && toAddress !== prevToAddress) {
|
if (toAddress && toAddress !== prevToAddress) {
|
||||||
tryReverseResolveAddress(toAddress);
|
tryReverseResolveAddress(toAddress);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isEthGasPrice !== prevIsEthGasPrice) {
|
||||||
|
if (isEthGasPrice) {
|
||||||
|
this.setState({
|
||||||
|
ethGasPriceWarning: this.context.t(ETH_GAS_PRICE_FETCH_WARNING_KEY),
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this.setState({
|
||||||
|
ethGasPriceWarning: '',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getErrorKey() {
|
getErrorKey() {
|
||||||
@ -160,6 +180,7 @@ export default class ConfirmTransactionBase extends Component {
|
|||||||
hexTransactionFee,
|
hexTransactionFee,
|
||||||
txData: { simulationFails, txParams: { value: amount } = {} } = {},
|
txData: { simulationFails, txParams: { value: amount } = {} } = {},
|
||||||
customGas,
|
customGas,
|
||||||
|
noGasPrice,
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
const insufficientBalance =
|
const insufficientBalance =
|
||||||
@ -194,6 +215,13 @@ export default class ConfirmTransactionBase extends Component {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (noGasPrice) {
|
||||||
|
return {
|
||||||
|
valid: false,
|
||||||
|
errorKey: GAS_PRICE_FETCH_FAILURE_ERROR_KEY,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
valid: true,
|
valid: true,
|
||||||
};
|
};
|
||||||
@ -243,9 +271,12 @@ export default class ConfirmTransactionBase extends Component {
|
|||||||
nextNonce,
|
nextNonce,
|
||||||
getNextNonce,
|
getNextNonce,
|
||||||
isMainnet,
|
isMainnet,
|
||||||
|
isEthGasPrice,
|
||||||
|
noGasPrice,
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
const notMainnetOrTest = !(isMainnet || process.env.IN_TEST);
|
const notMainnetOrTest = !(isMainnet || process.env.IN_TEST);
|
||||||
|
const gasPriceFetchFailure = isEthGasPrice || noGasPrice;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="confirm-page-container-content__details">
|
<div className="confirm-page-container-content__details">
|
||||||
@ -253,18 +284,26 @@ export default class ConfirmTransactionBase extends Component {
|
|||||||
<ConfirmDetailRow
|
<ConfirmDetailRow
|
||||||
label="Gas Fee"
|
label="Gas Fee"
|
||||||
value={hexTransactionFee}
|
value={hexTransactionFee}
|
||||||
headerText={notMainnetOrTest ? '' : 'Edit'}
|
headerText={notMainnetOrTest || gasPriceFetchFailure ? '' : 'Edit'}
|
||||||
headerTextClassName={
|
headerTextClassName={
|
||||||
notMainnetOrTest ? '' : 'confirm-detail-row__header-text--edit'
|
notMainnetOrTest || gasPriceFetchFailure
|
||||||
|
? ''
|
||||||
|
: 'confirm-detail-row__header-text--edit'
|
||||||
|
}
|
||||||
|
onHeaderClick={
|
||||||
|
notMainnetOrTest || gasPriceFetchFailure
|
||||||
|
? null
|
||||||
|
: () => this.handleEditGas()
|
||||||
}
|
}
|
||||||
onHeaderClick={notMainnetOrTest ? null : () => this.handleEditGas()}
|
|
||||||
secondaryText={
|
secondaryText={
|
||||||
hideFiatConversion
|
hideFiatConversion
|
||||||
? this.context.t('noConversionRateAvailable')
|
? this.context.t('noConversionRateAvailable')
|
||||||
: ''
|
: ''
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
{advancedInlineGasShown || notMainnetOrTest ? (
|
{advancedInlineGasShown ||
|
||||||
|
notMainnetOrTest ||
|
||||||
|
gasPriceFetchFailure ? (
|
||||||
<AdvancedGasInputs
|
<AdvancedGasInputs
|
||||||
updateCustomGasPrice={(newGasPrice) =>
|
updateCustomGasPrice={(newGasPrice) =>
|
||||||
updateGasAndCalculate({ ...customGas, gasPrice: newGasPrice })
|
updateGasAndCalculate({ ...customGas, gasPrice: newGasPrice })
|
||||||
@ -279,6 +318,11 @@ export default class ConfirmTransactionBase extends Component {
|
|||||||
isSpeedUp={false}
|
isSpeedUp={false}
|
||||||
/>
|
/>
|
||||||
) : null}
|
) : null}
|
||||||
|
{noGasPrice ? (
|
||||||
|
<div className="confirm-page-container-content__error-container">
|
||||||
|
<ErrorMessage errorKey={GAS_PRICE_FETCH_FAILURE_ERROR_KEY} />
|
||||||
|
</div>
|
||||||
|
) : null}
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
className={
|
className={
|
||||||
@ -672,7 +716,12 @@ export default class ConfirmTransactionBase extends Component {
|
|||||||
showAccountInHeader,
|
showAccountInHeader,
|
||||||
txData,
|
txData,
|
||||||
} = this.props;
|
} = this.props;
|
||||||
const { submitting, submitError, submitWarning } = this.state;
|
const {
|
||||||
|
submitting,
|
||||||
|
submitError,
|
||||||
|
submitWarning,
|
||||||
|
ethGasPriceWarning,
|
||||||
|
} = this.state;
|
||||||
|
|
||||||
const { name } = methodData;
|
const { name } = methodData;
|
||||||
const { valid, errorKey } = this.getErrorKey();
|
const { valid, errorKey } = this.getErrorKey();
|
||||||
@ -696,7 +745,6 @@ export default class ConfirmTransactionBase extends Component {
|
|||||||
functionType = t('contractInteraction');
|
functionType = t('contractInteraction');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ConfirmPageContainer
|
<ConfirmPageContainer
|
||||||
fromName={fromName}
|
fromName={fromName}
|
||||||
@ -739,6 +787,7 @@ export default class ConfirmTransactionBase extends Component {
|
|||||||
onSubmit={() => this.handleSubmit()}
|
onSubmit={() => this.handleSubmit()}
|
||||||
hideSenderToRecipient={hideSenderToRecipient}
|
hideSenderToRecipient={hideSenderToRecipient}
|
||||||
origin={txData.origin}
|
origin={txData.origin}
|
||||||
|
ethGasPriceWarning={ethGasPriceWarning}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -37,6 +37,8 @@ import {
|
|||||||
getUseNonceField,
|
getUseNonceField,
|
||||||
getPreferences,
|
getPreferences,
|
||||||
transactionFeeSelector,
|
transactionFeeSelector,
|
||||||
|
getNoGasPriceFetched,
|
||||||
|
getIsEthGasPriceFetched,
|
||||||
} from '../../selectors';
|
} from '../../selectors';
|
||||||
import { getMostRecentOverviewPage } from '../../ducks/history/history';
|
import { getMostRecentOverviewPage } from '../../ducks/history/history';
|
||||||
import { transactionMatchesNetwork } from '../../../../shared/modules/transaction.utils';
|
import { transactionMatchesNetwork } from '../../../../shared/modules/transaction.utils';
|
||||||
@ -150,6 +152,8 @@ const mapStateToProps = (state, ownProps) => {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
customNonceValue = getCustomNonceValue(state);
|
customNonceValue = getCustomNonceValue(state);
|
||||||
|
const isEthGasPrice = getIsEthGasPriceFetched(state);
|
||||||
|
const noGasPrice = getNoGasPriceFetched(state);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
balance,
|
balance,
|
||||||
@ -189,6 +193,8 @@ const mapStateToProps = (state, ownProps) => {
|
|||||||
nextNonce,
|
nextNonce,
|
||||||
mostRecentOverviewPage: getMostRecentOverviewPage(state),
|
mostRecentOverviewPage: getMostRecentOverviewPage(state),
|
||||||
isMainnet,
|
isMainnet,
|
||||||
|
isEthGasPrice,
|
||||||
|
noGasPrice,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -207,7 +213,12 @@ export const mapDispatchToProps = (dispatch) => {
|
|||||||
},
|
},
|
||||||
showCustomizeGasModal: ({ txData, onSubmit, validate }) => {
|
showCustomizeGasModal: ({ txData, onSubmit, validate }) => {
|
||||||
return dispatch(
|
return dispatch(
|
||||||
showModal({ name: 'CUSTOMIZE_GAS', txData, onSubmit, validate }),
|
showModal({
|
||||||
|
name: 'CUSTOMIZE_GAS',
|
||||||
|
txData,
|
||||||
|
onSubmit,
|
||||||
|
validate,
|
||||||
|
}),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
updateGasAndCalculate: (updatedTx) => {
|
updateGasAndCalculate: (updatedTx) => {
|
||||||
@ -278,6 +289,7 @@ const getValidateEditGas = ({ balance, conversionRate, txData }) => {
|
|||||||
|
|
||||||
const mergeProps = (stateProps, dispatchProps, ownProps) => {
|
const mergeProps = (stateProps, dispatchProps, ownProps) => {
|
||||||
const { balance, conversionRate, txData, unapprovedTxs } = stateProps;
|
const { balance, conversionRate, txData, unapprovedTxs } = stateProps;
|
||||||
|
|
||||||
const {
|
const {
|
||||||
cancelAllTransactions: dispatchCancelAllTransactions,
|
cancelAllTransactions: dispatchCancelAllTransactions,
|
||||||
showCustomizeGasModal: dispatchShowCustomizeGasModal,
|
showCustomizeGasModal: dispatchShowCustomizeGasModal,
|
||||||
|
@ -2,6 +2,11 @@ import React, { Component } from 'react';
|
|||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import PageContainerContent from '../../../components/ui/page-container/page-container-content.component';
|
import PageContainerContent from '../../../components/ui/page-container/page-container-content.component';
|
||||||
import Dialog from '../../../components/ui/dialog';
|
import Dialog from '../../../components/ui/dialog';
|
||||||
|
import {
|
||||||
|
ETH_GAS_PRICE_FETCH_WARNING_KEY,
|
||||||
|
GAS_PRICE_FETCH_FAILURE_ERROR_KEY,
|
||||||
|
GAS_PRICE_EXCESSIVE_ERROR_KEY,
|
||||||
|
} from '../../../helpers/constants/error-keys';
|
||||||
import SendAmountRow from './send-amount-row';
|
import SendAmountRow from './send-amount-row';
|
||||||
import SendGasRow from './send-gas-row';
|
import SendGasRow from './send-gas-row';
|
||||||
import SendHexDataRow from './send-hex-data-row';
|
import SendHexDataRow from './send-hex-data-row';
|
||||||
@ -21,16 +26,30 @@ export default class SendContent extends Component {
|
|||||||
warning: PropTypes.string,
|
warning: PropTypes.string,
|
||||||
error: PropTypes.string,
|
error: PropTypes.string,
|
||||||
gasIsExcessive: PropTypes.bool.isRequired,
|
gasIsExcessive: PropTypes.bool.isRequired,
|
||||||
|
isEthGasPrice: PropTypes.bool,
|
||||||
|
noGasPrice: PropTypes.bool,
|
||||||
};
|
};
|
||||||
|
|
||||||
updateGas = (updateData) => this.props.updateGas(updateData);
|
updateGas = (updateData) => this.props.updateGas(updateData);
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { warning, error, gasIsExcessive } = this.props;
|
const {
|
||||||
|
warning,
|
||||||
|
error,
|
||||||
|
gasIsExcessive,
|
||||||
|
isEthGasPrice,
|
||||||
|
noGasPrice,
|
||||||
|
} = this.props;
|
||||||
|
|
||||||
|
let gasError;
|
||||||
|
if (gasIsExcessive) gasError = GAS_PRICE_EXCESSIVE_ERROR_KEY;
|
||||||
|
else if (noGasPrice) gasError = GAS_PRICE_FETCH_FAILURE_ERROR_KEY;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<PageContainerContent>
|
<PageContainerContent>
|
||||||
<div className="send-v2__form">
|
<div className="send-v2__form">
|
||||||
{gasIsExcessive && this.renderError(true)}
|
{gasError && this.renderError(gasError)}
|
||||||
|
{isEthGasPrice && this.renderWarning(ETH_GAS_PRICE_FETCH_WARNING_KEY)}
|
||||||
{error && this.renderError()}
|
{error && this.renderError()}
|
||||||
{warning && this.renderWarning()}
|
{warning && this.renderWarning()}
|
||||||
{this.maybeRenderAddContact()}
|
{this.maybeRenderAddContact()}
|
||||||
@ -68,24 +87,22 @@ export default class SendContent extends Component {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
renderWarning() {
|
renderWarning(gasWarning = '') {
|
||||||
const { t } = this.context;
|
const { t } = this.context;
|
||||||
const { warning } = this.props;
|
const { warning } = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Dialog type="warning" className="send__error-dialog">
|
<Dialog type="warning" className="send__error-dialog">
|
||||||
{t(warning)}
|
{gasWarning === '' ? t(warning) : t(gasWarning)}
|
||||||
</Dialog>
|
</Dialog>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
renderError(gasError = false) {
|
renderError(gasError = '') {
|
||||||
const { t } = this.context;
|
const { t } = this.context;
|
||||||
const { error } = this.props;
|
const { error } = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Dialog type="error" className="send__error-dialog">
|
<Dialog type="error" className="send__error-dialog">
|
||||||
{gasError ? t('gasPriceExcessive') : t(error)}
|
{gasError === '' ? t(error) : t(gasError)}
|
||||||
</Dialog>
|
</Dialog>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,8 @@ import {
|
|||||||
getSendTo,
|
getSendTo,
|
||||||
accountsWithSendEtherInfoSelector,
|
accountsWithSendEtherInfoSelector,
|
||||||
getAddressBookEntry,
|
getAddressBookEntry,
|
||||||
|
getIsEthGasPriceFetched,
|
||||||
|
getNoGasPriceFetched,
|
||||||
} from '../../../selectors';
|
} from '../../../selectors';
|
||||||
|
|
||||||
import * as actions from '../../../store/actions';
|
import * as actions from '../../../store/actions';
|
||||||
@ -19,6 +21,8 @@ function mapStateToProps(state) {
|
|||||||
),
|
),
|
||||||
contact: getAddressBookEntry(state, to),
|
contact: getAddressBookEntry(state, to),
|
||||||
to,
|
to,
|
||||||
|
isEthGasPrice: getIsEthGasPriceFetched(state),
|
||||||
|
noGasPrice: getNoGasPriceFetched(state),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,6 +26,8 @@ export default class SendGasRow extends Component {
|
|||||||
gasLimit: PropTypes.string,
|
gasLimit: PropTypes.string,
|
||||||
insufficientBalance: PropTypes.bool,
|
insufficientBalance: PropTypes.bool,
|
||||||
isMainnet: PropTypes.bool,
|
isMainnet: PropTypes.bool,
|
||||||
|
isEthGasPrice: PropTypes.bool,
|
||||||
|
noGasPrice: PropTypes.bool,
|
||||||
};
|
};
|
||||||
|
|
||||||
static contextTypes = {
|
static contextTypes = {
|
||||||
@ -35,11 +37,19 @@ export default class SendGasRow extends Component {
|
|||||||
|
|
||||||
renderAdvancedOptionsButton() {
|
renderAdvancedOptionsButton() {
|
||||||
const { metricsEvent } = this.context;
|
const { metricsEvent } = this.context;
|
||||||
const { showCustomizeGasModal, isMainnet } = this.props;
|
const {
|
||||||
|
showCustomizeGasModal,
|
||||||
|
isMainnet,
|
||||||
|
isEthGasPrice,
|
||||||
|
noGasPrice,
|
||||||
|
} = this.props;
|
||||||
// Tests should behave in same way as mainnet, but are using Localhost
|
// Tests should behave in same way as mainnet, but are using Localhost
|
||||||
if (!isMainnet && !process.env.IN_TEST) {
|
if (!isMainnet && !process.env.IN_TEST) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
if (isEthGasPrice || noGasPrice) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className="advanced-gas-options-btn"
|
className="advanced-gas-options-btn"
|
||||||
@ -92,8 +102,11 @@ export default class SendGasRow extends Component {
|
|||||||
gasLimit,
|
gasLimit,
|
||||||
insufficientBalance,
|
insufficientBalance,
|
||||||
isMainnet,
|
isMainnet,
|
||||||
|
isEthGasPrice,
|
||||||
|
noGasPrice,
|
||||||
} = this.props;
|
} = this.props;
|
||||||
const { metricsEvent } = this.context;
|
const { metricsEvent } = this.context;
|
||||||
|
const gasPriceFetchFailure = isEthGasPrice || noGasPrice;
|
||||||
|
|
||||||
const gasPriceButtonGroup = (
|
const gasPriceButtonGroup = (
|
||||||
<div>
|
<div>
|
||||||
@ -148,7 +161,11 @@ export default class SendGasRow extends Component {
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
// Tests should behave in same way as mainnet, but are using Localhost
|
// Tests should behave in same way as mainnet, but are using Localhost
|
||||||
if (advancedInlineGasShown || (!isMainnet && !process.env.IN_TEST)) {
|
if (
|
||||||
|
advancedInlineGasShown ||
|
||||||
|
(!isMainnet && !process.env.IN_TEST) ||
|
||||||
|
gasPriceFetchFailure
|
||||||
|
) {
|
||||||
return advancedGasInputs;
|
return advancedGasInputs;
|
||||||
} else if (gasButtonGroupShown) {
|
} else if (gasButtonGroupShown) {
|
||||||
return gasPriceButtonGroup;
|
return gasPriceButtonGroup;
|
||||||
|
@ -18,6 +18,8 @@ import {
|
|||||||
getRenderableEstimateDataForSmallButtonsFromGWEI,
|
getRenderableEstimateDataForSmallButtonsFromGWEI,
|
||||||
getDefaultActiveButtonIndex,
|
getDefaultActiveButtonIndex,
|
||||||
getIsMainnet,
|
getIsMainnet,
|
||||||
|
getIsEthGasPriceFetched,
|
||||||
|
getNoGasPriceFetched,
|
||||||
} from '../../../../selectors';
|
} from '../../../../selectors';
|
||||||
import { isBalanceSufficient, calcGasTotal } from '../../send.utils';
|
import { isBalanceSufficient, calcGasTotal } from '../../send.utils';
|
||||||
import { calcMaxAmount } from '../send-amount-row/amount-max-button/amount-max-button.utils';
|
import { calcMaxAmount } from '../send-amount-row/amount-max-button/amount-max-button.utils';
|
||||||
@ -64,6 +66,8 @@ function mapStateToProps(state) {
|
|||||||
balance,
|
balance,
|
||||||
conversionRate,
|
conversionRate,
|
||||||
});
|
});
|
||||||
|
const isEthGasPrice = getIsEthGasPriceFetched(state);
|
||||||
|
const noGasPrice = getNoGasPriceFetched(state);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
balance: getSendFromBalance(state),
|
balance: getSendFromBalance(state),
|
||||||
@ -85,6 +89,8 @@ function mapStateToProps(state) {
|
|||||||
sendToken: getSendToken(state),
|
sendToken: getSendToken(state),
|
||||||
tokenBalance: getTokenBalance(state),
|
tokenBalance: getTokenBalance(state),
|
||||||
isMainnet: getIsMainnet(state),
|
isMainnet: getIsMainnet(state),
|
||||||
|
isEthGasPrice,
|
||||||
|
noGasPrice,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,6 +27,7 @@ export default class SendFooter extends Component {
|
|||||||
gasEstimateType: PropTypes.string,
|
gasEstimateType: PropTypes.string,
|
||||||
gasIsLoading: PropTypes.bool,
|
gasIsLoading: PropTypes.bool,
|
||||||
mostRecentOverviewPage: PropTypes.string.isRequired,
|
mostRecentOverviewPage: PropTypes.string.isRequired,
|
||||||
|
noGasPrice: PropTypes.bool,
|
||||||
};
|
};
|
||||||
|
|
||||||
static contextTypes = {
|
static contextTypes = {
|
||||||
@ -109,6 +110,7 @@ export default class SendFooter extends Component {
|
|||||||
to,
|
to,
|
||||||
gasLimit,
|
gasLimit,
|
||||||
gasIsLoading,
|
gasIsLoading,
|
||||||
|
noGasPrice,
|
||||||
} = this.props;
|
} = this.props;
|
||||||
const missingTokenBalance = sendToken && !tokenBalance;
|
const missingTokenBalance = sendToken && !tokenBalance;
|
||||||
const gasLimitTooLow = gasLimit < 5208; // 5208 is hex value of 21000, minimum gas limit
|
const gasLimitTooLow = gasLimit < 5208; // 5208 is hex value of 21000, minimum gas limit
|
||||||
@ -118,7 +120,8 @@ export default class SendFooter extends Component {
|
|||||||
missingTokenBalance ||
|
missingTokenBalance ||
|
||||||
!(data || to) ||
|
!(data || to) ||
|
||||||
gasLimitTooLow ||
|
gasLimitTooLow ||
|
||||||
gasIsLoading;
|
gasIsLoading ||
|
||||||
|
noGasPrice;
|
||||||
return shouldBeDisabled;
|
return shouldBeDisabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,6 +49,7 @@ describe('SendFooter Component', () => {
|
|||||||
update={propsMethodSpies.update}
|
update={propsMethodSpies.update}
|
||||||
sendErrors={{}}
|
sendErrors={{}}
|
||||||
mostRecentOverviewPage="mostRecentOverviewPage"
|
mostRecentOverviewPage="mostRecentOverviewPage"
|
||||||
|
noGasPrice={false}
|
||||||
/>,
|
/>,
|
||||||
{ context: { t: (str) => str, metricsEvent: () => ({}) } },
|
{ context: { t: (str) => str, metricsEvent: () => ({}) } },
|
||||||
);
|
);
|
||||||
|
@ -24,6 +24,7 @@ import {
|
|||||||
getGasIsLoading,
|
getGasIsLoading,
|
||||||
getRenderableEstimateDataForSmallButtonsFromGWEI,
|
getRenderableEstimateDataForSmallButtonsFromGWEI,
|
||||||
getDefaultActiveButtonIndex,
|
getDefaultActiveButtonIndex,
|
||||||
|
getNoGasPriceFetched,
|
||||||
} from '../../../selectors';
|
} from '../../../selectors';
|
||||||
import { getMostRecentOverviewPage } from '../../../ducks/history/history';
|
import { getMostRecentOverviewPage } from '../../../ducks/history/history';
|
||||||
import { addHexPrefix } from '../../../../../app/scripts/lib/util';
|
import { addHexPrefix } from '../../../../../app/scripts/lib/util';
|
||||||
@ -67,6 +68,7 @@ function mapStateToProps(state) {
|
|||||||
gasEstimateType,
|
gasEstimateType,
|
||||||
gasIsLoading: getGasIsLoading(state),
|
gasIsLoading: getGasIsLoading(state),
|
||||||
mostRecentOverviewPage: getMostRecentOverviewPage(state),
|
mostRecentOverviewPage: getMostRecentOverviewPage(state),
|
||||||
|
noGasPrice: getNoGasPriceFetched(state),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,12 +27,14 @@ export function getCustomGasPrice(state) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function getBasicGasEstimateLoadingStatus(state) {
|
export function getBasicGasEstimateLoadingStatus(state) {
|
||||||
return state.gas.basicEstimateIsLoading;
|
return state.gas.basicEstimateStatus === 'LOADING';
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getAveragePriceEstimateInHexWEI(state) {
|
export function getAveragePriceEstimateInHexWEI(state) {
|
||||||
const averagePriceEstimate = state.gas.basicEstimates.average;
|
const averagePriceEstimate = state.gas.basicEstimates
|
||||||
return getGasPriceInHexWei(averagePriceEstimate || '0x0');
|
? state.gas.basicEstimates.average
|
||||||
|
: '0x0';
|
||||||
|
return getGasPriceInHexWei(averagePriceEstimate);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getFastPriceEstimateInHexWEI(state) {
|
export function getFastPriceEstimateInHexWEI(state) {
|
||||||
@ -355,3 +357,17 @@ export function getRenderableEstimateDataForSmallButtonsFromGWEI(state) {
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getIsEthGasPriceFetched(state) {
|
||||||
|
const gasState = state.gas;
|
||||||
|
return Boolean(
|
||||||
|
gasState.estimateSource === 'eth_gasprice' &&
|
||||||
|
gasState.basicEstimateStatus === 'READY' &&
|
||||||
|
getIsMainnet(state),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getNoGasPriceFetched(state) {
|
||||||
|
const gasState = state.gas;
|
||||||
|
return Boolean(gasState.basicEstimateStatus === 'FAILED');
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user