diff --git a/README.md b/README.md index a1cd4d90..ca76fa45 100644 --- a/README.md +++ b/README.md @@ -47,28 +47,20 @@ If you wish to compile the app, install the following also: ``` cd wallet ``` - -3. Clone iri: - - ``` - git clone https://github.com/iotaledger/iri - ``` - - Note: make sure compiled iri.jar is in the `iri` folder. -4. Install components +3. Install components ``` npm install ``` -5. Run the app: +4. Run the app: ``` npm start ``` -6. If you wish to compile the app: +5. If you wish to compile the app: ``` npm run compile @@ -86,4 +78,4 @@ If you wish to compile the app, install the following also: #### Testnet -To build testnet binaries, rename `package.testnet.json` to `package.json` and follow instructions as above. Make sure the jar is named `iri-testnet.jar`. \ No newline at end of file +To build testnet binaries, rename `package.testnet.json` to `package.json` and follow instructions as above. diff --git a/app/js/main.js b/app/js/main.js index 65a968d0..40bfbf03 100644 --- a/app/js/main.js +++ b/app/js/main.js @@ -29,6 +29,9 @@ var __entityMap = { "/": '/' }; +var IRI_VERSION = '1.4.2.1' +var IRI_DIRECTORY = 'iri' + String.prototype.escapeHTML = function() { return String(this).replace(/[&<>"'\/]/g, function(s) { return __entityMap[s]; @@ -43,9 +46,9 @@ var App = (function(App, undefined) { var isStarted = false; var appDirectory = ""; var appDataDirectory = ""; + var tempDirectory = ""; var resourcesDirectory = ""; var databaseDirectory = ""; - var jarDirectory = ""; var javaLocations = []; var selectedJavaLocation; var currentLocationTest = 0; @@ -908,12 +911,12 @@ var App = (function(App, undefined) { appDataDirectory = path.join(electron.app.getPath("appData"), "IOTA Wallet" + (isTestNet ? " Testnet" : "")); } + tempDirectory = electron.app.getPath('temp') + App.loadSettings(); databaseDirectory = (settings.dbLocation ? settings.dbLocation : path.join(appDataDirectory, "iri")); - jarDirectory = path.join(resourcesDirectory, "iri"); - if (!fs.existsSync(appDataDirectory)) { fs.mkdirSync(appDataDirectory); } @@ -1010,11 +1013,11 @@ var App = (function(App, undefined) { App.start = function() { if (settings.lightWallet == 1 && (!settings.lightWalletHost || !settings.lightWalletPort)) { - App.showSetupWindow({"section": "light-node"}); + App.showSetupWindow({"section": "light-node", appDataDirectory, tempDirectory}); } else if (settings.lightWallet == 0 && settings.nodes.length == 0) { - App.showSetupWindow({"section": "full-node"}); + App.showSetupWindow({"section": "full-node", appDataDirectory, tempDirectory}); } else if (settings.lightWallet == -1) { - App.showSetupWindow(); + App.showSetupWindow({appDataDirectory, tempDirectory}); } else if (settings.lightWallet == 1) { global.lightWallet = true; App.startLightNode(); @@ -1228,7 +1231,7 @@ var App = (function(App, undefined) { params.push("-jar"); - params.push(path.join(jarDirectory, "iri" + (isTestNet ? "-testnet" : "") + ".jar")); + params.push(path.join(appDataDirectory, IRI_DIRECTORY, 'iri' + (isTestNet ? '-testnet' : '') + '-' + IRI_VERSION + '.jar')); // temporary ! // Only rescan once @@ -1802,7 +1805,10 @@ var App = (function(App, undefined) { "lightWalletPort" : settings.lightWalletPort, "port" : settings.port, "nodes" : settings.nodes, - "section" : params && params.section ? params.section : null}); + "section" : params && params.section ? params.section : null, + "appDataDirectory": params && params.appDataDirectory ? params.appDataDirectory : null, + "tempDirectory" : params && params.tempDirectory ? params.tempDirectory : null + }); } App.showInitializationAlertWindow = function(title, msg) { @@ -1851,14 +1857,19 @@ var App = (function(App, undefined) { "java64BitsOK" : java64BitsOK, "is64BitOS" : is64BitOS, "port" : settings.port, - "nodes" : settings.nodes}); + "nodes" : settings.nodes, + "appDataDirectory" : appDataDirectory, + "tempDirectory" : tempDirectory}); }); } else { App.showWindow("init_error.html", {"title" : title, "message" : msg, "serverOutput" : serverOutput, "port" : settings.port, - "nodes" : settings.nodes}); + "nodes" : settings.nodes, + "appDataDirectory" : appDataDirectory, + "tempDirectory" : tempDirectory + }); } selectedJavaLocation = ""; @@ -1971,7 +1982,9 @@ var App = (function(App, undefined) { //ready-to-show event not working.. otherWin.webContents.once("did-finish-load", function() { App.updateTitle(); - //win.webContents.toggleDevTools({"mode": "undocked"}); + if (isDebug) { + otherWin.webContents.openDevTools({"mode": "undocked"}); + } otherWin.webContents.send("show", params); }); diff --git a/app/windows/css/style.css b/app/windows/css/style.css index a232055c..cfc84bef 100644 --- a/app/windows/css/style.css +++ b/app/windows/css/style.css @@ -28,7 +28,7 @@ body { #footer { position: absolute; bottom: 0; - left: 0; + left: 0; right: 0; padding: 20px; background-color: #f1f1f1; @@ -162,4 +162,38 @@ p.note { .error { display: none; color: red; -} \ No newline at end of file +} + + +#download-iri-success { + display: none; +} + +#download-iri-progress { + display: none; + padding-bottom: 20px; +} + +#download-iri-progress-bar { + width: 100%; + height: 10px; + margin: 10px 0px; + background: #f0f0f0; + box-shadow: inset 3px 0px 10px rgba(0,0,0,0.14); + border-radius: 5px; + overflow: hidden; + position: relative; +} + +#download-iri-progress-bar-content { + transform: scaleX(0); + transform-origin: left; + width: 100%; + height: 10px; + border-radius: 10px; + box-shadow: 4px 1px 20px rgba(0,0,0,0.3); + background: linear-gradient(90deg, #4CAF50, #00E676); + position: absolute; + top: 0px; + left: 0px; +} diff --git a/app/windows/js/init_error.js b/app/windows/js/init_error.js index 6e286644..61ad8b7f 100644 --- a/app/windows/js/init_error.js +++ b/app/windows/js/init_error.js @@ -21,6 +21,8 @@ String.prototype.escapeHTML = function() { var UI = (function(UI, undefined) { var isLightWallet = false; + var _tempDirectory + var _appDataDirectory UI.initialize = function() { document.getElementById("quit-btn").addEventListener("click", function(e) { @@ -82,6 +84,8 @@ var UI = (function(UI, undefined) { UI.show = function(params) { if (params) { + _appDataDirectory = params.appDataDirectory + _tempDirectory = params.tempDirectory isLightWallet = params.lightWallet == 1; if (params.title) { document.getElementById("title").innerHTML = UI.format(params.title); @@ -130,7 +134,7 @@ var UI = (function(UI, undefined) { } UI.showSetupWindow = function(section) { - electron.ipcRenderer.send("showSetupWindow", {"section": section}); + electron.ipcRenderer.send("showSetupWindow", {"section": section, appDataDirectory: _appDataDirectory, tempDirectory: _tempDirectory}); } UI.updateContentSize = function() { @@ -203,4 +207,4 @@ electron.ipcRenderer.on("changeLanguage", function(event, language) { UI.changeLanguage(language, function() { UI.updateContentSize(); }); -}); \ No newline at end of file +}); diff --git a/app/windows/js/setup.js b/app/windows/js/setup.js index 5084d335..543dad12 100644 --- a/app/windows/js/setup.js +++ b/app/windows/js/setup.js @@ -1,6 +1,89 @@ -const electron = require("electron"); -const path = require("path"); -const https = require("https"); +const electron = require('electron') +const path = require('path') +const https = require('https') +const request = require('request') +const fs = require('fs') +const openpgp = require('openpgp') + +const IRI_VERSION = '1.4.2.1' +const IRI_DIRECTORY = 'iri' +const IRI_RELEASE_URI = `https://github.com/iotaledger/iri/releases/download/v${IRI_VERSION}/iri-${IRI_VERSION}.jar` +const IRI_RELEASE_PUB_KEY = `-----BEGIN PGP PUBLIC KEY BLOCK----- + +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 +=fX8W +-----END PGP PUBLIC KEY BLOCK-----` var isDevelopment = String(process.env.NODE_ENV).trim() === "development"; var resourcesDirectory = isDevelopment ? "../../" : "../../../"; @@ -23,6 +106,8 @@ String.prototype.escapeHTML = function() { var UI = (function(UI, undefined) { var _updateNodeConfiguration = false; var _lightWalletHosts = []; + var _appDataDirectory + var _tempDirectory UI.fetchProviders = function (urls) { return Promise.all(urls.map(url => { @@ -55,7 +140,6 @@ var UI = (function(UI, undefined) { hosts.push(host) } })) - console.log('PROVIDERS', hosts) if (!hosts.length) { return hosts } @@ -87,8 +171,14 @@ var UI = (function(UI, undefined) { }); document.getElementById("light-node-btn").addEventListener("click", UI.showLightNodeSection); - document.getElementById("full-node-btn").addEventListener("click", UI.showFullNodeSection); - document.getElementById("switch-btn").addEventListener("click", UI.showOtherNodeSection); + document.getElementById("full-node-btn").addEventListener("click", function() { + UI.showFullNodeSection({appDataDirectory: _appDataDirectory, tempDirectory: _tempDirectory}) + }); + document.getElementById("switch-btn").addEventListener("click", function () { + UI.showOtherNodeSection({appDataDirectory: _appDataDirectory, tempDirectory: _tempDirectory}) + }); + + document.getElementById('download-iri-btn').addEventListener('click', UI.downloadIRI) document.getElementById("quit-btn").addEventListener("click", function(e) { document.getElementById("quit-btn").disabled = true; @@ -190,13 +280,26 @@ var UI = (function(UI, undefined) { UI.updateContentSize(); } - UI.showFullNodeSection = function() { + UI.showFullNodeSection = function(params) { + _appDataDirectory = params.appDataDirectory + _tempDirectory = params.tempDirectory + let title = '' + if (fileExists(path.join(_appDataDirectory, IRI_DIRECTORY, `iri-${IRI_VERSION}.jar`))) { + renderFullNodeConfigurationSection() + title = 'full_node_settings' + document.getElementById("start-btn").style.display = "block" + } else { + renderDownloadIRISection() + title = 'download_iri_prompt' + document.getElementById('download-iri-btn').innerHTML = UI.t('download_iri') + '-' + IRI_VERSION + document.getElementById("start-btn").style.display = "none" + } + document.getElementById("node-choice").style.display = "none"; - UI.changeElementLanguage("title", "full_node_settings"); + UI.changeElementLanguage("title", title); document.getElementById("message").style.display = "none"; document.getElementById("light-node-section").style.display = "none"; document.getElementById("full-node-section").style.display = "block"; - document.getElementById("start-btn").style.display = "block"; document.getElementById("switch-btn").style.display = "block"; UI.changeElementLanguage("switch-btn", "switch_to_light_node"); document.getElementById("quit-btn").style.display = "none"; @@ -217,9 +320,9 @@ var UI = (function(UI, undefined) { UI.updateContentSize(); } - UI.showOtherNodeSection = function() { + UI.showOtherNodeSection = function(params) { if (document.getElementById("light-node-section").style.display == "block") { - UI.showFullNodeSection(); + UI.showFullNodeSection(params); UI.changeElementLanguage("switch-btn", "switch_to_light_node"); } else { UI.showLightNodeSection(); @@ -257,6 +360,8 @@ var UI = (function(UI, undefined) { document.getElementById("switch-btn").style.display = "none"; if (params) { + _appDataDirectory = params.appDataDirectory + _tempDirectory = params.tempDirectory if (params.lightWalletHost) { document.getElementById("host").value = params.lightWalletHost + (params.lightWalletPort ? ":" + params.lightWalletPort : ""); } @@ -270,7 +375,7 @@ var UI = (function(UI, undefined) { if (params.section == "light-node") { UI.showLightNodeSection(); } else if (params.section == "full-node") { - UI.showFullNodeSection(); + UI.showFullNodeSection(params); } } } @@ -292,6 +397,195 @@ var UI = (function(UI, undefined) { electron.remote.getCurrentWindow().setContentSize(600, parseInt(document.documentElement.scrollHeight, 10) + parseInt(document.getElementById("footer").scrollHeight, 10), false); } + UI.downloadIRI = function () { + const fileName = `iri-${IRI_VERSION}.jar` + const tempFileName = `iri-${IRI_VERSION}-unverified.jar` + const iriDirectory = path.join(_appDataDirectory, IRI_DIRECTORY) + const filePath = path.join(iriDirectory, fileName) + const tempFilePath = path.join(_tempDirectory, tempFileName) + + hideDownloadErrors() + disableButtons() + + downloadFile(IRI_RELEASE_URI, tempFilePath, { + onResponse: (size) => { + renderDownloadStatus() + renderDownloadProgress(0, size) + }, + onData: renderDownloadProgress + }) + + .then(() => { + downloadFile(`${IRI_RELEASE_URI}.asc`, `${tempFilePath}.asc`, { + onResponse: () => {}, + onData: () => {} + }) + .then(() => { + renderVerificationStatus() + return verifyFileSignature( + fs.readFileSync(tempFilePath), + fs.readFileSync(`${tempFilePath}.asc`, { encoding: 'utf8' }), + IRI_RELEASE_PUB_KEY + ) + }) + .then(valid => { + hideVerificationStatus() + if (!valid) { + return renderDownloadErrors(`Signature verification failed for downloaded file: ${tempFileName}`) + } + renameFile(tempFilePath, filePath) + .then(() => renameFile(`${tempFilePath}.asc`, `${filePath}.asc`)) + .then(() => renderDownloadSuccess()) + .catch(err => renderDownloadErrors(`Failed to save ${fileName}.`, err)) + }) + }) + + .catch(err => { + hideVerificationStatus() + renderDownloadErrors(`Failed to download ${fileName}`, err) + }) + } + + function downloadFile (uri, destination, hooks) { + return new Promise((resolve, reject) => { + let size = 0 + let bytesReceived = 0 + + let file = fs.createWriteStream(destination) + + request + .get(uri) + .on('response', data => { + size = parseInt(data.headers['content-length']) + hooks.onResponse(size) + }) + .on('data', chunk => { + bytesReceived += chunk.length + hooks.onData(bytesReceived, size) + }) + .on('error', err => reject(err)) + .on('end', () => resolve(file)) + .pipe(file) + }) + } + + function verifyFileSignature (file, signature, publicKey) { + const options = { + message: openpgp.message.fromBinary(file), + signature: openpgp.signature.readArmored(signature), + publicKeys: openpgp.key.readArmored(publicKey).keys + } + + return openpgp.verify(options) + .then(verified => verified.signatures[0].valid) + } + + function fileExists (path) { + return fs.existsSync(path) + } + + function renameFile (oldPath, newPath) { + return new Promise((resolve, reject) => + fs.rename(oldPath, newPath, err => { + if (err) reject(err) + else resolve() + }) + ) + } + + function renderDownloadIRISection () { + document.getElementById('full-node-download-iri-section').style.display = 'block' + document.getElementById('full-node-configuration-section').style.display = 'none' + document.getElementById('download-iri-verification-status').style.display = 'none' + document.getElementById('download-iri-verification-status').style.display = 'none' + UI.updateContentSize() + } + + function renderFullNodeConfigurationSection () { + document.getElementById('full-node-download-iri-section').style.display = 'none' + document.getElementById('full-node-configuration-section').style.display = 'block' + UI.updateContentSize() + } + + function disableButtons () { + document.getElementById('download-iri-prompt').style.display = 'none' + document.getElementById('download-iri-btn').disabled = true + document.getElementById('switch-btn').disabled = true + UI.updateContentSize() + } + + function enableButtons () { + document.getElementById('download-iri-prompt').style.display = 'block' + document.getElementById('download-iri-btn').style.display = 'block' + document.getElementById('download-iri-btn').disabled = false + document.getElementById('switch-btn').disabled = false + UI.updateContentSize() + } + + function renderDownloadStatus () { + document.getElementById('download-iri-progress').style.display = 'block' + document.getElementById('download-iri-btn').style.display = 'none' + document.getElementById('download-iri-verification-status').style.display = 'none' + document.getElementById('download-iri-success').style.display = 'none' + document.getElementById('download-iri-error').style.display = 'none' + UI.updateContentSize() + } + + function renderDownloadErrors (...errors) { + hideVerificationStatus() + const el = document.getElementById('download-iri-error') + el.style.display = 'block' + for (const err of Object.keys(errors)) { + const errEl = document.createElement('div') + errEl.innerHTML = UI.format(errors[err]) + el.append(errEl) + } + enableButtons() + } + + function hideDownloadErrors () { + const el = document.getElementById('download-iri-error') + el.style.display = 'none' + while (el.hasChildNodes()) { + el.removeChild(el.lastChild) + } + UI.updateContentSize() + } + + function renderDownloadProgress (received, size) { + document.getElementById('download-iri-progress').style.display = 'block' + const dx = (received * 100) / size + document.getElementById('download-iri-progress-percentage').innerHTML = UI.format(`${parseFloat(dx).toFixed(2)} %`) + document.getElementById('download-iri-progress-bar-content').style.transform = `scaleX(${(dx / 100).toString()})` + } + + function renderVerificationStatus () { + document.getElementById('download-iri-progress').style.display = 'none' + document.getElementById('download-iri-verification-status').style.display = 'block' + UI.updateContentSize() + } + + function hideVerificationStatus () { + document.getElementById('download-iri-verification-status').style.display = 'none' + UI.updateContentSize() + } + + function renderDownloadSuccess () { + document.getElementById('download-iri-success').style.display = 'block' + document.getElementById('download-iri-btn').style.display = 'none' + document.getElementById('download-iri-verification-status').style.display = 'none' + document.getElementById('switch-btn').disabled = false + UI.updateContentSize() + return new Promise((resolve, reject) => + setTimeout(() => { + UI.changeElementLanguage("title", 'full_node_settings'); + document.getElementById('start-btn').style.display = 'block' + renderFullNodeConfigurationSection() + resolve() + }, 2000) + ) + } + UI.makeMultilingual = function(currentLanguage, callback) { i18n = i18next .use(window.i18nextXHRBackend) diff --git a/app/windows/setup.html b/app/windows/setup.html index 560ea092..eb1f39b3 100644 --- a/app/windows/setup.html +++ b/app/windows/setup.html @@ -16,7 +16,7 @@
:
- -:
- -: udp://ip:12345
+:
+ +:
+ +: udp://ip:12345
+