aboutsummaryrefslogtreecommitdiffstats
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/data/mock-state.json1
-rw-r--r--test/e2e/beta/drizzle.spec.js51
-rw-r--r--test/e2e/beta/fetch-mocks.js6
-rw-r--r--test/e2e/beta/from-import-beta-ui.spec.js180
-rw-r--r--test/e2e/beta/helpers.js28
-rw-r--r--test/e2e/beta/metamask-beta-responsive-ui.spec.js291
-rw-r--r--test/e2e/beta/metamask-beta-ui.spec.js588
-rwxr-xr-xtest/e2e/beta/run-drizzle.sh31
-rw-r--r--test/e2e/func.js2
-rw-r--r--test/integration/lib/confirm-sig-requests.js12
-rw-r--r--test/integration/lib/currency-localization.js9
-rw-r--r--test/integration/lib/first-time.js117
-rw-r--r--test/integration/lib/mascara-first-time.js133
-rw-r--r--test/integration/lib/send-new-ui.js78
-rw-r--r--test/integration/lib/tx-list-items.js46
-rw-r--r--test/lib/mock-tx-gen.js1
-rw-r--r--test/mascara.conf.js17
-rw-r--r--test/setup.js2
-rw-r--r--test/unit/actions/config_test.js4
-rw-r--r--test/unit/actions/set_account_label_test.js4
-rw-r--r--test/unit/actions/set_selected_account_test.js4
-rw-r--r--test/unit/actions/tx_test.js2
-rw-r--r--test/unit/actions/view_info_test.js4
-rw-r--r--test/unit/actions/warning_test.js4
-rw-r--r--test/unit/app/buy-eth-url.spec.js11
-rw-r--r--test/unit/app/controllers/address-book-controller.js54
-rw-r--r--test/unit/app/controllers/cached-balances-test.js137
-rw-r--r--test/unit/app/controllers/metamask-controller-test.js1
-rw-r--r--test/unit/app/controllers/preferences-controller-test.js18
-rw-r--r--test/unit/app/controllers/token-rates-controller.js9
-rw-r--r--test/unit/app/controllers/transactions/pending-tx-test.js17
-rw-r--r--test/unit/app/controllers/transactions/tx-controller-test.js142
-rw-r--r--test/unit/balance-formatter-test.js2
-rw-r--r--test/unit/components/binary-renderer-test.js23
-rw-r--r--test/unit/components/bn-as-decimal-input-test.js89
-rw-r--r--test/unit/development/sample-changelog.md2
-rw-r--r--test/unit/migrations/029-test.js38
-rw-r--r--test/unit/migrations/030-test.js37
-rw-r--r--test/unit/migrations/031-test.js56
-rw-r--r--test/unit/nameForAccount_test.js41
-rw-r--r--test/unit/reducers/unlock_vault_test.js4
-rw-r--r--test/unit/responsive/components/dropdown-test.js2
-rw-r--r--test/unit/ui/add-token.spec.js43
-rw-r--r--test/unit/ui/app/actions.spec.js12
-rw-r--r--test/unit/ui/app/components/token-cell.spec.js4
-rw-r--r--test/unit/ui/app/reducers/app.spec.js4
-rw-r--r--test/unit/ui/app/reducers/metamask.spec.js14
-rw-r--r--test/unit/ui/app/selectors.spec.js5
-rw-r--r--test/unit/util_test.js2
49 files changed, 1194 insertions, 1188 deletions
diff --git a/test/data/mock-state.json b/test/data/mock-state.json
index 8deff5531..671697182 100644
--- a/test/data/mock-state.json
+++ b/test/data/mock-state.json
@@ -11,6 +11,7 @@
"name": "Test Account 2"
}
},
+ "cachedBalances": {},
"unapprovedTxs": {
"8393540981007587": {
"id": 8393540981007587,
diff --git a/test/e2e/beta/drizzle.spec.js b/test/e2e/beta/drizzle.spec.js
index a9d72a9ba..309df952c 100644
--- a/test/e2e/beta/drizzle.spec.js
+++ b/test/e2e/beta/drizzle.spec.js
@@ -81,22 +81,6 @@ describe('MetaMask', function () {
})
it('selects the new UI option', async () => {
- try {
- const overlay = await findElement(driver, By.css('.full-flex-height'))
- await driver.wait(until.stalenessOf(overlay))
- } catch (e) {}
-
- let button
- try {
- button = await findElement(driver, By.xpath("//button[contains(text(), 'Try it now')]"))
- } catch (e) {
- await loadExtension(driver, extensionId)
- await delay(largeDelayMs)
- button = await findElement(driver, By.xpath("//button[contains(text(), 'Try it now')]"))
- }
- await button.click()
- await delay(regularDelayMs)
-
// Close all other tabs
const [tab0, tab1, tab2] = await driver.getAllWindowHandles()
await driver.switchTo().window(tab0)
@@ -128,7 +112,7 @@ describe('MetaMask', function () {
await loadExtension(driver, extensionId)
await delay(regularDelayMs)
- const continueBtn = await findElement(driver, By.css('.welcome-screen__button'))
+ const continueBtn = await findElement(driver, By.css('.first-time-flow__button'))
await continueBtn.click()
await delay(regularDelayMs)
})
@@ -136,9 +120,9 @@ describe('MetaMask', function () {
describe('Going through the first time flow', () => {
it('accepts a secure password', async () => {
- const passwordBox = await findElement(driver, By.css('.create-password #create-password'))
- const passwordBoxConfirm = await findElement(driver, By.css('.create-password #confirm-password'))
- const button = await findElement(driver, By.css('.create-password button'))
+ const passwordBox = await findElement(driver, By.css('.first-time-flow__form #create-password'))
+ const passwordBoxConfirm = await findElement(driver, By.css('.first-time-flow__form #confirm-password'))
+ const button = await findElement(driver, By.css('.first-time-flow__form button'))
await passwordBox.sendKeys('correct horse battery staple')
await passwordBoxConfirm.sendKeys('correct horse battery staple')
@@ -147,19 +131,21 @@ describe('MetaMask', function () {
})
it('clicks through the unique image screen', async () => {
- const nextScreen = await findElement(driver, By.css('.unique-image button'))
+ await findElement(driver, By.css('.first-time-flow__unique-image'))
+ const nextScreen = await findElement(driver, By.css('button.first-time-flow__button'))
await nextScreen.click()
await delay(regularDelayMs)
})
it('clicks through the ToS', async () => {
// terms of use
- const canClickThrough = await driver.findElement(By.css('.tou button')).isEnabled()
+ await findElement(driver, By.css('.first-time-flow__markdown'))
+ const canClickThrough = await driver.findElement(By.css('button.first-time-flow__button')).isEnabled()
assert.equal(canClickThrough, false, 'disabled continue button')
const bottomOfTos = await findElement(driver, By.linkText('Attributions'))
await driver.executeScript('arguments[0].scrollIntoView(true)', bottomOfTos)
await delay(regularDelayMs)
- const acceptTos = await findElement(driver, By.css('.tou button'))
+ const acceptTos = await findElement(driver, By.css('button.first-time-flow__button'))
driver.wait(until.elementIsEnabled(acceptTos))
await acceptTos.click()
await delay(regularDelayMs)
@@ -167,17 +153,17 @@ describe('MetaMask', function () {
it('clicks through the privacy notice', async () => {
// privacy notice
- const nextScreen = await findElement(driver, By.css('.tou button'))
+ const nextScreen = await findElement(driver, By.css('button.first-time-flow__button'))
await nextScreen.click()
await delay(regularDelayMs)
})
it('clicks through the phishing notice', async () => {
// phishing notice
- const noticeElement = await driver.findElement(By.css('.markdown'))
+ const noticeElement = await driver.findElement(By.css('.first-time-flow__markdown'))
await driver.executeScript('arguments[0].scrollTop = arguments[0].scrollHeight', noticeElement)
await delay(regularDelayMs)
- const nextScreen = await findElement(driver, By.css('.tou button'))
+ const nextScreen = await findElement(driver, By.css('button.first-time-flow__button'))
await nextScreen.click()
await delay(regularDelayMs)
})
@@ -185,24 +171,23 @@ describe('MetaMask', function () {
let seedPhrase
it('reveals the seed phrase', async () => {
- const byRevealButton = By.css('.backup-phrase__secret-blocker .backup-phrase__reveal-button')
+ const byRevealButton = By.css('.reveal-seed-phrase__secret-blocker .reveal-seed-phrase__reveal-button')
await driver.wait(until.elementLocated(byRevealButton, 10000))
const revealSeedPhraseButton = await findElement(driver, byRevealButton, 10000)
await revealSeedPhraseButton.click()
await delay(regularDelayMs)
- seedPhrase = await driver.findElement(By.css('.backup-phrase__secret-words')).getText()
+ seedPhrase = await driver.findElement(By.css('.reveal-seed-phrase__secret-words')).getText()
assert.equal(seedPhrase.split(' ').length, 12)
await delay(regularDelayMs)
- const nextScreen = await findElement(driver, By.css('.backup-phrase button'))
+ const nextScreen = await findElement(driver, By.css('button.first-time-flow__button'))
await nextScreen.click()
await delay(regularDelayMs)
})
async function clickWordAndWait (word) {
- const xpathClass = 'backup-phrase__confirm-seed-option backup-phrase__confirm-seed-option--unselected'
- const xpath = `//button[@class='${xpathClass}' and contains(text(), '${word}')]`
+ const xpath = `//div[contains(@class, 'confirm-seed-phrase__seed-word--shuffled') and not(contains(@class, 'confirm-seed-phrase__seed-word--selected')) and contains(text(), '${word}')]`
const word0 = await findElement(driver, By.xpath(xpath), 10000)
await word0.click()
@@ -212,13 +197,13 @@ describe('MetaMask', function () {
async function retypeSeedPhrase (words, wasReloaded, count = 0) {
try {
if (wasReloaded) {
- const byRevealButton = By.css('.backup-phrase__secret-blocker .backup-phrase__reveal-button')
+ const byRevealButton = By.css('.reveal-seed-phrase__secret-blocker .reveal-seed-phrase__reveal-button')
await driver.wait(until.elementLocated(byRevealButton, 10000))
const revealSeedPhraseButton = await findElement(driver, byRevealButton, 10000)
await revealSeedPhraseButton.click()
await delay(regularDelayMs)
- const nextScreen = await findElement(driver, By.css('.backup-phrase button'))
+ const nextScreen = await findElement(driver, By.css('button.first-time-flow__button'))
await nextScreen.click()
await delay(regularDelayMs)
}
diff --git a/test/e2e/beta/fetch-mocks.js b/test/e2e/beta/fetch-mocks.js
new file mode 100644
index 000000000..6b885cc10
--- /dev/null
+++ b/test/e2e/beta/fetch-mocks.js
@@ -0,0 +1,6 @@
+module.exports = {
+ ethGasBasic: JSON.stringify({'average': 85.0, 'fastestWait': 0.6, 'fastWait': 0.6, 'fast': 200.0, 'safeLowWait': 4.8, 'blockNum': 6648312, 'avgWait': 4.2, 'block_time': 15.516129032258064, 'speed': 0.7828720873342716, 'fastest': 400.0, 'safeLow': 80.0}),
+ ethGasPredictTable: JSON.stringify([{'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 7.2632423756, 'pct_remaining5m': 0.0, 'sum': 7.029975, 'tx_atabove': 4136.0, 'hashpower_accepting': 10.4166666667, 'hpa_coef2': -0.067, 'total_seen_30m': null, 'int2': 6.9238, 'pct_remaining30m': null, 'gasprice': 1.2, 'pct_mined_5m': 0.0, 'total_seen_5m': 1.0, 'pct_mined_30m': null, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 250.99, 'avgdiff': 0, 'expectedWait': 1000.0, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 7.433788122, 'pct_remaining5m': 0.0, 'sum': 7.01731875, 'tx_atabove': 4136.0, 'hashpower_accepting': 10.9375, 'hpa_coef2': -0.067, 'total_seen_30m': null, 'int2': 6.9238, 'pct_remaining30m': null, 'gasprice': 1.5, 'pct_mined_5m': 0.0, 'total_seen_5m': 84.0, 'pct_mined_30m': null, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 250.99, 'avgdiff': 0, 'expectedWait': 1000.0, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 7.433788122, 'pct_remaining5m': 0.0, 'sum': 7.01731875, 'tx_atabove': 4136.0, 'hashpower_accepting': 10.9375, 'hpa_coef2': -0.067, 'total_seen_30m': null, 'int2': 6.9238, 'pct_remaining30m': null, 'gasprice': 1.7, 'pct_mined_5m': 0.0, 'total_seen_5m': 5.0, 'pct_mined_30m': null, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 250.99, 'avgdiff': 0, 'expectedWait': 1000.0, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 7.4638844302, 'pct_remaining5m': 0.0, 'sum': 7.01731875, 'tx_atabove': 4136.0, 'hashpower_accepting': 10.9375, 'hpa_coef2': -0.067, 'total_seen_30m': null, 'int2': 6.9238, 'pct_remaining30m': null, 'gasprice': 1.8, 'pct_mined_5m': 0.0, 'total_seen_5m': 20.0, 'pct_mined_30m': null, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 250.99, 'avgdiff': 0, 'expectedWait': 1000.0, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 7.4839486356, 'pct_remaining5m': 0.0, 'sum': 7.01731875, 'tx_atabove': 4136.0, 'hashpower_accepting': 10.9375, 'hpa_coef2': -0.067, 'total_seen_30m': null, 'int2': 6.9238, 'pct_remaining30m': null, 'gasprice': 1.9, 'pct_mined_5m': 0.0, 'total_seen_5m': 8.0, 'pct_mined_30m': null, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 250.99, 'avgdiff': 0, 'expectedWait': 1000.0, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 7.7347512039, 'pct_remaining5m': 0.0, 'sum': 7.0046625, 'tx_atabove': 4136.0, 'hashpower_accepting': 11.4583333333, 'hpa_coef2': -0.067, 'total_seen_30m': null, 'int2': 6.9238, 'pct_remaining30m': null, 'gasprice': 2.0, 'pct_mined_5m': 0.0, 'total_seen_5m': 52.0, 'pct_mined_30m': null, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 250.99, 'avgdiff': 0, 'expectedWait': 1000.0, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': 17.0, 'hashpower_accepting2': 7.7447833066, 'pct_remaining5m': 1.0, 'sum': 7.0046625, 'tx_atabove': 4136.0, 'hashpower_accepting': 11.4583333333, 'hpa_coef2': -0.067, 'total_seen_30m': null, 'int2': 6.9238, 'pct_remaining30m': null, 'gasprice': 2.1, 'pct_mined_5m': 0.0, 'total_seen_5m': 97.0, 'pct_mined_30m': null, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 250.99, 'avgdiff': 0, 'expectedWait': 1000.0, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': 20.0, 'hashpower_accepting2': 7.7447833066, 'pct_remaining5m': 1.0, 'sum': 7.0040625, 'tx_atabove': 4135.0, 'hashpower_accepting': 11.4583333333, 'hpa_coef2': -0.067, 'total_seen_30m': 6.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 2.2, 'pct_mined_5m': 0.0, 'total_seen_5m': 433.0, 'pct_mined_30m': 0.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 250.99, 'avgdiff': 0, 'expectedWait': 1000.0, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': 68.0, 'hashpower_accepting2': 7.7447833066, 'pct_remaining5m': 0.0, 'sum': 6.9986625, 'tx_atabove': 4126.0, 'hashpower_accepting': 11.4583333333, 'hpa_coef2': -0.067, 'total_seen_30m': 2.0, 'int2': 6.9238, 'pct_remaining30m': 50.0, 'gasprice': 2.3, 'pct_mined_5m': 0.0, 'total_seen_5m': 14.0, 'pct_mined_30m': 0.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 250.99, 'avgdiff': 0, 'expectedWait': 1000.0, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 7.7447833066, 'pct_remaining5m': 0.0, 'sum': 6.9980625, 'tx_atabove': 4125.0, 'hashpower_accepting': 11.4583333333, 'hpa_coef2': -0.067, 'total_seen_30m': null, 'int2': 6.9238, 'pct_remaining30m': null, 'gasprice': 2.4, 'pct_mined_5m': 0.0, 'total_seen_5m': 4.0, 'pct_mined_30m': null, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 250.99, 'avgdiff': 0, 'expectedWait': 1000.0, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': 20.0, 'hashpower_accepting2': 7.7447833066, 'pct_remaining5m': 37.0, 'sum': 6.9956625, 'tx_atabove': 4121.0, 'hashpower_accepting': 11.4583333333, 'hpa_coef2': -0.067, 'total_seen_30m': 4.0, 'int2': 6.9238, 'pct_remaining30m': 75.0, 'gasprice': 2.5, 'pct_mined_5m': 0.0, 'total_seen_5m': 45.0, 'pct_mined_30m': 0.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 250.99, 'avgdiff': 0, 'expectedWait': 1000.0, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': 79.0, 'hashpower_accepting2': 7.7447833066, 'pct_remaining5m': 0.0, 'sum': 6.9788625, 'tx_atabove': 4093.0, 'hashpower_accepting': 11.4583333333, 'hpa_coef2': -0.067, 'total_seen_30m': 1.0, 'int2': 6.9238, 'pct_remaining30m': 100.0, 'gasprice': 2.6, 'pct_mined_5m': 0.0, 'total_seen_5m': 3.0, 'pct_mined_30m': 0.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 250.99, 'avgdiff': 0, 'expectedWait': 1000.0, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': 27.5, 'hashpower_accepting2': 7.7447833066, 'pct_remaining5m': 100.0, 'sum': 6.9764625, 'tx_atabove': 4089.0, 'hashpower_accepting': 11.4583333333, 'hpa_coef2': -0.067, 'total_seen_30m': null, 'int2': 6.9238, 'pct_remaining30m': null, 'gasprice': 2.7, 'pct_mined_5m': 0.0, 'total_seen_5m': 3.0, 'pct_mined_30m': null, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 250.99, 'avgdiff': 0, 'expectedWait': 1000.0, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': 22.5, 'hashpower_accepting2': 7.7447833066, 'pct_remaining5m': 66.0, 'sum': 6.9740625, 'tx_atabove': 4085.0, 'hashpower_accepting': 11.4583333333, 'hpa_coef2': -0.067, 'total_seen_30m': null, 'int2': 6.9238, 'pct_remaining30m': null, 'gasprice': 2.8, 'pct_mined_5m': 0.0, 'total_seen_5m': 6.0, 'pct_mined_30m': null, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 250.99, 'avgdiff': 0, 'expectedWait': 1000.0, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': 20.0, 'hashpower_accepting2': 7.7548154093, 'pct_remaining5m': 38.0, 'sum': 6.9686625, 'tx_atabove': 4076.0, 'hashpower_accepting': 11.4583333333, 'hpa_coef2': -0.067, 'total_seen_30m': 2.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 2.9, 'pct_mined_5m': 2.0, 'total_seen_5m': 36.0, 'pct_mined_30m': 0.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 250.99, 'avgdiff': 0, 'expectedWait': 1000.0, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': 27.0, 'hashpower_accepting2': 11.5268860353, 'pct_remaining5m': 77.0, 'sum': 6.8307, 'tx_atabove': 4057.0, 'hashpower_accepting': 16.6666666667, 'hpa_coef2': -0.067, 'total_seen_30m': 127.0, 'int2': 6.9238, 'pct_remaining30m': 48.0, 'gasprice': 3.0, 'pct_mined_5m': 0.0, 'total_seen_5m': 322.0, 'pct_mined_30m': 39.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 250.99, 'avgdiff': 0, 'expectedWait': 1000.0, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': 67.0, 'hashpower_accepting2': 11.5268860353, 'pct_remaining5m': 100.0, 'sum': 6.5697, 'tx_atabove': 3622.0, 'hashpower_accepting': 16.6666666667, 'hpa_coef2': -0.067, 'total_seen_30m': 85.0, 'int2': 6.9238, 'pct_remaining30m': 98.0, 'gasprice': 3.1, 'pct_mined_5m': 0.0, 'total_seen_5m': 79.0, 'pct_mined_30m': 0.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 250.99, 'avgdiff': 0, 'expectedWait': 1000.0, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': 71.0, 'hashpower_accepting2': 11.5268860353, 'pct_remaining5m': 100.0, 'sum': 6.4311, 'tx_atabove': 3391.0, 'hashpower_accepting': 16.6666666667, 'hpa_coef2': -0.067, 'total_seen_30m': 7.0, 'int2': 6.9238, 'pct_remaining30m': 100.0, 'gasprice': 3.2, 'pct_mined_5m': 0.0, 'total_seen_5m': 4.0, 'pct_mined_30m': 0.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 250.99, 'avgdiff': 0, 'expectedWait': 1000.0, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': 62.0, 'hashpower_accepting2': 11.5268860353, 'pct_remaining5m': 100.0, 'sum': 6.4209, 'tx_atabove': 3374.0, 'hashpower_accepting': 16.6666666667, 'hpa_coef2': -0.067, 'total_seen_30m': 14.0, 'int2': 6.9238, 'pct_remaining30m': 92.0, 'gasprice': 3.3, 'pct_mined_5m': 0.0, 'total_seen_5m': 7.0, 'pct_mined_30m': 0.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 250.99, 'avgdiff': 0, 'expectedWait': 1000.0, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': 1472.0, 'hashpower_accepting2': 11.5569823435, 'pct_remaining5m': 100.0, 'sum': 6.3951, 'tx_atabove': 3331.0, 'hashpower_accepting': 16.6666666667, 'hpa_coef2': -0.067, 'total_seen_30m': 29.0, 'int2': 6.9238, 'pct_remaining30m': 100.0, 'gasprice': 3.4, 'pct_mined_5m': 0.0, 'total_seen_5m': 27.0, 'pct_mined_30m': 0.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 250.99, 'avgdiff': 0, 'expectedWait': 1000.0, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': 307.0, 'hashpower_accepting2': 11.5670144462, 'pct_remaining5m': 100.0, 'sum': 6.1521, 'tx_atabove': 2926.0, 'hashpower_accepting': 16.6666666667, 'hpa_coef2': -0.067, 'total_seen_30m': null, 'int2': 6.9238, 'pct_remaining30m': null, 'gasprice': 3.7, 'pct_mined_5m': 0.0, 'total_seen_5m': 1.0, 'pct_mined_30m': null, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 250.99, 'avgdiff': 0, 'expectedWait': 1000.0, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': 1399.0, 'hashpower_accepting2': 11.577046549, 'pct_remaining5m': 100.0, 'sum': 6.1395, 'tx_atabove': 2905.0, 'hashpower_accepting': 16.6666666667, 'hpa_coef2': -0.067, 'total_seen_30m': null, 'int2': 6.9238, 'pct_remaining30m': null, 'gasprice': 3.9, 'pct_mined_5m': 0.0, 'total_seen_5m': 1.0, 'pct_mined_30m': null, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 250.99, 'avgdiff': 0, 'expectedWait': 1000.0, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': 1005.0, 'hashpower_accepting2': 11.5971107544, 'pct_remaining5m': 88.0, 'sum': 6.1035, 'tx_atabove': 2845.0, 'hashpower_accepting': 16.6666666667, 'hpa_coef2': -0.067, 'total_seen_30m': 9.0, 'int2': 6.9238, 'pct_remaining30m': 88.0, 'gasprice': 4.0, 'pct_mined_5m': 0.0, 'total_seen_5m': 9.0, 'pct_mined_30m': 0.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 250.99, 'avgdiff': 0, 'expectedWait': 1000.0, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': 1546.0, 'hashpower_accepting2': 11.6171749599, 'pct_remaining5m': null, 'sum': 5.6151, 'tx_atabove': 2031.0, 'hashpower_accepting': 16.6666666667, 'hpa_coef2': -0.067, 'total_seen_30m': 1.0, 'int2': 6.9238, 'pct_remaining30m': 100.0, 'gasprice': 4.1, 'pct_mined_5m': null, 'total_seen_5m': null, 'pct_mined_30m': 0.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 250.99, 'avgdiff': 0, 'expectedWait': 1000.0, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': 1065.0, 'hashpower_accepting2': 11.6171749599, 'pct_remaining5m': 100.0, 'sum': 5.5509, 'tx_atabove': 1924.0, 'hashpower_accepting': 16.6666666667, 'hpa_coef2': -0.067, 'total_seen_30m': null, 'int2': 6.9238, 'pct_remaining30m': null, 'gasprice': 4.3, 'pct_mined_5m': 0.0, 'total_seen_5m': 2.0, 'pct_mined_30m': null, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 250.99, 'avgdiff': 0, 'expectedWait': 1000.0, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': 459.0, 'hashpower_accepting2': 11.6171749599, 'pct_remaining5m': 50.0, 'sum': 5.5137, 'tx_atabove': 1862.0, 'hashpower_accepting': 16.6666666667, 'hpa_coef2': -0.067, 'total_seen_30m': null, 'int2': 6.9238, 'pct_remaining30m': null, 'gasprice': 4.4, 'pct_mined_5m': 0.0, 'total_seen_5m': 2.0, 'pct_mined_30m': null, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 250.99, 'avgdiff': 0, 'expectedWait': 1000.0, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': 298.0, 'hashpower_accepting2': 11.6171749599, 'pct_remaining5m': null, 'sum': 5.4903, 'tx_atabove': 1823.0, 'hashpower_accepting': 16.6666666667, 'hpa_coef2': -0.067, 'total_seen_30m': 1.0, 'int2': 6.9238, 'pct_remaining30m': 100.0, 'gasprice': 4.7, 'pct_mined_5m': null, 'total_seen_5m': null, 'pct_mined_30m': 0.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 250.99, 'avgdiff': 0, 'expectedWait': 1000.0, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': 812.0, 'hashpower_accepting2': 11.6472712681, 'pct_remaining5m': 0.0, 'sum': 5.4831, 'tx_atabove': 1811.0, 'hashpower_accepting': 16.6666666667, 'hpa_coef2': -0.067, 'total_seen_30m': 2.0, 'int2': 6.9238, 'pct_remaining30m': 100.0, 'gasprice': 4.8, 'pct_mined_5m': 0.0, 'total_seen_5m': 1.0, 'pct_mined_30m': 0.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 250.99, 'avgdiff': 0, 'expectedWait': 1000.0, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': 541.0, 'hashpower_accepting2': 11.6472712681, 'pct_remaining5m': 100.0, 'sum': 5.4375, 'tx_atabove': 1735.0, 'hashpower_accepting': 16.6666666667, 'hpa_coef2': -0.067, 'total_seen_30m': null, 'int2': 6.9238, 'pct_remaining30m': null, 'gasprice': 4.9, 'pct_mined_5m': 0.0, 'total_seen_5m': 1.0, 'pct_mined_30m': null, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 250.99, 'avgdiff': 0, 'expectedWait': 1000.0, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': 1134.0, 'hashpower_accepting2': 11.7375601926, 'pct_remaining5m': 100.0, 'sum': 5.41824375, 'tx_atabove': 1724.0, 'hashpower_accepting': 17.1875, 'hpa_coef2': -0.067, 'total_seen_30m': 6.0, 'int2': 6.9238, 'pct_remaining30m': 100.0, 'gasprice': 5.0, 'pct_mined_5m': 0.0, 'total_seen_5m': 5.0, 'pct_mined_30m': 0.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 250.99, 'avgdiff': 0, 'expectedWait': 1000.0, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': 1958.0, 'hashpower_accepting2': 11.7676565008, 'pct_remaining5m': null, 'sum': 4.9567875, 'tx_atabove': 976.0, 'hashpower_accepting': 17.7083333333, 'hpa_coef2': -0.067, 'total_seen_30m': 1.0, 'int2': 6.9238, 'pct_remaining30m': 100.0, 'gasprice': 5.2, 'pct_mined_5m': null, 'total_seen_5m': null, 'pct_mined_30m': 0.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 250.99, 'avgdiff': 0, 'expectedWait': 1000.0, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': 1203.5, 'hashpower_accepting2': 11.8077849117, 'pct_remaining5m': null, 'sum': 4.9507875, 'tx_atabove': 966.0, 'hashpower_accepting': 17.7083333333, 'hpa_coef2': -0.067, 'total_seen_30m': 1.0, 'int2': 6.9238, 'pct_remaining30m': 100.0, 'gasprice': 5.3, 'pct_mined_5m': null, 'total_seen_5m': null, 'pct_mined_30m': 0.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 250.99, 'avgdiff': 0, 'expectedWait': 1000.0, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': 677.5, 'hashpower_accepting2': 11.8378812199, 'pct_remaining5m': null, 'sum': 4.9141875, 'tx_atabove': 905.0, 'hashpower_accepting': 17.7083333333, 'hpa_coef2': -0.067, 'total_seen_30m': 1.0, 'int2': 6.9238, 'pct_remaining30m': 100.0, 'gasprice': 5.5, 'pct_mined_5m': null, 'total_seen_5m': null, 'pct_mined_30m': 0.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 250.99, 'avgdiff': 0, 'expectedWait': 1000.0, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': 3.0, 'hashpower_accepting2': 13.3928571429, 'pct_remaining5m': 0.0, 'sum': 3.16120625, 'tx_atabove': 832.0, 'hashpower_accepting': 20.3125, 'hpa_coef2': -0.067, 'total_seen_30m': 9.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 6.0, 'pct_mined_5m': 100.0, 'total_seen_5m': 12.0, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 5.92, 'avgdiff': 1, 'expectedWait': 23.5990451154, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 14.0248796148, 'pct_remaining5m': 0.0, 'sum': 3.10120625, 'tx_atabove': 732.0, 'hashpower_accepting': 20.3125, 'hpa_coef2': -0.067, 'total_seen_30m': null, 'int2': 6.9238, 'pct_remaining30m': null, 'gasprice': 6.1, 'pct_mined_5m': 100.0, 'total_seen_5m': 1.0, 'pct_mined_30m': null, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 5.58, 'avgdiff': 1, 'expectedWait': 22.2247437161, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': 0.0, 'hashpower_accepting2': 14.1753611557, 'pct_remaining5m': 0.0, 'sum': 3.09640625, 'tx_atabove': 724.0, 'hashpower_accepting': 20.3125, 'hpa_coef2': -0.067, 'total_seen_30m': 3.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 6.2, 'pct_mined_5m': 100.0, 'total_seen_5m': 3.0, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 5.55, 'avgdiff': 1, 'expectedWait': 22.1183205662, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 14.3459069021, 'pct_remaining5m': 0.0, 'sum': 3.09580625, 'tx_atabove': 723.0, 'hashpower_accepting': 20.3125, 'hpa_coef2': -0.067, 'total_seen_30m': null, 'int2': 6.9238, 'pct_remaining30m': null, 'gasprice': 6.3, 'pct_mined_5m': 100.0, 'total_seen_5m': 4.0, 'pct_mined_30m': null, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 5.55, 'avgdiff': 1, 'expectedWait': 22.1050535543, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 14.3960674157, 'pct_remaining5m': 0.0, 'sum': 3.09460625, 'tx_atabove': 721.0, 'hashpower_accepting': 20.3125, 'hpa_coef2': -0.067, 'total_seen_30m': 1.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 6.4, 'pct_mined_5m': 100.0, 'total_seen_5m': 1.0, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 5.54, 'avgdiff': 1, 'expectedWait': 22.0785433993, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 14.5465489567, 'pct_remaining5m': 0.0, 'sum': 3.09460625, 'tx_atabove': 721.0, 'hashpower_accepting': 20.3125, 'hpa_coef2': -0.067, 'total_seen_30m': 1.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 6.5, 'pct_mined_5m': 100.0, 'total_seen_5m': 3.0, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 5.54, 'avgdiff': 1, 'expectedWait': 22.0785433993, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 14.5666131621, 'pct_remaining5m': null, 'sum': 3.09460625, 'tx_atabove': 721.0, 'hashpower_accepting': 20.3125, 'hpa_coef2': -0.067, 'total_seen_30m': 1.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 6.6, 'pct_mined_5m': null, 'total_seen_5m': null, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 5.54, 'avgdiff': 1, 'expectedWait': 22.0785433993, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': 2.0, 'hashpower_accepting2': 14.6769662921, 'pct_remaining5m': null, 'sum': 3.09460625, 'tx_atabove': 721.0, 'hashpower_accepting': 20.3125, 'hpa_coef2': -0.067, 'total_seen_30m': 2.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 6.7, 'pct_mined_5m': null, 'total_seen_5m': null, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 5.54, 'avgdiff': 1, 'expectedWait': 22.0785433993, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 14.7070626003, 'pct_remaining5m': null, 'sum': 3.09400625, 'tx_atabove': 720.0, 'hashpower_accepting': 20.3125, 'hpa_coef2': -0.067, 'total_seen_30m': 1.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 6.8, 'pct_mined_5m': null, 'total_seen_5m': null, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 5.54, 'avgdiff': 1, 'expectedWait': 22.0653002466, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 14.7271268058, 'pct_remaining5m': 0.0, 'sum': 3.09400625, 'tx_atabove': 720.0, 'hashpower_accepting': 20.3125, 'hpa_coef2': -0.067, 'total_seen_30m': null, 'int2': 6.9238, 'pct_remaining30m': null, 'gasprice': 6.9, 'pct_mined_5m': 100.0, 'total_seen_5m': 2.0, 'pct_mined_30m': null, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 5.54, 'avgdiff': 1, 'expectedWait': 22.0653002466, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': 3.0, 'hashpower_accepting2': 15.4795345104, 'pct_remaining5m': 0.0, 'sum': 3.06749375, 'tx_atabove': 718.0, 'hashpower_accepting': 21.3541666667, 'hpa_coef2': -0.067, 'total_seen_30m': 11.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 7.0, 'pct_mined_5m': 100.0, 'total_seen_5m': 6.0, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 5.39, 'avgdiff': 1, 'expectedWait': 21.4879808804, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': 0.0, 'hashpower_accepting2': 15.5898876404, 'pct_remaining5m': 0.0, 'sum': 3.06089375, 'tx_atabove': 707.0, 'hashpower_accepting': 21.3541666667, 'hpa_coef2': -0.067, 'total_seen_30m': 4.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 7.1, 'pct_mined_5m': 100.0, 'total_seen_5m': 2.0, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 5.36, 'avgdiff': 1, 'expectedWait': 21.3466271869, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 15.5999197432, 'pct_remaining5m': null, 'sum': 3.06029375, 'tx_atabove': 706.0, 'hashpower_accepting': 21.3541666667, 'hpa_coef2': -0.067, 'total_seen_30m': 1.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 7.2, 'pct_mined_5m': null, 'total_seen_5m': null, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 5.35, 'avgdiff': 1, 'expectedWait': 21.3338230522, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': 0.0, 'hashpower_accepting2': 15.8507223114, 'pct_remaining5m': 0.0, 'sum': 3.05969375, 'tx_atabove': 705.0, 'hashpower_accepting': 21.3541666667, 'hpa_coef2': -0.067, 'total_seen_30m': 5.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 7.6, 'pct_mined_5m': 100.0, 'total_seen_5m': 2.0, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 5.35, 'avgdiff': 1, 'expectedWait': 21.3210265977, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 15.8607544141, 'pct_remaining5m': null, 'sum': 3.05909375, 'tx_atabove': 704.0, 'hashpower_accepting': 21.3541666667, 'hpa_coef2': -0.067, 'total_seen_30m': 1.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 7.7, 'pct_mined_5m': null, 'total_seen_5m': null, 'pct_mined_30m': 0.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 5.35, 'avgdiff': 1, 'expectedWait': 21.3082378187, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': 0.0, 'hashpower_accepting2': 18.86035313, 'pct_remaining5m': 0.0, 'sum': 2.8933625, 'tx_atabove': 702.0, 'hashpower_accepting': 28.125, 'hpa_coef2': -0.067, 'total_seen_30m': 30.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 8.0, 'pct_mined_5m': 100.0, 'total_seen_5m': 37.0, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 4.53, 'avgdiff': 1, 'expectedWait': 18.053913939, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': 1.0, 'hashpower_accepting2': 19.1011235955, 'pct_remaining5m': 0.0, 'sum': 2.85250625, 'tx_atabove': 655.0, 'hashpower_accepting': 28.6458333333, 'hpa_coef2': -0.067, 'total_seen_30m': 1.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 8.1, 'pct_mined_5m': 100.0, 'total_seen_5m': 5.0, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 4.35, 'avgdiff': 1, 'expectedWait': 17.331163684, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 19.1613162119, 'pct_remaining5m': 0.0, 'sum': 2.84890625, 'tx_atabove': 649.0, 'hashpower_accepting': 28.6458333333, 'hpa_coef2': -0.067, 'total_seen_30m': 1.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 8.2, 'pct_mined_5m': 100.0, 'total_seen_5m': 3.0, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 4.33, 'avgdiff': 1, 'expectedWait': 17.268883666, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 19.231540931, 'pct_remaining5m': 0.0, 'sum': 2.8097375, 'tx_atabove': 647.0, 'hashpower_accepting': 30.2083333333, 'hpa_coef2': -0.067, 'total_seen_30m': null, 'int2': 6.9238, 'pct_remaining30m': null, 'gasprice': 8.4, 'pct_mined_5m': 100.0, 'total_seen_5m': 6.0, 'pct_mined_30m': null, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 4.17, 'avgdiff': 1, 'expectedWait': 16.6055586875, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': 1.0, 'hashpower_accepting2': 19.5224719101, 'pct_remaining5m': 0.0, 'sum': 2.777225, 'tx_atabove': 635.0, 'hashpower_accepting': 31.25, 'hpa_coef2': -0.067, 'total_seen_30m': 7.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 8.5, 'pct_mined_5m': 100.0, 'total_seen_5m': 12.0, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 4.03, 'avgdiff': 1, 'expectedWait': 16.0743526708, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': 0.0, 'hashpower_accepting2': 19.7331460674, 'pct_remaining5m': 0.0, 'sum': 2.774225, 'tx_atabove': 630.0, 'hashpower_accepting': 31.25, 'hpa_coef2': -0.067, 'total_seen_30m': 5.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 8.6, 'pct_mined_5m': 100.0, 'total_seen_5m': 1.0, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 4.02, 'avgdiff': 1, 'expectedWait': 16.0262018751, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 19.8033707865, 'pct_remaining5m': 0.0, 'sum': 2.72905625, 'tx_atabove': 618.0, 'hashpower_accepting': 32.8125, 'hpa_coef2': -0.067, 'total_seen_30m': 1.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 8.8, 'pct_mined_5m': 100.0, 'total_seen_5m': 1.0, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 3.84, 'avgdiff': 1, 'expectedWait': 15.3184234339, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 19.9638844302, 'pct_remaining5m': 0.0, 'sum': 2.6954, 'tx_atabove': 583.0, 'hashpower_accepting': 33.3333333333, 'hpa_coef2': -0.067, 'total_seen_30m': 1.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 8.9, 'pct_mined_5m': 100.0, 'total_seen_5m': 6.0, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 3.72, 'avgdiff': 1, 'expectedWait': 14.8114421454, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': 0.0, 'hashpower_accepting2': 23.6155698234, 'pct_remaining5m': 0.0, 'sum': 2.3937875, 'tx_atabove': 460.0, 'hashpower_accepting': 42.7083333333, 'hpa_coef2': -0.067, 'total_seen_30m': 43.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 9.0, 'pct_mined_5m': 100.0, 'total_seen_5m': 120.0, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 2.75, 'avgdiff': 1, 'expectedWait': 10.9549071782, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 24.0268860353, 'pct_remaining5m': 0.0, 'sum': 2.30313125, 'tx_atabove': 330.0, 'hashpower_accepting': 43.2291666667, 'hpa_coef2': -0.067, 'total_seen_30m': 2.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 9.1, 'pct_mined_5m': 100.0, 'total_seen_5m': 23.0, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 2.51, 'avgdiff': 1, 'expectedWait': 10.0054630618, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': 0.0, 'hashpower_accepting2': 24.1472712681, 'pct_remaining5m': 0.0, 'sum': 2.287475, 'tx_atabove': 325.0, 'hashpower_accepting': 43.75, 'hpa_coef2': -0.067, 'total_seen_30m': null, 'int2': 6.9238, 'pct_remaining30m': null, 'gasprice': 9.2, 'pct_mined_5m': 100.0, 'total_seen_5m': 3.0, 'pct_mined_30m': null, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 2.47, 'avgdiff': 1, 'expectedWait': 9.8500349165, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 24.2174959872, 'pct_remaining5m': 0.0, 'sum': 2.2609625, 'tx_atabove': 323.0, 'hashpower_accepting': 44.7916666667, 'hpa_coef2': -0.067, 'total_seen_30m': null, 'int2': 6.9238, 'pct_remaining30m': null, 'gasprice': 9.3, 'pct_mined_5m': 100.0, 'total_seen_5m': 1.0, 'pct_mined_30m': null, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 2.41, 'avgdiff': 1, 'expectedWait': 9.5923173304, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 24.3880417335, 'pct_remaining5m': 0.0, 'sum': 2.22239375, 'tx_atabove': 322.0, 'hashpower_accepting': 46.3541666667, 'hpa_coef2': -0.067, 'total_seen_30m': 1.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 9.4, 'pct_mined_5m': 100.0, 'total_seen_5m': 7.0, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 2.32, 'avgdiff': 1, 'expectedWait': 9.2293973144, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': 1.0, 'hashpower_accepting2': 24.5284911717, 'pct_remaining5m': 0.0, 'sum': 2.2091375, 'tx_atabove': 321.0, 'hashpower_accepting': 46.875, 'hpa_coef2': -0.067, 'total_seen_30m': 5.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 9.5, 'pct_mined_5m': 100.0, 'total_seen_5m': 3.0, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 2.29, 'avgdiff': 1, 'expectedWait': 9.1078574773, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 24.7391653291, 'pct_remaining5m': 0.0, 'sum': 2.2073375, 'tx_atabove': 318.0, 'hashpower_accepting': 46.875, 'hpa_coef2': -0.067, 'total_seen_30m': 9.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 9.6, 'pct_mined_5m': 100.0, 'total_seen_5m': 8.0, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 2.28, 'avgdiff': 1, 'expectedWait': 9.0914780797, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 24.9699036918, 'pct_remaining5m': 0.0, 'sum': 2.182025, 'tx_atabove': 318.0, 'hashpower_accepting': 47.9166666667, 'hpa_coef2': -0.067, 'total_seen_30m': 1.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 9.7, 'pct_mined_5m': 88.0, 'total_seen_5m': 9.0, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 2.22, 'avgdiff': 1, 'expectedWait': 8.8642381788, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': 2.0, 'hashpower_accepting2': 25.1203852327, 'pct_remaining5m': 0.0, 'sum': 2.16936875, 'tx_atabove': 318.0, 'hashpower_accepting': 48.4375, 'hpa_coef2': -0.067, 'total_seen_30m': 6.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 9.8, 'pct_mined_5m': 75.0, 'total_seen_5m': 4.0, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 2.2, 'avgdiff': 1, 'expectedWait': 8.7527571186, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 25.1705457464, 'pct_remaining5m': 0.0, 'sum': 2.1561125, 'tx_atabove': 317.0, 'hashpower_accepting': 48.9583333333, 'hpa_coef2': -0.067, 'total_seen_30m': 1.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 9.9, 'pct_mined_5m': 100.0, 'total_seen_5m': 1.0, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 2.17, 'avgdiff': 1, 'expectedWait': 8.637494048, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': 0.0, 'hashpower_accepting2': 36.3864365971, 'pct_remaining5m': 0.0, 'sum': 1.769825, 'tx_atabove': 306.0, 'hashpower_accepting': 64.5833333333, 'hpa_coef2': -0.067, 'total_seen_30m': 353.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 10.0, 'pct_mined_5m': 99.0, 'total_seen_5m': 245.0, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 1.47, 'avgdiff': 1, 'expectedWait': 5.8698260519, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 36.536918138, 'pct_remaining5m': 0.0, 'sum': 1.733225, 'tx_atabove': 245.0, 'hashpower_accepting': 64.5833333333, 'hpa_coef2': -0.067, 'total_seen_30m': 7.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 10.1, 'pct_mined_5m': 100.0, 'total_seen_5m': 2.0, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 1.42, 'avgdiff': 1, 'expectedWait': 5.658874382, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 36.7576243981, 'pct_remaining5m': 0.0, 'sum': 1.733225, 'tx_atabove': 245.0, 'hashpower_accepting': 64.5833333333, 'hpa_coef2': -0.067, 'total_seen_30m': 6.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 10.2, 'pct_mined_5m': 100.0, 'total_seen_5m': 2.0, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 1.42, 'avgdiff': 1, 'expectedWait': 5.658874382, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': 0.0, 'hashpower_accepting2': 36.8378812199, 'pct_remaining5m': 0.0, 'sum': 1.732625, 'tx_atabove': 244.0, 'hashpower_accepting': 64.5833333333, 'hpa_coef2': -0.067, 'total_seen_30m': 2.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 10.3, 'pct_mined_5m': 100.0, 'total_seen_5m': 3.0, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 1.42, 'avgdiff': 1, 'expectedWait': 5.6554800758, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 36.8679775281, 'pct_remaining5m': 0.0, 'sum': 1.732025, 'tx_atabove': 243.0, 'hashpower_accepting': 64.5833333333, 'hpa_coef2': -0.067, 'total_seen_30m': 1.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 10.4, 'pct_mined_5m': 100.0, 'total_seen_5m': 2.0, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 1.42, 'avgdiff': 1, 'expectedWait': 5.6520878055, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': 1.0, 'hashpower_accepting2': 37.8109951846, 'pct_remaining5m': 0.0, 'sum': 1.69405625, 'tx_atabove': 243.0, 'hashpower_accepting': 66.1458333333, 'hpa_coef2': -0.067, 'total_seen_30m': 12.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 10.5, 'pct_mined_5m': 100.0, 'total_seen_5m': 53.0, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 1.37, 'avgdiff': 1, 'expectedWait': 5.4415081179, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 37.871187801, 'pct_remaining5m': 0.0, 'sum': 1.69285625, 'tx_atabove': 241.0, 'hashpower_accepting': 66.1458333333, 'hpa_coef2': -0.067, 'total_seen_30m': 1.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 10.7, 'pct_mined_5m': 100.0, 'total_seen_5m': 2.0, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 1.36, 'avgdiff': 1, 'expectedWait': 5.4349822245, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': 0.0, 'hashpower_accepting2': 38.1019261637, 'pct_remaining5m': 0.0, 'sum': 1.69285625, 'tx_atabove': 241.0, 'hashpower_accepting': 66.1458333333, 'hpa_coef2': -0.067, 'total_seen_30m': 1.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 10.8, 'pct_mined_5m': 100.0, 'total_seen_5m': 6.0, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 1.36, 'avgdiff': 1, 'expectedWait': 5.4349822245, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 38.1821829856, 'pct_remaining5m': 0.0, 'sum': 1.68565625, 'tx_atabove': 229.0, 'hashpower_accepting': 66.1458333333, 'hpa_coef2': -0.067, 'total_seen_30m': 1.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 10.9, 'pct_mined_5m': 100.0, 'total_seen_5m': 3.0, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 1.35, 'avgdiff': 1, 'expectedWait': 5.3959908897, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': 0.0, 'hashpower_accepting2': 40.7002407705, 'pct_remaining5m': 0.0, 'sum': 1.520525, 'tx_atabove': 228.0, 'hashpower_accepting': 72.9166666667, 'hpa_coef2': -0.067, 'total_seen_30m': 84.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 11.0, 'pct_mined_5m': 100.0, 'total_seen_5m': 84.0, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 1.15, 'avgdiff': 1, 'expectedWait': 4.5746262436, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 40.8206260032, 'pct_remaining5m': 0.0, 'sum': 1.507325, 'tx_atabove': 206.0, 'hashpower_accepting': 72.9166666667, 'hpa_coef2': -0.067, 'total_seen_30m': 5.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 11.1, 'pct_mined_5m': 100.0, 'total_seen_5m': 4.0, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 1.13, 'avgdiff': 1, 'expectedWait': 4.5146379708, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 40.8908507223, 'pct_remaining5m': 0.0, 'sum': 1.507325, 'tx_atabove': 206.0, 'hashpower_accepting': 72.9166666667, 'hpa_coef2': -0.067, 'total_seen_30m': 2.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 11.2, 'pct_mined_5m': 100.0, 'total_seen_5m': 2.0, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 1.13, 'avgdiff': 1, 'expectedWait': 4.5146379708, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 41.4024879615, 'pct_remaining5m': 0.0, 'sum': 1.49466875, 'tx_atabove': 206.0, 'hashpower_accepting': 73.4375, 'hpa_coef2': -0.067, 'total_seen_30m': 15.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 11.4, 'pct_mined_5m': 100.0, 'total_seen_5m': 2.0, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 1.12, 'avgdiff': 1, 'expectedWait': 4.4578596422, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 41.4827447833, 'pct_remaining5m': 0.0, 'sum': 1.49466875, 'tx_atabove': 206.0, 'hashpower_accepting': 73.4375, 'hpa_coef2': -0.067, 'total_seen_30m': 2.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 11.5, 'pct_mined_5m': 100.0, 'total_seen_5m': 2.0, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 1.12, 'avgdiff': 1, 'expectedWait': 4.4578596422, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 41.6131621188, 'pct_remaining5m': 0.0, 'sum': 1.49406875, 'tx_atabove': 205.0, 'hashpower_accepting': 73.4375, 'hpa_coef2': -0.067, 'total_seen_30m': 8.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 11.6, 'pct_mined_5m': 100.0, 'total_seen_5m': 1.0, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 1.12, 'avgdiff': 1, 'expectedWait': 4.4551857287, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 41.6332263242, 'pct_remaining5m': 0.0, 'sum': 1.49406875, 'tx_atabove': 205.0, 'hashpower_accepting': 73.4375, 'hpa_coef2': -0.067, 'total_seen_30m': 1.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 11.7, 'pct_mined_5m': 100.0, 'total_seen_5m': 1.0, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 1.12, 'avgdiff': 1, 'expectedWait': 4.4551857287, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 41.753611557, 'pct_remaining5m': 0.0, 'sum': 1.49406875, 'tx_atabove': 205.0, 'hashpower_accepting': 73.4375, 'hpa_coef2': -0.067, 'total_seen_30m': 2.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 11.8, 'pct_mined_5m': 100.0, 'total_seen_5m': 6.0, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 1.12, 'avgdiff': 1, 'expectedWait': 4.4551857287, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 41.7736757624, 'pct_remaining5m': null, 'sum': 1.49406875, 'tx_atabove': 205.0, 'hashpower_accepting': 73.4375, 'hpa_coef2': -0.067, 'total_seen_30m': 2.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 11.9, 'pct_mined_5m': null, 'total_seen_5m': null, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 1.12, 'avgdiff': 1, 'expectedWait': 4.4551857287, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': 1.0, 'hashpower_accepting2': 44.7030497592, 'pct_remaining5m': 0.0, 'sum': 1.41813125, 'tx_atabove': 205.0, 'hashpower_accepting': 76.5625, 'hpa_coef2': -0.067, 'total_seen_30m': 96.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 12.0, 'pct_mined_5m': 100.0, 'total_seen_5m': 39.0, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 1.04, 'avgdiff': 1, 'expectedWait': 4.1293964158, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 44.9036918138, 'pct_remaining5m': 0.0, 'sum': 1.399475, 'tx_atabove': 195.0, 'hashpower_accepting': 77.0833333333, 'hpa_coef2': -0.067, 'total_seen_30m': 11.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 12.1, 'pct_mined_5m': 100.0, 'total_seen_5m': 6.0, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 1.02, 'avgdiff': 1, 'expectedWait': 4.0530715456, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': 0.0, 'hashpower_accepting2': 45.0341091493, 'pct_remaining5m': null, 'sum': 1.38681875, 'tx_atabove': 195.0, 'hashpower_accepting': 77.6041666667, 'hpa_coef2': -0.067, 'total_seen_30m': 3.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 12.2, 'pct_mined_5m': null, 'total_seen_5m': null, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 1.0, 'avgdiff': 1, 'expectedWait': 4.0020981056, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 45.1845906902, 'pct_remaining5m': 0.0, 'sum': 1.3735625, 'tx_atabove': 194.0, 'hashpower_accepting': 78.125, 'hpa_coef2': -0.067, 'total_seen_30m': 9.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 12.3, 'pct_mined_5m': 100.0, 'total_seen_5m': 2.0, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.99, 'avgdiff': 1, 'expectedWait': 3.9493953846, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 45.1946227929, 'pct_remaining5m': null, 'sum': 1.3735625, 'tx_atabove': 194.0, 'hashpower_accepting': 78.125, 'hpa_coef2': -0.067, 'total_seen_30m': 1.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 12.4, 'pct_mined_5m': null, 'total_seen_5m': null, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.99, 'avgdiff': 1, 'expectedWait': 3.9493953846, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 45.3752006421, 'pct_remaining5m': 0.0, 'sum': 1.36090625, 'tx_atabove': 194.0, 'hashpower_accepting': 78.6458333333, 'hpa_coef2': -0.067, 'total_seen_30m': 10.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 12.5, 'pct_mined_5m': 100.0, 'total_seen_5m': 2.0, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.98, 'avgdiff': 1, 'expectedWait': 3.8997258274, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 45.4955858748, 'pct_remaining5m': 0.0, 'sum': 1.36090625, 'tx_atabove': 194.0, 'hashpower_accepting': 78.6458333333, 'hpa_coef2': -0.067, 'total_seen_30m': 4.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 12.6, 'pct_mined_5m': 100.0, 'total_seen_5m': 1.0, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.98, 'avgdiff': 1, 'expectedWait': 3.8997258274, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 45.525682183, 'pct_remaining5m': null, 'sum': 1.36090625, 'tx_atabove': 194.0, 'hashpower_accepting': 78.6458333333, 'hpa_coef2': -0.067, 'total_seen_30m': 1.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 12.7, 'pct_mined_5m': null, 'total_seen_5m': null, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.98, 'avgdiff': 1, 'expectedWait': 3.8997258274, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 45.5858747994, 'pct_remaining5m': 0.0, 'sum': 1.36090625, 'tx_atabove': 194.0, 'hashpower_accepting': 78.6458333333, 'hpa_coef2': -0.067, 'total_seen_30m': 4.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 12.8, 'pct_mined_5m': 100.0, 'total_seen_5m': 1.0, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.98, 'avgdiff': 1, 'expectedWait': 3.8997258274, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 45.636035313, 'pct_remaining5m': 0.0, 'sum': 1.36090625, 'tx_atabove': 194.0, 'hashpower_accepting': 78.6458333333, 'hpa_coef2': -0.067, 'total_seen_30m': 1.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 12.9, 'pct_mined_5m': 100.0, 'total_seen_5m': 1.0, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.98, 'avgdiff': 1, 'expectedWait': 3.8997258274, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': 1.0, 'hashpower_accepting2': 46.9903691814, 'pct_remaining5m': 0.0, 'sum': 1.31028125, 'tx_atabove': 194.0, 'hashpower_accepting': 80.7291666667, 'hpa_coef2': -0.067, 'total_seen_30m': 47.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 13.0, 'pct_mined_5m': 100.0, 'total_seen_5m': 34.0, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.93, 'avgdiff': 1, 'expectedWait': 3.7072162202, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 47.5321027287, 'pct_remaining5m': 0.0, 'sum': 1.292825, 'tx_atabove': 186.0, 'hashpower_accepting': 81.25, 'hpa_coef2': -0.067, 'total_seen_30m': 9.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 13.2, 'pct_mined_5m': 100.0, 'total_seen_5m': 1.0, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.91, 'avgdiff': 1, 'expectedWait': 3.6430636874, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 47.5621990369, 'pct_remaining5m': 0.0, 'sum': 1.292825, 'tx_atabove': 186.0, 'hashpower_accepting': 81.25, 'hpa_coef2': -0.067, 'total_seen_30m': 1.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 13.3, 'pct_mined_5m': 100.0, 'total_seen_5m': 1.0, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.91, 'avgdiff': 1, 'expectedWait': 3.6430636874, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 47.632423756, 'pct_remaining5m': null, 'sum': 1.292825, 'tx_atabove': 186.0, 'hashpower_accepting': 81.25, 'hpa_coef2': -0.067, 'total_seen_30m': 2.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 13.4, 'pct_mined_5m': null, 'total_seen_5m': null, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.91, 'avgdiff': 1, 'expectedWait': 3.6430636874, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': 0.5, 'hashpower_accepting2': 48.1440609952, 'pct_remaining5m': 0.0, 'sum': 1.28016875, 'tx_atabove': 186.0, 'hashpower_accepting': 81.7708333333, 'hpa_coef2': -0.067, 'total_seen_30m': 2.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 13.5, 'pct_mined_5m': 100.0, 'total_seen_5m': 21.0, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.9, 'avgdiff': 1, 'expectedWait': 3.5972467097, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 48.4550561798, 'pct_remaining5m': 0.0, 'sum': 1.2651125, 'tx_atabove': 182.0, 'hashpower_accepting': 82.2916666667, 'hpa_coef2': -0.067, 'total_seen_30m': 10.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 13.6, 'pct_mined_5m': 100.0, 'total_seen_5m': 10.0, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.89, 'avgdiff': 1, 'expectedWait': 3.5434913565, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': 1.0, 'hashpower_accepting2': 55.9590690209, 'pct_remaining5m': 0.0, 'sum': 1.2398, 'tx_atabove': 182.0, 'hashpower_accepting': 83.3333333333, 'hpa_coef2': -0.067, 'total_seen_30m': 253.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 13.7, 'pct_mined_5m': 100.0, 'total_seen_5m': 212.0, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.87, 'avgdiff': 1, 'expectedWait': 3.4549224112, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 56.0593900482, 'pct_remaining5m': 0.0, 'sum': 1.226, 'tx_atabove': 159.0, 'hashpower_accepting': 83.3333333333, 'hpa_coef2': -0.067, 'total_seen_30m': 6.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 13.8, 'pct_mined_5m': 100.0, 'total_seen_5m': 2.0, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.86, 'avgdiff': 1, 'expectedWait': 3.4075719515, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 56.1095505618, 'pct_remaining5m': 0.0, 'sum': 1.226, 'tx_atabove': 159.0, 'hashpower_accepting': 83.3333333333, 'hpa_coef2': -0.067, 'total_seen_30m': 1.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 13.9, 'pct_mined_5m': 100.0, 'total_seen_5m': 4.0, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.86, 'avgdiff': 1, 'expectedWait': 3.4075719515, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': 0.5, 'hashpower_accepting2': 59.6408507223, 'pct_remaining5m': 0.0, 'sum': 1.13740625, 'tx_atabove': 159.0, 'hashpower_accepting': 86.9791666667, 'hpa_coef2': -0.067, 'total_seen_30m': 119.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 14.0, 'pct_mined_5m': 100.0, 'total_seen_5m': 115.0, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.78, 'avgdiff': 1, 'expectedWait': 3.1186688184, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 59.7311396469, 'pct_remaining5m': 0.0, 'sum': 1.13440625, 'tx_atabove': 154.0, 'hashpower_accepting': 86.9791666667, 'hpa_coef2': -0.067, 'total_seen_30m': null, 'int2': 6.9238, 'pct_remaining30m': null, 'gasprice': 14.1, 'pct_mined_5m': 100.0, 'total_seen_5m': 5.0, 'pct_mined_30m': null, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.78, 'avgdiff': 1, 'expectedWait': 3.1093268319, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 59.8214285714, 'pct_remaining5m': 0.0, 'sum': 1.13440625, 'tx_atabove': 154.0, 'hashpower_accepting': 86.9791666667, 'hpa_coef2': -0.067, 'total_seen_30m': 4.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 14.2, 'pct_mined_5m': 100.0, 'total_seen_5m': 4.0, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.78, 'avgdiff': 1, 'expectedWait': 3.1093268319, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': 1.0, 'hashpower_accepting2': 60.1524879615, 'pct_remaining5m': 0.0, 'sum': 1.13380625, 'tx_atabove': 153.0, 'hashpower_accepting': 86.9791666667, 'hpa_coef2': -0.067, 'total_seen_30m': 5.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 14.4, 'pct_mined_5m': 100.0, 'total_seen_5m': 3.0, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.78, 'avgdiff': 1, 'expectedWait': 3.1074617954, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 60.1725521669, 'pct_remaining5m': 0.0, 'sum': 1.13320625, 'tx_atabove': 152.0, 'hashpower_accepting': 86.9791666667, 'hpa_coef2': -0.067, 'total_seen_30m': 1.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 14.5, 'pct_mined_5m': 100.0, 'total_seen_5m': 1.0, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.78, 'avgdiff': 1, 'expectedWait': 3.1055978775, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 60.2528089888, 'pct_remaining5m': 0.0, 'sum': 1.13320625, 'tx_atabove': 152.0, 'hashpower_accepting': 86.9791666667, 'hpa_coef2': -0.067, 'total_seen_30m': 3.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 14.6, 'pct_mined_5m': 100.0, 'total_seen_5m': 2.0, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.78, 'avgdiff': 1, 'expectedWait': 3.1055978775, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 60.6440609952, 'pct_remaining5m': 0.0, 'sum': 1.13320625, 'tx_atabove': 152.0, 'hashpower_accepting': 86.9791666667, 'hpa_coef2': -0.067, 'total_seen_30m': 10.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 14.7, 'pct_mined_5m': 100.0, 'total_seen_5m': 10.0, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.78, 'avgdiff': 1, 'expectedWait': 3.1055978775, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 60.6641252006, 'pct_remaining5m': 0.0, 'sum': 1.13320625, 'tx_atabove': 152.0, 'hashpower_accepting': 86.9791666667, 'hpa_coef2': -0.067, 'total_seen_30m': 1.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 14.8, 'pct_mined_5m': 100.0, 'total_seen_5m': 1.0, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.78, 'avgdiff': 1, 'expectedWait': 3.1055978775, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 60.6942215088, 'pct_remaining5m': null, 'sum': 1.13320625, 'tx_atabove': 152.0, 'hashpower_accepting': 86.9791666667, 'hpa_coef2': -0.067, 'total_seen_30m': 2.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 14.9, 'pct_mined_5m': null, 'total_seen_5m': null, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.78, 'avgdiff': 1, 'expectedWait': 3.1055978775, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': 0.0, 'hashpower_accepting2': 62.9113162119, 'pct_remaining5m': 0.0, 'sum': 1.0952375, 'tx_atabove': 152.0, 'hashpower_accepting': 88.5416666667, 'hpa_coef2': -0.067, 'total_seen_30m': 65.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 15.0, 'pct_mined_5m': 100.0, 'total_seen_5m': 48.0, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.75, 'avgdiff': 1, 'expectedWait': 2.9898926986, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 63.4129213483, 'pct_remaining5m': 0.0, 'sum': 1.0910375, 'tx_atabove': 145.0, 'hashpower_accepting': 88.5416666667, 'hpa_coef2': -0.067, 'total_seen_30m': 11.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 15.1, 'pct_mined_5m': 100.0, 'total_seen_5m': 8.0, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.75, 'avgdiff': 1, 'expectedWait': 2.9773614832, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': 1.0, 'hashpower_accepting2': 64.4161316212, 'pct_remaining5m': 0.0, 'sum': 1.0886375, 'tx_atabove': 141.0, 'hashpower_accepting': 88.5416666667, 'hpa_coef2': -0.067, 'total_seen_30m': 1.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 15.5, 'pct_mined_5m': 100.0, 'total_seen_5m': 4.0, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.75, 'avgdiff': 1, 'expectedWait': 2.9702243836, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 64.4863563403, 'pct_remaining5m': 0.0, 'sum': 1.0820375, 'tx_atabove': 130.0, 'hashpower_accepting': 88.5416666667, 'hpa_coef2': -0.067, 'total_seen_30m': 5.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 15.6, 'pct_mined_5m': 50.0, 'total_seen_5m': 2.0, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.74, 'avgdiff': 1, 'expectedWait': 2.9506854521, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': 1.0, 'hashpower_accepting2': 66.1817817014, 'pct_remaining5m': 0.0, 'sum': 1.0820375, 'tx_atabove': 130.0, 'hashpower_accepting': 88.5416666667, 'hpa_coef2': -0.067, 'total_seen_30m': 24.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 15.7, 'pct_mined_5m': 100.0, 'total_seen_5m': 17.0, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.74, 'avgdiff': 1, 'expectedWait': 2.9506854521, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 66.2620385233, 'pct_remaining5m': 0.0, 'sum': 1.0766375, 'tx_atabove': 121.0, 'hashpower_accepting': 88.5416666667, 'hpa_coef2': -0.067, 'total_seen_30m': 2.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 15.8, 'pct_mined_5m': 83.0, 'total_seen_5m': 6.0, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.74, 'avgdiff': 1, 'expectedWait': 2.9347946943, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': 0.0, 'hashpower_accepting2': 67.2853130016, 'pct_remaining5m': 0.0, 'sum': 1.0766375, 'tx_atabove': 121.0, 'hashpower_accepting': 88.5416666667, 'hpa_coef2': -0.067, 'total_seen_30m': 15.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 16.0, 'pct_mined_5m': 100.0, 'total_seen_5m': 11.0, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.74, 'avgdiff': 1, 'expectedWait': 2.9347946943, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 67.2953451043, 'pct_remaining5m': null, 'sum': 1.0748375, 'tx_atabove': 118.0, 'hashpower_accepting': 88.5416666667, 'hpa_coef2': -0.067, 'total_seen_30m': 1.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 16.1, 'pct_mined_5m': null, 'total_seen_5m': null, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.74, 'avgdiff': 1, 'expectedWait': 2.9295168154, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 67.4458266453, 'pct_remaining5m': 0.0, 'sum': 1.0748375, 'tx_atabove': 118.0, 'hashpower_accepting': 88.5416666667, 'hpa_coef2': -0.067, 'total_seen_30m': 3.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 16.2, 'pct_mined_5m': 100.0, 'total_seen_5m': 7.0, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.74, 'avgdiff': 1, 'expectedWait': 2.9295168154, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 67.455858748, 'pct_remaining5m': 0.0, 'sum': 1.0748375, 'tx_atabove': 118.0, 'hashpower_accepting': 88.5416666667, 'hpa_coef2': -0.067, 'total_seen_30m': null, 'int2': 6.9238, 'pct_remaining30m': null, 'gasprice': 16.3, 'pct_mined_5m': 100.0, 'total_seen_5m': 1.0, 'pct_mined_30m': null, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.74, 'avgdiff': 1, 'expectedWait': 2.9295168154, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 67.6565008026, 'pct_remaining5m': 0.0, 'sum': 1.0748375, 'tx_atabove': 118.0, 'hashpower_accepting': 88.5416666667, 'hpa_coef2': -0.067, 'total_seen_30m': 5.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 16.4, 'pct_mined_5m': 100.0, 'total_seen_5m': 7.0, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.74, 'avgdiff': 1, 'expectedWait': 2.9295168154, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 67.7267255217, 'pct_remaining5m': 0.0, 'sum': 1.0742375, 'tx_atabove': 117.0, 'hashpower_accepting': 88.5416666667, 'hpa_coef2': -0.067, 'total_seen_30m': 1.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 16.5, 'pct_mined_5m': 100.0, 'total_seen_5m': 2.0, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.73, 'avgdiff': 1, 'expectedWait': 2.9277596325, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': 1.0, 'hashpower_accepting2': 68.6697431782, 'pct_remaining5m': 0.0, 'sum': 1.0742375, 'tx_atabove': 117.0, 'hashpower_accepting': 88.5416666667, 'hpa_coef2': -0.067, 'total_seen_30m': 42.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 16.7, 'pct_mined_5m': 100.0, 'total_seen_5m': 27.0, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.73, 'avgdiff': 1, 'expectedWait': 2.9277596325, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 68.8904494382, 'pct_remaining5m': 0.0, 'sum': 1.0718375, 'tx_atabove': 113.0, 'hashpower_accepting': 88.5416666667, 'hpa_coef2': -0.067, 'total_seen_30m': 11.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 17.0, 'pct_mined_5m': 100.0, 'total_seen_5m': 3.0, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.73, 'avgdiff': 1, 'expectedWait': 2.9207414346, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': 0.0, 'hashpower_accepting2': 69.0308988764, 'pct_remaining5m': 0.0, 'sum': 1.0712375, 'tx_atabove': 112.0, 'hashpower_accepting': 88.5416666667, 'hpa_coef2': -0.067, 'total_seen_30m': 8.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 17.1, 'pct_mined_5m': 100.0, 'total_seen_5m': 3.0, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.73, 'avgdiff': 1, 'expectedWait': 2.9189895153, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 69.0409309791, 'pct_remaining5m': null, 'sum': 1.0706375, 'tx_atabove': 111.0, 'hashpower_accepting': 88.5416666667, 'hpa_coef2': -0.067, 'total_seen_30m': 1.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 17.3, 'pct_mined_5m': null, 'total_seen_5m': null, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.73, 'avgdiff': 1, 'expectedWait': 2.9172386469, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 69.0710272873, 'pct_remaining5m': 0.0, 'sum': 1.0706375, 'tx_atabove': 111.0, 'hashpower_accepting': 88.5416666667, 'hpa_coef2': -0.067, 'total_seen_30m': null, 'int2': 6.9238, 'pct_remaining30m': null, 'gasprice': 17.5, 'pct_mined_5m': 100.0, 'total_seen_5m': 2.0, 'pct_mined_30m': null, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.73, 'avgdiff': 1, 'expectedWait': 2.9172386469, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 69.08105939, 'pct_remaining5m': 0.0, 'sum': 1.0706375, 'tx_atabove': 111.0, 'hashpower_accepting': 88.5416666667, 'hpa_coef2': -0.067, 'total_seen_30m': null, 'int2': 6.9238, 'pct_remaining30m': null, 'gasprice': 17.6, 'pct_mined_5m': 100.0, 'total_seen_5m': 1.0, 'pct_mined_30m': null, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.73, 'avgdiff': 1, 'expectedWait': 2.9172386469, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 69.1011235955, 'pct_remaining5m': null, 'sum': 1.0706375, 'tx_atabove': 111.0, 'hashpower_accepting': 88.5416666667, 'hpa_coef2': -0.067, 'total_seen_30m': 1.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 17.8, 'pct_mined_5m': null, 'total_seen_5m': null, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.73, 'avgdiff': 1, 'expectedWait': 2.9172386469, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 69.1111556982, 'pct_remaining5m': 0.0, 'sum': 1.0706375, 'tx_atabove': 111.0, 'hashpower_accepting': 88.5416666667, 'hpa_coef2': -0.067, 'total_seen_30m': 1.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 17.9, 'pct_mined_5m': 0.0, 'total_seen_5m': 1.0, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.73, 'avgdiff': 1, 'expectedWait': 2.9172386469, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 69.7632423756, 'pct_remaining5m': 0.0, 'sum': 1.05798125, 'tx_atabove': 111.0, 'hashpower_accepting': 89.0625, 'hpa_coef2': -0.067, 'total_seen_30m': 16.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 18.0, 'pct_mined_5m': 100.0, 'total_seen_5m': 16.0, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.72, 'avgdiff': 1, 'expectedWait': 2.8805500054, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 69.7732744783, 'pct_remaining5m': 0.0, 'sum': 1.05618125, 'tx_atabove': 108.0, 'hashpower_accepting': 89.0625, 'hpa_coef2': -0.067, 'total_seen_30m': null, 'int2': 6.9238, 'pct_remaining30m': null, 'gasprice': 18.1, 'pct_mined_5m': 100.0, 'total_seen_5m': 1.0, 'pct_mined_30m': null, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.72, 'avgdiff': 1, 'expectedWait': 2.875369679, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 69.8134028892, 'pct_remaining5m': 0.0, 'sum': 1.05618125, 'tx_atabove': 108.0, 'hashpower_accepting': 89.0625, 'hpa_coef2': -0.067, 'total_seen_30m': null, 'int2': 6.9238, 'pct_remaining30m': null, 'gasprice': 18.5, 'pct_mined_5m': 100.0, 'total_seen_5m': 2.0, 'pct_mined_30m': null, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.72, 'avgdiff': 1, 'expectedWait': 2.875369679, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 69.823434992, 'pct_remaining5m': 0.0, 'sum': 1.05618125, 'tx_atabove': 108.0, 'hashpower_accepting': 89.0625, 'hpa_coef2': -0.067, 'total_seen_30m': null, 'int2': 6.9238, 'pct_remaining30m': null, 'gasprice': 18.7, 'pct_mined_5m': 100.0, 'total_seen_5m': 1.0, 'pct_mined_30m': null, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.72, 'avgdiff': 1, 'expectedWait': 2.875369679, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 69.8535313002, 'pct_remaining5m': null, 'sum': 1.05618125, 'tx_atabove': 108.0, 'hashpower_accepting': 89.0625, 'hpa_coef2': -0.067, 'total_seen_30m': 2.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 18.8, 'pct_mined_5m': null, 'total_seen_5m': null, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.72, 'avgdiff': 1, 'expectedWait': 2.875369679, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 69.8735955056, 'pct_remaining5m': 0.0, 'sum': 1.05618125, 'tx_atabove': 108.0, 'hashpower_accepting': 89.0625, 'hpa_coef2': -0.067, 'total_seen_30m': 1.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 18.9, 'pct_mined_5m': 100.0, 'total_seen_5m': 1.0, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.72, 'avgdiff': 1, 'expectedWait': 2.875369679, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 70.3150080257, 'pct_remaining5m': 0.0, 'sum': 1.043525, 'tx_atabove': 108.0, 'hashpower_accepting': 89.5833333333, 'hpa_coef2': -0.067, 'total_seen_30m': 13.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 19.0, 'pct_mined_5m': 100.0, 'total_seen_5m': 11.0, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.71, 'avgdiff': 1, 'expectedWait': 2.8392076024, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 70.3350722311, 'pct_remaining5m': 0.0, 'sum': 1.042325, 'tx_atabove': 106.0, 'hashpower_accepting': 89.5833333333, 'hpa_coef2': -0.067, 'total_seen_30m': null, 'int2': 6.9238, 'pct_remaining30m': null, 'gasprice': 19.3, 'pct_mined_5m': 66.0, 'total_seen_5m': 3.0, 'pct_mined_30m': null, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.71, 'avgdiff': 1, 'expectedWait': 2.8358025967, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 70.3752006421, 'pct_remaining5m': 0.0, 'sum': 1.042325, 'tx_atabove': 106.0, 'hashpower_accepting': 89.5833333333, 'hpa_coef2': -0.067, 'total_seen_30m': null, 'int2': 6.9238, 'pct_remaining30m': null, 'gasprice': 19.4, 'pct_mined_5m': 100.0, 'total_seen_5m': 1.0, 'pct_mined_30m': null, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.71, 'avgdiff': 1, 'expectedWait': 2.8358025967, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 70.3852327448, 'pct_remaining5m': null, 'sum': 1.042325, 'tx_atabove': 106.0, 'hashpower_accepting': 89.5833333333, 'hpa_coef2': -0.067, 'total_seen_30m': 1.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 19.5, 'pct_mined_5m': null, 'total_seen_5m': null, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.71, 'avgdiff': 1, 'expectedWait': 2.8358025967, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 70.4052969502, 'pct_remaining5m': null, 'sum': 1.042325, 'tx_atabove': 106.0, 'hashpower_accepting': 89.5833333333, 'hpa_coef2': -0.067, 'total_seen_30m': 1.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 19.8, 'pct_mined_5m': null, 'total_seen_5m': null, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.71, 'avgdiff': 1, 'expectedWait': 2.8358025967, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 70.8266452648, 'pct_remaining5m': 0.0, 'sum': 1.042325, 'tx_atabove': 106.0, 'hashpower_accepting': 89.5833333333, 'hpa_coef2': -0.067, 'total_seen_30m': 18.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 19.9, 'pct_mined_5m': 100.0, 'total_seen_5m': 10.0, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.71, 'avgdiff': 1, 'expectedWait': 2.8358025967, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': 0.0, 'hashpower_accepting2': 75.2708667737, 'pct_remaining5m': 0.0, 'sum': 0.90310625, 'tx_atabove': 106.0, 'hashpower_accepting': 95.3125, 'hpa_coef2': -0.067, 'total_seen_30m': 144.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 20.0, 'pct_mined_5m': 100.0, 'total_seen_5m': 185.0, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.62, 'avgdiff': 1, 'expectedWait': 2.4672551317, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 75.3009630819, 'pct_remaining5m': null, 'sum': 0.89650625, 'tx_atabove': 95.0, 'hashpower_accepting': 95.3125, 'hpa_coef2': -0.067, 'total_seen_30m': 3.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 20.2, 'pct_mined_5m': null, 'total_seen_5m': null, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.62, 'avgdiff': 1, 'expectedWait': 2.4510248666, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 75.3210272873, 'pct_remaining5m': 0.0, 'sum': 0.89650625, 'tx_atabove': 95.0, 'hashpower_accepting': 95.3125, 'hpa_coef2': -0.067, 'total_seen_30m': null, 'int2': 6.9238, 'pct_remaining30m': null, 'gasprice': 20.3, 'pct_mined_5m': 100.0, 'total_seen_5m': 1.0, 'pct_mined_30m': null, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.62, 'avgdiff': 1, 'expectedWait': 2.4510248666, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 77.7387640449, 'pct_remaining5m': 0.0, 'sum': 0.88385, 'tx_atabove': 95.0, 'hashpower_accepting': 95.8333333333, 'hpa_coef2': -0.067, 'total_seen_30m': 24.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 20.5, 'pct_mined_5m': 100.0, 'total_seen_5m': 9.0, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.61, 'avgdiff': 1, 'expectedWait': 2.420199561, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 77.7688603531, 'pct_remaining5m': 0.0, 'sum': 0.88325, 'tx_atabove': 94.0, 'hashpower_accepting': 95.8333333333, 'hpa_coef2': -0.067, 'total_seen_30m': 1.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 20.7, 'pct_mined_5m': 100.0, 'total_seen_5m': 2.0, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.61, 'avgdiff': 1, 'expectedWait': 2.4187478768, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 77.9093097913, 'pct_remaining5m': null, 'sum': 0.87059375, 'tx_atabove': 94.0, 'hashpower_accepting': 96.3541666667, 'hpa_coef2': -0.067, 'total_seen_30m': 7.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 20.9, 'pct_mined_5m': null, 'total_seen_5m': null, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.6, 'avgdiff': 1, 'expectedWait': 2.3883285027, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': 0.0, 'hashpower_accepting2': 79.7752808989, 'pct_remaining5m': 0.0, 'sum': 0.87059375, 'tx_atabove': 94.0, 'hashpower_accepting': 96.3541666667, 'hpa_coef2': -0.067, 'total_seen_30m': 39.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 21.0, 'pct_mined_5m': 100.0, 'total_seen_5m': 36.0, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.6, 'avgdiff': 1, 'expectedWait': 2.3883285027, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 79.7953451043, 'pct_remaining5m': 0.0, 'sum': 0.86819375, 'tx_atabove': 90.0, 'hashpower_accepting': 96.3541666667, 'hpa_coef2': -0.067, 'total_seen_30m': null, 'int2': 6.9238, 'pct_remaining30m': null, 'gasprice': 21.1, 'pct_mined_5m': 100.0, 'total_seen_5m': 2.0, 'pct_mined_30m': null, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.6, 'avgdiff': 1, 'expectedWait': 2.3826033871, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 79.8154093098, 'pct_remaining5m': null, 'sum': 0.86819375, 'tx_atabove': 90.0, 'hashpower_accepting': 96.3541666667, 'hpa_coef2': -0.067, 'total_seen_30m': 2.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 21.4, 'pct_mined_5m': null, 'total_seen_5m': null, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.6, 'avgdiff': 1, 'expectedWait': 2.3826033871, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 79.845505618, 'pct_remaining5m': 0.0, 'sum': 0.86819375, 'tx_atabove': 90.0, 'hashpower_accepting': 96.3541666667, 'hpa_coef2': -0.067, 'total_seen_30m': 1.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 21.7, 'pct_mined_5m': 100.0, 'total_seen_5m': 1.0, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.6, 'avgdiff': 1, 'expectedWait': 2.3826033871, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 80.3069823435, 'pct_remaining5m': 0.0, 'sum': 0.86819375, 'tx_atabove': 90.0, 'hashpower_accepting': 96.3541666667, 'hpa_coef2': -0.067, 'total_seen_30m': 9.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 21.9, 'pct_mined_5m': 100.0, 'total_seen_5m': 3.0, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.6, 'avgdiff': 1, 'expectedWait': 2.3826033871, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 80.8888443018, 'pct_remaining5m': 0.0, 'sum': 0.8555375, 'tx_atabove': 90.0, 'hashpower_accepting': 96.875, 'hpa_coef2': -0.067, 'total_seen_30m': 13.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 22.0, 'pct_mined_5m': 100.0, 'total_seen_5m': 13.0, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.59, 'avgdiff': 1, 'expectedWait': 2.352638584, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 80.9089085072, 'pct_remaining5m': null, 'sum': 0.8555375, 'tx_atabove': 90.0, 'hashpower_accepting': 96.875, 'hpa_coef2': -0.067, 'total_seen_30m': 1.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 22.1, 'pct_mined_5m': null, 'total_seen_5m': null, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.59, 'avgdiff': 1, 'expectedWait': 2.352638584, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 80.91894061, 'pct_remaining5m': 0.0, 'sum': 0.8555375, 'tx_atabove': 90.0, 'hashpower_accepting': 96.875, 'hpa_coef2': -0.067, 'total_seen_30m': null, 'int2': 6.9238, 'pct_remaining30m': null, 'gasprice': 22.2, 'pct_mined_5m': 100.0, 'total_seen_5m': 1.0, 'pct_mined_30m': null, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.59, 'avgdiff': 1, 'expectedWait': 2.352638584, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 80.9289727127, 'pct_remaining5m': null, 'sum': 0.8555375, 'tx_atabove': 90.0, 'hashpower_accepting': 96.875, 'hpa_coef2': -0.067, 'total_seen_30m': 1.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 22.3, 'pct_mined_5m': null, 'total_seen_5m': null, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.59, 'avgdiff': 1, 'expectedWait': 2.352638584, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 80.9490369181, 'pct_remaining5m': 0.0, 'sum': 0.8555375, 'tx_atabove': 90.0, 'hashpower_accepting': 96.875, 'hpa_coef2': -0.067, 'total_seen_30m': null, 'int2': 6.9238, 'pct_remaining30m': null, 'gasprice': 22.5, 'pct_mined_5m': 100.0, 'total_seen_5m': 1.0, 'pct_mined_30m': null, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.59, 'avgdiff': 1, 'expectedWait': 2.352638584, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 80.9791332263, 'pct_remaining5m': 0.0, 'sum': 0.8555375, 'tx_atabove': 90.0, 'hashpower_accepting': 96.875, 'hpa_coef2': -0.067, 'total_seen_30m': 2.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 22.8, 'pct_mined_5m': 100.0, 'total_seen_5m': 1.0, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.59, 'avgdiff': 1, 'expectedWait': 2.352638584, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 80.9891653291, 'pct_remaining5m': null, 'sum': 0.8555375, 'tx_atabove': 90.0, 'hashpower_accepting': 96.875, 'hpa_coef2': -0.067, 'total_seen_30m': 1.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 22.9, 'pct_mined_5m': null, 'total_seen_5m': null, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.59, 'avgdiff': 1, 'expectedWait': 2.352638584, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': 0.0, 'hashpower_accepting2': 81.47070626, 'pct_remaining5m': 0.0, 'sum': 0.8555375, 'tx_atabove': 90.0, 'hashpower_accepting': 96.875, 'hpa_coef2': -0.067, 'total_seen_30m': 15.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 23.0, 'pct_mined_5m': 100.0, 'total_seen_5m': 19.0, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.59, 'avgdiff': 1, 'expectedWait': 2.352638584, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 81.4907704655, 'pct_remaining5m': 0.0, 'sum': 0.8531375, 'tx_atabove': 86.0, 'hashpower_accepting': 96.875, 'hpa_coef2': -0.067, 'total_seen_30m': null, 'int2': 6.9238, 'pct_remaining30m': null, 'gasprice': 23.1, 'pct_mined_5m': 100.0, 'total_seen_5m': 1.0, 'pct_mined_30m': null, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.59, 'avgdiff': 1, 'expectedWait': 2.3469990216, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 81.5108346709, 'pct_remaining5m': 0.0, 'sum': 0.8525375, 'tx_atabove': 85.0, 'hashpower_accepting': 96.875, 'hpa_coef2': -0.067, 'total_seen_30m': null, 'int2': 6.9238, 'pct_remaining30m': null, 'gasprice': 23.3, 'pct_mined_5m': 100.0, 'total_seen_5m': 2.0, 'pct_mined_30m': null, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.59, 'avgdiff': 1, 'expectedWait': 2.3455912446, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 81.6011235955, 'pct_remaining5m': 0.0, 'sum': 0.8525375, 'tx_atabove': 85.0, 'hashpower_accepting': 96.875, 'hpa_coef2': -0.067, 'total_seen_30m': 3.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 23.7, 'pct_mined_5m': 100.0, 'total_seen_5m': 3.0, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.59, 'avgdiff': 1, 'expectedWait': 2.3455912446, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 81.621187801, 'pct_remaining5m': 0.0, 'sum': 0.8525375, 'tx_atabove': 85.0, 'hashpower_accepting': 96.875, 'hpa_coef2': -0.067, 'total_seen_30m': null, 'int2': 6.9238, 'pct_remaining30m': null, 'gasprice': 23.9, 'pct_mined_5m': 100.0, 'total_seen_5m': 1.0, 'pct_mined_30m': null, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.59, 'avgdiff': 1, 'expectedWait': 2.3455912446, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': 0.0, 'hashpower_accepting2': 81.8719903692, 'pct_remaining5m': 0.0, 'sum': 0.8525375, 'tx_atabove': 85.0, 'hashpower_accepting': 96.875, 'hpa_coef2': -0.067, 'total_seen_30m': 7.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 24.0, 'pct_mined_5m': 100.0, 'total_seen_5m': 9.0, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.59, 'avgdiff': 1, 'expectedWait': 2.3455912446, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 81.8820224719, 'pct_remaining5m': 0.0, 'sum': 0.8501375, 'tx_atabove': 81.0, 'hashpower_accepting': 96.875, 'hpa_coef2': -0.067, 'total_seen_30m': null, 'int2': 6.9238, 'pct_remaining30m': null, 'gasprice': 24.3, 'pct_mined_5m': 100.0, 'total_seen_5m': 1.0, 'pct_mined_30m': null, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.59, 'avgdiff': 1, 'expectedWait': 2.3399685755, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 81.9121187801, 'pct_remaining5m': 0.0, 'sum': 0.8501375, 'tx_atabove': 81.0, 'hashpower_accepting': 96.875, 'hpa_coef2': -0.067, 'total_seen_30m': 2.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 24.6, 'pct_mined_5m': 100.0, 'total_seen_5m': 1.0, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.59, 'avgdiff': 1, 'expectedWait': 2.3399685755, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 81.9321829856, 'pct_remaining5m': 0.0, 'sum': 0.8501375, 'tx_atabove': 81.0, 'hashpower_accepting': 96.875, 'hpa_coef2': -0.067, 'total_seen_30m': null, 'int2': 6.9238, 'pct_remaining30m': null, 'gasprice': 24.7, 'pct_mined_5m': 100.0, 'total_seen_5m': 2.0, 'pct_mined_30m': null, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.59, 'avgdiff': 1, 'expectedWait': 2.3399685755, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': 0.0, 'hashpower_accepting2': 83.3868378812, 'pct_remaining5m': 0.0, 'sum': 0.83688125, 'tx_atabove': 80.0, 'hashpower_accepting': 97.3958333333, 'hpa_coef2': -0.067, 'total_seen_30m': 24.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 25.0, 'pct_mined_5m': 100.0, 'total_seen_5m': 32.0, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.58, 'avgdiff': 1, 'expectedWait': 2.3091540608, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 83.6276083467, 'pct_remaining5m': 0.0, 'sum': 0.82128125, 'tx_atabove': 54.0, 'hashpower_accepting': 97.3958333333, 'hpa_coef2': -0.067, 'total_seen_30m': 10.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 26.0, 'pct_mined_5m': 100.0, 'total_seen_5m': 7.0, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.57, 'avgdiff': 1, 'expectedWait': 2.2734107799, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': 0.0, 'hashpower_accepting2': 83.7379614767, 'pct_remaining5m': 0.0, 'sum': 0.82008125, 'tx_atabove': 52.0, 'hashpower_accepting': 97.3958333333, 'hpa_coef2': -0.067, 'total_seen_30m': 5.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 27.0, 'pct_mined_5m': 100.0, 'total_seen_5m': 1.0, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.57, 'avgdiff': 1, 'expectedWait': 2.2706843231, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 83.9887640449, 'pct_remaining5m': 0.0, 'sum': 0.81948125, 'tx_atabove': 51.0, 'hashpower_accepting': 97.3958333333, 'hpa_coef2': -0.067, 'total_seen_30m': 13.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 28.0, 'pct_mined_5m': 100.0, 'total_seen_5m': 7.0, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.57, 'avgdiff': 1, 'expectedWait': 2.2693223212, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 84.0690208668, 'pct_remaining5m': 0.0, 'sum': 0.806825, 'tx_atabove': 51.0, 'hashpower_accepting': 97.9166666667, 'hpa_coef2': -0.067, 'total_seen_30m': 4.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 29.0, 'pct_mined_5m': 100.0, 'total_seen_5m': 1.0, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.56, 'avgdiff': 1, 'expectedWait': 2.240782197, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': 0.0, 'hashpower_accepting2': 85.8447030498, 'pct_remaining5m': 0.0, 'sum': 0.7809125, 'tx_atabove': 50.0, 'hashpower_accepting': 98.9583333333, 'hpa_coef2': -0.067, 'total_seen_30m': 55.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 30.0, 'pct_mined_5m': 100.0, 'total_seen_5m': 49.0, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.55, 'avgdiff': 1, 'expectedWait': 2.1834637674, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 85.9751203852, 'pct_remaining5m': 0.0, 'sum': 0.7743125, 'tx_atabove': 39.0, 'hashpower_accepting': 98.9583333333, 'hpa_coef2': -0.067, 'total_seen_30m': 6.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 31.0, 'pct_mined_5m': 100.0, 'total_seen_5m': 5.0, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.54, 'avgdiff': 1, 'expectedWait': 2.169100358, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 86.1356340289, 'pct_remaining5m': 0.0, 'sum': 0.7743125, 'tx_atabove': 39.0, 'hashpower_accepting': 98.9583333333, 'hpa_coef2': -0.067, 'total_seen_30m': null, 'int2': 6.9238, 'pct_remaining30m': null, 'gasprice': 32.0, 'pct_mined_5m': 100.0, 'total_seen_5m': 4.0, 'pct_mined_30m': null, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.54, 'avgdiff': 1, 'expectedWait': 2.169100358, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 86.2760834671, 'pct_remaining5m': 0.0, 'sum': 0.7743125, 'tx_atabove': 39.0, 'hashpower_accepting': 98.9583333333, 'hpa_coef2': -0.067, 'total_seen_30m': 3.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 33.0, 'pct_mined_5m': 100.0, 'total_seen_5m': 6.0, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.54, 'avgdiff': 1, 'expectedWait': 2.169100358, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 86.4165329053, 'pct_remaining5m': 0.0, 'sum': 0.7737125, 'tx_atabove': 38.0, 'hashpower_accepting': 98.9583333333, 'hpa_coef2': -0.067, 'total_seen_30m': 6.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 34.0, 'pct_mined_5m': 60.0, 'total_seen_5m': 5.0, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.54, 'avgdiff': 1, 'expectedWait': 2.1677992881, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': 0.5, 'hashpower_accepting2': 86.7475922953, 'pct_remaining5m': 0.0, 'sum': 0.7737125, 'tx_atabove': 38.0, 'hashpower_accepting': 98.9583333333, 'hpa_coef2': -0.067, 'total_seen_30m': 10.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 35.0, 'pct_mined_5m': 100.0, 'total_seen_5m': 17.0, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.54, 'avgdiff': 1, 'expectedWait': 2.1677992881, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 86.7877207063, 'pct_remaining5m': 0.0, 'sum': 0.7725125, 'tx_atabove': 36.0, 'hashpower_accepting': 98.9583333333, 'hpa_coef2': -0.067, 'total_seen_30m': 1.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 36.0, 'pct_mined_5m': 100.0, 'total_seen_5m': 2.0, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.54, 'avgdiff': 1, 'expectedWait': 2.1651994891, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 86.8579454254, 'pct_remaining5m': 0.0, 'sum': 0.7725125, 'tx_atabove': 36.0, 'hashpower_accepting': 98.9583333333, 'hpa_coef2': -0.067, 'total_seen_30m': 2.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 37.0, 'pct_mined_5m': 66.0, 'total_seen_5m': 3.0, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.54, 'avgdiff': 1, 'expectedWait': 2.1651994891, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 86.908105939, 'pct_remaining5m': 0.0, 'sum': 0.7725125, 'tx_atabove': 36.0, 'hashpower_accepting': 98.9583333333, 'hpa_coef2': -0.067, 'total_seen_30m': 1.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 38.0, 'pct_mined_5m': 100.0, 'total_seen_5m': 1.0, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.54, 'avgdiff': 1, 'expectedWait': 2.1651994891, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 86.9783306581, 'pct_remaining5m': 0.0, 'sum': 0.7725125, 'tx_atabove': 36.0, 'hashpower_accepting': 98.9583333333, 'hpa_coef2': -0.067, 'total_seen_30m': 3.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 39.0, 'pct_mined_5m': 100.0, 'total_seen_5m': 2.0, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.54, 'avgdiff': 1, 'expectedWait': 2.1651994891, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': 1.0, 'hashpower_accepting2': 87.4498394864, 'pct_remaining5m': 0.0, 'sum': 0.75985625, 'tx_atabove': 36.0, 'hashpower_accepting': 99.4791666667, 'hpa_coef2': -0.067, 'total_seen_30m': 16.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 40.0, 'pct_mined_5m': 100.0, 'total_seen_5m': 14.0, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.54, 'avgdiff': 1, 'expectedWait': 2.1379688654, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': 1.0, 'hashpower_accepting2': 89.6167736758, 'pct_remaining5m': 0.0, 'sum': 0.75805625, 'tx_atabove': 33.0, 'hashpower_accepting': 99.4791666667, 'hpa_coef2': -0.067, 'total_seen_30m': 112.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 41.0, 'pct_mined_5m': 100.0, 'total_seen_5m': 57.0, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.54, 'avgdiff': 1, 'expectedWait': 2.1341239829, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 89.6869983949, 'pct_remaining5m': 0.0, 'sum': 0.75445625, 'tx_atabove': 27.0, 'hashpower_accepting': 99.4791666667, 'hpa_coef2': -0.067, 'total_seen_30m': 2.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 42.0, 'pct_mined_5m': 100.0, 'total_seen_5m': 3.0, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.53, 'avgdiff': 1, 'expectedWait': 2.1264549491, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 89.7070626003, 'pct_remaining5m': null, 'sum': 0.75385625, 'tx_atabove': 26.0, 'hashpower_accepting': 99.4791666667, 'hpa_coef2': -0.067, 'total_seen_30m': 1.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 43.0, 'pct_mined_5m': null, 'total_seen_5m': null, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.53, 'avgdiff': 1, 'expectedWait': 2.1251794588, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': 1.0, 'hashpower_accepting2': 89.9478330658, 'pct_remaining5m': 0.0, 'sum': 0.75385625, 'tx_atabove': 26.0, 'hashpower_accepting': 99.4791666667, 'hpa_coef2': -0.067, 'total_seen_30m': 9.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 44.0, 'pct_mined_5m': 100.0, 'total_seen_5m': 9.0, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.53, 'avgdiff': 1, 'expectedWait': 2.1251794588, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 90.088282504, 'pct_remaining5m': 0.0, 'sum': 0.7394, 'tx_atabove': 23.0, 'hashpower_accepting': 100.0, 'hpa_coef2': -0.067, 'total_seen_30m': 8.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 45.0, 'pct_mined_5m': 100.0, 'total_seen_5m': 5.0, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.53, 'avgdiff': 1, 'expectedWait': 2.0946783304, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': 1.0, 'hashpower_accepting2': 90.4995987159, 'pct_remaining5m': 0.0, 'sum': 0.7394, 'tx_atabove': 23.0, 'hashpower_accepting': 100.0, 'hpa_coef2': -0.067, 'total_seen_30m': 17.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 46.0, 'pct_mined_5m': 100.0, 'total_seen_5m': 19.0, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.53, 'avgdiff': 1, 'expectedWait': 2.0946783304, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 90.5999197432, 'pct_remaining5m': 0.0, 'sum': 0.7382, 'tx_atabove': 21.0, 'hashpower_accepting': 100.0, 'hpa_coef2': -0.067, 'total_seen_30m': 4.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 47.0, 'pct_mined_5m': 100.0, 'total_seen_5m': 1.0, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.53, 'avgdiff': 1, 'expectedWait': 2.0921662239, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 90.6199839486, 'pct_remaining5m': null, 'sum': 0.7382, 'tx_atabove': 21.0, 'hashpower_accepting': 100.0, 'hpa_coef2': -0.067, 'total_seen_30m': 2.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 48.0, 'pct_mined_5m': null, 'total_seen_5m': null, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.53, 'avgdiff': 1, 'expectedWait': 2.0921662239, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 90.6500802568, 'pct_remaining5m': null, 'sum': 0.7382, 'tx_atabove': 21.0, 'hashpower_accepting': 100.0, 'hpa_coef2': -0.067, 'total_seen_30m': 2.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 49.0, 'pct_mined_5m': null, 'total_seen_5m': null, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.53, 'avgdiff': 1, 'expectedWait': 2.0921662239, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': 1.0, 'hashpower_accepting2': 94.1412520064, 'pct_remaining5m': 0.0, 'sum': 0.7382, 'tx_atabove': 21.0, 'hashpower_accepting': 100.0, 'hpa_coef2': -0.067, 'total_seen_30m': 62.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 50.0, 'pct_mined_5m': 100.0, 'total_seen_5m': 71.0, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.53, 'avgdiff': 1, 'expectedWait': 2.0921662239, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 94.2114767255, 'pct_remaining5m': 0.0, 'sum': 0.7358, 'tx_atabove': 17.0, 'hashpower_accepting': 100.0, 'hpa_coef2': -0.067, 'total_seen_30m': 1.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 51.0, 'pct_mined_5m': 100.0, 'total_seen_5m': 3.0, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.52, 'avgdiff': 1, 'expectedWait': 2.0871510456, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 94.4422150883, 'pct_remaining5m': 0.0, 'sum': 0.7358, 'tx_atabove': 17.0, 'hashpower_accepting': 100.0, 'hpa_coef2': -0.067, 'total_seen_30m': 5.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 52.0, 'pct_mined_5m': 100.0, 'total_seen_5m': 2.0, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.52, 'avgdiff': 1, 'expectedWait': 2.0871510456, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 94.4723113965, 'pct_remaining5m': null, 'sum': 0.7358, 'tx_atabove': 17.0, 'hashpower_accepting': 100.0, 'hpa_coef2': -0.067, 'total_seen_30m': 2.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 54.0, 'pct_mined_5m': null, 'total_seen_5m': null, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.52, 'avgdiff': 1, 'expectedWait': 2.0871510456, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 94.4823434992, 'pct_remaining5m': null, 'sum': 0.7346, 'tx_atabove': 15.0, 'hashpower_accepting': 100.0, 'hpa_coef2': -0.067, 'total_seen_30m': 1.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 56.0, 'pct_mined_5m': null, 'total_seen_5m': null, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.52, 'avgdiff': 1, 'expectedWait': 2.0846479665, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': 0.0, 'hashpower_accepting2': 95.0140449438, 'pct_remaining5m': 0.0, 'sum': 0.7346, 'tx_atabove': 15.0, 'hashpower_accepting': 100.0, 'hpa_coef2': -0.067, 'total_seen_30m': 27.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 60.0, 'pct_mined_5m': 100.0, 'total_seen_5m': 17.0, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.52, 'avgdiff': 1, 'expectedWait': 2.0846479665, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': 0.0, 'hashpower_accepting2': 95.6059390048, 'pct_remaining5m': 0.0, 'sum': 0.7334, 'tx_atabove': 13.0, 'hashpower_accepting': 100.0, 'hpa_coef2': -0.067, 'total_seen_30m': 28.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 61.0, 'pct_mined_5m': 100.0, 'total_seen_5m': 14.0, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.52, 'avgdiff': 1, 'expectedWait': 2.0821478893, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 96.8699839486, 'pct_remaining5m': 0.0, 'sum': 0.7322, 'tx_atabove': 11.0, 'hashpower_accepting': 100.0, 'hpa_coef2': -0.067, 'total_seen_30m': 21.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 63.0, 'pct_mined_5m': 100.0, 'total_seen_5m': 25.0, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.52, 'avgdiff': 1, 'expectedWait': 2.0796508104, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': 1.0, 'hashpower_accepting2': 98.3948635634, 'pct_remaining5m': 0.0, 'sum': 0.7298, 'tx_atabove': 7.0, 'hashpower_accepting': 100.0, 'hpa_coef2': -0.067, 'total_seen_30m': 83.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 64.0, 'pct_mined_5m': 100.0, 'total_seen_5m': 38.0, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.52, 'avgdiff': 1, 'expectedWait': 2.0746656331, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 98.4149277689, 'pct_remaining5m': 0.0, 'sum': 0.728, 'tx_atabove': 4.0, 'hashpower_accepting': 100.0, 'hpa_coef2': -0.067, 'total_seen_30m': null, 'int2': 6.9238, 'pct_remaining30m': null, 'gasprice': 65.0, 'pct_mined_5m': 100.0, 'total_seen_5m': 2.0, 'pct_mined_30m': null, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.52, 'avgdiff': 1, 'expectedWait': 2.0709345939, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 98.4951845907, 'pct_remaining5m': 0.0, 'sum': 0.7274, 'tx_atabove': 3.0, 'hashpower_accepting': 100.0, 'hpa_coef2': -0.067, 'total_seen_30m': 3.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 66.0, 'pct_mined_5m': 100.0, 'total_seen_5m': 3.0, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.52, 'avgdiff': 1, 'expectedWait': 2.0696924058, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 98.5052166934, 'pct_remaining5m': null, 'sum': 0.7274, 'tx_atabove': 3.0, 'hashpower_accepting': 100.0, 'hpa_coef2': -0.067, 'total_seen_30m': 1.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 69.0, 'pct_mined_5m': null, 'total_seen_5m': null, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.52, 'avgdiff': 1, 'expectedWait': 2.0696924058, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 98.5152487961, 'pct_remaining5m': null, 'sum': 0.7274, 'tx_atabove': 3.0, 'hashpower_accepting': 100.0, 'hpa_coef2': -0.067, 'total_seen_30m': 1.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 70.0, 'pct_mined_5m': null, 'total_seen_5m': null, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.52, 'avgdiff': 1, 'expectedWait': 2.0696924058, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 98.5553772071, 'pct_remaining5m': 0.0, 'sum': 0.7274, 'tx_atabove': 3.0, 'hashpower_accepting': 100.0, 'hpa_coef2': -0.067, 'total_seen_30m': null, 'int2': 6.9238, 'pct_remaining30m': null, 'gasprice': 72.0, 'pct_mined_5m': 100.0, 'total_seen_5m': 2.0, 'pct_mined_30m': null, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.52, 'avgdiff': 1, 'expectedWait': 2.0696924058, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 98.5754414125, 'pct_remaining5m': 0.0, 'sum': 0.7274, 'tx_atabove': 3.0, 'hashpower_accepting': 100.0, 'hpa_coef2': -0.067, 'total_seen_30m': 1.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 73.0, 'pct_mined_5m': 100.0, 'total_seen_5m': 1.0, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.52, 'avgdiff': 1, 'expectedWait': 2.0696924058, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 98.5854735152, 'pct_remaining5m': 0.0, 'sum': 0.7274, 'tx_atabove': 3.0, 'hashpower_accepting': 100.0, 'hpa_coef2': -0.067, 'total_seen_30m': null, 'int2': 6.9238, 'pct_remaining30m': null, 'gasprice': 77.0, 'pct_mined_5m': 100.0, 'total_seen_5m': 1.0, 'pct_mined_30m': null, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.52, 'avgdiff': 1, 'expectedWait': 2.0696924058, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 98.6055377207, 'pct_remaining5m': null, 'sum': 0.7274, 'tx_atabove': 3.0, 'hashpower_accepting': 100.0, 'hpa_coef2': -0.067, 'total_seen_30m': 1.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 79.0, 'pct_mined_5m': null, 'total_seen_5m': null, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.52, 'avgdiff': 1, 'expectedWait': 2.0696924058, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 98.8663723917, 'pct_remaining5m': 0.0, 'sum': 0.7274, 'tx_atabove': 3.0, 'hashpower_accepting': 100.0, 'hpa_coef2': -0.067, 'total_seen_30m': 14.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 80.0, 'pct_mined_5m': 100.0, 'total_seen_5m': 6.0, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.52, 'avgdiff': 1, 'expectedWait': 2.0696924058, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 98.8864365971, 'pct_remaining5m': 0.0, 'sum': 0.7268, 'tx_atabove': 2.0, 'hashpower_accepting': 100.0, 'hpa_coef2': -0.067, 'total_seen_30m': 1.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 84.0, 'pct_mined_5m': 100.0, 'total_seen_5m': 1.0, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.52, 'avgdiff': 1, 'expectedWait': 2.0684509628, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 98.9466292135, 'pct_remaining5m': 0.0, 'sum': 0.7268, 'tx_atabove': 2.0, 'hashpower_accepting': 100.0, 'hpa_coef2': -0.067, 'total_seen_30m': 1.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 88.0, 'pct_mined_5m': 100.0, 'total_seen_5m': 1.0, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.52, 'avgdiff': 1, 'expectedWait': 2.0684509628, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 98.9566613162, 'pct_remaining5m': null, 'sum': 0.7268, 'tx_atabove': 2.0, 'hashpower_accepting': 100.0, 'hpa_coef2': -0.067, 'total_seen_30m': 1.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 90.0, 'pct_mined_5m': null, 'total_seen_5m': null, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.52, 'avgdiff': 1, 'expectedWait': 2.0684509628, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 99.0469502408, 'pct_remaining5m': 0.0, 'sum': 0.7268, 'tx_atabove': 2.0, 'hashpower_accepting': 100.0, 'hpa_coef2': -0.067, 'total_seen_30m': 4.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 91.0, 'pct_mined_5m': 100.0, 'total_seen_5m': 3.0, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.52, 'avgdiff': 1, 'expectedWait': 2.0684509628, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 99.1272070626, 'pct_remaining5m': 0.0, 'sum': 0.7268, 'tx_atabove': 2.0, 'hashpower_accepting': 100.0, 'hpa_coef2': -0.067, 'total_seen_30m': 3.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 96.0, 'pct_mined_5m': 100.0, 'total_seen_5m': 2.0, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.52, 'avgdiff': 1, 'expectedWait': 2.0684509628, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 99.1372391653, 'pct_remaining5m': 0.0, 'sum': 0.7268, 'tx_atabove': 2.0, 'hashpower_accepting': 100.0, 'hpa_coef2': -0.067, 'total_seen_30m': null, 'int2': 6.9238, 'pct_remaining30m': null, 'gasprice': 97.0, 'pct_mined_5m': 100.0, 'total_seen_5m': 1.0, 'pct_mined_30m': null, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.52, 'avgdiff': 1, 'expectedWait': 2.0684509628, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 99.1472712681, 'pct_remaining5m': 0.0, 'sum': 0.7268, 'tx_atabove': 2.0, 'hashpower_accepting': 100.0, 'hpa_coef2': -0.067, 'total_seen_30m': null, 'int2': 6.9238, 'pct_remaining30m': null, 'gasprice': 99.0, 'pct_mined_5m': 100.0, 'total_seen_5m': 1.0, 'pct_mined_30m': null, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.52, 'avgdiff': 1, 'expectedWait': 2.0684509628, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 99.7090690209, 'pct_remaining5m': 0.0, 'sum': 0.7268, 'tx_atabove': 2.0, 'hashpower_accepting': 100.0, 'hpa_coef2': -0.067, 'total_seen_30m': 23.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 100.0, 'pct_mined_5m': 100.0, 'total_seen_5m': 22.0, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.52, 'avgdiff': 1, 'expectedWait': 2.0684509628, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 99.8394863563, 'pct_remaining5m': 0.0, 'sum': 0.7268, 'tx_atabove': 2.0, 'hashpower_accepting': 100.0, 'hpa_coef2': -0.067, 'total_seen_30m': 7.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 101.0, 'pct_mined_5m': 100.0, 'total_seen_5m': 1.0, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.52, 'avgdiff': 1, 'expectedWait': 2.0684509628, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 99.9097110754, 'pct_remaining5m': 0.0, 'sum': 0.7268, 'tx_atabove': 2.0, 'hashpower_accepting': 100.0, 'hpa_coef2': -0.067, 'total_seen_30m': 2.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 120.0, 'pct_mined_5m': 100.0, 'total_seen_5m': 1.0, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.52, 'avgdiff': 1, 'expectedWait': 2.0684509628, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 99.9297752809, 'pct_remaining5m': 0.0, 'sum': 0.7268, 'tx_atabove': 2.0, 'hashpower_accepting': 100.0, 'hpa_coef2': -0.067, 'total_seen_30m': null, 'int2': 6.9238, 'pct_remaining30m': null, 'gasprice': 134.0, 'pct_mined_5m': 100.0, 'total_seen_5m': 2.0, 'pct_mined_30m': null, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.52, 'avgdiff': 1, 'expectedWait': 2.0684509628, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': 0.0, 'hashpower_accepting2': 99.9498394864, 'pct_remaining5m': 0.0, 'sum': 0.7268, 'tx_atabove': 2.0, 'hashpower_accepting': 100.0, 'hpa_coef2': -0.067, 'total_seen_30m': 1.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 137.0, 'pct_mined_5m': 100.0, 'total_seen_5m': 1.0, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.52, 'avgdiff': 1, 'expectedWait': 2.0684509628, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}, {'intercept': 4.8015, 'age': null, 'hashpower_accepting2': 99.9699036918, 'pct_remaining5m': null, 'sum': 0.7256, 'tx_atabove': 0.0, 'hashpower_accepting': 100.0, 'hpa_coef2': -0.067, 'total_seen_30m': 1.0, 'int2': 6.9238, 'pct_remaining30m': 0.0, 'gasprice': 180.0, 'pct_mined_5m': null, 'total_seen_5m': null, 'pct_mined_30m': 100.0, 'tx_atabove_coef': 0.0006, 'average': 600, 'safelow': 600, 'nomine': 550, 'expectedTime': 0.52, 'avgdiff': 1, 'expectedWait': 2.0659703104, 'avgdiff_coef': -1.6459, 'hpa_coef': -0.0243}]),
+ gasExpress: JSON.stringify({'safeLow': 2.0, 'standard': 3.0, 'fast': 10.0, 'fastest': 52.0, 'block_time': 15, 'blockNum': 6693030}),
+ metametrics: JSON.stringify({ 'mockMetaMetricsResponse': true }),
+}
diff --git a/test/e2e/beta/from-import-beta-ui.spec.js b/test/e2e/beta/from-import-beta-ui.spec.js
index d2c3f8958..8aa0fb628 100644
--- a/test/e2e/beta/from-import-beta-ui.spec.js
+++ b/test/e2e/beta/from-import-beta-ui.spec.js
@@ -16,8 +16,8 @@ const {
verboseReportOnFailure,
findElement,
findElements,
- loadExtension,
} = require('./helpers')
+const fetchMockResponses = require('./fetch-mocks.js')
describe('Using MetaMask with an existing account', function () {
@@ -27,7 +27,6 @@ describe('Using MetaMask with an existing account', function () {
const testSeedPhrase = 'phrase upgrade clock rough situate wedding elder clever doctor stamp excess tent'
const testAddress = '0xE18035BF8712672935FDB4e5e431b1a0183d2DFC'
const testPrivateKey2 = '14abe6f4aab7f9f626fe981c864d0adeb5685f289ac9270c27b8fd790b4235d6'
- const tinyDelayMs = 500
const regularDelayMs = 1000
const largeDelayMs = regularDelayMs * 2
@@ -35,13 +34,14 @@ describe('Using MetaMask with an existing account', function () {
this.bail(true)
before(async function () {
+ let extensionUrl
switch (process.env.SELENIUM_BROWSER) {
case 'chrome': {
const extensionPath = path.resolve('dist/chrome')
driver = buildChromeWebDriver(extensionPath)
extensionId = await getExtensionIdChrome(driver)
- await driver.get(`chrome-extension://${extensionId}/popup.html`)
await delay(regularDelayMs)
+ extensionUrl = `chrome-extension://${extensionId}/home.html`
break
}
case 'firefox': {
@@ -50,11 +50,34 @@ describe('Using MetaMask with an existing account', function () {
await installWebExt(driver, extensionPath)
await delay(regularDelayMs)
extensionId = await getExtensionIdFirefox(driver)
- await driver.get(`moz-extension://${extensionId}/popup.html`)
- await delay(regularDelayMs)
+ extensionUrl = `moz-extension://${extensionId}/home.html`
break
}
}
+ // Depending on the state of the application built into the above directory (extPath) and the value of
+ // METAMASK_DEBUG we will see different post-install behaviour and possibly some extra windows. Here we
+ // are closing any extraneous windows to reset us to a single window before continuing.
+ const [tab1] = await driver.getAllWindowHandles()
+ await closeAllWindowHandlesExcept(driver, [tab1])
+ await driver.switchTo().window(tab1)
+ await driver.get(extensionUrl)
+ })
+
+ beforeEach(async function () {
+ await driver.executeScript(
+ 'window.origFetch = window.fetch.bind(window);' +
+ 'window.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].match(/chromeextensionmm/)) { return ' +
+ 'Promise.resolve({ json: () => Promise.resolve(JSON.parse(\'' + fetchMockResponses.metametrics + '\')) }); } else if ' +
+ '(args[0] === "https://dev.blockscale.net/api/gasexpress.json") { return ' +
+ 'Promise.resolve({ json: () => Promise.resolve(JSON.parse(\'' + fetchMockResponses.gasExpress + '\')) }); } ' +
+ 'return window.origFetch(...args); }'
+ )
})
afterEach(async function () {
@@ -75,75 +98,28 @@ describe('Using MetaMask with an existing account', function () {
await driver.quit()
})
- describe('New UI setup', async function () {
- it('switches to first tab', async function () {
- await delay(tinyDelayMs)
- const [firstTab] = await driver.getAllWindowHandles()
- await driver.switchTo().window(firstTab)
- await delay(regularDelayMs)
+ describe('First time flow starting from an existing seed phrase', () => {
+ it('clicks the continue button on the welcome screen', async () => {
+ await findElement(driver, By.css('.welcome-page__header'))
+ const welcomeScreenBtn = await findElement(driver, By.css('.first-time-flow__button'))
+ welcomeScreenBtn.click()
+ await delay(largeDelayMs)
})
- it('selects the new UI option', async () => {
- try {
- const overlay = await findElement(driver, By.css('.full-flex-height'))
- await driver.wait(until.stalenessOf(overlay))
- } catch (e) {}
-
- let button
- try {
- button = await findElement(driver, By.xpath("//button[contains(text(), 'Try it now')]"))
- } catch (e) {
- await loadExtension(driver, extensionId)
- await delay(largeDelayMs)
- button = await findElement(driver, By.xpath("//button[contains(text(), 'Try it now')]"))
- }
- await button.click()
- await delay(regularDelayMs)
-
- // Close all other tabs
- const [tab0, tab1, tab2] = await driver.getAllWindowHandles()
- await driver.switchTo().window(tab0)
- await delay(tinyDelayMs)
-
- let selectedUrl = await driver.getCurrentUrl()
- await delay(tinyDelayMs)
- if (tab0 && selectedUrl.match(/popup.html/)) {
- await closeAllWindowHandlesExcept(driver, tab0)
- } else if (tab1) {
- await driver.switchTo().window(tab1)
- selectedUrl = await driver.getCurrentUrl()
- await delay(tinyDelayMs)
- if (selectedUrl.match(/popup.html/)) {
- await closeAllWindowHandlesExcept(driver, tab1)
- } else if (tab2) {
- await driver.switchTo().window(tab2)
- selectedUrl = await driver.getCurrentUrl()
- selectedUrl.match(/popup.html/) && await closeAllWindowHandlesExcept(driver, tab2)
- }
- } else {
- throw new Error('popup.html not found')
- }
- await delay(regularDelayMs)
- const [appTab] = await driver.getAllWindowHandles()
- await driver.switchTo().window(appTab)
- await delay(tinyDelayMs)
-
- await loadExtension(driver, extensionId)
- await delay(regularDelayMs)
+ it('clicks the "Import Wallet" option', async () => {
+ const customRpcButton = await findElement(driver, By.xpath(`//button[contains(text(), 'Import Wallet')]`))
+ customRpcButton.click()
+ await delay(largeDelayMs)
+ })
- const continueBtn = await findElement(driver, By.css('.welcome-screen__button'))
- await continueBtn.click()
- await delay(regularDelayMs)
+ it('clicks the "No thanks" option on the metametrics opt-in screen', async () => {
+ const optOutButton = await findElement(driver, By.css('.btn-default'))
+ optOutButton.click()
+ await delay(largeDelayMs)
})
- })
- describe('First time flow starting from an existing seed phrase', () => {
it('imports a seed phrase', async () => {
- const [seedPhrase] = await findElements(driver, By.xpath(`//a[contains(text(), 'Import with seed phrase')]`))
- await seedPhrase.click()
- await delay(regularDelayMs)
-
- const [seedTextArea] = await findElements(driver, By.css('textarea.import-account__secret-phrase'))
+ const [seedTextArea] = await findElements(driver, By.css('textarea.first-time-flow__textarea'))
await seedTextArea.sendKeys(testSeedPhrase)
await delay(regularDelayMs)
@@ -152,37 +128,18 @@ describe('Using MetaMask with an existing account', function () {
const [confirmPassword] = await findElements(driver, By.id('confirm-password'))
confirmPassword.sendKeys('correct horse battery staple')
+ const tosCheckBox = await findElement(driver, By.css('.first-time-flow__checkbox'))
+ await tosCheckBox.click()
+
const [importButton] = await findElements(driver, By.xpath(`//button[contains(text(), 'Import')]`))
await importButton.click()
await delay(regularDelayMs)
})
- it('clicks through the ToS', async () => {
- // terms of use
- const canClickThrough = await driver.findElement(By.css('.tou button')).isEnabled()
- assert.equal(canClickThrough, false, 'disabled continue button')
- const bottomOfTos = await findElement(driver, By.linkText('Attributions'))
- await driver.executeScript('arguments[0].scrollIntoView(true)', bottomOfTos)
- await delay(regularDelayMs)
- const acceptTos = await findElement(driver, By.css('.tou button'))
- await acceptTos.click()
- await delay(regularDelayMs)
- })
-
- it('clicks through the privacy notice', async () => {
- // privacy notice
- const nextScreen = await findElement(driver, By.css('.tou button'))
- await nextScreen.click()
- await delay(regularDelayMs)
- })
-
- it('clicks through the phishing notice', async () => {
- // phishing notice
- const noticeElement = await driver.findElement(By.css('.markdown'))
- await driver.executeScript('arguments[0].scrollTop = arguments[0].scrollHeight', noticeElement)
- await delay(regularDelayMs)
- const nextScreen = await findElement(driver, By.css('.tou button'))
- await nextScreen.click()
+ it('clicks through the success screen', async () => {
+ await findElement(driver, By.xpath(`//div[contains(text(), 'Congratulations')]`))
+ const doneButton = await findElement(driver, By.css('button.first-time-flow__button'))
+ await doneButton.click()
await delay(regularDelayMs)
})
})
@@ -280,7 +237,7 @@ describe('Using MetaMask with an existing account', function () {
})
describe('Send ETH from inside MetaMask', () => {
- it('starts to send a transaction', async function () {
+ it('starts a send transaction', async function () {
const sendButton = await findElement(driver, By.xpath(`//button[contains(text(), 'Send')]`))
await sendButton.click()
await delay(regularDelayMs)
@@ -291,7 +248,7 @@ describe('Using MetaMask with an existing account', function () {
await inputAmount.sendKeys('1')
// Set the gas limit
- const configureGas = await findElement(driver, By.css('.send-v2__gas-fee-display button'))
+ const configureGas = await findElement(driver, By.css('.advanced-gas-options-btn'))
await configureGas.click()
await delay(regularDelayMs)
@@ -373,36 +330,7 @@ describe('Using MetaMask with an existing account', function () {
await connectButtons[0].click()
await delay(regularDelayMs)
const allWindows = await driver.getAllWindowHandles()
- switch (process.env.SELENIUM_BROWSER) {
- case 'chrome':
- assert.equal(allWindows.length, 2)
- break
- default:
- assert.equal(allWindows.length, 1)
- }
- })
-
- it('should show the "Browser not supported" screen for non Chrome browsers', async () => {
- if (process.env.SELENIUM_BROWSER !== 'chrome') {
- const title = await findElements(driver, By.xpath(`//h3[contains(text(), 'Your Browser is not supported...')]`))
- assert.equal(title.length, 1)
-
- const downloadChromeButtons = await findElements(driver, By.xpath(`//button[contains(text(), 'Download Google Chrome')]`))
- assert.equal(downloadChromeButtons.length, 1)
-
- await downloadChromeButtons[0].click()
- await delay(regularDelayMs)
-
- const [newUITab, downloadChromeTab] = await driver.getAllWindowHandles()
-
- await driver.switchTo().window(downloadChromeTab)
- await delay(regularDelayMs)
- const tabUrl = await driver.getCurrentUrl()
- assert.equal(tabUrl, 'https://www.google.com/chrome/')
- await driver.close()
- await delay(regularDelayMs)
- await driver.switchTo().window(newUITab)
- }
+ assert.equal(allWindows.length, 2)
})
})
})
diff --git a/test/e2e/beta/helpers.js b/test/e2e/beta/helpers.js
index 08416857e..b6fc35e08 100644
--- a/test/e2e/beta/helpers.js
+++ b/test/e2e/beta/helpers.js
@@ -85,11 +85,22 @@ async function openNewPage (driver, url) {
await delay(1000)
}
-async function waitUntilXWindowHandles (driver, x) {
- const windowHandles = await driver.getAllWindowHandles()
- if (windowHandles.length === x) return
- await delay(1000)
- return await waitUntilXWindowHandles(driver, x)
+async function waitUntilXWindowHandles (driver, x, delayStep = 1000, timeout = 5000) {
+ let timeElapsed = 0
+ async function _pollWindowHandles () {
+ const windowHandles = await driver.getAllWindowHandles()
+ if (windowHandles.length === x) {
+ return
+ }
+ await delay(delayStep)
+ timeElapsed += delayStep
+ if (timeElapsed > timeout) {
+ throw new Error('waitUntilXWindowHandles timed out polling window handles')
+ } else {
+ await _pollWindowHandles()
+ }
+ }
+ return await _pollWindowHandles()
}
async function switchToWindowWithTitle (driver, title, windowHandles) {
@@ -109,6 +120,13 @@ async function switchToWindowWithTitle (driver, title, windowHandles) {
}
}
+/**
+ * Closes all windows except those in the given list of exceptions
+ * @param {object} driver the WebDriver instance
+ * @param {string|Array<string>} exceptions the list of window handle exceptions
+ * @param {Array?} windowHandles the full list of window handles
+ * @returns {Promise<void>}
+ */
async function closeAllWindowHandlesExcept (driver, exceptions, windowHandles) {
exceptions = typeof exceptions === 'string' ? [ exceptions ] : exceptions
windowHandles = windowHandles || await driver.getAllWindowHandles()
diff --git a/test/e2e/beta/metamask-beta-responsive-ui.spec.js b/test/e2e/beta/metamask-beta-responsive-ui.spec.js
index b93563b25..6df1da051 100644
--- a/test/e2e/beta/metamask-beta-responsive-ui.spec.js
+++ b/test/e2e/beta/metamask-beta-responsive-ui.spec.js
@@ -18,6 +18,7 @@ const {
loadExtension,
verboseReportOnFailure,
} = require('./helpers')
+const fetchMockResponses = require('./fetch-mocks.js')
describe('MetaMask', function () {
let extensionId
@@ -32,23 +33,50 @@ describe('MetaMask', function () {
this.bail(true)
before(async function () {
+ let extensionUrl
switch (process.env.SELENIUM_BROWSER) {
case 'chrome': {
const extPath = path.resolve('dist/chrome')
driver = buildChromeWebDriver(extPath, { responsive: true })
extensionId = await getExtensionIdChrome(driver)
- await driver.get(`chrome-extension://${extensionId}/popup.html`)
+ await delay(largeDelayMs)
+ extensionUrl = `chrome-extension://${extensionId}/home.html`
break
}
case 'firefox': {
const extPath = path.resolve('dist/firefox')
driver = buildFirefoxWebdriver({ responsive: true })
await installWebExt(driver, extPath)
- await delay(700)
+ await delay(largeDelayMs)
extensionId = await getExtensionIdFirefox(driver)
- await driver.get(`moz-extension://${extensionId}/popup.html`)
+ extensionUrl = `moz-extension://${extensionId}/home.html`
+ break
}
}
+ // Depending on the state of the application built into the above directory (extPath) and the value of
+ // METAMASK_DEBUG we will see different post-install behaviour and possibly some extra windows. Here we
+ // are closing any extraneous windows to reset us to a single window before continuing.
+ const [tab1] = await driver.getAllWindowHandles()
+ await closeAllWindowHandlesExcept(driver, [tab1])
+ await driver.switchTo().window(tab1)
+ await driver.get(extensionUrl)
+ })
+
+ beforeEach(async function () {
+ await driver.executeScript(
+ 'window.origFetch = window.fetch.bind(window);' +
+ 'window.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].match(/chromeextensionmm/)) { return ' +
+ 'Promise.resolve({ json: () => Promise.resolve(JSON.parse(\'' + fetchMockResponses.metametrics + '\')) }); } else if ' +
+ '(args[0] === "https://dev.blockscale.net/api/gasexpress.json") { return ' +
+ 'Promise.resolve({ json: () => Promise.resolve(JSON.parse(\'' + fetchMockResponses.gasExpress + '\')) }); } ' +
+ 'return window.origFetch(...args); }'
+ )
})
afterEach(async function () {
@@ -69,189 +97,111 @@ describe('MetaMask', function () {
await driver.quit()
})
- describe('New UI setup', async function () {
- it('switches to first tab', async function () {
- await delay(tinyDelayMs)
- const [firstTab] = await driver.getAllWindowHandles()
- await driver.switchTo().window(firstTab)
- await delay(regularDelayMs)
- })
-
- it('selects the new UI option', async () => {
- try {
- const overlay = await findElement(driver, By.css('.full-flex-height'))
- await driver.wait(until.stalenessOf(overlay))
- } catch (e) {}
-
- let button
- try {
- button = await findElement(driver, By.xpath("//button[contains(text(), 'Try it now')]"))
- } catch (e) {
- await loadExtension(driver, extensionId)
+ describe('Going through the first time flow', () => {
+ it('clicks the continue button on the welcome screen', async () => {
+ await findElement(driver, By.css('.welcome-page__header'))
+ const welcomeScreenBtn = await findElement(driver, By.css('.first-time-flow__button'))
+ welcomeScreenBtn.click()
await delay(largeDelayMs)
- button = await findElement(driver, By.xpath("//button[contains(text(), 'Try it now')]"))
- }
- await button.click()
- await delay(regularDelayMs)
+ })
- // Close all other tabs
- const [tab0, tab1, tab2] = await driver.getAllWindowHandles()
- await driver.switchTo().window(tab0)
- await delay(tinyDelayMs)
-
- let selectedUrl = await driver.getCurrentUrl()
- await delay(tinyDelayMs)
- if (tab0 && selectedUrl.match(/popup.html/)) {
- await closeAllWindowHandlesExcept(driver, tab0)
- } else if (tab1) {
- await driver.switchTo().window(tab1)
- selectedUrl = await driver.getCurrentUrl()
- await delay(tinyDelayMs)
- if (selectedUrl.match(/popup.html/)) {
- await closeAllWindowHandlesExcept(driver, tab1)
- } else if (tab2) {
- await driver.switchTo().window(tab2)
- selectedUrl = await driver.getCurrentUrl()
- selectedUrl.match(/popup.html/) && await closeAllWindowHandlesExcept(driver, tab2)
- }
- } else {
- throw new Error('popup.html not found')
- }
- await delay(regularDelayMs)
- const [appTab] = await driver.getAllWindowHandles()
- await driver.switchTo().window(appTab)
- await delay(tinyDelayMs)
-
- await loadExtension(driver, extensionId)
- await delay(regularDelayMs)
-
- const continueBtn = await findElement(driver, By.css('.welcome-screen__button'))
- await continueBtn.click()
- await delay(regularDelayMs)
- })
- })
-
- describe('Going through the first time flow', () => {
- it('accepts a secure password', async () => {
- const passwordBox = await findElement(driver, By.css('.create-password #create-password'))
- const passwordBoxConfirm = await findElement(driver, By.css('.create-password #confirm-password'))
- const button = await findElement(driver, By.css('.create-password button'))
-
- await passwordBox.sendKeys('correct horse battery staple')
- await passwordBoxConfirm.sendKeys('correct horse battery staple')
- await button.click()
- await delay(regularDelayMs)
- })
+ it('clicks the "Create New Wallet" option', async () => {
+ const customRpcButton = await findElement(driver, By.xpath(`//button[contains(text(), 'Create a Wallet')]`))
+ customRpcButton.click()
+ await delay(largeDelayMs)
+ })
- it('clicks through the unique image screen', async () => {
- const nextScreen = await findElement(driver, By.css('.unique-image button'))
- await nextScreen.click()
- await delay(regularDelayMs)
- })
+ it('clicks the "I agree" option on the metametrics opt-in screen', async () => {
+ const optOutButton = await findElement(driver, By.css('.btn-confirm'))
+ optOutButton.click()
+ await delay(largeDelayMs)
+ })
- it('clicks through the ToS', async () => {
- // terms of use
- const canClickThrough = await driver.findElement(By.css('.tou button')).isEnabled()
- assert.equal(canClickThrough, false, 'disabled continue button')
- const bottomOfTos = await findElement(driver, By.linkText('Attributions'))
- await driver.executeScript('arguments[0].scrollIntoView(true)', bottomOfTos)
- await delay(regularDelayMs)
- const acceptTos = await findElement(driver, By.css('.tou button'))
- driver.wait(until.elementIsEnabled(acceptTos))
- await acceptTos.click()
- await delay(regularDelayMs)
- })
+ it('accepts a secure password', async () => {
+ const passwordBox = await findElement(driver, By.css('.first-time-flow__form #create-password'))
+ const passwordBoxConfirm = await findElement(driver, By.css('.first-time-flow__form #confirm-password'))
+ const button = await findElement(driver, By.css('.first-time-flow__form button'))
- it('clicks through the privacy notice', async () => {
- // privacy notice
- const nextScreen = await findElement(driver, By.css('.tou button'))
- await nextScreen.click()
- await delay(regularDelayMs)
- })
+ await passwordBox.sendKeys('correct horse battery staple')
+ await passwordBoxConfirm.sendKeys('correct horse battery staple')
- it('clicks through the phishing notice', async () => {
- // phishing notice
- const noticeElement = await driver.findElement(By.css('.markdown'))
- await driver.executeScript('arguments[0].scrollTop = arguments[0].scrollHeight', noticeElement)
- await delay(regularDelayMs)
- const nextScreen = await findElement(driver, By.css('.tou button'))
- await nextScreen.click()
- await delay(regularDelayMs)
- })
+ const tosCheckBox = await findElement(driver, By.css('.first-time-flow__checkbox'))
+ await tosCheckBox.click()
- let seedPhrase
+ await button.click()
+ await delay(regularDelayMs)
+ })
- it('reveals the seed phrase', async () => {
- const byRevealButton = By.css('.backup-phrase__secret-blocker .backup-phrase__reveal-button')
- await driver.wait(until.elementLocated(byRevealButton, 10000))
- const revealSeedPhraseButton = await findElement(driver, byRevealButton, 10000)
- await revealSeedPhraseButton.click()
- await delay(regularDelayMs)
+ let seedPhrase
- seedPhrase = await driver.findElement(By.css('.backup-phrase__secret-words')).getText()
- assert.equal(seedPhrase.split(' ').length, 12)
- await delay(regularDelayMs)
+ it('reveals the seed phrase', async () => {
+ const byRevealButton = By.css('.reveal-seed-phrase__secret-blocker .reveal-seed-phrase__reveal-button')
+ await driver.wait(until.elementLocated(byRevealButton, 10000))
+ const revealSeedPhraseButton = await findElement(driver, byRevealButton, 10000)
+ await revealSeedPhraseButton.click()
+ await delay(regularDelayMs)
- const nextScreen = await findElement(driver, By.css('.backup-phrase button'))
- await nextScreen.click()
- await delay(regularDelayMs)
- })
+ seedPhrase = await driver.findElement(By.css('.reveal-seed-phrase__secret-words')).getText()
+ assert.equal(seedPhrase.split(' ').length, 12)
+ await delay(regularDelayMs)
- async function clickWordAndWait (word) {
- const xpathClass = 'backup-phrase__confirm-seed-option backup-phrase__confirm-seed-option--unselected'
- const xpath = `//button[@class='${xpathClass}' and contains(text(), '${word}')]`
- const word0 = await findElement(driver, By.xpath(xpath), 10000)
+ const nextScreen = await findElement(driver, By.css('button.first-time-flow__button'))
+ await nextScreen.click()
+ await delay(regularDelayMs)
+ })
- await word0.click()
- await delay(tinyDelayMs)
- }
+ async function clickWordAndWait (word) {
+ const xpath = `//div[contains(@class, 'confirm-seed-phrase__seed-word--shuffled') and not(contains(@class, 'confirm-seed-phrase__seed-word--selected')) and contains(text(), '${word}')]`
+ const word0 = await findElement(driver, By.xpath(xpath), 10000)
- async function retypeSeedPhrase (words, wasReloaded, count = 0) {
- try {
- if (wasReloaded) {
- const byRevealButton = By.css('.backup-phrase__secret-blocker .backup-phrase__reveal-button')
- await driver.wait(until.elementLocated(byRevealButton, 10000))
- const revealSeedPhraseButton = await findElement(driver, byRevealButton, 10000)
- await revealSeedPhraseButton.click()
- await delay(regularDelayMs)
-
- const nextScreen = await findElement(driver, By.css('.backup-phrase button'))
- await nextScreen.click()
- await delay(regularDelayMs)
- }
+ await word0.click()
+ await delay(tinyDelayMs)
+ }
- for (let i = 0; i < 12; i++) {
- await clickWordAndWait(words[i])
- }
- } catch (e) {
- if (count > 2) {
- throw e
- } else {
- await loadExtension(driver, extensionId)
- await retypeSeedPhrase(words, true, count + 1)
+ async function retypeSeedPhrase (words, wasReloaded, count = 0) {
+ try {
+ if (wasReloaded) {
+ const byRevealButton = By.css('.reveal-seed-phrase__secret-blocker .reveal-seed-phrase__reveal-button')
+ await driver.wait(until.elementLocated(byRevealButton, 10000))
+ const revealSeedPhraseButton = await findElement(driver, byRevealButton, 10000)
+ await revealSeedPhraseButton.click()
+ await delay(regularDelayMs)
+
+ const nextScreen = await findElement(driver, By.css('button.first-time-flow__button'))
+ await nextScreen.click()
+ await delay(regularDelayMs)
+ }
+
+ for (let i = 0; i < 12; i++) {
+ await clickWordAndWait(words[i])
+ }
+ } catch (e) {
+ if (count > 2) {
+ throw e
+ } else {
+ await loadExtension(driver, extensionId)
+ await retypeSeedPhrase(words, true, count + 1)
+ }
}
}
- }
- it('can retype the seed phrase', async () => {
- const words = seedPhrase.split(' ')
+ it('can retype the seed phrase', async () => {
+ const words = seedPhrase.split(' ')
- await retypeSeedPhrase(words)
+ await retypeSeedPhrase(words)
- const confirm = await findElement(driver, By.xpath(`//button[contains(text(), 'Confirm')]`))
- await confirm.click()
- await delay(regularDelayMs)
- })
+ const confirm = await findElement(driver, By.xpath(`//button[contains(text(), 'Confirm')]`))
+ await confirm.click()
+ await delay(regularDelayMs)
+ })
- it('clicks through the deposit modal', async () => {
- const byBuyModal = By.css('span .modal')
- const buyModal = await driver.wait(until.elementLocated(byBuyModal))
- const closeModal = await findElement(driver, By.css('.page-container__header-close'))
- await closeModal.click()
- await driver.wait(until.stalenessOf(buyModal))
- await delay(regularDelayMs)
+ it('clicks through the success screen', async () => {
+ await findElement(driver, By.xpath(`//div[contains(text(), 'Congratulations')]`))
+ const doneButton = await findElement(driver, By.css('button.first-time-flow__button'))
+ await doneButton.click()
+ await delay(regularDelayMs)
+ })
})
- })
describe('Show account information', () => {
it('show account details dropdown menu', async () => {
@@ -322,19 +272,24 @@ describe('MetaMask', function () {
const inputValue = await inputAmount.getAttribute('value')
assert.equal(inputValue, '1')
+ await delay(regularDelayMs)
+ })
+ it('opens and closes the gas modal', async function () {
// Set the gas limit
- const configureGas = await findElement(driver, By.css('.send-v2__gas-fee-display button'))
+ const configureGas = await findElement(driver, By.css('.advanced-gas-options-btn'))
await configureGas.click()
await delay(regularDelayMs)
const gasModal = await driver.findElement(By.css('span .modal'))
- const save = await findElement(driver, By.xpath(`//button[contains(text(), 'Save')]`))
+ const save = await findElement(driver, By.css('.page-container__header-close-text'))
await save.click()
- await driver.wait(until.stalenessOf(gasModal))
+ await driver.wait(until.stalenessOf(gasModal), 10000)
await delay(regularDelayMs)
+ })
+ it('clicks through to the confirm screen', async function () {
// Continue to next screen
const nextScreen = await findElement(driver, By.xpath(`//button[contains(text(), 'Next')]`))
await nextScreen.click()
diff --git a/test/e2e/beta/metamask-beta-ui.spec.js b/test/e2e/beta/metamask-beta-ui.spec.js
index 3bfa1eaf2..2700d1656 100644
--- a/test/e2e/beta/metamask-beta-ui.spec.js
+++ b/test/e2e/beta/metamask-beta-ui.spec.js
@@ -22,6 +22,7 @@ const {
verboseReportOnFailure,
waitUntilXWindowHandles,
} = require('./helpers')
+const fetchMockResponses = require('./fetch-mocks.js')
describe('MetaMask', function () {
let extensionId
@@ -37,23 +38,50 @@ describe('MetaMask', function () {
this.bail(true)
before(async function () {
+ let extensionUrl
switch (process.env.SELENIUM_BROWSER) {
case 'chrome': {
const extPath = path.resolve('dist/chrome')
driver = buildChromeWebDriver(extPath)
extensionId = await getExtensionIdChrome(driver)
- await driver.get(`chrome-extension://${extensionId}/popup.html`)
+ await delay(largeDelayMs)
+ extensionUrl = `chrome-extension://${extensionId}/home.html`
break
}
case 'firefox': {
const extPath = path.resolve('dist/firefox')
driver = buildFirefoxWebdriver()
await installWebExt(driver, extPath)
- await delay(700)
+ await delay(largeDelayMs)
extensionId = await getExtensionIdFirefox(driver)
- await driver.get(`moz-extension://${extensionId}/popup.html`)
+ extensionUrl = `moz-extension://${extensionId}/home.html`
+ break
}
}
+ // Depending on the state of the application built into the above directory (extPath) and the value of
+ // METAMASK_DEBUG we will see different post-install behaviour and possibly some extra windows. Here we
+ // are closing any extraneous windows to reset us to a single window before continuing.
+ const [tab1] = await driver.getAllWindowHandles()
+ await closeAllWindowHandlesExcept(driver, [tab1])
+ await driver.switchTo().window(tab1)
+ await driver.get(extensionUrl)
+ })
+
+ beforeEach(async function () {
+ await driver.executeScript(
+ 'window.origFetch = window.fetch.bind(window);' +
+ 'window.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].match(/chromeextensionmm/)) { return ' +
+ 'Promise.resolve({ json: () => Promise.resolve(JSON.parse(\'' + fetchMockResponses.metametrics + '\')) }); } else if ' +
+ '(args[0] === "https://dev.blockscale.net/api/gasexpress.json") { return ' +
+ 'Promise.resolve({ json: () => Promise.resolve(JSON.parse(\'' + fetchMockResponses.gasExpress + '\')) }); } ' +
+ 'return window.origFetch(...args); }'
+ )
})
afterEach(async function () {
@@ -74,137 +102,61 @@ describe('MetaMask', function () {
await driver.quit()
})
- describe('New UI setup', async function () {
- it('switches to first tab', async function () {
- await delay(tinyDelayMs)
- const [firstTab] = await driver.getAllWindowHandles()
- await driver.switchTo().window(firstTab)
- await delay(regularDelayMs)
+ describe('Going through the first time flow', () => {
+ it('clicks the continue button on the welcome screen', async () => {
+ await findElement(driver, By.css('.welcome-page__header'))
+ const welcomeScreenBtn = await findElement(driver, By.css('.first-time-flow__button'))
+ welcomeScreenBtn.click()
+ await delay(largeDelayMs)
})
- it('selects the new UI option', async () => {
- try {
- const overlay = await findElement(driver, By.css('.full-flex-height'))
- await driver.wait(until.stalenessOf(overlay))
- } catch (e) {}
-
- let button
- try {
- button = await findElement(driver, By.xpath("//button[contains(text(), 'Try it now')]"))
- } catch (e) {
- await loadExtension(driver, extensionId)
- await delay(largeDelayMs)
- button = await findElement(driver, By.xpath("//button[contains(text(), 'Try it now')]"))
- }
- await button.click()
- await delay(regularDelayMs)
-
- // Close all other tabs
- const [tab0, tab1, tab2] = await driver.getAllWindowHandles()
- await driver.switchTo().window(tab0)
- await delay(tinyDelayMs)
-
- let selectedUrl = await driver.getCurrentUrl()
- await delay(tinyDelayMs)
- if (tab0 && selectedUrl.match(/popup.html/)) {
- await closeAllWindowHandlesExcept(driver, tab0)
- } else if (tab1) {
- await driver.switchTo().window(tab1)
- selectedUrl = await driver.getCurrentUrl()
- await delay(tinyDelayMs)
- if (selectedUrl.match(/popup.html/)) {
- await closeAllWindowHandlesExcept(driver, tab1)
- } else if (tab2) {
- await driver.switchTo().window(tab2)
- selectedUrl = await driver.getCurrentUrl()
- selectedUrl.match(/popup.html/) && await closeAllWindowHandlesExcept(driver, tab2)
- }
- } else {
- throw new Error('popup.html not found')
- }
- await delay(regularDelayMs)
- const [appTab] = await driver.getAllWindowHandles()
- await driver.switchTo().window(appTab)
- await delay(tinyDelayMs)
-
- await loadExtension(driver, extensionId)
- await delay(regularDelayMs)
+ it('clicks the "Create New Wallet" option', async () => {
+ const customRpcButton = await findElement(driver, By.xpath(`//button[contains(text(), 'Create a Wallet')]`))
+ customRpcButton.click()
+ await delay(largeDelayMs)
+ })
- const continueBtn = await findElement(driver, By.css('.welcome-screen__button'))
- await continueBtn.click()
- await delay(regularDelayMs)
+ it('clicks the "No thanks" option on the metametrics opt-in screen', async () => {
+ const optOutButton = await findElement(driver, By.css('.btn-default'))
+ optOutButton.click()
+ await delay(largeDelayMs)
})
- })
- describe('Going through the first time flow', () => {
it('accepts a secure password', async () => {
- const passwordBox = await findElement(driver, By.css('.create-password #create-password'))
- const passwordBoxConfirm = await findElement(driver, By.css('.create-password #confirm-password'))
- const button = await findElement(driver, By.css('.create-password button'))
+ const passwordBox = await findElement(driver, By.css('.first-time-flow__form #create-password'))
+ const passwordBoxConfirm = await findElement(driver, By.css('.first-time-flow__form #confirm-password'))
+ const button = await findElement(driver, By.css('.first-time-flow__form button'))
await passwordBox.sendKeys('correct horse battery staple')
await passwordBoxConfirm.sendKeys('correct horse battery staple')
- await button.click()
- await delay(regularDelayMs)
- })
-
- it('clicks through the unique image screen', async () => {
- const nextScreen = await findElement(driver, By.css('.unique-image button'))
- await nextScreen.click()
- await delay(regularDelayMs)
- })
- it('clicks through the ToS', async () => {
- // terms of use
- const canClickThrough = await driver.findElement(By.css('.tou button')).isEnabled()
- assert.equal(canClickThrough, false, 'disabled continue button')
- const bottomOfTos = await findElement(driver, By.linkText('Attributions'))
- await driver.executeScript('arguments[0].scrollIntoView(true)', bottomOfTos)
- await delay(regularDelayMs)
- const acceptTos = await findElement(driver, By.css('.tou button'))
- driver.wait(until.elementIsEnabled(acceptTos))
- await acceptTos.click()
- await delay(regularDelayMs)
- })
-
- it('clicks through the privacy notice', async () => {
- // privacy notice
- const nextScreen = await findElement(driver, By.css('.tou button'))
- await nextScreen.click()
- await delay(regularDelayMs)
- })
+ const tosCheckBox = await findElement(driver, By.css('.first-time-flow__checkbox'))
+ await tosCheckBox.click()
- it('clicks through the phishing notice', async () => {
- // phishing notice
- const noticeElement = await driver.findElement(By.css('.markdown'))
- await driver.executeScript('arguments[0].scrollTop = arguments[0].scrollHeight', noticeElement)
- await delay(regularDelayMs)
- const nextScreen = await findElement(driver, By.css('.tou button'))
- await nextScreen.click()
+ await button.click()
await delay(regularDelayMs)
})
let seedPhrase
it('reveals the seed phrase', async () => {
- const byRevealButton = By.css('.backup-phrase__secret-blocker .backup-phrase__reveal-button')
+ const byRevealButton = By.css('.reveal-seed-phrase__secret-blocker .reveal-seed-phrase__reveal-button')
await driver.wait(until.elementLocated(byRevealButton, 10000))
const revealSeedPhraseButton = await findElement(driver, byRevealButton, 10000)
await revealSeedPhraseButton.click()
await delay(regularDelayMs)
- seedPhrase = await driver.findElement(By.css('.backup-phrase__secret-words')).getText()
+ seedPhrase = await driver.findElement(By.css('.reveal-seed-phrase__secret-words')).getText()
assert.equal(seedPhrase.split(' ').length, 12)
await delay(regularDelayMs)
- const nextScreen = await findElement(driver, By.css('.backup-phrase button'))
+ const nextScreen = await findElement(driver, By.css('button.first-time-flow__button'))
await nextScreen.click()
await delay(regularDelayMs)
})
async function clickWordAndWait (word) {
- const xpathClass = 'backup-phrase__confirm-seed-option backup-phrase__confirm-seed-option--unselected'
- const xpath = `//button[@class='${xpathClass}' and contains(text(), '${word}')]`
+ const xpath = `//div[contains(@class, 'confirm-seed-phrase__seed-word--shuffled') and not(contains(@class, 'confirm-seed-phrase__seed-word--selected')) and contains(text(), '${word}')]`
const word0 = await findElement(driver, By.xpath(xpath), 10000)
await word0.click()
@@ -214,13 +166,13 @@ describe('MetaMask', function () {
async function retypeSeedPhrase (words, wasReloaded, count = 0) {
try {
if (wasReloaded) {
- const byRevealButton = By.css('.backup-phrase__secret-blocker .backup-phrase__reveal-button')
+ const byRevealButton = By.css('.reveal-seed-phrase__secret-blocker .reveal-seed-phrase__reveal-button')
await driver.wait(until.elementLocated(byRevealButton, 10000))
const revealSeedPhraseButton = await findElement(driver, byRevealButton, 10000)
await revealSeedPhraseButton.click()
await delay(regularDelayMs)
- const nextScreen = await findElement(driver, By.css('.backup-phrase button'))
+ const nextScreen = await findElement(driver, By.css('button.first-time-flow__button'))
await nextScreen.click()
await delay(regularDelayMs)
}
@@ -248,12 +200,10 @@ describe('MetaMask', function () {
await delay(regularDelayMs)
})
- it('clicks through the deposit modal', async () => {
- const byBuyModal = By.css('span .modal')
- const buyModal = await driver.wait(until.elementLocated(byBuyModal))
- const closeModal = await findElement(driver, By.css('.page-container__header-close'))
- await closeModal.click()
- await driver.wait(until.stalenessOf(buyModal))
+ it('clicks through the success screen', async () => {
+ await findElement(driver, By.xpath(`//div[contains(text(), 'Congratulations')]`))
+ const doneButton = await findElement(driver, By.css('button.first-time-flow__button'))
+ await doneButton.click()
await delay(regularDelayMs)
})
})
@@ -283,7 +233,11 @@ describe('MetaMask', function () {
await customRpcButton.click()
await delay(regularDelayMs)
- const privacyToggle = await findElement(driver, By.css('.settings-page__content-row:nth-of-type(10) .settings-page__content-item-col > div'))
+ const securityTab = await findElement(driver, By.xpath(`//div[contains(text(), 'Security & Privacy')]`))
+ await securityTab.click()
+ await delay(regularDelayMs)
+
+ const privacyToggle = await findElement(driver, By.css('.settings-page__content-row:nth-of-type(1) .settings-page__content-item-col > div'))
await privacyToggle.click()
await delay(largeDelayMs * 2)
})
@@ -381,8 +335,88 @@ describe('MetaMask', function () {
})
})
- describe('Send ETH from inside MetaMask', () => {
- it('starts to send a transaction', async function () {
+ describe('Send ETH from inside MetaMask using default gas', () => {
+ it('starts a send transaction', async function () {
+ const sendButton = await findElement(driver, By.xpath(`//button[contains(text(), 'Send')]`))
+ await sendButton.click()
+ await delay(regularDelayMs)
+
+ const inputAddress = await findElement(driver, By.css('input[placeholder="Recipient Address"]'))
+ const inputAmount = await findElement(driver, By.css('.unit-input__input'))
+ await inputAddress.sendKeys('0x2f318C334780961FB129D2a6c30D0763d9a5C970')
+ await inputAmount.sendKeys('1')
+
+ const inputValue = await inputAmount.getAttribute('value')
+ assert.equal(inputValue, '1')
+ await delay(regularDelayMs)
+
+ // Continue to next screen
+ const nextScreen = await findElement(driver, By.xpath(`//button[contains(text(), 'Next')]`))
+ await nextScreen.click()
+ await delay(regularDelayMs)
+ })
+
+ it('confirms the transaction', async function () {
+ const confirmButton = await findElement(driver, By.xpath(`//button[contains(text(), 'Confirm')]`))
+ await confirmButton.click()
+ await delay(largeDelayMs)
+ })
+
+ it('finds the transaction in the transactions list', async function () {
+ const transactions = await findElements(driver, By.css('.transaction-list-item'))
+ assert.equal(transactions.length, 1)
+
+ if (process.env.SELENIUM_BROWSER !== 'firefox') {
+ const txValues = await findElement(driver, By.css('.transaction-list-item__amount--primary'))
+ await driver.wait(until.elementTextMatches(txValues, /-1\s*ETH/), 10000)
+ }
+ })
+ })
+
+ describe('Send ETH from inside MetaMask using fast gas option', () => {
+ it('starts a send transaction', async function () {
+ const sendButton = await findElement(driver, By.xpath(`//button[contains(text(), 'Send')]`))
+ await sendButton.click()
+ await delay(regularDelayMs)
+
+ const inputAddress = await findElement(driver, By.css('input[placeholder="Recipient Address"]'))
+ const inputAmount = await findElement(driver, By.css('.unit-input__input'))
+ await inputAddress.sendKeys('0x2f318C334780961FB129D2a6c30D0763d9a5C970')
+ await inputAmount.sendKeys('1')
+
+ const inputValue = await inputAmount.getAttribute('value')
+ assert.equal(inputValue, '1')
+
+ // Set the gas price
+ const fastGas = await findElement(driver, By.xpath(`//button/div/div[contains(text(), "Fast")]`))
+ await fastGas.click()
+ await delay(regularDelayMs)
+
+ // Continue to next screen
+ const nextScreen = await findElement(driver, By.xpath(`//button[contains(text(), 'Next')]`))
+ await nextScreen.click()
+ await delay(regularDelayMs)
+ })
+
+ it('confirms the transaction', async function () {
+ const confirmButton = await findElement(driver, By.xpath(`//button[contains(text(), 'Confirm')]`))
+ await confirmButton.click()
+ await delay(largeDelayMs)
+ })
+
+ it('finds the transaction in the transactions list', async function () {
+ const transactions = await findElements(driver, By.css('.transaction-list-item'))
+ assert.equal(transactions.length, 2)
+
+ if (process.env.SELENIUM_BROWSER !== 'firefox') {
+ const txValues = await findElement(driver, By.css('.transaction-list-item__amount--primary'))
+ await driver.wait(until.elementTextMatches(txValues, /-1\s*ETH/), 10000)
+ }
+ })
+ })
+
+ describe('Send ETH from inside MetaMask using advanced gas modal', () => {
+ it('starts a send transaction', async function () {
const sendButton = await findElement(driver, By.xpath(`//button[contains(text(), 'Send')]`))
await sendButton.click()
await delay(regularDelayMs)
@@ -396,12 +430,11 @@ describe('MetaMask', function () {
assert.equal(inputValue, '1')
// Set the gas limit
- const configureGas = await findElement(driver, By.css('.send-v2__gas-fee-display button'))
+ const configureGas = await findElement(driver, By.css('.advanced-gas-options-btn'))
await configureGas.click()
await delay(regularDelayMs)
const gasModal = await driver.findElement(By.css('span .modal'))
-
const save = await findElement(driver, By.xpath(`//button[contains(text(), 'Save')]`))
await save.click()
await driver.wait(until.stalenessOf(gasModal))
@@ -421,7 +454,7 @@ describe('MetaMask', function () {
it('finds the transaction in the transactions list', async function () {
const transactions = await findElements(driver, By.css('.transaction-list-item'))
- assert.equal(transactions.length, 1)
+ assert.equal(transactions.length, 3)
if (process.env.SELENIUM_BROWSER !== 'firefox') {
const txValues = await findElement(driver, By.css('.transaction-list-item__amount--primary'))
@@ -430,12 +463,43 @@ describe('MetaMask', function () {
})
})
- describe('Send ETH from dapp', () => {
+ describe('Send ETH from dapp using advanced gas controls', () => {
let windowHandles
let extension
let popup
let dapp
+ it('goes to the settings screen', async () => {
+ await driver.findElement(By.css('.account-menu__icon')).click()
+ await delay(regularDelayMs)
+
+ const settingsButton = await findElement(driver, By.xpath(`//div[contains(text(), 'Settings')]`))
+ settingsButton.click()
+
+ // await findElement(driver, By.css('.tab-bar'))
+
+ const advancedTab = await findElement(driver, By.xpath(`//div[contains(text(), 'Advanced')]`))
+ await advancedTab.click()
+ await delay(regularDelayMs)
+
+ const showConversionToggle = await findElement(driver, By.css('.settings-page__content-row:nth-of-type(7) .settings-page__content-item-col > div'))
+ await showConversionToggle.click()
+
+ const advancedGasTitle = await findElement(driver, By.xpath(`//span[contains(text(), 'Advanced gas controls')]`))
+ await driver.executeScript('arguments[0].scrollIntoView(true)', advancedGasTitle)
+
+ const advancedGasToggle = await findElement(driver, By.css('.settings-page__content-row:nth-of-type(5) .settings-page__content-item-col > div'))
+ await advancedGasToggle.click()
+ windowHandles = await driver.getAllWindowHandles()
+ extension = windowHandles[0]
+ await closeAllWindowHandlesExcept(driver, [extension])
+
+ const metamaskHomeButton = await findElement(driver, By.css('.app-header__logo-container'))
+ await metamaskHomeButton.click()
+
+ await delay(largeDelayMs)
+ })
+
it('starts a send transaction inside the dapp', async () => {
await openNewPage(driver, 'http://127.0.0.1:8080/')
await delay(regularDelayMs)
@@ -450,12 +514,12 @@ describe('MetaMask', function () {
await delay(regularDelayMs)
const approveButton = await findElement(driver, By.xpath(`//button[contains(text(), 'Connect')]`))
await approveButton.click()
- })
- it('initiates a send from the dapp', async () => {
await driver.switchTo().window(dapp)
await delay(regularDelayMs)
+ })
+ it('initiates a send from the dapp', async () => {
const send3eth = await findElement(driver, By.xpath(`//button[contains(text(), 'Send')]`), 10000)
await send3eth.click()
await delay(5000)
@@ -466,6 +530,17 @@ describe('MetaMask', function () {
await assertElementNotPresent(webdriver, driver, By.xpath(`//li[contains(text(), 'Data')]`))
+ const [gasPriceInput, gasLimitInput] = await findElements(driver, By.css('.advanced-gas-inputs__gas-edit-row__input'))
+ await gasPriceInput.clear()
+ await delay(tinyDelayMs)
+
+ await gasPriceInput.sendKeys(Key.BACK_SPACE)
+ await gasPriceInput.sendKeys(Key.BACK_SPACE)
+ await gasPriceInput.sendKeys('10')
+ await delay(tinyDelayMs)
+ await gasLimitInput.sendKeys('5')
+ await delay(tinyDelayMs)
+
const confirmButton = await findElement(driver, By.xpath(`//button[contains(text(), 'Confirm')]`), 10000)
await confirmButton.click()
await delay(regularDelayMs)
@@ -475,12 +550,177 @@ describe('MetaMask', function () {
await delay(regularDelayMs)
})
+ let txValues
+
it('finds the transaction in the transactions list', async function () {
const transactions = await findElements(driver, By.css('.transaction-list-item'))
- assert.equal(transactions.length, 2)
+ assert.equal(transactions.length, 4)
- const txValues = await findElement(driver, By.css('.transaction-list-item__amount--primary'))
- await driver.wait(until.elementTextMatches(txValues, /-3\s*ETH/), 10000)
+ txValues = await findElements(driver, By.css('.transaction-list-item__amount--primary'))
+ await driver.wait(until.elementTextMatches(txValues[0], /-3\s*ETH/), 10000)
+ })
+
+ it('the transaction has the expected gas price', async function () {
+ await delay(largeDelayMs)
+ let txGasPriceLabels
+ let txGasPrices
+ try {
+ await txValues[0].click()
+ txGasPrices = await findElements(driver, By.css('.transaction-breakdown__value'))
+ txGasPriceLabels = await findElements(driver, By.css('.transaction-breakdown-row__title'))
+ txGasPrices = await findElements(driver, By.css('.transaction-breakdown__value'))
+ await driver.wait(until.elementTextMatches(txGasPrices[3], /^10$/), 10000)
+ } catch (e) {
+ console.log(e.message)
+ txValues = await findElements(driver, By.css('.transaction-list-item__amount--primary'))
+ await txValues[0].click()
+ txGasPriceLabels = await findElements(driver, By.css('.transaction-breakdown-row__title'))
+ txGasPrices = await findElements(driver, By.css('.transaction-breakdown__value'))
+ await driver.wait(until.elementTextMatches(txGasPrices[3], /^10$/), 10000)
+ }
+ assert(txGasPriceLabels[2])
+
+ await txValues[0].click()
+ })
+ })
+
+ describe('Navigate transactions', () => {
+ it('adds multiple transactions', async () => {
+ await delay(regularDelayMs)
+
+ await waitUntilXWindowHandles(driver, 2)
+ const windowHandles = await driver.getAllWindowHandles()
+ const extension = windowHandles[0]
+ const dapp = windowHandles[1]
+
+ await driver.switchTo().window(dapp)
+ await delay(regularDelayMs)
+
+ const send3eth = await findElement(driver, By.xpath(`//button[contains(text(), 'Send')]`), 10000)
+ await send3eth.click()
+ await delay(regularDelayMs)
+
+ const contractDeployment = await findElement(driver, By.xpath(`//button[contains(text(), 'Deploy Contract')]`), 10000)
+ await contractDeployment.click()
+ await delay(regularDelayMs)
+
+ await send3eth.click()
+ await contractDeployment.click()
+ await delay(regularDelayMs)
+
+ await driver.switchTo().window(extension)
+ await delay(regularDelayMs)
+
+ const transactions = await findElements(driver, By.css('.transaction-list-item'))
+ await transactions[3].click()
+ await delay(regularDelayMs)
+ })
+
+ it('navigates the transactions', async () => {
+ let navigateTxButtons = await findElements(driver, By.css('.confirm-page-container-navigation__arrow'), 20000)
+ assert.equal(navigateTxButtons.length, 4, 'navigation button present')
+
+ await navigateTxButtons[2].click()
+ let navigationElement = await findElement(driver, By.css('.confirm-page-container-navigation'))
+ let navigationText = await navigationElement.getText()
+ assert.equal(navigationText.includes('2'), true, 'changed transaction right')
+
+ navigateTxButtons = await findElements(driver, By.css('.confirm-page-container-navigation__arrow'))
+ await navigateTxButtons[2].click()
+ navigationElement = await findElement(driver, By.css('.confirm-page-container-navigation'))
+ navigationText = await navigationElement.getText()
+ assert.equal(navigationText.includes('3'), true, 'changed transaction right')
+
+ navigateTxButtons = await findElements(driver, By.css('.confirm-page-container-navigation__arrow'))
+ await navigateTxButtons[2].click()
+ navigationElement = await findElement(driver, By.css('.confirm-page-container-navigation'))
+ navigationText = await navigationElement.getText()
+ assert.equal(navigationText.includes('4'), true, 'changed transaction right')
+
+ navigateTxButtons = await findElements(driver, By.css('.confirm-page-container-navigation__arrow'))
+ await navigateTxButtons[0].click()
+ navigationElement = await findElement(driver, By.css('.confirm-page-container-navigation'))
+ navigationText = await navigationElement.getText()
+ assert.equal(navigationText.includes('1'), true, 'navigate to first transaction')
+
+ navigateTxButtons = await findElements(driver, By.css('.confirm-page-container-navigation__arrow'))
+ await navigateTxButtons[3].click()
+ navigationElement = await findElement(driver, By.css('.confirm-page-container-navigation'))
+ navigationText = await navigationElement.getText()
+ assert.equal(navigationText.split('4').length, 3, 'navigate to last transaction')
+
+ navigateTxButtons = await findElements(driver, By.css('.confirm-page-container-navigation__arrow'))
+ await navigateTxButtons[1].click()
+ navigationElement = await findElement(driver, By.css('.confirm-page-container-navigation'))
+ navigationText = await navigationElement.getText()
+ assert.equal(navigationText.includes('3'), true, 'changed transaction left')
+
+ navigateTxButtons = await findElements(driver, By.css('.confirm-page-container-navigation__arrow'))
+ await navigateTxButtons[1].click()
+ navigationElement = await findElement(driver, By.css('.confirm-page-container-navigation'))
+ navigationText = await navigationElement.getText()
+ assert.equal(navigationText.includes('2'), true, 'changed transaction left')
+ })
+
+ it('adds a transaction while confirm screen is in focus', async () => {
+ let navigationElement = await findElement(driver, By.css('.confirm-page-container-navigation'))
+ let navigationText = await navigationElement.getText()
+ assert.equal(navigationText.includes('2'), true, 'second transaction in focus')
+
+ const windowHandles = await driver.getAllWindowHandles()
+ const extension = windowHandles[0]
+ const dapp = windowHandles[1]
+
+ await driver.switchTo().window(dapp)
+ await delay(regularDelayMs)
+
+ const send3eth = await findElement(driver, By.xpath(`//button[contains(text(), 'Send')]`), 10000)
+ await send3eth.click()
+ await delay(regularDelayMs)
+
+ await driver.switchTo().window(extension)
+ await delay(regularDelayMs)
+
+ navigationElement = await findElement(driver, By.css('.confirm-page-container-navigation'))
+ navigationText = await navigationElement.getText()
+ assert.equal(navigationText.includes('3'), true, 'correct transaction in focus')
+ })
+
+ it('confirms a transaction', async () => {
+ const confirmButton = await findElement(driver, By.xpath(`//button[contains(text(), 'Confirm')]`), 10000)
+ await confirmButton.click()
+ await delay(regularDelayMs)
+
+ const navigationElement = await findElement(driver, By.css('.confirm-page-container-navigation'))
+ const navigationText = await navigationElement.getText()
+ assert.equal(navigationText.includes('4'), true, 'transaction confirmed')
+ })
+
+ it('rejects a transaction', async () => {
+ await delay(tinyDelayMs / 2)
+ const rejectButton = await findElement(driver, By.xpath(`//button[contains(text(), 'Reject')]`), 10000)
+ await delay(tinyDelayMs / 2)
+ await rejectButton.click()
+ await delay(regularDelayMs)
+
+ const navigationElement = await findElement(driver, By.css('.confirm-page-container-navigation'))
+ await delay(tinyDelayMs / 2)
+ const navigationText = await navigationElement.getText()
+ await delay(tinyDelayMs / 2)
+ assert.equal(navigationText.includes('3'), true, 'transaction rejected')
+ })
+
+ it('rejects the rest of the transactions', async () => {
+ const rejectAllButton = await findElement(driver, By.xpath(`//a[contains(text(), 'Reject 3')]`), 10000)
+ await rejectAllButton.click()
+ await delay(regularDelayMs)
+
+ const rejectButton = await findElement(driver, By.xpath(`//button[contains(text(), 'Reject All')]`), 10000)
+ await rejectButton.click()
+ await delay(largeDelayMs * 2)
+
+ const confirmedTxes = await findElements(driver, By.css('.transaction-list__completed-transactions .transaction-list-item'))
+ assert.equal(confirmedTxes.length, 5, '5 transactions present')
})
})
@@ -529,9 +769,9 @@ describe('MetaMask', function () {
await confirmButton.click()
await delay(largeDelayMs)
- driver.wait(async () => {
+ await driver.wait(async () => {
const confirmedTxes = await findElements(driver, By.css('.transaction-list__completed-transactions .transaction-list-item'))
- return confirmedTxes.length === 3
+ return confirmedTxes.length === 6
}, 10000)
const txAction = await findElements(driver, By.css('.transaction-list-item__action'))
@@ -568,9 +808,12 @@ describe('MetaMask', function () {
await delay(regularDelayMs)
const gasModal = await findElement(driver, By.css('span .modal'))
- await driver.wait(until.elementLocated(By.css('.customize-gas__title')), 10000)
+ await delay(regularDelayMs)
+ const modalTabs = await findElements(driver, By.css('.page-container__tab'))
+ await modalTabs[1].click()
+ await delay(regularDelayMs)
- const [gasPriceInput, gasLimitInput] = await findElements(driver, By.css('.customize-gas-input'))
+ const [gasPriceInput, gasLimitInput] = await findElements(driver, By.css('.advanced-tab__gas-edit-row__input'))
await gasPriceInput.clear()
await gasPriceInput.sendKeys('10')
await gasLimitInput.clear()
@@ -586,9 +829,9 @@ describe('MetaMask', function () {
await confirmButton.click()
await delay(regularDelayMs)
- driver.wait(async () => {
+ await driver.wait(async () => {
const confirmedTxes = await findElements(driver, By.css('.transaction-list__completed-transactions .transaction-list-item'))
- return confirmedTxes.length === 4
+ return confirmedTxes.length === 7
}, 10000)
const txValues = await findElements(driver, By.css('.transaction-list-item__amount--primary'))
@@ -618,9 +861,9 @@ describe('MetaMask', function () {
await confirmButton.click()
await delay(regularDelayMs)
- driver.wait(async () => {
+ await driver.wait(async () => {
const confirmedTxes = await findElements(driver, By.css('.transaction-list__completed-transactions .transaction-list-item'))
- return confirmedTxes.length === 5
+ return confirmedTxes.length === 8
}, 10000)
const txValues = await findElement(driver, By.css('.transaction-list-item__amount--primary'))
@@ -634,9 +877,9 @@ describe('MetaMask', function () {
const balance = await findElement(driver, By.css('.transaction-view-balance__primary-balance'))
await delay(regularDelayMs)
if (process.env.SELENIUM_BROWSER !== 'firefox') {
- await driver.wait(until.elementTextMatches(balance, /^92.*\s*ETH.*$/), 10000)
+ await driver.wait(until.elementTextMatches(balance, /^87.*\s*ETH.*$/), 10000)
const tokenAmount = await balance.getText()
- assert.ok(/^92.*\s*ETH.*$/.test(tokenAmount))
+ assert.ok(/^87.*\s*ETH.*$/.test(tokenAmount))
await delay(regularDelayMs)
}
})
@@ -661,6 +904,22 @@ describe('MetaMask', function () {
await driver.switchTo().window(popup)
await delay(regularDelayMs)
+ const configureGas = await driver.wait(until.elementLocated(By.css('.confirm-detail-row__header-text--edit')), 10000)
+ await configureGas.click()
+ await delay(regularDelayMs)
+
+ const advancedTabButton = await driver.wait(until.elementLocated(By.xpath(`//li[contains(text(), 'Advanced')]`)), 10000)
+ await advancedTabButton.click()
+ await delay(tinyDelayMs)
+
+ const [gasPriceInput, gasLimitInput] = await findElements(driver, By.css('.advanced-tab__gas-edit-row__input'))
+ assert(gasPriceInput.getAttribute('value'), 20)
+ assert(gasLimitInput.getAttribute('value'), 4700000)
+
+ const saveButton = await findElement(driver, By.xpath(`//button[contains(text(), 'Save')]`))
+ await saveButton.click()
+ await delay(regularDelayMs)
+
const confirmButton = await findElement(driver, By.xpath(`//button[contains(text(), 'Confirm')]`))
await confirmButton.click()
await delay(regularDelayMs)
@@ -704,7 +963,7 @@ describe('MetaMask', function () {
})
it('renders the balance for the new token', async () => {
- const balance = await findElement(driver, By.css('.transaction-view-balance .transaction-view-balance__token-balance'))
+ const balance = await findElement(driver, By.css('.transaction-view-balance .transaction-view-balance__primary-balance'))
await driver.wait(until.elementTextMatches(balance, /^100\s*TST\s*$/))
const tokenAmount = await balance.getText()
assert.ok(/^100\s*TST\s*$/.test(tokenAmount))
@@ -725,15 +984,16 @@ describe('MetaMask', function () {
await inputAmount.sendKeys('50')
// Set the gas limit
- const configureGas = await findElement(driver, By.css('.send-v2__gas-fee-display button'))
+ const configureGas = await findElement(driver, By.css('.advanced-gas-options-btn'))
await configureGas.click()
await delay(regularDelayMs)
gasModal = await driver.findElement(By.css('span .modal'))
+ await delay(regularDelayMs)
})
- it('opens customizes gas modal', async () => {
- await driver.wait(until.elementLocated(By.css('.send-v2__customize-gas__title')))
+ it('opens customize gas modal', async () => {
+ await driver.wait(until.elementLocated(By.css('.page-container__title')))
const save = await findElement(driver, By.xpath(`//button[contains(text(), 'Save')]`))
await save.click()
await delay(regularDelayMs)
@@ -785,7 +1045,7 @@ describe('MetaMask', function () {
await driver.wait(until.elementTextMatches(txValues[0], /-50\s*TST/), 10000)
}
- driver.wait(async () => {
+ await driver.wait(async () => {
const confirmedTxes = await findElements(driver, By.css('.transaction-list__completed-transactions .transaction-list-item'))
return confirmedTxes.length === 1
}, 10000)
@@ -801,7 +1061,6 @@ describe('MetaMask', function () {
const windowHandles = await driver.getAllWindowHandles()
const extension = windowHandles[0]
const dapp = await switchToWindowWithTitle(driver, 'E2E Test Dapp', windowHandles)
- await closeAllWindowHandlesExcept(driver, [extension, dapp])
await delay(regularDelayMs)
await driver.switchTo().window(dapp)
@@ -810,7 +1069,6 @@ describe('MetaMask', function () {
const transferTokens = await findElement(driver, By.xpath(`//button[contains(text(), 'Transfer Tokens')]`))
await transferTokens.click()
- await closeAllWindowHandlesExcept(driver, [extension, dapp])
await driver.switchTo().window(extension)
await delay(largeDelayMs)
@@ -829,31 +1087,36 @@ describe('MetaMask', function () {
})
it('customizes gas', async () => {
- await driver.wait(until.elementLocated(By.css('.customize-gas__title')))
+ const modalTabs = await findElements(driver, By.css('.page-container__tab'))
+ await modalTabs[1].click()
+ await delay(regularDelayMs)
- const [gasPriceInput, gasLimitInput] = await findElements(driver, By.css('.customize-gas-input'))
+ const [gasPriceInput, gasLimitInput] = await findElements(driver, By.css('.advanced-tab__gas-edit-row__input'))
await gasPriceInput.clear()
await delay(tinyDelayMs)
+
+ await gasPriceInput.sendKeys(Key.BACK_SPACE)
+ await gasPriceInput.sendKeys(Key.BACK_SPACE)
await gasPriceInput.sendKeys('10')
await delay(tinyDelayMs)
await gasLimitInput.clear()
await delay(tinyDelayMs)
await gasLimitInput.sendKeys(Key.chord(Key.CONTROL, 'a'))
+ await gasLimitInput.sendKeys(Key.BACK_SPACE)
+ await gasLimitInput.sendKeys(Key.BACK_SPACE)
+ await gasLimitInput.sendKeys(Key.BACK_SPACE)
+ await gasLimitInput.sendKeys(Key.BACK_SPACE)
+ await gasLimitInput.sendKeys(Key.BACK_SPACE)
await gasLimitInput.sendKeys('60000')
await gasLimitInput.sendKeys(Key.chord(Key.CONTROL, 'e'))
- // Needed for different behaviour of input in different versions of firefox
- const gasLimitInputValue = await gasLimitInput.getAttribute('value')
- if (gasLimitInputValue === '600001') {
- await gasLimitInput.sendKeys(Key.BACK_SPACE)
- }
-
- const save = await findElement(driver, By.css('.customize-gas__save'))
+ const save = await findElement(driver, By.css('.page-container__footer-button'))
await save.click()
await driver.wait(until.stalenessOf(gasModal))
const gasFeeInputs = await findElements(driver, By.css('.confirm-detail-row__primary'))
- assert.equal(await gasFeeInputs[0].getText(), '0.0006')
+ const renderedGasFee = await gasFeeInputs[0].getText()
+ assert.equal(renderedGasFee, '0.0006')
})
it('submits the transaction', async function () {
@@ -863,15 +1126,16 @@ describe('MetaMask', function () {
})
it('finds the transaction in the transactions list', async function () {
- driver.wait(async () => {
+ await driver.wait(async () => {
const confirmedTxes = await findElements(driver, By.css('.transaction-list__completed-transactions .transaction-list-item'))
return confirmedTxes.length === 2
}, 10000)
+ await delay(regularDelayMs)
const txValues = await findElements(driver, By.css('.transaction-list-item__amount--primary'))
await driver.wait(until.elementTextMatches(txValues[0], /-7\s*TST/))
const txStatuses = await findElements(driver, By.css('.transaction-list-item__action'))
- await driver.wait(until.elementTextMatches(txStatuses[0], /Sent\sToken/))
+ await driver.wait(until.elementTextMatches(txStatuses[0], /Sent\sToken/), 10000)
const walletBalance = await findElement(driver, By.css('.wallet-balance'))
await walletBalance.click()
@@ -883,8 +1147,8 @@ describe('MetaMask', function () {
// test cancelled on firefox until https://github.com/mozilla/geckodriver/issues/906 is resolved,
// or possibly until we use latest version of firefox in the tests
if (process.env.SELENIUM_BROWSER !== 'firefox') {
- const tokenBalanceAmount = await findElement(driver, By.css('.transaction-view-balance__token-balance'))
- assert.equal(await tokenBalanceAmount.getText(), '43 TST')
+ const tokenBalanceAmount = await findElements(driver, By.css('.transaction-view-balance__primary-balance'))
+ await driver.wait(until.elementTextMatches(tokenBalanceAmount[0], /43\s*TST/), 10000)
}
})
})
@@ -908,7 +1172,7 @@ describe('MetaMask', function () {
await driver.switchTo().window(extension)
await delay(regularDelayMs)
- driver.wait(async () => {
+ await driver.wait(async () => {
const pendingTxes = await findElements(driver, By.css('.transaction-list__pending-transactions .transaction-list-item'))
return pendingTxes.length === 1
}, 10000)
@@ -952,9 +1216,11 @@ describe('MetaMask', function () {
})
it('customizes gas', async () => {
- await driver.wait(until.elementLocated(By.css('.customize-gas__title')))
+ const modalTabs = await findElements(driver, By.css('.page-container__tab'))
+ await modalTabs[1].click()
+ await delay(regularDelayMs)
- const [gasPriceInput, gasLimitInput] = await findElements(driver, By.css('.customize-gas-input'))
+ const [gasPriceInput, gasLimitInput] = await findElements(driver, By.css('.advanced-tab__gas-edit-row__input'))
await gasPriceInput.clear()
await delay(tinyDelayMs)
await gasPriceInput.sendKeys('10')
@@ -971,7 +1237,7 @@ describe('MetaMask', function () {
await gasLimitInput.sendKeys(Key.BACK_SPACE)
}
- const save = await findElement(driver, By.css('.customize-gas__save'))
+ const save = await findElement(driver, By.css('.page-container__footer-button'))
await save.click()
await driver.wait(until.stalenessOf(gasModal))
@@ -986,7 +1252,7 @@ describe('MetaMask', function () {
})
it('finds the transaction in the transactions list', async function () {
- driver.wait(async () => {
+ await driver.wait(async () => {
const confirmedTxes = await findElements(driver, By.css('.transaction-list__completed-transactions .transaction-list-item'))
return confirmedTxes.length === 3
}, 10000)
@@ -1044,7 +1310,7 @@ describe('MetaMask', function () {
})
it('renders the balance for the chosen token', async () => {
- const balance = await findElement(driver, By.css('.transaction-view-balance__token-balance'))
+ const balance = await findElement(driver, By.css('.transaction-view-balance__primary-balance'))
await driver.wait(until.elementTextMatches(balance, /0\s*BAT/))
await delay(regularDelayMs)
})
diff --git a/test/e2e/beta/run-drizzle.sh b/test/e2e/beta/run-drizzle.sh
index bfb7e6fdb..0799b5a65 100755
--- a/test/e2e/beta/run-drizzle.sh
+++ b/test/e2e/beta/run-drizzle.sh
@@ -4,17 +4,28 @@ set -e
set -u
set -o pipefail
-export PATH="$PATH:./node_modules/.bin"
-
npm run ganache:start -- -b 2 >> /dev/null 2>&1 &
+npm_run_ganache_start_pid=$!
sleep 5
-cd test/e2e/beta/
-rm -rf drizzle-test
-mkdir drizzle-test && cd drizzle-test
-sudo npm install -g truffle
-truffle unbox drizzle
+
+pushd "$(mktemp -d)"
+npm install --no-package-lock truffle
+truffle="$(npm bin)/truffle"
+$truffle unbox drizzle
echo "Deploying contracts for Drizzle test..."
-truffle compile && truffle migrate
+$truffle compile
+$truffle migrate
+
BROWSER=none npm start >> /dev/null 2>&1 &
-cd ../../../../
-mocha test/e2e/beta/drizzle.spec
+npm_start_pid=$!
+
+popd
+if ! mocha test/e2e/beta/drizzle.spec
+then
+ test_status=1
+fi
+
+! kill -15 $npm_run_ganache_start_pid
+! kill -15 $npm_start_pid
+! wait $npm_run_ganache_start_pid $npm_start_pid
+exit ${test_status:-}
diff --git a/test/e2e/func.js b/test/e2e/func.js
index 5301d78ae..dfad8466c 100644
--- a/test/e2e/func.js
+++ b/test/e2e/func.js
@@ -85,7 +85,7 @@ function buildFirefoxWebdriver (opts = {}) {
async function getExtensionIdChrome (driver) {
await driver.get('chrome://extensions')
- const extensionId = await driver.executeScript('return document.querySelector("extensions-manager").shadowRoot.querySelector("extensions-view-manager extensions-item-list").shadowRoot.querySelector("extensions-item:nth-child(2)").getAttribute("id")')
+ const extensionId = await driver.executeScript('return document.querySelector("extensions-manager").shadowRoot.querySelector("extensions-item-list").shadowRoot.querySelector("extensions-item:nth-child(2)").getAttribute("id")')
return extensionId
}
diff --git a/test/integration/lib/confirm-sig-requests.js b/test/integration/lib/confirm-sig-requests.js
index 9c2ad7cf4..e4540c4f2 100644
--- a/test/integration/lib/confirm-sig-requests.js
+++ b/test/integration/lib/confirm-sig-requests.js
@@ -3,6 +3,7 @@ const {
timeout,
queryAsync,
} = require('../../lib/util')
+const fetchMockResponses = require('../../e2e/beta/fetch-mocks.js')
QUnit.module('confirm sig requests')
@@ -19,10 +20,17 @@ async function runConfirmSigRequestsTest (assert, done) {
selectState.val('confirm sig requests')
reactTriggerChange(selectState[0])
+ global.fetch = (...args) => {
+ if (args[0].match(/chromeextensionmm/)) {
+ return Promise.resolve({ json: () => Promise.resolve(JSON.parse(fetchMockResponses.metametrics)) })
+ }
+ return window.fetch(...args)
+ }
+
const pendingRequestItem = $.find('.transaction-list-item .transaction-list-item__grid')
- if (pendingRequestItem[0]) {
- pendingRequestItem[0].click()
+ if (pendingRequestItem[2]) {
+ pendingRequestItem[2].click()
}
await timeout(1000)
diff --git a/test/integration/lib/currency-localization.js b/test/integration/lib/currency-localization.js
index f6b751ba2..cd10efa30 100644
--- a/test/integration/lib/currency-localization.js
+++ b/test/integration/lib/currency-localization.js
@@ -4,6 +4,7 @@ const {
queryAsync,
findAsync,
} = require('../../lib/util')
+const fetchMockResponses = require('../../e2e/beta/fetch-mocks.js')
QUnit.module('currency localization')
@@ -19,6 +20,14 @@ async function runCurrencyLocalizationTest (assert, done) {
console.log('*** start runCurrencyLocalizationTest')
const selectState = await queryAsync($, 'select')
selectState.val('currency localization')
+
+ global.fetch = (...args) => {
+ if (args[0].match(/chromeextensionmm/)) {
+ return Promise.resolve({ json: () => Promise.resolve(JSON.parse(fetchMockResponses.metametrics)) })
+ }
+ return window.fetch(...args)
+ }
+
await timeout(1000)
reactTriggerChange(selectState[0])
await timeout(1000)
diff --git a/test/integration/lib/first-time.js b/test/integration/lib/first-time.js
deleted file mode 100644
index 8cacd7f14..000000000
--- a/test/integration/lib/first-time.js
+++ /dev/null
@@ -1,117 +0,0 @@
-const reactTriggerChange = require('react-trigger-change')
-const PASSWORD = 'password123'
-const runMascaraFirstTimeTest = require('./mascara-first-time')
-const {
- timeout,
- findAsync,
-} = require('../../lib/util')
-
-QUnit.module('first time usage')
-
-QUnit.test('render init screen', (assert) => {
- const done = assert.async()
- runFirstTimeUsageTest(assert).then(done).catch((err) => {
- assert.notOk(err, `Error was thrown: ${err.stack}`)
- done()
- })
-})
-
-async function runFirstTimeUsageTest(assert, done) {
- if (window.METAMASK_PLATFORM_TYPE === 'mascara') {
- return runMascaraFirstTimeTest(assert, done)
- }
-
- const selectState = $('select')
- selectState.val('first time')
- reactTriggerChange(selectState[0])
-
- const app = $('#app-content')
-
- // Selects new ui
- const tryNewUIButton = (await findAsync(app, 'button.negative'))[0]
- tryNewUIButton.click()
- await timeout()
-
- // recurse notices
- while (true) {
- const button = await findAsync(app, 'button')
- if (button.html() === 'Accept') {
- // still notices to accept
- const termsPageRaw = await findAsync(app, '.markdown')
- const termsPage = (await findAsync(app, '.markdown'))[0]
- console.log('termsPageRaw', termsPageRaw)
- termsPage.scrollTop = termsPage.scrollHeight
- console.log('Clearing notice')
- button.click()
- } else {
- // exit loop
- console.log('No more notices...')
- break
- }
- }
-
- // Scroll through terms
- const title = (await findAsync(app, 'h1'))[0]
- assert.equal(title.textContent, 'MetaMask', 'title screen')
-
- // enter password
- const pwBox = (await findAsync(app, '#password-box'))[0]
- const confBox = (await findAsync(app, '#password-box-confirm'))[0]
- pwBox.value = PASSWORD
- confBox.value = PASSWORD
-
- // create vault
- const createButton = (await findAsync(app, 'button.primary'))[0]
- createButton.click()
-
- await timeout()
- const created = (await findAsync(app, 'h3'))[0]
- assert.equal(created.textContent, 'Vault Created', 'Vault created screen')
-
- // Agree button
- const button = (await findAsync(app, 'button'))[0]
- assert.ok(button, 'button present')
- button.click()
-
- const detail = (await findAsync(app, '.account-detail-section'))[0]
- assert.ok(detail, 'Account detail section loaded.')
-
- const sandwich = (await findAsync(app, '.sandwich-expando'))[0]
- sandwich.click()
-
- const menu = (await findAsync(app, '.menu-droppo'))[0]
- const children = menu.children
- const logout = children[2]
- assert.ok(logout, 'Lock menu item found')
- logout.click()
-
- const pwBox2 = (await findAsync(app, '#password-box'))[0]
- pwBox2.value = PASSWORD
-
- const createButton2 = (await findAsync(app, 'button.primary'))[0]
- createButton2.click()
-
- const detail2 = (await findAsync(app, '.account-detail-section'))[0]
- assert.ok(detail2, 'Account detail section loaded again.')
-
- // open account settings dropdown
- const qrButton = (await findAsync(app, '.fa.fa-ellipsis-h'))[0]
- qrButton.click()
-
- // qr code item
- const qrButton2 = (await findAsync(app, '.dropdown-menu-item'))[1]
- qrButton2.click()
-
- const qrHeader = (await findAsync(app, '.qr-header'))[0]
- const qrContainer = (await findAsync(app, '#qr-container'))[0]
- assert.equal(qrHeader.textContent, 'Account 1', 'Should show account label.')
- assert.ok(qrContainer, 'QR Container found')
-
- const networkMenu = (await findAsync(app, '.network-indicator'))[0]
- networkMenu.click()
-
- const networkMenu2 = (await findAsync(app, '.network-indicator'))[0]
- const children2 = networkMenu2.children
- children2.length[3]
- assert.ok(children2, 'All network options present')
-}
diff --git a/test/integration/lib/mascara-first-time.js b/test/integration/lib/mascara-first-time.js
deleted file mode 100644
index 6756b83f9..000000000
--- a/test/integration/lib/mascara-first-time.js
+++ /dev/null
@@ -1,133 +0,0 @@
-const PASSWORD = 'password123'
-const {
- timeout,
- findAsync,
- queryAsync,
-} = require('../../lib/util')
-
-async function runFirstTimeUsageTest (assert, done) {
- await timeout(4000)
-
- const app = await queryAsync($, '#app-content')
-
- // Used to set values on TextField input component
- const nativeInputValueSetter = Object.getOwnPropertyDescriptor(
- window.HTMLInputElement.prototype, 'value'
- ).set
-
- await skipNotices(app)
-
- const welcomeButton = (await findAsync(app, '.welcome-screen__button'))[0]
- welcomeButton.click()
-
- // Scroll through terms
- const title = (await findAsync(app, '.create-password__title')).text()
- assert.equal(title, 'Create Password', 'create password screen')
-
- // enter password
- const pwBox = (await findAsync(app, '#create-password'))[0]
- const confBox = (await findAsync(app, '#confirm-password'))[0]
-
- nativeInputValueSetter.call(pwBox, PASSWORD)
- pwBox.dispatchEvent(new Event('input', { bubbles: true}))
-
- nativeInputValueSetter.call(confBox, PASSWORD)
- confBox.dispatchEvent(new Event('input', { bubbles: true}))
-
- // Create Password
- const createButton = (await findAsync(app, 'button.first-time-flow__button'))[0]
- createButton.click()
-
- const created = (await findAsync(app, '.unique-image__title'))[0]
- assert.equal(created.textContent, 'Your unique account image', 'unique image screen')
-
- // Agree button
- const button = (await findAsync(app, 'button'))[0]
- assert.ok(button, 'button present')
- button.click()
-
- await skipNotices(app)
-
- // secret backup phrase
- const seedTitle = (await findAsync(app, '.backup-phrase__title'))[0]
- assert.equal(seedTitle.textContent, 'Secret Backup Phrase', 'seed phrase screen')
- ;(await findAsync(app, '.backup-phrase__reveal-button')).click()
- const seedPhrase = (await findAsync(app, '.backup-phrase__secret-words')).text().split(' ')
- ;(await findAsync(app, '.first-time-flow__button')).click()
-
- await timeout()
- const selectPhrase = text => {
- const option = $('.backup-phrase__confirm-seed-option')
- .filter((i, d) => d.textContent === text)[0]
- $(option).click()
- }
-
- seedPhrase.forEach(sp => selectPhrase(sp))
- ;(await findAsync(app, '.first-time-flow__button')).click()
-
- // Deposit Ether Screen
- const depositEthTitle = (await findAsync(app, '.page-container__title'))[0]
- assert.equal(depositEthTitle.textContent, 'Deposit Ether', 'deposit ether screen')
- ;(await findAsync(app, '.page-container__header-close')).click()
-
- const menu = (await findAsync(app, '.account-menu__icon'))[0]
- menu.click()
-
- const lock = (await findAsync(app, '.account-menu__logout-button'))[0]
- assert.ok(lock, 'Lock menu item found')
- lock.click()
-
- await timeout(5000)
-
- const pwBox2 = (await findAsync(app, '#password'))[0]
- pwBox2.focus()
- await timeout(1000)
-
- nativeInputValueSetter.call(pwBox2, PASSWORD)
- pwBox2.dispatchEvent(new Event('input', { bubbles: true}))
-
- const createButton2 = (await findAsync(app, 'button[type="submit"]'))[0]
- createButton2.click()
-
- const detail2 = (await findAsync(app, '.wallet-view'))[0]
- assert.ok(detail2, 'Account detail section loaded again.')
-
- // open account settings dropdown
- const qrButton = (await findAsync(app, '.wallet-view__details-button'))[0]
- qrButton.click()
-
- const qrHeader = (await findAsync(app, '.editable-label__value'))[0]
- const qrContainer = (await findAsync(app, '.qr-wrapper'))[0]
- assert.equal(qrHeader.textContent, 'Account 1', 'Should show account label.')
- assert.ok(qrContainer, 'QR Container found')
-
- const networkMenu = (await findAsync(app, '.network-component'))[0]
- networkMenu.click()
-
- const networkMenu2 = (await findAsync(app, '.network-indicator'))[0]
- const children2 = networkMenu2.children
- children2.length[3]
- assert.ok(children2, 'All network options present')
-}
-
-module.exports = runFirstTimeUsageTest
-
-async function skipNotices (app) {
- while (true) {
- const button = await findAsync(app, 'button')
- if (button && button.html() === 'Accept') {
- // still notices to accept
- const termsPage = (await findAsync(app, '.markdown'))[0]
- if (!termsPage) {
- break
- }
- termsPage.scrollTop = termsPage.scrollHeight
- await timeout()
- button.click()
- await timeout()
- } else {
- console.log('No more notices...')
- break
- }
- }
-}
diff --git a/test/integration/lib/send-new-ui.js b/test/integration/lib/send-new-ui.js
index 271dd91cf..d7003f4cc 100644
--- a/test/integration/lib/send-new-ui.js
+++ b/test/integration/lib/send-new-ui.js
@@ -4,6 +4,7 @@ const {
queryAsync,
findAsync,
} = require('../../lib/util')
+const fetchMockResponses = require('../../e2e/beta/fetch-mocks.js')
QUnit.module('new ui send flow')
@@ -21,38 +22,22 @@ global.ethQuery = {
global.ethereumProvider = {}
-async function customizeGas (assert, price, limit, ethFee, usdFee) {
- const sendGasOpenCustomizeModalButton = await queryAsync($, '.sliders-icon-container')
- sendGasOpenCustomizeModalButton[0].click()
-
- const customizeGasModal = await queryAsync($, '.send-v2__customize-gas')
- assert.ok(customizeGasModal[0], 'should render the customize gas modal')
-
- const customizeGasPriceInput = (await queryAsync($, '.send-v2__gas-modal-card')).first().find('input')
- customizeGasPriceInput.val(price)
- reactTriggerChange(customizeGasPriceInput[0])
- const customizeGasLimitInput = (await queryAsync($, '.send-v2__gas-modal-card')).last().find('input')
- customizeGasLimitInput.val(limit)
- reactTriggerChange(customizeGasLimitInput[0])
-
- const customizeGasSaveButton = await queryAsync($, '.send-v2__customize-gas__save')
- customizeGasSaveButton[0].click()
- const sendGasField = await queryAsync($, '.send-v2__gas-fee-display')
-
- assert.equal(
- (await findAsync(sendGasField, '.currency-display-component'))[0].textContent,
- ethFee,
- 'send gas field should show customized gas total'
- )
-
- assert.equal(
- (await findAsync(sendGasField, '.currency-display__converted-value'))[0].textContent,
- usdFee,
- 'send gas field should show customized gas total converted to USD'
- )
-}
-
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)) })
+ } else if (args[0].match(/chromeextensionmm/)) {
+ return Promise.resolve({ json: () => Promise.resolve(JSON.parse(fetchMockResponses.metametrics)) })
+ }
+ return window.fetch(...args)
+ }
+
console.log('*** start runSendFlowTest')
const selectState = await queryAsync($, 'select')
selectState.val('send new ui')
@@ -71,23 +56,14 @@ async function runSendFlowTest (assert, done) {
const sendFromField = await queryAsync($, '.send-v2__form-field')
assert.ok(sendFromField[0], 'send screen has a from field')
- let sendFromFieldItemAddress = await queryAsync($, '.account-list-item__account-name')
- assert.equal(sendFromFieldItemAddress[0].textContent, 'Send Account 4', 'send from field shows correct account name')
-
- const sendFromFieldItem = await queryAsync($, '.account-list-item')
- sendFromFieldItem[0].click()
-
- // this seems to fail if the firefox window is not in focus...
- const sendFromDropdownList = await queryAsync($, '.send-v2__from-dropdown__list')
- assert.equal(sendFromDropdownList.children().length, 4, 'send from dropdown shows all accounts')
- sendFromDropdownList.children()[1].click()
-
- sendFromFieldItemAddress = await queryAsync($, '.account-list-item__account-name')
- assert.equal(sendFromFieldItemAddress[0].textContent, 'Send Account 2', 'send from field dropdown changes account name')
+ const sendFromFieldItemAddress = await queryAsync($, '.account-list-item__account-name')
+ assert.equal(sendFromFieldItemAddress[0].textContent, 'Send Account 2', 'send from field shows correct account name')
const sendToFieldInput = await queryAsync($, '.send-v2__to-autocomplete__input')
sendToFieldInput[0].focus()
+ await timeout(1000)
+
const sendToDropdownList = await queryAsync($, '.send-v2__from-dropdown__list')
assert.equal(sendToDropdownList.children().length, 5, 'send to dropdown shows all accounts and address book accounts')
@@ -112,10 +88,6 @@ async function runSendFlowTest (assert, done) {
errorMessage = $('.send-v2__error')
assert.equal(errorMessage.length, 0, 'send should stop rendering amount error message after amount is corrected')
- await customizeGas(assert, 0, 21000, '0ETH', '$0.00USD')
- await customizeGas(assert, 1, 21000, '0.000021ETH', '$0.03USD')
- await customizeGas(assert, 500, 60000, '0.03ETH', '$36.03USD')
-
const sendButton = await queryAsync($, 'button.btn-primary.btn--large.page-container__footer-button')
assert.equal(sendButton[0].textContent, 'Next', 'next button rendered')
sendButton[0].click()
@@ -125,7 +97,7 @@ async function runSendFlowTest (assert, done) {
reactTriggerChange(selectState[0])
const confirmFromName = (await queryAsync($, '.sender-to-recipient__name')).first()
- assert.equal(confirmFromName[0].textContent, 'Send Account 4', 'confirm screen should show correct from name')
+ assert.equal(confirmFromName[0].textContent, 'Send Account 2', 'confirm screen should show correct from name')
const confirmToName = (await queryAsync($, '.sender-to-recipient__name')).last()
assert.equal(confirmToName[0].textContent, 'Send Account 3', 'confirm screen should show correct to name')
@@ -139,12 +111,6 @@ async function runSendFlowTest (assert, done) {
const confirmScreenBackButton = await queryAsync($, '.confirm-page-container-header__back-button')
confirmScreenBackButton[0].click()
- const sendFromFieldItemInEdit = await queryAsync($, '.account-list-item')
- sendFromFieldItemInEdit[0].click()
-
- const sendFromDropdownListInEdit = await queryAsync($, '.send-v2__from-dropdown__list')
- sendFromDropdownListInEdit.children()[2].click()
-
const sendToFieldInputInEdit = await queryAsync($, '.send-v2__to-autocomplete__input')
sendToFieldInputInEdit[0].focus()
sendToFieldInputInEdit.val('0xd85a4b6a394794842887b8284293d69163007bbb')
@@ -164,6 +130,8 @@ async function runSendFlowTest (assert, done) {
const cancelButtonInEdit = await queryAsync($, '.btn-default.btn--large.page-container__footer-button')
cancelButtonInEdit[0].click()
+
+ global.fetch = tempFetch
// sendButtonInEdit[0].click()
// // TODO: Need a way to mock background so that we can test correct transition from editing to confirm
diff --git a/test/integration/lib/tx-list-items.js b/test/integration/lib/tx-list-items.js
index ed4f82074..c0056dd22 100644
--- a/test/integration/lib/tx-list-items.js
+++ b/test/integration/lib/tx-list-items.js
@@ -3,6 +3,7 @@ const {
queryAsync,
findAsync,
} = require('../../lib/util')
+const fetchMockResponses = require('../../e2e/beta/fetch-mocks.js')
QUnit.module('tx list items')
@@ -16,7 +17,7 @@ QUnit.test('renders list items successfully', (assert) => {
global.ethQuery = global.ethQuery || {}
global.ethQuery.getTransactionCount = (_, cb) => {
- cb(null, '0x3')
+ cb(null, '0x4')
}
async function runTxListItemsTest (assert, done) {
@@ -25,6 +26,13 @@ async function runTxListItemsTest (assert, done) {
selectState.val('tx list items')
reactTriggerChange(selectState[0])
+ global.fetch = (...args) => {
+ if (args[0].match(/chromeextensionmm/)) {
+ return Promise.resolve({ json: () => Promise.resolve(JSON.parse(fetchMockResponses.metametrics)) })
+ }
+ return window.fetch(...args)
+ }
+
const metamaskLogo = await queryAsync($, '.app-header__logo-container')
assert.ok(metamaskLogo[0], 'metamask logo present')
metamaskLogo[0].click()
@@ -32,33 +40,27 @@ async function runTxListItemsTest (assert, done) {
const txListItems = await queryAsync($, '.transaction-list-item')
assert.equal(txListItems.length, 8, 'all tx list items are rendered')
- const retryTxGrid = await findAsync($(txListItems[2]), '.transaction-list-item__grid')
- retryTxGrid[0].click()
- const retryTxDetails = await findAsync($, '.transaction-list-item-details')
- const headerButtons = await findAsync($(retryTxDetails[0]), '.transaction-list-item-details__header-button')
- assert.equal(headerButtons[0].textContent, 'speed up')
+ const unapprovedMsg = txListItems[0]
+ const unapprovedMsgDescription = await findAsync($(unapprovedMsg), '.transaction-list-item__action')
+ assert.equal(unapprovedMsgDescription[0].textContent, 'Signature Request', 'unapprovedMsg has correct description')
const approvedTx = txListItems[2]
const approvedTxRenderedStatus = await findAsync($(approvedTx), '.transaction-list-item__status')
assert.equal(approvedTxRenderedStatus[0].textContent, 'pending', 'approvedTx has correct label')
- const unapprovedMsg = txListItems[0]
- const unapprovedMsgDescription = await findAsync($(unapprovedMsg), '.transaction-list-item__action')
- assert.equal(unapprovedMsgDescription[0].textContent, 'Signature Request', 'unapprovedMsg has correct description')
-
- const failedTx = txListItems[4]
- const failedTxRenderedStatus = await findAsync($(failedTx), '.transaction-list-item__status')
- assert.equal(failedTxRenderedStatus[0].textContent, 'Failed', 'failedTx has correct label')
+ const confirmedTokenTx1 = txListItems[4]
+ const confirmedTokenTx1Address = await findAsync($(confirmedTokenTx1), '.transaction-list-item__status')
+ assert.equal(confirmedTokenTx1Address[0].textContent, 'Confirmed', 'confirmedTokenTx has correct status')
- const shapeShiftTx = txListItems[5]
- const shapeShiftTxStatus = await findAsync($(shapeShiftTx), '.flex-column div:eq(1)')
- assert.equal(shapeShiftTxStatus[0].textContent, 'No deposits received', 'shapeShiftTx has correct status')
+ const shapeShiftTx1 = txListItems[5]
+ const shapeShiftTx1Status = await findAsync($(shapeShiftTx1), '.flex-column div:eq(1)')
+ assert.equal(shapeShiftTx1Status[0].textContent, 'No deposits received', 'shapeShiftTx has correct status')
- const confirmedTokenTx = txListItems[6]
- const confirmedTokenTxAddress = await findAsync($(confirmedTokenTx), '.transaction-list-item__status')
- assert.equal(confirmedTokenTxAddress[0].textContent, 'Confirmed', 'confirmedTokenTx has correct address')
+ const confirmedTokenTx2 = txListItems[6]
+ const confirmedTokenTx2Address = await findAsync($(confirmedTokenTx2), '.transaction-list-item__status')
+ assert.equal(confirmedTokenTx2Address[0].textContent, 'Confirmed', 'confirmedTokenTx has correct status')
- const rejectedTx = txListItems[7]
- const rejectedTxRenderedStatus = await findAsync($(rejectedTx), '.transaction-list-item__status')
- assert.equal(rejectedTxRenderedStatus[0].textContent, 'Rejected', 'rejectedTx has correct label')
+ const shapeShiftTx2 = txListItems[7]
+ const shapeShiftTx2Address = await findAsync($(shapeShiftTx2), '.flex-column div:eq(1)')
+ assert.equal(shapeShiftTx2Address[0].textContent, 'No deposits received', 'shapeShiftTx has correct status')
}
diff --git a/test/lib/mock-tx-gen.js b/test/lib/mock-tx-gen.js
index 106101500..e39551a7a 100644
--- a/test/lib/mock-tx-gen.js
+++ b/test/lib/mock-tx-gen.js
@@ -2,6 +2,7 @@ const extend = require('xtend')
const BN = require('ethereumjs-util').BN
const template = {
'status': 'submitted',
+ 'history': [{}],
'txParams': {
'from': '0x7d3517b0d011698406d6e0aed8453f0be2697926',
'gas': '0x30d40',
diff --git a/test/mascara.conf.js b/test/mascara.conf.js
deleted file mode 100644
index faf3147bd..000000000
--- a/test/mascara.conf.js
+++ /dev/null
@@ -1,17 +0,0 @@
-const getBaseConfig = require('./base.conf.js')
-
-module.exports = function (config) {
- const settings = getBaseConfig(config)
-
- // ui and tests
- settings.files.push('dist/mascara/ui.js')
- settings.files.push('dist/mascara/tests.js')
- // service worker background
- settings.files.push({ pattern: 'dist/mascara/background.js', watched: false, included: false, served: true })
- settings.proxies['/background.js'] = '/base/dist/mascara/background.js'
-
- // use this to keep the browser open for debugging
- settings.browserNoActivityTimeout = 10000000
-
- config.set(settings)
-}
diff --git a/test/setup.js b/test/setup.js
index 8e7965a37..1a69f4866 100644
--- a/test/setup.js
+++ b/test/setup.js
@@ -3,3 +3,5 @@ require('babel-register')({
})
require('./helper')
+
+window.SVGPathElement = window.SVGPathElement || { prototype: {} }
diff --git a/test/unit/actions/config_test.js b/test/unit/actions/config_test.js
index 648f456fb..9127474a8 100644
--- a/test/unit/actions/config_test.js
+++ b/test/unit/actions/config_test.js
@@ -3,8 +3,8 @@ var assert = require('assert')
var freeze = require('deep-freeze-strict')
var path = require('path')
-var actions = require(path.join(__dirname, '..', '..', '..', 'ui', 'app', 'actions.js'))
-var reducers = require(path.join(__dirname, '..', '..', '..', 'ui', 'app', 'reducers.js'))
+var actions = require(path.join(__dirname, '..', '..', '..', 'ui', 'app', 'store', 'actions.js'))
+var reducers = require(path.join(__dirname, '..', '..', '..', 'ui', 'app', 'ducks', 'index.js'))
describe('config view actions', function () {
var initialState = {
diff --git a/test/unit/actions/set_account_label_test.js b/test/unit/actions/set_account_label_test.js
index 53ea1d130..1601d6383 100644
--- a/test/unit/actions/set_account_label_test.js
+++ b/test/unit/actions/set_account_label_test.js
@@ -2,8 +2,8 @@ const assert = require('assert')
const freeze = require('deep-freeze-strict')
const path = require('path')
-const actions = require(path.join(__dirname, '..', '..', '..', 'ui', 'app', 'actions.js'))
-const reducers = require(path.join(__dirname, '..', '..', '..', 'ui', 'app', 'reducers.js'))
+const actions = require(path.join(__dirname, '..', '..', '..', 'ui', 'app', 'store', 'actions.js'))
+const reducers = require(path.join(__dirname, '..', '..', '..', 'ui', 'app', 'ducks', 'index.js'))
describe('SET_ACCOUNT_LABEL', function () {
it('updates the state.metamask.identities[:i].name property of the state to the action.value.label', function () {
diff --git a/test/unit/actions/set_selected_account_test.js b/test/unit/actions/set_selected_account_test.js
index 28b47d09d..36d312d7b 100644
--- a/test/unit/actions/set_selected_account_test.js
+++ b/test/unit/actions/set_selected_account_test.js
@@ -3,8 +3,8 @@ var assert = require('assert')
var freeze = require('deep-freeze-strict')
var path = require('path')
-var actions = require(path.join(__dirname, '..', '..', '..', 'ui', 'app', 'actions.js'))
-var reducers = require(path.join(__dirname, '..', '..', '..', 'ui', 'app', 'reducers.js'))
+var actions = require(path.join(__dirname, '..', '..', '..', 'ui', 'app', 'store', 'actions.js'))
+var reducers = require(path.join(__dirname, '..', '..', '..', 'ui', 'app', 'ducks', 'index.js'))
describe('SET_SELECTED_ACCOUNT', function () {
it('sets the state.appState.activeAddress property of the state to the action.value', function () {
diff --git a/test/unit/actions/tx_test.js b/test/unit/actions/tx_test.js
index 160cd4552..8c64d844f 100644
--- a/test/unit/actions/tx_test.js
+++ b/test/unit/actions/tx_test.js
@@ -4,7 +4,7 @@ var path = require('path')
import configureMockStore from 'redux-mock-store'
import thunk from 'redux-thunk'
-const actions = require(path.join(__dirname, '../../../ui/app/actions.js'))
+const actions = require(path.join(__dirname, '../../../ui/app/store/actions.js'))
const middlewares = [thunk]
const mockStore = configureMockStore(middlewares)
diff --git a/test/unit/actions/view_info_test.js b/test/unit/actions/view_info_test.js
index 69895d801..5785a368c 100644
--- a/test/unit/actions/view_info_test.js
+++ b/test/unit/actions/view_info_test.js
@@ -3,8 +3,8 @@ var assert = require('assert')
var freeze = require('deep-freeze-strict')
var path = require('path')
-var actions = require(path.join(__dirname, '..', '..', '..', 'ui', 'app', 'actions.js'))
-var reducers = require(path.join(__dirname, '..', '..', '..', 'ui', 'app', 'reducers.js'))
+var actions = require(path.join(__dirname, '..', '..', '..', 'ui', 'app', 'store', 'actions.js'))
+var reducers = require(path.join(__dirname, '..', '..', '..', 'ui', 'app', 'ducks', 'index.js'))
describe('SHOW_INFO_PAGE', function () {
it('sets the state.appState.currentView.name property to info', function () {
diff --git a/test/unit/actions/warning_test.js b/test/unit/actions/warning_test.js
index 28b565499..e57374cda 100644
--- a/test/unit/actions/warning_test.js
+++ b/test/unit/actions/warning_test.js
@@ -3,8 +3,8 @@ var assert = require('assert')
var freeze = require('deep-freeze-strict')
var path = require('path')
-var actions = require(path.join(__dirname, '..', '..', '..', 'ui', 'app', 'actions.js'))
-var reducers = require(path.join(__dirname, '..', '..', '..', 'ui', 'app', 'reducers.js'))
+var actions = require(path.join(__dirname, '..', '..', '..', 'ui', 'app', 'store', 'actions.js'))
+var reducers = require(path.join(__dirname, '..', '..', '..', 'ui', 'app', 'ducks', 'index.js'))
describe('action DISPLAY_WARNING', function () {
it('sets appState.warning to provided value', function () {
diff --git a/test/unit/app/buy-eth-url.spec.js b/test/unit/app/buy-eth-url.spec.js
index 36646fa68..6cf3e7d75 100644
--- a/test/unit/app/buy-eth-url.spec.js
+++ b/test/unit/app/buy-eth-url.spec.js
@@ -18,14 +18,9 @@ describe('', function () {
}
it('returns coinbase url with amount and address for network 1', function () {
- const coinbaseUrl = getBuyEthUrl(mainnet)
- const coinbase = coinbaseUrl.match(/(https:\/\/buy.coinbase.com)/)
- const amount = coinbaseUrl.match(/(amount)\D\d/)
- const address = coinbaseUrl.match(/(address)(.*)(?=&)/)
-
- assert.equal(coinbase[0], 'https://buy.coinbase.com')
- assert.equal(amount[0], 'amount=5')
- assert.equal(address[0], 'address=0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc')
+ const wyreUrl = getBuyEthUrl(mainnet)
+
+ assert.equal(wyreUrl, 'https://dash.sendwyre.com/sign-up')
})
diff --git a/test/unit/app/controllers/address-book-controller.js b/test/unit/app/controllers/address-book-controller.js
deleted file mode 100644
index 1350e1a61..000000000
--- a/test/unit/app/controllers/address-book-controller.js
+++ /dev/null
@@ -1,54 +0,0 @@
-const assert = require('assert')
-const AddressBookController = require('../../../../app/scripts/controllers/address-book')
-
-const stubPreferencesStore = {
- getState: function () {
- return {
- identities: {
- '0x0aaa': {
- address: '0x0aaa',
- name: 'owned',
- },
- },
- }
- },
-}
-
-describe('address-book-controller', function () {
- var addressBookController
-
- beforeEach(function () {
- addressBookController = new AddressBookController({
- preferencesStore: stubPreferencesStore,
- })
- })
-
- describe('addres book management', function () {
- describe('#_getAddressBook', function () {
- it('should be empty by default.', function () {
- assert.equal(addressBookController._getAddressBook().length, 0)
- })
- })
- describe('#setAddressBook', function () {
- it('should properly set a new address.', function () {
- addressBookController.setAddressBook('0x01234', 'test')
- var addressBook = addressBookController._getAddressBook()
- assert.equal(addressBook.length, 1, 'incorrect address book length.')
- assert.equal(addressBook[0].address, '0x01234', 'incorrect addresss')
- assert.equal(addressBook[0].name, 'test', 'incorrect nickname')
- })
-
- it('should reject duplicates.', function () {
- addressBookController.setAddressBook('0x01234', 'test')
- addressBookController.setAddressBook('0x01234', 'test')
- var addressBook = addressBookController._getAddressBook()
- assert.equal(addressBook.length, 1, 'incorrect address book length.')
- })
- it('should not add any identities that are under user control', function () {
- addressBookController.setAddressBook('0x0aaa', ' ')
- var addressBook = addressBookController._getAddressBook()
- assert.equal(addressBook.length, 0, 'incorrect address book length.')
- })
- })
- })
-})
diff --git a/test/unit/app/controllers/cached-balances-test.js b/test/unit/app/controllers/cached-balances-test.js
new file mode 100644
index 000000000..27aeabba2
--- /dev/null
+++ b/test/unit/app/controllers/cached-balances-test.js
@@ -0,0 +1,137 @@
+const assert = require('assert')
+const sinon = require('sinon')
+const CachedBalancesController = require('../../../../app/scripts/controllers/cached-balances')
+
+describe('CachedBalancesController', () => {
+ describe('updateCachedBalances', () => {
+ it('should update the cached balances', async () => {
+ const controller = new CachedBalancesController({
+ getNetwork: () => Promise.resolve(17),
+ accountTracker: {
+ store: {
+ subscribe: () => {},
+ },
+ },
+ initState: {
+ cachedBalances: 'mockCachedBalances',
+ },
+ })
+
+ controller._generateBalancesToCache = sinon.stub().callsFake(() => Promise.resolve('mockNewCachedBalances'))
+
+ await controller.updateCachedBalances({ accounts: 'mockAccounts' })
+
+ assert.equal(controller._generateBalancesToCache.callCount, 1)
+ assert.deepEqual(controller._generateBalancesToCache.args[0], ['mockAccounts', 17])
+ assert.equal(controller.store.getState().cachedBalances, 'mockNewCachedBalances')
+ })
+ })
+
+ describe('_generateBalancesToCache', () => {
+ it('should generate updated account balances where the current network was updated', () => {
+ const controller = new CachedBalancesController({
+ accountTracker: {
+ store: {
+ subscribe: () => {},
+ },
+ },
+ initState: {
+ cachedBalances: {
+ 17: {
+ a: '0x1',
+ b: '0x2',
+ c: '0x3',
+ },
+ 16: {
+ a: '0xa',
+ b: '0xb',
+ c: '0xc',
+ },
+ },
+ },
+ })
+
+ const result = controller._generateBalancesToCache({
+ a: { balance: '0x4' },
+ b: { balance: null },
+ c: { balance: '0x5' },
+ }, 17)
+
+ assert.deepEqual(result, {
+ 17: {
+ a: '0x4',
+ b: '0x2',
+ c: '0x5',
+ },
+ 16: {
+ a: '0xa',
+ b: '0xb',
+ c: '0xc',
+ },
+ })
+ })
+
+ it('should generate updated account balances where the a new network was selected', () => {
+ const controller = new CachedBalancesController({
+ accountTracker: {
+ store: {
+ subscribe: () => {},
+ },
+ },
+ initState: {
+ cachedBalances: {
+ 17: {
+ a: '0x1',
+ b: '0x2',
+ c: '0x3',
+ },
+ },
+ },
+ })
+
+ const result = controller._generateBalancesToCache({
+ a: { balance: '0x4' },
+ b: { balance: null },
+ c: { balance: '0x5' },
+ }, 16)
+
+ assert.deepEqual(result, {
+ 17: {
+ a: '0x1',
+ b: '0x2',
+ c: '0x3',
+ },
+ 16: {
+ a: '0x4',
+ c: '0x5',
+ },
+ })
+ })
+ })
+
+ describe('_registerUpdates', () => {
+ it('should subscribe to the account tracker with the updateCachedBalances method', async () => {
+ const subscribeSpy = sinon.spy()
+ const controller = new CachedBalancesController({
+ getNetwork: () => Promise.resolve(17),
+ accountTracker: {
+ store: {
+ subscribe: subscribeSpy,
+ },
+ },
+ })
+ subscribeSpy.resetHistory()
+
+ const updateCachedBalancesSpy = sinon.spy()
+ controller.updateCachedBalances = updateCachedBalancesSpy
+ controller._registerUpdates({ accounts: 'mockAccounts' })
+
+ assert.equal(subscribeSpy.callCount, 1)
+
+ subscribeSpy.args[0][0]()
+
+ assert.equal(updateCachedBalancesSpy.callCount, 1)
+ })
+ })
+
+})
diff --git a/test/unit/app/controllers/metamask-controller-test.js b/test/unit/app/controllers/metamask-controller-test.js
index 17be2c028..1ed6a95fb 100644
--- a/test/unit/app/controllers/metamask-controller-test.js
+++ b/test/unit/app/controllers/metamask-controller-test.js
@@ -58,6 +58,7 @@ describe('MetaMaskController', function () {
},
},
initState: clone(firstTimeState),
+ platform: { showTransactionNotification: () => {} },
})
// disable diagnostics
metamaskController.diagnostics = null
diff --git a/test/unit/app/controllers/preferences-controller-test.js b/test/unit/app/controllers/preferences-controller-test.js
index 473f22f8b..558597ae7 100644
--- a/test/unit/app/controllers/preferences-controller-test.js
+++ b/test/unit/app/controllers/preferences-controller-test.js
@@ -511,18 +511,30 @@ describe('preferences controller', function () {
})
})
+ describe('#updateRpc', function () {
+ it('should update the rpcDetails properly', () => {
+ preferencesController.store.updateState({frequentRpcListDetail: [{}, { rpcUrl: 'test' }, {}]})
+ preferencesController.updateRpc({ rpcUrl: 'test', chainId: 1 })
+ preferencesController.updateRpc({ rpcUrl: 'test/1', chainId: 1 })
+ preferencesController.updateRpc({ rpcUrl: 'test/2', chainId: 1 })
+ preferencesController.updateRpc({ rpcUrl: 'test/3', chainId: 1 })
+ const list = preferencesController.getFrequentRpcListDetail()
+ assert.deepEqual(list[1], { rpcUrl: 'test', chainId: 1 })
+ })
+ })
+
describe('on updateFrequentRpcList', function () {
it('should add custom RPC url to state', function () {
preferencesController.addToFrequentRpcList('rpc_url', 1)
preferencesController.addToFrequentRpcList('http://localhost:8545', 1)
- assert.deepEqual(preferencesController.store.getState().frequentRpcListDetail, [{ rpcUrl: 'rpc_url', chainId: 1, ticker: 'ETH', nickname: '' }] )
+ assert.deepEqual(preferencesController.store.getState().frequentRpcListDetail, [{ rpcUrl: 'rpc_url', chainId: 1, ticker: 'ETH', nickname: '' }])
preferencesController.addToFrequentRpcList('rpc_url', 1)
- assert.deepEqual(preferencesController.store.getState().frequentRpcListDetail, [{ rpcUrl: 'rpc_url', chainId: 1, ticker: 'ETH', nickname: '' }] )
+ assert.deepEqual(preferencesController.store.getState().frequentRpcListDetail, [{ rpcUrl: 'rpc_url', chainId: 1, ticker: 'ETH', nickname: '' }])
})
it('should remove custom RPC url from state', function () {
preferencesController.addToFrequentRpcList('rpc_url', 1)
- assert.deepEqual(preferencesController.store.getState().frequentRpcListDetail, [{ rpcUrl: 'rpc_url', chainId: 1, ticker: 'ETH', nickname: '' }] )
+ assert.deepEqual(preferencesController.store.getState().frequentRpcListDetail, [{ rpcUrl: 'rpc_url', chainId: 1, ticker: 'ETH', nickname: '' }])
preferencesController.removeFromFrequentRpcList('other_rpc_url')
preferencesController.removeFromFrequentRpcList('http://localhost:8545')
preferencesController.removeFromFrequentRpcList('rpc_url')
diff --git a/test/unit/app/controllers/token-rates-controller.js b/test/unit/app/controllers/token-rates-controller.js
index 28e583d8d..ccc279cbe 100644
--- a/test/unit/app/controllers/token-rates-controller.js
+++ b/test/unit/app/controllers/token-rates-controller.js
@@ -17,13 +17,4 @@ describe('TokenRatesController', () => {
assert.strictEqual(stub.getCall(0).args[1], 1337)
stub.restore()
})
-
- it('should fetch each token rate based on address', async () => {
- const controller = new TokenRatesController()
- controller.isActive = true
- controller.fetchExchangeRate = address => address
- controller.tokens = [{ address: 'foo' }, { address: 'bar' }]
- await controller.updateExchangeRates()
- assert.deepEqual(controller.store.getState().contractExchangeRates, { foo: 'foo', bar: 'bar' })
- })
})
diff --git a/test/unit/app/controllers/transactions/pending-tx-test.js b/test/unit/app/controllers/transactions/pending-tx-test.js
index ba15f1953..2988bf61f 100644
--- a/test/unit/app/controllers/transactions/pending-tx-test.js
+++ b/test/unit/app/controllers/transactions/pending-tx-test.js
@@ -20,11 +20,13 @@ describe('PendingTransactionTracker', function () {
nonce: '0x1',
value: '0xfffff',
},
+ history: [{}],
rawTx: '0xf86c808504a817c800827b0d940c62bb85faa3311a998d3aba8098c1235c564966880de0b6b3a7640000802aa08ff665feb887a25d4099e40e11f0fef93ee9608f404bd3f853dd9e84ed3317a6a02ec9d3d1d6e176d4d2593dd760e74ccac753e6a0ea0d00cc9789d0d7ff1f471d',
}
txMetaNoHash = {
id: 2,
- status: 'signed',
+ history: [{}],
+ status: 'submitted',
txParams: { from: '0x1678a085c290ebd122dc42cba69373b5953b831d'},
}
@@ -212,6 +214,7 @@ describe('PendingTransactionTracker', function () {
pendingTxTracker.publishTransaction = async (rawTx) => {
assert.equal(rawTx, txMeta.rawTx, 'Should pass the rawTx')
}
+ pendingTxTracker.approveTransaction = async () => {}
sinon.spy(pendingTxTracker, 'publishTransaction')
txMetaToTestExponentialBackoff = Object.assign({}, txMeta, {
@@ -266,6 +269,18 @@ describe('PendingTransactionTracker', function () {
assert.equal(pendingTxTracker.publishTransaction.callCount, 1, 'Should call publish transaction')
})
+
+ it('should call opts.approveTransaction with the id if the tx is not signed', async () => {
+ const stubTx = {
+ id: 40,
+ }
+ const approveMock = sinon.stub(pendingTxTracker, 'approveTransaction')
+
+ pendingTxTracker._resubmitTx(stubTx)
+
+ assert.ok(approveMock.called)
+ approveMock.restore()
+ })
})
describe('#_checkIfNonceIsTaken', function () {
diff --git a/test/unit/app/controllers/transactions/tx-controller-test.js b/test/unit/app/controllers/transactions/tx-controller-test.js
index ea58aa560..9000cd364 100644
--- a/test/unit/app/controllers/transactions/tx-controller-test.js
+++ b/test/unit/app/controllers/transactions/tx-controller-test.js
@@ -5,11 +5,14 @@ const EthTx = require('ethereumjs-tx')
const ObservableStore = require('obs-store')
const sinon = require('sinon')
const TransactionController = require('../../../../../app/scripts/controllers/transactions')
+const {
+ TRANSACTION_TYPE_RETRY,
+} = require('../../../../../app/scripts/controllers/transactions/enums')
const { createTestProviderTools, getTestAccounts } = require('../../../../stub/provider')
const noop = () => true
const currentNetworkId = 42
-
+const netStore = new ObservableStore(currentNetworkId)
describe('Transaction Controller', function () {
let txController, provider, providerResultStub, fromAccount
@@ -28,7 +31,8 @@ describe('Transaction Controller', function () {
blockTrackerStub.getLatestBlock = noop
txController = new TransactionController({
provider,
- networkStore: new ObservableStore(currentNetworkId),
+ getGasPrice: function () { return '0xee6b2800' },
+ networkStore: netStore,
txHistoryLimit: 10,
blockTracker: blockTrackerStub,
signTransaction: (ethTx) => new Promise((resolve) => {
@@ -52,9 +56,9 @@ describe('Transaction Controller', function () {
describe('#getUnapprovedTxCount', function () {
it('should return the number of unapproved txs', function () {
txController.txStateManager._saveTxList([
- { id: 1, status: 'unapproved', metamaskNetworkId: currentNetworkId, txParams: {}, history: [] },
- { id: 2, status: 'unapproved', metamaskNetworkId: currentNetworkId, txParams: {}, history: [] },
- { id: 3, status: 'unapproved', metamaskNetworkId: currentNetworkId, txParams: {}, history: [] },
+ { id: 1, status: 'unapproved', metamaskNetworkId: currentNetworkId, txParams: {}, history: [{}] },
+ { id: 2, status: 'unapproved', metamaskNetworkId: currentNetworkId, txParams: {}, history: [{}] },
+ { id: 3, status: 'unapproved', metamaskNetworkId: currentNetworkId, txParams: {}, history: [{}] },
])
const unapprovedTxCount = txController.getUnapprovedTxCount()
assert.equal(unapprovedTxCount, 3, 'should be 3')
@@ -64,9 +68,9 @@ describe('Transaction Controller', function () {
describe('#getPendingTxCount', function () {
it('should return the number of pending txs', function () {
txController.txStateManager._saveTxList([
- { id: 1, status: 'submitted', metamaskNetworkId: currentNetworkId, txParams: {}, history: [] },
- { id: 2, status: 'submitted', metamaskNetworkId: currentNetworkId, txParams: {}, history: [] },
- { id: 3, status: 'submitted', metamaskNetworkId: currentNetworkId, txParams: {}, history: [] },
+ { id: 1, status: 'submitted', metamaskNetworkId: currentNetworkId, txParams: {}, history: [{}] },
+ { id: 2, status: 'submitted', metamaskNetworkId: currentNetworkId, txParams: {}, history: [{}] },
+ { id: 3, status: 'submitted', metamaskNetworkId: currentNetworkId, txParams: {}, history: [{}] },
])
const pendingTxCount = txController.getPendingTxCount()
assert.equal(pendingTxCount, 3, 'should be 3')
@@ -82,15 +86,15 @@ describe('Transaction Controller', function () {
'to': '0xc684832530fcbddae4b4230a47e991ddcec2831d',
}
txController.txStateManager._saveTxList([
- {id: 0, status: 'confirmed', metamaskNetworkId: currentNetworkId, txParams, history: [] },
- {id: 1, status: 'confirmed', metamaskNetworkId: currentNetworkId, txParams, history: [] },
- {id: 2, status: 'confirmed', metamaskNetworkId: currentNetworkId, txParams, history: [] },
- {id: 3, status: 'unapproved', metamaskNetworkId: currentNetworkId, txParams, history: [] },
- {id: 4, status: 'rejected', metamaskNetworkId: currentNetworkId, txParams, history: [] },
- {id: 5, status: 'approved', metamaskNetworkId: currentNetworkId, txParams, history: [] },
- {id: 6, status: 'signed', metamaskNetworkId: currentNetworkId, txParams, history: [] },
- {id: 7, status: 'submitted', metamaskNetworkId: currentNetworkId, txParams, history: [] },
- {id: 8, status: 'failed', metamaskNetworkId: currentNetworkId, txParams, history: [] },
+ {id: 0, status: 'confirmed', metamaskNetworkId: currentNetworkId, txParams, history: [{}] },
+ {id: 1, status: 'confirmed', metamaskNetworkId: currentNetworkId, txParams, history: [{}] },
+ {id: 2, status: 'confirmed', metamaskNetworkId: currentNetworkId, txParams, history: [{}] },
+ {id: 3, status: 'unapproved', metamaskNetworkId: currentNetworkId, txParams, history: [{}] },
+ {id: 4, status: 'rejected', metamaskNetworkId: currentNetworkId, txParams, history: [{}] },
+ {id: 5, status: 'approved', metamaskNetworkId: currentNetworkId, txParams, history: [{}] },
+ {id: 6, status: 'signed', metamaskNetworkId: currentNetworkId, txParams, history: [{}] },
+ {id: 7, status: 'submitted', metamaskNetworkId: currentNetworkId, txParams, history: [{}] },
+ {id: 8, status: 'failed', metamaskNetworkId: currentNetworkId, txParams, history: [{}] },
])
})
@@ -112,7 +116,7 @@ describe('Transaction Controller', function () {
id: 1,
metamaskNetworkId: currentNetworkId,
txParams,
- history: [],
+ history: [{}],
}
txController.txStateManager._saveTxList([txMeta])
stub = sinon.stub(txController, 'addUnapprovedTransaction').callsFake(() => {
@@ -223,6 +227,15 @@ describe('Transaction Controller', function () {
txController.addUnapprovedTransaction({ from: selectedAddress, to: '0x0d1d4e623D10F9FBA5Db95830F7d3839406C6AF2' })
.catch(done)
})
+
+ it('should fail if netId is loading', function (done) {
+ txController.networkStore = new ObservableStore('loading')
+ txController.addUnapprovedTransaction({ from: selectedAddress, to: '0x0d1d4e623D10F9FBA5Db95830F7d3839406C6AF2' })
+ .catch((err) => {
+ if (err.message === 'MetaMask is having trouble connecting to the network') done()
+ else done(err)
+ })
+ })
})
describe('#addTxGasDefaults', function () {
@@ -232,7 +245,7 @@ describe('Transaction Controller', function () {
from: '0xc684832530fcbddae4b4230a47e991ddcec2831d',
to: '0xc684832530fcbddae4b4230a47e991ddcec2831d',
},
- history: [],
+ history: [{}],
}
providerResultStub.eth_gasPrice = '4a817c800'
providerResultStub.eth_getBlockByNumber = { gasLimit: '47b784' }
@@ -313,6 +326,7 @@ describe('Transaction Controller', function () {
assert.equal(params.gas, originalValue, 'gas unmodified')
assert.equal(params.gasPrice, originalValue, 'gas price unmodified')
assert.equal(result.hash, originalValue, `hash was set \n got: ${result.hash} \n expected: ${originalValue}`)
+ assert.equal(result.status, 'submitted', 'Should have reached the submitted status.')
signStub.restore()
pubStub.restore()
done()
@@ -390,6 +404,70 @@ describe('Transaction Controller', function () {
})
+ describe('#createSpeedUpTransaction', () => {
+ let addTxSpy
+ let approveTransactionSpy
+ let txParams
+ let expectedTxParams
+
+ beforeEach(() => {
+ addTxSpy = sinon.spy(txController, 'addTx')
+ approveTransactionSpy = sinon.spy(txController, 'approveTransaction')
+
+ txParams = {
+ nonce: '0x00',
+ from: '0xB09d8505E1F4EF1CeA089D47094f5DD3464083d4',
+ to: '0xB09d8505E1F4EF1CeA089D47094f5DD3464083d4',
+ gas: '0x5209',
+ gasPrice: '0xa',
+ }
+ txController.txStateManager._saveTxList([
+ { id: 1, status: 'submitted', metamaskNetworkId: currentNetworkId, txParams, history: [{}] },
+ ])
+
+ expectedTxParams = Object.assign({}, txParams, { gasPrice: '0xb'})
+ })
+
+ afterEach(() => {
+ addTxSpy.restore()
+ approveTransactionSpy.restore()
+ })
+
+ it('should call this.addTx and this.approveTransaction with the expected args', async () => {
+ await txController.createSpeedUpTransaction(1)
+ assert.equal(addTxSpy.callCount, 1)
+
+ const addTxArgs = addTxSpy.getCall(0).args[0]
+ assert.deepEqual(addTxArgs.txParams, expectedTxParams)
+
+ const { lastGasPrice, type } = addTxArgs
+ assert.deepEqual({ lastGasPrice, type }, {
+ lastGasPrice: '0xa',
+ type: TRANSACTION_TYPE_RETRY,
+ })
+ })
+
+ it('should call this.approveTransaction with the id of the returned tx', async () => {
+ const result = await txController.createSpeedUpTransaction(1)
+ assert.equal(approveTransactionSpy.callCount, 1)
+
+ const approveTransactionArg = approveTransactionSpy.getCall(0).args[0]
+ assert.equal(result.id, approveTransactionArg)
+ })
+
+ it('should return the expected txMeta', async () => {
+ const result = await txController.createSpeedUpTransaction(1)
+
+ assert.deepEqual(result.txParams, expectedTxParams)
+
+ const { lastGasPrice, type } = result
+ assert.deepEqual({ lastGasPrice, type }, {
+ lastGasPrice: '0xa',
+ type: TRANSACTION_TYPE_RETRY,
+ })
+ })
+ })
+
describe('#publishTransaction', function () {
let hash, txMeta
beforeEach(function () {
@@ -414,18 +492,20 @@ describe('Transaction Controller', function () {
})
describe('#retryTransaction', function () {
- it('should create a new txMeta with the same txParams as the original one', function (done) {
+ it('should create a new txMeta with the same txParams as the original one but with a higher gasPrice', function (done) {
const txParams = {
+ gasPrice: '0xee6b2800',
nonce: '0x00',
from: '0xB09d8505E1F4EF1CeA089D47094f5DD3464083d4',
to: '0xB09d8505E1F4EF1CeA089D47094f5DD3464083d4',
data: '0x0',
}
txController.txStateManager._saveTxList([
- { id: 1, status: 'submitted', metamaskNetworkId: currentNetworkId, txParams, history: [] },
+ { id: 1, status: 'submitted', metamaskNetworkId: currentNetworkId, txParams, history: [{}] },
])
txController.retryTransaction(1)
.then((txMeta) => {
+ assert.equal(txMeta.txParams.gasPrice, '0x10642ac00', 'gasPrice should have a %10 gasPrice bump')
assert.equal(txMeta.txParams.nonce, txParams.nonce, 'nonce should be the same')
assert.equal(txMeta.txParams.from, txParams.from, 'from should be the same')
assert.equal(txMeta.txParams.to, txParams.to, 'to should be the same')
@@ -461,17 +541,19 @@ describe('Transaction Controller', function () {
beforeEach(function () {
txController.txStateManager._saveTxList([
{ id: 1, status: 'unapproved', metamaskNetworkId: currentNetworkId, txParams: {} },
- { id: 2, status: 'rejected', metamaskNetworkId: currentNetworkId, txParams: {} },
- { id: 3, status: 'approved', metamaskNetworkId: currentNetworkId, txParams: {} },
- { id: 4, status: 'signed', metamaskNetworkId: currentNetworkId, txParams: {} },
- { id: 5, status: 'submitted', metamaskNetworkId: currentNetworkId, txParams: {} },
- { id: 6, status: 'confirmed', metamaskNetworkId: currentNetworkId, txParams: {} },
- { id: 7, status: 'failed', metamaskNetworkId: currentNetworkId, txParams: {} },
+ { id: 2, status: 'rejected', metamaskNetworkId: currentNetworkId, txParams: {}, history: [{}] },
+ { id: 3, status: 'approved', metamaskNetworkId: currentNetworkId, txParams: {}, history: [{}] },
+ { id: 4, status: 'signed', metamaskNetworkId: currentNetworkId, txParams: {}, history: [{}] },
+ { id: 5, status: 'submitted', metamaskNetworkId: currentNetworkId, txParams: {}, history: [{}] },
+ { id: 6, status: 'confirmed', metamaskNetworkId: currentNetworkId, txParams: {}, history: [{}] },
+ { id: 7, status: 'failed', metamaskNetworkId: currentNetworkId, txParams: {}, history: [{}] },
])
})
- it('should show only submitted transactions as pending transasction', function () {
- assert(txController.pendingTxTracker.getPendingTransactions().length, 1)
- assert(txController.pendingTxTracker.getPendingTransactions()[0].status, 'submitted')
+ it('should show only submitted and approved transactions as pending transasction', function () {
+ assert(txController.pendingTxTracker.getPendingTransactions().length, 2)
+ const states = txController.pendingTxTracker.getPendingTransactions().map(tx => tx.status)
+ assert(states.includes('approved'), 'includes approved')
+ assert(states.includes('submitted'), 'includes submitted')
})
})
})
diff --git a/test/unit/balance-formatter-test.js b/test/unit/balance-formatter-test.js
index ab6daa19c..bd0eb5008 100644
--- a/test/unit/balance-formatter-test.js
+++ b/test/unit/balance-formatter-test.js
@@ -1,6 +1,6 @@
const assert = require('assert')
const currencyFormatter = require('currency-formatter')
-const infuraConversion = require('../../ui/app/infura-conversion.json')
+const infuraConversion = require('../../ui/app/helpers/constants/infura-conversion.json')
describe('currencyFormatting', function () {
it('be able to format any infura currency', function (done) {
diff --git a/test/unit/components/binary-renderer-test.js b/test/unit/components/binary-renderer-test.js
deleted file mode 100644
index e428c26ad..000000000
--- a/test/unit/components/binary-renderer-test.js
+++ /dev/null
@@ -1,23 +0,0 @@
-var assert = require('assert')
-var BinaryRenderer = require('../../../old-ui/app/components/binary-renderer')
-
-describe('BinaryRenderer', function () {
- let binaryRenderer
- const message = 'Hello, world!'
- const buffer = Buffer.from(message, 'utf8')
- const hex = buffer.toString('hex')
-
- beforeEach(function () {
- binaryRenderer = new BinaryRenderer()
- })
-
- it('recovers message', function () {
- const result = binaryRenderer.hexToText(hex)
- assert.equal(result, message)
- })
-
- it('recovers message with hex prefix', function () {
- const result = binaryRenderer.hexToText('0x' + hex)
- assert.equal(result, message)
- })
-})
diff --git a/test/unit/components/bn-as-decimal-input-test.js b/test/unit/components/bn-as-decimal-input-test.js
deleted file mode 100644
index fab396548..000000000
--- a/test/unit/components/bn-as-decimal-input-test.js
+++ /dev/null
@@ -1,89 +0,0 @@
-var assert = require('assert')
-
-const additions = require('react-testutils-additions')
-const h = require('react-hyperscript')
-const ReactTestUtils = require('react-addons-test-utils')
-const ethUtil = require('ethereumjs-util')
-const BN = ethUtil.BN
-
-var BnInput = require('../../../old-ui/app/components/bn-as-decimal-input')
-
-describe('BnInput', function () {
- it('can tolerate a gas decimal number at a high precision', function (done) {
- const renderer = ReactTestUtils.createRenderer()
-
- let valueStr = '20'
- while (valueStr.length < 20) {
- valueStr += '0'
- }
- const value = new BN(valueStr, 10)
-
- const inputStr = '2.3'
-
- let targetStr = '23'
- while (targetStr.length < 19) {
- targetStr += '0'
- }
- const target = new BN(targetStr, 10)
-
- const precision = 18 // ether precision
- const scale = 18
-
- const props = {
- value,
- scale,
- precision,
- onChange: (newBn) => {
- assert.equal(newBn.toString(), target.toString(), 'should tolerate increase')
- done()
- },
- }
-
- const inputComponent = h(BnInput, props)
- const component = additions.renderIntoDocument(inputComponent)
- renderer.render(inputComponent)
- const input = additions.find(component, 'input.hex-input')[0]
- ReactTestUtils.Simulate.change(input, { preventDefault () {}, target: {
- value: inputStr,
- checkValidity () { return true } },
- })
- })
-
- it('can tolerate wei precision', function (done) {
- const renderer = ReactTestUtils.createRenderer()
-
- const valueStr = '1000000000'
-
- const value = new BN(valueStr, 10)
- const inputStr = '1.000000001'
-
-
- const targetStr = '1000000001'
-
- const target = new BN(targetStr, 10)
-
- const precision = 9 // gwei precision
- const scale = 9
-
- const props = {
- value,
- scale,
- precision,
- onChange: (newBn) => {
- assert.equal(newBn.toString(), target.toString(), 'should tolerate increase')
- const reInput = BnInput.prototype.downsize(newBn.toString(), 9, 9)
- assert.equal(reInput.toString(), inputStr, 'should tolerate increase')
- done()
- },
- }
-
- const inputComponent = h(BnInput, props)
- const component = additions.renderIntoDocument(inputComponent)
- renderer.render(inputComponent)
- const input = additions.find(component, 'input.hex-input')[0]
- ReactTestUtils.Simulate.change(input, { preventDefault () {}, target: {
- value: inputStr,
- checkValidity () { return true } },
- })
- })
-})
diff --git a/test/unit/development/sample-changelog.md b/test/unit/development/sample-changelog.md
index fd980e375..69f6513e6 100644
--- a/test/unit/development/sample-changelog.md
+++ b/test/unit/development/sample-changelog.md
@@ -1,6 +1,6 @@
# Changelog
-## Current Master
+## Current Develop Branch
## 4.1.3 2018-2-28
diff --git a/test/unit/migrations/029-test.js b/test/unit/migrations/029-test.js
new file mode 100644
index 000000000..a2876487b
--- /dev/null
+++ b/test/unit/migrations/029-test.js
@@ -0,0 +1,38 @@
+const assert = require('assert')
+const migration29 = require('../../../app/scripts/migrations/029')
+const properTime = (new Date()).getTime()
+const storage = {
+ 'meta': {},
+ 'data': {
+ 'TransactionController': {
+ 'transactions': [
+ { 'status': 'approved', id: 1, submittedTime: 0 },
+ { 'status': 'approved', id: 2, submittedTime: properTime },
+ { 'status': 'confirmed', id: 3, submittedTime: properTime },
+ { 'status': 'submitted', id: 4, submittedTime: properTime },
+ { 'status': 'submitted', id: 5, submittedTime: 0 },
+ ],
+ },
+ },
+}
+
+describe('storage is migrated successfully where transactions that are submitted have submittedTimes', () => {
+ it('should auto fail transactions more than 12 hours old', (done) => {
+ migration29.migrate(storage)
+ .then((migratedData) => {
+ const txs = migratedData.data.TransactionController.transactions
+ const [ txMeta1 ] = txs
+ assert.equal(migratedData.meta.version, 29)
+
+ assert.equal(txMeta1.status, 'failed', 'old tx is auto failed')
+ assert(txMeta1.err.message.includes('too long'), 'error message assigned')
+
+ txs.forEach((tx) => {
+ if (tx.id === 1) return
+ assert.notEqual(tx.status, 'failed', 'other tx is not auto failed')
+ })
+
+ done()
+ }).catch(done)
+ })
+})
diff --git a/test/unit/migrations/030-test.js b/test/unit/migrations/030-test.js
new file mode 100644
index 000000000..ca410342f
--- /dev/null
+++ b/test/unit/migrations/030-test.js
@@ -0,0 +1,37 @@
+const assert = require('assert')
+const migrationTemplate = require('../../../app/scripts/migrations/030.js')
+const storage = {
+ meta: {},
+ data: {
+ NetworkController: {
+ network: 'fail',
+ provider: {
+ chainId: 'fail',
+ nickname: '',
+ rpcTarget: 'https://api.myetherwallet.com/eth',
+ ticker: 'ETH',
+ type: 'rinkeby',
+ },
+ },
+ PreferencesController: {
+ frequentRpcListDetail: [
+ {chainId: 'fail', nickname: '', rpcUrl: 'http://127.0.0.1:8545', ticker: ''},
+ {chainId: '1', nickname: '', rpcUrl: 'https://api.myetherwallet.com/eth', ticker: 'ETH'},
+ ],
+ },
+ },
+}
+
+describe('storage is migrated successfully', () => {
+ it('should work', (done) => {
+ migrationTemplate.migrate(storage)
+ .then((migratedData) => {
+ assert.equal(migratedData.meta.version, 30)
+ assert.equal(migratedData.data.PreferencesController.frequentRpcListDetail[0].chainId, undefined)
+ assert.equal(migratedData.data.PreferencesController.frequentRpcListDetail[1].chainId, '1')
+ assert.equal(migratedData.data.NetworkController.provider.chainId, undefined)
+ assert.equal(migratedData.data.NetworkController.network, undefined)
+ done()
+ }).catch(done)
+ })
+})
diff --git a/test/unit/migrations/031-test.js b/test/unit/migrations/031-test.js
new file mode 100644
index 000000000..c85fd7af4
--- /dev/null
+++ b/test/unit/migrations/031-test.js
@@ -0,0 +1,56 @@
+const assert = require('assert')
+const migration31 = require('../../../app/scripts/migrations/031')
+
+ describe('migration #31', () => {
+ it('should set completedOnboarding to true if vault exists', done => {
+ const oldStorage = {
+ 'meta': {},
+ 'data': {
+ 'PreferencesController': {
+ 'tokens': [{address: '0xa', symbol: 'A', decimals: 4}, {address: '0xb', symbol: 'B', decimals: 4}],
+ 'identities': {
+ '0x6d14': {},
+ '0x3695': {},
+ },
+ },
+ 'KeyringController': {
+ 'vault': {
+ 'data': 'test0',
+ 'iv': 'test1',
+ 'salt': 'test2',
+ },
+ },
+ },
+ }
+
+ migration31.migrate(oldStorage)
+ .then(newStorage => {
+ assert.equal(newStorage.data.PreferencesController.completedOnboarding, true)
+ done()
+ })
+ .catch(done)
+ })
+
+ it('should set completedOnboarding to false if vault does not exist', done => {
+ const oldStorage = {
+ 'meta': {},
+ 'data': {
+ 'PreferencesController': {
+ 'tokens': [{address: '0xa', symbol: 'A', decimals: 4}, {address: '0xb', symbol: 'B', decimals: 4}],
+ 'identities': {
+ '0x6d14': {},
+ '0x3695': {},
+ },
+ },
+ 'KeyringController': {},
+ },
+ }
+
+ migration31.migrate(oldStorage)
+ .then(newStorage => {
+ assert.equal(newStorage.data.PreferencesController.completedOnboarding, false)
+ done()
+ })
+ .catch(done)
+ })
+})
diff --git a/test/unit/nameForAccount_test.js b/test/unit/nameForAccount_test.js
deleted file mode 100644
index 9bb02c6bc..000000000
--- a/test/unit/nameForAccount_test.js
+++ /dev/null
@@ -1,41 +0,0 @@
-var assert = require('assert')
-var sinon = require('sinon')
-
-var path = require('path')
-var contractNamer = require(path.join(__dirname, '..', '..', 'old-ui', 'lib', 'contract-namer.js'))
-
-describe('contractNamer', function () {
- beforeEach(function () {
- this.sinon = sinon.createSandbox()
- })
-
- afterEach(function () {
- this.sinon.restore()
- })
-
- describe('naming a contract', function () {
- it('should return nothing for an unknown random account', function () {
- const input = '0x2386F26FC10000'
- const output = contractNamer(input)
- assert.deepEqual(output, null)
- })
-
- it('should accept identities as an optional second parameter', function () {
- const input = '0x2386F26FC10000'.toLowerCase()
- const expected = 'bar'
- const identities = {}
- identities[input] = { name: expected }
- const output = contractNamer(input, identities)
- assert.deepEqual(output, expected)
- })
-
- it('should check for identities case insensitively', function () {
- const input = '0x2386F26FC10000'.toLowerCase()
- const expected = 'bar'
- const identities = {}
- identities[input] = { name: expected }
- const output = contractNamer(input.toUpperCase(), identities)
- assert.deepEqual(output, expected)
- })
- })
-})
diff --git a/test/unit/reducers/unlock_vault_test.js b/test/unit/reducers/unlock_vault_test.js
index d66e8edbb..d66891a63 100644
--- a/test/unit/reducers/unlock_vault_test.js
+++ b/test/unit/reducers/unlock_vault_test.js
@@ -4,8 +4,8 @@ var assert = require('assert')
var path = require('path')
var sinon = require('sinon')
-var actions = require(path.join(__dirname, '..', '..', '..', 'ui', 'app', 'actions.js'))
-var reducers = require(path.join(__dirname, '..', '..', '..', 'ui', 'app', 'reducers.js'))
+var actions = require(path.join(__dirname, '..', '..', '..', 'ui', 'app', 'store', 'actions.js'))
+var reducers = require(path.join(__dirname, '..', '..', '..', 'ui', 'app', 'ducks', 'index.js'))
describe('#unlockMetamask(selectedAccount)', function () {
beforeEach(function () {
diff --git a/test/unit/responsive/components/dropdown-test.js b/test/unit/responsive/components/dropdown-test.js
index f3f236d90..1fadbfb60 100644
--- a/test/unit/responsive/components/dropdown-test.js
+++ b/test/unit/responsive/components/dropdown-test.js
@@ -3,7 +3,7 @@ const assert = require('assert')
const h = require('react-hyperscript')
const sinon = require('sinon')
const path = require('path')
-const Dropdown = require(path.join(__dirname, '..', '..', '..', '..', 'ui', 'app', 'components', 'dropdowns', 'index.js')).Dropdown
+const Dropdown = require(path.join(__dirname, '..', '..', '..', '..', 'ui', 'app', 'components', 'app', 'dropdowns', 'index.js')).Dropdown
const { createMockStore } = require('redux-test-utils')
const { mountWithStore } = require('../../../lib/render-helpers')
diff --git a/test/unit/ui/add-token.spec.js b/test/unit/ui/add-token.spec.js
deleted file mode 100644
index f6b6155a0..000000000
--- a/test/unit/ui/add-token.spec.js
+++ /dev/null
@@ -1,43 +0,0 @@
-const assert = require('assert')
-const { createMockStore } = require('redux-test-utils')
-const h = require('react-hyperscript')
-const { shallowWithStore } = require('../../lib/render-helpers')
-const AddTokenScreen = require('../../../old-ui/app/add-token')
-
-describe('Add Token Screen', function () {
- let addTokenComponent, store, component
- const mockState = {
- metamask: {
- identities: {
- '0x7d3517b0d011698406d6e0aed8453f0be2697926': {
- 'address': '0x7d3517b0d011698406d6e0aed8453f0be2697926',
- 'name': 'Add Token Name',
- },
- },
- },
- }
- beforeEach(function () {
- store = createMockStore(mockState)
- component = shallowWithStore(h(AddTokenScreen), store)
- addTokenComponent = component.dive()
- })
-
- describe('#ValidateInputs', function () {
-
- it('Default State', function () {
- addTokenComponent.instance().validateInputs()
- const state = addTokenComponent.state()
- assert.equal(state.warning, 'Address is invalid.')
- })
-
- it('Address is a Metamask Identity', function () {
- addTokenComponent.setState({
- address: '0x7d3517b0d011698406d6e0aed8453f0be2697926',
- })
- addTokenComponent.instance().validateInputs()
- const state = addTokenComponent.state()
- assert.equal(state.warning, 'Personal address detected. Input the token contract address.')
- })
-
- })
-})
diff --git a/test/unit/ui/app/actions.spec.js b/test/unit/ui/app/actions.spec.js
index df7d2ee8f..46e94bb32 100644
--- a/test/unit/ui/app/actions.spec.js
+++ b/test/unit/ui/app/actions.spec.js
@@ -16,7 +16,7 @@ const { createTestProviderTools } = require('../../../stub/provider')
const provider = createTestProviderTools({ scaffold: {}}).provider
const enLocale = require('../../../../app/_locales/en/messages.json')
-const actions = require('../../../../ui/app/actions')
+const actions = require('../../../../ui/app/store/actions')
const MetaMaskController = require('../../../../app/scripts/metamask-controller')
const firstTimeState = require('../../../unit/localhostState')
@@ -198,7 +198,7 @@ describe('Actions', () => {
createNewVaultAndRestoreSpy = sinon.spy(background, 'createNewVaultAndRestore')
clearSeedWordCacheSpy = sinon.spy(background, 'clearSeedWordCache')
return store.dispatch(actions.createNewVaultAndRestore())
- .then(() => {
+ .catch(() => {
assert(clearSeedWordCacheSpy.calledOnce)
assert(createNewVaultAndRestoreSpy.calledOnce)
})
@@ -218,7 +218,7 @@ describe('Actions', () => {
})
return store.dispatch(actions.createNewVaultAndRestore())
- .then(() => {
+ .catch(() => {
assert.deepEqual(store.getActions(), expectedActions)
})
})
@@ -240,7 +240,7 @@ describe('Actions', () => {
})
return store.dispatch(actions.createNewVaultAndRestore())
- .then(() => {
+ .catch(() => {
assert.deepEqual(store.getActions(), expectedActions)
})
})
@@ -1079,8 +1079,10 @@ describe('Actions', () => {
describe('#setProviderType', () => {
let setProviderTypeSpy
+ let store
beforeEach(() => {
+ store = mockStore({ metamask: { provider: {} } })
setProviderTypeSpy = sinon.stub(background, 'setProviderType')
})
@@ -1089,13 +1091,11 @@ describe('Actions', () => {
})
it('', () => {
- const store = mockStore()
store.dispatch(actions.setProviderType())
assert(setProviderTypeSpy.calledOnce)
})
it('', () => {
- const store = mockStore()
const expectedActions = [
{ type: 'DISPLAY_WARNING', value: 'Had a problem changing networks!' },
]
diff --git a/test/unit/ui/app/components/token-cell.spec.js b/test/unit/ui/app/components/token-cell.spec.js
index 6145c6924..23e76c418 100644
--- a/test/unit/ui/app/components/token-cell.spec.js
+++ b/test/unit/ui/app/components/token-cell.spec.js
@@ -5,8 +5,8 @@ import { Provider } from 'react-redux'
import configureMockStore from 'redux-mock-store'
import { mount } from 'enzyme'
-import TokenCell from '../../../../../ui/app/components/token-cell'
-import Identicon from '../../../../../ui/app/components/identicon'
+import TokenCell from '../../../../../ui/app/components/app/token-cell'
+import Identicon from '../../../../../ui/app/components/ui/identicon'
describe('Token Cell', () => {
let wrapper
diff --git a/test/unit/ui/app/reducers/app.spec.js b/test/unit/ui/app/reducers/app.spec.js
index bee4963e5..6c77e0ef9 100644
--- a/test/unit/ui/app/reducers/app.spec.js
+++ b/test/unit/ui/app/reducers/app.spec.js
@@ -1,6 +1,6 @@
import assert from 'assert'
-import reduceApp from '../../../../../ui/app/reducers/app'
-import * as actions from '../../../../../ui/app/actions'
+import reduceApp from '../../../../../ui/app/ducks/app/app'
+import * as actions from '../../../../../ui/app/store/actions'
describe('App State', () => {
diff --git a/test/unit/ui/app/reducers/metamask.spec.js b/test/unit/ui/app/reducers/metamask.spec.js
index e1a50eef2..388c67c76 100644
--- a/test/unit/ui/app/reducers/metamask.spec.js
+++ b/test/unit/ui/app/reducers/metamask.spec.js
@@ -1,11 +1,11 @@
import assert from 'assert'
-import reduceMetamask from '../../../../../ui/app/reducers/metamask'
-import * as actions from '../../../../../ui/app/actions'
+import reduceMetamask from '../../../../../ui/app/ducks/metamask/metamask'
+import * as actions from '../../../../../ui/app/store/actions'
describe('MetaMask Reducers', () => {
it('init state', () => {
- const initState = reduceMetamask({metamask:{}}, {})
+ const initState = reduceMetamask({metamask: {}}, {})
assert(initState)
})
@@ -502,17 +502,15 @@ describe('MetaMask Reducers', () => {
assert.equal(state.useBlockie, true)
})
- it('updates feature flag', () => {
+ it('updates an arbitrary feature flag', () => {
const state = reduceMetamask({}, {
type: actions.UPDATE_FEATURE_FLAGS,
value: {
- betaUI: true,
- skipAnnounceBetaUI: true,
+ foo: true,
},
})
- assert.equal(state.featureFlags.betaUI, true)
- assert.equal(state.featureFlags.skipAnnounceBetaUI, true)
+ assert.equal(state.featureFlags.foo, true)
})
it('updates network endpoint type', () => {
diff --git a/test/unit/ui/app/selectors.spec.js b/test/unit/ui/app/selectors.spec.js
index 78c4267ee..b4aa8e272 100644
--- a/test/unit/ui/app/selectors.spec.js
+++ b/test/unit/ui/app/selectors.spec.js
@@ -1,5 +1,5 @@
const assert = require('assert')
-const selectors = require('../../../../ui/app/selectors')
+const selectors = require('../../../../ui/app/selectors/selectors')
const mockState = require('../../../data/mock-state.json')
const Eth = require('ethjs')
@@ -19,6 +19,7 @@ describe('Selectors', function () {
'address': '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc',
},
},
+ cachedBalances: {},
},
}
})
@@ -148,7 +149,7 @@ describe('Selectors', function () {
it('#getSelectedTokenToFiatRate', () => {
const selectedTokenToFiatRate = selectors.getSelectedTokenToFiatRate(mockState)
- assert.equal(selectedTokenToFiatRate, '0.21880988420033493')
+ assert.equal(selectedTokenToFiatRate, '0.21880988420033492152')
})
describe('#getSelectedTokenContract', () => {
diff --git a/test/unit/util_test.js b/test/unit/util_test.js
index 39473854f..87f57b218 100644
--- a/test/unit/util_test.js
+++ b/test/unit/util_test.js
@@ -3,7 +3,7 @@ var sinon = require('sinon')
const ethUtil = require('ethereumjs-util')
var path = require('path')
-var util = require(path.join(__dirname, '..', '..', 'ui', 'app', 'util.js'))
+var util = require(path.join(__dirname, '..', '..', 'ui', 'app', 'helpers', 'utils', 'util.js'))
describe('util', function () {
var ethInWei = '1'