diff --git a/gulpfile.js b/gulpfile.js
index 1ec73adea..59006cf5a 100644
--- a/gulpfile.js
+++ b/gulpfile.js
@@ -7,7 +7,7 @@ var packager = require('electron-packager');
var spawn = require('child_process').spawn;
var merge = require('merge-stream');
var rename = require("gulp-rename");
-var download = require('gulp-download');
+var download = require('gulp-download-stream');
var decompress = require('gulp-decompress');
var tap = require("gulp-tap");
// const zip = require('gulp-zip');
diff --git a/interface/client/templates/popupWindows/splashScreen.html b/interface/client/templates/popupWindows/splashScreen.html
index 1cf165530..008408034 100644
--- a/interface/client/templates/popupWindows/splashScreen.html
+++ b/interface/client/templates/popupWindows/splashScreen.html
@@ -21,7 +21,9 @@
{{#if TemplateVar.get "showProgressBar"}}
-
+ {{#if TemplateVar.get "showStateProgressBar"}}
+
+ {{/if}}
{{/if}}
\ No newline at end of file
diff --git a/interface/client/templates/popupWindows/splashScreen.js b/interface/client/templates/popupWindows/splashScreen.js
index b588ce249..8d47c9e0e 100644
--- a/interface/client/templates/popupWindows/splashScreen.js
+++ b/interface/client/templates/popupWindows/splashScreen.js
@@ -100,8 +100,10 @@ Template['popupWindows_splashScreen'].onCreated(function(){
if(web3.net.peerCount > 0) {
// Check which state we are
- if ( lastSyncData.pulledStates != Math.round(lastSyncData._displayState)
- || lastSyncData.knownStates != Math.round(lastSyncData._displayKnownStates)) {
+ if ( 0 < lastSyncData._displayKnownStates && (
+ lastSyncData.pulledStates != Math.round(lastSyncData._displayState)
+ || lastSyncData.knownStates != Math.round(lastSyncData._displayKnownStates))
+ ) {
// Mostly downloading new states
translationString = 'mist.startScreen.nodeSyncInfoStates';
@@ -181,16 +183,13 @@ Template['popupWindows_splashScreen'].helpers({
if (!(syncData._displayBlock > -1)) {
// initialize the display numbers
syncData._displayBlock = Number(syncData.currentBlock);
- syncData._displayState = Number(syncData.pulledStates);
- syncData._displayKnownStates = Number(syncData.knownStates);
-
+ syncData._displayState = Number(syncData.pulledStates || 0);
+ syncData._displayKnownStates = Number(syncData.knownStates || 0);
} else {
// Increment each them slowly to match target number
- syncData._displayBlock = syncData._displayBlock + (Number(syncData.currentBlock) - syncData._displayBlock) / 10;
-
- syncData._displayState = syncData._displayState + (Number(syncData.pulledStates) - syncData._displayState) / 10;
-
- syncData._displayKnownStates = syncData._displayKnownStates + (Number(syncData.knownStates) - syncData._displayKnownStates) / 10;
+ syncData._displayBlock += (Number(syncData.currentBlock) - syncData._displayBlock) / 10;
+ syncData._displayState += (Number(syncData.pulledStates || 0) - syncData._displayState) / 10;
+ syncData._displayKnownStates += (Number(syncData.knownStates || 0) - syncData._displayKnownStates) / 10;
};
// Create the fancy strings
@@ -202,7 +201,10 @@ Template['popupWindows_splashScreen'].helpers({
var translatedMessage = TAPi18n.__(translationString, syncData);
// Calculates both progress bars
- var stateProgress = (lastSyncData._displayState / lastSyncData._displayKnownStates) * 100;
+ var stateProgress = null;
+ if (0 < lastSyncData._displayKnownStates) {
+ stateProgress = (lastSyncData._displayState / lastSyncData._displayKnownStates) * 100;
+ }
var progress = ((lastSyncData._displayBlock - Number(lastSyncData.startingBlock)) / (Number(lastSyncData._highestBlock) - Number(lastSyncData.startingBlock))) * 100 ;
@@ -214,7 +216,10 @@ Template['popupWindows_splashScreen'].helpers({
if(_.isFinite(progress)) {
TemplateVar.set(template, 'showProgressBar', true);
TemplateVar.set(template, 'progress', progress);
- TemplateVar.set(template, 'stateProgress', stateProgress);
+ if (null !== stateProgress) {
+ TemplateVar.set(template, 'showStateProgressBar', true);
+ TemplateVar.set(template, 'stateProgress', stateProgress);
+ }
}
}, 100);
diff --git a/main.js b/main.js
index 239f57446..c6d844573 100644
--- a/main.js
+++ b/main.js
@@ -144,20 +144,14 @@ app.on('before-quit', function(event){
// delay quit, so the sockets can close
setTimeout(function(){
- killedSockets = true;
-
ethereumNode.stop().then(function() {
+ killedSockets = true;
app.quit();
});
}, 500);
});
-
-
-const NODE_TYPE = 'geth';
-
-
var mainWindow;
var splashWindow;
diff --git a/modules/ethereumNode.js b/modules/ethereumNode.js
index cc4b31696..8cf2a3f8f 100644
--- a/modules/ethereumNode.js
+++ b/modules/ethereumNode.js
@@ -24,7 +24,7 @@ const DEFAULT_NETWORK = 'main';
const UNABLE_TO_BIND_PORT_ERROR = 'unableToBindPort';
const UNABLE_TO_SPAWN_ERROR = 'unableToSpan';
const PASSWORD_WRONG_ERROR = 'badPassword';
-
+const NODE_START_WAIT_MS = 3000;
/**
@@ -143,7 +143,7 @@ class EthereumNode extends EventEmitter {
return this._start(this.defaultNodeType, this.defaultNetwork)
.catch((err) => {
log.error('Failed to start node', err);
-
+
throw err;
});
});
@@ -289,8 +289,8 @@ class EthereumNode extends EventEmitter {
this._saveUserData('network', this._network);
return this._socket.connect({ path: ipcPath }, {
- timeout: 30000 /* 30s */
- })
+ timeout: 30000 /* 30s */
+ })
.then(() => {
this.state = STATES.CONNECTED;
})
@@ -336,60 +336,8 @@ class EthereumNode extends EventEmitter {
log.debug(`Start node using ${binPath}`);
return new Q((resolve, reject) => {
- if ('eth' === nodeType) {
- let modalWindow = Windows.createPopup('unlockMasterPassword', {
- electronOptions: {
- width: 400,
- height: 220,
- },
- useWeb3: false,
- });
-
- let called = false;
-
- modalWindow.on('closed', () => {
- if (!called) {
- app.quit();
- }
- });
-
- let popupCallback = function(err) {
- if (err && _.get(modalWindow,'webContents')) {
- log.error('unlockMasterPassword error', err);
-
- if(UNABLE_TO_SPAWN_ERROR === err) {
- modalWindow.close();
- modalWindow = null;
- } else {
- modalWindow.webContents.send('data', {
- masterPasswordWrong: true
- });
- }
- } else {
- called = true;
- modalWindow.close();
- modalWindow = null;
- ipc.removeAllListeners('backendAction_unlockedMasterPassword');
- }
- };
-
- ipc.on('backendAction_unlockedMasterPassword', (ev, err, pw) => {
- if (_.get(modalWindow, 'webContents') && ev.sender.getId() === modalWindow.webContents.getId()) {
- if (!err) {
- this.__startProcess(nodeType, network, binPath, pw, popupCallback)
- .then(resolve, reject);
- } else {
- app.quit();
- }
-
- return;
- }
- });
- } else {
- this.__startProcess(nodeType, network, binPath)
- .then(resolve, reject);
- }
-
+ this.__startProcess(nodeType, network, binPath)
+ .then(resolve, reject);
});
}
@@ -397,7 +345,7 @@ class EthereumNode extends EventEmitter {
/**
* @return {Promise}
*/
- __startProcess (nodeType, network, binPath, pw, popupCallback) {
+ __startProcess (nodeType, network, binPath) {
return new Q((resolve, reject) => {
log.trace('Rotate log file');
@@ -421,8 +369,7 @@ class EthereumNode extends EventEmitter {
else {
args = (nodeType === 'geth')
? ['--fast', '--cache', '512']
- : ['--unsafe-transactions', '--master', pw];
- pw = null;
+ : ['--unsafe-transactions'];
}
let nodeOptions = Settings.nodeOptions;
@@ -442,10 +389,6 @@ class EthereumNode extends EventEmitter {
if (STATES.STARTING === this.state) {
this.state = STATES.ERROR;
- if (popupCallback) {
- popupCallback(UNABLE_TO_SPAWN_ERROR);
- }
-
log.info('Node startup error');
// TODO: detect this properly
@@ -455,17 +398,6 @@ class EthereumNode extends EventEmitter {
}
});
- // node quit, e.g. master pw wrong
- proc.once('exit', () => {
- if ('eth' === nodeType) {
- log.warn('Password wrong!');
-
- if (popupCallback) {
- popupCallback(PASSWORD_WRONG_ERROR);
- }
- }
- });
-
// we need to read the buff to prevent node from not working
proc.stderr.pipe(
fs.createWriteStream(this._buildFilePath('node.log'), { flags: 'a' })
@@ -510,20 +442,17 @@ class EthereumNode extends EventEmitter {
// when data is first received
this.once('data', () => {
/*
- Assume startup succeeded after 5 seconds. At this point
- IPC connections are usually possible.
+ We wait a short while before marking startup as successful
+ because we may want to parse the initial node output for
+ errors, etc (see geth port-binding error above)
*/
setTimeout(() => {
if (STATES.STARTING === this.state) {
- log.info('4s elapsed, assuming node started up successfully');
-
- if (popupCallback) {
- popupCallback();
- }
+ log.info(`${NODE_START_WAIT_MS}ms elapsed, assuming node started up successfully`);
resolve(proc);
}
- }, 4000);
+ }, NODE_START_WAIT_MS);
})
});
});
@@ -571,8 +500,8 @@ class EthereumNode extends EventEmitter {
_loadDefaults () {
log.trace('Load defaults');
- this.defaultNodeType = this._loadUserData('node') || DEFAULT_NODE_TYPE;
- this.defaultNetwork = this._loadUserData('network') || DEFAULT_NETWORK;
+ this.defaultNodeType = Settings.nodeType || this._loadUserData('node') || DEFAULT_NODE_TYPE;
+ this.defaultNetwork = Settings.network || this._loadUserData('network') || DEFAULT_NETWORK;
}
diff --git a/modules/settings.js b/modules/settings.js
index 4b0072115..ee166be02 100644
--- a/modules/settings.js
+++ b/modules/settings.js
@@ -27,6 +27,24 @@ const argv = require('yargs')
type: 'string',
group: 'Mist options:',
},
+ node: {
+ demand: false,
+ default: null,
+ describe: 'Node to use: geth, eth',
+ requiresArg: true,
+ nargs: 1,
+ type: 'string',
+ group: 'Mist options:',
+ },
+ network: {
+ demand: false,
+ default: null,
+ describe: 'Network to connect to: main, test',
+ requiresArg: true,
+ nargs: 1,
+ type: 'string',
+ group: 'Mist options:',
+ },
ipcpath: {
demand: false,
describe: 'Path to node IPC socket file (this will automatically get passed as an option to Geth).',
@@ -162,6 +180,14 @@ class Settings {
return argv.ipcpath;
}
+ get nodeType () {
+ return argv.node;
+ }
+
+ get network () {
+ return argv.network;
+ }
+
get nodeOptions () {
return argv.nodeOptions;
}
diff --git a/modules/sockets.js b/modules/sockets.js
index 4d14010bd..895948adf 100644
--- a/modules/sockets.js
+++ b/modules/sockets.js
@@ -10,6 +10,9 @@ const dechunker = require('./ipc/dechunker.js');
+const CONNECT_INTERVAL_MS = 1000;
+const CONNECT_TIMEOUT_MS = 3000;
+
/**
* Socket connecting to Ethereum Node.
@@ -41,51 +44,66 @@ class Socket extends EventEmitter {
* Connect to host.
* @param {Object} connectConfig
* @param {Object} [options]
- * @param {Number} [options.timeout] Milliseconds to wait before timeout.
+ * @param {Number} [options.timeout] Milliseconds to wait before timeout (default is 5000).
* @return {Promise}
*/
connect (connectConfig, options) {
this._log.info(`Connect to ${JSON.stringify(connectConfig)}`);
- options = options || {};
+ options = _.extend({
+ timeout: CONNECT_TIMEOUT_MS,
+ }, options);
return this._resetSocket()
.then(() => {
+ let connectTimerId = null;
+ let timeoutTimerId = null;
+
this._log.debug('Connecting...');
+ this._log.debug(`Will wait ${options.timeout}ms for connection to happen.`);
+
this._state = STATE.CONNECTING;
return new Q((resolve, reject) => {
this._socket.once('connect', () => {
- this._log.info('Connected!');
+ if (STATE.CONNECTING === this._state) {
+ this._log.info('Connected!');
- this._state = STATE.CONNECTED;
+ this._state = STATE.CONNECTED;
- this.emit('connect');
+ clearTimeout(connectTimerId);
+ clearTimeout(timeoutTimerId);
- resolve();
+ this.emit('connect');
+
+ resolve();
+ }
});
- this._socket.once('error', (err) => {
+ this._socket.on('error', (err) => {
if (STATE.CONNECTING === this._state) {
- this._log.error('Connection error', err);
-
- this._state = STATE.ERROR;
+ this._log.warn(`Connection failed, retrying after ${CONNECT_INTERVAL_MS}ms...`);
- return reject(new Error(`Unable to connect to socket: ${err.message}`));
+ connectTimerId = setTimeout(() => {
+ this._socket.connect(connectConfig);
+ }, CONNECT_INTERVAL_MS);
}
});
- if (options.timeout) {
- this._log.debug(`Will wait ${options.timeout}ms for connection to happen.`);
+ timeoutTimerId = setTimeout(() => {
+ if (STATE.CONNECTING === this._state) {
+ this._log.error(`Connection failed (${options.timeout}ms elapsed)`);
- setTimeout(() => {
- if (STATE.CONNECTING === this._state) {
- this._socket.emit('error', `Connection timeout (took longer than ${options.timeout} ms)`);
- }
- }, options.timeout);
- }
+ this._state = STATE.CONNECTION_TIMEOUT;
+
+ clearTimeout(connectTimerId);
+
+ return reject(new Error(`Unable to connect to socket: timeout`));
+ }
+ }, options.timeout);
+ // initial kick-off
this._socket.connect(connectConfig);
});
});
@@ -388,6 +406,7 @@ const STATE = Socket.STATE = {
DISCONNECTED: 4,
ERROR: -1,
DISCONNECTION_TIMEOUT: -2,
+ CONNECTION_TIMEOUT: -3,
};
diff --git a/modules/windows.js b/modules/windows.js
index 3adf9fdb8..7caa82297 100644
--- a/modules/windows.js
+++ b/modules/windows.js
@@ -177,11 +177,12 @@ class Windows {
alwaysOnTop: true,
resizable: false,
width: 100,
- height: 50,
+ height: 80,
center: true,
frame: false,
useContentSize: true,
titleBarStyle: 'hidden', //hidden-inset: more space
+ skipTaskbar: true
},
});
diff --git a/package.json b/package.json
index 915a67fac..0c04fce9b 100644
--- a/package.json
+++ b/package.json
@@ -34,7 +34,7 @@
"electron-packager": "^7.0.4",
"gulp": "^3.9.0",
"gulp-decompress": "^2.0.0",
- "gulp-download": "0.0.1",
+ "gulp-download-stream": "0.0.13",
"gulp-rename": "^1.2.2",
"gulp-replace": "^0.5.4",
"gulp-tap": "^0.1.3",