From d5c311b13e6a9399252c4617b07ad463f6ead9b0 Mon Sep 17 00:00:00 2001 From: frankiebee Date: Sun, 14 Jan 2018 13:56:54 -0800 Subject: [PATCH 1/6] add a loading spinner to conf-tx view --- ui/app/conf-tx.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/ui/app/conf-tx.js b/ui/app/conf-tx.js index cb1afedfe..ce4d153b5 100644 --- a/ui/app/conf-tx.js +++ b/ui/app/conf-tx.js @@ -4,6 +4,7 @@ const h = require('react-hyperscript') const connect = require('react-redux').connect const actions = require('./actions') const NetworkIndicator = require('./components/network') +const LoadingIndicator = require('./components/loading') const txHelper = require('../lib/tx-helper') const isPopupOrNotification = require('../../app/scripts/lib/is-popup-or-notification') @@ -60,6 +61,11 @@ ConfirmTxScreen.prototype.render = function () { h('.flex-column.flex-grow', [ + h(LoadingIndicator, { + isLoading: txData.loadingDefaults, + loadingMessage: 'Estimating transaction cost…', + }), + // subtitle and nav h('.section-title.flex-row.flex-center', [ !isNotification ? h('i.fa.fa-arrow-left.fa-lg.cursor-pointer', { From f0dd4f19238d63875fbdfa3a9b31fa7b9d8925ed Mon Sep 17 00:00:00 2001 From: frankiebee Date: Sun, 14 Jan 2018 14:00:17 -0800 Subject: [PATCH 2/6] transactions - emit 'newUnapprovedTx' before estimateGas finishes --- app/scripts/controllers/transactions.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index ded9739a8..bb9253175 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -139,7 +139,6 @@ module.exports = class TransactionController extends EventEmitter { async newUnapprovedTransaction (txParams) { log.debug(`MetaMaskController newUnapprovedTransaction ${JSON.stringify(txParams)}`) const initialTxMeta = await this.addUnapprovedTransaction(txParams) - this.emit('newUnapprovedTx', initialTxMeta) // listen for tx completion (success, fail) return new Promise((resolve, reject) => { this.txStateManager.once(`${initialTxMeta.id}:finished`, (finishedTxMeta) => { @@ -167,11 +166,16 @@ module.exports = class TransactionController extends EventEmitter { status: 'unapproved', metamaskNetworkId: this.getNetwork(), txParams: txParams, + loadingDefaults: true, } + this.addTx(txMeta) + this.emit('newUnapprovedTx', txMeta) // add default tx params await this.addTxDefaults(txMeta) + + txMeta.loadingDefaults = false // save txMeta - this.addTx(txMeta) + this.txStateManager.updateTx(txMeta) return txMeta } From 409b49b411fee4c3f6f9106d99e2bba915bb5f0f Mon Sep 17 00:00:00 2001 From: frankiebee Date: Sun, 14 Jan 2018 14:00:59 -0800 Subject: [PATCH 3/6] test - create ethJsQuery stub --- test/stub/provider.js | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/test/stub/provider.js b/test/stub/provider.js index 8a306f6d9..85e1da707 100644 --- a/test/stub/provider.js +++ b/test/stub/provider.js @@ -5,7 +5,8 @@ module.exports = { createEngineForTestData, providerFromEngine, scaffoldMiddleware, - createStubedProvider + createEthJsQueryStub, + createStubedProvider, } @@ -18,6 +19,18 @@ function providerFromEngine (engine) { return provider } +function createEthJsQueryStub (stubProvider) { + return new Proxy({}, { + get: (obj, method) => { + return (...params) => { + return new Promise((resolve, reject) => { + stubProvider.sendAsync({ method: `eth_${method}`, params }, (err, ress) => resolve(ress.result)) + }) + } + }, + }) +} + function createStubedProvider (resultStub) { const engine = createEngineForTestData() engine.push(scaffoldMiddleware(resultStub)) From 7a30950e4dd31a2e4b1807bf3d1e2a09a25da323 Mon Sep 17 00:00:00 2001 From: frankiebee Date: Sun, 14 Jan 2018 14:01:37 -0800 Subject: [PATCH 4/6] test - fix to match expected behavior --- test/unit/tx-controller-test.js | 42 ++++++++++++++++++++++----------- 1 file changed, 28 insertions(+), 14 deletions(-) diff --git a/test/unit/tx-controller-test.js b/test/unit/tx-controller-test.js index aeefd5ec6..36f3e1c68 100644 --- a/test/unit/tx-controller-test.js +++ b/test/unit/tx-controller-test.js @@ -5,7 +5,7 @@ const ObservableStore = require('obs-store') const sinon = require('sinon') const TransactionController = require('../../app/scripts/controllers/transactions') const TxGasUtils = require('../../app/scripts/lib/tx-gas-utils') -const { createStubedProvider } = require('../stub/provider') +const { createStubedProvider, createEthJsQueryStub } = require('../stub/provider') const noop = () => true const currentNetworkId = 42 @@ -30,6 +30,8 @@ describe('Transaction Controller', function () { resolve() }), }) + txController.query = createEthJsQueryStub(provider) + txController.txGasUtil.query = createEthJsQueryStub(provider) txController.nonceTracker.getNonceLock = () => Promise.resolve({ nextNonce: 0, releaseLock: noop }) txController.txProviderUtils = new TxGasUtils(txController.provider) }) @@ -110,23 +112,16 @@ describe('Transaction Controller', function () { history: [], } txController.txStateManager._saveTxList([txMeta]) - stub = sinon.stub(txController, 'addUnapprovedTransaction').returns(Promise.resolve(txController.txStateManager.addTx(txMeta))) + stub = sinon.stub(txController, 'addUnapprovedTransaction').callsFake(() => { + txController.emit('newUnapprovedTx', txMeta) + return Promise.resolve(txController.txStateManager.addTx(txMeta)) }) afterEach(function () { txController.txStateManager._saveTxList([]) stub.restore() }) - - it('should emit newUnapprovedTx event and pass txMeta as the first argument', function (done) { - txController.once('newUnapprovedTx', (txMetaFromEmit) => { - assert(txMetaFromEmit, 'txMeta is falsey') - assert.equal(txMetaFromEmit.id, 1, 'the right txMeta was passed') - done() - }) - txController.newUnapprovedTransaction(txParams) - .catch(done) - }) + }) it('should resolve when finished and status is submitted and resolve with the hash', function (done) { txController.once('newUnapprovedTx', (txMetaFromEmit) => { @@ -160,8 +155,17 @@ describe('Transaction Controller', function () { }) describe('#addUnapprovedTransaction', function () { + let addTxDefaults + beforeEach(() => { + addTxDefaults = txController.addTxDefaults + txController.addTxDefaults = function addTxDefaultsStub () { return Promise.resolve() } + + }) + afterEach(() => { + txController.addTxDefaults = addTxDefaults + }) + it('should add an unapproved transaction and return a valid txMeta', function (done) { - const addTxDefaultsStub = sinon.stub(txController, 'addTxDefaults').callsFake(() => Promise.resolve()) txController.addUnapprovedTransaction({}) .then((txMeta) => { assert(('id' in txMeta), 'should have a id') @@ -172,10 +176,20 @@ describe('Transaction Controller', function () { const memTxMeta = txController.txStateManager.getTx(txMeta.id) assert.deepEqual(txMeta, memTxMeta, `txMeta should be stored in txController after adding it\n expected: ${txMeta} \n got: ${memTxMeta}`) - addTxDefaultsStub.restore() done() }).catch(done) }) + + it('should emit newUnapprovedTx event and pass txMeta as the first argument', function (done) { + providerResultStub.eth_gasPrice = '4a817c800' + txController.once('newUnapprovedTx', (txMetaFromEmit) => { + assert(txMetaFromEmit, 'txMeta is falsey') + done() + }) + txController.addUnapprovedTransaction({}) + .catch(done) + }) + }) describe('#addTxDefaults', function () { From 724197b95f30931e17edaf86c7391687b2922457 Mon Sep 17 00:00:00 2001 From: frankiebee Date: Mon, 15 Jan 2018 15:23:11 -0800 Subject: [PATCH 5/6] add to CHANGELOG.md --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4b4218210..b681ebcb8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ## Current Master +- Open metamask popup for transaction confirmation before gas estimation finishes and add a loading screen over transaction confirmation. + ## 3.13.4 2018-1-9 - Remove recipient field if application initializes a tx with an empty string, or 0x, and tx data. Throw an error with the same condition, but without tx data. From 58be1742e1fbfc6ae73e50256849f2e673989446 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Mon, 15 Jan 2018 16:04:49 -0800 Subject: [PATCH 6/6] Rename lock to log out Fixes #2475 --- ui/app/app.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/app/app.js b/ui/app/app.js index bc198b482..f0dfef34f 100644 --- a/ui/app/app.js +++ b/ui/app/app.js @@ -395,7 +395,7 @@ App.prototype.renderDropdown = function () { h(DropdownMenuItem, { closeMenu: () => this.setState({ isMainMenuOpen: !isOpen }), onClick: () => { this.props.dispatch(actions.lockMetamask()) }, - }, 'Lock'), + }, 'Log Out'), h(DropdownMenuItem, { closeMenu: () => this.setState({ isMainMenuOpen: !isOpen }),