mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-11-22 18:00:18 +01:00
Merge branch 'develop' into i5846-ProviderCrashes
This commit is contained in:
commit
3bfd4d1524
@ -197,6 +197,7 @@
|
|||||||
},
|
},
|
||||||
"basicEstimateIsLoading": false,
|
"basicEstimateIsLoading": false,
|
||||||
"gasEstimatesLoading": false,
|
"gasEstimatesLoading": false,
|
||||||
|
"basicPriceAndTimeEstimates": [],
|
||||||
"priceAndTimeEstimates": [
|
"priceAndTimeEstimates": [
|
||||||
{
|
{
|
||||||
"expectedTime": "1374.1168296452973076627",
|
"expectedTime": "1374.1168296452973076627",
|
||||||
|
@ -139,7 +139,8 @@
|
|||||||
"send": {
|
"send": {
|
||||||
"fromDropdownOpen": false,
|
"fromDropdownOpen": false,
|
||||||
"toDropdownOpen": false,
|
"toDropdownOpen": false,
|
||||||
"errors": {}
|
"errors": {},
|
||||||
|
"gasButtonGroupShown": true
|
||||||
},
|
},
|
||||||
"confirmTransaction": {
|
"confirmTransaction": {
|
||||||
"txData": {},
|
"txData": {},
|
||||||
@ -179,6 +180,7 @@
|
|||||||
},
|
},
|
||||||
"basicEstimateIsLoading": false,
|
"basicEstimateIsLoading": false,
|
||||||
"gasEstimatesLoading": false,
|
"gasEstimatesLoading": false,
|
||||||
|
"basicPriceAndTimeEstimates": [],
|
||||||
"priceAndTimeEstimates": [
|
"priceAndTimeEstimates": [
|
||||||
{
|
{
|
||||||
"expectedTime": "1374.1168296452973076627",
|
"expectedTime": "1374.1168296452973076627",
|
||||||
|
@ -69,6 +69,7 @@ describe('MetaMask', function () {
|
|||||||
|
|
||||||
beforeEach(async function () {
|
beforeEach(async function () {
|
||||||
await driver.executeScript(
|
await driver.executeScript(
|
||||||
|
'window.origFetch = window.fetch.bind(window);' +
|
||||||
'window.fetch = ' +
|
'window.fetch = ' +
|
||||||
'(...args) => { ' +
|
'(...args) => { ' +
|
||||||
'if (args[0] === "https://ethgasstation.info/json/ethgasAPI.json") { return ' +
|
'if (args[0] === "https://ethgasstation.info/json/ethgasAPI.json") { return ' +
|
||||||
@ -77,7 +78,7 @@ describe('MetaMask', function () {
|
|||||||
'Promise.resolve({ json: () => Promise.resolve(JSON.parse(\'' + fetchMockResponses.ethGasPredictTable + '\')) }); } else if ' +
|
'Promise.resolve({ json: () => Promise.resolve(JSON.parse(\'' + fetchMockResponses.ethGasPredictTable + '\')) }); } else if ' +
|
||||||
'(args[0] === "https://dev.blockscale.net/api/gasexpress.json") { return ' +
|
'(args[0] === "https://dev.blockscale.net/api/gasexpress.json") { return ' +
|
||||||
'Promise.resolve({ json: () => Promise.resolve(JSON.parse(\'' + fetchMockResponses.gasExpress + '\')) }); } ' +
|
'Promise.resolve({ json: () => Promise.resolve(JSON.parse(\'' + fetchMockResponses.gasExpress + '\')) }); } ' +
|
||||||
'return window.fetch(...args); }'
|
'return window.origFetch(...args); }'
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@ const {
|
|||||||
queryAsync,
|
queryAsync,
|
||||||
findAsync,
|
findAsync,
|
||||||
} = require('../../lib/util')
|
} = require('../../lib/util')
|
||||||
|
const fetchMockResponses = require('../../e2e/beta/fetch-mocks.js')
|
||||||
|
|
||||||
QUnit.module('new ui send flow')
|
QUnit.module('new ui send flow')
|
||||||
|
|
||||||
@ -22,6 +23,19 @@ global.ethQuery = {
|
|||||||
global.ethereumProvider = {}
|
global.ethereumProvider = {}
|
||||||
|
|
||||||
async function runSendFlowTest (assert, done) {
|
async function runSendFlowTest (assert, done) {
|
||||||
|
const tempFetch = global.fetch
|
||||||
|
|
||||||
|
global.fetch = (...args) => {
|
||||||
|
if (args[0] === 'https://ethgasstation.info/json/ethgasAPI.json') {
|
||||||
|
return Promise.resolve({ json: () => Promise.resolve(JSON.parse(fetchMockResponses.ethGasBasic)) })
|
||||||
|
} else if (args[0] === 'https://ethgasstation.info/json/predictTable.json') {
|
||||||
|
return 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)
|
||||||
|
}
|
||||||
|
|
||||||
console.log('*** start runSendFlowTest')
|
console.log('*** start runSendFlowTest')
|
||||||
const selectState = await queryAsync($, 'select')
|
const selectState = await queryAsync($, 'select')
|
||||||
selectState.val('send new ui')
|
selectState.val('send new ui')
|
||||||
@ -129,6 +143,8 @@ async function runSendFlowTest (assert, done) {
|
|||||||
|
|
||||||
const cancelButtonInEdit = await queryAsync($, '.btn-default.btn--large.page-container__footer-button')
|
const cancelButtonInEdit = await queryAsync($, '.btn-default.btn--large.page-container__footer-button')
|
||||||
cancelButtonInEdit[0].click()
|
cancelButtonInEdit[0].click()
|
||||||
|
|
||||||
|
global.fetch = tempFetch
|
||||||
// sendButtonInEdit[0].click()
|
// sendButtonInEdit[0].click()
|
||||||
|
|
||||||
// // TODO: Need a way to mock background so that we can test correct transition from editing to confirm
|
// // TODO: Need a way to mock background so that we can test correct transition from editing to confirm
|
||||||
|
@ -21,6 +21,8 @@ export default class AdvancedTabContent extends Component {
|
|||||||
timeRemaining: PropTypes.string,
|
timeRemaining: PropTypes.string,
|
||||||
gasChartProps: PropTypes.object,
|
gasChartProps: PropTypes.object,
|
||||||
insufficientBalance: PropTypes.bool,
|
insufficientBalance: PropTypes.bool,
|
||||||
|
customPriceIsSafe: PropTypes.bool,
|
||||||
|
isSpeedUp: PropTypes.bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor (props) {
|
constructor (props) {
|
||||||
@ -37,27 +39,62 @@ export default class AdvancedTabContent extends Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
gasInput (value, onChange, min, insufficientBalance, showGWEI) {
|
gasInputError ({ labelKey, insufficientBalance, customPriceIsSafe, isSpeedUp, value }) {
|
||||||
|
let errorText
|
||||||
|
let errorType
|
||||||
|
let isInError = true
|
||||||
|
|
||||||
|
|
||||||
|
if (insufficientBalance) {
|
||||||
|
errorText = 'Insufficient Balance'
|
||||||
|
errorType = 'error'
|
||||||
|
} else if (labelKey === 'gasPrice' && isSpeedUp && value === 0) {
|
||||||
|
errorText = 'Zero gas price on speed up'
|
||||||
|
errorType = 'error'
|
||||||
|
} else if (labelKey === 'gasPrice' && !customPriceIsSafe) {
|
||||||
|
errorText = 'Gas Price Extremely Low'
|
||||||
|
errorType = 'warning'
|
||||||
|
} else {
|
||||||
|
isInError = false
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
isInError,
|
||||||
|
errorText,
|
||||||
|
errorType,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gasInput ({ labelKey, value, onChange, insufficientBalance, showGWEI, customPriceIsSafe, isSpeedUp }) {
|
||||||
|
const {
|
||||||
|
isInError,
|
||||||
|
errorText,
|
||||||
|
errorType,
|
||||||
|
} = this.gasInputError({ labelKey, insufficientBalance, customPriceIsSafe, isSpeedUp, value })
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="advanced-tab__gas-edit-row__input-wrapper">
|
<div className="advanced-tab__gas-edit-row__input-wrapper">
|
||||||
<input
|
<input
|
||||||
className={classnames('advanced-tab__gas-edit-row__input', {
|
className={classnames('advanced-tab__gas-edit-row__input', {
|
||||||
'advanced-tab__gas-edit-row__input--error': insufficientBalance,
|
'advanced-tab__gas-edit-row__input--error': isInError && errorType === 'error',
|
||||||
|
'advanced-tab__gas-edit-row__input--warning': isInError && errorType === 'warning',
|
||||||
})}
|
})}
|
||||||
type="number"
|
type="number"
|
||||||
value={value}
|
value={value}
|
||||||
min={min}
|
|
||||||
onChange={event => onChange(Number(event.target.value))}
|
onChange={event => onChange(Number(event.target.value))}
|
||||||
/>
|
/>
|
||||||
<div className={classnames('advanced-tab__gas-edit-row__input-arrows', {
|
<div className={classnames('advanced-tab__gas-edit-row__input-arrows', {
|
||||||
'advanced-tab__gas-edit-row__input-arrows--error': insufficientBalance,
|
'advanced-tab__gas-edit-row__input--error': isInError && errorType === 'error',
|
||||||
|
'advanced-tab__gas-edit-row__input--warning': isInError && errorType === 'warning',
|
||||||
})}>
|
})}>
|
||||||
<div className="advanced-tab__gas-edit-row__input-arrows__i-wrap" onClick={() => onChange(value + 1)}><i className="fa fa-sm fa-angle-up" /></div>
|
<div className="advanced-tab__gas-edit-row__input-arrows__i-wrap" onClick={() => onChange(value + 1)}><i className="fa fa-sm fa-angle-up" /></div>
|
||||||
<div className="advanced-tab__gas-edit-row__input-arrows__i-wrap" onClick={() => onChange(value - 1)}><i className="fa fa-sm fa-angle-down" /></div>
|
<div className="advanced-tab__gas-edit-row__input-arrows__i-wrap" onClick={() => onChange(value - 1)}><i className="fa fa-sm fa-angle-down" /></div>
|
||||||
</div>
|
</div>
|
||||||
{insufficientBalance && <div className="advanced-tab__gas-edit-row__insufficient-balance">
|
{ isInError
|
||||||
Insufficient Balance
|
? <div className={`advanced-tab__gas-edit-row__${errorType}-text`}>
|
||||||
</div>}
|
{ errorText }
|
||||||
|
</div>
|
||||||
|
: null }
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -83,23 +120,45 @@ export default class AdvancedTabContent extends Component {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
renderGasEditRow (labelKey, ...gasInputArgs) {
|
renderGasEditRow (gasInputArgs) {
|
||||||
return (
|
return (
|
||||||
<div className="advanced-tab__gas-edit-row">
|
<div className="advanced-tab__gas-edit-row">
|
||||||
<div className="advanced-tab__gas-edit-row__label">
|
<div className="advanced-tab__gas-edit-row__label">
|
||||||
{ this.context.t(labelKey) }
|
{ this.context.t(gasInputArgs.labelKey) }
|
||||||
{ this.infoButton(() => {}) }
|
{ this.infoButton(() => {}) }
|
||||||
</div>
|
</div>
|
||||||
{ this.gasInput(...gasInputArgs) }
|
{ this.gasInput(gasInputArgs) }
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
renderGasEditRows (customGasPrice, updateCustomGasPrice, customGasLimit, updateCustomGasLimit, insufficientBalance) {
|
renderGasEditRows ({
|
||||||
|
customGasPrice,
|
||||||
|
updateCustomGasPrice,
|
||||||
|
customGasLimit,
|
||||||
|
updateCustomGasLimit,
|
||||||
|
insufficientBalance,
|
||||||
|
customPriceIsSafe,
|
||||||
|
isSpeedUp,
|
||||||
|
}) {
|
||||||
return (
|
return (
|
||||||
<div className="advanced-tab__gas-edit-rows">
|
<div className="advanced-tab__gas-edit-rows">
|
||||||
{ this.renderGasEditRow('gasPrice', customGasPrice, updateCustomGasPrice, customGasPrice, insufficientBalance, true) }
|
{ this.renderGasEditRow({
|
||||||
{ this.renderGasEditRow('gasLimit', customGasLimit, this.onChangeGasLimit, customGasLimit, insufficientBalance) }
|
labelKey: 'gasPrice',
|
||||||
|
value: customGasPrice,
|
||||||
|
onChange: updateCustomGasPrice,
|
||||||
|
insufficientBalance,
|
||||||
|
customPriceIsSafe,
|
||||||
|
showGWEI: true,
|
||||||
|
isSpeedUp,
|
||||||
|
}) }
|
||||||
|
{ this.renderGasEditRow({
|
||||||
|
labelKey: 'gasLimit',
|
||||||
|
value: customGasLimit,
|
||||||
|
onChange: this.onChangeGasLimit,
|
||||||
|
insufficientBalance,
|
||||||
|
customPriceIsSafe,
|
||||||
|
}) }
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -115,19 +174,23 @@ export default class AdvancedTabContent extends Component {
|
|||||||
totalFee,
|
totalFee,
|
||||||
gasChartProps,
|
gasChartProps,
|
||||||
gasEstimatesLoading,
|
gasEstimatesLoading,
|
||||||
|
customPriceIsSafe,
|
||||||
|
isSpeedUp,
|
||||||
} = this.props
|
} = this.props
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="advanced-tab">
|
<div className="advanced-tab">
|
||||||
{ this.renderDataSummary(totalFee, timeRemaining) }
|
{ this.renderDataSummary(totalFee, timeRemaining) }
|
||||||
<div className="advanced-tab__fee-chart">
|
<div className="advanced-tab__fee-chart">
|
||||||
{ this.renderGasEditRows(
|
{ this.renderGasEditRows({
|
||||||
customGasPrice,
|
customGasPrice,
|
||||||
updateCustomGasPrice,
|
updateCustomGasPrice,
|
||||||
customGasLimit,
|
customGasLimit,
|
||||||
updateCustomGasLimit,
|
updateCustomGasLimit,
|
||||||
insufficientBalance
|
insufficientBalance,
|
||||||
) }
|
customPriceIsSafe,
|
||||||
|
isSpeedUp,
|
||||||
|
}) }
|
||||||
<div className="advanced-tab__fee-chart__title">Live Gas Price Predictions</div>
|
<div className="advanced-tab__fee-chart__title">Live Gas Price Predictions</div>
|
||||||
{!gasEstimatesLoading
|
{!gasEstimatesLoading
|
||||||
? <GasPriceChart {...gasChartProps} updateCustomGasPrice={updateCustomGasPrice} />
|
? <GasPriceChart {...gasChartProps} updateCustomGasPrice={updateCustomGasPrice} />
|
||||||
|
@ -102,11 +102,15 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&__insufficient-balance {
|
&__error-text {
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
color: red;
|
color: red;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&__warning-text {
|
||||||
|
font-size: 12px;
|
||||||
|
color: orange;
|
||||||
|
}
|
||||||
|
|
||||||
&__input-wrapper {
|
&__input-wrapper {
|
||||||
position: relative;
|
position: relative;
|
||||||
@ -128,6 +132,10 @@
|
|||||||
border: 1px solid $red;
|
border: 1px solid $red;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&__input--warning {
|
||||||
|
border: 1px solid $orange;
|
||||||
|
}
|
||||||
|
|
||||||
&__input-arrows {
|
&__input-arrows {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 7px;
|
top: 7px;
|
||||||
@ -169,6 +177,10 @@
|
|||||||
border: 1px solid $red;
|
border: 1px solid $red;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&__input-arrows--warning {
|
||||||
|
border: 1px solid $orange;
|
||||||
|
}
|
||||||
|
|
||||||
input[type="number"]::-webkit-inner-spin-button {
|
input[type="number"]::-webkit-inner-spin-button {
|
||||||
-webkit-appearance: none;
|
-webkit-appearance: none;
|
||||||
-moz-appearance: none;
|
-moz-appearance: none;
|
||||||
|
@ -16,6 +16,7 @@ sinon.spy(AdvancedTabContent.prototype, 'renderGasEditRow')
|
|||||||
sinon.spy(AdvancedTabContent.prototype, 'gasInput')
|
sinon.spy(AdvancedTabContent.prototype, 'gasInput')
|
||||||
sinon.spy(AdvancedTabContent.prototype, 'renderGasEditRows')
|
sinon.spy(AdvancedTabContent.prototype, 'renderGasEditRows')
|
||||||
sinon.spy(AdvancedTabContent.prototype, 'renderDataSummary')
|
sinon.spy(AdvancedTabContent.prototype, 'renderDataSummary')
|
||||||
|
sinon.spy(AdvancedTabContent.prototype, 'gasInputError')
|
||||||
|
|
||||||
describe('AdvancedTabContent Component', function () {
|
describe('AdvancedTabContent Component', function () {
|
||||||
let wrapper
|
let wrapper
|
||||||
@ -29,6 +30,8 @@ describe('AdvancedTabContent Component', function () {
|
|||||||
timeRemaining={21500}
|
timeRemaining={21500}
|
||||||
totalFee={'$0.25'}
|
totalFee={'$0.25'}
|
||||||
insufficientBalance={false}
|
insufficientBalance={false}
|
||||||
|
customPriceIsSafe={true}
|
||||||
|
isSpeedUp={false}
|
||||||
/>, { context: { t: (str1, str2) => str2 ? str1 + str2 : str1 } })
|
/>, { context: { t: (str1, str2) => str2 ? str1 + str2 : str1 } })
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -86,9 +89,15 @@ describe('AdvancedTabContent Component', function () {
|
|||||||
it('should call renderGasEditRows with the expected params', () => {
|
it('should call renderGasEditRows with the expected params', () => {
|
||||||
assert.equal(AdvancedTabContent.prototype.renderGasEditRows.callCount, 1)
|
assert.equal(AdvancedTabContent.prototype.renderGasEditRows.callCount, 1)
|
||||||
const renderGasEditRowArgs = AdvancedTabContent.prototype.renderGasEditRows.getCall(0).args
|
const renderGasEditRowArgs = AdvancedTabContent.prototype.renderGasEditRows.getCall(0).args
|
||||||
assert.deepEqual(renderGasEditRowArgs, [
|
assert.deepEqual(renderGasEditRowArgs, [{
|
||||||
11, propsMethodSpies.updateCustomGasPrice, 23456, propsMethodSpies.updateCustomGasLimit, false,
|
customGasPrice: 11,
|
||||||
])
|
customGasLimit: 23456,
|
||||||
|
insufficientBalance: false,
|
||||||
|
customPriceIsSafe: true,
|
||||||
|
updateCustomGasPrice: propsMethodSpies.updateCustomGasPrice,
|
||||||
|
updateCustomGasLimit: propsMethodSpies.updateCustomGasLimit,
|
||||||
|
isSpeedUp: false,
|
||||||
|
}])
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -124,9 +133,10 @@ describe('AdvancedTabContent Component', function () {
|
|||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
AdvancedTabContent.prototype.gasInput.resetHistory()
|
AdvancedTabContent.prototype.gasInput.resetHistory()
|
||||||
gasEditRow = shallow(wrapper.instance().renderGasEditRow(
|
gasEditRow = shallow(wrapper.instance().renderGasEditRow({
|
||||||
'mockLabelKey', 'argA', 'argB'
|
labelKey: 'mockLabelKey',
|
||||||
))
|
someArg: 'argA',
|
||||||
|
}))
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should render the gas-edit-row root node', () => {
|
it('should render the gas-edit-row root node', () => {
|
||||||
@ -149,7 +159,7 @@ describe('AdvancedTabContent Component', function () {
|
|||||||
|
|
||||||
it('should call this.gasInput with the correct args', () => {
|
it('should call this.gasInput with the correct args', () => {
|
||||||
const gasInputSpyArgs = AdvancedTabContent.prototype.gasInput.args
|
const gasInputSpyArgs = AdvancedTabContent.prototype.gasInput.args
|
||||||
assert.deepEqual(gasInputSpyArgs[0], [ 'argA', 'argB' ])
|
assert.deepEqual(gasInputSpyArgs[0], [ { labelKey: 'mockLabelKey', someArg: 'argA' } ])
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -188,12 +198,22 @@ describe('AdvancedTabContent Component', function () {
|
|||||||
it('should call this.renderGasEditRow twice, with the expected args', () => {
|
it('should call this.renderGasEditRow twice, with the expected args', () => {
|
||||||
const renderGasEditRowSpyArgs = AdvancedTabContent.prototype.renderGasEditRow.args
|
const renderGasEditRowSpyArgs = AdvancedTabContent.prototype.renderGasEditRow.args
|
||||||
assert.equal(renderGasEditRowSpyArgs.length, 2)
|
assert.equal(renderGasEditRowSpyArgs.length, 2)
|
||||||
assert.deepEqual(renderGasEditRowSpyArgs[0].map(String), [
|
assert.deepEqual(renderGasEditRowSpyArgs[0].map(String), [{
|
||||||
'gasPrice', 'mockGasPrice', () => 'mockUpdateCustomGasPriceReturn', 'mockGasPrice', false, true,
|
labelKey: 'gasPrice',
|
||||||
].map(String))
|
value: 'mockGasLimit',
|
||||||
assert.deepEqual(renderGasEditRowSpyArgs[1].map(String), [
|
onChange: () => 'mockOnChangeGasLimit',
|
||||||
'gasLimit', 'mockGasLimit', () => 'mockOnChangeGasLimit', 'mockGasLimit', false,
|
insufficientBalance: false,
|
||||||
].map(String))
|
customPriceIsSafe: true,
|
||||||
|
showGWEI: true,
|
||||||
|
}].map(String))
|
||||||
|
assert.deepEqual(renderGasEditRowSpyArgs[1].map(String), [{
|
||||||
|
labelKey: 'gasPrice',
|
||||||
|
value: 'mockGasPrice',
|
||||||
|
onChange: () => 'mockUpdateCustomGasPriceReturn',
|
||||||
|
insufficientBalance: false,
|
||||||
|
customPriceIsSafe: true,
|
||||||
|
showGWEI: true,
|
||||||
|
}].map(String))
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -219,13 +239,16 @@ describe('AdvancedTabContent Component', function () {
|
|||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
AdvancedTabContent.prototype.renderGasEditRow.resetHistory()
|
AdvancedTabContent.prototype.renderGasEditRow.resetHistory()
|
||||||
gasInput = shallow(wrapper.instance().gasInput(
|
AdvancedTabContent.prototype.gasInputError.resetHistory()
|
||||||
321,
|
gasInput = shallow(wrapper.instance().gasInput({
|
||||||
value => value + 7,
|
labelKey: 'gasPrice',
|
||||||
0,
|
value: 321,
|
||||||
false,
|
onChange: value => value + 7,
|
||||||
8
|
insufficientBalance: false,
|
||||||
))
|
showGWEI: true,
|
||||||
|
customPriceIsSafe: true,
|
||||||
|
isSpeedUp: false,
|
||||||
|
}))
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should render the input-wrapper root node', () => {
|
it('should render the input-wrapper root node', () => {
|
||||||
@ -237,12 +260,6 @@ describe('AdvancedTabContent Component', function () {
|
|||||||
assert(gasInput.children().at(0).hasClass('advanced-tab__gas-edit-row__input'))
|
assert(gasInput.children().at(0).hasClass('advanced-tab__gas-edit-row__input'))
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should pass the correct value min and precision props to the input', () => {
|
|
||||||
const inputProps = gasInput.find('input').props()
|
|
||||||
assert.equal(inputProps.min, 0)
|
|
||||||
assert.equal(inputProps.value, 321)
|
|
||||||
})
|
|
||||||
|
|
||||||
it('should call the passed onChange method with the value of the input onChange event', () => {
|
it('should call the passed onChange method with the value of the input onChange event', () => {
|
||||||
const inputOnChange = gasInput.find('input').props().onChange
|
const inputOnChange = gasInput.find('input').props().onChange
|
||||||
assert.equal(inputOnChange({ target: { value: 8} }), 15)
|
assert.equal(inputOnChange({ target: { value: 8} }), 15)
|
||||||
@ -256,18 +273,92 @@ describe('AdvancedTabContent Component', function () {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it('should call onChange with the value incremented decremented when its onchange method is called', () => {
|
it('should call onChange with the value incremented decremented when its onchange method is called', () => {
|
||||||
gasInput = shallow(wrapper.instance().gasInput(
|
|
||||||
321,
|
|
||||||
value => value + 7,
|
|
||||||
0,
|
|
||||||
8,
|
|
||||||
false
|
|
||||||
))
|
|
||||||
const upArrow = gasInput.find('.advanced-tab__gas-edit-row__input-arrows__i-wrap').at(0)
|
const upArrow = gasInput.find('.advanced-tab__gas-edit-row__input-arrows__i-wrap').at(0)
|
||||||
assert.equal(upArrow.props().onClick(), 329)
|
assert.equal(upArrow.props().onClick(), 329)
|
||||||
const downArrow = gasInput.find('.advanced-tab__gas-edit-row__input-arrows__i-wrap').at(1)
|
const downArrow = gasInput.find('.advanced-tab__gas-edit-row__input-arrows__i-wrap').at(1)
|
||||||
assert.equal(downArrow.props().onClick(), 327)
|
assert.equal(downArrow.props().onClick(), 327)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('should call gasInputError with the expected params', () => {
|
||||||
|
assert.equal(AdvancedTabContent.prototype.gasInputError.callCount, 1)
|
||||||
|
const gasInputErrorArgs = AdvancedTabContent.prototype.gasInputError.getCall(0).args
|
||||||
|
assert.deepEqual(gasInputErrorArgs, [{
|
||||||
|
labelKey: 'gasPrice',
|
||||||
|
insufficientBalance: false,
|
||||||
|
customPriceIsSafe: true,
|
||||||
|
value: 321,
|
||||||
|
isSpeedUp: false,
|
||||||
|
}])
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('gasInputError()', () => {
|
||||||
|
let gasInputError
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
AdvancedTabContent.prototype.renderGasEditRow.resetHistory()
|
||||||
|
gasInputError = wrapper.instance().gasInputError({
|
||||||
|
labelKey: '',
|
||||||
|
insufficientBalance: false,
|
||||||
|
customPriceIsSafe: true,
|
||||||
|
isSpeedUp: false,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should return an insufficientBalance error', () => {
|
||||||
|
const gasInputError = wrapper.instance().gasInputError({
|
||||||
|
labelKey: 'gasPrice',
|
||||||
|
insufficientBalance: true,
|
||||||
|
customPriceIsSafe: true,
|
||||||
|
isSpeedUp: false,
|
||||||
|
value: 1,
|
||||||
|
})
|
||||||
|
assert.deepEqual(gasInputError, {
|
||||||
|
isInError: true,
|
||||||
|
errorText: 'Insufficient Balance',
|
||||||
|
errorType: 'error',
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should return a zero gas on retry error', () => {
|
||||||
|
const gasInputError = wrapper.instance().gasInputError({
|
||||||
|
labelKey: 'gasPrice',
|
||||||
|
insufficientBalance: false,
|
||||||
|
customPriceIsSafe: false,
|
||||||
|
isSpeedUp: true,
|
||||||
|
value: 0,
|
||||||
|
})
|
||||||
|
assert.deepEqual(gasInputError, {
|
||||||
|
isInError: true,
|
||||||
|
errorText: 'Zero gas price on speed up',
|
||||||
|
errorType: 'error',
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should return a low gas warning', () => {
|
||||||
|
const gasInputError = wrapper.instance().gasInputError({
|
||||||
|
labelKey: 'gasPrice',
|
||||||
|
insufficientBalance: false,
|
||||||
|
customPriceIsSafe: false,
|
||||||
|
isSpeedUp: false,
|
||||||
|
value: 1,
|
||||||
|
})
|
||||||
|
assert.deepEqual(gasInputError, {
|
||||||
|
isInError: true,
|
||||||
|
errorText: 'Gas Price Extremely Low',
|
||||||
|
errorType: 'warning',
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should return isInError false if there is no error', () => {
|
||||||
|
gasInputError = wrapper.instance().gasInputError({
|
||||||
|
labelKey: 'gasPrice',
|
||||||
|
insufficientBalance: false,
|
||||||
|
customPriceIsSafe: true,
|
||||||
|
value: 1,
|
||||||
|
})
|
||||||
|
assert.equal(gasInputError.isInError, false)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
})
|
})
|
||||||
|
@ -35,6 +35,9 @@ export default class GasModalPageContainer extends Component {
|
|||||||
PropTypes.string,
|
PropTypes.string,
|
||||||
PropTypes.number,
|
PropTypes.number,
|
||||||
]),
|
]),
|
||||||
|
customPriceIsSafe: PropTypes.bool,
|
||||||
|
isSpeedUp: PropTypes.bool,
|
||||||
|
disableSave: PropTypes.bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
state = {}
|
state = {}
|
||||||
@ -69,6 +72,8 @@ export default class GasModalPageContainer extends Component {
|
|||||||
currentTimeEstimate,
|
currentTimeEstimate,
|
||||||
insufficientBalance,
|
insufficientBalance,
|
||||||
gasEstimatesLoading,
|
gasEstimatesLoading,
|
||||||
|
customPriceIsSafe,
|
||||||
|
isSpeedUp,
|
||||||
}) {
|
}) {
|
||||||
const { transactionFee } = this.props
|
const { transactionFee } = this.props
|
||||||
return (
|
return (
|
||||||
@ -83,6 +88,8 @@ export default class GasModalPageContainer extends Component {
|
|||||||
gasChartProps={gasChartProps}
|
gasChartProps={gasChartProps}
|
||||||
insufficientBalance={insufficientBalance}
|
insufficientBalance={insufficientBalance}
|
||||||
gasEstimatesLoading={gasEstimatesLoading}
|
gasEstimatesLoading={gasEstimatesLoading}
|
||||||
|
customPriceIsSafe={customPriceIsSafe}
|
||||||
|
isSpeedUp={isSpeedUp}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -153,6 +160,7 @@ export default class GasModalPageContainer extends Component {
|
|||||||
onSubmit,
|
onSubmit,
|
||||||
customModalGasPriceInHex,
|
customModalGasPriceInHex,
|
||||||
customModalGasLimitInHex,
|
customModalGasLimitInHex,
|
||||||
|
disableSave,
|
||||||
...tabProps
|
...tabProps
|
||||||
} = this.props
|
} = this.props
|
||||||
|
|
||||||
@ -162,7 +170,7 @@ export default class GasModalPageContainer extends Component {
|
|||||||
title={this.context.t('customGas')}
|
title={this.context.t('customGas')}
|
||||||
subtitle={this.context.t('customGasSubTitle')}
|
subtitle={this.context.t('customGasSubTitle')}
|
||||||
tabsComponent={this.renderTabs(infoRowProps, tabProps)}
|
tabsComponent={this.renderTabs(infoRowProps, tabProps)}
|
||||||
disabled={tabProps.insufficientBalance}
|
disabled={disableSave}
|
||||||
onCancel={() => cancelAndClose()}
|
onCancel={() => cancelAndClose()}
|
||||||
onClose={() => cancelAndClose()}
|
onClose={() => cancelAndClose()}
|
||||||
onSubmit={() => {
|
onSubmit={() => {
|
||||||
|
@ -40,6 +40,7 @@ import {
|
|||||||
getEstimatedGasTimes,
|
getEstimatedGasTimes,
|
||||||
getRenderableBasicEstimateData,
|
getRenderableBasicEstimateData,
|
||||||
getBasicGasEstimateBlockTime,
|
getBasicGasEstimateBlockTime,
|
||||||
|
isCustomPriceSafe,
|
||||||
} from '../../../selectors/custom-gas'
|
} from '../../../selectors/custom-gas'
|
||||||
import {
|
import {
|
||||||
submittedPendingTransactionsSelector,
|
submittedPendingTransactionsSelector,
|
||||||
@ -107,6 +108,7 @@ const mapStateToProps = (state, ownProps) => {
|
|||||||
newTotalFiat,
|
newTotalFiat,
|
||||||
currentTimeEstimate: getRenderableTimeEstimate(customGasPrice, gasPrices, estimatedTimes),
|
currentTimeEstimate: getRenderableTimeEstimate(customGasPrice, gasPrices, estimatedTimes),
|
||||||
blockTime: getBasicGasEstimateBlockTime(state),
|
blockTime: getBasicGasEstimateBlockTime(state),
|
||||||
|
customPriceIsSafe: isCustomPriceSafe(state),
|
||||||
gasPriceButtonGroupProps: {
|
gasPriceButtonGroupProps: {
|
||||||
buttonDataLoading,
|
buttonDataLoading,
|
||||||
defaultActiveButtonIndex: getDefaultActiveButtonIndex(gasButtonInfo, customModalGasPriceInHex),
|
defaultActiveButtonIndex: getDefaultActiveButtonIndex(gasButtonInfo, customModalGasPriceInHex),
|
||||||
@ -167,7 +169,7 @@ const mapDispatchToProps = dispatch => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const mergeProps = (stateProps, dispatchProps, ownProps) => {
|
const mergeProps = (stateProps, dispatchProps, ownProps) => {
|
||||||
const { gasPriceButtonGroupProps, isConfirm, isSpeedUp, txId } = stateProps
|
const { gasPriceButtonGroupProps, isConfirm, txId, isSpeedUp, insufficientBalance, customGasPrice } = stateProps
|
||||||
const {
|
const {
|
||||||
updateCustomGasPrice: dispatchUpdateCustomGasPrice,
|
updateCustomGasPrice: dispatchUpdateCustomGasPrice,
|
||||||
hideGasButtonGroup: dispatchHideGasButtonGroup,
|
hideGasButtonGroup: dispatchHideGasButtonGroup,
|
||||||
@ -208,6 +210,7 @@ const mergeProps = (stateProps, dispatchProps, ownProps) => {
|
|||||||
dispatchHideSidebar()
|
dispatchHideSidebar()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
disableSave: insufficientBalance || (isSpeedUp && customGasPrice === 0),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -78,6 +78,7 @@ describe('GasModalPageContainer Component', function () {
|
|||||||
customGasPriceInHex={'mockCustomGasPriceInHex'}
|
customGasPriceInHex={'mockCustomGasPriceInHex'}
|
||||||
customGasLimitInHex={'mockCustomGasLimitInHex'}
|
customGasLimitInHex={'mockCustomGasLimitInHex'}
|
||||||
insufficientBalance={false}
|
insufficientBalance={false}
|
||||||
|
disableSave={false}
|
||||||
/>, { context: { t: (str1, str2) => str2 ? str1 + str2 : str1 } })
|
/>, { context: { t: (str1, str2) => str2 ? str1 + str2 : str1 } })
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -75,6 +75,7 @@ describe('gas-modal-page-container container', () => {
|
|||||||
gas: {
|
gas: {
|
||||||
basicEstimates: {
|
basicEstimates: {
|
||||||
blockTime: 12,
|
blockTime: 12,
|
||||||
|
safeLow: 2,
|
||||||
},
|
},
|
||||||
customData: {
|
customData: {
|
||||||
limit: 'aaaaaaaa',
|
limit: 'aaaaaaaa',
|
||||||
@ -107,9 +108,10 @@ describe('gas-modal-page-container container', () => {
|
|||||||
blockTime: 12,
|
blockTime: 12,
|
||||||
customModalGasLimitInHex: 'aaaaaaaa',
|
customModalGasLimitInHex: 'aaaaaaaa',
|
||||||
customModalGasPriceInHex: 'ffffffff',
|
customModalGasPriceInHex: 'ffffffff',
|
||||||
|
customPriceIsSafe: true,
|
||||||
gasChartProps: {
|
gasChartProps: {
|
||||||
'currentPrice': 4.294967295,
|
'currentPrice': 4.294967295,
|
||||||
estimatedTimes: ['31', '62', '93', '124'],
|
estimatedTimes: [31, 62, 93, 124],
|
||||||
estimatedTimesMax: '31',
|
estimatedTimesMax: '31',
|
||||||
gasPrices: [3, 4, 5, 6],
|
gasPrices: [3, 4, 5, 6],
|
||||||
gasPricesMax: 6,
|
gasPricesMax: 6,
|
||||||
|
@ -11,7 +11,7 @@ import { formatDate } from '../../util'
|
|||||||
import {
|
import {
|
||||||
fetchBasicGasAndTimeEstimates,
|
fetchBasicGasAndTimeEstimates,
|
||||||
fetchGasEstimates,
|
fetchGasEstimates,
|
||||||
setCustomGasPrice,
|
setCustomGasPriceForRetry,
|
||||||
setCustomGasLimit,
|
setCustomGasLimit,
|
||||||
} from '../../ducks/gas.duck'
|
} from '../../ducks/gas.duck'
|
||||||
|
|
||||||
@ -21,7 +21,7 @@ const mapDispatchToProps = dispatch => {
|
|||||||
fetchGasEstimates: (blockTime) => dispatch(fetchGasEstimates(blockTime)),
|
fetchGasEstimates: (blockTime) => dispatch(fetchGasEstimates(blockTime)),
|
||||||
setSelectedToken: tokenAddress => dispatch(setSelectedToken(tokenAddress)),
|
setSelectedToken: tokenAddress => dispatch(setSelectedToken(tokenAddress)),
|
||||||
retryTransaction: (transaction, gasPrice) => {
|
retryTransaction: (transaction, gasPrice) => {
|
||||||
dispatch(setCustomGasPrice(gasPrice || transaction.txParams.gasPrice))
|
dispatch(setCustomGasPriceForRetry(gasPrice || transaction.txParams.gasPrice))
|
||||||
dispatch(setCustomGasLimit(transaction.txParams.gas))
|
dispatch(setCustomGasLimit(transaction.txParams.gas))
|
||||||
dispatch(showSidebar({
|
dispatch(showSidebar({
|
||||||
transitionName: 'sidebar-left',
|
transitionName: 'sidebar-left',
|
||||||
|
@ -23,6 +23,7 @@ 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'
|
const SET_BASIC_API_ESTIMATES_LAST_RETRIEVED = 'metamask/gas/SET_BASIC_API_ESTIMATES_LAST_RETRIEVED'
|
||||||
|
const SET_BASIC_PRICE_ESTIMATES_LAST_RETRIEVED = 'metamask/gas/SET_BASIC_PRICE_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 = {
|
||||||
@ -49,6 +50,7 @@ const initState = {
|
|||||||
basicPriceAndTimeEstimates: [],
|
basicPriceAndTimeEstimates: [],
|
||||||
priceAndTimeEstimatesLastRetrieved: 0,
|
priceAndTimeEstimatesLastRetrieved: 0,
|
||||||
basicPriceAndTimeEstimatesLastRetrieved: 0,
|
basicPriceAndTimeEstimatesLastRetrieved: 0,
|
||||||
|
basicPriceEstimatesLastRetrieved: 0,
|
||||||
errors: {},
|
errors: {},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -129,6 +131,11 @@ export default function reducer ({ gas: gasState = initState }, action = {}) {
|
|||||||
...newState,
|
...newState,
|
||||||
basicPriceAndTimeEstimatesLastRetrieved: action.value,
|
basicPriceAndTimeEstimatesLastRetrieved: action.value,
|
||||||
}
|
}
|
||||||
|
case SET_BASIC_PRICE_ESTIMATES_LAST_RETRIEVED:
|
||||||
|
return {
|
||||||
|
...newState,
|
||||||
|
basicPriceEstimatesLastRetrieved: action.value,
|
||||||
|
}
|
||||||
case RESET_CUSTOM_DATA:
|
case RESET_CUSTOM_DATA:
|
||||||
return {
|
return {
|
||||||
...newState,
|
...newState,
|
||||||
@ -167,10 +174,17 @@ export function gasEstimatesLoadingFinished () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function fetchBasicGasEstimates () {
|
export function fetchBasicGasEstimates () {
|
||||||
return (dispatch) => {
|
return (dispatch, getState) => {
|
||||||
|
const {
|
||||||
|
basicPriceEstimatesLastRetrieved,
|
||||||
|
basicPriceAndTimeEstimates,
|
||||||
|
} = getState().gas
|
||||||
|
const timeLastRetrieved = basicPriceEstimatesLastRetrieved || loadLocalStorageData('BASIC_PRICE_ESTIMATES_LAST_RETRIEVED') || 0
|
||||||
|
|
||||||
dispatch(basicGasEstimatesLoadingStarted())
|
dispatch(basicGasEstimatesLoadingStarted())
|
||||||
|
|
||||||
return fetch('https://dev.blockscale.net/api/gasexpress.json', {
|
const promiseToFetch = Date.now() - timeLastRetrieved > 75000
|
||||||
|
? fetch('https://dev.blockscale.net/api/gasexpress.json', {
|
||||||
'headers': {},
|
'headers': {},
|
||||||
'referrer': 'https://dev.blockscale.net/api/',
|
'referrer': 'https://dev.blockscale.net/api/',
|
||||||
'referrerPolicy': 'no-referrer-when-downgrade',
|
'referrerPolicy': 'no-referrer-when-downgrade',
|
||||||
@ -195,10 +209,24 @@ export function fetchBasicGasEstimates () {
|
|||||||
blockTime,
|
blockTime,
|
||||||
blockNum,
|
blockNum,
|
||||||
}
|
}
|
||||||
dispatch(setBasicGasEstimateData(basicEstimates))
|
|
||||||
dispatch(basicGasEstimatesLoadingFinished())
|
const timeRetrieved = Date.now()
|
||||||
|
dispatch(setBasicPriceEstimatesLastRetrieved(timeRetrieved))
|
||||||
|
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
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -473,6 +501,13 @@ export function setBasicApiEstimatesLastRetrieved (retrievalTime) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function setBasicPriceEstimatesLastRetrieved (retrievalTime) {
|
||||||
|
return {
|
||||||
|
type: SET_BASIC_PRICE_ESTIMATES_LAST_RETRIEVED,
|
||||||
|
value: retrievalTime,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export function resetCustomGasState () {
|
export function resetCustomGasState () {
|
||||||
return { type: RESET_CUSTOM_GAS_STATE }
|
return { type: RESET_CUSTOM_GAS_STATE }
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,7 @@ const {
|
|||||||
setCustomGasErrors,
|
setCustomGasErrors,
|
||||||
resetCustomGasState,
|
resetCustomGasState,
|
||||||
fetchBasicGasAndTimeEstimates,
|
fetchBasicGasAndTimeEstimates,
|
||||||
|
fetchBasicGasEstimates,
|
||||||
gasEstimatesLoadingStarted,
|
gasEstimatesLoadingStarted,
|
||||||
gasEstimatesLoadingFinished,
|
gasEstimatesLoadingFinished,
|
||||||
setPricesAndTimeEstimates,
|
setPricesAndTimeEstimates,
|
||||||
@ -43,6 +44,7 @@ describe('Gas Duck', () => {
|
|||||||
safeLow: 10,
|
safeLow: 10,
|
||||||
safeLowWait: 'mockSafeLowWait',
|
safeLowWait: 'mockSafeLowWait',
|
||||||
speed: 'mockSpeed',
|
speed: 'mockSpeed',
|
||||||
|
standard: 20,
|
||||||
}
|
}
|
||||||
const mockPredictTableResponse = [
|
const mockPredictTableResponse = [
|
||||||
{ expectedTime: 400, expectedWait: 40, gasprice: 0.25, somethingElse: 'foobar' },
|
{ expectedTime: 400, expectedWait: 40, gasprice: 0.25, somethingElse: 'foobar' },
|
||||||
@ -67,7 +69,7 @@ describe('Gas Duck', () => {
|
|||||||
{ 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 fetchStub = sinon.stub().callsFake((url) => new Promise(resolve => {
|
||||||
const dataToResolve = url.match(/ethgasAPI/)
|
const dataToResolve = url.match(/ethgasAPI|gasexpress/)
|
||||||
? mockEthGasApiResponse
|
? mockEthGasApiResponse
|
||||||
: mockPredictTableResponse
|
: mockPredictTableResponse
|
||||||
resolve({
|
resolve({
|
||||||
@ -83,6 +85,7 @@ describe('Gas Duck', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
|
fetchStub.resetHistory()
|
||||||
global.fetch = tempFetch
|
global.fetch = tempFetch
|
||||||
global.Date.now = tempDateNow
|
global.Date.now = tempDateNow
|
||||||
})
|
})
|
||||||
@ -117,8 +120,7 @@ describe('Gas Duck', () => {
|
|||||||
priceAndTimeEstimatesLastRetrieved: 0,
|
priceAndTimeEstimatesLastRetrieved: 0,
|
||||||
basicPriceAndTimeEstimates: [],
|
basicPriceAndTimeEstimates: [],
|
||||||
basicPriceAndTimeEstimatesLastRetrieved: 0,
|
basicPriceAndTimeEstimatesLastRetrieved: 0,
|
||||||
|
basicPriceEstimatesLastRetrieved: 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'
|
||||||
const BASIC_GAS_ESTIMATE_LOADING_STARTED = 'metamask/gas/BASIC_GAS_ESTIMATE_LOADING_STARTED'
|
const BASIC_GAS_ESTIMATE_LOADING_STARTED = 'metamask/gas/BASIC_GAS_ESTIMATE_LOADING_STARTED'
|
||||||
@ -133,6 +135,7 @@ describe('Gas Duck', () => {
|
|||||||
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'
|
const SET_BASIC_API_ESTIMATES_LAST_RETRIEVED = 'metamask/gas/SET_BASIC_API_ESTIMATES_LAST_RETRIEVED'
|
||||||
|
const SET_BASIC_PRICE_ESTIMATES_LAST_RETRIEVED = 'metamask/gas/SET_BASIC_PRICE_ESTIMATES_LAST_RETRIEVED'
|
||||||
|
|
||||||
describe('GasReducer()', () => {
|
describe('GasReducer()', () => {
|
||||||
it('should initialize state', () => {
|
it('should initialize state', () => {
|
||||||
@ -301,6 +304,59 @@ describe('Gas Duck', () => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe('fetchBasicGasEstimates', () => {
|
||||||
|
const mockDistpatch = sinon.spy()
|
||||||
|
it('should call fetch with the expected params', async () => {
|
||||||
|
await fetchBasicGasEstimates()(mockDistpatch, () => ({ gas: Object.assign(
|
||||||
|
{},
|
||||||
|
initState,
|
||||||
|
{ basicPriceAEstimatesLastRetrieved: 1000000 }
|
||||||
|
) }))
|
||||||
|
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(
|
||||||
|
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 }]
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
describe('fetchBasicGasAndTimeEstimates', () => {
|
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 () => {
|
||||||
|
@ -2,6 +2,7 @@ import { pipe, partialRight } from 'ramda'
|
|||||||
import {
|
import {
|
||||||
conversionUtil,
|
conversionUtil,
|
||||||
multiplyCurrencies,
|
multiplyCurrencies,
|
||||||
|
conversionGreaterThan,
|
||||||
} from '../conversion-util'
|
} from '../conversion-util'
|
||||||
import {
|
import {
|
||||||
getCurrentCurrency,
|
getCurrentCurrency,
|
||||||
@ -38,6 +39,8 @@ const selectors = {
|
|||||||
getRenderableBasicEstimateData,
|
getRenderableBasicEstimateData,
|
||||||
getRenderableEstimateDataForSmallButtonsFromGWEI,
|
getRenderableEstimateDataForSmallButtonsFromGWEI,
|
||||||
priceEstimateToWei,
|
priceEstimateToWei,
|
||||||
|
getSafeLowEstimate,
|
||||||
|
isCustomPriceSafe,
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = selectors
|
module.exports = selectors
|
||||||
@ -96,6 +99,39 @@ function getDefaultActiveButtonIndex (gasButtonInfo, customGasPriceInHex, gasPri
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getSafeLowEstimate (state) {
|
||||||
|
const {
|
||||||
|
gas: {
|
||||||
|
basicEstimates: {
|
||||||
|
safeLow,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
} = state
|
||||||
|
|
||||||
|
return safeLow
|
||||||
|
}
|
||||||
|
|
||||||
|
function isCustomPriceSafe (state) {
|
||||||
|
const safeLow = getSafeLowEstimate(state)
|
||||||
|
const customGasPrice = getCustomGasPrice(state)
|
||||||
|
|
||||||
|
if (!customGasPrice) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
const customPriceSafe = conversionGreaterThan(
|
||||||
|
{
|
||||||
|
value: customGasPrice,
|
||||||
|
fromNumericBase: 'hex',
|
||||||
|
fromDenomination: 'WEI',
|
||||||
|
toDenomination: 'GWEI',
|
||||||
|
},
|
||||||
|
{ value: safeLow, fromNumericBase: 'dec' }
|
||||||
|
)
|
||||||
|
|
||||||
|
return customPriceSafe
|
||||||
|
}
|
||||||
|
|
||||||
function getBasicGasEstimateBlockTime (state) {
|
function getBasicGasEstimateBlockTime (state) {
|
||||||
return state.gas.basicEstimates.blockTime
|
return state.gas.basicEstimates.blockTime
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user