From 87091f7d6e5ba23e66c48c028d30dbf38d49a74f Mon Sep 17 00:00:00 2001 From: Chris Dukakis Date: Sat, 13 Jan 2018 16:22:16 +0200 Subject: [PATCH 1/6] employ wereAddressesSpentFrom() for preventing key reuse --- ui/js/ui.recover.js | 58 ++++---------------------------------- ui/js/ui.transfers.js | 65 ++++++++----------------------------------- 2 files changed, 18 insertions(+), 105 deletions(-) diff --git a/ui/js/ui.recover.js b/ui/js/ui.recover.js index d93bafc1..a5380e6e 100644 --- a/ui/js/ui.recover.js +++ b/ui/js/ui.recover.js @@ -185,9 +185,13 @@ WHGl/N/YlZ/p38kb7ZXtuRca7VUPxRzqv3FrUBg recoveryNextBtn.loadingReset('recovery_next') return } - filterSpentAddresses([{address: newAddress}]) + const newAddressesToCheck = [newAddress] + for (let i = 1; i < 50; i++) { + newAddressesToCheck.push(iota.api._newAddress(newSeed, i, 2, false)) + } + filterSpentAddresses(newAddressesToCheck) .then(unspentAddresses => { - if (unspentAddresses.length === 0) { + if (unspentAddresses.length !== newAddressesToCheck.length) { UI.formError('recover', 'sent_to_key_reuse_error', {initial: 'recovery_next'}) $('.remodal-close').off('click') recoveryNextBtn.loadingReset('recovery_next') @@ -650,55 +654,5 @@ WHGl/N/YlZ/p38kb7ZXtuRca7VUPxRzqv3FrUBg return trits } - function filterSpentAddresses (inputs) { - return new Promise((resolve, reject) => { - iota.api.findTransactionObjects({addresses: inputs.map(input => iota.utils.noChecksum(input.address))}, (err, txs) => { - if (err) { - reject(err) - } - txs = txs.filter(tx => tx.value < 0) - if (txs.length > 0) { - var bundles = txs.map(tx => tx.bundle) - iota.api.findTransactionObjects({bundles: bundles}, (err, txs) => { - if (err) { - reject(err) - } - var hashes = txs.filter(tx => tx.currentIndex === 0) - hashes = hashes.map(tx => tx.hash) - iota.api.getLatestInclusion(hashes, (err, states) => { - if (err) { - reject(err) - } - var confirmedHashes = hashes.filter((hash, i) => states[i]) - var unconfirmedHashes = hashes.filter(hash => confirmedHashes.indexOf(hash) === -1).map(hash => { - return { hash: hash, validate: true } - }) - var getBundles = confirmedHashes.concat(unconfirmedHashes).map(hash => new Promise((resolve, reject) => { - iota.api.traverseBundle(typeof hash === 'string' ? hash : hash.hash, null, [], (err, bundle) => { - if (err) { - reject(err) - } - resolve(typeof hash === 'string' ? bundle : {bundle: bundle, validate: true}) - }) - })) - resolve(Promise.all(getBundles).then(bundles => { - bundles = bundles.filter(bundle => { - if (bundle.validate) { - return iota.utils.isBundle(bundle.bundle) - } - return true - }).map(bundle => bundle.hasOwnProperty('validate') ? bundle.bundle : bundle) - var blacklist = bundles.reduce((a, b) => a.concat(b), []).filter(tx => tx.value < 0).map(tx => tx.address) - return inputs.filter(input => blacklist.indexOf(input.address) === -1) - }).catch(err => reject(err))) - }) - }) - } else { - resolve(inputs) - } - }) - }) - } - return UI }(UI || {}, jQuery)) diff --git a/ui/js/ui.transfers.js b/ui/js/ui.transfers.js index cfcfd351..bded3d3e 100644 --- a/ui/js/ui.transfers.js +++ b/ui/js/ui.transfers.js @@ -82,7 +82,7 @@ var UI = (function(UI, $, undefined) { } var transfers = [{"address": address, "value": amount, "message": "", "tag": tag}]; - var outputsToCheck = transfers.map(transfer => { return {address: iota.utils.noChecksum(transfer.address)}}); + var outputsToCheck = transfers.map(transfer => iota.utils.noChecksum(transfer.address)); var exptectedOutputsLength = outputsToCheck.length; filterSpentAddresses(outputsToCheck).then(filtered => { if (filtered.length !== exptectedOutputsLength) { @@ -123,8 +123,11 @@ var UI = (function(UI, $, undefined) { $stack.removeClass("loading"); }); }); + }).catch(err => { + UI.formError('transfer', err, {initial: 'send_it_now'}) + $stack.removeClass("loading") }); - }); + }) }); $("#key-reuse-close-btn").on("click", function(e) { @@ -213,59 +216,16 @@ var UI = (function(UI, $, undefined) { }(UI || {}, jQuery)); -function filterSpentAddresses(inputs) { +function filterSpentAddresses (addresses) { return new Promise((resolve, reject) => { - iota.api.findTransactionObjects({addresses: inputs.map(input => input.address)}, (err, txs) => { - if (err) { - reject(err) - } - txs = txs.filter(tx => tx.value < 0) - if (txs.length > 0) { - var bundles = txs.map(tx => tx.bundle) - iota.api.findTransactionObjects({bundles: bundles}, (err, txs) => { - if (err) { - reject(err) - } - var hashes = txs.filter(tx => tx.currentIndex === 0) - var allBundleHashes = txs.map(tx => tx.bundle) - hashes = hashes.map(tx => tx.hash) - iota.api.getLatestInclusion(hashes, (err, states) => { - if (err) { - reject(err) - } - var confirmedHashes = hashes.filter((hash, i) => states[i]) - var unconfirmedHashes = hashes.filter(hash => confirmedHashes.indexOf(hash) === -1).map(hash => { - return { hash: hash, validate: true } - }) - var getBundles = confirmedHashes.concat(unconfirmedHashes).map(hash => new Promise((resolve, reject) => { - iota.api.traverseBundle(typeof hash == 'string' ? hash : hash.hash, null, [], (err, bundle) => { - if (err) { - reject(err) - } - resolve(typeof hash === 'string' ? bundle : {bundle: bundle, validate: true}) - }) - })) - resolve(Promise.all(getBundles).then(bundles => { - bundles = bundles.filter(bundle => { - if (bundle.validate) { - return iota.utils.isBundle(bundle.bundle) - } - return true - }).map(bundle => bundle.hasOwnProperty('validate') ? bundle.bundle : bundle) - var blacklist = bundles.reduce((a, b) => a.concat(b), []).filter(tx => tx.value < 0).map(tx => tx.address) - return inputs.filter(input => blacklist.indexOf(input.address) === -1) - }).catch(err => reject(err))) - }) - }) - } - else { - resolve(inputs); - } - }) + iota.api.wereAddressesSpentFrom( + iota.valid.isArrayOfHashes(addresses) ? addresses : addresses.map(address => address.address), + (err, wereSpent) => err ? reject(err) : resolve(addresses.filter((address, i) => !wereSpent[i])) + ) }) } -function getUnspentInputs(seed, start, threshold, inputs, cb) { +function getUnspentInputs (seed, start, threshold, inputs, cb) { if (arguments.length === 4) { cb = arguments[3] inputs = {inputs: [], totalBalance: 0, allBalance: 0} @@ -283,8 +243,7 @@ function getUnspentInputs(seed, start, threshold, inputs, cb) { var ordered = res.inputs.sort((a, b) => a.keyIndex - b.keyIndex).reverse() var end = ordered[0].keyIndex getUnspentInputs(seed, end + 1, diff, {inputs: inputs.inputs.concat(filtered), totalBalance: inputs.totalBalance + collected, allBalance: inputs.allBalance}, cb) - } - else { + } else { cb(null, {inputs: inputs.inputs.concat(filtered), totalBalance: inputs.totalBalance + collected, allBalance: inputs.allBalance}) } }).catch(err => cb(err, inputs)) From bcd42e3ce7ec38e79beb8e38cde99235c5f8d08d Mon Sep 17 00:00:00 2001 From: Chris Dukakis Date: Sun, 28 Jan 2018 21:55:15 +0200 Subject: [PATCH 2/6] download iri.jar on demand --- app/js/main.js | 35 +++- app/windows/css/style.css | 38 +++- app/windows/js/init_error.js | 8 +- app/windows/js/setup.js | 386 +++++++++++++++++++++++++++++++++-- app/windows/setup.html | 34 ++- locales/en/translation.json | 8 +- package-lock.json | 194 +++++++++--------- package.json | 5 +- 8 files changed, 580 insertions(+), 128 deletions(-) diff --git a/app/js/main.js b/app/js/main.js index 65a968d0..ed3eaed1 100644 --- a/app/js/main.js +++ b/app/js/main.js @@ -29,6 +29,9 @@ var __entityMap = { "/": '/' }; +var IRI_VERSION = '1.4.1.7' +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..76522fc9 100644 --- a/app/windows/js/setup.js +++ b/app/windows/js/setup.js @@ -1,6 +1,158 @@ -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.1.7' +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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 +jmYGC3AGYL1vyg== +=Om04 +-----END PGP PUBLIC KEY BLOCK-----` var isDevelopment = String(process.env.NODE_ENV).trim() === "development"; var resourcesDirectory = isDevelopment ? "../../" : "../../../"; @@ -23,6 +175,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 +209,6 @@ var UI = (function(UI, undefined) { hosts.push(host) } })) - console.log('PROVIDERS', hosts) if (!hosts.length) { return hosts } @@ -87,8 +240,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 +349,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 +389,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 +429,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 +444,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 +466,194 @@ 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('start-btn').style.display = 'block' + document.getElementById('switch-btn').disabled = 'false' + UI.updateContentSize() + return new Promise((resolve, reject) => + setTimeout(() => { + 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 @@

-

+

@@ -26,11 +26,31 @@

-

:

- -

:

- -

: udp://ip:12345

+
+

:

+ +

:

+ +

: udp://ip:12345

+
+
+
+

+
+

+
+
+
+
+
+
+ +
+
+ +
+ +
@@ -45,4 +65,4 @@

require("./js/setup.js") - \ No newline at end of file + diff --git a/locales/en/translation.json b/locales/en/translation.json index ce137d33..56c78060 100644 --- a/locales/en/translation.json +++ b/locales/en/translation.json @@ -361,5 +361,11 @@ "recovery_old_seed_hash_balance": "Old seed has balance. Please move the balance to a new seed and try again.", "recovery_submitted_address": "Any reclaimed tokens will be sent to your address shown below. For security reasons, do not spend from this address until you receive all your funds.", "recovery_unexpected_error": "An unxpected error occured. Please try again.", - "recovery_receive_address": "Address:" + "recovery_receive_address": "Address:", + "download_iri_prompt": "Download IRI", + "download_iri_prompt_text": "Click the button below to start downloading IRI. Wallet fetches IRI from official releases page and automatically verifies the file signature.", + "download_iri": "Download iri", + "download_iri_downloading": "Downloading IRI...", + "download_iri_verifying": "Verifying signature...", + "download_iri_success": "Downloaded IRI successfully" } diff --git a/package-lock.json b/package-lock.json index 28c4c69c..5fe76a69 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,7 +10,9 @@ "integrity": "sha512-+rr4OgeTNrLuJAf09o3USdttEYiXvZshWMkhD6wR9v1ieXH0JM1Q2yT41/cJuJcqiPpSXlM/g3aR+Y5MWQdr0Q==", "dev": true, "requires": { - "7zip-bin-linux": "1.1.0" + "7zip-bin-linux": "1.1.0", + "7zip-bin-mac": "1.0.1", + "7zip-bin-win": "2.1.1" } }, "7zip-bin-linux": { @@ -20,6 +22,20 @@ "dev": true, "optional": true }, + "7zip-bin-mac": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/7zip-bin-mac/-/7zip-bin-mac-1.0.1.tgz", + "integrity": "sha1-Pmh3i78JJq3GgVlCcHRQXUdVXAI=", + "dev": true, + "optional": true + }, + "7zip-bin-win": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/7zip-bin-win/-/7zip-bin-win-2.1.1.tgz", + "integrity": "sha512-6VGEW7PXGroTsoI2QW3b0ea95HJmbVBHvfANKLLMzSzFA1zKqVX5ybNuhmeGpf6vA0x8FJTt6twpprDANsY5WQ==", + "dev": true, + "optional": true + }, "@types/node": { "version": "7.0.46", "resolved": "https://registry.npmjs.org/@types/node/-/node-7.0.46.tgz", @@ -30,7 +46,6 @@ "version": "5.2.3", "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.2.3.tgz", "integrity": "sha1-wG9Zh3jETGsWGrr+NGa4GtGBTtI=", - "dev": true, "requires": { "co": "4.6.0", "fast-deep-equal": "1.0.0", @@ -192,14 +207,12 @@ "asn1": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", - "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=", - "dev": true + "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=" }, "assert-plus": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" }, "async-exit-hook": { "version": "2.0.1", @@ -210,20 +223,17 @@ "asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", - "dev": true + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" }, "aws-sign2": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", - "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", - "dev": true + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" }, "aws4": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz", - "integrity": "sha1-g+9cqGCysy5KDe7e6MdxudtXRx4=", - "dev": true + "integrity": "sha1-g+9cqGCysy5KDe7e6MdxudtXRx4=" }, "balanced-match": { "version": "1.0.0", @@ -240,7 +250,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz", "integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=", - "dev": true, "optional": true, "requires": { "tweetnacl": "0.14.5" @@ -311,7 +320,6 @@ "version": "4.3.1", "resolved": "https://registry.npmjs.org/boom/-/boom-4.3.1.tgz", "integrity": "sha1-T4owBctKfjiJ90kDD9JbluAdLjE=", - "dev": true, "requires": { "hoek": "4.2.0" } @@ -468,8 +476,7 @@ "caseless": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", - "dev": true + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" }, "chalk": { "version": "2.1.0", @@ -520,8 +527,7 @@ "co": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", - "dev": true + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=" }, "code-point-at": { "version": "1.1.0", @@ -548,7 +554,6 @@ "version": "1.0.5", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz", "integrity": "sha1-k4NwpXtKUd6ix3wV1cX9+JUWQAk=", - "dev": true, "requires": { "delayed-stream": "1.0.0" } @@ -656,7 +661,6 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-3.1.2.tgz", "integrity": "sha1-qJ+7Ig9c4l7FboxKqKT9e1sNKf4=", - "dev": true, "requires": { "boom": "5.2.0" }, @@ -665,7 +669,6 @@ "version": "5.2.0", "resolved": "https://registry.npmjs.org/boom/-/boom-5.2.0.tgz", "integrity": "sha512-Z5BTk6ZRe4tXXQlkqftmsAUANpXmuwlsF5Oov8ThoMbQRzdGTA1ngYRW160GexgOgjsFOKJz0LYhoNi+2AMBUw==", - "dev": true, "requires": { "hoek": "4.2.0" } @@ -718,7 +721,6 @@ "version": "1.14.1", "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", - "dev": true, "requires": { "assert-plus": "1.0.0" } @@ -746,8 +748,7 @@ "delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", - "dev": true + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" }, "delegates": { "version": "1.0.0", @@ -812,7 +813,6 @@ "version": "0.1.1", "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", "integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=", - "dev": true, "optional": true, "requires": { "jsbn": "0.1.1" @@ -1008,6 +1008,14 @@ "mime": "2.0.3" } }, + "encoding": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.12.tgz", + "integrity": "sha1-U4tm8+5izRq1HsMjgp0flIDHS+s=", + "requires": { + "iconv-lite": "0.4.19" + } + }, "end-of-stream": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.0.tgz", @@ -1074,8 +1082,7 @@ "extend": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", - "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=", - "dev": true + "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=" }, "extract-zip": { "version": "1.6.5", @@ -1109,14 +1116,12 @@ "extsprintf": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", - "dev": true + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" }, "fast-deep-equal": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz", - "integrity": "sha1-liVqO8l1WV6zbYLpkp0GDYk0Of8=", - "dev": true + "integrity": "sha1-liVqO8l1WV6zbYLpkp0GDYk0Of8=" }, "fd-slicer": { "version": "1.0.1", @@ -1161,14 +1166,12 @@ "forever-agent": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", - "dev": true + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" }, "form-data": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.1.tgz", "integrity": "sha1-b7lPvXGIUwbXPRXMSX/kzE7NRL8=", - "dev": true, "requires": { "asynckit": "0.4.0", "combined-stream": "1.0.5", @@ -1260,7 +1263,6 @@ "version": "0.1.7", "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", - "dev": true, "requires": { "assert-plus": "1.0.0" } @@ -1328,14 +1330,12 @@ "har-schema": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", - "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", - "dev": true + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" }, "har-validator": { "version": "5.0.3", "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.0.3.tgz", "integrity": "sha1-ukAsJmGU8VlW7xXg/PJCmT9qff0=", - "dev": true, "requires": { "ajv": "5.2.3", "har-schema": "2.0.0" @@ -1357,19 +1357,17 @@ "version": "6.0.2", "resolved": "https://registry.npmjs.org/hawk/-/hawk-6.0.2.tgz", "integrity": "sha512-miowhl2+U7Qle4vdLqDdPt9m09K6yZhkLDTWGoUiUzrQCn+mHHSmfJgAyGaLRZbPmTqfFFjRV1QWCW0VWUJBbQ==", - "dev": true, "requires": { "boom": "4.3.1", "cryptiles": "3.1.2", "hoek": "4.2.0", - "sntp": "2.0.2" + "sntp": "2.1.0" } }, "hoek": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.0.tgz", - "integrity": "sha512-v0XCLxICi9nPfYrS9RL8HbYnXi9obYAeLbSP00BmnZwCK9+Ih9WOjoZ8YoHCoav2csqn4FOz4Orldsy2dmDwmQ==", - "dev": true + "integrity": "sha512-v0XCLxICi9nPfYrS9RL8HbYnXi9obYAeLbSP00BmnZwCK9+Ih9WOjoZ8YoHCoav2csqn4FOz4Orldsy2dmDwmQ==" }, "home-path": { "version": "1.0.5", @@ -1387,7 +1385,6 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", - "dev": true, "requires": { "assert-plus": "1.0.0", "jsprim": "1.4.1", @@ -1410,8 +1407,7 @@ "iconv-lite": { "version": "0.4.19", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", - "integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==", - "dev": true + "integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==" }, "import-lazy": { "version": "2.1.0", @@ -1422,8 +1418,7 @@ "imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", - "dev": true + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=" }, "indent-string": { "version": "2.1.0", @@ -1554,14 +1549,12 @@ "is-stream": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", - "dev": true + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" }, "is-typedarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", - "dev": true + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" }, "is-utf8": { "version": "0.2.1", @@ -1590,8 +1583,7 @@ "isstream": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", - "dev": true + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" }, "js-yaml": { "version": "3.10.0", @@ -1607,26 +1599,22 @@ "version": "0.1.1", "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", - "dev": true, "optional": true }, "json-schema": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", - "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", - "dev": true + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" }, "json-schema-traverse": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", - "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=", - "dev": true + "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=" }, "json-stable-stringify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", - "dev": true, "requires": { "jsonify": "0.0.0" } @@ -1634,8 +1622,7 @@ "json-stringify-safe": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", - "dev": true + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" }, "json5": { "version": "0.4.0", @@ -1653,14 +1640,12 @@ "jsonify": { "version": "0.0.0", "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", - "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", - "dev": true + "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=" }, "jsprim": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", - "dev": true, "requires": { "assert-plus": "1.0.0", "extsprintf": "1.3.0", @@ -1814,14 +1799,12 @@ "mime-db": { "version": "1.30.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.30.0.tgz", - "integrity": "sha1-dMZD2i3Z1qRTmZY0ZbJtXKfXHwE=", - "dev": true + "integrity": "sha1-dMZD2i3Z1qRTmZY0ZbJtXKfXHwE=" }, "mime-types": { "version": "2.1.17", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.17.tgz", "integrity": "sha1-Cdejk/A+mVp5+K+Fe3Cp4KsWVXo=", - "dev": true, "requires": { "mime-db": "1.30.0" } @@ -1888,6 +1871,35 @@ "lodash.toarray": "4.4.0" } }, + "node-fetch": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.3.tgz", + "integrity": "sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ==", + "requires": { + "encoding": "0.1.12", + "is-stream": "1.1.0" + } + }, + "node-localstorage": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/node-localstorage/-/node-localstorage-1.3.0.tgz", + "integrity": "sha1-LkNqro3Mms6XtDxlwWwNV3vgpVw=", + "requires": { + "write-file-atomic": "1.3.4" + }, + "dependencies": { + "write-file-atomic": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-1.3.4.tgz", + "integrity": "sha1-+Aek8LHZ6ROuekgRLmzDrxmRtF8=", + "requires": { + "graceful-fs": "4.1.11", + "imurmurhash": "0.1.4", + "slide": "1.1.6" + } + } + } + }, "noop-logger": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/noop-logger/-/noop-logger-0.1.1.tgz", @@ -1951,8 +1963,7 @@ "oauth-sign": { "version": "0.8.2", "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", - "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=", - "dev": true + "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=" }, "object-assign": { "version": "4.1.1", @@ -1974,6 +1985,15 @@ "wrappy": "1.0.2" } }, + "openpgp": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/openpgp/-/openpgp-2.6.2.tgz", + "integrity": "sha512-Bpgf4Dx5BKJMI0z47j4Bga4opC+oUU935MlFyNS/KZfh4gVGUGCR+P1y/22EtlgtfP9Rw6EHnpVJZ9xC+iOURg==", + "requires": { + "node-fetch": "1.7.3", + "node-localstorage": "1.3.0" + } + }, "os-homedir": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", @@ -2096,8 +2116,7 @@ "performance-now": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", - "dev": true + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" }, "pidusage": { "version": "1.1.6", @@ -2234,14 +2253,12 @@ "punycode": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", - "dev": true + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" }, "qs": { "version": "6.5.1", "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz", - "integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A==", - "dev": true + "integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A==" }, "rabin-bindings": { "version": "1.7.3", @@ -2393,7 +2410,6 @@ "version": "2.83.0", "resolved": "https://registry.npmjs.org/request/-/request-2.83.0.tgz", "integrity": "sha512-lR3gD69osqm6EYLk9wB/G1W/laGWjzH90t1vEa2xuxHD5KUrSzp9pUSfTm+YC5Nxt2T8nMPEvKlhbQayU7bgFw==", - "dev": true, "requires": { "aws-sign2": "0.7.0", "aws4": "1.6.0", @@ -2443,8 +2459,7 @@ "safe-buffer": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", - "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==", - "dev": true + "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==" }, "sanitize-filename": { "version": "1.6.1", @@ -2531,11 +2546,15 @@ "string-width": "1.0.2" } }, + "slide": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/slide/-/slide-1.1.6.tgz", + "integrity": "sha1-VusCfWW00tzmyy4tMsTUr8nh1wc=" + }, "sntp": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/sntp/-/sntp-2.0.2.tgz", - "integrity": "sha1-UGQRDwr4X3z9t9a2ekACjOUrSys=", - "dev": true, + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/sntp/-/sntp-2.1.0.tgz", + "integrity": "sha512-FL1b58BDrqS3A11lJ0zEdnJ3UOKqVxawAkF3k7F0CVN7VQ34aZrV+G8BZ1WC9ZL7NyrwsW0oviwsWDgRuVYtJg==", "requires": { "hoek": "4.2.0" } @@ -2592,7 +2611,6 @@ "version": "1.13.1", "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.13.1.tgz", "integrity": "sha1-US322mKHFEMW3EwY/hzx2UBzm+M=", - "dev": true, "requires": { "asn1": "0.2.3", "assert-plus": "1.0.0", @@ -2630,8 +2648,7 @@ "stringstream": { "version": "0.0.5", "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", - "integrity": "sha1-TkhM1N5aC7vuGORjB3EKioFiGHg=", - "dev": true + "integrity": "sha1-TkhM1N5aC7vuGORjB3EKioFiGHg=" }, "strip-ansi": { "version": "3.0.1", @@ -2817,7 +2834,6 @@ "version": "2.3.3", "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.3.tgz", "integrity": "sha1-C2GKVWW23qkL80JdBNVe3EdadWE=", - "dev": true, "requires": { "punycode": "1.4.1" } @@ -2841,7 +2857,6 @@ "version": "0.6.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", - "dev": true, "requires": { "safe-buffer": "5.1.1" } @@ -2850,7 +2865,6 @@ "version": "0.14.5", "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", - "dev": true, "optional": true }, "typedarray": { @@ -2921,8 +2935,7 @@ "uuid": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.1.0.tgz", - "integrity": "sha512-DIWtzUkw04M4k3bf1IcpS2tngXEL26YUD2M0tMDUpnUrz2hgzUBlD55a4FjdLGPvfHxS6uluGWvaVEqgBcVa+g==", - "dev": true + "integrity": "sha512-DIWtzUkw04M4k3bf1IcpS2tngXEL26YUD2M0tMDUpnUrz2hgzUBlD55a4FjdLGPvfHxS6uluGWvaVEqgBcVa+g==" }, "validate-npm-package-license": { "version": "3.0.1", @@ -2938,7 +2951,6 @@ "version": "1.10.0", "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", - "dev": true, "requires": { "assert-plus": "1.0.0", "core-util-is": "1.0.2", diff --git a/package.json b/package.json index 2d8eafa9..b83a42e0 100644 --- a/package.json +++ b/package.json @@ -35,7 +35,9 @@ "glob": "^7.1.2", "i18next": "^8.4.2", "i18next-sync-fs-backend": "^0.1.0", - "pidusage": "^1.1.5" + "openpgp": "^2.6.2", + "pidusage": "^1.1.5", + "request": "^2.83.0" }, "devDependencies": { "electron": "1.7.9", @@ -53,7 +55,6 @@ ], "appId": "com.iotatoken.wallet", "extraResources": [ - "iri/iri.jar", "ccurl/**/*", "ui/**/*", "locales/**/*" From 8ac2d6d0fd4dd31a78298ef7394c5ff2ae9c280e Mon Sep 17 00:00:00 2001 From: Chris Dukakis Date: Sun, 28 Jan 2018 22:24:38 +0200 Subject: [PATCH 3/6] update deps in testnet package.json --- package.testnet.json | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/package.testnet.json b/package.testnet.json index 0aa30bd9..93f50cb4 100644 --- a/package.testnet.json +++ b/package.testnet.json @@ -28,13 +28,16 @@ "url": "https://github.com/iotaledger/wallet" }, "dependencies": { + "core-util-is": "^1.0.2", "curl.lib.js": "^1.0.22", "ffi": "^2.2.0", "fs-extra": "^1.0.0", "glob": "^7.1.2", "i18next": "^8.4.2", "i18next-sync-fs-backend": "^0.1.0", - "pidusage": "^1.1.5" + "openpgp": "^2.6.2", + "pidusage": "^1.1.5", + "request": "^2.83.0" }, "devDependencies": { "electron": "1.7.4", @@ -52,7 +55,6 @@ ], "appId": "com.iotatoken.wallet-testnet", "extraResources": [ - "iri/iri-testnet.jar", "ccurl/**/*", "ui/**/*", "locales/**/*" From a92fdfa0292240c82a3a7bfdaf98af885698c8bf Mon Sep 17 00:00:00 2001 From: Chris Dukakis Date: Sun, 28 Jan 2018 22:25:06 +0200 Subject: [PATCH 4/6] update readme --- README.md | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) 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. From 612af34d7580056dd81ddd4cc0feeb5aa1f0cdfa Mon Sep 17 00:00:00 2001 From: Chris Dukakis Date: Mon, 29 Jan 2018 01:46:34 +0200 Subject: [PATCH 5/6] fix buttons & settings title --- app/windows/js/setup.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/app/windows/js/setup.js b/app/windows/js/setup.js index 76522fc9..73dab8b5 100644 --- a/app/windows/js/setup.js +++ b/app/windows/js/setup.js @@ -643,11 +643,12 @@ var UI = (function(UI, undefined) { 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('start-btn').style.display = 'block' - document.getElementById('switch-btn').disabled = 'false' + 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) From 9ec1e7fe0639ffc55fe481af4578a6f3bb8f0524 Mon Sep 17 00:00:00 2001 From: Chris Dukakis Date: Mon, 29 Jan 2018 03:37:57 +0200 Subject: [PATCH 6/6] add latest iri version & correct public key --- app/js/main.js | 2 +- app/windows/js/setup.js | 217 ++++++++++++++-------------------------- 2 files changed, 75 insertions(+), 144 deletions(-) diff --git a/app/js/main.js b/app/js/main.js index ed3eaed1..40bfbf03 100644 --- a/app/js/main.js +++ b/app/js/main.js @@ -29,7 +29,7 @@ var __entityMap = { "/": '/' }; -var IRI_VERSION = '1.4.1.7' +var IRI_VERSION = '1.4.2.1' var IRI_DIRECTORY = 'iri' String.prototype.escapeHTML = function() { diff --git a/app/windows/js/setup.js b/app/windows/js/setup.js index 73dab8b5..543dad12 100644 --- a/app/windows/js/setup.js +++ b/app/windows/js/setup.js @@ -5,153 +5,84 @@ const request = require('request') const fs = require('fs') const openpgp = require('openpgp') -const IRI_VERSION = '1.4.1.7' +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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 -jmYGC3AGYL1vyg== -=Om04 +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 +=fX8W -----END PGP PUBLIC KEY BLOCK-----` var isDevelopment = String(process.env.NODE_ENV).trim() === "development";