mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-12-23 09:52:26 +01:00
Check for invalid gas estimates from local storage (#6800)
* Remove unused state 'gas.basicPriceAndTimeEstimates' * Check for invalid estimates from local storage Gas estimates were being cached in local storage then later retrieved, but the retrieved values were not being checked. If the data failed to save, failed to load, or was cleared since being saved, it would result in the gas estimates being set to undefined. The estimates retrieved from local storage are now checked before they are used. If they are falsy, the estimates are retrieved from the network instead. This should fix this Sentry issue: [METAMASK-6W0T](https://sentry.io/share/issue/cfe470314a5741768b19050815322aa4/) A few additional changes were made to the gas-duck tests to accommodate the use of `sinon.restore`. `restore` is strongly recommended by the `sinon` team, as neglecting to use it can result in memory leaks. It has the additional benefit of ensuring you create fresh stubs/spies for each test, which means they no longer need to be reset between tests.
This commit is contained in:
parent
c7608e6fe9
commit
ec40b2a325
@ -202,7 +202,6 @@
|
|||||||
},
|
},
|
||||||
"basicEstimateIsLoading": false,
|
"basicEstimateIsLoading": false,
|
||||||
"gasEstimatesLoading": false,
|
"gasEstimatesLoading": false,
|
||||||
"basicPriceAndTimeEstimates": [],
|
|
||||||
"priceAndTimeEstimates": [
|
"priceAndTimeEstimates": [
|
||||||
{
|
{
|
||||||
"expectedTime": "1374.1168296452973076627",
|
"expectedTime": "1374.1168296452973076627",
|
||||||
|
@ -228,7 +228,6 @@
|
|||||||
},
|
},
|
||||||
"basicEstimateIsLoading": false,
|
"basicEstimateIsLoading": false,
|
||||||
"gasEstimatesLoading": false,
|
"gasEstimatesLoading": false,
|
||||||
"basicPriceAndTimeEstimates": [],
|
|
||||||
"priceAndTimeEstimates": [
|
"priceAndTimeEstimates": [
|
||||||
{
|
{
|
||||||
"expectedTime": "1374.1168296452973076627",
|
"expectedTime": "1374.1168296452973076627",
|
||||||
|
@ -178,7 +178,6 @@
|
|||||||
},
|
},
|
||||||
"basicEstimateIsLoading": false,
|
"basicEstimateIsLoading": false,
|
||||||
"gasEstimatesLoading": false,
|
"gasEstimatesLoading": false,
|
||||||
"basicPriceAndTimeEstimates": [],
|
|
||||||
"priceAndTimeEstimates": [
|
"priceAndTimeEstimates": [
|
||||||
{
|
{
|
||||||
"expectedTime": "1374.1168296452973076627",
|
"expectedTime": "1374.1168296452973076627",
|
||||||
|
@ -206,7 +206,6 @@
|
|||||||
},
|
},
|
||||||
"basicEstimateIsLoading": false,
|
"basicEstimateIsLoading": false,
|
||||||
"gasEstimatesLoading": false,
|
"gasEstimatesLoading": false,
|
||||||
"basicPriceAndTimeEstimates": [],
|
|
||||||
"priceAndTimeEstimates": [
|
"priceAndTimeEstimates": [
|
||||||
{
|
{
|
||||||
"expectedTime": "1374.1168296452973076627",
|
"expectedTime": "1374.1168296452973076627",
|
||||||
|
@ -186,7 +186,6 @@
|
|||||||
},
|
},
|
||||||
"basicEstimateIsLoading": false,
|
"basicEstimateIsLoading": false,
|
||||||
"gasEstimatesLoading": false,
|
"gasEstimatesLoading": false,
|
||||||
"basicPriceAndTimeEstimates": [],
|
|
||||||
"priceAndTimeEstimates": [
|
"priceAndTimeEstimates": [
|
||||||
{
|
{
|
||||||
"expectedTime": "1374.1168296452973076627",
|
"expectedTime": "1374.1168296452973076627",
|
||||||
|
@ -1109,7 +1109,6 @@
|
|||||||
},
|
},
|
||||||
"basicEstimateIsLoading": false,
|
"basicEstimateIsLoading": false,
|
||||||
"gasEstimatesLoading": false,
|
"gasEstimatesLoading": false,
|
||||||
"basicPriceAndTimeEstimates": [],
|
|
||||||
"priceAndTimeEstimates": [
|
"priceAndTimeEstimates": [
|
||||||
{
|
{
|
||||||
"expectedTime": "1374.1168296452973076627",
|
"expectedTime": "1374.1168296452973076627",
|
||||||
|
@ -2,12 +2,10 @@ import assert from 'assert'
|
|||||||
import sinon from 'sinon'
|
import sinon from 'sinon'
|
||||||
import proxyquire from 'proxyquire'
|
import proxyquire from 'proxyquire'
|
||||||
|
|
||||||
|
const fakeLocalStorage = {}
|
||||||
|
|
||||||
const GasDuck = proxyquire('./gas.duck.js', {
|
const GasDuck = proxyquire('./gas.duck.js', {
|
||||||
'../../../lib/local-storage-helpers': {
|
'../../../lib/local-storage-helpers': fakeLocalStorage,
|
||||||
loadLocalStorageData: sinon.spy(),
|
|
||||||
saveLocalStorageData: sinon.spy(),
|
|
||||||
},
|
|
||||||
})
|
})
|
||||||
|
|
||||||
const {
|
const {
|
||||||
@ -68,24 +66,28 @@ describe('Gas Duck', () => {
|
|||||||
{ expectedTime: 1.1, expectedWait: 0.6, gasprice: 19.9, somethingElse: 'foobar' },
|
{ expectedTime: 1.1, expectedWait: 0.6, gasprice: 19.9, somethingElse: 'foobar' },
|
||||||
{ expectedTime: 1, expectedWait: 0.5, gasprice: 20, somethingElse: 'foobar' },
|
{ expectedTime: 1, expectedWait: 0.5, gasprice: 20, somethingElse: 'foobar' },
|
||||||
]
|
]
|
||||||
const fetchStub = sinon.stub().callsFake((url) => new Promise(resolve => {
|
const fakeFetch = (url) => new Promise(resolve => {
|
||||||
const dataToResolve = url.match(/ethgasAPI|gasexpress/)
|
const dataToResolve = url.match(/ethgasAPI|gasexpress/)
|
||||||
? mockEthGasApiResponse
|
? mockEthGasApiResponse
|
||||||
: mockPredictTableResponse
|
: mockPredictTableResponse
|
||||||
resolve({
|
resolve({
|
||||||
json: () => new Promise(resolve => resolve(dataToResolve)),
|
json: () => new Promise(resolve => resolve(dataToResolve)),
|
||||||
})
|
})
|
||||||
}))
|
})
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
tempFetch = global.fetch
|
tempFetch = global.fetch
|
||||||
tempDateNow = global.Date.now
|
tempDateNow = global.Date.now
|
||||||
global.fetch = fetchStub
|
|
||||||
|
fakeLocalStorage.loadLocalStorageData = sinon.stub()
|
||||||
|
fakeLocalStorage.saveLocalStorageData = sinon.spy()
|
||||||
|
global.fetch = sinon.stub().callsFake(fakeFetch)
|
||||||
global.Date.now = () => 2000000
|
global.Date.now = () => 2000000
|
||||||
})
|
})
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
fetchStub.resetHistory()
|
sinon.restore()
|
||||||
|
|
||||||
global.fetch = tempFetch
|
global.fetch = tempFetch
|
||||||
global.Date.now = tempDateNow
|
global.Date.now = tempDateNow
|
||||||
})
|
})
|
||||||
@ -118,7 +120,6 @@ describe('Gas Duck', () => {
|
|||||||
gasEstimatesLoading: true,
|
gasEstimatesLoading: true,
|
||||||
priceAndTimeEstimates: [],
|
priceAndTimeEstimates: [],
|
||||||
priceAndTimeEstimatesLastRetrieved: 0,
|
priceAndTimeEstimatesLastRetrieved: 0,
|
||||||
basicPriceAndTimeEstimates: [],
|
|
||||||
basicPriceAndTimeEstimatesLastRetrieved: 0,
|
basicPriceAndTimeEstimatesLastRetrieved: 0,
|
||||||
basicPriceEstimatesLastRetrieved: 0,
|
basicPriceEstimatesLastRetrieved: 0,
|
||||||
}
|
}
|
||||||
@ -305,8 +306,9 @@ describe('Gas Duck', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
describe('fetchBasicGasEstimates', () => {
|
describe('fetchBasicGasEstimates', () => {
|
||||||
const mockDistpatch = sinon.spy()
|
|
||||||
it('should call fetch with the expected params', async () => {
|
it('should call fetch with the expected params', async () => {
|
||||||
|
const mockDistpatch = sinon.spy()
|
||||||
|
|
||||||
await fetchBasicGasEstimates()(mockDistpatch, () => ({ gas: Object.assign(
|
await fetchBasicGasEstimates()(mockDistpatch, () => ({ gas: Object.assign(
|
||||||
{},
|
{},
|
||||||
initState,
|
initState,
|
||||||
@ -330,12 +332,109 @@ describe('Gas Duck', () => {
|
|||||||
},
|
},
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
assert.deepEqual(
|
assert.deepEqual(
|
||||||
mockDistpatch.getCall(1).args,
|
mockDistpatch.getCall(1).args,
|
||||||
[{ type: SET_BASIC_PRICE_ESTIMATES_LAST_RETRIEVED, value: 2000000 } ]
|
[{ type: SET_BASIC_PRICE_ESTIMATES_LAST_RETRIEVED, value: 2000000 } ]
|
||||||
)
|
)
|
||||||
|
assert.deepEqual(
|
||||||
|
mockDistpatch.getCall(2).args,
|
||||||
|
[{
|
||||||
|
type: SET_BASIC_GAS_ESTIMATE_DATA,
|
||||||
|
value: {
|
||||||
|
average: 20,
|
||||||
|
blockTime: 'mockBlock_time',
|
||||||
|
blockNum: 'mockBlockNum',
|
||||||
|
fast: 30,
|
||||||
|
fastest: 40,
|
||||||
|
safeLow: 10,
|
||||||
|
},
|
||||||
|
}]
|
||||||
|
)
|
||||||
|
assert.deepEqual(
|
||||||
|
mockDistpatch.getCall(3).args,
|
||||||
|
[{ type: BASIC_GAS_ESTIMATE_LOADING_FINISHED }]
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should fetch recently retrieved estimates from local storage', async () => {
|
||||||
|
const mockDistpatch = sinon.spy()
|
||||||
|
fakeLocalStorage.loadLocalStorageData
|
||||||
|
.withArgs('BASIC_PRICE_ESTIMATES_LAST_RETRIEVED')
|
||||||
|
.returns(2000000 - 1) // one second ago from "now"
|
||||||
|
fakeLocalStorage.loadLocalStorageData
|
||||||
|
.withArgs('BASIC_PRICE_ESTIMATES')
|
||||||
|
.returns({
|
||||||
|
average: 25,
|
||||||
|
blockTime: 'mockBlock_time',
|
||||||
|
blockNum: 'mockBlockNum',
|
||||||
|
fast: 35,
|
||||||
|
fastest: 45,
|
||||||
|
safeLow: 15,
|
||||||
|
})
|
||||||
|
|
||||||
|
await fetchBasicGasEstimates()(mockDistpatch, () => ({ gas: Object.assign(
|
||||||
|
{},
|
||||||
|
initState,
|
||||||
|
{}
|
||||||
|
) }))
|
||||||
|
assert.deepEqual(
|
||||||
|
mockDistpatch.getCall(0).args,
|
||||||
|
[{ type: BASIC_GAS_ESTIMATE_LOADING_STARTED} ]
|
||||||
|
)
|
||||||
|
assert.ok(global.fetch.notCalled)
|
||||||
|
assert.deepEqual(
|
||||||
|
mockDistpatch.getCall(1).args,
|
||||||
|
[{
|
||||||
|
type: SET_BASIC_GAS_ESTIMATE_DATA,
|
||||||
|
value: {
|
||||||
|
average: 25,
|
||||||
|
blockTime: 'mockBlock_time',
|
||||||
|
blockNum: 'mockBlockNum',
|
||||||
|
fast: 35,
|
||||||
|
fastest: 45,
|
||||||
|
safeLow: 15,
|
||||||
|
},
|
||||||
|
}]
|
||||||
|
)
|
||||||
|
assert.deepEqual(
|
||||||
|
mockDistpatch.getCall(2).args,
|
||||||
|
[{ type: BASIC_GAS_ESTIMATE_LOADING_FINISHED }]
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should fallback to network if retrieving estimates from local storage fails', async () => {
|
||||||
|
const mockDistpatch = sinon.spy()
|
||||||
|
fakeLocalStorage.loadLocalStorageData
|
||||||
|
.withArgs('BASIC_PRICE_ESTIMATES_LAST_RETRIEVED')
|
||||||
|
.returns(2000000 - 1) // one second ago from "now"
|
||||||
|
|
||||||
|
await fetchBasicGasEstimates()(mockDistpatch, () => ({ gas: Object.assign(
|
||||||
|
{},
|
||||||
|
initState,
|
||||||
|
{}
|
||||||
|
) }))
|
||||||
|
assert.deepEqual(
|
||||||
|
mockDistpatch.getCall(0).args,
|
||||||
|
[{ type: BASIC_GAS_ESTIMATE_LOADING_STARTED} ]
|
||||||
|
)
|
||||||
|
assert.deepEqual(
|
||||||
|
global.fetch.getCall(0).args,
|
||||||
|
[
|
||||||
|
'https://dev.blockscale.net/api/gasexpress.json',
|
||||||
|
{
|
||||||
|
'headers': {},
|
||||||
|
'referrer': 'https://dev.blockscale.net/api/',
|
||||||
|
'referrerPolicy': 'no-referrer-when-downgrade',
|
||||||
|
'body': null,
|
||||||
|
'method': 'GET',
|
||||||
|
'mode': 'cors',
|
||||||
|
},
|
||||||
|
]
|
||||||
|
)
|
||||||
|
assert.deepEqual(
|
||||||
|
mockDistpatch.getCall(1).args,
|
||||||
|
[{ type: SET_BASIC_PRICE_ESTIMATES_LAST_RETRIEVED, value: 2000000 } ]
|
||||||
|
)
|
||||||
assert.deepEqual(
|
assert.deepEqual(
|
||||||
mockDistpatch.getCall(2).args,
|
mockDistpatch.getCall(2).args,
|
||||||
[{
|
[{
|
||||||
@ -358,8 +457,9 @@ describe('Gas Duck', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
describe('fetchBasicGasAndTimeEstimates', () => {
|
describe('fetchBasicGasAndTimeEstimates', () => {
|
||||||
const mockDistpatch = sinon.spy()
|
|
||||||
it('should call fetch with the expected params', async () => {
|
it('should call fetch with the expected params', async () => {
|
||||||
|
const mockDistpatch = sinon.spy()
|
||||||
|
|
||||||
await fetchBasicGasAndTimeEstimates()(mockDistpatch, () => ({ gas: Object.assign(
|
await fetchBasicGasAndTimeEstimates()(mockDistpatch, () => ({ gas: Object.assign(
|
||||||
{},
|
{},
|
||||||
initState,
|
initState,
|
||||||
@ -415,17 +515,133 @@ describe('Gas Duck', () => {
|
|||||||
[{ type: BASIC_GAS_ESTIMATE_LOADING_FINISHED }]
|
[{ type: BASIC_GAS_ESTIMATE_LOADING_FINISHED }]
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('should fetch recently retrieved estimates from local storage', async () => {
|
||||||
|
const mockDistpatch = sinon.spy()
|
||||||
|
fakeLocalStorage.loadLocalStorageData
|
||||||
|
.withArgs('BASIC_GAS_AND_TIME_API_ESTIMATES_LAST_RETRIEVED')
|
||||||
|
.returns(2000000 - 1) // one second ago from "now"
|
||||||
|
fakeLocalStorage.loadLocalStorageData
|
||||||
|
.withArgs('BASIC_GAS_AND_TIME_API_ESTIMATES')
|
||||||
|
.returns({
|
||||||
|
average: 5,
|
||||||
|
avgWait: 'mockAvgWait',
|
||||||
|
blockTime: 'mockBlock_time',
|
||||||
|
blockNum: 'mockBlockNum',
|
||||||
|
fast: 6,
|
||||||
|
fastest: 7,
|
||||||
|
fastestWait: 'mockFastestWait',
|
||||||
|
fastWait: 'mockFastWait',
|
||||||
|
safeLow: 1,
|
||||||
|
safeLowWait: 'mockSafeLowWait',
|
||||||
|
speed: 'mockSpeed',
|
||||||
|
})
|
||||||
|
|
||||||
|
await fetchBasicGasAndTimeEstimates()(mockDistpatch, () => ({ gas: Object.assign(
|
||||||
|
{},
|
||||||
|
initState,
|
||||||
|
{}
|
||||||
|
),
|
||||||
|
metamask: { provider: { type: 'ropsten' } },
|
||||||
|
}))
|
||||||
|
assert.deepEqual(
|
||||||
|
mockDistpatch.getCall(0).args,
|
||||||
|
[{ type: BASIC_GAS_ESTIMATE_LOADING_STARTED} ]
|
||||||
|
)
|
||||||
|
assert.ok(global.fetch.notCalled)
|
||||||
|
|
||||||
|
assert.deepEqual(
|
||||||
|
mockDistpatch.getCall(1).args,
|
||||||
|
[{
|
||||||
|
type: SET_BASIC_GAS_ESTIMATE_DATA,
|
||||||
|
value: {
|
||||||
|
average: 5,
|
||||||
|
avgWait: 'mockAvgWait',
|
||||||
|
blockTime: 'mockBlock_time',
|
||||||
|
blockNum: 'mockBlockNum',
|
||||||
|
fast: 6,
|
||||||
|
fastest: 7,
|
||||||
|
fastestWait: 'mockFastestWait',
|
||||||
|
fastWait: 'mockFastWait',
|
||||||
|
safeLow: 1,
|
||||||
|
safeLowWait: 'mockSafeLowWait',
|
||||||
|
speed: 'mockSpeed',
|
||||||
|
},
|
||||||
|
}]
|
||||||
|
)
|
||||||
|
assert.deepEqual(
|
||||||
|
mockDistpatch.getCall(2).args,
|
||||||
|
[{ type: BASIC_GAS_ESTIMATE_LOADING_FINISHED }]
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should fallback to network if retrieving estimates from local storage fails', async () => {
|
||||||
|
const mockDistpatch = sinon.spy()
|
||||||
|
fakeLocalStorage.loadLocalStorageData
|
||||||
|
.withArgs('BASIC_GAS_AND_TIME_API_ESTIMATES_LAST_RETRIEVED')
|
||||||
|
.returns(2000000 - 1) // one second ago from "now"
|
||||||
|
|
||||||
|
await fetchBasicGasAndTimeEstimates()(mockDistpatch, () => ({ gas: Object.assign(
|
||||||
|
{},
|
||||||
|
initState,
|
||||||
|
{}
|
||||||
|
),
|
||||||
|
metamask: { provider: { type: 'ropsten' } },
|
||||||
|
}))
|
||||||
|
assert.deepEqual(
|
||||||
|
mockDistpatch.getCall(0).args,
|
||||||
|
[{ type: BASIC_GAS_ESTIMATE_LOADING_STARTED} ]
|
||||||
|
)
|
||||||
|
assert.deepEqual(
|
||||||
|
global.fetch.getCall(0).args,
|
||||||
|
[
|
||||||
|
'https://ethgasstation.info/json/ethgasAPI.json',
|
||||||
|
{
|
||||||
|
'headers': {},
|
||||||
|
'referrer': 'http://ethgasstation.info/json/',
|
||||||
|
'referrerPolicy': 'no-referrer-when-downgrade',
|
||||||
|
'body': null,
|
||||||
|
'method': 'GET',
|
||||||
|
'mode': 'cors',
|
||||||
|
},
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
assert.deepEqual(
|
||||||
|
mockDistpatch.getCall(1).args,
|
||||||
|
[{ type: SET_BASIC_API_ESTIMATES_LAST_RETRIEVED, value: 2000000 } ]
|
||||||
|
)
|
||||||
|
|
||||||
|
assert.deepEqual(
|
||||||
|
mockDistpatch.getCall(2).args,
|
||||||
|
[{
|
||||||
|
type: SET_BASIC_GAS_ESTIMATE_DATA,
|
||||||
|
value: {
|
||||||
|
average: 2,
|
||||||
|
avgWait: 'mockAvgWait',
|
||||||
|
blockTime: 'mockBlock_time',
|
||||||
|
blockNum: 'mockBlockNum',
|
||||||
|
fast: 3,
|
||||||
|
fastest: 4,
|
||||||
|
fastestWait: 'mockFastestWait',
|
||||||
|
fastWait: 'mockFastWait',
|
||||||
|
safeLow: 1,
|
||||||
|
safeLowWait: 'mockSafeLowWait',
|
||||||
|
speed: 'mockSpeed',
|
||||||
|
},
|
||||||
|
}]
|
||||||
|
)
|
||||||
|
assert.deepEqual(
|
||||||
|
mockDistpatch.getCall(3).args,
|
||||||
|
[{ type: BASIC_GAS_ESTIMATE_LOADING_FINISHED }]
|
||||||
|
)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('fetchGasEstimates', () => {
|
describe('fetchGasEstimates', () => {
|
||||||
const mockDistpatch = sinon.spy()
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
mockDistpatch.resetHistory()
|
|
||||||
})
|
|
||||||
|
|
||||||
it('should call fetch with the expected params', async () => {
|
it('should call fetch with the expected params', async () => {
|
||||||
global.fetch.resetHistory()
|
const mockDistpatch = sinon.spy()
|
||||||
|
|
||||||
await fetchGasEstimates(5)(mockDistpatch, () => ({ gas: Object.assign(
|
await fetchGasEstimates(5)(mockDistpatch, () => ({ gas: Object.assign(
|
||||||
{},
|
{},
|
||||||
initState,
|
initState,
|
||||||
@ -471,7 +687,8 @@ describe('Gas Duck', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it('should not call fetch if the estimates were retrieved < 75000 ms ago', async () => {
|
it('should not call fetch if the estimates were retrieved < 75000 ms ago', async () => {
|
||||||
global.fetch.resetHistory()
|
const mockDistpatch = sinon.spy()
|
||||||
|
|
||||||
await fetchGasEstimates(5)(mockDistpatch, () => ({ gas: Object.assign(
|
await fetchGasEstimates(5)(mockDistpatch, () => ({ gas: Object.assign(
|
||||||
{},
|
{},
|
||||||
initState,
|
initState,
|
||||||
|
@ -50,7 +50,6 @@ const initState = {
|
|||||||
basicEstimateIsLoading: true,
|
basicEstimateIsLoading: true,
|
||||||
gasEstimatesLoading: true,
|
gasEstimatesLoading: true,
|
||||||
priceAndTimeEstimates: [],
|
priceAndTimeEstimates: [],
|
||||||
basicPriceAndTimeEstimates: [],
|
|
||||||
priceAndTimeEstimatesLastRetrieved: 0,
|
priceAndTimeEstimatesLastRetrieved: 0,
|
||||||
basicPriceAndTimeEstimatesLastRetrieved: 0,
|
basicPriceAndTimeEstimatesLastRetrieved: 0,
|
||||||
basicPriceEstimatesLastRetrieved: 0,
|
basicPriceEstimatesLastRetrieved: 0,
|
||||||
@ -177,136 +176,134 @@ export function gasEstimatesLoadingFinished () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function fetchBasicGasEstimates () {
|
export function fetchBasicGasEstimates () {
|
||||||
return (dispatch, getState) => {
|
return async (dispatch, getState) => {
|
||||||
const {
|
const { basicPriceEstimatesLastRetrieved } = getState().gas
|
||||||
basicPriceEstimatesLastRetrieved,
|
|
||||||
basicPriceAndTimeEstimates,
|
|
||||||
} = getState().gas
|
|
||||||
const timeLastRetrieved = basicPriceEstimatesLastRetrieved || loadLocalStorageData('BASIC_PRICE_ESTIMATES_LAST_RETRIEVED') || 0
|
const timeLastRetrieved = basicPriceEstimatesLastRetrieved || loadLocalStorageData('BASIC_PRICE_ESTIMATES_LAST_RETRIEVED') || 0
|
||||||
|
|
||||||
dispatch(basicGasEstimatesLoadingStarted())
|
dispatch(basicGasEstimatesLoadingStarted())
|
||||||
|
|
||||||
const promiseToFetch = Date.now() - timeLastRetrieved > 75000
|
let basicEstimates
|
||||||
? fetch('https://dev.blockscale.net/api/gasexpress.json', {
|
if (Date.now() - timeLastRetrieved > 75000) {
|
||||||
'headers': {},
|
basicEstimates = await fetchExternalBasicGasEstimates(dispatch)
|
||||||
'referrer': 'https://dev.blockscale.net/api/',
|
} else {
|
||||||
'referrerPolicy': 'no-referrer-when-downgrade',
|
const cachedBasicEstimates = loadLocalStorageData('BASIC_PRICE_ESTIMATES')
|
||||||
'body': null,
|
basicEstimates = cachedBasicEstimates || await fetchExternalBasicGasEstimates(dispatch)
|
||||||
'method': 'GET',
|
}
|
||||||
'mode': 'cors'}
|
|
||||||
)
|
|
||||||
.then(r => r.json())
|
|
||||||
.then(({
|
|
||||||
safeLow,
|
|
||||||
standard: average,
|
|
||||||
fast,
|
|
||||||
fastest,
|
|
||||||
block_time: blockTime,
|
|
||||||
blockNum,
|
|
||||||
}) => {
|
|
||||||
const basicEstimates = {
|
|
||||||
safeLow,
|
|
||||||
average,
|
|
||||||
fast,
|
|
||||||
fastest,
|
|
||||||
blockTime,
|
|
||||||
blockNum,
|
|
||||||
}
|
|
||||||
|
|
||||||
const timeRetrieved = Date.now()
|
dispatch(setBasicGasEstimateData(basicEstimates))
|
||||||
dispatch(setBasicPriceEstimatesLastRetrieved(timeRetrieved))
|
dispatch(basicGasEstimatesLoadingFinished())
|
||||||
saveLocalStorageData(timeRetrieved, 'BASIC_PRICE_ESTIMATES_LAST_RETRIEVED')
|
|
||||||
saveLocalStorageData(basicEstimates, 'BASIC_PRICE_ESTIMATES')
|
|
||||||
|
|
||||||
return basicEstimates
|
return basicEstimates
|
||||||
})
|
|
||||||
: Promise.resolve(basicPriceAndTimeEstimates.length
|
|
||||||
? basicPriceAndTimeEstimates
|
|
||||||
: loadLocalStorageData('BASIC_PRICE_ESTIMATES')
|
|
||||||
)
|
|
||||||
|
|
||||||
return promiseToFetch.then(basicEstimates => {
|
|
||||||
dispatch(setBasicGasEstimateData(basicEstimates))
|
|
||||||
dispatch(basicGasEstimatesLoadingFinished())
|
|
||||||
return basicEstimates
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function fetchExternalBasicGasEstimates (dispatch) {
|
||||||
|
const response = await fetch('https://dev.blockscale.net/api/gasexpress.json', {
|
||||||
|
'headers': {},
|
||||||
|
'referrer': 'https://dev.blockscale.net/api/',
|
||||||
|
'referrerPolicy': 'no-referrer-when-downgrade',
|
||||||
|
'body': null,
|
||||||
|
'method': 'GET',
|
||||||
|
'mode': 'cors'}
|
||||||
|
)
|
||||||
|
const {
|
||||||
|
safeLow,
|
||||||
|
standard: average,
|
||||||
|
fast,
|
||||||
|
fastest,
|
||||||
|
block_time: blockTime,
|
||||||
|
blockNum,
|
||||||
|
} = await response.json()
|
||||||
|
|
||||||
|
const basicEstimates = {
|
||||||
|
safeLow,
|
||||||
|
average,
|
||||||
|
fast,
|
||||||
|
fastest,
|
||||||
|
blockTime,
|
||||||
|
blockNum,
|
||||||
|
}
|
||||||
|
|
||||||
|
const timeRetrieved = Date.now()
|
||||||
|
saveLocalStorageData(basicEstimates, 'BASIC_PRICE_ESTIMATES')
|
||||||
|
saveLocalStorageData(timeRetrieved, 'BASIC_PRICE_ESTIMATES_LAST_RETRIEVED')
|
||||||
|
dispatch(setBasicPriceEstimatesLastRetrieved(timeRetrieved))
|
||||||
|
|
||||||
|
return basicEstimates
|
||||||
|
}
|
||||||
|
|
||||||
export function fetchBasicGasAndTimeEstimates () {
|
export function fetchBasicGasAndTimeEstimates () {
|
||||||
return (dispatch, getState) => {
|
return async (dispatch, getState) => {
|
||||||
const {
|
const { basicPriceAndTimeEstimatesLastRetrieved } = getState().gas
|
||||||
basicPriceAndTimeEstimatesLastRetrieved,
|
|
||||||
basicPriceAndTimeEstimates,
|
|
||||||
} = getState().gas
|
|
||||||
const timeLastRetrieved = basicPriceAndTimeEstimatesLastRetrieved || loadLocalStorageData('BASIC_GAS_AND_TIME_API_ESTIMATES_LAST_RETRIEVED') || 0
|
const timeLastRetrieved = basicPriceAndTimeEstimatesLastRetrieved || loadLocalStorageData('BASIC_GAS_AND_TIME_API_ESTIMATES_LAST_RETRIEVED') || 0
|
||||||
|
|
||||||
dispatch(basicGasEstimatesLoadingStarted())
|
dispatch(basicGasEstimatesLoadingStarted())
|
||||||
|
|
||||||
const promiseToFetch = Date.now() - timeLastRetrieved > 75000
|
let basicEstimates
|
||||||
? fetch('https://ethgasstation.info/json/ethgasAPI.json', {
|
if (Date.now() - timeLastRetrieved > 75000) {
|
||||||
'headers': {},
|
basicEstimates = await fetchExternalBasicGasAndTimeEstimates(dispatch)
|
||||||
'referrer': 'http://ethgasstation.info/json/',
|
} else {
|
||||||
'referrerPolicy': 'no-referrer-when-downgrade',
|
const cachedBasicEstimates = loadLocalStorageData('BASIC_GAS_AND_TIME_API_ESTIMATES')
|
||||||
'body': null,
|
basicEstimates = cachedBasicEstimates || await fetchExternalBasicGasAndTimeEstimates(dispatch)
|
||||||
'method': 'GET',
|
}
|
||||||
'mode': 'cors'}
|
|
||||||
)
|
|
||||||
.then(r => r.json())
|
|
||||||
.then(({
|
|
||||||
average: averageTimes10,
|
|
||||||
avgWait,
|
|
||||||
block_time: blockTime,
|
|
||||||
blockNum,
|
|
||||||
fast: fastTimes10,
|
|
||||||
fastest: fastestTimes10,
|
|
||||||
fastestWait,
|
|
||||||
fastWait,
|
|
||||||
safeLow: safeLowTimes10,
|
|
||||||
safeLowWait,
|
|
||||||
speed,
|
|
||||||
}) => {
|
|
||||||
const [average, fast, fastest, safeLow] = [
|
|
||||||
averageTimes10,
|
|
||||||
fastTimes10,
|
|
||||||
fastestTimes10,
|
|
||||||
safeLowTimes10,
|
|
||||||
].map(price => (new BigNumber(price)).div(10).toNumber())
|
|
||||||
|
|
||||||
const basicEstimates = {
|
dispatch(setBasicGasEstimateData(basicEstimates))
|
||||||
average,
|
dispatch(basicGasEstimatesLoadingFinished())
|
||||||
avgWait,
|
return basicEstimates
|
||||||
blockTime,
|
|
||||||
blockNum,
|
|
||||||
fast,
|
|
||||||
fastest,
|
|
||||||
fastestWait,
|
|
||||||
fastWait,
|
|
||||||
safeLow,
|
|
||||||
safeLowWait,
|
|
||||||
speed,
|
|
||||||
}
|
|
||||||
|
|
||||||
const timeRetrieved = Date.now()
|
|
||||||
dispatch(setBasicApiEstimatesLastRetrieved(timeRetrieved))
|
|
||||||
saveLocalStorageData(timeRetrieved, 'BASIC_GAS_AND_TIME_API_ESTIMATES_LAST_RETRIEVED')
|
|
||||||
saveLocalStorageData(basicEstimates, 'BASIC_GAS_AND_TIME_API_ESTIMATES')
|
|
||||||
|
|
||||||
return basicEstimates
|
|
||||||
})
|
|
||||||
: Promise.resolve(basicPriceAndTimeEstimates.length
|
|
||||||
? basicPriceAndTimeEstimates
|
|
||||||
: loadLocalStorageData('BASIC_GAS_AND_TIME_API_ESTIMATES')
|
|
||||||
)
|
|
||||||
|
|
||||||
return promiseToFetch.then(basicEstimates => {
|
|
||||||
dispatch(setBasicGasEstimateData(basicEstimates))
|
|
||||||
dispatch(basicGasEstimatesLoadingFinished())
|
|
||||||
return basicEstimates
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function fetchExternalBasicGasAndTimeEstimates (dispatch) {
|
||||||
|
const response = await fetch('https://ethgasstation.info/json/ethgasAPI.json', {
|
||||||
|
'headers': {},
|
||||||
|
'referrer': 'http://ethgasstation.info/json/',
|
||||||
|
'referrerPolicy': 'no-referrer-when-downgrade',
|
||||||
|
'body': null,
|
||||||
|
'method': 'GET',
|
||||||
|
'mode': 'cors'}
|
||||||
|
)
|
||||||
|
const {
|
||||||
|
average: averageTimes10,
|
||||||
|
avgWait,
|
||||||
|
block_time: blockTime,
|
||||||
|
blockNum,
|
||||||
|
fast: fastTimes10,
|
||||||
|
fastest: fastestTimes10,
|
||||||
|
fastestWait,
|
||||||
|
fastWait,
|
||||||
|
safeLow: safeLowTimes10,
|
||||||
|
safeLowWait,
|
||||||
|
speed,
|
||||||
|
} = await response.json()
|
||||||
|
const [average, fast, fastest, safeLow] = [
|
||||||
|
averageTimes10,
|
||||||
|
fastTimes10,
|
||||||
|
fastestTimes10,
|
||||||
|
safeLowTimes10,
|
||||||
|
].map(price => (new BigNumber(price)).div(10).toNumber())
|
||||||
|
|
||||||
|
const basicEstimates = {
|
||||||
|
average,
|
||||||
|
avgWait,
|
||||||
|
blockTime,
|
||||||
|
blockNum,
|
||||||
|
fast,
|
||||||
|
fastest,
|
||||||
|
fastestWait,
|
||||||
|
fastWait,
|
||||||
|
safeLow,
|
||||||
|
safeLowWait,
|
||||||
|
speed,
|
||||||
|
}
|
||||||
|
|
||||||
|
const timeRetrieved = Date.now()
|
||||||
|
saveLocalStorageData(basicEstimates, 'BASIC_GAS_AND_TIME_API_ESTIMATES')
|
||||||
|
saveLocalStorageData(timeRetrieved, 'BASIC_GAS_AND_TIME_API_ESTIMATES_LAST_RETRIEVED')
|
||||||
|
dispatch(setBasicApiEstimatesLastRetrieved(timeRetrieved))
|
||||||
|
|
||||||
|
return basicEstimates
|
||||||
|
}
|
||||||
|
|
||||||
function extrapolateY ({ higherY, lowerY, higherX, lowerX, xForExtrapolation }) {
|
function extrapolateY ({ higherY, lowerY, higherX, lowerX, xForExtrapolation }) {
|
||||||
higherY = new BigNumber(higherY, 10)
|
higherY = new BigNumber(higherY, 10)
|
||||||
lowerY = new BigNumber(lowerY, 10)
|
lowerY = new BigNumber(lowerY, 10)
|
||||||
|
Loading…
Reference in New Issue
Block a user