diff --git a/main.js b/main.js
index 3b05586..5ad411c 100644
--- a/main.js
+++ b/main.js
@@ -1,10 +1,8 @@
-const { app, dialog, Tray, Menu } = require('electron');
+const { app, Tray, Menu } = require('electron');
const path = require('path');
const fs = require('fs');
const url = require('url');
-const https = require('https');
const platform = require('os').platform();
-const crypto = require('crypto');
const Store = require('electron-store');
const settings = new Store({ name: 'Settings' });
const log = require('electron-log');
@@ -15,32 +13,12 @@ const IS_DEV = (process.argv[1] === 'dev' || process.argv[2] === 'dev');
const IS_DEBUG = IS_DEV || process.argv[1] === 'debug' || process.argv[2] === 'debug';
const LOG_LEVEL = IS_DEBUG ? 'debug' : 'warn';
const WALLET_CFGFILE = path.join(app.getPath('userData'), 'wconfig.txt');
-
-const SVALINN_VERSION = app.getVersion() || '0.3.x';
-const SERVICE_FILENAME = (platform === 'win32' ? `${config.walletServiceBinaryFilename}.exe` : config.walletServiceBinaryFilename);
-const SERVICE_OSDIR = (platform === 'win32' ? 'win' : (platform === 'darwin' ? 'osx' : 'lin'));
-const DEFAULT_SERVICE_BIN = path.join(process.resourcesPath, 'bin', SERVICE_OSDIR, SERVICE_FILENAME);
-
-const DEFAULT_REMOTE_NODE = config.remoteNodeListFallback
- .map((a) => ({ sort: Math.random(), value: a }))
- .sort((a, b) => a.sort - b.sort)
- .map((a) => a.value)[0];
+const SVALINN_VERSION = app.getVersion();
const DEFAULT_SETTINGS = {
- service_bin: DEFAULT_SERVICE_BIN,
- service_host: '127.0.0.1',
- service_port: config.walletServiceRpcPort,
- service_password: 'passwrd',
- service_timeout: 10,
- node_address: DEFAULT_REMOTE_NODE,
- pubnodes_last_updated: 946697799000,
- pubnodes_data: config.remoteNodeListFallback,
- pubnodes_custom: ['127.0.0.1:11898'],
- pubnodes_exclude_offline: false,
tray_minimize: false,
tray_close: false,
darkmode: false,
- service_config_format: config.walletServiceConfigFormat
};
const DEFAULT_SIZE = { width: 840, height: 840 };
const WIN_TITLE = `${config.appName} ${SVALINN_VERSION} - ${config.appDescription}`;
@@ -50,7 +28,6 @@ app.prompShown = false;
app.needToExit = false;
app.debug = IS_DEBUG;
app.walletConfig = WALLET_CFGFILE;
-app.publicNodesUpdated = false;
app.setAppUserModelId(config.appId);
log.transports.console.level = LOG_LEVEL;
@@ -65,7 +42,8 @@ let trayIconHide = path.join(__dirname, 'src/assets/trayon.png');
let win;
let tray;
-function createWindow() {
+function createWindow()
+{
// Create the browser window.
let darkmode = settings.get('darkmode', false);
let bgColor = darkmode ? '#000000' : '#02853E';
@@ -152,7 +130,6 @@ function createWindow() {
tray.setToolTip(config.appSlogan);
tray.setContextMenu(contextMenu);
-
tray.on('click', () => {
if(!win.isFocused() && win.isVisible()){
win.focus();
@@ -231,59 +208,13 @@ function createWindow() {
});
}
-function serviceBinCheck() {
- /*
- if (DEFAULT_SERVICE_BIN.startsWith('/tmp')) {
- log.warn(`AppImage env, copying service bin file`);
- let targetPath = path.join(app.getPath('userData'), SERVICE_FILENAME);
- try {
- fs.renameSync(targetPath, `${targetPath}.bak`, (err) => {
- if (err) log.error(err);
- });
- } catch (_e) { }
-
- try {
- fs.copyFile(DEFAULT_SERVICE_BIN, targetPath, (err) => {
- if (err) {
- log.error(err);
- return;
- }
- settings.set('service_bin', targetPath);
- log.debug(`service binary copied to ${targetPath}`);
- });
- } catch (_e) { }
- } else {
- // don't trust user's settings, recheck
- let svcbin = settings.get('service_bin');
- try{
- if(!fs.existsSync(svcbin)){
- log.warn(`Service binary can't be found, falling back to default`);
- settings.set('service_bin', DEFAULT_SERVICE_BIN);
- }else{
- log.info('Service binary found');
- }
- }catch(_e) {
- log.warn('Failed to check for service binary path, falling back to default');
- settings.set('service_bin', DEFAULT_SERVICE_BIN);
- }
- }
- */
-}
-
function initSettings() {
Object.keys(DEFAULT_SETTINGS).forEach((k) => {
if (!settings.has(k) || settings.get(k) === null) {
settings.set(k, DEFAULT_SETTINGS[k]);
}
});
- settings.set('service_password', crypto.randomBytes(32).toString('hex'));
settings.set('version', SVALINN_VERSION);
- // serviceBinCheck();
- /*
- fs.unlink(WALLET_CFGFILE, (err) => {
- if (err) log.debug(err.code === 'ENOENT' ? 'No stalled wallet config' : err.message);
- });
- */
}
app.on('browser-window-created', function (e, window) {
@@ -343,10 +274,4 @@ app.on('ready', () => {
if (tx > 0 && ty > 0) {
try { win.setPosition(parseInt(tx, 10), parseInt(ty, 10)); } catch (_e) { }
}
-
- // remove old settings cruft if exist
- setTimeout(() => {
- try { settings.delete('pubnodes_checked'); } catch (e) { }
- try { settings.delete('pubnodes_date'); } catch (e) { }
- }, 2500);
});
\ No newline at end of file
diff --git a/package.json b/package.json
index 0ce3880..1597dce 100644
--- a/package.json
+++ b/package.json
@@ -2,7 +2,7 @@
"name": "svalinn",
"productName": "Svalinn",
"description": "ICONation ICX Wallet",
- "version": "0.1.5",
+ "version": "0.1.6",
"homepage": "https://github.com/ICONation/svalinn",
"repository": "https://github.com/ICONation/svalinn",
"main": "main.js",
@@ -37,7 +37,9 @@
"node-crypto-gcm": "^1.0.3",
"qr-image": "^3.2.0",
"request": "^2.88.0",
- "request-promise-native": "^1.0.7"
+ "request-promise-native": "^1.0.7",
+ "shell": "^0.5.0",
+ "superagent": "^4.1.0"
},
"build": {
"appId": "org.iconation.svalinn",
diff --git a/src/css/common.css b/src/css/common.css
index b112057..f66bef0 100644
--- a/src/css/common.css
+++ b/src/css/common.css
@@ -1076,6 +1076,10 @@ h4.input-required:after{
text-shadow: 1px 1px 1px #000;
}
+.dont-color-link {
+ color : inherit;
+}
+
.help-hl{
color: rgba(255,255,255,1.0);
}
diff --git a/src/html/about.html b/src/html/about.html
index b5c81ae..d26f012 100644
--- a/src/html/about.html
+++ b/src/html/about.html
@@ -5,7 +5,7 @@
diff --git a/src/html/settings.html b/src/html/settings.html
deleted file mode 100644
index 328c4b9..0000000
--- a/src/html/settings.html
+++ /dev/null
@@ -1,63 +0,0 @@
-
-
-
-
-
Settings
-
-
-
-
- Save
- Back
-
-
-
-
-
diff --git a/src/js/ws_api.js b/src/js/ws_api.js
deleted file mode 100644
index c85732f..0000000
--- a/src/js/ws_api.js
+++ /dev/null
@@ -1,269 +0,0 @@
-const request = require('request-promise-native');
-const config = require('./ws_config.js');
-
-class SvalinnApi {
- constructor(args) {
- args = args || {};
- if (!(this instanceof SvalinnApi)) return new SvalinnApi(args);
- this.service_host = args.service_host || '127.0.0.1';
- this.service_port = args.service_port || config.walletServiceRpcPort;
- this.service_password = args.service_password || "WHATEVER1234567891";
- this.minimum_fee = (args.minimum_fee !== undefined) ? args.minimum_fee : (config.minimumFee * config.decimalDivisor);
- this.anonimity = config.defaultMixin;
- }
- _sendRequest(method, params, timeout) {
- return new Promise((resolve, reject) => {
- if (method.length === 0) return reject(new Error('Invalid Method'));
- params = params || {};
- timeout = timeout || 3000;
- let data = {
- jsonrpc: '2.0',
- method: method,
- params: params,
- password: this.service_password
- };
- let s_host = this.service_host;
- let s_port = this.service_port;
- request({
- uri: `http://${s_host}:${s_port}/json_rpc`,
- method: 'POST',
- headers: {
- Connection: 'keep-alive',
- },
- body: data,
- json: true,
- timeout: timeout
- }).then((res) => {
- if (!res) return resolve(true);
- if (!res.error) {
- if (res.result) return resolve(res.result);
- return resolve(res);
- } else {
- return reject(res.error.message);
- }
- }).catch((err) => {
- return reject(err);
- });
- });
- }
- // only get single addres only, no multi address support for this wallet, yet
- getAddress() {
- return new Promise((resolve, reject) => {
- this._sendRequest('getAddresses').then((result) => {
- return resolve(result.addresses[0]);
- }).catch((err) => {
- return reject(err);
- });
- });
- }
- getFeeInfo() {
- return new Promise((resolve, reject) => {
- this._sendRequest('getFeeInfo').then((result) => {
- return resolve(result);
- }).catch((err) => {
- return reject(err);
- });
- });
- }
- getBalance(params) {
- return new Promise((resolve, reject) => {
- params = params || {};
- params.address = params.address || '';
- let req_params = {
- address: params.address
- };
- this._sendRequest('getBalance', req_params).then((result) => {
- return resolve(result);
- }).catch((err) => {
- return reject(err);
- });
- });
- }
- getStatus() {
- return new Promise((resolve, reject) => {
- this._sendRequest('getStatus').then((result) => {
- return resolve(result);
- }).catch((err) => {
- return reject(err);
- });
- });
- }
- save() {
- return new Promise((resolve, reject) => {
- this._sendRequest('save', {}, 6000).then(() => {
- return resolve();
- }).catch((err) => {
- return reject(err);
- });
- });
- }
- getViewKey() {
- return new Promise((resolve, reject) => {
- this._sendRequest('getViewKey').then((result) => {
- return resolve(result);
- }).catch((err) => {
- return reject(err);
- });
- });
- }
- getSpendKeys(params) {
- return new Promise((resolve, reject) => {
- params = params || {};
- params.address = params.address || '';
- if (!params.address.length)
- return reject(new Error('Missing address parameter'));
- var req_params = {
- address: params.address
- };
- this._sendRequest('getSpendKeys', req_params).then((result) => {
- return resolve(result);
- }).catch((err) => {
- return reject(err);
- });
- });
- }
- getMnemonicSeed(params) {
- return new Promise((resolve, reject) => {
- params = params || {};
- params.address = params.address || '';
- if (params.address.length === 0)
- return reject(new Error('Missing address parameter'));
- var req_params = {
- address: params.address
- };
- this._sendRequest('getMnemonicSeed', req_params).then((result) => {
- return resolve(result);
- }).catch((err) => {
- return reject(err);
- });
- });
- }
- getBackupKeys(params) {
- return new Promise((resolve, reject) => {
- params = params || {};
- params.address = params.address || '';
- if (params.address.length === 0) return reject(new Error('Missing address parameter'));
- var req_params = {
- address: params.address
- };
- var backupKeys = {};
- this.getViewKey().then((vkres) => {
- backupKeys.viewSecretKey = vkres.viewSecretKey;
- return backupKeys;
- }).then(() => {
- this.getSpendKeys(req_params).then((vsres) => {
- backupKeys.spendSecretKey = vsres.spendSecretKey;
- return backupKeys;
- }).catch((err) => {
- return reject(err);
- });
- }).then(() => {
- this.getMnemonicSeed(req_params).then((mres) => {
- backupKeys.mnemonicSeed = mres.mnemonicSeed;
- return resolve(backupKeys);
- }).catch((_err) => { /* jshint ignore:line */
- backupKeys.mnemonicSeed = "";
- return resolve(backupKeys);
- });
- }).catch((err) => {
- return reject(err);
- });
- });
- }
- getTransactions(params) {
- return new Promise((resolve, reject) => {
- params = params || {};
- params.firstBlockIndex = params.firstBlockIndex || 1;
- params.blockCount = params.blockCount || 100;
- var req_params = {
- firstBlockIndex: (params.firstBlockIndex >= 1) ? params.firstBlockIndex : 1,
- blockCount: (params.blockCount >= 1) ? params.blockCount : 100
- };
- this._sendRequest('getTransactions', req_params).then((result) => {
- return resolve(result);
- }).catch((err) => {
- return reject(err);
- });
- });
- }
- // send single transaction
- sendTransaction(params) {
- return new Promise((resolve, reject) => {
- params = params || {};
- params.amount = params.amount || false;
- params.address = params.address || false;
- //params.transfers = params.transfers || false;
- params.paymentId = params.paymentId || false;
- params.fee = params.fee || this.minimum_fee;
- if (!params.address) return reject(new Error('Missing recipient address parameter'));
- if (!params.amount) return reject(new Error('Missing transaction amount parameter'));
- if (parseFloat(params.fee) < 0.1) return reject(new Error('Minimum fee is 0.1 ICX'));
- //[{address: "ICXxxxx...", amount: 100}];
- var req_params = {
- transfers: [{ address: params.address, amount: params.amount }],
- fee: params.fee
- };
- if (params.paymentId) req_params.paymentId = params.paymentId;
- // give extra long timeout
- this._sendRequest('sendTransaction', req_params, 10000).then((result) => {
- return resolve(result);
- }).catch((err) => {
- return reject(err);
- });
- });
- }
- reset(params) {
- return new Promise((resolve, reject) => {
- params = params || {};
- params.scanHeight = params.scanHeight || 0;
- let req_params = {};
- if (params.scanHeight && params.scanHeight > 1) {
- req_params = { scanHeight: params.scanHeight };
- }
- this._sendRequest('reset', req_params).then(() => {
- return resolve(true);
- }).catch((err) => {
- return reject(err);
- });
- });
- }
- estimateFusion(params) {
- return new Promise((resolve, reject) => {
- params = params || {};
- if (!params.threshold) return reject(new Error('Missing threshold parameter'));
- this._sendRequest('estimateFusion', params).then((result) => {
- return resolve(result);
- }).catch((err) => {
- return reject(err);
- });
- });
- }
- sendFusionTransaction(params) {
- return new Promise((resolve, reject) => {
- params = params || {};
- if (!params.threshold) return reject(new Error('Missing threshold parameter'));
- if (!params.anonimity) params.anonimity = this.anonimity;
- this._sendRequest('sendFusionTransaction', params).then((result) => {
- return resolve(result);
- }).catch((err) => {
- return reject(err);
- });
- });
- }
- createIntegratedAddress(params) {
- return new Promise((resolve, reject) => {
- params = params || {};
- if (!params.address || !params.paymentId) {
- return reject(new Error('Address and Payment Id parameters are required'));
- }
-
- this._sendRequest('createIntegratedAddress', params).then((result) => {
- return resolve(result);
- }).catch((err) => {
- return reject(err);
- });
- });
- }
-}
-
-module.exports = SvalinnApi;
\ No newline at end of file
diff --git a/src/js/ws_config.js b/src/js/ws_config.js
index 4762110..427a695 100644
--- a/src/js/ws_config.js
+++ b/src/js/ws_config.js
@@ -7,44 +7,11 @@ config.appSlogan = 'Svalinn';
config.appId = 'org.iconation.svalinn';
config.appGitRepo = 'https://github.com/ICONation/svalinn';
-// default port number for your daemon
-config.daemonDefaultRpcPort = 11898;
-
// wallet file created by this app will have this extension
config.walletFileDefaultExt = 'icx';
// transaction file created by this app will have this extension
config.transactionFileDefaultExt = 'tx';
-// change this to match your wallet service executable filename
-config.walletServiceBinaryFilename = 'svalinn';
-
-// version on the bundled service (turtle-service)
-config.walletServiceBinaryVersion = "v0.12.0";
-
-// config file format supported by wallet service, possible values:
-// ini --> for turtle service (or its forks) version <= v0.8.3
-// json --> for turtle service (or its forks) version >= v0.8.4
-config.walletServiceConfigFormat = "json";
-
-// default port number for your wallet service (e.g. turtle-service)
-config.walletServiceRpcPort = 8070;
-
-// block explorer url, the [[TX_HASH]] will be substituted w/ actual transaction hash
-config.blockExplorerUrl = 'https://explorer.turtlecoin.lol/transaction.html?hash=[[TX_HASH]]';
-
-// default remote node to connect to, set this to a known reliable node for 'just works' user experience
-config.remoteNodeDefaultHost = 'turtlenode.co';
-
-// remote node list update url, set to null if you don't have one
-config.remoteNodeListUpdateUrl = 'https://raw.githubusercontent.com/turtlecoin/turtlecoin-nodes-json/master/turtlecoin-nodes.json';
-
-// fallback remote node list, in case fetching update failed, fill this with known to works remote nodes
-config.remoteNodeListFallback = [
- 'turtlenode.co:11898',
- 'nodes.hashvault.pro:11898',
- 'turtle.mine.nu:11898',
-];
-
// your currency name
config.assetName = 'ICX';
// your currency ticker
@@ -58,10 +25,6 @@ config.addressLength = 42;
config.minimumFee = 100000;
// minimum amount for sending transaction
config.mininumSend = 0.0;
-// default mixin/anonimity for transaction
-config.defaultMixin = 3;
-// to convert from atomic unit
-config.decimalDivisor = 1000000000000000000;
// to represent human readable value
config.decimalPlaces = 18;
diff --git a/src/js/ws_manager.js b/src/js/ws_manager.js
index 6fbefb4..bf5f243 100644
--- a/src/js/ws_manager.js
+++ b/src/js/ws_manager.js
@@ -1,86 +1,32 @@
-const path = require('path');
const fs = require('fs');
const os = require('os');
-const childProcess = require('child_process');
const log = require('electron-log');
const Store = require('electron-store');
const SvalinnSession = require('./ws_session');
-const SvalinnApi = require('./ws_api');
const uiupdater = require('./wsui_updater');
-const wsutil = require('./ws_utils');
-const config = require('./ws_config');
const IconService = require('icon-sdk-js');
const { remote } = require('electron');
const settings = new Store({ name: 'Settings' });
const sessConfig = { debug: remote.app.debug, walletConfig: remote.app.walletConfig };
const wsession = new SvalinnSession(sessConfig);
-const SERVICE_LOG_DEBUG = wsession.get('debug');
-const SERVICE_LOG_LEVEL_DEFAULT = 0;
-const SERVICE_LOG_LEVEL_DEBUG = 5;
-const SERVICE_LOG_LEVEL = (SERVICE_LOG_DEBUG ? SERVICE_LOG_LEVEL_DEBUG : SERVICE_LOG_LEVEL_DEFAULT);
-
-const ERROR_WALLET_EXEC = `Failed to start ${config.walletServiceBinaryFilename}. Set the path to ${config.walletServiceBinaryFilename} properly in the settings tab.`;
-const ERROR_WALLET_PASSWORD = 'Failed to load your wallet, please check your password';
-const ERROR_WALLET_IMPORT = 'Import failed, please check that you have entered all information correctly';
const ERROR_WALLET_CREATE = 'Wallet can not be created, please check your input and try again';
-const ERROR_TRANSACTION_CREATE = 'Transaction can not be created, please check your input and try again';
const ERROR_PASSWORD_FORMAT = 'Password must be at least 8 characters long and contain a combination of letters, numbers, and special characters. (?!:.,%+-/*<>{}()[]`"\'~_^\\|@#$&)';
-const ERROR_RPC_TIMEOUT = 'Unable to communicate with selected node, please try again in a few seconds or switch to another node address';
-const INFO_FUSION_DONE = 'Wallet optimization completed, your balance may appear incorrect for a while.';
-const INFO_FUSION_SKIPPED = 'Wallet already optimized. No further optimization is needed.';
-const ERROR_FUSION_FAILED = 'Unable to optimize your wallet, please try again in a few seconds';
-var SvalinnManager = function () {
+var SvalinnManager = function ()
+{
if (!(this instanceof SvalinnManager)) {
return new SvalinnManager();
}
- let nodeAddress = settings.get('node_address').split(':');
- this.daemonHost = nodeAddress[0] || null;
- this.daemonPort = nodeAddress[1] || null;
- this.serviceProcess = null;
- this.serviceBin = settings.get('service_bin');
- this.servicePassword = settings.get('service_password');
- this.serviceHost = settings.get('service_host');
- this.servicePort = settings.get('service_port');
- this.serviceTimeout = settings.get('service_timeout');
- this.serviceArgsDefault = ['--rpc-password', settings.get('service_password')];
- this.walletConfigDefault = { 'rpc-password': settings.get('service_password') };
- this.servicePid = null;
- this.serviceLastPid = null;
- this.serviceActiveArgs = [];
- this.serviceApi = null;
- this.syncWorker = null;
- this.fusionTxHash = [];
-
this.iconNetworks = [
- {desc: "None", url: "unknown", nid: 0},
- {desc: "Mainnet", url: "https://ctz.solidwallet.io", nid: 1},
- {desc: "Testnet for Exchanges (Euljiro)", url: "https://test-ctz.solidwallet.io", nid: 2},
- {desc: "Testnet for DApps (Yeouido)", url: "https://bicon.net.solidwallet.io", nid: 3}
+ {desc: "None", url: "unknown", tracker: "", nid: 0},
+ {desc: "Mainnet", url: "https://ctz.solidwallet.io", tracker: "https://tracker.icon.foundation", nid: 1},
+ {desc: "Testnet for Exchanges (Euljiro)", url: "https://test-ctz.solidwallet.io", tracker: "https://trackerdev.icon.foundation", nid: 2},
+ {desc: "Testnet for DApps (Yeouido)", url: "https://bicon.net.solidwallet.io", tracker: "https://bicon.tracker.solidwallet.io", nid: 3}
];
};
-SvalinnManager.prototype.init = function () {
- this._getSettings();
- if (this.serviceApi !== null) return;
-
- let cfg = {
- service_host: this.serviceHost,
- service_port: this.servicePort,
- service_password: this.servicePassword
- };
- this.serviceApi = new SvalinnApi(cfg);
-};
-
-SvalinnManager.prototype._getSettings = function () {
- let nodeAddress = settings.get('node_address').split(':');
- this.daemonHost = nodeAddress[0] || null;
- this.daemonPort = nodeAddress[1] || null;
- this.serviceBin = settings.get('service_bin');
-};
-
SvalinnManager.prototype._reinitSession = function () {
this._wipeConfig();
wsession.reset();
@@ -90,78 +36,13 @@ SvalinnManager.prototype._reinitSession = function () {
});
};
-SvalinnManager.prototype._serviceBinExists = function () {
- wsutil.isFileExist(this.serviceBin);
-};
-
-// check
-SvalinnManager.prototype.serviceStatus = function () {
- return (undefined !== this.serviceProcess && null !== this.serviceProcess);
-};
-
-SvalinnManager.prototype.isRunning = function () {
- /*
- this.init();
- let proc = path.basename(this.serviceBin);
- let platform = process.platform;
- let cmd = '';
- switch (platform) {
- case 'win32': cmd = `tasklist`; break;
- case 'darwin': cmd = `ps -ax | grep ${proc}`; break;
- case 'linux': cmd = `ps -A`; break;
- default: break;
- }
- if (cmd === '' || proc === '') return false;
-
- childProcess.exec(cmd, (err, stdout, stderr) => {
- if (err) log.debug(err.message);
- if (stderr) log.debug(stderr.toLocaleLowerCase());
- let found = stdout.toLowerCase().indexOf(proc.toLowerCase()) > -1;
- log.debug(`Process found: ${found}`);
- return found;
- });
- */
-};
-
-SvalinnManager.prototype._writeIniConfig = function (cfg) {
- let configFile = wsession.get('walletConfig');
- if (!configFile) return '';
-
- try {
- fs.writeFileSync(configFile, cfg);
- return configFile;
- } catch (err) {
- log.error(err);
- return '';
- }
-};
-
-SvalinnManager.prototype._writeConfig = function (cfg) {
- let configFile = wsession.get('walletConfig');
- if (!configFile) return '';
-
- cfg = cfg || {};
- if (!cfg) return '';
-
- let configData = '';
- Object.keys(cfg).map((k) => { configData += `${k}=${cfg[k]}${os.EOL}`; });
- try {
- fs.writeFileSync(configFile, configData);
- return configFile;
- } catch (err) {
- log.error(err);
- return '';
- }
-};
-
SvalinnManager.prototype._wipeConfig = function () {
try { fs.unlinkSync(wsession.get('walletConfig')); } catch (e) { }
};
-SvalinnManager.prototype.startService = function (walletFile, onError, onSuccess, onDelay) {
-
+SvalinnManager.prototype.startService = function (walletFile, onError, onSuccess, onDelay)
+{
const keystore = JSON.parse (fs.readFileSync (walletFile, 'utf8').replace(/^\uFEFF/, ''));
-
try {
wsession.set ('loadedWalletAddress', keystore.address);
wsession.set ('serviceReady', true);
@@ -171,34 +52,6 @@ SvalinnManager.prototype.startService = function (walletFile, onError, onSuccess
}
};
-SvalinnManager.prototype._argsToIni = function (args) {
- let configData = "";
- if ("object" !== typeof args || !args.length) return configData;
- args.forEach((k, v) => {
- let sep = ((v % 2) === 0) ? os.EOL : "=";
- configData += `${sep}${k.toString().replace('--', '')}`;
- });
- return configData.trim();
-};
-
-SvalinnManager.prototype.stopService = function () {
-};
-
-SvalinnManager.prototype.terminateService = function (force) {
-};
-
-SvalinnManager.prototype.startSyncWorker = function () {
-};
-
-SvalinnManager.prototype.stopSyncWorker = function () {
-};
-
-SvalinnManager.prototype.getNodeFee = function () {
-};
-
-SvalinnManager.prototype.genIntegratedAddress = function (paymentId, address) {
-};
-
function check_password (password) {
return /^(?=.*\d)(?=.*[a-zA-Z])(?=.*[?!:\.,%+-/*<>{}\(\)\[\]`"'~_^\\|@#$&]).{8,}$/.test(password)
}
@@ -232,6 +85,7 @@ SvalinnManager.prototype.createTransaction = function (tx, transactionFile, wall
// Open the wallet
try {
+ // Wallets may have been saved in UTF-8 format for unknown reasons, thus we need to remove the BOM header
const keystore = JSON.parse (fs.readFileSync (walletFile, 'utf8').replace(/^\uFEFF/, ''));
const wallet = IconService.IconWallet.loadKeystore (keystore, walletPass);
@@ -285,41 +139,8 @@ SvalinnManager.prototype.importFromKeys = function (walletFile, password, privat
});
};
-SvalinnManager.prototype.importFromSeed = function (walletFile, password, mnemonicSeed, scanHeight) {
- this.init();
- let wsm = this;
- return new Promise((resolve, reject) => {
- scanHeight = scanHeight || 0;
-
- let serviceArgs = wsm.serviceArgsDefault.concat([
- '-g', '-w', walletFile, '-p', password,
- '--mnemonic-seed', mnemonicSeed,
- '--log-level', 0, '--log-file', path.join(remote.app.getPath('temp'), 'ts.log')
- ]);
-
- if (scanHeight >= 0) serviceArgs = serviceArgs.concat(['--scan-height', scanHeight]);
-
- childProcess.execFile(
- wsm.serviceBin, serviceArgs, (error, stdout, stderr) => {
- if (stdout) log.debug(stdout);
- if (stderr) log.debug(stderr);
-
- if (error) {
- log.debug(`Error importing seed: ${error.message}`);
- return reject(new Error(ERROR_WALLET_IMPORT));
- } else {
- if (!wsutil.isRegularFileAndWritable(walletFile)) {
- return reject(new Error(ERROR_WALLET_IMPORT));
- }
- return resolve(walletFile);
- }
- }
- );
- });
-};
-
-SvalinnManager.prototype.getSecretKeys = function (walletPass) {
-
+SvalinnManager.prototype.getSecretKeys = function (walletPass)
+{
return new Promise((resolve, reject) => {
try {
const walletFile = settings.get ('recentWallet');
@@ -332,19 +153,8 @@ SvalinnManager.prototype.getSecretKeys = function (walletPass) {
});
};
-SvalinnManager.prototype.sendTransaction = function (params) {
- let wsm = this;
- return new Promise((resolve, reject) => {
- wsm.serviceApi.sendTransaction(params).then((result) => {
- return resolve(result);
- }).catch((err) => {
- return reject(err);
- });
- });
-};
-
-SvalinnManager.prototype.sendSignedTransaction = function (tx) {
-
+SvalinnManager.prototype.sendSignedTransaction = function (tx)
+{
let mgr = this;
return new Promise((resolve, reject) => {
@@ -361,218 +171,12 @@ SvalinnManager.prototype.sendSignedTransaction = function (tx) {
});
};
-SvalinnManager.prototype.rescanWallet = function (scanHeight) {
- let wsm = this;
-
- function resetSession() {
- wsession.set('walletUnlockedBalance', 0);
- wsession.set('walletLockedBalance', 0);
- wsession.set('synchronized', false);
- wsession.set('txList', []);
- wsession.set('txLen', 0);
- wsession.set('txLastHash', null);
- wsession.set('txLastTimestamp', null);
- wsession.set('txNew', []);
- let fakeBlock = -300;
- let resetdata = {
- type: 'blockUpdated',
- data: {
- blockCount: fakeBlock,
- displayBlockCount: fakeBlock,
- knownBlockCount: fakeBlock,
- displayKnownBlockCount: fakeBlock,
- syncPercent: fakeBlock
- }
- };
- wsm.notifyUpdate(resetdata);
- }
-
- return new Promise((resolve) => {
- wsm.serviceApi.reset({ scanHeight: scanHeight }).then(() => {
- resetSession();
- return resolve(true);
- }).catch(() => {
- resetSession();
- return resolve(false);
- });
- });
-};
-
-SvalinnManager.prototype._fusionGetMinThreshold = function (threshold, minThreshold, maxFusionReadyCount, counter) {
- let wsm = this;
- return new Promise((resolve, reject) => {
- counter = counter || 0;
- threshold = threshold || (parseInt(wsession.get('walletUnlockedBalance'), 10) * 100) + 1;
- threshold = parseInt(threshold, 10);
- minThreshold = minThreshold || threshold;
- maxFusionReadyCount = maxFusionReadyCount || 0;
-
- let maxThreshCheckIter = 20;
-
- wsm.serviceApi.estimateFusion({ threshold: threshold }).then((res) => {
- // nothing to optimize
- if (counter === 0 && res.fusionReadyCount === 0) return resolve(0);
- // stop at maxThreshCheckIter or when threshold too low
- if (counter > maxThreshCheckIter || threshold < 10) return resolve(minThreshold);
- // we got a possibly best minThreshold
- if (res.fusionReadyCount < maxFusionReadyCount) {
- return resolve(minThreshold);
- }
- // continue to find next best minThreshold
- maxFusionReadyCount = res.fusionReadyCount;
- minThreshold = threshold;
- threshold /= 2;
- counter += 1;
- resolve(wsm._fusionGetMinThreshold(threshold, minThreshold, maxFusionReadyCount, counter).then((res) => {
- return res;
- }));
- }).catch((err) => {
- return reject(new Error(err));
- });
- });
-};
-
-SvalinnManager.prototype._fusionSendTx = function (threshold, counter) {
- let wsm = this;
- const wtime = ms => new Promise(resolve => setTimeout(resolve, ms));
-
- return new Promise((resolve, reject) => {
- counter = counter || 0;
- let maxIter = 256;
- if (counter >= maxIter) return resolve(wsm.fusionTxHash); // stop at max iter
-
- wtime(2400).then(() => {
- // keep sending fusion tx till it hit IOOR or reaching max iter
- log.debug(`send fusion tx, iteration: ${counter}`);
- wsm.serviceApi.sendFusionTransaction({ threshold: threshold }).then((resp) => {
- wsm.fusionTxHash.push(resp.transactionHash);
- counter += 1;
- return resolve(wsm._fusionSendTx(threshold, counter).then((resp) => {
- return resp;
- }));
- }).catch((err) => {
- if (typeof err === 'string') {
- if (!err.toLocaleLowerCase().includes('index is out of range')) {
- log.debug(err);
- return reject(new Error(err));
- }
- } else if (typeof err === 'object') {
- if (!err.message.toLowerCase().includes('index is out of range')) {
- log.debug(err);
- return reject(new Error(err));
- }
- }
-
- counter += 1;
- return resolve(wsm._fusionSendTx(threshold, counter).then((resp) => {
- return resp;
- }));
- });
-
- });
- });
-};
-
-SvalinnManager.prototype.optimizeWallet = function () {
- let wsm = this;
- log.debug('running optimizeWallet');
- return new Promise((resolve, reject) => {
- wsm.fusionTxHash = [];
- wsm._fusionGetMinThreshold().then((res) => {
- if (res <= 0) {
- wsm.notifyUpdate({
- type: 'fusionTxCompleted',
- data: INFO_FUSION_SKIPPED,
- code: 0
- });
- log.debug('fusion skipped');
- log.debug(wsm.fusionTxHash);
- return resolve(INFO_FUSION_SKIPPED);
- }
-
- log.debug(`performing fusion tx, threshold: ${res}`);
-
- return resolve(
- wsm._fusionSendTx(res).then(() => {
- wsm.notifyUpdate({
- type: 'fusionTxCompleted',
- data: INFO_FUSION_DONE,
- code: 1
- });
- log.debug('fusion done');
- log.debug(wsm.fusionTxHash);
- return INFO_FUSION_DONE;
- }).catch((err) => {
- let msg = err.message.toLowerCase();
- let outMsg = ERROR_FUSION_FAILED;
- switch (msg) {
- case 'index is out of range':
- outMsg = wsm.fusionTxHash.length >= 1 ? INFO_FUSION_DONE : INFO_FUSION_SKIPPED;
- break;
- default:
- break;
- }
- log.debug(`fusionTx outMsg: ${outMsg}`);
- log.debug(wsm.fusionTxHash);
- wsm.notifyUpdate({
- type: 'fusionTxCompleted',
- data: outMsg,
- code: outMsg === INFO_FUSION_SKIPPED ? 0 : 1
- });
- return outMsg;
- })
- );
- }).catch((err) => {
- // todo handle this differently!
- log.debug('fusion error');
- return reject((err.message));
- });
- });
-};
-
-SvalinnManager.prototype.networkStateUpdate = function (state) {
- if (!this.syncWorker) return;
- log.debug('ServiceProcess PID: ' + this.servicePid);
- if (state === 0) {
- // pause the syncworker, but leave service running
- this.syncWorker.send({
- type: 'pause',
- data: null
- });
- } else {
- this.init();
- // looks like turtle-service always stalled after disconnected, just kill & relaunch it
- let pid = this.serviceProcess.pid || null;
- this.terminateService();
- // remove config
- this._wipeConfig();
- // wait a bit
- setImmediate(() => {
- if (pid) {
- try { process.kill(pid, 'SIGKILL'); } catch (e) { }
- // remove config
- this._wipeConfig();
- }
- setTimeout(() => {
- log.debug(`respawning ${config.walletServiceBinaryFilename}`);
- this.serviceProcess = childProcess.spawn(this.serviceBin, this.serviceActiveArgs);
- // store new pid
- this.servicePid = this.serviceProcess.pid;
- this.syncWorker.send({
- type: 'resume',
- data: null
- });
- }, 15000);
- }, 2500);
- }
-};
-
SvalinnManager.prototype.notifyUpdate = function (msg) {
uiupdater.updateUiState(msg);
};
-SvalinnManager.prototype.getBalance = function (address, nid) {
-
+SvalinnManager.prototype.getBalance = function (address, nid)
+{
let mgr = this;
return new Promise ((resolve, reject) => {
diff --git a/src/js/ws_session.js b/src/js/ws_session.js
index 35ea9b7..5bbcf53 100644
--- a/src/js/ws_session.js
+++ b/src/js/ws_session.js
@@ -1,15 +1,4 @@
-//const path = require('path');
-//const remote = require('electron').remote;
-const Store = require('electron-store');
-const settings = new Store({ name: 'Settings' });
-const config = require('./ws_config');
-
-const WS_VERSION = settings.get('version', 'unknown');
-const DEFAULT_TITLE = `${config.appName} ${WS_VERSION} - ${config.appDescription}`;
-const SESSION_KEY = 'wlshell';
-
-//const IS_DEBUG = remote.getGlobal('wsession').debug;
-//const WALLET_CFG = path.join(remote.app.getPath('userData'), 'wconfig.txt');
+const SESSION_KEY = 'svalinSessionKey';
var SvalinnSession = function (opts) {
if (!(this instanceof SvalinnSession)) return new SvalinnSession(opts);
@@ -19,43 +8,22 @@ var SvalinnSession = function (opts) {
this.eventName = 'sessionUpdated';
this.sessDefault = {
loadedWalletAddress: '',
- walletHash: '',
walletUnlockedBalance: 0,
- walletLockedBalance: 0,
walletConfig: opts.walletConfig || 'wconfig.txt',
- synchronized: false,
- syncStarted: false,
serviceReady: false,
- connectedNode: '',
- txList: [],
- txLen: 0,
- txLastHash: null,
- txLastTimestamp: null,
- txNew: [],
- nodeFee: 0,
- nodeChoices: settings.get('pubnodes_data', []),
- servicePath: settings.get('service_bin', 'svalinn'),
- configUpdated: false,
- uiStateChanged: false,
- defaultTitle: DEFAULT_TITLE,
debug: opts.debug || false,
- fusionStarted: false,
- fusionProgress: false,
addressBookErr: false
};
this.stickyVals = {
- publicNodes: [],
- addressBook: null // {id: null, name: null, path: null, data: {}}
+ addressBook: null
};
- /* jshint ignore:start */
- this.keys = Object.keys({ ...this.sessDefault, ...this.stickyVals });
+ this.keys = Object.keys({ ...this.sessDefault, ...this.stickyVals });
// initialize
if (!sessionStorage.getItem(this.sessKey)) {
sessionStorage.setItem(this.sessKey, JSON.stringify({ ...this.sessDefault, ...this.stickyVals }));
}
- /* jshint ignore:end */
};
SvalinnSession.prototype.get = function (key) {
@@ -98,14 +66,13 @@ SvalinnSession.prototype.reset = function (key) {
sessData[key] = this.sessDefault[key]; // set to default value
return sessionStorage.setItem(this.sessKey, JSON.stringify(sessData[key]));
}
- //return sessionStorage.setItem(this.sessKey, JSON.stringify(this.sessDefault));
+
let stickyData = {};
Object.keys(this.stickyVals).forEach((e) => {
stickyData[e] = this.get(e);
});
- /* jshint ignore: start */
+
return sessionStorage.setItem(this.sessKey, JSON.stringify({ ...this.sessDefault, ...stickyData }));
- /* jshint ignore: end */
};
SvalinnSession.prototype.destroy = function () {
diff --git a/src/js/ws_syncworker.js b/src/js/ws_syncworker.js
deleted file mode 100644
index 9fd560c..0000000
--- a/src/js/ws_syncworker.js
+++ /dev/null
@@ -1,307 +0,0 @@
-const log = require('electron-log');
-const SvalinnApi = require('./ws_api');
-
-let DEBUG = false;
-log.transports.file.maxSize = 5 * 1024 * 1024;
-log.transports.console.level = 'debug';
-log.transports.file.level = 'debug';
-
-const SYNC_INTERVAL = 4 * 1000;
-const SYNC_FAILED_MAX = 24;
-
-var serviceConfig = null; // { service_host: '127.0.0.1', service_port: '8070', service_password: 'xxx'};
-var workerState = {
- CONNECTED: true,
- PAUSED: false,
- TX_CHECK_INITIALIZED: false,
- FAILED_COUNT: 0
-};
-var syncState = {
- LAST_BLOCK_COUNT: 1,
- LAST_KNOWN_BLOCK_COUNT: 1,
- TX_LAST_INDEX: 1,
- TX_LAST_COUNT: 0,
- TX_CHECK_SKIPPED_COUNT: 0,
-
-};
-var wsapi = null;
-var taskWorker = null;
-
-function logDebug(msg) {
- if (!DEBUG) return;
- log.debug(`[syncworker] ${msg}`);
-}
-
-function initApi(cfg) {
- if (wsapi instanceof SvalinnApi) return;
- logDebug('Initializing SvalinnApi');
- serviceConfig = cfg;
- wsapi = new SvalinnApi(serviceConfig);
-}
-
-function checkBlockUpdate() {
- if (!serviceConfig || wsapi === null) return;
- logDebug('-> blockUpdater: fetching block update');
- wsapi.getStatus().then((blockStatus) => {
- let lastConStatus = workerState.CONNECTED;
- let conFailed = parseInt(blockStatus.knownBlockCount, 10) === 1;
- if (conFailed) {
- logDebug('-> blockUpdater: Got bad known block count, mark connection as broken');
- if (lastConStatus !== conFailed) {
- let fakeStatus = {
- blockCount: -200,
- knownBlockCount: -200,
- displayBlockCount: -200,
- displayKnownBlockCount: -200,
- syncPercent: -200
- };
- process.send({
- type: 'blockUpdated',
- data: fakeStatus
- });
- }
- workerState.CONNECTED = false;
- return;
- }
-
- // we have good connection
- workerState.CONNECTED = true;
- workerState.FAILED_COUNT = 0;
- let blockCount = parseInt(blockStatus.blockCount, 10);
- let knownBlockCount = parseInt(blockStatus.knownBlockCount, 10);
-
- let blockCountUpdated = (blockCount > syncState.LAST_BLOCK_COUNT);
- let knownBlockCountUpdated = (knownBlockCount > syncState.LAST_KNOWN_BLOCK_COUNT);
- if (!blockCountUpdated && !knownBlockCountUpdated && syncState.TX_CHECK_SKIPPED_COUNT < 8) {
- logDebug(`-> blockUpdater: no update, skip block notifier (${syncState.TX_CHECK_SKIPPED_COUNT})`);
- syncState.TX_CHECK_SKIPPED_COUNT += 1;
- return;
- }
-
- syncState.TX_CHECK_SKIPPED_COUNT = 0;
- logDebug('-> blockUpdater: block updated, notify block update');
- let txcheck = (syncState.LAST_KNOWN_BLOCK_COUNT < knownBlockCount || syncState.LAST_BLOCK_COUNT < knownBlockCount);
- syncState.LAST_BLOCK_COUNT = blockCount;
- syncState.LAST_KNOWN_BLOCK_COUNT = knownBlockCount;
-
- // add any extras here, so renderer not doing too much things
- let dispKnownBlockCount = (knownBlockCount - 1);
- let dispBlockCount = (blockCount > dispKnownBlockCount ? dispKnownBlockCount : blockCount);
- let syncPercent = ((dispBlockCount / dispKnownBlockCount) * 100);
- if (syncPercent <= 0 || syncPercent >= 99.995) {
- syncPercent = 100;
- } else {
- syncPercent = syncPercent.toFixed(2);
- }
-
- blockStatus.displayBlockCount = dispBlockCount;
- blockStatus.displayKnownBlockCount = dispKnownBlockCount;
- blockStatus.syncPercent = syncPercent;
- process.send({
- type: 'blockUpdated',
- data: blockStatus
- });
-
- // don't check if we can't get any block
- if (syncState.LAST_BLOCK_COUNT <= 1) return;
-
- // don't check tx if block count not updated
- if (!txcheck && workerState.TX_CHECK_INITIALIZED) {
- logDebug('-> blockUpdater: Tx check skipped');
- return;
- }
-
- checkTransactionsUpdate();
-
- }).catch((err) => {
- workerState.FAILED_COUNT++;
- logDebug(`-> blockUpdater: FAILED, ${err.message} | failed count: ${workerState.FAILED_COUNT}`);
- if (workerState.FAILED_COUNT > SYNC_FAILED_MAX) {
- logDebug('-> blockUpdater: too many timeout, mark connection as broken');
-
- let fakeStatus = {
- blockCount: -200,
- knownBlockCount: -200,
- displayBlockCount: -200,
- displayKnownBlockCount: -200,
- syncPercent: -200
- };
- process.send({
- type: 'blockUpdated',
- data: fakeStatus
- });
- workerState.STATE_CONNECTED = false;
- return;
- }
- return false;
- });
-}
-
-function checkTransactionsUpdate() {
- if (!serviceConfig || wsapi === null) return;
-
- wsapi.getBalance().then((balance) => {
- process.send({
- type: 'balanceUpdated',
- data: balance
- });
-
- if (syncState.LAST_BLOCK_COUNT > 1) {
- logDebug('-> txUpdater: checking tx update');
- let currentBLockCount = syncState.LAST_BLOCK_COUNT - 1;
- let startIndex = (!workerState.TX_CHECK_INITIALIZED ? 1 : syncState.TX_LAST_INDEX);
- let searchCount = currentBLockCount;
- let needCountMargin = false;
- let blockMargin = 10;
- if (workerState.TX_CHECK_INITIALIZED) {
- searchCount = (currentBLockCount - syncState.TX_LAST_COUNT);
- needCountMargin = true;
- }
-
- let startIndexWithMargin = (startIndex === 1 ? 1 : (startIndex - blockMargin));
- let searchCountWithMargin = needCountMargin ? searchCount + blockMargin : searchCount;
- let trx_args = {
- firstBlockIndex: startIndexWithMargin,
- blockCount: searchCountWithMargin
- };
- logDebug(`-> txUpdater: args=${JSON.stringify(trx_args)}`);
- wsapi.getTransactions(trx_args).then((trx) => {
- process.send({
- type: 'transactionUpdated',
- data: trx
- });
- saveWallet();
- return true;
- }).catch((err) => {
- logDebug(`-> txUpdater: getTransactions FAILED, ${err.message}`);
- return false;
- });
- workerState.TX_CHECK_INITIALIZED = true;
- syncState.TX_LAST_INDEX = currentBLockCount;
- syncState.TX_LAST_COUNT = currentBLockCount;
- }
- }).catch((err) => {
- logDebug(`-> txUpdater: getBalance FAILED, ${err.message}`);
- return false;
- });
-}
-
-function saveWallet() {
- if (!serviceConfig) return;
- wsapi.save().then(() => {
- logDebug(`-> saveWallet: OK`);
- return true;
- }).catch(() => {
- return false;
- });
-}
-
-function syncWallet() {
- taskWorker = setInterval(() => {
- if (workerState.PAUSED) return;
- logDebug(`Wallet sync tasks...`);
- checkBlockUpdate();
- }, SYNC_INTERVAL);
-}
-
-// {type: 'blah', msg: 'any'}
-process.on('message', (msg) => {
- let cmd = msg || '';
- cmd.type = msg.type || 'cfg';
- cmd.data = msg.data || null;
-
- switch (cmd.type) {
- case 'cfg':
- if (cmd.data) {
- serviceConfig = cmd.data;
- initApi(serviceConfig);
- process.send({
- type: 'serviceStatus',
- data: 'OK'
- });
- }
- if (cmd.debug) {
- DEBUG = true;
- logDebug('Config received.');
- logDebug('Running in debug mode.');
- }
- break;
- case 'start':
- logDebug('Starting');
- try { clearInterval(taskWorker); } catch (err) { }
- // initial block check;
- checkBlockUpdate();
-
- // initial check, only to get balance
- checkTransactionsUpdate();
-
- setTimeout(syncWallet, 5000);
- break;
- case 'pause':
- if (workerState.PAUSED) return;
- logDebug('Got suspend command');
- process.send({
- type: 'blockUpdated',
- data: {
- blockCount: -50,
- knownBlockCount: -50,
- displayBlockCount: -50,
- displayKnownBlockCount: -50,
- syncPercent: -50
- }
- });
- workerState.PAUSED = true;
- break;
- case 'resume':
- logDebug('Got resume command');
- syncState.TX_CHECK_SKIPPED_COUNT = 5;
- wsapi = null;
- initApi(serviceConfig);
- setTimeout(() => {
- wsapi.getBalance().then(() => {
- logDebug(`Warming up: getBalance OK`);
- }).catch((err) => {
- logDebug(`Warming up: getBalance FAILED, ${err.message}`);
- });
- workerState.PAUSED = false;
- }, 15000);
-
- process.send({
- type: 'blockUpdated',
- data: {
- blockCount: -10,
- knownBlockCount: -10,
- displayBlockCount: -10,
- displayKnownBlockCount: -10,
- syncPercent: -10
- }
- });
- break;
- case 'stop':
- logDebug('Got stop command, halting all tasks and exit...');
- syncState.TX_SKIPPED_COUNT = 0;
- serviceConfig = wsapi = null;
- if (taskWorker === undefined || taskWorker === null) {
- try {
- clearInterval(taskWorker);
- process.exit(0);
- } catch (e) {
- logDebug(`FAILED, ${e.message}`);
- process.exit(1);
- }
- }
- break;
- default:
- break;
- }
-});
-
-process.on('uncaughtException', function (err) {
- logDebug(`worker uncaughtException: ${err.message}`);
- process.exit(1);
-});
-
-process.on('disconnect', () => function () {
- logDebug(`worker disconnected`);
- process.exit(1);
-});
\ No newline at end of file
diff --git a/src/js/ws_utils.js b/src/js/ws_utils.js
index 3f5da2b..5440403 100644
--- a/src/js/ws_utils.js
+++ b/src/js/ws_utils.js
@@ -7,11 +7,9 @@ const config = require('./ws_config');
const fnv = require('fnv-plus');
const GCM = require('node-crypto-gcm').GCM;
-const ADDRESS_REGEX_STR = `^(hx|cx)(?=[aA-zZ0-9]*$)(?:.{${config.addressLength - config.addressPrefix.length}})$`;
+const ADDRESS_REGEX_STR = `^(hx|cx)(?=[a-z0-9]*$)(?:.{${config.addressLength - config.addressPrefix.length}})$`;
const ADDRESS_REGEX = new RegExp(ADDRESS_REGEX_STR);
-const PAYMENT_ID_REGEX = new RegExp(/^([aA-zZ0-9]{64})$/);
-const SECRET_KEY_REGEX = new RegExp(/^[aA-zZ0-9]{64}$/);
-const MNEMONIC_SEED_REGEX = new RegExp(/^[aA-zZ]+(?!.* )[a-zA-Z0-9 ]*$/);
+const SECRET_KEY_REGEX = new RegExp(/^[a-z0-9]{64}$/);
/***** * DOM util *****/
exports.triggerEvent = (el, type) => {
@@ -94,7 +92,7 @@ exports.showToast = (msg, duration, elId) => {
}, duration + 100);
}
- blekok.innerText = msg;
+ blekok.innerHTML = msg;
blekok.classList.remove('off');
window.TOASTT = setTimeout(function () {
blekok.classList.add('off');
@@ -167,58 +165,14 @@ exports.genQrDataUrl = (inputStr) => {
return nImg.toDataURL();
};
-let decimalAdjust = (type, value, exp) => {
- if (typeof exp === 'undefined' || +exp === 0) {
- return Math[type](value);
- }
- value = +value;
- exp = +exp;
- if (isNaN(value) || !(typeof exp === 'number' && exp % 1 === 0)) {
- return NaN;
- }
- // Shift
- value = value.toString().split('e');
- value = Math[type](+(value[0] + 'e' + (value[1] ? (+value[1] - exp) : -exp)));
- // Shift back
- value = value.toString().split('e');
- return +(value[0] + 'e' + (value[1] ? (+value[1] + exp) : exp));
-};
-
exports.validateAddress = (address) => {
return ADDRESS_REGEX.test(address);
};
-exports.validatePaymentId = (paymentId) => {
- if (!paymentId) return true; // true allow empty
- return PAYMENT_ID_REGEX.test(paymentId);
-};
-
exports.validateSecretKey = (key) => {
return SECRET_KEY_REGEX.test(key);
};
-exports.validateMnemonic = (seed) => {
- if (!seed) return false;
-
- if (!MNEMONIC_SEED_REGEX.test(seed)) return false;
-
- if (seed.split(' ').length !== 25) return false;
-
- return true;
-};
-
-exports.amountForMortal = (amount) => {
- if (!config.decimalDivisor) return amount;
- let decimalPlaces = config.decimalPlaces || 2;
- return (amount / config.decimalDivisor).toFixed(decimalPlaces);
-};
-
-exports.amountForImmortal = (amount) => {
- if (!config.decimalDivisor) return amount;
- let da = decimalAdjust("round", parseFloat(amount), -(config.decimalPlaces));
- return parseInt(da * config.decimalDivisor);
-};
-
exports.isFileExist = (filePath) => {
if (!filePath) return false;
return fs.existsSync(filePath);
diff --git a/src/js/wsui_main.js b/src/js/wsui_main.js
index 4b46cc0..4aba94c 100644
--- a/src/js/wsui_main.js
+++ b/src/js/wsui_main.js
@@ -1,9 +1,9 @@
/*jshint bitwise: false*/
/* global AbortController */
const os = require('os');
-const net = require('net');
const path = require('path');
const fs = require('fs');
+const superagent = require('superagent');
const { clipboard, remote, ipcRenderer, shell } = require('electron');
const Store = require('electron-store');
const Mousetrap = require('./extras/mousetrap.min.js');
@@ -12,7 +12,6 @@ const wsutil = require('./ws_utils');
const SvalinnSession = require('./ws_session');
const SvalinnManager = require('./ws_manager');
const config = require('./ws_config');
-const async = require('async');
const AgGrid = require('ag-grid-community');
const wsmanager = new SvalinnManager();
const sessConfig = { debug: remote.app.debug, walletConfig: remote.app.walletConfig };
@@ -116,11 +115,7 @@ let importSeedInputPassword;
let importSeedInputMnemonic;
let importSeedInputScanHeight;
// transaction
-let txButtonRefresh;
-let txButtonSortAmount;
let txButtonSortDate;
-let txInputUpdated;
-let txButtonExport;
// misc
let thtml;
let dmswitch;
@@ -145,14 +140,6 @@ function populateElementVars()
// Main section link
sectionButtons = document.querySelectorAll('[data-section]');
- // Settings input & elements
- settingsInputServiceBin = document.getElementById('input-settings-path');
- settingsInputMinToTray = document.getElementById('checkbox-tray-minimize');
- settingsInputCloseToTray = document.getElementById('checkbox-tray-close');
- settingsInputExcludeOfflineNodes = document.getElementById('pubnodes-exclude-offline');
- settingsInputTimeout = document.getElementById('input-settings-timeout');
- settingsButtonSave = document.getElementById('button-settings-save');
-
// Overview pages
overviewWalletAddress = document.getElementById('wallet-address');
overviewWalletCloseButton = document.getElementById('button-overview-closewallet');
@@ -245,7 +232,7 @@ function setDarkMode(dark)
dmswitch.firstChild.dataset.icon = 'sun';
} else {
thtml.classList.remove('dark');
- dmswitch.setAttribute('title', 'Swith to dark mode');
+ dmswitch.setAttribute('title', 'Switch to dark mode');
dmswitch.firstChild.classList.remove('fa-sun');
dmswitch.firstChild.classList.add('fa-moon');
settings.set('darkmode', false);
@@ -269,6 +256,29 @@ function showKeyBindings()
dialog.showModal();
}
+function checkUpdate ()
+{
+ superagent.get('https://api.github.com/repos/iconation/svalinn/releases/latest').end((err, res) => {
+ if (!err && res) {
+ let result = JSON.parse (res.text);
+ let tag = result.tag_name;
+ if (settings.get('version') != tag)
+ {
+ wsutil.showToast ('A new version of Svalinn is available (' + tag + ') ! '
+ + 'Checkout
https://github.com/iconation/svalinn ',
+ 20 * 1000);
+
+ dialog = document.getElementById('belekok');
+ let goLatestRelease = dialog.querySelector ('#go-latest-release-github');
+
+ goLatestRelease.addEventListener('click', (event) => {
+ shell.openExternal ('https://github.com/iconation/Svalinn/releases/latest');
+ });
+ }
+ }
+ });
+}
+
function showAbout()
{
let dialog = document.getElementById('ab-dialog');
@@ -281,10 +291,10 @@ function showAbout()
`;
dialog.innerHTML = info;
dialog.showModal();
-
}
-function switchTab() {
+function switchTab()
+{
if (WALLET_OPEN_IN_PROGRESS) {
wsutil.showToast('Opening wallet in progress, please wait...');
return;
@@ -297,8 +307,6 @@ function switchTab() {
if (!isServiceReady) {
skippedSections = ['section-create-transaction', 'section-send-transaction'];
if (nextSection === 'section-overview') nextSection = 'section-welcome';
- } else if (wsession.get('fusionProgress')) {
- skippedSections = ['section-create-transaction'];
}
while (skippedSections.indexOf(nextSection) >= 0) {
@@ -309,7 +317,8 @@ function switchTab() {
}
// section switcher
-function changeSection(sectionId, targetRedir) {
+function changeSection(sectionId, targetRedir)
+{
wsutil.showToast('');
if (WALLET_OPEN_IN_PROGRESS) {
@@ -320,23 +329,14 @@ function changeSection(sectionId, targetRedir) {
targetRedir = targetRedir === true ? true : false;
let targetSection = sectionId.trim();
- let isSynced = wsession.get('synchronized') || true;
let isServiceReady = wsession.get('serviceReady') || false;
let needServiceReady = ['section-create-transaction', 'section-overview'];
let needServiceStopped = 'section-welcome';
- let needSynced = ['section-create-transaction'];
let origTarget = targetSection;
let finalTarget = targetSection;
let toastMsg = '';
-
- if (needSynced.includes(targetSection) && wsession.get('fusionProgress')) {
- // fusion in progress, return early
- wsutil.showToast('Wallet optimization in progress, please wait');
- return;
- }
-
if (needServiceReady.includes(targetSection) && !isServiceReady) {
// no access to wallet, send, tx when no wallet opened
finalTarget = 'section-welcome';
@@ -344,10 +344,6 @@ function changeSection(sectionId, targetRedir) {
if (!notoast.includes(origTarget)) {
toastMsg = "Please create or open your wallet first !";
}
- } else if (needSynced.includes(targetSection) && !isSynced) {
- // need synced, return early
- wsutil.showToast("Please wait until the syncing completes!");
- return;
} else if (needServiceStopped.includes(targetSection) && isServiceReady) {
finalTarget = 'section-overview';
} else {
@@ -362,9 +358,6 @@ function changeSection(sectionId, targetRedir) {
}
// reset quick filters
- if (finalTarget === 'section-send-transaction' && window.TXOPTSAPI) {
- window.TXOPTSAPI.api.setQuickFilter('');
- }
if (finalTarget === 'section-addressbook' && window.ABOPTSAPI) {
window.ABOPTSAPI.api.setQuickFilter('');
}
@@ -397,38 +390,6 @@ function changeSection(sectionId, targetRedir) {
}
}
-function initNodeSelection(nodeAddr)
-{
-}
-
-// initial settings value or updater
-function initSettingVal(values) {
- values = values || null;
- if (values) {
- // save new settings
- settings.set('service_bin', values.service_bin);
- settings.set('node_address', values.node_address);
- settings.set('tray_minimize', values.tray_minimize);
- settings.set('tray_close', values.tray_close);
- settings.set('service_timeout', values.service_timeout);
- settings.set('pubnodes_exclude_offline', values.pubnodes_exclude_offline);
- }
- settingsInputServiceBin.value = settings.get('service_bin');
- settingsInputMinToTray.checked = settings.get('tray_minimize');
- settingsInputCloseToTray.checked = settings.get('tray_close');
- settingsInputExcludeOfflineNodes.checked = settings.get('pubnodes_exclude_offline');
-
- // if custom node, save it
- let mynode = settings.get('node_address');
- let pnodes = settings.get('pubnodes_data');
- if (!settings.has('pubnodes_custom')) settings.set('pubnodes_custom', []);
- let cnodes = settings.get('pubnodes_custom');
- if (pnodes.indexOf(mynode) === -1 && cnodes.indexOf(mynode) === -1) {
- cnodes.push(mynode);
- settings.set('pubnodes_custom', cnodes);
- }
-}
-
// generic form message reset
function formMessageReset() {
if (!genericFormMessage.length) return;
@@ -453,74 +414,13 @@ function formMessageSet(target, status, txt) {
}
}
-// utility: blank tx filler
-function setTxFiller(show) {
- /*
- show = show || false;
- let fillerRow = document.getElementById('txfiller');
- let txRow = document.getElementById('transaction-lists');
-
- if (!show && fillerRow) {
- fillerRow.classList.add('hidden');
- txRow.classList.remove('hidden');
- } else {
- txRow.classList.add('hidden');
- fillerRow.classList.remove('hidden');
- }
- */
-}
-
// display initial page, settings page on first run, else overview page
function showInitialPage() {
// other initiations here
formMessageReset();
- initSettingVal(); // initial settings value
changeSection('section-welcome');
- settings.set('firstRun', 0);
let versionInfo = document.getElementById('svalinnVersion');
if (versionInfo) versionInfo.innerHTML = WS_VERSION;
- let tsVersionInfo = document.getElementById('turtleServiceVersion');
- if (tsVersionInfo) tsVersionInfo.innerHTML = config.walletServiceBinaryVersion;
-}
-
-// settings page handlers
-function handleSettings() {
- settingsButtonSave.addEventListener('click', function () {
- formMessageReset();
- let serviceBinValue = settingsInputServiceBin.value ? settingsInputServiceBin.value.trim() : '';
- let timeoutValue = settingsInputTimeout.value ? parseInt(settingsInputTimeout.value,10): 30;
-
- if (!serviceBinValue.length) {
- formMessageSet('settings', 'error', `Settings can't be saved, please enter correct values`);
- return false;
- }
-
- if (!wsutil.isRegularFileAndWritable(serviceBinValue)) {
- formMessageSet('settings', 'error', `Unable to find ${config.walletServiceBinaryFilename}, please enter the correct path`);
- return false;
- }
-
- if(timeoutValue < 30 || timeoutValue > 120) {
- formMessageSet('settings', 'error', `Timeout value must be between 0 and 120`);
- return false;
- }
-
- let vals = {
- service_bin: serviceBinValue,
- node_address: settings.get('node_address'),
- service_timeout: timeoutValue,
- tray_minimize: settingsInputMinToTray.checked,
- tray_close: settingsInputCloseToTray.checked,
- pubnodes_exclude_offline: settingsInputExcludeOfflineNodes.checked
- };
-
- initSettingVal(vals);
-
- formMessageReset();
- let goTo = wsession.get('loadedWalletAddress').length ? 'section-overview' : 'section-welcome';
- changeSection(goTo, true);
- wsutil.showToast('Settings have been updated.', 8000);
- });
}
// address book completions
@@ -558,7 +458,6 @@ function initAddressCompletion(data) {
return `Tx. Hash: ${params.data.transactionHash}
- You are connected to a public node (${settings.get('node_address')}) that charges a fee to send transactions.