diff --git a/packages/fether-electron/src/main/cli/index.js b/packages/fether-electron/src/main/cli/index.js index bfc1e5b47ef7c3adb67dbf349e26cf044a7074ab..ff27b4f015e04e4f0f940e9776aadf775aa5065d 100644 --- a/packages/fether-electron/src/main/cli/index.js +++ b/packages/fether-electron/src/main/cli/index.js @@ -3,7 +3,7 @@ // // SPDX-License-Identifier: BSD-3-Clause -const cli = require('commander'); +import cli from 'commander'; const { productName } = require('../../../electron-builder.json'); const { version } = require('../../../package.json'); @@ -54,7 +54,7 @@ const camelcase = flag => // Now we must think which arguments passed to cli must be passed down to // parity. -const parityArgv = cli.rawArgs +export const parityArgv = cli.rawArgs .splice(2) // Remove first 2 arguments which are program path .filter((item, index, array) => { const key = camelcase(item.replace('--', '').replace('no-', '')); // Remove '--' and then camelCase @@ -87,4 +87,4 @@ const parityArgv = cli.rawArgs return true; }); -module.exports = { cli, parityArgv }; +export { cli }; diff --git a/packages/fether-electron/src/main/index.js b/packages/fether-electron/src/main/index.js index 5641dc61a994162b89bb8bf1a5ec50deac0cc8eb..56582ec9bda6ce281b7c557385b4687947d70b4f 100644 --- a/packages/fether-electron/src/main/index.js +++ b/packages/fether-electron/src/main/index.js @@ -5,22 +5,23 @@ /* global __static */ -const electron = require('electron'); -const path = require('path'); -const url = require('url'); - -const addMenu = require('./menu'); -const { cli } = require('./cli'); -const { doesParityExist } = require('./operations/doesParityExist'); -const fetchParity = require('./operations/fetchParity'); -const handleError = require('./operations/handleError'); -const messages = require('./messages'); -const { productName } = require('../../electron-builder.json'); -const pino = require('./utils/pino')({ name: 'electron' }); -const { runParity, killParity } = require('./operations/runParity'); +import electron from 'electron'; +import path from 'path'; +import url from 'url'; + +import addMenu from './menu'; +import { cli } from './cli'; +import { doesParityExist } from './operations/doesParityExist'; +import fetchParity from './operations/fetchParity'; +import handleError from './operations/handleError'; +import messages from './messages'; +import { productName } from '../../electron-builder.json'; +import Pino from './utils/pino'; +import { runParity, killParity } from './operations/runParity'; const { app, BrowserWindow, ipcMain, session } = electron; let mainWindow; +const pino = Pino(); function createWindow () { pino.info(`Starting ${productName}...`); diff --git a/packages/fether-electron/src/main/menu/index.js b/packages/fether-electron/src/main/menu/index.js index 0df70ab665907b4f0708ef7ba1a11c8bdaf4da12..b41c6006f5eaa7547183daf246b3400d9fc8e01c 100644 --- a/packages/fether-electron/src/main/menu/index.js +++ b/packages/fether-electron/src/main/menu/index.js @@ -3,11 +3,11 @@ // // SPDX-License-Identifier: BSD-3-Clause -const electron = require('electron'); +import electron from 'electron'; const { app, Menu, shell } = electron; -module.exports = mainWindow => { +export default mainWindow => { // Create the Application's main menu // https://github.com/electron/electron/blob/master/docs/api/menu.md#examples const template = [ diff --git a/packages/fether-electron/src/main/messages/index.js b/packages/fether-electron/src/main/messages/index.js index 6cc50ff2d3f07ad11fa632161bf7d1dd6a52c70c..a402859401e566247a6a657e54385628fe57e94a 100644 --- a/packages/fether-electron/src/main/messages/index.js +++ b/packages/fether-electron/src/main/messages/index.js @@ -3,12 +3,12 @@ // // SPDX-License-Identifier: BSD-3-Clause -const signerNewToken = require('../operations/signerNewToken'); +import signerNewToken from '../operations/signerNewToken'; /** * Handle all asynchronous messages from renderer to main. */ -module.exports = (event, arg) => { +export default (event, arg) => { switch (arg) { case 'signer-new-token': { signerNewToken(event); diff --git a/packages/fether-electron/src/main/operations/doesParityExist.js b/packages/fether-electron/src/main/operations/doesParityExist.js index f9c0ce4cf5a357157c3a1d74d5597d4b377e178f..1beab61b884e23c827e836aeedb131dd4a2ec4a4 100644 --- a/packages/fether-electron/src/main/operations/doesParityExist.js +++ b/packages/fether-electron/src/main/operations/doesParityExist.js @@ -3,21 +3,22 @@ // // SPDX-License-Identifier: BSD-3-Clause -const { app } = require('electron'); -const commandExists = require('command-exists'); -const fs = require('fs'); -const promiseAny = require('promise-any'); -const { promisify } = require('util'); +import { app } from 'electron'; +import commandExists from 'command-exists'; +import fs from 'fs'; +import promiseAny from 'promise-any'; +import { promisify } from 'util'; -const pino = require('../utils/pino')(); +import Pino from '../utils/pino'; const fsExists = promisify(fs.stat); +const pino = Pino(); // The default path to install parity, in case there's no other instance found // on the machine. -const defaultParityPath = `${app.getPath( - 'userData' -)}/parity${process.platform === 'win32' ? '.exe' : ''}`; +export const defaultParityPath = `${app.getPath('userData')}/parity${ + process.platform === 'win32' ? '.exe' : '' +}`; let parityPath; // The real parity path, will be populated after doesParityExist Promise resolves @@ -28,43 +29,41 @@ const locations = { win32: ['C:\\Program Files\\Parity Technologies\\Parity\\parity.exe'] }; -module.exports = { - defaultParityPath, - /** - * This function checks if parity has been installed on the local machine: - * - first check if the program is in $PATH, using `command-exists` - * - then check the OS default installation dir if a parity folder exists - * - finally check parity-ui's own userData folder - * This function should run in node env. - * - * @return Promise - Resolves to a string which is the command to run parity. - */ - doesParityExist () { - return commandExists('parity') // First test if `parity` command exists - .then(() => 'parity') // If yes, return `parity` as command to launch parity - .catch(() => - // Then test if OS-specific locations contain parity - promiseAny( - locations[process.platform].map(location => - fsExists(location).then(() => location) - ) +/** + * This function checks if parity has been installed on the local machine: + * - first check if the program is in $PATH, using `command-exists` + * - then check the OS default installation dir if a parity folder exists + * - finally check parity-ui's own userData folder + * This function should run in node env. + * + * @return Promise - Resolves to a string which is the command to run parity. + */ +export const doesParityExist = () => { + return commandExists('parity') // First test if `parity` command exists + .then(() => 'parity') // If yes, return `parity` as command to launch parity + .catch(() => + // Then test if OS-specific locations contain parity + promiseAny( + locations[process.platform].map(location => + fsExists(location).then(() => location) ) ) - .catch(() => - // Finally test userData folder - fsExists(defaultParityPath).then(() => defaultParityPath) - ) - .then(path => { - parityPath = path; // Save the final result in module variable - pino.info(`Parity found on machine, can be run with "${path}".`); - return path; - }) - .catch(err => { - pino.info(`Parity not found on machine.`); - throw err; - }); - }, - parityPath () { - return parityPath; - } + ) + .catch(() => + // Finally test userData folder + fsExists(defaultParityPath).then(() => defaultParityPath) + ) + .then(path => { + parityPath = path; // Save the final result in module variable + pino.info(`Parity found on machine, can be run with "${path}".`); + return path; + }) + .catch(err => { + pino.info(`Parity not found on machine.`); + throw err; + }); +}; + +export const getParityPath = () => { + return parityPath; }; diff --git a/packages/fether-electron/src/main/operations/fetchParity.js b/packages/fether-electron/src/main/operations/fetchParity.js index 4f8f45aeccbbd83be6c00f64e038a3e6d56546cf..fae9d7141bd5b6881c5fc72ae1f9e7f77cba873b 100644 --- a/packages/fether-electron/src/main/operations/fetchParity.js +++ b/packages/fether-electron/src/main/operations/fetchParity.js @@ -3,23 +3,22 @@ // // SPDX-License-Identifier: BSD-3-Clause -const { app } = require('electron'); -const axios = require('axios'); -const cs = require('checksum'); -const { download } = require('electron-dl'); -const fs = require('fs'); -const { promisify } = require('util'); -const retry = require('async-retry'); +import { app } from 'electron'; +import axios from 'axios'; +import cs from 'checksum'; +import { download } from 'electron-dl'; +import fs from 'fs'; +import { promisify } from 'util'; +import retry from 'async-retry'; -const { defaultParityPath, doesParityExist } = require('./doesParityExist'); -const handleError = require('./handleError'); -const { - parity: { channel } -} = require('../../../package.json'); -const pino = require('../utils/pino')(); +import { defaultParityPath, doesParityExist } from './doesParityExist'; +import handleError from './handleError'; +import { parity } from '../../../package.json'; +import Pino from '../utils/pino'; const checksum = promisify(cs.file); const fsChmod = promisify(fs.chmod); +const pino = Pino(); const VANITY_URL = 'https://vanity-service.parity.io/parity-binaries'; @@ -64,7 +63,7 @@ const deleteParity = () => { }; // Fetch parity from https://vanity-service.parity.io/parity-binaries -module.exports = mainWindow => { +export default mainWindow => { try { return retry( async (_, attempt) => { @@ -74,10 +73,14 @@ module.exports = mainWindow => { // Fetch the metadata of the correct version of parity pino.info( - `Downloading from ${VANITY_URL}?version=${channel}&os=${getOs()}&architecture=${getArch()}.` + `Downloading from ${VANITY_URL}?version=${ + parity.channel + }&os=${getOs()}&architecture=${getArch()}.` ); const { data } = await axios.get( - `${VANITY_URL}?version=${channel}&os=${getOs()}&architecture=${getArch()}` + `${VANITY_URL}?version=${ + parity.channel + }&os=${getOs()}&architecture=${getArch()}` ); // Get the binary's url diff --git a/packages/fether-electron/src/main/operations/handleError.js b/packages/fether-electron/src/main/operations/handleError.js index 4c151c338e588be349e8fbe685b08d4138f56e36..2c46aa48992104ec5327cff7c9b54eb0a1a6629d 100644 --- a/packages/fether-electron/src/main/operations/handleError.js +++ b/packages/fether-electron/src/main/operations/handleError.js @@ -3,15 +3,14 @@ // // SPDX-License-Identifier: BSD-3-Clause -const { app, dialog } = require('electron'); +import { app, dialog } from 'electron'; -const { - bugs: { url }, - parity: { channel } -} = require('../../../package.json'); -const pino = require('../utils/pino')(); +import { bugs, parity } from '../../../package.json'; +import Pino from '../utils/pino'; -module.exports = (err, message = 'An error occurred.') => { +const pino = Pino(); + +export default (err, message = 'An error occurred.') => { pino.error(err); dialog.showMessageBox( { @@ -19,12 +18,12 @@ module.exports = (err, message = 'An error occurred.') => { detail: `Please attach the following debugging info: OS: ${process.platform} Arch: ${process.arch} -Channel: ${channel} +Channel: ${parity.channel} Error: ${err.message} Please also attach the contents of the following file: ${app.getPath('userData')}/parity.log`, - message: `${message} Please file an issue at ${url}.`, + message: `${message} Please file an issue at ${bugs.url}.`, title: 'Parity Error', type: 'error' }, diff --git a/packages/fether-electron/src/main/operations/isParityRunning.js b/packages/fether-electron/src/main/operations/isParityRunning.js index 92efbba34459b8192181cfa7e5f8a9f214621494..c17cf2e0144abcb16d63718f17e365890ddf9067 100644 --- a/packages/fether-electron/src/main/operations/isParityRunning.js +++ b/packages/fether-electron/src/main/operations/isParityRunning.js @@ -3,11 +3,13 @@ // // SPDX-License-Identifier: BSD-3-Clause -const axios = require('axios'); -const retry = require('async-retry'); +import axios from 'axios'; +import retry from 'async-retry'; -const { cli } = require('../cli'); -const pino = require('../utils/pino')(); +import { cli } from '../cli'; +import Pino from '../utils/pino'; + +const pino = Pino(); // Try to ping these hosts const hostsToPing = ['http://127.0.0.1:8545', 'http://127.0.0.1:8546']; @@ -48,4 +50,4 @@ const isParityRunning = async mainWindow => { } }; -module.exports = isParityRunning; +export default isParityRunning; diff --git a/packages/fether-electron/src/main/operations/runParity.js b/packages/fether-electron/src/main/operations/runParity.js index d82b3606aec682f3d333332a8f5b78c9dd69ec5c..d41745303281248c90b8bf790f944a91c7a644c9 100644 --- a/packages/fether-electron/src/main/operations/runParity.js +++ b/packages/fether-electron/src/main/operations/runParity.js @@ -3,19 +3,20 @@ // // SPDX-License-Identifier: BSD-3-Clause -const { app } = require('electron'); -const fs = require('fs'); -const { spawn } = require('child_process'); -const { promisify } = require('util'); - -const { cli, parityArgv } = require('../cli'); -const isParityRunning = require('./isParityRunning'); -const handleError = require('./handleError'); -const { parityPath } = require('./doesParityExist'); -const pino = require('../utils/pino')(); -const pinoParity = require('../utils/pino')({ name: 'parity' }); +import { app } from 'electron'; +import fs from 'fs'; +import { spawn } from 'child_process'; +import { promisify } from 'util'; + +import { cli, parityArgv } from '../cli'; +import isParityRunning from './isParityRunning'; +import handleError from './handleError'; +import { getParityPath } from './doesParityExist'; +import Pino from '../utils/pino'; const fsChmod = promisify(fs.chmod); +const pino = Pino(); +const pinoParity = Pino({ name: 'parity' }); let parity = null; // Will hold the running parity instance @@ -27,100 +28,100 @@ const catchableErrors = [ 'IO error: While lock file:' ]; -module.exports = { - async runParity (mainWindow) { +export const runParity = async mainWindow => { + try { + // Do not run parity with --no-run-parity + if (cli.runParity === false) { + return; + } + + // Do not run parity if there is already another instance running + const isRunning = await isParityRunning(mainWindow); + if (isRunning) { + return; + } + + // Do not run parity if parityPath has not been calculated. Shouldn't + // happen as we always run runParity after doesParityExist resolves. + if (!getParityPath()) { + throw new Error('Attempting to run Parity before parityPath is set.'); + } + + // Some users somehow had no +x on the parity binary after downloading + // it. We try to set it here (no guarantee it will work, we might not + // have rights to do it). try { - // Do not run parity with --no-run-parity - if (cli.runParity === false) { + await fsChmod(getParityPath(), '755'); + } catch (e) {} + + let logLastLine; // Always contains last line of the Parity logs + + // Run an instance of parity with the correct args + parity = spawn(getParityPath(), parityArgv); + pino.info( + `Running command "${getParityPath().replace( + ' ', + '\\ ' + )} ${parityArgv.join(' ')}".` + ); + + // Save in memory the last line of the log file, for handling error + const callback = data => { + if (data && data.length) { + logLastLine = data.toString(); + } + pinoParity.info(data.toString()); + }; + parity.stdout.on('data', callback); + parity.stderr.on('data', callback); + + parity.on('error', err => { + handleError(err, 'An error occured while running parity.'); + }); + parity.on('close', (exitCode, signal) => { + if (exitCode === 0) { return; } - // Do not run parity if there is already another instance running - const isRunning = await isParityRunning(mainWindow); - if (isRunning) { + // When there's already an instance of parity running, then the log + // is logging a particular line, see below. In this case, we just + // silently ignore our local instance, and let the 1st parity + // instance be the main one. + if ( + logLastLine && + catchableErrors.some(error => logLastLine.includes(error)) + ) { + pino.warn( + 'Another instance of parity is running, closing local instance.' + ); return; } - // Do not run parity if parityPath has not been calculated. Shouldn't - // happen as we always run runParity after doesParityExist resolves. - if (!parityPath) { - throw new Error('Attempting to run Parity before parityPath is set.'); + // If the exit code is not 0, then we show some error message + if (Object.keys(parityArgv).length > 0) { + app.exit(1); + } else { + handleError( + new Error(`Exit code ${exitCode}, with signal ${signal}.`), + 'An error occured while running parity.' + ); } + }); - // Some users somehow had no +x on the parity binary after downloading - // it. We try to set it here (no guarantee it will work, we might not - // have rights to do it). - try { - await fsChmod(parityPath(), '755'); - } catch (e) {} - - let logLastLine; // Always contains last line of the Parity logs - - // Run an instance of parity with the correct args - parity = spawn(parityPath(), parityArgv); - pino.info( - `Running command "${parityPath().replace(' ', '\\ ')} ${parityArgv.join( - ' ' - )}".` - ); - - // Save in memory the last line of the log file, for handling error - const callback = data => { - if (data && data.length) { - logLastLine = data.toString(); - } - pinoParity.info(data.toString()); - }; - parity.stdout.on('data', callback); - parity.stderr.on('data', callback); - - parity.on('error', err => { - handleError(err, 'An error occured while running parity.'); - }); - parity.on('close', (exitCode, signal) => { - if (exitCode === 0) { - return; - } - - // When there's already an instance of parity running, then the log - // is logging a particular line, see below. In this case, we just - // silently ignore our local instance, and let the 1st parity - // instance be the main one. - if ( - logLastLine && - catchableErrors.some(error => logLastLine.includes(error)) - ) { - pino.warn( - 'Another instance of parity is running, closing local instance.' - ); - return; - } - - // If the exit code is not 0, then we show some error message - if (Object.keys(parityArgv).length > 0) { - app.exit(1); - } else { - handleError( - new Error(`Exit code ${exitCode}, with signal ${signal}.`), - 'An error occured while running parity.' - ); - } - }); - - // Notify the renderers - mainWindow.webContents.send('parity-running', true); - global.isParityRunning = true; // Send this variable to renderes via IPC - - return Promise.resolve(); - } catch (err) { - handleError(err, 'An error occured while running parity.'); - } - }, - killParity () { - if (parity) { - pino.info('Stopping parity.'); - parity.kill(); - parity = null; - } + // Notify the renderers + mainWindow.webContents.send('parity-running', true); + global.isParityRunning = true; // Send this variable to renderes via IPC + + return Promise.resolve(); + } catch (err) { + handleError(err, 'An error occured while running parity.'); + } +}; + +export const killParity = () => { + if (parity) { + pino.info('Stopping parity.'); + parity.kill(); + parity = null; } }; diff --git a/packages/fether-electron/src/main/operations/signerNewToken.js b/packages/fether-electron/src/main/operations/signerNewToken.js index f0e5e4f784cf4082ed4bd095fe63a94e76460a39..612ecf3e1627bc6a663f4b6447e6ee1359fa9339 100644 --- a/packages/fether-electron/src/main/operations/signerNewToken.js +++ b/packages/fether-electron/src/main/operations/signerNewToken.js @@ -3,14 +3,16 @@ // // SPDX-License-Identifier: BSD-3-Clause -const pino = require('../utils/pino')(); -const { spawn } = require('child_process'); +import { spawn } from 'child_process'; -const { parityPath } = require('./doesParityExist'); +import { getParityPath } from './doesParityExist'; +import Pino from '../utils/pino'; -module.exports = event => { +const pino = Pino(); + +export default event => { // Generate a new token - const paritySigner = spawn(parityPath(), ['signer', 'new-token']); + const paritySigner = spawn(getParityPath(), ['signer', 'new-token']); pino.info('Requesting new token.'); diff --git a/packages/fether-electron/src/main/utils/pino.js b/packages/fether-electron/src/main/utils/pino.js index 1dea1f71cb1e5a801171615901109f23a4fde301..6b7e3ba99acc5c314cadcf5d2f3109aa445db6ed 100644 --- a/packages/fether-electron/src/main/utils/pino.js +++ b/packages/fether-electron/src/main/utils/pino.js @@ -3,10 +3,10 @@ // // SPDX-License-Identifier: BSD-3-Clause -const { app } = require('electron'); -const fs = require('fs'); -const { multistream } = require('pino-multi-stream'); -const pino = require('pino'); +import { app } from 'electron'; +import fs from 'fs'; +import { multistream } from 'pino-multi-stream'; +import pino from 'pino'; // Pino by default outputs JSON. We prettify that. const pretty = pino.pretty(); @@ -24,9 +24,13 @@ const streams = [ ]; /** - * Usage: const pino = require('../path/to/pino')({ name: 'something' }); + * Create a pino instance * * @param {Object} opts - Options to pass to pino. Defaults to { name: 'electron' }. + * @example + * import Pino from './utils/pino'; + * const pino1 = Pino(); + * const pino2 = Pino({ name: 'parity' }); */ -module.exports = opts => +export default opts => pino({ name: 'electron', ...opts }, multistream(streams)); diff --git a/packages/fether-react/src/Send/TxForm/TxForm.js b/packages/fether-react/src/Send/TxForm/TxForm.js index 9ba396a8efeb596d7f8ca7f50a818de0dd6548ea..b20c3e5b9837128196b5e2a78821e6d4df2e7fc5 100644 --- a/packages/fether-react/src/Send/TxForm/TxForm.js +++ b/packages/fether-react/src/Send/TxForm/TxForm.js @@ -147,6 +147,7 @@ class Send extends Component { max={maxAmount} min={0} onChange={this.handleChangeAmount} + placeholder='1.00' required step={+fromWei(1)} type='number'