2021-02-04 19:15:23 +01:00
|
|
|
import { cloneDeep } from 'lodash';
|
|
|
|
import BigNumber from 'bignumber.js';
|
2021-04-28 21:53:59 +02:00
|
|
|
import {
|
|
|
|
getStorageItem,
|
|
|
|
setStorageItem,
|
|
|
|
} from '../../helpers/utils/storage-helpers';
|
2021-02-19 03:48:23 +01:00
|
|
|
import {
|
|
|
|
decGWEIToHexWEI,
|
|
|
|
getValueFromWeiHex,
|
|
|
|
} from '../../helpers/utils/conversions.util';
|
|
|
|
import { getIsMainnet, getCurrentChainId } from '../../selectors';
|
2021-03-09 20:49:27 +01:00
|
|
|
import fetchWithCache from '../../helpers/utils/fetch-with-cache';
|
2018-08-16 14:28:27 +02:00
|
|
|
|
2021-04-28 20:02:01 +02:00
|
|
|
const BASIC_ESTIMATE_STATES = {
|
|
|
|
LOADING: 'LOADING',
|
|
|
|
FAILED: 'FAILED',
|
|
|
|
READY: 'READY',
|
|
|
|
};
|
|
|
|
|
|
|
|
const GAS_SOURCE = {
|
|
|
|
METASWAPS: 'MetaSwaps',
|
|
|
|
ETHGASPRICE: 'eth_gasprice',
|
|
|
|
};
|
|
|
|
|
2018-08-16 14:28:27 +02:00
|
|
|
// Actions
|
2021-04-28 20:02:01 +02:00
|
|
|
const BASIC_GAS_ESTIMATE_STATUS = 'metamask/gas/BASIC_GAS_ESTIMATE_STATUS';
|
2021-02-04 19:15:23 +01:00
|
|
|
const RESET_CUSTOM_DATA = 'metamask/gas/RESET_CUSTOM_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_PRICE = 'metamask/gas/SET_CUSTOM_GAS_PRICE';
|
2021-04-28 20:02:01 +02:00
|
|
|
const SET_ESTIMATE_SOURCE = 'metamask/gas/SET_ESTIMATE_SOURCE';
|
2018-08-16 14:28:27 +02:00
|
|
|
|
|
|
|
const initState = {
|
|
|
|
customData: {
|
2018-09-13 10:47:05 +02:00
|
|
|
price: null,
|
2018-12-12 15:54:03 +01:00
|
|
|
limit: null,
|
2018-08-16 14:28:27 +02:00
|
|
|
},
|
|
|
|
basicEstimates: {
|
2020-12-03 00:25:19 +01:00
|
|
|
safeLow: null,
|
2018-08-16 14:28:27 +02:00
|
|
|
average: null,
|
|
|
|
fast: null,
|
|
|
|
},
|
2021-04-28 20:02:01 +02:00
|
|
|
basicEstimateStatus: BASIC_ESTIMATE_STATES.LOADING,
|
|
|
|
estimateSource: '',
|
2021-02-04 19:15:23 +01:00
|
|
|
};
|
2018-08-16 14:28:27 +02:00
|
|
|
|
|
|
|
// Reducer
|
2020-11-03 00:41:28 +01:00
|
|
|
export default function reducer(state = initState, action) {
|
2018-08-16 14:28:27 +02:00
|
|
|
switch (action.type) {
|
2021-04-28 20:02:01 +02:00
|
|
|
case BASIC_GAS_ESTIMATE_STATUS:
|
2018-08-16 14:28:27 +02:00
|
|
|
return {
|
2020-02-06 17:38:14 +01:00
|
|
|
...state,
|
2021-04-28 20:02:01 +02:00
|
|
|
basicEstimateStatus: action.value,
|
2021-02-04 19:15:23 +01:00
|
|
|
};
|
2018-08-16 14:28:27 +02:00
|
|
|
case SET_BASIC_GAS_ESTIMATE_DATA:
|
|
|
|
return {
|
2020-02-06 17:38:14 +01:00
|
|
|
...state,
|
2018-08-16 14:28:27 +02:00
|
|
|
basicEstimates: action.value,
|
2021-02-04 19:15:23 +01:00
|
|
|
};
|
2018-08-16 14:28:27 +02:00
|
|
|
case SET_CUSTOM_GAS_PRICE:
|
|
|
|
return {
|
2020-02-06 17:38:14 +01:00
|
|
|
...state,
|
2018-08-16 14:28:27 +02:00
|
|
|
customData: {
|
2020-02-06 17:38:14 +01:00
|
|
|
...state.customData,
|
2018-08-16 14:28:27 +02:00
|
|
|
price: action.value,
|
|
|
|
},
|
2021-02-04 19:15:23 +01:00
|
|
|
};
|
2018-08-16 14:28:27 +02:00
|
|
|
case SET_CUSTOM_GAS_LIMIT:
|
|
|
|
return {
|
2020-02-06 17:38:14 +01:00
|
|
|
...state,
|
2018-08-16 14:28:27 +02:00
|
|
|
customData: {
|
2020-02-06 17:38:14 +01:00
|
|
|
...state.customData,
|
2018-08-16 14:28:27 +02:00
|
|
|
limit: action.value,
|
|
|
|
},
|
2021-02-04 19:15:23 +01:00
|
|
|
};
|
2018-09-20 18:06:23 +02:00
|
|
|
case RESET_CUSTOM_DATA:
|
|
|
|
return {
|
2020-02-06 17:38:14 +01:00
|
|
|
...state,
|
2020-07-08 22:17:53 +02:00
|
|
|
customData: cloneDeep(initState.customData),
|
2021-02-04 19:15:23 +01:00
|
|
|
};
|
2021-04-28 20:02:01 +02:00
|
|
|
case SET_ESTIMATE_SOURCE:
|
|
|
|
return {
|
|
|
|
...state,
|
|
|
|
estimateSource: action.value,
|
|
|
|
};
|
2018-08-16 14:28:27 +02:00
|
|
|
default:
|
2021-02-04 19:15:23 +01:00
|
|
|
return state;
|
2018-08-16 14:28:27 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Action Creators
|
2021-04-28 20:02:01 +02:00
|
|
|
export function setBasicEstimateStatus(status) {
|
2018-08-16 14:28:27 +02:00
|
|
|
return {
|
2021-04-28 20:02:01 +02:00
|
|
|
type: BASIC_GAS_ESTIMATE_STATUS,
|
|
|
|
value: status,
|
2021-02-04 19:15:23 +01:00
|
|
|
};
|
2018-08-16 14:28:27 +02:00
|
|
|
}
|
|
|
|
|
2020-12-03 00:25:19 +01:00
|
|
|
async function basicGasPriceQuery() {
|
2021-02-04 19:15:23 +01:00
|
|
|
const url = `https://api.metaswap.codefi.network/gasPrices`;
|
2021-03-09 20:49:27 +01:00
|
|
|
return await fetchWithCache(
|
|
|
|
url,
|
|
|
|
{
|
|
|
|
referrer: url,
|
|
|
|
referrerPolicy: 'no-referrer-when-downgrade',
|
|
|
|
method: 'GET',
|
|
|
|
mode: 'cors',
|
|
|
|
},
|
|
|
|
{ cacheRefreshTime: 75000 },
|
|
|
|
);
|
2020-06-29 19:26:21 +02:00
|
|
|
}
|
|
|
|
|
2020-11-03 00:41:28 +01:00
|
|
|
export function fetchBasicGasEstimates() {
|
2019-07-04 21:18:12 +02:00
|
|
|
return async (dispatch, getState) => {
|
2021-02-19 03:48:23 +01:00
|
|
|
const isMainnet = getIsMainnet(getState());
|
2018-12-10 22:51:00 +01:00
|
|
|
|
2021-04-28 20:02:01 +02:00
|
|
|
dispatch(setBasicEstimateStatus(BASIC_ESTIMATE_STATES.LOADING));
|
2021-02-04 19:15:23 +01:00
|
|
|
let basicEstimates;
|
2021-04-28 20:02:01 +02:00
|
|
|
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));
|
2019-07-04 21:18:12 +02:00
|
|
|
}
|
2018-12-10 22:51:00 +01:00
|
|
|
|
2021-02-04 19:15:23 +01:00
|
|
|
return basicEstimates;
|
|
|
|
};
|
2019-07-04 21:18:12 +02:00
|
|
|
}
|
|
|
|
|
2021-03-09 20:49:27 +01:00
|
|
|
async function fetchExternalBasicGasEstimates() {
|
|
|
|
const {
|
|
|
|
SafeGasPrice,
|
|
|
|
ProposeGasPrice,
|
|
|
|
FastGasPrice,
|
|
|
|
} = await basicGasPriceQuery();
|
2018-12-10 22:51:00 +01:00
|
|
|
|
2020-12-03 00:25:19 +01:00
|
|
|
const [safeLow, average, fast] = [
|
|
|
|
SafeGasPrice,
|
|
|
|
ProposeGasPrice,
|
|
|
|
FastGasPrice,
|
2021-02-04 19:15:23 +01:00
|
|
|
].map((price) => new BigNumber(price, 10).toNumber());
|
2019-08-22 16:04:52 +02:00
|
|
|
|
2019-07-04 21:18:12 +02:00
|
|
|
const basicEstimates = {
|
|
|
|
safeLow,
|
|
|
|
average,
|
|
|
|
fast,
|
2021-02-04 19:15:23 +01:00
|
|
|
};
|
2019-07-04 21:18:12 +02:00
|
|
|
|
2021-02-19 03:48:23 +01:00
|
|
|
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,
|
|
|
|
),
|
|
|
|
]);
|
2019-07-04 21:18:12 +02:00
|
|
|
|
2021-02-04 19:15:23 +01:00
|
|
|
return basicEstimates;
|
2018-11-13 17:36:52 +01:00
|
|
|
}
|
|
|
|
|
2020-11-03 00:41:28 +01:00
|
|
|
export function setCustomGasPriceForRetry(newPrice) {
|
2020-11-24 16:38:04 +01:00
|
|
|
return async (dispatch) => {
|
2020-08-14 13:47:43 +02:00
|
|
|
if (newPrice === '0x0') {
|
2021-03-09 20:49:27 +01:00
|
|
|
const { fast } = await fetchExternalBasicGasEstimates();
|
2021-02-04 19:15:23 +01:00
|
|
|
dispatch(setCustomGasPrice(decGWEIToHexWEI(fast)));
|
2020-08-14 13:47:43 +02:00
|
|
|
} else {
|
2021-02-04 19:15:23 +01:00
|
|
|
dispatch(setCustomGasPrice(newPrice));
|
2018-12-09 21:48:06 +01:00
|
|
|
}
|
2021-02-04 19:15:23 +01:00
|
|
|
};
|
2018-12-09 21:48:06 +01:00
|
|
|
}
|
|
|
|
|
2020-11-03 00:41:28 +01:00
|
|
|
export function setBasicGasEstimateData(basicGasEstimateData) {
|
2018-08-16 14:28:27 +02:00
|
|
|
return {
|
|
|
|
type: SET_BASIC_GAS_ESTIMATE_DATA,
|
|
|
|
value: basicGasEstimateData,
|
2021-02-04 19:15:23 +01:00
|
|
|
};
|
2018-08-16 14:28:27 +02:00
|
|
|
}
|
|
|
|
|
2020-11-03 00:41:28 +01:00
|
|
|
export function setCustomGasPrice(newPrice) {
|
2018-08-16 14:28:27 +02:00
|
|
|
return {
|
|
|
|
type: SET_CUSTOM_GAS_PRICE,
|
|
|
|
value: newPrice,
|
2021-02-04 19:15:23 +01:00
|
|
|
};
|
2018-08-16 14:28:27 +02:00
|
|
|
}
|
|
|
|
|
2020-11-03 00:41:28 +01:00
|
|
|
export function setCustomGasLimit(newLimit) {
|
2018-08-16 14:28:27 +02:00
|
|
|
return {
|
|
|
|
type: SET_CUSTOM_GAS_LIMIT,
|
|
|
|
value: newLimit,
|
2021-02-04 19:15:23 +01:00
|
|
|
};
|
2018-08-16 14:28:27 +02:00
|
|
|
}
|
|
|
|
|
2020-11-03 00:41:28 +01:00
|
|
|
export function resetCustomData() {
|
2021-02-04 19:15:23 +01:00
|
|
|
return { type: RESET_CUSTOM_DATA };
|
2018-09-20 18:06:23 +02:00
|
|
|
}
|
2021-04-28 20:02:01 +02:00
|
|
|
|
|
|
|
export function setEstimateSource(estimateSource) {
|
|
|
|
return {
|
|
|
|
type: SET_ESTIMATE_SOURCE,
|
|
|
|
value: estimateSource,
|
|
|
|
};
|
|
|
|
}
|