mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-12-23 09:52:26 +01:00
Use async storage instead of localstorage (#9919)
This commit is contained in:
parent
9f6fa64d67
commit
bf65c979d2
@ -131,6 +131,7 @@
|
||||
"json-rpc-engine": "^5.3.0",
|
||||
"json-rpc-middleware-stream": "^2.1.1",
|
||||
"jsonschema": "^1.2.4",
|
||||
"localforage": "^1.9.0",
|
||||
"lodash": "^4.17.19",
|
||||
"loglevel": "^1.4.1",
|
||||
"luxon": "^1.24.1",
|
||||
|
@ -2,10 +2,10 @@ import assert from 'assert'
|
||||
import sinon from 'sinon'
|
||||
import proxyquire from 'proxyquire'
|
||||
|
||||
const fakeLocalStorage = {}
|
||||
const fakeStorage = {}
|
||||
|
||||
const GasDuck = proxyquire('./gas.duck.js', {
|
||||
'../../../lib/local-storage-helpers': fakeLocalStorage,
|
||||
'../../../lib/storage-helpers': fakeStorage,
|
||||
})
|
||||
|
||||
const {
|
||||
@ -160,8 +160,8 @@ describe('Gas Duck', function () {
|
||||
tempFetch = window.fetch
|
||||
tempDateNow = global.Date.now
|
||||
|
||||
fakeLocalStorage.loadLocalStorageData = sinon.stub()
|
||||
fakeLocalStorage.saveLocalStorageData = sinon.spy()
|
||||
fakeStorage.getStorageItem = sinon.stub()
|
||||
fakeStorage.setStorageItem = sinon.spy()
|
||||
window.fetch = sinon.stub().callsFake(fakeFetch)
|
||||
global.Date.now = () => 2000000
|
||||
})
|
||||
@ -412,14 +412,12 @@ describe('Gas Duck', function () {
|
||||
])
|
||||
})
|
||||
|
||||
it('should fetch recently retrieved estimates from local storage', async function () {
|
||||
it('should fetch recently retrieved estimates from storage', async function () {
|
||||
const mockDistpatch = sinon.spy()
|
||||
fakeLocalStorage.loadLocalStorageData
|
||||
fakeStorage.getStorageItem
|
||||
.withArgs('BASIC_PRICE_ESTIMATES_LAST_RETRIEVED')
|
||||
.returns(2000000 - 1) // one second ago from "now"
|
||||
fakeLocalStorage.loadLocalStorageData
|
||||
.withArgs('BASIC_PRICE_ESTIMATES')
|
||||
.returns({
|
||||
fakeStorage.getStorageItem.withArgs('BASIC_PRICE_ESTIMATES').returns({
|
||||
average: 25,
|
||||
blockTime: 'mockBlock_time',
|
||||
blockNum: 'mockBlockNum',
|
||||
@ -453,9 +451,9 @@ describe('Gas Duck', function () {
|
||||
])
|
||||
})
|
||||
|
||||
it('should fallback to network if retrieving estimates from local storage fails', async function () {
|
||||
it('should fallback to network if retrieving estimates from storage fails', async function () {
|
||||
const mockDistpatch = sinon.spy()
|
||||
fakeLocalStorage.loadLocalStorageData
|
||||
fakeStorage.getStorageItem
|
||||
.withArgs('BASIC_PRICE_ESTIMATES_LAST_RETRIEVED')
|
||||
.returns(2000000 - 1) // one second ago from "now"
|
||||
|
||||
@ -541,12 +539,12 @@ describe('Gas Duck', function () {
|
||||
])
|
||||
})
|
||||
|
||||
it('should fetch recently retrieved estimates from local storage', async function () {
|
||||
it('should fetch recently retrieved estimates from storage', async function () {
|
||||
const mockDistpatch = sinon.spy()
|
||||
fakeLocalStorage.loadLocalStorageData
|
||||
fakeStorage.getStorageItem
|
||||
.withArgs('BASIC_GAS_AND_TIME_API_ESTIMATES_LAST_RETRIEVED')
|
||||
.returns(2000000 - 1) // one second ago from "now"
|
||||
fakeLocalStorage.loadLocalStorageData
|
||||
fakeStorage.getStorageItem
|
||||
.withArgs('BASIC_GAS_AND_TIME_API_ESTIMATES')
|
||||
.returns({
|
||||
average: 5,
|
||||
@ -596,9 +594,9 @@ describe('Gas Duck', function () {
|
||||
])
|
||||
})
|
||||
|
||||
it('should fallback to network if retrieving estimates from local storage fails', async function () {
|
||||
it('should fallback to network if retrieving estimates from storage fails', async function () {
|
||||
const mockDistpatch = sinon.spy()
|
||||
fakeLocalStorage.loadLocalStorageData
|
||||
fakeStorage.getStorageItem
|
||||
.withArgs('BASIC_GAS_AND_TIME_API_ESTIMATES_LAST_RETRIEVED')
|
||||
.returns(2000000 - 1) // one second ago from "now"
|
||||
|
||||
|
@ -1,9 +1,7 @@
|
||||
import { uniqBy, cloneDeep, flatten } from 'lodash'
|
||||
import BigNumber from 'bignumber.js'
|
||||
import {
|
||||
loadLocalStorageData,
|
||||
saveLocalStorageData,
|
||||
} from '../../../lib/local-storage-helpers'
|
||||
import { getStorageItem, setStorageItem } from '../../../lib/storage-helpers'
|
||||
|
||||
import { decGWEIToHexWEI } from '../../helpers/utils/conversions.util'
|
||||
import { isEthereumNetwork } from '../../selectors'
|
||||
|
||||
@ -209,7 +207,7 @@ export function fetchBasicGasEstimates() {
|
||||
const { basicPriceEstimatesLastRetrieved } = getState().gas
|
||||
const timeLastRetrieved =
|
||||
basicPriceEstimatesLastRetrieved ||
|
||||
loadLocalStorageData('BASIC_PRICE_ESTIMATES_LAST_RETRIEVED') ||
|
||||
(await getStorageItem('BASIC_PRICE_ESTIMATES_LAST_RETRIEVED')) ||
|
||||
0
|
||||
|
||||
dispatch(basicGasEstimatesLoadingStarted())
|
||||
@ -218,7 +216,7 @@ export function fetchBasicGasEstimates() {
|
||||
if (Date.now() - timeLastRetrieved > 75000) {
|
||||
basicEstimates = await fetchExternalBasicGasEstimates(dispatch)
|
||||
} else {
|
||||
const cachedBasicEstimates = loadLocalStorageData('BASIC_PRICE_ESTIMATES')
|
||||
const cachedBasicEstimates = await getStorageItem('BASIC_PRICE_ESTIMATES')
|
||||
basicEstimates =
|
||||
cachedBasicEstimates || (await fetchExternalBasicGasEstimates(dispatch))
|
||||
}
|
||||
@ -259,8 +257,10 @@ async function fetchExternalBasicGasEstimates(dispatch) {
|
||||
}
|
||||
|
||||
const timeRetrieved = Date.now()
|
||||
saveLocalStorageData(basicEstimates, 'BASIC_PRICE_ESTIMATES')
|
||||
saveLocalStorageData(timeRetrieved, 'BASIC_PRICE_ESTIMATES_LAST_RETRIEVED')
|
||||
await Promise.all([
|
||||
setStorageItem('BASIC_PRICE_ESTIMATES', basicEstimates),
|
||||
setStorageItem('BASIC_PRICE_ESTIMATES_LAST_RETRIEVED', timeRetrieved),
|
||||
])
|
||||
dispatch(setBasicPriceEstimatesLastRetrieved(timeRetrieved))
|
||||
|
||||
return basicEstimates
|
||||
@ -271,7 +271,9 @@ export function fetchBasicGasAndTimeEstimates() {
|
||||
const { basicPriceAndTimeEstimatesLastRetrieved } = getState().gas
|
||||
const timeLastRetrieved =
|
||||
basicPriceAndTimeEstimatesLastRetrieved ||
|
||||
loadLocalStorageData('BASIC_GAS_AND_TIME_API_ESTIMATES_LAST_RETRIEVED') ||
|
||||
(await getStorageItem(
|
||||
'BASIC_GAS_AND_TIME_API_ESTIMATES_LAST_RETRIEVED',
|
||||
)) ||
|
||||
0
|
||||
|
||||
dispatch(basicGasEstimatesLoadingStarted())
|
||||
@ -280,7 +282,7 @@ export function fetchBasicGasAndTimeEstimates() {
|
||||
if (Date.now() - timeLastRetrieved > 75000) {
|
||||
basicEstimates = await fetchExternalBasicGasAndTimeEstimates(dispatch)
|
||||
} else {
|
||||
const cachedBasicEstimates = loadLocalStorageData(
|
||||
const cachedBasicEstimates = await getStorageItem(
|
||||
'BASIC_GAS_AND_TIME_API_ESTIMATES',
|
||||
)
|
||||
basicEstimates =
|
||||
@ -332,11 +334,13 @@ async function fetchExternalBasicGasAndTimeEstimates(dispatch) {
|
||||
}
|
||||
|
||||
const timeRetrieved = Date.now()
|
||||
saveLocalStorageData(basicEstimates, 'BASIC_GAS_AND_TIME_API_ESTIMATES')
|
||||
saveLocalStorageData(
|
||||
timeRetrieved,
|
||||
await Promise.all([
|
||||
setStorageItem('BASIC_GAS_AND_TIME_API_ESTIMATES', basicEstimates),
|
||||
setStorageItem(
|
||||
'BASIC_GAS_AND_TIME_API_ESTIMATES_LAST_RETRIEVED',
|
||||
)
|
||||
timeRetrieved,
|
||||
),
|
||||
])
|
||||
dispatch(setBasicApiEstimatesLastRetrieved(timeRetrieved))
|
||||
|
||||
return basicEstimates
|
||||
@ -403,11 +407,11 @@ function inliersByIQR(data, prop) {
|
||||
}
|
||||
|
||||
export function fetchGasEstimates(blockTime) {
|
||||
return (dispatch, getState) => {
|
||||
return async (dispatch, getState) => {
|
||||
const state = getState()
|
||||
|
||||
if (!isEthereumNetwork(state)) {
|
||||
return Promise.resolve(null)
|
||||
return
|
||||
}
|
||||
|
||||
const {
|
||||
@ -416,17 +420,18 @@ export function fetchGasEstimates(blockTime) {
|
||||
} = state.gas
|
||||
const timeLastRetrieved =
|
||||
priceAndTimeEstimatesLastRetrieved ||
|
||||
loadLocalStorageData('GAS_API_ESTIMATES_LAST_RETRIEVED') ||
|
||||
(await getStorageItem('GAS_API_ESTIMATES_LAST_RETRIEVED')) ||
|
||||
0
|
||||
|
||||
dispatch(gasEstimatesLoadingStarted())
|
||||
|
||||
const promiseToFetch =
|
||||
Date.now() - timeLastRetrieved > 75000
|
||||
? queryEthGasStationPredictionTable()
|
||||
.then((r) => r.json())
|
||||
.then((r) => {
|
||||
const estimatedPricesAndTimes = r.map(
|
||||
const shouldGetFreshGasQuote = Date.now() - timeLastRetrieved > 75000
|
||||
let estimates
|
||||
if (shouldGetFreshGasQuote) {
|
||||
const response = await queryEthGasStationPredictionTable()
|
||||
const tableJson = await response.json()
|
||||
|
||||
const estimatedPricesAndTimes = tableJson.map(
|
||||
({ expectedTime, expectedWait, gasprice }) => ({
|
||||
expectedTime,
|
||||
expectedWait,
|
||||
@ -499,31 +504,28 @@ export function fetchGasEstimates(blockTime) {
|
||||
|
||||
const timeRetrieved = Date.now()
|
||||
dispatch(setApiEstimatesLastRetrieved(timeRetrieved))
|
||||
saveLocalStorageData(
|
||||
timeRetrieved,
|
||||
'GAS_API_ESTIMATES_LAST_RETRIEVED',
|
||||
)
|
||||
saveLocalStorageData(timeMappedToSeconds, 'GAS_API_ESTIMATES')
|
||||
|
||||
return timeMappedToSeconds
|
||||
})
|
||||
: Promise.resolve(
|
||||
priceAndTimeEstimates.length
|
||||
? priceAndTimeEstimates
|
||||
: loadLocalStorageData('GAS_API_ESTIMATES'),
|
||||
)
|
||||
await Promise.all([
|
||||
setStorageItem('GAS_API_ESTIMATES_LAST_RETRIEVED', timeRetrieved),
|
||||
setStorageItem('GAS_API_ESTIMATES', timeMappedToSeconds),
|
||||
])
|
||||
|
||||
estimates = timeMappedToSeconds
|
||||
} else if (priceAndTimeEstimates.length) {
|
||||
estimates = priceAndTimeEstimates
|
||||
} else {
|
||||
estimates = await getStorageItem('GAS_API_ESTIMATES')
|
||||
}
|
||||
|
||||
return promiseToFetch.then((estimates) => {
|
||||
dispatch(setPricesAndTimeEstimates(estimates))
|
||||
dispatch(gasEstimatesLoadingFinished())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export function setCustomGasPriceForRetry(newPrice) {
|
||||
return (dispatch) => {
|
||||
return async (dispatch) => {
|
||||
if (newPrice === '0x0') {
|
||||
const { fast } = loadLocalStorageData('BASIC_PRICE_ESTIMATES')
|
||||
const { fast } = await getStorageItem('BASIC_PRICE_ESTIMATES')
|
||||
dispatch(setCustomGasPrice(decGWEIToHexWEI(fast)))
|
||||
} else {
|
||||
dispatch(setCustomGasPrice(newPrice))
|
||||
|
@ -2,10 +2,8 @@ import { createSlice } from '@reduxjs/toolkit'
|
||||
import BigNumber from 'bignumber.js'
|
||||
import log from 'loglevel'
|
||||
|
||||
import {
|
||||
loadLocalStorageData,
|
||||
saveLocalStorageData,
|
||||
} from '../../../lib/local-storage-helpers'
|
||||
import { getStorageItem, setStorageItem } from '../../../lib/storage-helpers'
|
||||
|
||||
import {
|
||||
addToken,
|
||||
addUnapprovedTransaction,
|
||||
@ -754,7 +752,7 @@ export function fetchMetaSwapsGasPriceEstimates() {
|
||||
)
|
||||
const timeLastRetrieved =
|
||||
priceEstimatesLastRetrieved ||
|
||||
loadLocalStorageData('METASWAP_GAS_PRICE_ESTIMATES_LAST_RETRIEVED') ||
|
||||
(await getStorageItem('METASWAP_GAS_PRICE_ESTIMATES_LAST_RETRIEVED')) ||
|
||||
0
|
||||
|
||||
dispatch(swapGasPriceEstimatesFetchStarted())
|
||||
@ -764,7 +762,7 @@ export function fetchMetaSwapsGasPriceEstimates() {
|
||||
if (Date.now() - timeLastRetrieved > 30000) {
|
||||
priceEstimates = await fetchSwapsGasPrices()
|
||||
} else {
|
||||
const cachedPriceEstimates = loadLocalStorageData(
|
||||
const cachedPriceEstimates = await getStorageItem(
|
||||
'METASWAP_GAS_PRICE_ESTIMATES',
|
||||
)
|
||||
priceEstimates = cachedPriceEstimates || (await fetchSwapsGasPrices())
|
||||
@ -795,11 +793,13 @@ export function fetchMetaSwapsGasPriceEstimates() {
|
||||
|
||||
const timeRetrieved = Date.now()
|
||||
|
||||
saveLocalStorageData(priceEstimates, 'METASWAP_GAS_PRICE_ESTIMATES')
|
||||
saveLocalStorageData(
|
||||
timeRetrieved,
|
||||
await Promise.all([
|
||||
setStorageItem('METASWAP_GAS_PRICE_ESTIMATES', priceEstimates),
|
||||
setStorageItem(
|
||||
'METASWAP_GAS_PRICE_ESTIMATES_LAST_RETRIEVED',
|
||||
)
|
||||
timeRetrieved,
|
||||
),
|
||||
])
|
||||
|
||||
dispatch(
|
||||
swapGasPriceEstimatesFetchCompleted({
|
||||
|
@ -1,7 +1,4 @@
|
||||
import {
|
||||
loadLocalStorageData,
|
||||
saveLocalStorageData,
|
||||
} from '../../../lib/local-storage-helpers'
|
||||
import { getStorageItem, setStorageItem } from '../../../lib/storage-helpers'
|
||||
import fetchWithTimeout from '../../../../app/scripts/lib/fetch-with-timeout'
|
||||
|
||||
const fetchWithCache = async (
|
||||
@ -27,7 +24,7 @@ const fetchWithCache = async (
|
||||
}
|
||||
|
||||
const currentTime = Date.now()
|
||||
const cachedFetch = loadLocalStorageData('cachedFetch') || {}
|
||||
const cachedFetch = (await getStorageItem('cachedFetch')) || {}
|
||||
const { cachedResponse, cachedTime } = cachedFetch[url] || {}
|
||||
if (cachedResponse && currentTime - cachedTime < cacheRefreshTime) {
|
||||
return cachedResponse
|
||||
@ -52,7 +49,7 @@ const fetchWithCache = async (
|
||||
cachedTime: currentTime,
|
||||
}
|
||||
cachedFetch[url] = cacheEntry
|
||||
saveLocalStorageData(cachedFetch, 'cachedFetch')
|
||||
await setStorageItem('cachedFetch', cachedFetch)
|
||||
return responseJson
|
||||
}
|
||||
|
||||
|
@ -3,15 +3,15 @@ import nock from 'nock'
|
||||
import sinon from 'sinon'
|
||||
import proxyquire from 'proxyquire'
|
||||
|
||||
const fakeLocalStorageHelpers = {}
|
||||
const fakeStorage = {}
|
||||
const fetchWithCache = proxyquire('./fetch-with-cache', {
|
||||
'../../../lib/local-storage-helpers': fakeLocalStorageHelpers,
|
||||
'../../../lib/storage-helpers': fakeStorage,
|
||||
}).default
|
||||
|
||||
describe('Fetch with cache', function () {
|
||||
beforeEach(function () {
|
||||
fakeLocalStorageHelpers.loadLocalStorageData = sinon.stub()
|
||||
fakeLocalStorageHelpers.saveLocalStorageData = sinon.stub()
|
||||
fakeStorage.getStorageItem = sinon.stub()
|
||||
fakeStorage.setStorageItem = sinon.stub()
|
||||
})
|
||||
afterEach(function () {
|
||||
sinon.restore()
|
||||
@ -36,7 +36,7 @@ describe('Fetch with cache', function () {
|
||||
.get('/price')
|
||||
.reply(200, '{"average": 2}')
|
||||
|
||||
fakeLocalStorageHelpers.loadLocalStorageData.returns({
|
||||
fakeStorage.getStorageItem.returns({
|
||||
'https://fetchwithcache.metamask.io/price': {
|
||||
cachedResponse: { average: 1 },
|
||||
cachedTime: Date.now(),
|
||||
@ -56,7 +56,7 @@ describe('Fetch with cache', function () {
|
||||
.get('/price')
|
||||
.reply(200, '{"average": 3}')
|
||||
|
||||
fakeLocalStorageHelpers.loadLocalStorageData.returns({
|
||||
fakeStorage.getStorageItem.returns({
|
||||
'https://fetchwithcache.metamask.io/cached': {
|
||||
cachedResponse: { average: 1 },
|
||||
cachedTime: Date.now() - 1000,
|
||||
|
@ -38,7 +38,7 @@ export function useRetryTransaction(transactionGroup) {
|
||||
await dispatch(fetchGasEstimates(basicEstimates.blockTime))
|
||||
const transaction = initialTransaction
|
||||
const increasedGasPrice = increaseLastGasPrice(gasPrice)
|
||||
dispatch(
|
||||
await dispatch(
|
||||
setCustomGasPriceForRetry(
|
||||
increasedGasPrice || transaction.txParams.gasPrice,
|
||||
),
|
||||
|
@ -1,20 +0,0 @@
|
||||
export function loadLocalStorageData(itemKey) {
|
||||
try {
|
||||
const serializedData = window.localStorage.getItem(itemKey)
|
||||
if (serializedData === null) {
|
||||
return undefined
|
||||
}
|
||||
return JSON.parse(serializedData)
|
||||
} catch (err) {
|
||||
return undefined
|
||||
}
|
||||
}
|
||||
|
||||
export function saveLocalStorageData(data, itemKey) {
|
||||
try {
|
||||
const serializedData = JSON.stringify(data)
|
||||
window.localStorage.setItem(itemKey, serializedData)
|
||||
} catch (err) {
|
||||
console.warn(err)
|
||||
}
|
||||
}
|
23
ui/lib/storage-helpers.js
Normal file
23
ui/lib/storage-helpers.js
Normal file
@ -0,0 +1,23 @@
|
||||
import localforage from 'localforage'
|
||||
|
||||
export async function getStorageItem(key) {
|
||||
try {
|
||||
const serializedData = await localforage.getItem(key)
|
||||
if (serializedData === null) {
|
||||
return undefined
|
||||
}
|
||||
|
||||
return JSON.parse(serializedData)
|
||||
} catch (err) {
|
||||
return undefined
|
||||
}
|
||||
}
|
||||
|
||||
export async function setStorageItem(key, value) {
|
||||
try {
|
||||
const serializedData = JSON.stringify(value)
|
||||
await localforage.setItem(key, serializedData)
|
||||
} catch (err) {
|
||||
console.warn(err)
|
||||
}
|
||||
}
|
@ -16608,6 +16608,13 @@ localforage@1.8.1:
|
||||
dependencies:
|
||||
lie "3.1.1"
|
||||
|
||||
localforage@^1.9.0:
|
||||
version "1.9.0"
|
||||
resolved "https://registry.yarnpkg.com/localforage/-/localforage-1.9.0.tgz#f3e4d32a8300b362b4634cc4e066d9d00d2f09d1"
|
||||
integrity sha512-rR1oyNrKulpe+VM9cYmcFn6tsHuokyVHFaCM3+osEmxaHTbEk8oQu6eGDfS6DQLWi/N67XRmB8ECG37OES368g==
|
||||
dependencies:
|
||||
lie "3.1.1"
|
||||
|
||||
localstorage-down@^0.6.7:
|
||||
version "0.6.7"
|
||||
resolved "https://registry.yarnpkg.com/localstorage-down/-/localstorage-down-0.6.7.tgz#d0799a93b31e6c5fa5188ec06242eb1cce9d6d15"
|
||||
|
Loading…
Reference in New Issue
Block a user