1
0
mirror of https://github.com/kremalicious/metamask-extension.git synced 2024-11-24 11:01:41 +01:00
metamask-extension/ui/app/ducks/gas/gas.duck.js
Erik Marks 7159dd6867
Fetch with a timeout everywhere (#10101)
* Use fetchWithTimeout everywhere
* Memoize getFetchWithTimeout
* Require specified timeout
2021-01-19 08:41:57 -08:00

211 lines
5.4 KiB
JavaScript

import { cloneDeep } from 'lodash'
import BigNumber from 'bignumber.js'
import { getStorageItem, setStorageItem } from '../../../lib/storage-helpers'
import { decGWEIToHexWEI } from '../../helpers/utils/conversions.util'
import getFetchWithTimeout from '../../../../shared/modules/fetch-with-timeout'
const fetchWithTimeout = getFetchWithTimeout(30000)
// Actions
const BASIC_GAS_ESTIMATE_LOADING_FINISHED =
'metamask/gas/BASIC_GAS_ESTIMATE_LOADING_FINISHED'
const BASIC_GAS_ESTIMATE_LOADING_STARTED =
'metamask/gas/BASIC_GAS_ESTIMATE_LOADING_STARTED'
const RESET_CUSTOM_GAS_STATE = 'metamask/gas/RESET_CUSTOM_GAS_STATE'
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'
const SET_BASIC_PRICE_ESTIMATES_LAST_RETRIEVED =
'metamask/gas/SET_BASIC_PRICE_ESTIMATES_LAST_RETRIEVED'
const initState = {
customData: {
price: null,
limit: null,
},
basicEstimates: {
safeLow: null,
average: null,
fast: null,
},
basicEstimateIsLoading: true,
basicPriceEstimatesLastRetrieved: 0,
}
// Reducer
export default function reducer(state = initState, action) {
switch (action.type) {
case BASIC_GAS_ESTIMATE_LOADING_STARTED:
return {
...state,
basicEstimateIsLoading: true,
}
case BASIC_GAS_ESTIMATE_LOADING_FINISHED:
return {
...state,
basicEstimateIsLoading: false,
}
case SET_BASIC_GAS_ESTIMATE_DATA:
return {
...state,
basicEstimates: action.value,
}
case SET_CUSTOM_GAS_PRICE:
return {
...state,
customData: {
...state.customData,
price: action.value,
},
}
case SET_CUSTOM_GAS_LIMIT:
return {
...state,
customData: {
...state.customData,
limit: action.value,
},
}
case SET_BASIC_PRICE_ESTIMATES_LAST_RETRIEVED:
return {
...state,
basicPriceEstimatesLastRetrieved: action.value,
}
case RESET_CUSTOM_DATA:
return {
...state,
customData: cloneDeep(initState.customData),
}
case RESET_CUSTOM_GAS_STATE:
return cloneDeep(initState)
default:
return state
}
}
// Action Creators
export function basicGasEstimatesLoadingStarted() {
return {
type: BASIC_GAS_ESTIMATE_LOADING_STARTED,
}
}
export function basicGasEstimatesLoadingFinished() {
return {
type: BASIC_GAS_ESTIMATE_LOADING_FINISHED,
}
}
async function basicGasPriceQuery() {
const url = `https://api.metaswap.codefi.network/gasPrices`
return await fetchWithTimeout(url, {
headers: {},
referrer: 'https://api.metaswap.codefi.network/gasPrices',
referrerPolicy: 'no-referrer-when-downgrade',
body: null,
method: 'GET',
mode: 'cors',
})
}
export function fetchBasicGasEstimates() {
return async (dispatch, getState) => {
const { basicPriceEstimatesLastRetrieved } = getState().gas
const timeLastRetrieved =
basicPriceEstimatesLastRetrieved ||
(await getStorageItem('BASIC_PRICE_ESTIMATES_LAST_RETRIEVED')) ||
0
dispatch(basicGasEstimatesLoadingStarted())
let basicEstimates
if (Date.now() - timeLastRetrieved > 75000) {
basicEstimates = await fetchExternalBasicGasEstimates(dispatch)
} else {
const cachedBasicEstimates = await getStorageItem('BASIC_PRICE_ESTIMATES')
basicEstimates =
cachedBasicEstimates || (await fetchExternalBasicGasEstimates(dispatch))
}
dispatch(setBasicGasEstimateData(basicEstimates))
dispatch(basicGasEstimatesLoadingFinished())
return basicEstimates
}
}
async function fetchExternalBasicGasEstimates(dispatch) {
const response = await basicGasPriceQuery()
const { SafeGasPrice, ProposeGasPrice, FastGasPrice } = await response.json()
const [safeLow, average, fast] = [
SafeGasPrice,
ProposeGasPrice,
FastGasPrice,
].map((price) => new BigNumber(price, 10).toNumber())
const basicEstimates = {
safeLow,
average,
fast,
}
const timeRetrieved = Date.now()
await Promise.all([
setStorageItem('BASIC_PRICE_ESTIMATES', basicEstimates),
setStorageItem('BASIC_PRICE_ESTIMATES_LAST_RETRIEVED', timeRetrieved),
])
dispatch(setBasicPriceEstimatesLastRetrieved(timeRetrieved))
return basicEstimates
}
export function setCustomGasPriceForRetry(newPrice) {
return async (dispatch) => {
if (newPrice === '0x0') {
const { fast } = await getStorageItem('BASIC_PRICE_ESTIMATES')
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) {
return {
type: SET_CUSTOM_GAS_PRICE,
value: newPrice,
}
}
export function setCustomGasLimit(newLimit) {
return {
type: SET_CUSTOM_GAS_LIMIT,
value: newLimit,
}
}
export function setBasicPriceEstimatesLastRetrieved(retrievalTime) {
return {
type: SET_BASIC_PRICE_ESTIMATES_LAST_RETRIEVED,
value: retrievalTime,
}
}
export function resetCustomGasState() {
return { type: RESET_CUSTOM_GAS_STATE }
}
export function resetCustomData() {
return { type: RESET_CUSTOM_DATA }
}