1
0
mirror of https://github.com/kremalicious/metamask-extension.git synced 2024-12-23 09:52:26 +01:00

Uses more reliable api on main send screen; caches basic api results in modal

This commit is contained in:
Dan Miller 2018-11-13 13:06:52 -03:30
parent fe535159bb
commit 7f2c5c09de
21 changed files with 311 additions and 142 deletions

File diff suppressed because one or more lines are too long

View File

@ -74,7 +74,9 @@ describe('MetaMask', function () {
'if (args[0] === "https://ethgasstation.info/json/ethgasAPI.json") { return ' + 'if (args[0] === "https://ethgasstation.info/json/ethgasAPI.json") { return ' +
'Promise.resolve({ json: () => Promise.resolve(JSON.parse(\'' + fetchMockResponses.ethGasBasic + '\')) }); } else if ' + 'Promise.resolve({ json: () => Promise.resolve(JSON.parse(\'' + fetchMockResponses.ethGasBasic + '\')) }); } else if ' +
'(args[0] === "https://ethgasstation.info/json/predictTable.json") { return ' + '(args[0] === "https://ethgasstation.info/json/predictTable.json") { return ' +
'Promise.resolve({ json: () => Promise.resolve(JSON.parse(\'' + fetchMockResponses.ethGasPredictTable + '\')) }); } ' + 'Promise.resolve({ json: () => Promise.resolve(JSON.parse(\'' + fetchMockResponses.ethGasPredictTable + '\')) }); } else if ' +
'(args[0] === "https://dev.blockscale.net/api/gasexpress.json") { return ' +
'Promise.resolve({ json: () => Promise.resolve(JSON.parse(\'' + fetchMockResponses.gasExpress + '\')) }); } ' +
'return window.fetch(...args); }' 'return window.fetch(...args); }'
) )
}) })

View File

