1
0
mirror of https://github.com/kremalicious/metamask-extension.git synced 2024-10-22 11:22:43 +02:00

Connect the gas-button-group component to redux and a live api.

This commit is contained in:
Dan Miller 2018-08-16 09:58:27 -02:30
parent 112d18e316
commit 0a7dfcd55d
15 changed files with 573 additions and 111 deletions

View File

@ -5,6 +5,7 @@ import classnames from 'classnames'
export default class ButtonGroup extends PureComponent {
static propTypes = {
defaultActiveButtonIndex: PropTypes.number,
noButtonActiveByDefault: PropTypes.bool,
disabled: PropTypes.bool,
children: PropTypes.array,
className: PropTypes.string,
@ -16,7 +17,9 @@ export default class ButtonGroup extends PureComponent {
}
state = {
activeButtonIndex: this.props.defaultActiveButtonIndex || 0,
activeButtonIndex: this.props.noButtonActiveByDefault
? null
: this.props.defaultActiveButtonIndex || 0,
}
handleButtonClick (activeButtonIndex) {

View File

@ -15,7 +15,13 @@ export default class BasicTabContent extends Component {
return (
<div className="basic-tab-content">
<div className="basic-tab-content__title">Suggest gas fee increases</div>
<GasPriceButtonGroup {...this.props.gasPriceButtonGroupProps} />
<GasPriceButtonGroup
{...this.props.gasPriceButtonGroupProps}
className="gas-price-button-group"
noButtonActiveByDefault={true}
showCheck={true}
handleGasPriceSelection={(newPrice) => console.log('New Price:', newPrice)}
/>
</div>
)
}

View File

@ -23,7 +23,9 @@ export default class GasModalPageContainer extends Component {
renderBasicTabContent () {
return (
<BasicTabContent gasPriceButtonGroupProps={this.props.gasPriceButtonGroupProps} />
<BasicTabContent
gasPriceButtonGroupProps={this.props.gasPriceButtonGroupProps}
/>
)
}

View File

@ -4,45 +4,23 @@ import { hideModal } from '../../../actions'
import {
setCustomGasPrice,
setCustomGasLimit,
} from '../../../ducks/custom-gas'
} from '../../../ducks/gas.duck'
import {
getCustomGasPrice,
getCustomGasLimit,
getRenderableBasicEstimateData,
getBasicGasEstimateLoadingStatus,
} from '../../../selectors/custom-gas'
const mockGasPriceButtonGroupProps = {
buttonDataLoading: false,
className: 'gas-price-button-group',
gasButtonInfo: [
{
feeInPrimaryCurrency: '$0.52',
feeInSecondaryCurrency: '0.0048 ETH',
timeEstimate: '~ 1 min 0 sec',
priceInHexWei: '0xa1b2c3f',
},
{
feeInPrimaryCurrency: '$0.39',
feeInSecondaryCurrency: '0.004 ETH',
timeEstimate: '~ 1 min 30 sec',
priceInHexWei: '0xa1b2c39',
},
{
feeInPrimaryCurrency: '$0.30',
feeInSecondaryCurrency: '0.00354 ETH',
timeEstimate: '~ 2 min 1 sec',
priceInHexWei: '0xa1b2c30',
},
],
handleGasPriceSelection: newPrice => console.log('NewPrice: ', newPrice),
noButtonActiveByDefault: true,
showCheck: true,
}
const mapStateToProps = state => {
const buttonDataLoading = getBasicGasEstimateLoadingStatus(state)
return {
customGasPrice: getCustomGasPrice(state),
customGasLimit: getCustomGasLimit(state),
gasPriceButtonGroupProps: mockGasPriceButtonGroupProps,
gasPriceButtonGroupProps: {
buttonDataLoading,
gasButtonInfo: getRenderableBasicEstimateData(state),
},
}
}
@ -51,6 +29,7 @@ const mapDispatchToProps = dispatch => {
hideModal: () => dispatch(hideModal()),
updateCustomGasPrice: (newPrice) => dispatch(setCustomGasPrice(newPrice)),
updateCustomGasLimit: (newLimit) => dispatch(setCustomGasLimit(newLimit)),
handleGasPriceSelection: newPrice => console.log('NewPrice: ', newPrice),
}
}

View File

@ -25,9 +25,11 @@ proxyquire('../gas-modal-page-container.container.js', {
'../../../selectors/custom-gas': {
getCustomGasPrice: (s) => `mockGasPrice:${s}`,
getCustomGasLimit: (s) => `mockGasLimit:${s}`,
getBasicGasEstimateLoadingStatus: (s) => `mockBasicGasEstimateLoadingStatus:${s}`,
getRenderableBasicEstimateData: (s) => `mockRenderableBasicEstimateData:${s}`,
},
'../../../actions': actionSpies,
'../../../ducks/custom-gas': customGasActionSpies,
'../../../ducks/gas.duck': customGasActionSpies,
})
describe('gas-modal-page-container container', () => {
@ -37,6 +39,8 @@ describe('gas-modal-page-container container', () => {
it('should map the correct properties to props', () => {
assert.equal(mapStateToProps('mockState').customGasPrice, 'mockGasPrice:mockState')
assert.equal(mapStateToProps('mockState').customGasLimit, 'mockGasLimit:mockState')
assert.equal(mapStateToProps('mockState').gasPriceButtonGroupProps.buttonDataLoading, 'mockBasicGasEstimateLoadingStatus:mockState')
assert.equal(mapStateToProps('mockState').gasPriceButtonGroupProps.gasButtonInfo, 'mockRenderableBasicEstimateData:mockState')
})
})

View File

@ -0,0 +1,14 @@
const selectors = {
getCurrentBlockTime,
getBasicGasEstimateLoadingStatus,
}
module.exports = selectors
function getCurrentBlockTime (state) {
return state.gas.currentBlockTime
}
function getBasicGasEstimateLoadingStatus (state) {
return state.gas.basicEstimateIsLoading
}

View File

@ -162,6 +162,10 @@ export default class SendTransactionScreen extends PersistentForm {
}
}
componentDidMount () {
this.props.fetchGasEstimates()
}
componentWillMount () {
const {
from: { address },

View File

@ -36,6 +36,9 @@ import {
resetSendState,
updateSendErrors,
} from '../../ducks/send.duck'
import {
fetchGasEstimates,
} from '../../ducks/gas.duck'
import {
calcGasTotal,
} from './send.utils.js'
@ -104,5 +107,6 @@ function mapDispatchToProps (dispatch) {
scanQrCode: () => dispatch(showQrScanner(SEND_ROUTE)),
qrCodeDetected: (data) => dispatch(qrCodeDetected(data)),
updateSendTo: (to, nickname) => dispatch(updateSendTo(to, nickname)),
fetchGasEstimates: () => dispatch(fetchGasEstimates()),
}
}

View File

@ -13,6 +13,7 @@ const propsMethodSpies = {
updateSendErrors: sinon.spy(),
updateSendTokenBalance: sinon.spy(),
resetSendState: sinon.spy(),
fetchGasEstimates: sinon.spy(),
}
const utilsMethodStubs = {
getAmountErrorObject: sinon.stub().returns({ amount: 'mockAmountError' }),
@ -37,6 +38,7 @@ describe('Send Component', function () {
blockGasLimit={'mockBlockGasLimit'}
conversionRate={10}
editingTransactionId={'mockEditingTransactionId'}
fetchGasEstimates={propsMethodSpies.fetchGasEstimates}
from={ { address: 'mockAddress', balance: 'mockBalance' } }
gasLimit={'mockGasLimit'}
gasPrice={'mockGasPrice'}
@ -63,6 +65,7 @@ describe('Send Component', function () {
utilsMethodStubs.doesAmountErrorRequireUpdate.resetHistory()
utilsMethodStubs.getAmountErrorObject.resetHistory()
utilsMethodStubs.getGasFeeErrorObject.resetHistory()
propsMethodSpies.fetchGasEstimates.resetHistory()
propsMethodSpies.updateAndSetGasTotal.resetHistory()
propsMethodSpies.updateSendErrors.resetHistory()
propsMethodSpies.updateSendTokenBalance.resetHistory()
@ -82,6 +85,15 @@ describe('Send Component', function () {
})
})
describe('componentDidMount', () => {
it('should call props.fetchGasEstimates', () => {
propsMethodSpies.fetchGasEstimates.resetHistory()
assert.equal(propsMethodSpies.fetchGasEstimates.callCount, 0)
wrapper.instance().componentDidMount()
assert.equal(propsMethodSpies.fetchGasEstimates.callCount, 1)
})
})
describe('componentWillUnmount', () => {
it('should call this.props.resetSendState', () => {
propsMethodSpies.resetSendState.resetHistory()

View File

@ -1,67 +0,0 @@
import extend from 'xtend'
// Actions
const SET_CUSTOM_GAS_PRICE = 'metamask/custom-gas/SET_CUSTOM_GAS_PRICE'
const SET_CUSTOM_GAS_LIMIT = 'metamask/custom-gas/SET_CUSTOM_GAS_LIMIT'
const SET_CUSTOM_GAS_ERRORS = 'metamask/custom-gas/SET_CUSTOM_GAS_ERRORS'
const RESET_CUSTOM_GAS_STATE = 'metamask/custom-gas/RESET_CUSTOM_GAS_STATE'
// TODO: determine if this approach to initState is consistent with conventional ducks pattern
const initState = {
price: 0,
limit: 21000,
errors: {},
}
// Reducer
export default function reducer ({ customGas: customGasState = initState }, action = {}) {
const newState = extend({}, customGasState)
switch (action.type) {
case SET_CUSTOM_GAS_PRICE:
return extend(newState, {
price: action.value,
})
case SET_CUSTOM_GAS_LIMIT:
return extend(newState, {
limit: action.value,
})
case SET_CUSTOM_GAS_ERRORS:
return extend(newState, {
errors: {
...newState.errors,
...action.value,
},
})
case RESET_CUSTOM_GAS_STATE:
return extend({}, initState)
default:
return newState
}
}
// Action Creators
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 setCustomGasErrors (newErrors) {
return {
type: SET_CUSTOM_GAS_ERRORS,
value: newErrors,
}
}
export function resetCustomGasState () {
return { type: RESET_CUSTOM_GAS_STATE }
}

189
ui/app/ducks/gas.duck.js Normal file
View File

@ -0,0 +1,189 @@
import { clone } from 'ramda'
// 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 SET_BASIC_GAS_ESTIMATE_DATA = 'metamask/gas/SET_BASIC_GAS_ESTIMATE_DATA'
const SET_CUSTOM_GAS_ERRORS = 'metamask/gas/SET_CUSTOM_GAS_ERRORS'
const SET_CUSTOM_GAS_LIMIT = 'metamask/gas/SET_CUSTOM_GAS_LIMIT'
const SET_CUSTOM_GAS_PRICE = 'metamask/gas/SET_CUSTOM_GAS_PRICE'
const SET_CUSTOM_GAS_TOTAL = 'metamask/gas/SET_CUSTOM_GAS_TOTAL'
// TODO: determine if this approach to initState is consistent with conventional ducks pattern
const initState = {
customData: {
price: 0,
limit: 21000,
},
basicEstimates: {
average: null,
fastestWait: null,
fastWait: null,
fast: null,
safeLowWait: null,
blockNum: null,
avgWait: null,
blockTime: null,
speed: null,
fastest: null,
safeLow: null,
},
basicEstimateIsLoading: true,
errors: {},
}
// Reducer
export default function reducer ({ gas: gasState = initState }, action = {}) {
const newState = clone(gasState)
switch (action.type) {
case BASIC_GAS_ESTIMATE_LOADING_STARTED:
return {
...newState,
basicEstimateIsLoading: true,
}
case BASIC_GAS_ESTIMATE_LOADING_FINISHED:
return {
...newState,
basicEstimateIsLoading: false,
}
case SET_BASIC_GAS_ESTIMATE_DATA:
return {
...newState,
basicEstimates: action.value,
}
case SET_CUSTOM_GAS_PRICE:
return {
...newState,
customData: {
...newState.customData,
price: action.value,
},
}
case SET_CUSTOM_GAS_LIMIT:
return {
...newState,
customData: {
...newState.customData,
limit: action.value,
},
}
case SET_CUSTOM_GAS_TOTAL:
return {
...newState,
customData: {
...newState.customData,
total: action.value,
},
}
case SET_CUSTOM_GAS_ERRORS:
return {
...newState,
errors: {
...newState.errors,
...action.value,
},
}
case RESET_CUSTOM_GAS_STATE:
return clone(initState)
default:
return newState
}
}
// Action Creators
export function basicGasEstimatesLoadingStarted () {
return {
type: BASIC_GAS_ESTIMATE_LOADING_STARTED,
}
}
export function basicGasEstimatesLoadingFinished () {
return {
type: BASIC_GAS_ESTIMATE_LOADING_FINISHED,
}
}
export function fetchGasEstimates () {
return (dispatch) => {
dispatch(basicGasEstimatesLoadingStarted())
return 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,
avgWait,
block_time: blockTime,
blockNum,
fast,
fastest,
fastestWait,
fastWait,
safeLow,
safeLowWait,
speed,
}) => {
dispatch(setBasicGasEstimateData({
average,
avgWait,
blockTime,
blockNum,
fast,
fastest,
fastestWait,
fastWait,
safeLow,
safeLowWait,
speed,
}))
dispatch(basicGasEstimatesLoadingFinished())
})
}
}
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 setCustomGasTotal (newTotal) {
return {
type: SET_CUSTOM_GAS_TOTAL,
value: newTotal,
}
}
export function setCustomGasErrors (newErrors) {
return {
type: SET_CUSTOM_GAS_ERRORS,
value: newErrors,
}
}
export function resetCustomGasState () {
return { type: RESET_CUSTOM_GAS_STATE }
}

View File

@ -95,7 +95,7 @@ export function formatCurrency (value, currencyCode) {
const upperCaseCurrencyCode = currencyCode.toUpperCase()
return currencies.find(currency => currency.code === upperCaseCurrencyCode)
? currencyFormatter.format(Number(value), { code: upperCaseCurrencyCode })
? currencyFormatter.format(Number(value), { code: upperCaseCurrencyCode, style: 'currency' })
: value
}

View File

@ -10,7 +10,7 @@ const reduceApp = require('./reducers/app')
const reduceLocale = require('./reducers/locale')
const reduceSend = require('./ducks/send.duck').default
import reduceConfirmTransaction from './ducks/confirm-transaction.duck'
import reduceCustomGas from './ducks/custom-gas'
import reduceGas from './ducks/gas.duck'
window.METAMASK_CACHED_LOG_STATE = null
@ -50,7 +50,7 @@ function rootReducer (state, action) {
state.confirmTransaction = reduceConfirmTransaction(state, action)
state.customGas = reduceCustomGas(state, action)
state.gas = reduceGas(state, action)
window.METAMASK_CACHED_LOG_STATE = state
return state

View File

@ -1,19 +1,191 @@
import { pipe, partialRight } from 'ramda'
import {
getConversionRate,
getGasLimit,
} from '../components/send/send.selectors'
import {
conversionUtil,
multiplyCurrencies,
} from '../conversion-util'
import {
getCurrentCurrency,
} from '../selectors'
import {
formatCurrency,
} from '../helpers/confirm-transaction/util'
import {
calcGasTotal,
} from '../components/send/send.utils'
import { addHexPrefix } from 'ethereumjs-util'
const selectors = {
getCustomGasPrice,
getCustomGasLimit,
getCustomGasErrors,
getCustomGasLimit,
getCustomGasPrice,
getCustomGasTotal,
getRenderableBasicEstimateData,
getBasicGasEstimateLoadingStatus,
}
module.exports = selectors
function getCustomGasPrice (state) {
return state.customGas.price
function getCustomGasErrors (state) {
return state.gas.errors
}
function getCustomGasLimit (state) {
return state.customGas.limit
return state.gas.customData.limit
}
function getCustomGasErrors (state) {
return state.customGas.errors
function getCustomGasPrice (state) {
return state.gas.customData.price
}
function getCustomGasTotal (state) {
return state.gas.customData.total
}
function getBasicGasEstimateLoadingStatus (state) {
return state.gas.basicEstimateIsLoading
}
function apiEstimateModifiedToGWEI (estimate) {
return multiplyCurrencies(estimate, 0.10, {
toNumericBase: 'hex',
multiplicandBase: 10,
multiplierBase: 10,
numberOfDecimals: 9,
})
}
function basicPriceEstimateToETHTotal (estimate, gasLimit) {
return conversionUtil(calcGasTotal(gasLimit, estimate), {
fromNumericBase: 'hex',
toNumericBase: 'dec',
fromDenomination: 'GWEI',
numberOfDecimals: 9,
})
}
function ethTotalToConvertedCurrency (ethTotal, convertedCurrency, conversionRate) {
return conversionUtil(ethTotal, {
fromNumericBase: 'dec',
toNumericBase: 'dec',
fromCurrency: 'ETH',
toCurrency: convertedCurrency,
numberOfDecimals: 2,
conversionRate,
})
}
function formatETHFee (ethFee) {
return ethFee + ' ETH'
}
function getRenderableEthFee (estimate, gasLimit) {
return pipe(
apiEstimateModifiedToGWEI,
partialRight(basicPriceEstimateToETHTotal, [gasLimit]),
formatETHFee
)(estimate, gasLimit)
}
function getRenderableConvertedCurrencyFee (estimate, gasLimit, convertedCurrency, conversionRate) {
return pipe(
apiEstimateModifiedToGWEI,
partialRight(basicPriceEstimateToETHTotal, [gasLimit]),
partialRight(ethTotalToConvertedCurrency, [convertedCurrency, conversionRate]),
partialRight(formatCurrency, [convertedCurrency])
)(estimate, gasLimit, convertedCurrency, conversionRate)
}
function getTimeEstimateInSeconds (blockWaitEstimate, currentBlockTime) {
return multiplyCurrencies(blockWaitEstimate, currentBlockTime, {
toNumericBase: 'dec',
multiplicandBase: 10,
multiplierBase: 10,
numberOfDecimals: 1,
})
}
function formatTimeEstimate (totalSeconds) {
const minutes = Math.floor(totalSeconds / 60)
const seconds = Math.floor(totalSeconds % 60)
const formattedMin = `${minutes ? minutes + ' min' : ''}`
const formattedSec = `${seconds ? seconds + ' sec' : ''}`
const formattedCombined = formattedMin && formattedSec
? `~${formattedMin} ${formattedSec}`
: '~' + [formattedMin, formattedSec].find(t => t)
return formattedCombined
}
function getRenderableTimeEstimate (blockWaitEstimate, currentBlockTime) {
return pipe(
getTimeEstimateInSeconds,
formatTimeEstimate
)(blockWaitEstimate, currentBlockTime)
}
function priceEstimateToWei (priceEstimate) {
return conversionUtil(priceEstimate, {
fromNumericBase: 'hex',
toNumericBase: 'hex',
fromDenomination: 'GWEI',
toDenomination: 'WEI',
numberOfDecimals: 9,
})
}
function getGasPriceInHexWei (price) {
return pipe(
apiEstimateModifiedToGWEI,
priceEstimateToWei,
addHexPrefix
)(price)
}
function getRenderableBasicEstimateData (state) {
if (getBasicGasEstimateLoadingStatus(state)) {
return []
}
const gasLimit = getGasLimit(state)
const conversionRate = getConversionRate(state)
const currentCurrency = getCurrentCurrency(state)
const {
gas: {
basicEstimates: {
safeLow,
average,
fast,
blockTime,
safeLowWait,
avgWait,
fastWait,
},
},
} = state
return [
{
feeInPrimaryCurrency: getRenderableConvertedCurrencyFee(fast, gasLimit, currentCurrency, conversionRate),
feeInSecondaryCurrency: getRenderableEthFee(fast, gasLimit),
timeEstimate: getRenderableTimeEstimate(fastWait, blockTime),
priceInHexWei: getGasPriceInHexWei(fast),
},
{
feeInPrimaryCurrency: getRenderableConvertedCurrencyFee(average, gasLimit, currentCurrency, conversionRate),
feeInSecondaryCurrency: getRenderableEthFee(average, gasLimit),
timeEstimate: getRenderableTimeEstimate(avgWait, blockTime),
priceInHexWei: getGasPriceInHexWei(average),
},
{
feeInPrimaryCurrency: getRenderableConvertedCurrencyFee(safeLow, gasLimit, currentCurrency, conversionRate),
feeInSecondaryCurrency: getRenderableEthFee(safeLow, gasLimit),
timeEstimate: getRenderableTimeEstimate(safeLowWait, blockTime),
priceInHexWei: getGasPriceInHexWei(safeLow),
},
]
}

View File

@ -0,0 +1,140 @@
import assert from 'assert'
import proxyquire from 'proxyquire'
const {
getCustomGasErrors,
getCustomGasLimit,
getCustomGasPrice,
getCustomGasTotal,
getRenderableBasicEstimateData,
} = proxyquire('../custom-gas', {})
describe('custom-gas selectors', () => {
describe('getCustomGasPrice()', () => {
it('should return gas.customData.price', () => {
const mockState = { gas: { customData: { price: 'mockPrice' } } }
assert.equal(getCustomGasPrice(mockState), 'mockPrice')
})
})
describe('getCustomGasLimit()', () => {
it('should return gas.customData.limit', () => {
const mockState = { gas: { customData: { limit: 'mockLimit' } } }
assert.equal(getCustomGasLimit(mockState), 'mockLimit')
})
})
describe('getCustomGasTotal()', () => {
it('should return gas.customData.total', () => {
const mockState = { gas: { customData: { total: 'mockTotal' } } }
assert.equal(getCustomGasTotal(mockState), 'mockTotal')
})
})
describe('getCustomGasErrors()', () => {
it('should return gas.errors', () => {
const mockState = { gas: { errors: 'mockErrors' } }
assert.equal(getCustomGasErrors(mockState), 'mockErrors')
})
})
describe('getRenderableBasicEstimateData()', () => {
const tests = [
{
expectedResult: [
{
feeInPrimaryCurrency: '$0.05',
feeInSecondaryCurrency: '0.00021 ETH',
timeEstimate: '~7 sec',
priceInHexWei: '0x2540be400',
},
{
feeInPrimaryCurrency: '$0.03',
feeInSecondaryCurrency: '0.000105 ETH',
timeEstimate: '~46 sec',
priceInHexWei: '0x12a05f200',
},
{
feeInPrimaryCurrency: '$0.01',
feeInSecondaryCurrency: '0.0000525 ETH',
timeEstimate: '~1 min 33 sec',
priceInHexWei: '0x9502f900',
},
],
mockState: {
metamask: {
conversionRate: 255.71,
currentCurrency: 'usd',
send: {
gasLimit: '0x5208',
},
},
gas: {
basicEstimates: {
blockTime: 14.16326530612245,
safeLow: 25,
safeLowWait: 6.6,
average: 50,
avgWait: 3.3,
fast: 100,
fastWait: 0.5,
},
},
},
},
{
expectedResult: [
{
feeInPrimaryCurrency: '$1.07',
feeInSecondaryCurrency: '0.00042 ETH',
timeEstimate: '~14 sec',
priceInHexWei: '0x4a817c800',
},
{
feeInPrimaryCurrency: '$0.54',
feeInSecondaryCurrency: '0.00021 ETH',
timeEstimate: '~1 min 33 sec',
priceInHexWei: '0x2540be400',
},
{
feeInPrimaryCurrency: '$0.27',
feeInSecondaryCurrency: '0.000105 ETH',
timeEstimate: '~3 min 7 sec',
priceInHexWei: '0x12a05f200',
},
],
mockState: {
metamask: {
conversionRate: 2557.1,
currentCurrency: 'usd',
send: {
gasLimit: '0x5208',
},
},
gas: {
basicEstimates: {
blockTime: 14.16326530612245,
safeLow: 50,
safeLowWait: 13.2,
average: 100,
avgWait: 6.6,
fast: 200,
fastWait: 1.0,
},
},
},
},
]
it('should return renderable data about basic estimates', () => {
tests.forEach(test => {
assert.deepEqual(
getRenderableBasicEstimateData(test.mockState),
test.expectedResult
)
})
})
})
})