diff --git a/js/src/redux/providers/chainMiddleware.js b/js/src/redux/providers/chainMiddleware.js index 2df40ed86..398e604be 100644 --- a/js/src/redux/providers/chainMiddleware.js +++ b/js/src/redux/providers/chainMiddleware.js @@ -14,8 +14,6 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -import BalancesProvider from './balances'; -import { showSnackbar } from './snackbarActions'; import { DEFAULT_NETCHAIN } from './statusReducer'; export default class ChainMiddleware { @@ -24,20 +22,34 @@ export default class ChainMiddleware { if (action.type === 'statusCollection') { const { collection } = action; - if (collection && collection.netChain) { - const newChain = collection.netChain; + if (collection) { const { nodeStatus } = store.getState(); + const { netChain, nodeKind } = nodeStatus; + const newChain = collection.netChain; + const newNodeKind = collection.nodeKind; + let reloadChain = false; + let reloadType = false; - if (newChain !== nodeStatus.netChain && nodeStatus.netChain !== DEFAULT_NETCHAIN) { - store.dispatch(showSnackbar(`Switched to ${newChain}. The UI will reload now...`)); + // force reload when chain has changed and is not initial value + if (newChain) { + const hasChainChanged = newChain !== netChain; + const isInitialChain = netChain === DEFAULT_NETCHAIN; + + reloadChain = !isInitialChain && hasChainChanged; + } + + // force reload when nodeKind (availability or capability) has changed + if (newNodeKind && nodeKind) { + const hasAvailabilityChanged = nodeKind.availability !== newNodeKind.availability; + const hasCapabilityChanged = nodeKind.capability !== newNodeKind.capability; + + reloadType = hasAvailabilityChanged || hasCapabilityChanged; + } + + if (reloadChain || reloadType) { setTimeout(() => { window.location.reload(); }, 0); - - // Fetch the new balances without notifying the user of any change - BalancesProvider.get(store).fetchAllBalances({ - changedNetwork: true - }); } } } diff --git a/js/src/redux/providers/chainMiddleware.spec.js b/js/src/redux/providers/chainMiddleware.spec.js index 50a25caf6..837031c29 100644 --- a/js/src/redux/providers/chainMiddleware.spec.js +++ b/js/src/redux/providers/chainMiddleware.spec.js @@ -24,11 +24,22 @@ import { createWsApi } from '~/../test/e2e/ethapi'; let middleware; let next; let store; +let clock; const api = createWsApi(); Contracts.create(api); +function stubGlobals () { + clock = sinon.useFakeTimers(); + sinon.spy(window.location, 'reload'); +} + +function restoreGlobals () { + window.location.reload.restore(); + clock.restore(); +} + function createMiddleware (collection = {}) { middleware = new ChainMiddleware().toMiddleware(); next = sinon.stub(); @@ -46,10 +57,22 @@ function createMiddleware (collection = {}) { } function callMiddleware (action) { - return middleware(store)(next)(action); + const result = middleware(store)(next)(action); + + clock.tick(100); + + return result; } describe('reduxs/providers/ChainMiddleware', () => { + beforeEach(() => { + stubGlobals(); + }); + + afterEach(() => { + restoreGlobals(); + }); + describe('next action', () => { beforeEach(() => { createMiddleware(); @@ -69,25 +92,25 @@ describe('reduxs/providers/ChainMiddleware', () => { }); describe('chain switching', () => { - it('does not dispatch when moving from the initial/unknown chain', () => { + it('does not reload when moving from the initial/unknown chain', () => { createMiddleware(); callMiddleware({ type: 'statusCollection', collection: { netChain: 'homestead' } }); - expect(store.dispatch).not.to.have.been.called; + expect(window.location.reload).not.to.have.been.called; }); - it('does not dispatch when moving to the same chain', () => { + it('does not reload when moving to the same chain', () => { createMiddleware({ netChain: 'homestead' }); callMiddleware({ type: 'statusCollection', collection: { netChain: 'homestead' } }); - expect(store.dispatch).not.to.have.been.called; + expect(window.location.reload).not.to.have.been.called; }); - it('does dispatch when moving between chains', () => { + it('does reload when moving between chains', () => { createMiddleware({ netChain: 'homestead' }); callMiddleware({ type: 'statusCollection', collection: { netChain: 'ropsten' } }); - expect(store.dispatch).to.have.been.called; + expect(window.location.reload).to.have.been.called; }); }); }); diff --git a/js/src/redux/providers/status.js b/js/src/redux/providers/status.js index 0fa354d1a..19bec2c0a 100644 --- a/js/src/redux/providers/status.js +++ b/js/src/redux/providers/status.js @@ -156,7 +156,8 @@ export default class Status { } _pollTraceMode = () => { - return this._api.trace.block() + return this._api.trace + .block() .then(blockTraces => { // Assumes not in Trace Mode if no transactions // in latest block... @@ -168,14 +169,12 @@ export default class Status { getApiStatus = () => { const { isConnected, isConnecting, needsToken, secureToken } = this._api; - const apiStatus = { + return { isConnected, isConnecting, needsToken, secureToken }; - - return apiStatus; } _pollStatus = () => { @@ -194,7 +193,10 @@ export default class Status { return Promise.resolve(); } - const statusPromises = [ this._api.eth.syncing(), this._api.parity.netPeers() ]; + const statusPromises = [ + this._api.eth.syncing(), + this._api.parity.netPeers() + ]; return Promise .all(statusPromises) @@ -225,7 +227,10 @@ export default class Status { return Promise.resolve(); } - const nextTimeout = (timeout = 30000) => { + const { nodeKindFull } = this._store.getState().nodeStatus; + const defaultTimeout = (nodeKindFull === false ? 240 : 30) * 1000; + + const nextTimeout = (timeout = defaultTimeout) => { if (this._timeoutIds.longStatus) { clearTimeout(this._timeoutIds.longStatus); } @@ -233,24 +238,34 @@ export default class Status { this._timeoutIds.longStatus = setTimeout(() => this._pollLongStatus(), timeout); }; + const statusPromises = [ + this._api.parity.nodeKind(), + this._api.parity.netPeers(), + this._api.web3.clientVersion(), + this._api.net.version(), + this._api.parity.netChain() + ]; + + if (nodeKindFull) { + statusPromises.push(this._upgradeStore.checkUpgrade()); + } + return Promise - .all([ - this._api.parity.netPeers(), - this._api.web3.clientVersion(), - this._api.net.version(), - this._api.parity.netChain(), - this._upgradeStore.checkUpgrade() - ]) - .then(([ - netPeers, clientVersion, netVersion, netChain, upgradeStatus - ]) => { + .all(statusPromises) + .then(([nodeKind, netPeers, clientVersion, netVersion, netChain]) => { const isTest = [ '2', // morden '3', // ropsten '42' // kovan ].includes(netVersion); + const nodeKindFull = nodeKind && + nodeKind.availability === 'personal' && + nodeKind.capability === 'full'; + const longStatus = { + nodeKind, + nodeKindFull, netPeers, clientVersion, netChain, diff --git a/js/src/redux/providers/statusReducer.js b/js/src/redux/providers/statusReducer.js index 6f509735e..12fe9654d 100644 --- a/js/src/redux/providers/statusReducer.js +++ b/js/src/redux/providers/statusReducer.js @@ -31,6 +31,8 @@ const initialState = { peers: [] }, netVersion: '0', + nodeKind: null, + nodeKindFull: null, syncing: true, isConnected: false, isConnecting: false,