@ -12,10 +12,13 @@ export default class GasModalPageContainer extends Component {
static propTypes = { static propTypes = {
hideModal: PropTypes.func, hideModal: PropTypes.func,
hideBasic: PropTypes.bool,
updateCustomGasPrice: PropTypes.func, updateCustomGasPrice: PropTypes.func,
updateCustomGasLimit: PropTypes.func, updateCustomGasLimit: PropTypes.func,
customGasPrice: PropTypes.number, customGasPrice: PropTypes.number,
customGasLimit: PropTypes.number, customGasLimit: PropTypes.number,
fetchBasicGasAndTimeEstimates: PropTypes.func,
fetchGasEstimates: PropTypes.func,
gasPriceButtonGroupProps: PropTypes.object, gasPriceButtonGroupProps: PropTypes.object,
infoRowProps: PropTypes.shape({ infoRowProps: PropTypes.shape({
originalTotalFiat: PropTypes.string, originalTotalFiat: PropTypes.string,
@ -28,10 +31,26 @@ export default class GasModalPageContainer extends Component {
customModalGasLimitInHex: PropTypes.string, customModalGasLimitInHex: PropTypes.string,
cancelAndClose: PropTypes.func, cancelAndClose: PropTypes.func,
transactionFee: PropTypes.string, transactionFee: PropTypes.string,
blockTime: PropTypes.oneOfType([
PropTypes.string,
PropTypes.number,
]),
} }
state = {} state = {}
componentDidMount () {
const promise = this.props.hideBasic
? Promise.resolve(this.props.blockTime)
: this.props.fetchBasicGasAndTimeEstimates()
.then(basicEstimates => basicEstimates.blockTime)
promise
.then(blockTime => {
this.props.fetchGasEstimates(blockTime)
})
}
renderBasicTabContent (gasPriceButtonGroupProps) { renderBasicTabContent (gasPriceButtonGroupProps) {
return ( return (
<BasicTabContent <BasicTabContent

View File

@ -13,6 +13,8 @@ import {
setCustomGasLimit, setCustomGasLimit,
resetCustomData, resetCustomData,
setCustomTimeEstimate, setCustomTimeEstimate,
fetchGasEstimates,
fetchBasicGasAndTimeEstimates,
} from '../../../ducks/gas.duck' } from '../../../ducks/gas.duck'
import { import {
hideGasButtonGroup, hideGasButtonGroup,
@ -28,7 +30,7 @@ import {
} from '../../../selectors.js' } from '../../../selectors.js'
import { import {
formatTimeEstimate, formatTimeEstimate,
getAveragePriceEstimateInHexWEI, getFastPriceEstimateInHexWEI,
getBasicGasEstimateLoadingStatus, getBasicGasEstimateLoadingStatus,
getCustomGasLimit, getCustomGasLimit,
getCustomGasPrice, getCustomGasPrice,
@ -36,6 +38,7 @@ import {
getEstimatedGasPrices, getEstimatedGasPrices,
getEstimatedGasTimes, getEstimatedGasTimes,
getRenderableBasicEstimateData, getRenderableBasicEstimateData,
getBasicGasEstimateBlockTime,
} from '../../../selectors/custom-gas' } from '../../../selectors/custom-gas'
import { import {
submittedPendingTransactionsSelector, submittedPendingTransactionsSelector,
@ -100,6 +103,7 @@ const mapStateToProps = (state, ownProps) => {
customGasLimit: calcCustomGasLimit(customModalGasLimitInHex), customGasLimit: calcCustomGasLimit(customModalGasLimitInHex),
newTotalFiat, newTotalFiat,
currentTimeEstimate: getRenderableTimeEstimate(customGasPrice, gasPrices, estimatedTimes), currentTimeEstimate: getRenderableTimeEstimate(customGasPrice, gasPrices, estimatedTimes),
blockTime: getBasicGasEstimateBlockTime(state),
gasPriceButtonGroupProps: { gasPriceButtonGroupProps: {
buttonDataLoading, buttonDataLoading,
defaultActiveButtonIndex: getDefaultActiveButtonIndex(gasButtonInfo, customModalGasPriceInHex), defaultActiveButtonIndex: getDefaultActiveButtonIndex(gasButtonInfo, customModalGasPriceInHex),
@ -150,6 +154,8 @@ const mapDispatchToProps = dispatch => {
hideGasButtonGroup: () => dispatch(hideGasButtonGroup()), hideGasButtonGroup: () => dispatch(hideGasButtonGroup()),
setCustomTimeEstimate: (timeEstimateInSeconds) => dispatch(setCustomTimeEstimate(timeEstimateInSeconds)), setCustomTimeEstimate: (timeEstimateInSeconds) => dispatch(setCustomTimeEstimate(timeEstimateInSeconds)),
hideSidebar: () => dispatch(hideSidebar()), hideSidebar: () => dispatch(hideSidebar()),
fetchGasEstimates: (blockTime) => dispatch(fetchGasEstimates(blockTime)),
fetchBasicGasAndTimeEstimates: () => dispatch(fetchBasicGasAndTimeEstimates()),
} }
} }
@ -209,7 +215,7 @@ function getTxParams (state, transactionId) {
return txData.txParams || pendingTxParams || { return txData.txParams || pendingTxParams || {
from: send.from, from: send.from,
gas: send.gasLimit, gas: send.gasLimit,
gasPrice: send.gasPrice || getAveragePriceEstimateInHexWEI(state), gasPrice: send.gasPrice || getFastPriceEstimateInHexWEI(state, true),
to: send.to, to: send.to,
value: getSelectedToken(state) ? '0x0' : send.amount, value: getSelectedToken(state) ? '0x0' : send.amount,
} }

View File

@ -3,14 +3,21 @@ import assert from 'assert'
import shallow from '../../../../../lib/shallow-with-context' import shallow from '../../../../../lib/shallow-with-context'
import sinon from 'sinon' import sinon from 'sinon'
import GasModalPageContainer from '../gas-modal-page-container.component.js' import GasModalPageContainer from '../gas-modal-page-container.component.js'
import timeout from '../../../../../lib/test-timeout'
import PageContainer from '../../../page-container' import PageContainer from '../../../page-container'
import { Tab } from '../../../tabs' import { Tab } from '../../../tabs'
const mockBasicGasEstimates = {
blockTime: 'mockBlockTime',
}
const propsMethodSpies = { const propsMethodSpies = {
cancelAndClose: sinon.spy(), cancelAndClose: sinon.spy(),
onSubmit: sinon.spy(), onSubmit: sinon.spy(),
fetchBasicGasAndTimeEstimates: sinon.stub().returns(Promise.resolve(mockBasicGasEstimates)),
fetchGasEstimates: sinon.spy(),
} }
const mockGasPriceButtonGroupProps = { const mockGasPriceButtonGroupProps = {
@ -59,6 +66,8 @@ describe('GasModalPageContainer Component', function () {
wrapper = shallow(<GasModalPageContainer wrapper = shallow(<GasModalPageContainer
cancelAndClose={propsMethodSpies.cancelAndClose} cancelAndClose={propsMethodSpies.cancelAndClose}
onSubmit={propsMethodSpies.onSubmit} onSubmit={propsMethodSpies.onSubmit}
fetchBasicGasAndTimeEstimates={propsMethodSpies.fetchBasicGasAndTimeEstimates}
fetchGasEstimates={propsMethodSpies.fetchGasEstimates}
updateCustomGasPrice={() => 'mockupdateCustomGasPrice'} updateCustomGasPrice={() => 'mockupdateCustomGasPrice'}
updateCustomGasLimit={() => 'mockupdateCustomGasLimit'} updateCustomGasLimit={() => 'mockupdateCustomGasLimit'}
customGasPrice={21} customGasPrice={21}
@ -76,6 +85,24 @@ describe('GasModalPageContainer Component', function () {
propsMethodSpies.cancelAndClose.resetHistory() propsMethodSpies.cancelAndClose.resetHistory()
}) })
describe('componentDidMount', () => {
it('should call props.fetchBasicGasAndTimeEstimates', () => {
propsMethodSpies.fetchBasicGasAndTimeEstimates.resetHistory()
assert.equal(propsMethodSpies.fetchBasicGasAndTimeEstimates.callCount, 0)
wrapper.instance().componentDidMount()
assert.equal(propsMethodSpies.fetchBasicGasAndTimeEstimates.callCount, 1)
})
it('should call props.fetchGasEstimates with the block time returned by fetchBasicGasAndTimeEstimates', async () => {
propsMethodSpies.fetchGasEstimates.resetHistory()
assert.equal(propsMethodSpies.fetchGasEstimates.callCount, 0)
wrapper.instance().componentDidMount()
await timeout(250)
assert.equal(propsMethodSpies.fetchGasEstimates.callCount, 1)
assert.equal(propsMethodSpies.fetchGasEstimates.getCall(0).args[0], 'mockBlockTime')
})
})
describe('render', () => { describe('render', () => {
it('should render a PageContainer compenent', () => { it('should render a PageContainer compenent', () => {
assert.equal(wrapper.find(PageContainer).length, 1) assert.equal(wrapper.find(PageContainer).length, 1)
@ -106,7 +133,10 @@ describe('GasModalPageContainer Component', function () {
it('should pass the correct renderTabs property to PageContainer', () => { it('should pass the correct renderTabs property to PageContainer', () => {
sinon.stub(GP, 'renderTabs').returns('mockTabs') sinon.stub(GP, 'renderTabs').returns('mockTabs')
const renderTabsWrapperTester = shallow(<GasModalPageContainer />, { context: { t: (str1, str2) => str2 ? str1 + str2 : str1 } }) const renderTabsWrapperTester = shallow(<GasModalPageContainer
fetchBasicGasAndTimeEstimates={propsMethodSpies.fetchBasicGasAndTimeEstimates}
fetchGasEstimates={propsMethodSpies.fetchGasEstimates}
/>, { context: { t: (str1, str2) => str2 ? str1 + str2 : str1 } })
const { tabsComponent } = renderTabsWrapperTester.find(PageContainer).props() const { tabsComponent } = renderTabsWrapperTester.find(PageContainer).props()
assert.equal(tabsComponent, 'mockTabs') assert.equal(tabsComponent, 'mockTabs')
GasModalPageContainer.prototype.renderTabs.restore() GasModalPageContainer.prototype.renderTabs.restore()

View File

@ -73,6 +73,9 @@ describe('gas-modal-page-container container', () => {
conversionRate: 50, conversionRate: 50,
}, },
gas: { gas: {
basicEstimates: {
blockTime: 12,
},
customData: { customData: {
limit: 'aaaaaaaa', limit: 'aaaaaaaa',
price: 'ffffffff', price: 'ffffffff',
@ -100,6 +103,7 @@ describe('gas-modal-page-container container', () => {
customGasLimit: 2863311530, customGasLimit: 2863311530,
currentTimeEstimate: '~1 min 11 sec', currentTimeEstimate: '~1 min 11 sec',
newTotalFiat: '637.41', newTotalFiat: '637.41',
blockTime: 12,
customModalGasLimitInHex: 'aaaaaaaa', customModalGasLimitInHex: 'aaaaaaaa',
customModalGasPriceInHex: 'ffffffff', customModalGasPriceInHex: 'ffffffff',
gasChartProps: { gasChartProps: {

View File

@ -32,7 +32,7 @@ export default class ConfirmTransaction extends Component {
setTransactionToConfirm: PropTypes.func, setTransactionToConfirm: PropTypes.func,
confirmTransaction: PropTypes.object, confirmTransaction: PropTypes.object,
clearConfirmTransaction: PropTypes.func, clearConfirmTransaction: PropTypes.func,
fetchBasicGasEstimates: PropTypes.func, fetchBasicGasAndTimeEstimates: PropTypes.func,
} }
getParamsTransactionId () { getParamsTransactionId () {
@ -46,7 +46,7 @@ export default class ConfirmTransaction extends Component {
send = {}, send = {},
history, history,
confirmTransaction: { txData: { id: transactionId } = {} }, confirmTransaction: { txData: { id: transactionId } = {} },
fetchBasicGasEstimates, fetchBasicGasAndTimeEstimates,
} = this.props } = this.props
if (!totalUnapprovedCount && !send.to) { if (!totalUnapprovedCount && !send.to) {
@ -55,7 +55,7 @@ export default class ConfirmTransaction extends Component {
} }
if (!transactionId) { if (!transactionId) {
fetchBasicGasEstimates() fetchBasicGasAndTimeEstimates()
this.setTransactionToConfirm() this.setTransactionToConfirm()
} }
} }

View File

@ -6,7 +6,7 @@ import {
clearConfirmTransaction, clearConfirmTransaction,
} from '../../../ducks/confirm-transaction.duck' } from '../../../ducks/confirm-transaction.duck'
import { import {
fetchBasicGasEstimates, fetchBasicGasAndTimeEstimates,
} from '../../../ducks/gas.duck' } from '../../../ducks/gas.duck'
import ConfirmTransaction from './confirm-transaction.component' import ConfirmTransaction from './confirm-transaction.component'
import { getTotalUnapprovedCount } from '../../../selectors' import { getTotalUnapprovedCount } from '../../../selectors'
@ -27,7 +27,7 @@ const mapDispatchToProps = dispatch => {
return { return {
setTransactionToConfirm: transactionId => dispatch(setTransactionToConfirm(transactionId)), setTransactionToConfirm: transactionId => dispatch(setTransactionToConfirm(transactionId)),
clearConfirmTransaction: () => dispatch(clearConfirmTransaction()), clearConfirmTransaction: () => dispatch(clearConfirmTransaction()),
fetchBasicGasEstimates: () => dispatch(fetchBasicGasEstimates()), fetchBasicGasAndTimeEstimates: () => dispatch(fetchBasicGasAndTimeEstimates()),
} }
} }

View File

@ -7,7 +7,7 @@ import {
} from '../../send.selectors.js' } from '../../send.selectors.js'
import { import {
getBasicGasEstimateLoadingStatus, getBasicGasEstimateLoadingStatus,
getRenderableEstimateDataForSmallButtons, getRenderableEstimateDataForSmallButtonsFromGWEI,
getDefaultActiveButtonIndex, getDefaultActiveButtonIndex,
} from '../../../../selectors/custom-gas' } from '../../../../selectors/custom-gas'
import { import {
@ -23,7 +23,7 @@ import SendGasRow from './send-gas-row.component'
export default connect(mapStateToProps, mapDispatchToProps, mergeProps)(SendGasRow) export default connect(mapStateToProps, mapDispatchToProps, mergeProps)(SendGasRow)
function mapStateToProps (state) { function mapStateToProps (state) {
const gasButtonInfo = getRenderableEstimateDataForSmallButtons(state) const gasButtonInfo = getRenderableEstimateDataForSmallButtonsFromGWEI(state)
const activeButtonIndex = getDefaultActiveButtonIndex(gasButtonInfo, getGasPrice(state)) const activeButtonIndex = getDefaultActiveButtonIndex(gasButtonInfo, getGasPrice(state))
return { return {

View File

@ -42,7 +42,7 @@ proxyquire('../send-gas-row.container.js', {
'../../../../actions': actionSpies, '../../../../actions': actionSpies,
'../../../../selectors/custom-gas': { '../../../../selectors/custom-gas': {
getBasicGasEstimateLoadingStatus: (s) => `mockBasicGasEstimateLoadingStatus:${s}`, getBasicGasEstimateLoadingStatus: (s) => `mockBasicGasEstimateLoadingStatus:${s}`,
getRenderableEstimateDataForSmallButtons: (s) => `mockGasButtonInfo:${s}`, getRenderableEstimateDataForSmallButtonsFromGWEI: (s) => `mockGasButtonInfo:${s}`,
getDefaultActiveButtonIndex: (gasButtonInfo, gasPrice) => gasButtonInfo.length + gasPrice.length, getDefaultActiveButtonIndex: (gasButtonInfo, gasPrice) => gasButtonInfo.length + gasPrice.length,
}, },
'../../../../ducks/send.duck': sendDuckSpies, '../../../../ducks/send.duck': sendDuckSpies,

View File

@ -35,6 +35,7 @@ export default class SendTransactionScreen extends PersistentForm {
selectedToken: PropTypes.object, selectedToken: PropTypes.object,
tokenBalance: PropTypes.string, tokenBalance: PropTypes.string,
tokenContract: PropTypes.object, tokenContract: PropTypes.object,
fetchBasicGasEstimates: PropTypes.func,
updateAndSetGasTotal: PropTypes.func, updateAndSetGasTotal: PropTypes.func,
updateSendErrors: PropTypes.func, updateSendErrors: PropTypes.func,
updateSendTokenBalance: PropTypes.func, updateSendTokenBalance: PropTypes.func,
@ -164,9 +165,8 @@ export default class SendTransactionScreen extends PersistentForm {
componentDidMount () { componentDidMount () {
this.props.fetchBasicGasEstimates() this.props.fetchBasicGasEstimates()
.then(basicEstimates => { .then(() => {
this.updateGas() this.updateGas()
this.props.fetchGasEstimates(basicEstimates.blockTime)
}) })
} }

View File

@ -38,7 +38,6 @@ import {
} from '../../ducks/send.duck' } from '../../ducks/send.duck'
import { import {
fetchBasicGasEstimates, fetchBasicGasEstimates,
fetchGasEstimates,
} from '../../ducks/gas.duck' } from '../../ducks/gas.duck'
import { import {
calcGasTotal, calcGasTotal,
@ -109,6 +108,5 @@ function mapDispatchToProps (dispatch) {
qrCodeDetected: (data) => dispatch(qrCodeDetected(data)), qrCodeDetected: (data) => dispatch(qrCodeDetected(data)),
updateSendTo: (to, nickname) => dispatch(updateSendTo(to, nickname)), updateSendTo: (to, nickname) => dispatch(updateSendTo(to, nickname)),
fetchBasicGasEstimates: () => dispatch(fetchBasicGasEstimates()), fetchBasicGasEstimates: () => dispatch(fetchBasicGasEstimates()),
fetchGasEstimates: (blockTime) => dispatch(fetchGasEstimates(blockTime)),
} }
} }

View File

@ -11,7 +11,7 @@ const {
calcGasTotal, calcGasTotal,
} = require('./send.utils') } = require('./send.utils')
import { import {
getAveragePriceEstimateInHexWEI, getFastPriceEstimateInHexWEI,
} from '../../selectors/custom-gas' } from '../../selectors/custom-gas'
const selectors = { const selectors = {
@ -139,7 +139,7 @@ function getGasLimit (state) {
} }
function getGasPrice (state) { function getGasPrice (state) {
return state.metamask.send.gasPrice || getAveragePriceEstimateInHexWEI(state) return state.metamask.send.gasPrice || getFastPriceEstimateInHexWEI(state)
} }
function getGasPriceFromRecentBlocks (state) { function getGasPriceFromRecentBlocks (state) {

View File

@ -3,17 +3,12 @@ import assert from 'assert'
import proxyquire from 'proxyquire' import proxyquire from 'proxyquire'
import { shallow } from 'enzyme' import { shallow } from 'enzyme'
import sinon from 'sinon' import sinon from 'sinon'
import timeout from '../../../../lib/test-timeout'
import SendHeader from '../send-header/send-header.container' import SendHeader from '../send-header/send-header.container'
import SendContent from '../send-content/send-content.component' import SendContent from '../send-content/send-content.component'
import SendFooter from '../send-footer/send-footer.container' import SendFooter from '../send-footer/send-footer.container'
function timeout (time) {
return new Promise((resolve, reject) => {
setTimeout(resolve, time || 1500)
})
}
const mockBasicGasEstimates = { const mockBasicGasEstimates = {
blockTime: 'mockBlockTime', blockTime: 'mockBlockTime',
} }
@ -88,7 +83,7 @@ describe('Send Component', function () {
}) })
describe('componentDidMount', () => { describe('componentDidMount', () => {
it('should call props.fetchBasicGasEstimates', () => { it('should call props.fetchBasicGasAndTimeEstimates', () => {
propsMethodSpies.fetchBasicGasEstimates.resetHistory() propsMethodSpies.fetchBasicGasEstimates.resetHistory()
assert.equal(propsMethodSpies.fetchBasicGasEstimates.callCount, 0) assert.equal(propsMethodSpies.fetchBasicGasEstimates.callCount, 0)
wrapper.instance().componentDidMount() wrapper.instance().componentDidMount()
@ -103,15 +98,6 @@ describe('Send Component', function () {
await timeout(250) await timeout(250)
assert.equal(SendTransactionScreen.prototype.updateGas.callCount, 1) assert.equal(SendTransactionScreen.prototype.updateGas.callCount, 1)
}) })
it('should call props.fetchGasEstimates with the block time returned by fetchBasicGasEstimates', async () => {
propsMethodSpies.fetchGasEstimates.resetHistory()
assert.equal(propsMethodSpies.fetchGasEstimates.callCount, 0)
wrapper.instance().componentDidMount()
await timeout(250)
assert.equal(propsMethodSpies.fetchGasEstimates.callCount, 1)
assert.equal(propsMethodSpies.fetchGasEstimates.getCall(0).args[0], 'mockBlockTime')
})
}) })
describe('componentWillUnmount', () => { describe('componentWillUnmount', () => {

View File

@ -27,7 +27,7 @@ export default class TransactionListItem extends PureComponent {
tokenData: PropTypes.object, tokenData: PropTypes.object,
transaction: PropTypes.object, transaction: PropTypes.object,
value: PropTypes.string, value: PropTypes.string,
fetchBasicGasEstimates: PropTypes.func, fetchBasicGasAndTimeEstimates: PropTypes.func,
fetchGasEstimates: PropTypes.func, fetchGasEstimates: PropTypes.func,
} }
@ -71,8 +71,8 @@ export default class TransactionListItem extends PureComponent {
} }
resubmit () { resubmit () {
const { transaction, retryTransaction, fetchBasicGasEstimates, fetchGasEstimates } = this.props const { transaction, retryTransaction, fetchBasicGasAndTimeEstimates, fetchGasEstimates } = this.props
fetchBasicGasEstimates().then(basicEstimates => { fetchBasicGasAndTimeEstimates().then(basicEstimates => {
fetchGasEstimates(basicEstimates.blockTime) fetchGasEstimates(basicEstimates.blockTime)
}).then(() => { }).then(() => {
retryTransaction(transaction) retryTransaction(transaction)

View File

@ -8,7 +8,7 @@ import { hexToDecimal } from '../../helpers/conversions.util'
import { getTokenData } from '../../helpers/transactions.util' import { getTokenData } from '../../helpers/transactions.util'
import { formatDate } from '../../util' import { formatDate } from '../../util'
import { import {
fetchBasicGasEstimates, fetchBasicGasAndTimeEstimates,
fetchGasEstimates, fetchGasEstimates,
setCustomGasPrice, setCustomGasPrice,
setCustomGasLimit, setCustomGasLimit,
@ -29,7 +29,7 @@ const mapStateToProps = (state, ownProps) => {
const mapDispatchToProps = dispatch => { const mapDispatchToProps = dispatch => {
return { return {
fetchBasicGasEstimates: () => dispatch(fetchBasicGasEstimates()), fetchBasicGasAndTimeEstimates: () => dispatch(fetchBasicGasAndTimeEstimates()),
fetchGasEstimates: (blockTime) => dispatch(fetchGasEstimates(blockTime)), fetchGasEstimates: (blockTime) => dispatch(fetchGasEstimates(blockTime)),
setSelectedToken: tokenAddress => dispatch(setSelectedToken(tokenAddress)), setSelectedToken: tokenAddress => dispatch(setSelectedToken(tokenAddress)),
retryTransaction: (transaction) => { retryTransaction: (transaction) => {

View File

@ -19,6 +19,7 @@ const SET_CUSTOM_GAS_PRICE = 'metamask/gas/SET_CUSTOM_GAS_PRICE'
const SET_CUSTOM_GAS_TOTAL = 'metamask/gas/SET_CUSTOM_GAS_TOTAL' const SET_CUSTOM_GAS_TOTAL = 'metamask/gas/SET_CUSTOM_GAS_TOTAL'
const SET_PRICE_AND_TIME_ESTIMATES = 'metamask/gas/SET_PRICE_AND_TIME_ESTIMATES' const SET_PRICE_AND_TIME_ESTIMATES = 'metamask/gas/SET_PRICE_AND_TIME_ESTIMATES'
const SET_API_ESTIMATES_LAST_RETRIEVED = 'metamask/gas/SET_API_ESTIMATES_LAST_RETRIEVED' const SET_API_ESTIMATES_LAST_RETRIEVED = 'metamask/gas/SET_API_ESTIMATES_LAST_RETRIEVED'
const SET_BASIC_API_ESTIMATES_LAST_RETRIEVED = 'metamask/gas/SET_BASIC_API_ESTIMATES_LAST_RETRIEVED'
// TODO: determine if this approach to initState is consistent with conventional ducks pattern // TODO: determine if this approach to initState is consistent with conventional ducks pattern
const initState = { const initState = {
@ -42,7 +43,9 @@ const initState = {
basicEstimateIsLoading: true, basicEstimateIsLoading: true,
gasEstimatesLoading: true, gasEstimatesLoading: true,
priceAndTimeEstimates: [], priceAndTimeEstimates: [],
basicPriceAndTimeEstimates: [],
priceAndTimeEstimatesLastRetrieved: 0, priceAndTimeEstimatesLastRetrieved: 0,
basicPriceAndTimeEstimatesLastRetrieved: 0,
errors: {}, errors: {},
} }
@ -118,6 +121,11 @@ export default function reducer ({ gas: gasState = initState }, action = {}) {
...newState, ...newState,
priceAndTimeEstimatesLastRetrieved: action.value, priceAndTimeEstimatesLastRetrieved: action.value,
} }
case SET_BASIC_API_ESTIMATES_LAST_RETRIEVED:
return {
...newState,
basicPriceAndTimeEstimatesLastRetrieved: action.value,
}
case RESET_CUSTOM_DATA: case RESET_CUSTOM_DATA:
return { return {
...newState, ...newState,
@ -159,9 +167,9 @@ export function fetchBasicGasEstimates () {
return (dispatch) => { return (dispatch) => {
dispatch(basicGasEstimatesLoadingStarted()) dispatch(basicGasEstimatesLoadingStarted())
return fetch('https://ethgasstation.info/json/ethgasAPI.json', { return fetch('https://dev.blockscale.net/api/gasexpress.json', {
'headers': {}, 'headers': {},
'referrer': 'http://ethgasstation.info/json/', 'referrer': 'https://dev.blockscale.net/api/',
'referrerPolicy': 'no-referrer-when-downgrade', 'referrerPolicy': 'no-referrer-when-downgrade',
'body': null, 'body': null,
'method': 'GET', 'method': 'GET',
@ -169,22 +177,52 @@ export function fetchBasicGasEstimates () {
) )
.then(r => r.json()) .then(r => r.json())
.then(({ .then(({
average, safeLow,
avgWait, standard: average,
block_time: blockTime,
blockNum,
fast, fast,
fastest, fastest,
fastestWait, block_time: blockTime,
fastWait, blockNum,
safeLow,
safeLowWait,
speed,
}) => { }) => {
const basicEstimates = { const basicEstimates = {
safeLow,
average,
fast,
fastest,
blockTime,
blockNum,
}
dispatch(setBasicGasEstimateData(basicEstimates))
dispatch(basicGasEstimatesLoadingFinished())
return basicEstimates
})
}
}
export function fetchBasicGasAndTimeEstimates () {
return (dispatch, getState) => {
const {
basicPriceAndTimeEstimatesLastRetrieved,
basicPriceAndTimeEstimates,
} = getState().gas
const timeLastRetrieved = basicPriceAndTimeEstimatesLastRetrieved || loadLocalStorageData('BASIC_GAS_AND_TIME_API_ESTIMATES_LAST_RETRIEVED') || 0
dispatch(basicGasEstimatesLoadingStarted())
const promiseToFetch = Date.now() - timeLastRetrieved > 75000
? fetch('https://ethgasstation.info/json/ethgasAPI.json', {
'headers': {},
'referrer': 'http://ethgasstation.info/json/',
'referrerPolicy': 'no-referrer-when-downgrade',
'body': null,
'method': 'GET',
'mode': 'cors'}
)
.then(r => r.json())
.then(({
average, average,
avgWait, avgWait,
blockTime, block_time: blockTime,
blockNum, blockNum,
fast, fast,
fastest, fastest,
@ -193,7 +231,34 @@ export function fetchBasicGasEstimates () {
safeLow, safeLow,
safeLowWait, safeLowWait,
speed, speed,
} }) => {
const basicEstimates = {
average,
avgWait,
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(setBasicGasEstimateData(basicEstimates))
dispatch(basicGasEstimatesLoadingFinished()) dispatch(basicGasEstimatesLoadingFinished())
return basicEstimates return basicEstimates
@ -301,6 +366,13 @@ export function setApiEstimatesLastRetrieved (retrievalTime) {
} }
} }
export function setBasicApiEstimatesLastRetrieved (retrievalTime) {
return {
type: SET_BASIC_API_ESTIMATES_LAST_RETRIEVED,
value: retrievalTime,
}
}
export function resetCustomGasState () { export function resetCustomGasState () {
return { type: RESET_CUSTOM_GAS_STATE } return { type: RESET_CUSTOM_GAS_STATE }
} }

View File

@ -19,7 +19,7 @@ const {
setCustomGasTotal, setCustomGasTotal,
setCustomGasErrors, setCustomGasErrors,
resetCustomGasState, resetCustomGasState,
fetchBasicGasEstimates, fetchBasicGasAndTimeEstimates,
gasEstimatesLoadingStarted, gasEstimatesLoadingStarted,
gasEstimatesLoadingFinished, gasEstimatesLoadingFinished,
setPricesAndTimeEstimates, setPricesAndTimeEstimates,
@ -100,6 +100,9 @@ describe('Gas Duck', () => {
gasEstimatesLoading: true, gasEstimatesLoading: true,
priceAndTimeEstimates: [], priceAndTimeEstimates: [],
priceAndTimeEstimatesLastRetrieved: 0, priceAndTimeEstimatesLastRetrieved: 0,
basicPriceAndTimeEstimates: [],
basicPriceAndTimeEstimatesLastRetrieved: 0,
} }
const BASIC_GAS_ESTIMATE_LOADING_FINISHED = 'metamask/gas/BASIC_GAS_ESTIMATE_LOADING_FINISHED' const BASIC_GAS_ESTIMATE_LOADING_FINISHED = 'metamask/gas/BASIC_GAS_ESTIMATE_LOADING_FINISHED'
@ -114,6 +117,7 @@ describe('Gas Duck', () => {
const SET_CUSTOM_GAS_TOTAL = 'metamask/gas/SET_CUSTOM_GAS_TOTAL' const SET_CUSTOM_GAS_TOTAL = 'metamask/gas/SET_CUSTOM_GAS_TOTAL'
const SET_PRICE_AND_TIME_ESTIMATES = 'metamask/gas/SET_PRICE_AND_TIME_ESTIMATES' const SET_PRICE_AND_TIME_ESTIMATES = 'metamask/gas/SET_PRICE_AND_TIME_ESTIMATES'
const SET_API_ESTIMATES_LAST_RETRIEVED = 'metamask/gas/SET_API_ESTIMATES_LAST_RETRIEVED' const SET_API_ESTIMATES_LAST_RETRIEVED = 'metamask/gas/SET_API_ESTIMATES_LAST_RETRIEVED'
const SET_BASIC_API_ESTIMATES_LAST_RETRIEVED = 'metamask/gas/SET_BASIC_API_ESTIMATES_LAST_RETRIEVED'
describe('GasReducer()', () => { describe('GasReducer()', () => {
it('should initialize state', () => { it('should initialize state', () => {
@ -224,7 +228,7 @@ describe('Gas Duck', () => {
) )
}) })
it('should set priceAndTimeEstimatesLastRetrieved when receivinga SET_API_ESTIMATES_LAST_RETRIEVED action', () => { it('should set priceAndTimeEstimatesLastRetrieved when receiving a SET_API_ESTIMATES_LAST_RETRIEVED action', () => {
assert.deepEqual( assert.deepEqual(
GasReducer(mockState, { GasReducer(mockState, {
type: SET_API_ESTIMATES_LAST_RETRIEVED, type: SET_API_ESTIMATES_LAST_RETRIEVED,
@ -234,6 +238,16 @@ describe('Gas Duck', () => {
) )
}) })
it('should set priceAndTimeEstimatesLastRetrieved when receiving a SET_BASIC_API_ESTIMATES_LAST_RETRIEVED action', () => {
assert.deepEqual(
GasReducer(mockState, {
type: SET_BASIC_API_ESTIMATES_LAST_RETRIEVED,
value: 1700000000000,
}),
Object.assign({ basicPriceAndTimeEstimatesLastRetrieved: 1700000000000 }, mockState.gas)
)
})
it('should set errors when receiving a SET_CUSTOM_GAS_ERRORS action', () => { it('should set errors when receiving a SET_CUSTOM_GAS_ERRORS action', () => {
assert.deepEqual( assert.deepEqual(
GasReducer(mockState, { GasReducer(mockState, {
@ -272,10 +286,14 @@ describe('Gas Duck', () => {
}) })
}) })
describe('fetchBasicGasEstimates', () => { describe('fetchBasicGasAndTimeEstimates', () => {
const mockDistpatch = sinon.spy() const mockDistpatch = sinon.spy()
it('should call fetch with the expected params', async () => { it('should call fetch with the expected params', async () => {
await fetchBasicGasEstimates()(mockDistpatch) await fetchBasicGasAndTimeEstimates()(mockDistpatch, () => ({ gas: Object.assign(
{},
initState,
{ basicPriceAndTimeEstimatesLastRetrieved: 1000000 }
) }))
assert.deepEqual( assert.deepEqual(
mockDistpatch.getCall(0).args, mockDistpatch.getCall(0).args,
[{ type: BASIC_GAS_ESTIMATE_LOADING_STARTED} ] [{ type: BASIC_GAS_ESTIMATE_LOADING_STARTED} ]
@ -294,8 +312,14 @@ describe('Gas Duck', () => {
}, },
] ]
) )
assert.deepEqual( assert.deepEqual(
mockDistpatch.getCall(1).args, 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, type: SET_BASIC_GAS_ESTIMATE_DATA,
value: { value: {
@ -314,7 +338,7 @@ describe('Gas Duck', () => {
}] }]
) )
assert.deepEqual( assert.deepEqual(
mockDistpatch.getCall(2).args, mockDistpatch.getCall(3).args,
[{ type: BASIC_GAS_ESTIMATE_LOADING_FINISHED }] [{ type: BASIC_GAS_ESTIMATE_LOADING_FINISHED }]
) )
}) })

View File

@ -23,7 +23,9 @@ import { addHexPrefix } from 'ethereumjs-util'
const selectors = { const selectors = {
formatTimeEstimate, formatTimeEstimate,
getAveragePriceEstimateInHexWEI, getAveragePriceEstimateInHexWEI,
getFastPriceEstimateInHexWEI,
getBasicGasEstimateLoadingStatus, getBasicGasEstimateLoadingStatus,
getBasicGasEstimateBlockTime,
getCustomGasErrors, getCustomGasErrors,
getCustomGasLimit, getCustomGasLimit,
getCustomGasPrice, getCustomGasPrice,
@ -33,7 +35,7 @@ const selectors = {
getEstimatedGasTimes, getEstimatedGasTimes,
getPriceAndTimeEstimates, getPriceAndTimeEstimates,
getRenderableBasicEstimateData, getRenderableBasicEstimateData,
getRenderableEstimateDataForSmallButtons, getRenderableEstimateDataForSmallButtonsFromGWEI,
priceEstimateToWei, priceEstimateToWei,
} }
@ -78,12 +80,21 @@ function getAveragePriceEstimateInHexWEI (state) {
return getGasPriceInHexWei(averagePriceEstimate || '0x0') return getGasPriceInHexWei(averagePriceEstimate || '0x0')
} }
function getFastPriceEstimateInHexWEI (state, convertFromDecGWEI) {
const fastPriceEstimate = state.gas.basicEstimates.fast
return getGasPriceInHexWei(fastPriceEstimate || '0x0', convertFromDecGWEI)
}
function getDefaultActiveButtonIndex (gasButtonInfo, customGasPriceInHex, gasPrice) { function getDefaultActiveButtonIndex (gasButtonInfo, customGasPriceInHex, gasPrice) {
return gasButtonInfo.findIndex(({ priceInHexWei }) => { return gasButtonInfo.findIndex(({ priceInHexWei }) => {
return priceInHexWei === addHexPrefix(customGasPriceInHex || gasPrice) return priceInHexWei === addHexPrefix(customGasPriceInHex || gasPrice)
}) })
} }
function getBasicGasEstimateBlockTime (state) {
return state.gas.basicEstimates.blockTime
}
function apiEstimateModifiedToGWEI (estimate) { function apiEstimateModifiedToGWEI (estimate) {
return multiplyCurrencies(estimate, 0.10, { return multiplyCurrencies(estimate, 0.10, {
toNumericBase: 'hex', toNumericBase: 'hex',
@ -102,26 +113,34 @@ function basicPriceEstimateToETHTotal (estimate, gasLimit, numberOfDecimals = 9)
}) })
} }
function getRenderableEthFee (estimate, gasLimit, numberOfDecimals = 9) { function getRenderableEthFee (estimate, gasLimit, numberOfDecimals = 9, convertFromDecGWEI) {
const initialConversion = convertFromDecGWEI
? x => conversionUtil(x, { fromNumericBase: 'dec', toNumericBase: 'hex' })
: apiEstimateModifiedToGWEI
return pipe( return pipe(
apiEstimateModifiedToGWEI, initialConversion,
partialRight(basicPriceEstimateToETHTotal, [gasLimit, numberOfDecimals]), partialRight(basicPriceEstimateToETHTotal, [gasLimit, numberOfDecimals]),
formatETHFee formatETHFee
)(estimate, gasLimit) )(estimate, gasLimit)
} }
function getRenderableConvertedCurrencyFee (estimate, gasLimit, convertedCurrency, conversionRate) { function getRenderableConvertedCurrencyFee (estimate, gasLimit, convertedCurrency, conversionRate, convertFromDecGWEI) {
const initialConversion = convertFromDecGWEI
? x => conversionUtil(x, { fromNumericBase: 'dec', toNumericBase: 'hex' })
: apiEstimateModifiedToGWEI
return pipe( return pipe(
apiEstimateModifiedToGWEI, initialConversion,
partialRight(basicPriceEstimateToETHTotal, [gasLimit]), partialRight(basicPriceEstimateToETHTotal, [gasLimit]),
partialRight(ethTotalToConvertedCurrency, [convertedCurrency, conversionRate]), partialRight(ethTotalToConvertedCurrency, [convertedCurrency, conversionRate]),
partialRight(formatCurrency, [convertedCurrency]) partialRight(formatCurrency, [convertedCurrency])
)(estimate, gasLimit, convertedCurrency, conversionRate) )(estimate, gasLimit, convertedCurrency, conversionRate)
} }
function getTimeEstimateInSeconds (blockWaitEstimate, currentBlockTime) { function getTimeEstimateInSeconds (blockWaitEstimate) {
return multiplyCurrencies(blockWaitEstimate, currentBlockTime, { return multiplyCurrencies(blockWaitEstimate, 60, {
toNumericBase: 'dec', toNumericBase: 'dec',
multiplicandBase: 10, multiplicandBase: 10,
multiplierBase: 10, multiplierBase: 10,
@ -141,11 +160,11 @@ function formatTimeEstimate (totalSeconds) {
return formattedCombined return formattedCombined
} }
function getRenderableTimeEstimate (blockWaitEstimate, currentBlockTime) { function getRenderableTimeEstimate (blockWaitEstimate) {
return pipe( return pipe(
getTimeEstimateInSeconds, getTimeEstimateInSeconds,
formatTimeEstimate formatTimeEstimate
)(blockWaitEstimate, currentBlockTime) )(blockWaitEstimate)
} }
function priceEstimateToWei (priceEstimate) { function priceEstimateToWei (priceEstimate) {
@ -158,9 +177,13 @@ function priceEstimateToWei (priceEstimate) {
}) })
} }
function getGasPriceInHexWei (price) { function getGasPriceInHexWei (price, convertFromDecGWEI) {
const initialConversion = convertFromDecGWEI
? x => conversionUtil(x, { fromNumericBase: 'dec', toNumericBase: 'hex' })
: apiEstimateModifiedToGWEI
return pipe( return pipe(
apiEstimateModifiedToGWEI, initialConversion,
priceEstimateToWei, priceEstimateToWei,
addHexPrefix addHexPrefix
)(price) )(price)
@ -177,11 +200,10 @@ function getRenderableBasicEstimateData (state) {
gas: { gas: {
basicEstimates: { basicEstimates: {
safeLow, safeLow,
average,
fast, fast,
blockTime, fastest,
safeLowWait, safeLowWait,
avgWait, fastestWait,
fastWait, fastWait,
}, },
}, },
@ -190,29 +212,29 @@ function getRenderableBasicEstimateData (state) {
return [ return [
{ {
labelKey: 'fastest', labelKey: 'fastest',
feeInPrimaryCurrency: getRenderableConvertedCurrencyFee(fast, gasLimit, currentCurrency, conversionRate), feeInPrimaryCurrency: getRenderableConvertedCurrencyFee(fastest, gasLimit, currentCurrency, conversionRate),
feeInSecondaryCurrency: getRenderableEthFee(fast, gasLimit), feeInSecondaryCurrency: getRenderableEthFee(fastest, gasLimit),
timeEstimate: getRenderableTimeEstimate(fastWait, blockTime), timeEstimate: fastestWait && getRenderableTimeEstimate(fastestWait),
priceInHexWei: getGasPriceInHexWei(fast), priceInHexWei: getGasPriceInHexWei(fastest),
}, },
{ {
labelKey: 'fast', labelKey: 'fast',
feeInPrimaryCurrency: getRenderableConvertedCurrencyFee(average, gasLimit, currentCurrency, conversionRate), feeInPrimaryCurrency: getRenderableConvertedCurrencyFee(fast, gasLimit, currentCurrency, conversionRate),
feeInSecondaryCurrency: getRenderableEthFee(average, gasLimit), feeInSecondaryCurrency: getRenderableEthFee(fast, gasLimit),
timeEstimate: getRenderableTimeEstimate(avgWait, blockTime), timeEstimate: fastWait && getRenderableTimeEstimate(fastWait),
priceInHexWei: getGasPriceInHexWei(average), priceInHexWei: getGasPriceInHexWei(fast),
}, },
{ {
labelKey: 'slow', labelKey: 'slow',
feeInPrimaryCurrency: getRenderableConvertedCurrencyFee(safeLow, gasLimit, currentCurrency, conversionRate), feeInPrimaryCurrency: getRenderableConvertedCurrencyFee(safeLow, gasLimit, currentCurrency, conversionRate),
feeInSecondaryCurrency: getRenderableEthFee(safeLow, gasLimit), feeInSecondaryCurrency: getRenderableEthFee(safeLow, gasLimit),
timeEstimate: getRenderableTimeEstimate(safeLowWait, blockTime), timeEstimate: safeLowWait && getRenderableTimeEstimate(safeLowWait),
priceInHexWei: getGasPriceInHexWei(safeLow), priceInHexWei: getGasPriceInHexWei(safeLow),
}, },
] ]
} }
function getRenderableEstimateDataForSmallButtons (state) { function getRenderableEstimateDataForSmallButtonsFromGWEI (state) {
if (getBasicGasEstimateLoadingStatus(state)) { if (getBasicGasEstimateLoadingStatus(state)) {
return [] return []
} }
@ -223,30 +245,30 @@ function getRenderableEstimateDataForSmallButtons (state) {
gas: { gas: {
basicEstimates: { basicEstimates: {
safeLow, safeLow,
average,
fast, fast,
fastest,
}, },
}, },
} = state } = state
return [ return [
{ {
labelKey: 'fast', labelKey: 'fastest',
feeInSecondaryCurrency: getRenderableConvertedCurrencyFee(fast, gasLimit, currentCurrency, conversionRate), feeInSecondaryCurrency: getRenderableConvertedCurrencyFee(fastest, gasLimit, currentCurrency, conversionRate, true),
feeInPrimaryCurrency: getRenderableEthFee(fast, gasLimit, NUMBER_OF_DECIMALS_SM_BTNS), feeInPrimaryCurrency: getRenderableEthFee(fastest, gasLimit, NUMBER_OF_DECIMALS_SM_BTNS, true),
priceInHexWei: getGasPriceInHexWei(fast), priceInHexWei: getGasPriceInHexWei(fastest, true),
}, },
{ {
labelKey: 'average', labelKey: 'fast',
feeInSecondaryCurrency: getRenderableConvertedCurrencyFee(average, gasLimit, currentCurrency, conversionRate), feeInSecondaryCurrency: getRenderableConvertedCurrencyFee(fast, gasLimit, currentCurrency, conversionRate, true),
feeInPrimaryCurrency: getRenderableEthFee(average, gasLimit, NUMBER_OF_DECIMALS_SM_BTNS), feeInPrimaryCurrency: getRenderableEthFee(fast, gasLimit, NUMBER_OF_DECIMALS_SM_BTNS, true),
priceInHexWei: getGasPriceInHexWei(average), priceInHexWei: getGasPriceInHexWei(fast, true),
}, },
{ {
labelKey: 'slow', labelKey: 'slow',
feeInSecondaryCurrency: getRenderableConvertedCurrencyFee(safeLow, gasLimit, currentCurrency, conversionRate), feeInSecondaryCurrency: getRenderableConvertedCurrencyFee(safeLow, gasLimit, currentCurrency, conversionRate, true),
feeInPrimaryCurrency: getRenderableEthFee(safeLow, gasLimit, NUMBER_OF_DECIMALS_SM_BTNS), feeInPrimaryCurrency: getRenderableEthFee(safeLow, gasLimit, NUMBER_OF_DECIMALS_SM_BTNS, true),
priceInHexWei: getGasPriceInHexWei(safeLow), priceInHexWei: getGasPriceInHexWei(safeLow, true),
}, },
] ]
} }

View File

@ -10,7 +10,7 @@ const {
getEstimatedGasTimes, getEstimatedGasTimes,
getPriceAndTimeEstimates, getPriceAndTimeEstimates,
getRenderableBasicEstimateData, getRenderableBasicEstimateData,
getRenderableEstimateDataForSmallButtons, getRenderableEstimateDataForSmallButtonsFromGWEI,
} = proxyquire('../custom-gas', {}) } = proxyquire('../custom-gas', {})
describe('custom-gas selectors', () => { describe('custom-gas selectors', () => {
@ -80,21 +80,21 @@ describe('custom-gas selectors', () => {
labelKey: 'fastest', labelKey: 'fastest',
feeInPrimaryCurrency: '$0.05', feeInPrimaryCurrency: '$0.05',
feeInSecondaryCurrency: '0.00021 ETH', feeInSecondaryCurrency: '0.00021 ETH',
timeEstimate: '~7 sec', timeEstimate: '~30 sec',
priceInHexWei: '0x2540be400', priceInHexWei: '0x2540be400',
}, },
{ {
labelKey: 'fast', labelKey: 'fast',
feeInPrimaryCurrency: '$0.03', feeInPrimaryCurrency: '$0.03',
feeInSecondaryCurrency: '0.000105 ETH', feeInSecondaryCurrency: '0.000105 ETH',
timeEstimate: '~46 sec', timeEstimate: '~3 min 18 sec',
priceInHexWei: '0x12a05f200', priceInHexWei: '0x12a05f200',
}, },
{ {
labelKey: 'slow', labelKey: 'slow',
feeInPrimaryCurrency: '$0.01', feeInPrimaryCurrency: '$0.01',
feeInSecondaryCurrency: '0.0000525 ETH', feeInSecondaryCurrency: '0.0000525 ETH',
timeEstimate: '~1 min 33 sec', timeEstimate: '~6 min 36 sec',
priceInHexWei: '0x9502f900', priceInHexWei: '0x9502f900',
}, },
], ],
@ -111,10 +111,10 @@ describe('custom-gas selectors', () => {
blockTime: 14.16326530612245, blockTime: 14.16326530612245,
safeLow: 25, safeLow: 25,
safeLowWait: 6.6, safeLowWait: 6.6,
average: 50, fast: 50,
avgWait: 3.3, fastWait: 3.3,
fast: 100, fastest: 100,
fastWait: 0.5, fastestWait: 0.5,
}, },
}, },
}, },
@ -125,21 +125,21 @@ describe('custom-gas selectors', () => {
labelKey: 'fastest', labelKey: 'fastest',
feeInPrimaryCurrency: '$1.07', feeInPrimaryCurrency: '$1.07',
feeInSecondaryCurrency: '0.00042 ETH', feeInSecondaryCurrency: '0.00042 ETH',
timeEstimate: '~14 sec', timeEstimate: '~1 min',
priceInHexWei: '0x4a817c800', priceInHexWei: '0x4a817c800',
}, },
{ {
labelKey: 'fast', labelKey: 'fast',
feeInPrimaryCurrency: '$0.54', feeInPrimaryCurrency: '$0.54',
feeInSecondaryCurrency: '0.00021 ETH', feeInSecondaryCurrency: '0.00021 ETH',
timeEstimate: '~1 min 33 sec', timeEstimate: '~6 min 36 sec',
priceInHexWei: '0x2540be400', priceInHexWei: '0x2540be400',
}, },
{ {
labelKey: 'slow', labelKey: 'slow',
feeInPrimaryCurrency: '$0.27', feeInPrimaryCurrency: '$0.27',
feeInSecondaryCurrency: '0.000105 ETH', feeInSecondaryCurrency: '0.000105 ETH',
timeEstimate: '~3 min 7 sec', timeEstimate: '~13 min 12 sec',
priceInHexWei: '0x12a05f200', priceInHexWei: '0x12a05f200',
}, },
], ],
@ -156,10 +156,10 @@ describe('custom-gas selectors', () => {
blockTime: 14.16326530612245, blockTime: 14.16326530612245,
safeLow: 50, safeLow: 50,
safeLowWait: 13.2, safeLowWait: 13.2,
average: 100, fast: 100,
avgWait: 6.6, fastWait: 6.6,
fast: 200, fastest: 200,
fastWait: 1.0, fastestWait: 1.0,
}, },
}, },
}, },
@ -176,27 +176,27 @@ describe('custom-gas selectors', () => {
}) })
describe('getRenderableEstimateDataForSmallButtons()', () => { describe('getRenderableEstimateDataForSmallButtonsFromGWEI()', () => {
const tests = [ const tests = [
{ {
expectedResult: [ expectedResult: [
{ {
feeInSecondaryCurrency: '$0.05', feeInSecondaryCurrency: '$0.54',
feeInPrimaryCurrency: '0.00021 ETH', feeInPrimaryCurrency: '0.0021 ETH',
labelKey: 'fastest',
priceInHexWei: '0x174876e800',
},
{
feeInSecondaryCurrency: '$0.27',
feeInPrimaryCurrency: '0.00105 ETH',
labelKey: 'fast', labelKey: 'fast',
priceInHexWei: '0x2540be400', priceInHexWei: '0xba43b7400',
}, },
{ {
feeInSecondaryCurrency: '$0.03', feeInSecondaryCurrency: '$0.13',
feeInPrimaryCurrency: '0.0001 ETH', feeInPrimaryCurrency: '0.00052 ETH',
labelKey: 'average',
priceInHexWei: '0x12a05f200',
},
{
feeInSecondaryCurrency: '$0.01',
feeInPrimaryCurrency: '0.00005 ETH',
labelKey: 'slow', labelKey: 'slow',
priceInHexWei: '0x9502f900', priceInHexWei: '0x5d21dba00',
}, },
], ],
mockState: { mockState: {
@ -212,10 +212,10 @@ describe('custom-gas selectors', () => {
blockTime: 14.16326530612245, blockTime: 14.16326530612245,
safeLow: 25, safeLow: 25,
safeLowWait: 6.6, safeLowWait: 6.6,
average: 50, fast: 50,
avgWait: 3.3, fastWait: 3.3,
fast: 100, fastest: 100,
fastWait: 0.5, fastestWait: 0.5,
}, },
}, },
}, },
@ -223,22 +223,22 @@ describe('custom-gas selectors', () => {
{ {
expectedResult: [ expectedResult: [
{ {
feeInSecondaryCurrency: '$1.07', feeInSecondaryCurrency: '$10.74',
feeInPrimaryCurrency: '0.00042 ETH', feeInPrimaryCurrency: '0.0042 ETH',
labelKey: 'fastest',
priceInHexWei: '0x2e90edd000',
},
{
feeInSecondaryCurrency: '$5.37',
feeInPrimaryCurrency: '0.0021 ETH',
labelKey: 'fast', labelKey: 'fast',
priceInHexWei: '0x4a817c800', priceInHexWei: '0x174876e800',
}, },
{ {
feeInSecondaryCurrency: '$0.54', feeInSecondaryCurrency: '$2.68',
feeInPrimaryCurrency: '0.00021 ETH', feeInPrimaryCurrency: '0.00105 ETH',
labelKey: 'average',
priceInHexWei: '0x2540be400',
},
{
feeInSecondaryCurrency: '$0.27',
feeInPrimaryCurrency: '0.0001 ETH',
labelKey: 'slow', labelKey: 'slow',
priceInHexWei: '0x12a05f200', priceInHexWei: '0xba43b7400',
}, },
], ],
mockState: { mockState: {
@ -254,10 +254,10 @@ describe('custom-gas selectors', () => {
blockTime: 14.16326530612245, blockTime: 14.16326530612245,
safeLow: 50, safeLow: 50,
safeLowWait: 13.2, safeLowWait: 13.2,
average: 100, fast: 100,
avgWait: 6.6, fastWait: 6.6,
fast: 200, fastest: 200,
fastWait: 1.0, fastestWait: 1.0,
}, },
}, },
}, },
@ -266,7 +266,7 @@ describe('custom-gas selectors', () => {
it('should return renderable data about basic estimates appropriate for buttons with less info', () => { it('should return renderable data about basic estimates appropriate for buttons with less info', () => {
tests.forEach(test => { tests.forEach(test => {
assert.deepEqual( assert.deepEqual(
getRenderableEstimateDataForSmallButtons(test.mockState), getRenderableEstimateDataForSmallButtonsFromGWEI(test.mockState),
test.expectedResult test.expectedResult
) )
}) })

5
ui/lib/test-timeout.js Normal file
View File

@ -0,0 +1,5 @@
export default function timeout (time) {
return new Promise((resolve, reject) => {
setTimeout(resolve, time || 1500)
})
}