From 4fc45ee29491835775972585ec26ea1a62dd4e39 Mon Sep 17 00:00:00 2001 From: pbca26 Date: Mon, 18 Dec 2017 23:17:22 +0300 Subject: [PATCH 01/67] kmd rpcbind -> rpcport --- routes/shepherd/daemonControl.js | 38 +++++++++++++++++--------------- 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/routes/shepherd/daemonControl.js b/routes/shepherd/daemonControl.js index 32f0c91..5c58e08 100644 --- a/routes/shepherd/daemonControl.js +++ b/routes/shepherd/daemonControl.js @@ -655,26 +655,28 @@ module.exports = (shepherd) => { }); } - const rpcbind = () => { + const rpcport = () => { return new Promise((resolve, reject) => { - const result = 'checking rpcbind...'; + const result = 'checking rpcport...'; - if (status[0].hasOwnProperty('rpcbind')) { - shepherd.log('rpcbind: OK'); - shepherd.writeLog('rpcbind: OK'); - } else { - shepherd.log('rpcbind: NOT FOUND'); - shepherd.writeLog('rpcbind: NOT FOUND'); + if (flock === 'komodod') { + if (status[0].hasOwnProperty('rpcport')) { + shepherd.log('rpcport: OK'); + shepherd.writeLog('rpcport: OK'); + } else { + shepherd.log('rpcport: NOT FOUND'); + shepherd.writeLog('rpcport: NOT FOUND'); - fs.appendFile(DaemonConfPath, '\nrpcbind=127.0.0.1', (err) => { - if (err) { - shepherd.writeLog(`append daemon conf err: ${err}`); - shepherd.log(`append daemon conf err: ${err}`); - } - // throw err; - shepherd.log('rpcbind: ADDED'); - shepherd.writeLog('rpcbind: ADDED'); - }); + fs.appendFile(DaemonConfPath, '\rpcport=7771', (err) => { + if (err) { + shepherd.writeLog(`append daemon conf err: ${err}`); + shepherd.log(`append daemon conf err: ${err}`); + } + // throw err; + shepherd.log('rpcport: ADDED'); + shepherd.writeLog('rpcport: ADDED'); + }); + } } resolve(result); @@ -764,7 +766,7 @@ module.exports = (shepherd) => { return rpcpass(); }) .then(server) - .then(rpcbind) + .then(rpcport) .then(addnode); }); From 3008f2686324e06b5193ac86ed8eee8fefc21c26 Mon Sep 17 00:00:00 2001 From: pbca26 Date: Tue, 19 Dec 2017 21:21:35 +0300 Subject: [PATCH 02/67] 12 new spv coins --- main.js | 11 +- package.json | 2 +- routes/electrumjs/electrumServers.js | 132 ++++++++- routes/electrumjs/electrumjs.networks.js | 327 +++++++++++++---------- routes/shepherd/addCoinShortcuts.js | 10 +- routes/shepherd/electrum/createtx.js | 31 ++- routes/shepherd/electrum/keys.js | 41 ++- 7 files changed, 389 insertions(+), 165 deletions(-) diff --git a/main.js b/main.js index b15f04a..9cb3651 100644 --- a/main.js +++ b/main.js @@ -56,6 +56,7 @@ app.setVersion(appBasicInfo.version); shepherd.createAgamaDirs(); const appSessionHash = md5(Date.now().toString()); +const _spvFees = shepherd.getSpvFees(); shepherd.writeLog(`app init ${appSessionHash}`); shepherd.writeLog(`app info: ${appBasicInfo.name} ${appBasicInfo.version}`); @@ -407,6 +408,7 @@ function createWindow(status, hideLoadingWindow) { mainWindow.activeSection = 'wallets'; mainWindow.argv = process.argv; mainWindow.getAssetChainPorts = shepherd.getAssetChainPorts; + mainWindow.spvFees = _spvFees; if (appConfig.dev) { mainWindow.loadURL('http://127.0.0.1:3000'); @@ -491,7 +493,9 @@ function createWindow(status, hideLoadingWindow) { let _appClosingInterval; - // shepherd.killRogueProcess('marketmaker'); + if (process.argv.indexOf('dexonly') > -1) { + shepherd.killRogueProcess('marketmaker'); + } if (!Object.keys(shepherd.coindInstanceRegistry).length || !appConfig.stopNativeDaemonsOnQuit) { closeApp(); @@ -527,8 +531,9 @@ app.on('window-all-closed', () => { // Calling event.preventDefault() will prevent the default behaviour, which is terminating the application. app.on('before-quit', (event) => { shepherd.log('before-quit'); - // shepherd.killRogueProcess('marketmaker'); - + if (process.argv.indexOf('dexonly') > -1) { + shepherd.killRogueProcess('marketmaker'); + } /*if (!forceQuitApp && mainWindow === null && loadingWindow != null) { // mainWindow not intitialised and loadingWindow not dereferenced diff --git a/package.json b/package.json index 017b863..1841ae5 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "agama-app", "productName": "Agama", - "version": "0.2.24", + "version": "0.2.25", "description": "Agama Wallet Desktop App", "main": "main.js", "scripts": { diff --git a/routes/electrumjs/electrumServers.js b/routes/electrumjs/electrumServers.js index ba69081..9239a24 100644 --- a/routes/electrumjs/electrumServers.js +++ b/routes/electrumjs/electrumServers.js @@ -1,8 +1,12 @@ let electrumServers = { - /*zcash: { + /*zcash: { 2 bytes address fix is required address: '173.212.225.176', port: 50032, proto: 'tcp', + serverList: [ + '173.212.225.176:50032', + '136.243.45.140:50032' + ], },*/ coqui: { // !estimatefee address: 'electrum1.cipig.net', @@ -169,13 +173,21 @@ let electrumServers = { proto: 'tcp', txfee: 100000000, abbr: 'DOGE', + serverList: [ + '173.212.225.176:50015', + '136.243.45.140:50015' + ], }, viacoin: { // !estimatefee - address: 'vialectrum.bitops.me', - port: 50002, - proto: 'ssl', + address: '173.212.225.176', + port: 50033, + proto: 'tcp', txfee: 100000, abbr: 'VIA', + serverList: [ + '173.212.225.176:50033', + '136.243.45.140:50033' + ], }, vertcoin: { address: '173.212.225.176', @@ -183,6 +195,10 @@ let electrumServers = { proto: 'tcp', txfee: 100000, abbr: 'VTC', + serverList: [ + '173.212.225.176:50088', + '136.243.45.140:50088' + ], }, namecoin: { address: '173.212.225.176', @@ -190,6 +206,10 @@ let electrumServers = { proto: 'tcp', txfee: 100000, abbr: 'NMC', + serverList: [ + '173.212.225.176:50036', + '136.243.45.140:50036' + ], }, monacoin: { // !estimatefee address: '173.212.225.176', @@ -197,13 +217,21 @@ let electrumServers = { proto: 'tcp', txfee: 100000, abbr: 'MONA', + serverList: [ + '173.212.225.176:50002', + '136.243.45.140:50002' + ], }, litecoin: { address: '173.212.225.176', port: 50012, proto: 'tcp', - txfee: 10000, + txfee: 30000, abbr: 'LTC', + serverList: [ + '173.212.225.176:50012', + '136.243.45.140:50012' + ], }, faircoin: { address: '173.212.225.176', @@ -211,13 +239,21 @@ let electrumServers = { proto: 'tcp', txfee: 1000000, abbr: 'FAIR', + serverList: [ + '173.212.225.176:50005', + '136.243.45.140:50005' + ], }, - digibyte: { + dgb: { address: '173.212.225.176', port: 50022, proto: 'tcp', txfee: 100000, abbr: 'DGB', + serverList: [ + '173.212.225.176:50022', + '136.243.45.140:50022' + ], }, dash: { address: '173.212.225.176', @@ -225,6 +261,10 @@ let electrumServers = { proto: 'tcp', txfee: 10000, abbr: 'DASH', + serverList: [ + '173.212.225.176:50098', + '136.243.45.140:50098' + ], }, crown: { address: '173.212.225.176', @@ -232,31 +272,97 @@ let electrumServers = { proto: 'tcp', txfee: 10000, abbr: 'CRW', + serverList: [ + '173.212.225.176:50041', + '136.243.45.140:50041' + ], }, - bitcoin: { - address: '173.212.225.176', - port: 50001, + /*btc: { + address: 'electrum1.cipig.net', + port: 10000, proto: 'tcp', abbr: 'BTC', + serverList: [ + 'electrum1.cipig.net:10000', + 'electrum2.cipig.net:10000' + ], }, + btg: { + address: '173.212.225.176', + port: 10052, + proto: 'tcp', + abbr: 'BTG', + txfee: 10000, + serverList: [ + '173.212.225.176:10052', + '94.130.224.11:10052' + ], + }, + /*blk: { can't decode tx! + address: 'electrum1.cipig.net', + port: 10054, + proto: 'tcp', + abbr: 'BLK', + txfee: 10000, + serverList: [ + 'electrum1.cipig.net:10054', + 'electrum2.cipig.net:10054' + ], + },*/ + sib: { + address: 'electrum1.cipig.net', + port: 10050, + proto: 'tcp', + abbr: 'SIB', + txfee: 10000, + serverList: [ + 'electrum1.cipig.net:10050', + 'electrum2.cipig.net:10050' + ], + }, + /*bch: { + address: 'electrum1.cipig.net', + port: 10051, + proto: 'tcp', + abbr: 'BCH', + txfee: 10000, + serverList: [ + 'electrum1.cipig.net:10051', + 'electrum2.cipig.net:10051' + ], + },*/ argentum: { // !estimatefee address: '173.212.225.176', port: 50081, proto: 'tcp', txfee: 50000, abbr: 'ARG', + serverList: [ + '173.212.225.176:50081', + '136.243.45.140:50081' + ], }, chips: { // !estimatefee - address: '173.212.225.176', - port: 50076, + address: 'electrum1.cipig.net', + port: 10053, proto: 'tcp', txfee: 10000, abbr: 'CHIPS', serverList: [ - '173.212.225.176:50076', - '136.243.45.140:50076' + 'electrum1.cipig.net:10053', + 'electrum2.cipig.net:10053' ], }, }; +electrumServers.crw = electrumServers.crown; +electrumServers.fair = electrumServers.faircoin; +electrumServers.arg = electrumServers.argentum; +electrumServers.ltc = electrumServers.litecoin; +electrumServers.mona = electrumServers.litecoin; +electrumServers.nmc = electrumServers.namecoin; +electrumServers.vtc = electrumServers.vertcoin; +electrumServers.via = electrumServers.viacoin; +electrumServers.doge = electrumServers.dogecoin; + module.exports = electrumServers; \ No newline at end of file diff --git a/routes/electrumjs/electrumjs.networks.js b/routes/electrumjs/electrumjs.networks.js index d49015c..7f1d50a 100644 --- a/routes/electrumjs/electrumjs.networks.js +++ b/routes/electrumjs/electrumjs.networks.js @@ -2,196 +2,249 @@ var bitcoin = require('bitcoinjs-lib'); var networks = exports; -Object.keys(bitcoin.networks).forEach(function(key){ - networks[key] = bitcoin.networks[key] +Object.keys(bitcoin.networks).forEach((key) => { + networks[key] = bitcoin.networks[key]; }); networks.litecoin = { - messagePrefix: '\x19Litecoin Signed Message:\n', - bip32: { - public: 0x019da462, - private: 0x019d9cfe - }, - pubKeyHash: 0x30, - scriptHash: 0x32, - wif: 0xb0, - dustThreshold: 0, // https://github.com/litecoin-project/litecoin/blob/v0.8.7.2/src/main.cpp#L360-L365 + messagePrefix: '\x19Litecoin Signed Message:\n', + bip32: { + public: 0x019da462, + private: 0x019d9cfe + }, + pubKeyHash: 0x30, + scriptHash: 0x32, + wif: 0xb0, + dustThreshold: 0, // https://github.com/litecoin-project/litecoin/blob/v0.8.7.2/src/main.cpp#L360-L365 } networks.dogecoin = { - messagePrefix: '\x19Dogecoin Signed Message:\n', - bip32: { - public: 0x02facafd, - private: 0x02fac398, - }, - pubKeyHash: 0x1e, - scriptHash: 0x16, - wif: 0x9e, - dustThreshold: 0 // https://github.com/dogecoin/dogecoin/blob/v1.7.1/src/core.h#L155-L160 + messagePrefix: '\x19Dogecoin Signed Message:\n', + bip32: { + public: 0x02facafd, + private: 0x02fac398, + }, + pubKeyHash: 0x1e, + scriptHash: 0x16, + wif: 0x9e, + dustThreshold: 0 // https://github.com/dogecoin/dogecoin/blob/v1.7.1/src/core.h#L155-L160 }; // https://github.com/monacoinproject/monacoin/blob/master-0.10/src/chainparams.cpp#L161 networks.monacoin = { - messagePrefix: '\x19Monacoin Signed Message:\n', - bip32: { - public: 0x0488b21e, - private: 0x0488ade4, - }, - pubKeyHash: 0x32, - scriptHash: 0x05, - wif: 0xB2, - dustThreshold: 546, // https://github.com/bitcoin/bitcoin/blob/v0.9.2/src/core.h#L151-L162 + messagePrefix: '\x19Monacoin Signed Message:\n', + bip32: { + public: 0x0488b21e, + private: 0x0488ade4, + }, + pubKeyHash: 0x32, + scriptHash: 0x05, + wif: 0xB2, + dustThreshold: 546, // https://github.com/bitcoin/bitcoin/blob/v0.9.2/src/core.h#L151-L162 }; // https://github.com/gamecredits-project/GameCredits/blob/master/src/chainparams.cpp#L136 networks.game = { - messagePrefix: '\x19GameCredits Signed Message:\n', - bip32: { - public: 0x043587cf, - private: 0x04358394, - }, - pubKeyHash: 0x6f, - scriptHash: 0xc4, - wif: 0xef, - dustThreshold: 546, // https://github.com/bitcoin/bitcoin/blob/v0.9.2/src/core.h#L151-L162 + messagePrefix: '\x19GameCredits Signed Message:\n', + bip32: { + public: 0x043587cf, + private: 0x04358394, + }, + pubKeyHash: 0x6f, + scriptHash: 0xc4, + wif: 0xef, + dustThreshold: 546, // https://github.com/bitcoin/bitcoin/blob/v0.9.2/src/core.h#L151-L162 }; // https://github.com/dashpay/dash/blob/master/src/chainparams.cpp#L171 networks.dash = { - messagePrefix: '\x19DarkCoin Signed Message:\n', - bip32: { - public: 0x02fe52f8, - private: 0x02fe52cc, - }, - pubKeyHash: 0x4c, - scriptHash: 0x10, - wif: 0xcc, - dustThreshold: 5460, // https://github.com/dashpay/dash/blob/v0.12.0.x/src/primitives/transaction.h#L144-L155 + messagePrefix: '\x19DarkCoin Signed Message:\n', + bip32: { + public: 0x02fe52f8, + private: 0x02fe52cc, + }, + pubKeyHash: 0x4c, + scriptHash: 0x10, + wif: 0xcc, + dustThreshold: 5460, // https://github.com/dashpay/dash/blob/v0.12.0.x/src/primitives/transaction.h#L144-L155 }; // https://github.com/zcoinofficial/zcoin/blob/c93eccb39b07a6132cb3d787ac18be406b24c3fa/src/base58.h#L275 networks.zcoin = { - messagePrefix: '\x19ZCoin Signed Message:\n', - bip32: { - public: 0x0488b21e, // todo - private: 0x0488ade4, // todo - }, - pubKeyHash: 0x52, - scriptHash: 0x07, - wif: 0x52 + 128, - dustThreshold: 1000, // https://github.com/zcoinofficial/zcoin/blob/f755f95a036eedfef7c96bcfb6769cb79278939f/src/main.h#L59 + messagePrefix: '\x19ZCoin Signed Message:\n', + bip32: { + public: 0x0488b21e, // todo + private: 0x0488ade4, // todo + }, + pubKeyHash: 0x52, + scriptHash: 0x07, + wif: 0x52 + 128, + dustThreshold: 1000, // https://github.com/zcoinofficial/zcoin/blob/f755f95a036eedfef7c96bcfb6769cb79278939f/src/main.h#L59 }; // https://raw.githubusercontent.com/jl777/komodo/beta/src/chainparams.cpp networks.komodo = { - messagePrefix: '\x19Komodo Signed Message:\n', - bip32: { - public: 0x0488b21e, - private: 0x0488ade4, - }, - pubKeyHash: 0x3c, - scriptHash: 0x55, - wif: 0xbc, - dustThreshold: 1000, + messagePrefix: '\x19Komodo Signed Message:\n', + bip32: { + public: 0x0488b21e, + private: 0x0488ade4, + }, + pubKeyHash: 0x3c, + scriptHash: 0x55, + wif: 0xbc, + dustThreshold: 1000, }; networks.viacoin = { - messagePrefix: '\x19Viacoin Signed Message:\n', - bip32: { - public: 0x0488b21e, - private: 0x0488ade4, - }, - pubKeyHash: 0x47, - scriptHash: 0x21, - wif: 0xc7, - dustThreshold: 1000, + messagePrefix: '\x19Viacoin Signed Message:\n', + bip32: { + public: 0x0488b21e, + private: 0x0488ade4, + }, + pubKeyHash: 0x47, + scriptHash: 0x21, + wif: 0xc7, + dustThreshold: 1000, }; networks.vertcoin = { - messagePrefix: '\x19Vertcoin Signed Message:\n', - bip32: { - public: 0x0488b21e, - private: 0x0488ade4, - }, - pubKeyHash: 0x47, - scriptHash: 0x5, - wif: 0x80, - dustThreshold: 1000, + messagePrefix: '\x19Vertcoin Signed Message:\n', + bip32: { + public: 0x0488b21e, + private: 0x0488ade4, + }, + pubKeyHash: 0x47, + scriptHash: 0x5, + wif: 0x80, + dustThreshold: 1000, }; networks.namecoin = { - messagePrefix: '\x19Namecoin Signed Message:\n', - bip32: { - public: 0x0488b21e, - private: 0x0488ade4, - }, - pubKeyHash: 0x34, - scriptHash: 0xd, - wif: 0xb4, - dustThreshold: 1000, + messagePrefix: '\x19Namecoin Signed Message:\n', + bip32: { + public: 0x0488b21e, + private: 0x0488ade4, + }, + pubKeyHash: 0x34, + scriptHash: 0xd, + wif: 0xb4, + dustThreshold: 1000, }; networks.faircoin = { - messagePrefix: '\x19Faircoin Signed Message:\n', - bip32: { - public: 0x0488b21e, - private: 0x0488ade4, - }, - pubKeyHash: 0x5f, - scriptHash: 0x24, - wif: 0xdf, - dustThreshold: 1000, + messagePrefix: '\x19Faircoin Signed Message:\n', + bip32: { + public: 0x0488b21e, + private: 0x0488ade4, + }, + pubKeyHash: 0x5f, + scriptHash: 0x24, + wif: 0xdf, + dustThreshold: 1000, }; networks.digibyte = { - messagePrefix: '\x19Digibyte Signed Message:\n', - bip32: { - public: 0x0488b21e, - private: 0x0488ade4, - }, - pubKeyHash: 0x1e, - scriptHash: 0x5, - wif: 0x80, - dustThreshold: 1000, + messagePrefix: '\x19Digibyte Signed Message:\n', + bip32: { + public: 0x0488b21e, + private: 0x0488ade4, + }, + pubKeyHash: 0x1e, + scriptHash: 0x5, + wif: 0x80, + dustThreshold: 1000, }; networks.crown = { - messagePrefix: '\x19Crown Signed Message:\n', - bip32: { - public: 0x0488b21e, - private: 0x0488ade4, - }, - pubKeyHash: 0x0, - scriptHash: 0x1c, - wif: 0x80, - dustThreshold: 1000, + messagePrefix: '\x19Crown Signed Message:\n', + bip32: { + public: 0x0488b21e, + private: 0x0488ade4, + }, + pubKeyHash: 0x0, + scriptHash: 0x1c, + wif: 0x80, + dustThreshold: 1000, }; networks.argentum = { - messagePrefix: '\x19Argentum Signed Message:\n', - bip32: { - public: 0x0488b21e, - private: 0x0488ade4, - }, - pubKeyHash: 0x17, - scriptHash: 0x5, - wif: 0x97, - dustThreshold: 1000, + messagePrefix: '\x19Argentum Signed Message:\n', + bip32: { + public: 0x0488b21e, + private: 0x0488ade4, + }, + pubKeyHash: 0x17, + scriptHash: 0x5, + wif: 0x97, + dustThreshold: 1000, }; networks.chips = { - messagePrefix: '\x19Chips Signed Message:\n', - bip32: { - public: 0x0488b21e, - private: 0x0488ade4, - }, - pubKeyHash: 0x3c, - scriptHash: 0x55, - wif: 0xbc, - dustThreshold: 1000, + messagePrefix: '\x19Chips Signed Message:\n', + bip32: { + public: 0x0488b21e, + private: 0x0488ade4, + }, + pubKeyHash: 0x3c, + scriptHash: 0x55, + wif: 0xbc, + dustThreshold: 1000, +}; + +networks.btg = { + messagePrefix: '\x19BitcoinGold Signed Message:\n', + bip32: { + public: 0x0488b21e, + private: 0x0488ade4, + }, + pubKeyHash: 0x26, + scriptHash: 0x17, + wif: 0x80, + dustThreshold: 1000, +}; + +networks.bch = { + messagePrefix: '\x19BitcoinCash Signed Message:\n', + bip32: { + public: 0x0488b21e, + private: 0x0488ade4, + }, + pubKeyHash: 0x0, + scriptHash: 0x5, + wif: 0x80, + dustThreshold: 1000, +}; + +networks.blk = { + messagePrefix: '\x19BlackCoin Signed Message:\n', + bip32: { + public: 0x0488b21e, + private: 0x0488ade4, + }, + pubKeyHash: 0x19, + scriptHash: 0x55, + wif: 0x99, + dustThreshold: 1000, }; +networks.sib = { + messagePrefix: '\x19SibCoin Signed Message:\n', + bip32: { + public: 0x0488b21e, + private: 0x0488ade4, + }, + pubKeyHash: 0x3f, + scriptHash: 0x28, + wif: 0x80, + dustThreshold: 1000, +}; + +networks.btc = networks.bitcoin; +networks.crw = networks.crown; +networks.dgb = networks.digibyte; +networks.arg = networks.argentum; + /*networks.zcash = { messagePrefix: '\x19Zcash Signed Message:\n', bip32: { diff --git a/routes/shepherd/addCoinShortcuts.js b/routes/shepherd/addCoinShortcuts.js index 7232d37..d3af01e 100644 --- a/routes/shepherd/addCoinShortcuts.js +++ b/routes/shepherd/addCoinShortcuts.js @@ -1,3 +1,5 @@ +const electrumServers = require('../electrumjs/electrumServers'); + module.exports = (shepherd) => { shepherd.startSPV = (coin) => { if (coin === 'KMD+REVS+JUMBLR') { @@ -5,7 +7,13 @@ module.exports = (shepherd) => { shepherd.addElectrumCoin('REVS'); shepherd.addElectrumCoin('JUMBLR'); } else { - shepherd.addElectrumCoin(coin); + if (process.argv.indexOf('spvcoins=all/add-all') > -1) { + for (let key in electrumServers) { + shepherd.addElectrumCoin(electrumServers[key].abbr); + } + } else { + shepherd.addElectrumCoin(coin); + } } } diff --git a/routes/shepherd/electrum/createtx.js b/routes/shepherd/electrum/createtx.js index 8c9c4d6..3478ab1 100644 --- a/routes/shepherd/electrum/createtx.js +++ b/routes/shepherd/electrum/createtx.js @@ -106,9 +106,9 @@ module.exports = (shepherd) => { const ecl = new shepherd.electrumJSCore(shepherd.electrumServers[network].port, shepherd.electrumServers[network].address, shepherd.electrumServers[network].proto); // tcp or tls const outputAddress = req.query.address; const changeAddress = req.query.change; - let value = Number(req.query.value); const push = req.query.push; - const fee = shepherd.electrumServers[network].txfee; + let fee = shepherd.electrumServers[network].txfee; + let value = Number(req.query.value); let wif = req.query.wif; if (req.query.gui) { @@ -163,12 +163,27 @@ module.exports = (shepherd) => { shepherd.log('targets =>', true); shepherd.log(targets, true); - const feeRate = 20; // sats/byte + const feeRate = shepherd.getNetworkData(network).messagePrefix === '\x19Komodo Signed Message:\n' || shepherd.getNetworkData(network).messagePrefix === '\x19Chips Signed Message:\n' ? 20 : 0; // sats/byte + + if (!feeRate) { + targets[0].value = targets[0].value + fee; + } + + shepherd.log(`fee rate ${feeRate}`, true); + shepherd.log(`default fee ${fee}`, true); + shepherd.log(`targets ==>`, true); + shepherd.log(targets, true); // default coin selection algo blackjack with fallback to accumulative // make a first run, calc approx tx fee // if ins and outs are empty reduce max spend by txfee - let { inputs, outputs, fee } = shepherd.coinSelect(utxoListFormatted, targets, feeRate); + const firstRun = shepherd.coinSelect(utxoListFormatted, targets, feeRate); + let inputs = firstRun.inputs; + let outputs = firstRun.outputs; + + if (feeRate) { + fee = firstRun.fee; + } shepherd.log('coinselect res =>', true); shepherd.log('coinselect inputs =>', true); @@ -204,6 +219,14 @@ module.exports = (shepherd) => { _change = outputs[1].value; } + // non komodo coins, subtract fee from output value + if (!feeRate) { + outputs[0].value = outputs[0].value - fee; + + shepherd.log('non komodo adjusted outputs, value - default fee =>', true); + shepherd.log(outputs, true); + } + // check if any outputs are unverified if (inputs && inputs.length) { diff --git a/routes/shepherd/electrum/keys.js b/routes/shepherd/electrum/keys.js index ff49d89..c347a12 100644 --- a/routes/shepherd/electrum/keys.js +++ b/routes/shepherd/electrum/keys.js @@ -1,4 +1,6 @@ const sha256 = require('js-sha256'); +const bip39 = require('bip39'); +const crypto = require('crypto'); module.exports = (shepherd) => { shepherd.seedToWif = (seed, network, iguana) => { @@ -32,10 +34,10 @@ module.exports = (shepherd) => { key.compressed = true; - // shepherd.log(`seed: ${seed}`, true); - // shepherd.log(`network ${network}`, true); - // shepherd.log(`seedtowif priv key ${key.privateWif}`, true); - // shepherd.log(`seedtowif pub key ${key.publicAddress}`, true); + /*shepherd.log(`seed: ${seed}`, true); + shepherd.log(`network ${network}`, true); + shepherd.log(`seedtowif priv key ${key.privateWif}`, true); + shepherd.log(`seedtowif pub key ${key.publicAddress}`, true);*/ return { priv: key.privateWif, @@ -43,6 +45,23 @@ module.exports = (shepherd) => { }; } + shepherd.get('/electrum/wiftopub', (req, res, next) => { + let key = shepherd.bitcoinJS.ECPair.fromWIF(req.query.wif, shepherd.electrumJSNetworks[req.query.coin]); + keys = { + priv: key.toWIF(), + pub: key.getAddress(), + }; + + const successObj = { + msg: 'success', + result: { + keys, + }, + }; + + res.end(JSON.stringify(successObj)); + }); + shepherd.get('/electrum/seedtowif', (req, res, next) => { const keys = shepherd.seedToWif(req.query.seed, req.query.network, req.query.iguana); @@ -92,9 +111,19 @@ module.exports = (shepherd) => { res.end(JSON.stringify(successObj)); }); + shepherd.getSpvFees = () => { + let _fees = {}; + + for (let key in shepherd.electrumServers) { + if (shepherd.electrumServers[key].txfee) { + _fees[shepherd.electrumServers[key].abbr] = shepherd.electrumServers[key].txfee; + } + } + + return _fees; + }; + shepherd.post('/electrum/seed/bip39/match', (req, res, next) => { - const bip39 = require('bip39'); // npm i -S bip39 - const crypto = require('crypto'); const seed = bip39.mnemonicToSeed(req.body.seed); const hdMaster = shepherd.bitcoinJS.HDNode.fromSeedBuffer(seed, shepherd.electrumJSNetworks.komodo); // seed from above const matchPattern = req.body.match; From d5e5648d19cc731fbfde92ee6c1f372c4927805c Mon Sep 17 00:00:00 2001 From: pbca26 Date: Tue, 19 Dec 2017 21:22:14 +0300 Subject: [PATCH 03/67] version bump --- version | 4 ++-- version_build | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/version b/version index 97d8e39..01b0e67 100644 --- a/version +++ b/version @@ -1,3 +1,3 @@ -version=0.2.0.25e -type=e-beta +version=0.2.0.25f +type=f-beta minversion=0.2.0.2 \ No newline at end of file diff --git a/version_build b/version_build index 857b972..8ce7c05 100644 --- a/version_build +++ b/version_build @@ -1 +1 @@ -0.2.0.25e-beta \ No newline at end of file +0.2.0.25f-beta \ No newline at end of file From e3c0082e06eb08a9a1752d556cb99df4a68ede9c Mon Sep 17 00:00:00 2001 From: pbca26 Date: Wed, 20 Dec 2017 13:25:54 +0300 Subject: [PATCH 04/67] bch, btg support --- package.json | 2 + routes/electrumjs/electrumServers.js | 6 +- routes/shepherd/electrum/createtx.js | 103 +++++++++++++++++++++++---- 3 files changed, 96 insertions(+), 15 deletions(-) diff --git a/package.json b/package.json index 1841ae5..94e1645 100644 --- a/package.json +++ b/package.json @@ -30,6 +30,8 @@ "arch": "^2.1.0", "bip39": "^2.4.0", "bitcoinjs-lib": "^3.2.0", + "bitcoinjs-lib-bch": "git://github.com/bitcoinjs/bitcoinjs-lib#opt-in-bitcoincash-sighash", + "bitcoinjs-lib-zcash": "git://github.com/karel-3d/bitcoinjs-lib#zcash", "bluebird": "^3.4.7", "body-parser": "^1.15.2", "buffer-reverse": "^1.0.1", diff --git a/routes/electrumjs/electrumServers.js b/routes/electrumjs/electrumServers.js index 9239a24..2329a1d 100644 --- a/routes/electrumjs/electrumServers.js +++ b/routes/electrumjs/electrumServers.js @@ -286,7 +286,7 @@ let electrumServers = { 'electrum1.cipig.net:10000', 'electrum2.cipig.net:10000' ], - }, + },*/ btg: { address: '173.212.225.176', port: 10052, @@ -320,7 +320,7 @@ let electrumServers = { 'electrum2.cipig.net:10050' ], }, - /*bch: { + bch: { address: 'electrum1.cipig.net', port: 10051, proto: 'tcp', @@ -330,7 +330,7 @@ let electrumServers = { 'electrum1.cipig.net:10051', 'electrum2.cipig.net:10051' ], - },*/ + }, argentum: { // !estimatefee address: '173.212.225.176', port: 50081, diff --git a/routes/shepherd/electrum/createtx.js b/routes/shepherd/electrum/createtx.js index 3478ab1..a87da8a 100644 --- a/routes/shepherd/electrum/createtx.js +++ b/routes/shepherd/electrum/createtx.js @@ -1,7 +1,17 @@ +const bitcoinJSForks = require('bitcoinforksjs-lib'); + module.exports = (shepherd) => { // unsigned tx shepherd.buildUnsignedTx = (sendTo, changeAddress, network, utxo, changeValue, spendValue) => { - let tx = new shepherd.bitcoinJS.TransactionBuilder(shepherd.getNetworkData(network)); + let tx; + + if (network === 'btg') { + shepherd.log('enable btg'); + tx = new bitcoinJSForks.TransactionBuilder(shepherd.getNetworkData(network)); + tx.enableBitcoinGold(true); + } else { + tx = new shepherd.bitcoinJS.TransactionBuilder(shepherd.getNetworkData(network)); + } shepherd.log('buildSignedTx'); // console.log(`buildSignedTx priv key ${wif}`); @@ -86,6 +96,60 @@ module.exports = (shepherd) => { return rawtx; } + // btg + shepherd.buildSignedTxForks = (sendTo, changeAddress, wif, network, utxo, changeValue, spendValue) => { + let tx; + + if (network === 'btg' || + network === 'bch') { + tx = new bitcoinJSForks.TransactionBuilder(shepherd.getNetworkData(network)); + } + + const keyPair = bitcoinJSForks.ECPair.fromWIF(wif, shepherd.getNetworkData(network)); + const pk = bitcoinJSForks.crypto.hash160(keyPair.getPublicKeyBuffer()); + const spk = bitcoinJSForks.script.pubKeyHash.output.encode(pk); + + shepherd.log(`buildSignedTx${network.toUpperCase()}`); + + for (let i = 0; i < utxo.length; i++) { + tx.addInput(utxo[i].txid, utxo[i].vout, bitcoinJSForks.Transaction.DEFAULT_SEQUENCE, spk); + } + + tx.addOutput(sendTo, Number(spendValue)); + + if (changeValue > 0) { + tx.addOutput(changeAddress, Number(changeValue)); + } + + if (network === 'btg') { + tx.enableBitcoinGold(true); + } else if (network === 'bch') { + tx.enableBitcoinCash(true); + } + + tx.setVersion(2); + + shepherd.log('buildSignedTx unsigned tx data vin', true); + shepherd.log(tx.tx.ins, true); + shepherd.log('buildSignedTx unsigned tx data vout', true); + shepherd.log(tx.tx.outs, true); + shepherd.log('buildSignedTx unsigned tx data', true); + shepherd.log(tx, true); + + const hashType = bitcoinJSForks.Transaction.SIGHASH_ALL | bitcoinJSForks.Transaction.SIGHASH_BITCOINCASHBIP143; + + for (let i = 0; i < utxo.length; i++) { + tx.sign(i, keyPair, null, hashType, utxo[i].value); + } + + const rawtx = tx.build().toHex(); + + shepherd.log('buildSignedTx signed tx hex', true); + shepherd.log(rawtx, true); + + return rawtx; + } + shepherd.maxSpendBalance = (utxoList, fee) => { let maxSpendBalance = 0; @@ -101,7 +165,7 @@ module.exports = (shepherd) => { } shepherd.get('/electrum/createrawtx', (req, res, next) => { - // txid 64 char + // TODO: unconf output(s) error message const network = req.query.network || shepherd.findNetworkObj(req.query.coin); const ecl = new shepherd.electrumJSCore(shepherd.electrumServers[network].port, shepherd.electrumServers[network].address, shepherd.electrumServers[network].proto); // tcp or tls const outputAddress = req.query.address; @@ -123,7 +187,9 @@ module.exports = (shepherd) => { ecl.close(); if (utxoList && - utxoList.length) { + utxoList.length && + utxoList[0] && + utxoList[0].txid) { let utxoListFormatted = []; let totalInterest = 0; let totalInterestUTXOCount = 0; @@ -316,15 +382,28 @@ module.exports = (shepherd) => { value ); } else { - _rawtx = shepherd.buildSignedTx( - outputAddress, - changeAddress, - wif, - network, - inputs, - _change, - value - ); + if (network === 'btg' || + network === 'bch') { + _rawtx = shepherd.buildSignedTxForks( + outputAddress, + changeAddress, + wif, + network, + inputs, + _change, + value + ); + } else { + _rawtx = shepherd.buildSignedTx( + outputAddress, + changeAddress, + wif, + network, + inputs, + _change, + value + ); + } } if (!push || From 04841e71782b3bed9a167dcb3931776eba306fc9 Mon Sep 17 00:00:00 2001 From: pbca26 Date: Wed, 20 Dec 2017 15:59:32 +0300 Subject: [PATCH 05/67] version bump --- version | 4 ++-- version_build | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/version b/version index 01b0e67..6186073 100644 --- a/version +++ b/version @@ -1,3 +1,3 @@ -version=0.2.0.25f -type=f-beta +version=0.2.0.25g +type=g-beta minversion=0.2.0.2 \ No newline at end of file diff --git a/version_build b/version_build index 8ce7c05..424197b 100644 --- a/version_build +++ b/version_build @@ -1 +1 @@ -0.2.0.25f-beta \ No newline at end of file +0.2.0.25g-beta \ No newline at end of file From ef3efbd4e293aeaf84c59af78c97ad3c96f83d00 Mon Sep 17 00:00:00 2001 From: pbca26 Date: Wed, 20 Dec 2017 17:15:57 +0300 Subject: [PATCH 06/67] bitcoinforksjs lib name change --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 94e1645..0c496b8 100644 --- a/package.json +++ b/package.json @@ -30,7 +30,7 @@ "arch": "^2.1.0", "bip39": "^2.4.0", "bitcoinjs-lib": "^3.2.0", - "bitcoinjs-lib-bch": "git://github.com/bitcoinjs/bitcoinjs-lib#opt-in-bitcoincash-sighash", + "bitcoinforksjs-lib": "git://github.com/bitcoinjs/bitcoinjs-lib#opt-in-bitcoincash-sighash", "bitcoinjs-lib-zcash": "git://github.com/karel-3d/bitcoinjs-lib#zcash", "bluebird": "^3.4.7", "body-parser": "^1.15.2", From b4e7effa5741bd8dbe8ae82de4bf63af96464c46 Mon Sep 17 00:00:00 2001 From: pbca26 Date: Mon, 25 Dec 2017 02:21:16 +0300 Subject: [PATCH 07/67] zec, hush spv --- package.json | 4 +- routes/electrumjs/electrumServers.js | 35 +++-- routes/electrumjs/electrumjs.networks.js | 37 ++++-- .../electrumjs/electrumjs.txdecoder-2bytes.js | 120 ++++++++++++++++++ routes/shepherd.js | 2 +- routes/shepherd/daemonControl.js | 91 +++++++------ routes/shepherd/electrum/balance.js | 2 +- routes/shepherd/electrum/createtx.js | 5 +- routes/shepherd/electrum/keys.js | 34 ++--- routes/shepherd/electrum/listunspent.js | 5 +- routes/shepherd/electrum/merkle.js | 4 +- routes/shepherd/electrum/network.js | 13 ++ routes/shepherd/electrum/transactions.js | 6 +- 13 files changed, 260 insertions(+), 98 deletions(-) create mode 100644 routes/electrumjs/electrumjs.txdecoder-2bytes.js diff --git a/package.json b/package.json index 0c496b8..2c76e0e 100644 --- a/package.json +++ b/package.json @@ -28,14 +28,14 @@ "dependencies": { "adm-zip": "^0.4.7", "arch": "^2.1.0", + "bigi": "^1.4.2", "bip39": "^2.4.0", - "bitcoinjs-lib": "^3.2.0", "bitcoinforksjs-lib": "git://github.com/bitcoinjs/bitcoinjs-lib#opt-in-bitcoincash-sighash", + "bitcoinjs-lib": "^3.2.0", "bitcoinjs-lib-zcash": "git://github.com/karel-3d/bitcoinjs-lib#zcash", "bluebird": "^3.4.7", "body-parser": "^1.15.2", "buffer-reverse": "^1.0.1", - "coinkey": "^2.0.0", "coinselect": "github:bitcoinjs/coinselect", "electron": "1.6.5", "express": "^4.14.0", diff --git a/routes/electrumjs/electrumServers.js b/routes/electrumjs/electrumServers.js index 2329a1d..6cb351f 100644 --- a/routes/electrumjs/electrumServers.js +++ b/routes/electrumjs/electrumServers.js @@ -1,13 +1,4 @@ let electrumServers = { - /*zcash: { 2 bytes address fix is required - address: '173.212.225.176', - port: 50032, - proto: 'tcp', - serverList: [ - '173.212.225.176:50032', - '136.243.45.140:50032' - ], - },*/ coqui: { // !estimatefee address: 'electrum1.cipig.net', port: 10011, @@ -298,7 +289,7 @@ let electrumServers = { '94.130.224.11:10052' ], }, - /*blk: { can't decode tx! + blk: { // can't decode tx! address: 'electrum1.cipig.net', port: 10054, proto: 'tcp', @@ -308,7 +299,7 @@ let electrumServers = { 'electrum1.cipig.net:10054', 'electrum2.cipig.net:10054' ], - },*/ + }, sib: { address: 'electrum1.cipig.net', port: 10050, @@ -353,6 +344,28 @@ let electrumServers = { 'electrum2.cipig.net:10053' ], }, + zec: { + address: '173.212.225.176', + port: 50032, + proto: 'tcp', + txfee: 10000, + abbr: 'ZEC', + serverList: [ + '173.212.225.176:50032', + '136.243.45.140:50032' + ], + }, + hush: { + address: '173.212.225.176', + port: 50013, + proto: 'tcp', + txfee: 10000, + abbr: 'HUSH', + serverList: [ + '173.212.225.176:50013', + '136.243.45.140:50013' + ], + }, }; electrumServers.crw = electrumServers.crown; diff --git a/routes/electrumjs/electrumjs.networks.js b/routes/electrumjs/electrumjs.networks.js index 7f1d50a..e82295c 100644 --- a/routes/electrumjs/electrumjs.networks.js +++ b/routes/electrumjs/electrumjs.networks.js @@ -240,19 +240,32 @@ networks.sib = { dustThreshold: 1000, }; +networks.zcash = { + messagePrefix: '\x19Zcash Signed Message:\n', + bip32: { + public: 0x0488b21e, + private: 0x05358394, + }, + pubKeyHash: 0x1cb8, + scriptHash: 0x1cbd, + wif: 0x80, + dustThreshold: 1000, +}; + +networks.hush = { + messagePrefix: '\Hush Signed Message:\n', + bip32: { + public: 0x0488b21e, + private: 0x0488ade4, + }, + pubKeyHash: 0x1cb8, + scriptHash: 0x1cbd, + wif: 0x80, + dustThreshold: 1000, +}; + networks.btc = networks.bitcoin; networks.crw = networks.crown; networks.dgb = networks.digibyte; networks.arg = networks.argentum; - -/*networks.zcash = { - messagePrefix: '\x19Zcash Signed Message:\n', - bip32: { - public: 0x0488b21e, - private: 0x0488ade4, - }, - pubKeyHash: 0x1cb8, - scriptHash: 0x1cbd, - wif: 0x80, - dustThreshold: 1000, -};*/ \ No newline at end of file +networks.zec = networks.zcash; \ No newline at end of file diff --git a/routes/electrumjs/electrumjs.txdecoder-2bytes.js b/routes/electrumjs/electrumjs.txdecoder-2bytes.js new file mode 100644 index 0000000..f96199a --- /dev/null +++ b/routes/electrumjs/electrumjs.txdecoder-2bytes.js @@ -0,0 +1,120 @@ +/* +MIT License + +Copyright (c) 2017 Yuki Akiyama, SuperNET + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +var bitcoin = require('bitcoinjs-lib-zcash'); + +var decodeFormat = function(tx) { + var result = { + txid: tx.getId(), + version: tx.version, + locktime: tx.locktime, + }; + + return result; +} + +var decodeInput = function(tx) { + var result = []; + + tx.ins.forEach(function(input, n) { + var vin = { + txid: input.hash.reverse().toString('hex'), + n: input.index, + script: bitcoin.script.toASM(input.script), + sequence: input.sequence, + }; + + result.push(vin); + }); + + return result; +} + +var decodeOutput = function(tx, network) { + var format = function(out, n, network) { + var vout = { + satoshi: out.value, + value: (1e-8 * out.value).toFixed(8), + n: n, + scriptPubKey: { + asm: bitcoin.script.toASM(out.script), + hex: out.script.toString('hex'), + type: bitcoin.script.classifyOutput(out.script), + addresses: [], + }, + }; + + switch(vout.scriptPubKey.type) { + case 'pubkeyhash': + vout.scriptPubKey.addresses.push(bitcoin.address.fromOutputScript(out.script, network)); + break; + case 'pubkey': + const pubKeyBuffer = new Buffer(vout.scriptPubKey.asm.split(' ')[0], 'hex'); + vout.scriptPubKey.addresses.push(bitcoin.ECPair.fromPublicKeyBuffer(pubKeyBuffer, network).getAddress()); + break; + case 'scripthash': + vout.scriptPubKey.addresses.push(bitcoin.address.fromOutputScript(out.script, network)); + break; + } + + return vout; + } + + var result = []; + + tx.outs.forEach(function(out, n) { + result.push(format(out, n, network)); + }); + + return result; +} + +var TxDecoder = module.exports = function(rawtx, network) { + try { + const _tx = bitcoin.Transaction.fromHex(rawtx); + + return { + tx: _tx, + network: network, + format: decodeFormat(_tx), + inputs: decodeInput(_tx), + outputs: decodeOutput(_tx, network), + }; + } catch (e) { + return false; + } +} + +TxDecoder.prototype.decode = function() { + var result = {}; + var self = this; + + Object.keys(self.format).forEach(function(key) { + result[key] = self.format[key]; + }); + + result.outputs = self.outputs; + + return result; +} \ No newline at end of file diff --git a/routes/shepherd.js b/routes/shepherd.js index ee070b7..fa38930 100644 --- a/routes/shepherd.js +++ b/routes/shepherd.js @@ -18,7 +18,6 @@ shepherd.Promise = require('bluebird'); shepherd.exec = require('child_process').exec; shepherd.execFile = require('child_process').execFile; shepherd.sha256 = require('sha256'); -shepherd.CoinKey = require('coinkey'); shepherd.bitcoinJS = require('bitcoinjs-lib'); shepherd.coinSelect = require('coinselect'); shepherd.fixPath = require('fix-path'); @@ -63,6 +62,7 @@ shepherd.electrumKeys = {}; shepherd.electrumJSCore = require('./electrumjs/electrumjs.core.js'); shepherd.electrumJSNetworks = require('./electrumjs/electrumjs.networks.js'); shepherd.electrumJSTxDecoder = require('./electrumjs/electrumjs.txdecoder.js'); +shepherd.electrumJSTxDecoderZ = require('./electrumjs/electrumjs.txdecoder-2bytes.js'); shepherd.electrumServers = require('./electrumjs/electrumServers.js'); shepherd.CONNECTION_ERROR_OR_INCOMPLETE_DATA = 'connection error or incomplete data'; diff --git a/routes/shepherd/daemonControl.js b/routes/shepherd/daemonControl.js index 5c58e08..9bb0143 100644 --- a/routes/shepherd/daemonControl.js +++ b/routes/shepherd/daemonControl.js @@ -11,6 +11,7 @@ const md5 = require('../md5.js'); module.exports = (shepherd) => { const getConf = (flock, coind) => { + const _platform = os.platform(); let DaemonConfPath = ''; let nativeCoindDir; @@ -23,7 +24,7 @@ module.exports = (shepherd) => { shepherd.writeLog(`getconf flock: ${flock}`); if (coind) { - switch (os.platform()) { + switch (_platform) { case 'darwin': nativeCoindDir = `${process.env.HOME}/Library/Application Support/${shepherd.nativeCoindList[coind.toLowerCase()].bin}`; break; @@ -39,29 +40,29 @@ module.exports = (shepherd) => { switch (flock) { case 'komodod': DaemonConfPath = shepherd.komodoDir; - if (os.platform() === 'win32') { + if (_platform === 'win32') { DaemonConfPath = path.normalize(DaemonConfPath); shepherd.log('===>>> SHEPHERD API OUTPUT ===>>>'); } break; case 'zcashd': DaemonConfPath = shepherd.ZcashDir; - if (os.platform() === 'win32') { + if (_platform === 'win32') { DaemonConfPath = path.normalize(DaemonConfPath); } break; case 'chipsd': DaemonConfPath = shepherd.chipsDir; - if (os.platform() === 'win32') { + if (_platform === 'win32') { DaemonConfPath = path.normalize(DaemonConfPath); } break; case 'coind': - DaemonConfPath = os.platform() === 'win32' ? shepherd.path.normalize(`${shepherd.coindRootDir}/${coind.toLowerCase()}`) : `${shepherd.coindRootDir}/${coind.toLowerCase()}`; + DaemonConfPath = _platform === 'win32' ? shepherd.path.normalize(`${shepherd.coindRootDir}/${coind.toLowerCase()}`) : `${shepherd.coindRootDir}/${coind.toLowerCase()}`; break; default: DaemonConfPath = `${shepherd.komodoDir}/${flock}`; - if (os.platform() === 'win32') { + if (_platform === 'win32') { DaemonConfPath = shepherd.path.normalize(DaemonConfPath); } } @@ -482,57 +483,58 @@ module.exports = (shepherd) => { } const setConf = (flock, coind) => { + const _platform = os.platform(); let nativeCoindDir; let DaemonConfPath; shepherd.log(flock); shepherd.writeLog(`setconf ${flock}`); - if (os.platform() === 'darwin') { - nativeCoindDir = coind ? `${process.env.HOME}/Library/Application Support/${shepherd.nativeCoindList[coind.toLowerCase()].bin}` : null; - } - - if (os.platform() === 'linux') { - nativeCoindDir = coind ? `${process.env.HOME}/.${shepherd.nativeCoindList[coind.toLowerCase()].bin.toLowerCase()}` : null; - } - - if (os.platform() === 'win32') { - nativeCoindDir = coind ? `${process.env.APPDATA}/${shepherd.nativeCoindList[coind.toLowerCase()].bin}` : null; + switch (_platform) { + case 'darwin': + nativeCoindDir = coind ? `${process.env.HOME}/Library/Application Support/${shepherd.nativeCoindList[coind.toLowerCase()].bin}` : null; + break; + case 'linux': + nativeCoindDir = coind ? `${process.env.HOME}/.${shepherd.nativeCoindList[coind.toLowerCase()].bin.toLowerCase()}` : null; + break; + case 'win32': + nativeCoindDir = coind ? `${process.env.APPDATA}/${shepherd.nativeCoindList[coind.toLowerCase()].bin}` : null; + break; } switch (flock) { case 'komodod': DaemonConfPath = `${shepherd.komodoDir}/komodo.conf`; - if (os.platform() === 'win32') { + if (_platform === 'win32') { DaemonConfPath = path.normalize(DaemonConfPath); } break; case 'zcashd': DaemonConfPath = `${shepherd.ZcashDir}/zcash.conf`; - if (os.platform() === 'win32') { + if (_platform === 'win32') { DaemonConfPath = path.normalize(DaemonConfPath); } break; case 'chipsd': DaemonConfPath = `${shepherd.chipsDir}/chips.conf`; - if (os.platform() === 'win32') { + if (_platform === 'win32') { DaemonConfPath = path.normalize(DaemonConfPath); } break; case 'coind': DaemonConfPath = `${nativeCoindDir}/${shepherd.nativeCoindList[coind.toLowerCase()].bin.toLowerCase()}.conf`; - if (os.platform() === 'win32') { + if (_platform === 'win32') { DaemonConfPath = path.normalize(DaemonConfPath); } break; default: DaemonConfPath = `${shepherd.komodoDir}/${flock}/${flock}.conf`; - if (os.platform() === 'win32') { + if (_platform === 'win32') { DaemonConfPath = path.normalize(DaemonConfPath); } } @@ -790,14 +792,17 @@ module.exports = (shepherd) => { * params: herd */ shepherd.post('/herd', (req, res) => { - shepherd.log('======= req.body ======='); - shepherd.log(req.body); + const _body = req.body; + shepherd.log('herd req.body =>'); + shepherd.log(_body); - if (req.body.options && + if (_body.options && !shepherd.kmdMainPassiveMode) { const testCoindPort = (skipError) => { + const _acName = req.body.options.ac_name; + if (!shepherd.lockDownAddCoin) { - const _port = shepherd.assetChainPorts[req.body.options.ac_name]; + const _port = shepherd.assetChainPorts[_acName]; portscanner.checkPortStatus(_port, '127.0.0.1', (error, status) => { // Status is 'open' if currently in use or 'closed' if available @@ -808,13 +813,13 @@ module.exports = (shepherd) => { shepherd.writeLog(`komodod service start error at port ${_port}, reason: port is closed`); shepherd.io.emit('service', { komodod: { - error: `error starting ${req.body.herd} ${req.body.options.ac_name} daemon. Port ${_port} is already taken!`, + error: `error starting ${_body.herd} ${_acName} daemon. Port ${_port} is already taken!`, }, }); const obj = { msg: 'error', - result: `error starting ${req.body.herd} ${req.body.options.ac_name} daemon. Port ${_port} is already taken!`, + result: `error starting ${_body.herd} ${_acName} daemon. Port ${_port} is already taken!`, }; res.status(500); @@ -825,7 +830,7 @@ module.exports = (shepherd) => { } } else { if (!skipError) { - herder(req.body.herd, req.body.options); + herder(_body.herd, _body.options); const obj = { msg: 'success', @@ -842,14 +847,14 @@ module.exports = (shepherd) => { } } - if (req.body.herd === 'komodod') { + if (_body.herd === 'komodod') { // check if komodod instance is already running testCoindPort(); setTimeout(() => { testCoindPort(true); }, 10000); } else { - herder(req.body.herd, req.body.options, req.body.coind); + herder(_body.herd, _body.options, _body.coind); const obj = { msg: 'success', @@ -860,7 +865,7 @@ module.exports = (shepherd) => { } } else { // (?) - herder(req.body.herd, req.body.options); + herder(_body.herd, _body.options); const obj = { msg: 'success', @@ -875,14 +880,16 @@ module.exports = (shepherd) => { * type: POST */ shepherd.post('/setconf', (req, res) => { - shepherd.log('======= req.body ======='); - shepherd.log(req.body); + const _body = req.body; + + shepherd.log('setconf req.body =>'); + shepherd.log(_body); if (os.platform() === 'win32' && - req.body.chain == 'komodod') { + _body.chain == 'komodod') { setkomodoconf = spawn(path.join(__dirname, '../assets/bin/win64/genkmdconf.bat')); } else { - shepherd.setConf(req.body.chain); + shepherd.setConf(_body.chain); } const obj = { @@ -897,15 +904,15 @@ module.exports = (shepherd) => { * type: POST */ shepherd.post('/getconf', (req, res) => { - shepherd.log('======= req.body ======='); - shepherd.log(req.body); + const _body = req.body; + + shepherd.log('getconf req.body =>'); + shepherd.log(_body); - const confpath = getConf(req.body.chain, req.body.coind); + const confpath = getConf(_body.chain, _body.coind); - shepherd.log('got conf path is:'); - shepherd.log(confpath); - shepherd.writeLog('got conf path is:'); - shepherd.writeLog(confpath); + shepherd.log(`getconf path is: ${confpath}`); + shepherd.writeLog(`getconf path is: ${confpath}`); const obj = { msg: 'success', diff --git a/routes/shepherd/electrum/balance.js b/routes/shepherd/electrum/balance.js index 9291a7f..5f9b099 100644 --- a/routes/shepherd/electrum/balance.js +++ b/routes/shepherd/electrum/balance.js @@ -45,7 +45,7 @@ module.exports = (shepherd) => { // decode tx const _network = shepherd.getNetworkData(network); - const decodedTx = shepherd.electrumJSTxDecoder(_rawtxJSON, _network); + const decodedTx = shepherd.isZcash(network) ? shepherd.electrumJSTxDecoderZ(_rawtxJSON, _network) : shepherd.electrumJSTxDecoder(_rawtxJSON, _network); if (decodedTx && decodedTx.format && diff --git a/routes/shepherd/electrum/createtx.js b/routes/shepherd/electrum/createtx.js index a87da8a..f109f84 100644 --- a/routes/shepherd/electrum/createtx.js +++ b/routes/shepherd/electrum/createtx.js @@ -1,4 +1,5 @@ const bitcoinJSForks = require('bitcoinforksjs-lib'); +const bitcoinZcash = require('bitcoinjs-lib-zcash'); module.exports = (shepherd) => { // unsigned tx @@ -52,8 +53,8 @@ module.exports = (shepherd) => { // single sig shepherd.buildSignedTx = (sendTo, changeAddress, wif, network, utxo, changeValue, spendValue) => { - let key = shepherd.bitcoinJS.ECPair.fromWIF(wif, shepherd.getNetworkData(network)); - let tx = new shepherd.bitcoinJS.TransactionBuilder(shepherd.getNetworkData(network)); + let key = shepherd.isZcash(network) ? bitcoinZcash.ECPair.fromWIF(wif, shepherd.getNetworkData(network)) : shepherd.bitcoinJS.ECPair.fromWIF(wif, shepherd.getNetworkData(network)); + let tx = shepherd.isZcash(network) ? new bitcoinZcash.TransactionBuilder(shepherd.getNetworkData(network)) : new shepherd.bitcoinJS.TransactionBuilder(shepherd.getNetworkData(network)); shepherd.log('buildSignedTx'); // console.log(`buildSignedTx priv key ${wif}`); diff --git a/routes/shepherd/electrum/keys.js b/routes/shepherd/electrum/keys.js index c347a12..6ad3eb5 100644 --- a/routes/shepherd/electrum/keys.js +++ b/routes/shepherd/electrum/keys.js @@ -1,6 +1,9 @@ const sha256 = require('js-sha256'); const bip39 = require('bip39'); const crypto = require('crypto'); +const bigi = require('bigi'); +const bitcoinZcash = require('bitcoinjs-lib-zcash'); +const bitcoin = require('bitcoinjs-lib'); module.exports = (shepherd) => { shepherd.seedToWif = (seed, network, iguana) => { @@ -19,30 +22,19 @@ module.exports = (shepherd) => { bytes[31] |= 64; } - const toHexString = (byteArray) => { - return Array.from(byteArray, (byte) => { - return ('0' + (byte & 0xFF).toString(16)).slice(-2); - }).join(''); - } - - const hex = toHexString(bytes); - - const key = new shepherd.CoinKey(new Buffer(hex, 'hex'), { - private: shepherd.getNetworkData(network).wif, - public: shepherd.getNetworkData(network).pubKeyHash, - }); - - key.compressed = true; + const d = bigi.fromBuffer(bytes); + const keyPair = shepherd.isZcash(network) ? new bitcoinZcash.ECPair(d, null, { network: shepherd.getNetworkData(network) }) : new bitcoinZcash.ECPair(d, null, { network: shepherd.getNetworkData(network) }); + const keys = { + pub: keyPair.getAddress(), + priv: keyPair.toWIF(), + }; /*shepherd.log(`seed: ${seed}`, true); shepherd.log(`network ${network}`, true); - shepherd.log(`seedtowif priv key ${key.privateWif}`, true); - shepherd.log(`seedtowif pub key ${key.publicAddress}`, true);*/ + shepherd.log(`seedtowif priv key ${keys.priv}`, true); + shepherd.log(`seedtowif pub key ${keys.pub}`, true);*/ - return { - priv: key.privateWif, - pub: key.publicAddress, - }; + return keys; } shepherd.get('/electrum/wiftopub', (req, res, next) => { @@ -63,7 +55,7 @@ module.exports = (shepherd) => { }); shepherd.get('/electrum/seedtowif', (req, res, next) => { - const keys = shepherd.seedToWif(req.query.seed, req.query.network, req.query.iguana); + let keys = shepherd.seedToWif(req.query.seed, req.query.network, req.query.iguana); const successObj = { msg: 'success', diff --git a/routes/shepherd/electrum/listunspent.js b/routes/shepherd/electrum/listunspent.js index b0a645b..b3262e0 100644 --- a/routes/shepherd/electrum/listunspent.js +++ b/routes/shepherd/electrum/listunspent.js @@ -36,7 +36,7 @@ module.exports = (shepherd) => { // decode tx const _network = shepherd.getNetworkData(network); - const decodedTx = shepherd.electrumJSTxDecoder(_rawtxJSON, _network); + const decodedTx = shepherd.isZcash(network) ? shepherd.electrumJSTxDecoderZ(_rawtxJSON, _network) : shepherd.electrumJSTxDecoder(_rawtxJSON, _network); shepherd.log('decoded tx =>', true); shepherd.log(decodedTx, true); @@ -71,7 +71,8 @@ module.exports = (shepherd) => { if (verify) { shepherd.verifyMerkleByCoin(shepherd.findCoinName(network), _utxoItem['tx_hash'], _utxoItem.height) .then((verifyMerkleRes) => { - if (verifyMerkleRes && verifyMerkleRes === shepherd.CONNECTION_ERROR_OR_INCOMPLETE_DATA) { + if (verifyMerkleRes && + verifyMerkleRes === shepherd.CONNECTION_ERROR_OR_INCOMPLETE_DATA) { verifyMerkleRes = false; } diff --git a/routes/shepherd/electrum/merkle.js b/routes/shepherd/electrum/merkle.js index b3fbe03..5f428e9 100644 --- a/routes/shepherd/electrum/merkle.js +++ b/routes/shepherd/electrum/merkle.js @@ -2,11 +2,11 @@ module.exports = (shepherd) => { // get merkle root shepherd.getMerkleRoot = (txid, proof, pos) => { const reverse = require('buffer-reverse'); - let hash = txid; - let serialized; const _sha256 = (data) => { return shepherd.crypto.createHash('sha256').update(data).digest(); } + let hash = txid; + let serialized; shepherd.log(`getMerkleRoot txid ${txid}`, true); shepherd.log(`getMerkleRoot pos ${pos}`, true); diff --git a/routes/shepherd/electrum/network.js b/routes/shepherd/electrum/network.js index ad37672..0937079 100644 --- a/routes/shepherd/electrum/network.js +++ b/routes/shepherd/electrum/network.js @@ -1,4 +1,17 @@ module.exports = (shepherd) => { + shepherd.isZcash = (network) => { + if (network === 'ZEC' || + network === 'zec' || + network === 'zcash' || + network === 'ZCASH' || + network === 'HUSH' || + network === 'hush' || + network === 'blk' || + network === 'BLK') { + return true; + } + }; + shepherd.getNetworkData = (network) => { const coin = shepherd.findNetworkObj(network) || shepherd.findNetworkObj(network.toUpperCase()) || shepherd.findNetworkObj(network.toLowerCase()); const coinUC = coin ? coin.toUpperCase() : null; diff --git a/routes/shepherd/electrum/transactions.js b/routes/shepherd/electrum/transactions.js index df5725f..8142f0f 100644 --- a/routes/shepherd/electrum/transactions.js +++ b/routes/shepherd/electrum/transactions.js @@ -69,9 +69,10 @@ module.exports = (shepherd) => { // decode tx const _network = shepherd.getNetworkData(network); - const decodedTx = shepherd.electrumJSTxDecoder(_rawtxJSON, _network); + const decodedTx = shepherd.isZcash(network) ? shepherd.electrumJSTxDecoderZ(_rawtxJSON, _network) : shepherd.electrumJSTxDecoder(_rawtxJSON, _network); let txInputs = []; + shepherd.log(`decodedtx network ${network}`, true); shepherd.log('decodedtx =>', true); shepherd.log(decodedTx.outputs, true); @@ -83,7 +84,7 @@ module.exports = (shepherd) => { if (_decodedInput.txid !== '0000000000000000000000000000000000000000000000000000000000000000') { ecl.blockchainTransactionGet(_decodedInput.txid) .then((rawInput) => { - const decodedVinVout = shepherd.electrumJSTxDecoder(rawInput, _network); + const decodedVinVout = shepherd.isZcash(network) ? shepherd.electrumJSTxDecoderZ(rawInput, _network) : shepherd.electrumJSTxDecoder(rawInput, _network); shepherd.log('electrum raw input tx ==>', true); @@ -352,6 +353,7 @@ module.exports = (shepherd) => { shepherd.log('electrum decoderawtx input tx ==>', true); + if (req.query.parseonly || decodedTx.inputs[0].txid === '0000000000000000000000000000000000000000000000000000000000000000') { const successObj = { From f348f50e85caea416f6f346a36e0b545068b741c Mon Sep 17 00:00:00 2001 From: pbca26 Date: Mon, 25 Dec 2017 02:50:56 +0300 Subject: [PATCH 08/67] version bump --- version | 4 ++-- version_build | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/version b/version index 6186073..2ded27d 100644 --- a/version +++ b/version @@ -1,3 +1,3 @@ -version=0.2.0.25g -type=g-beta +version=0.2.0.25h +type=h-beta minversion=0.2.0.2 \ No newline at end of file diff --git a/version_build b/version_build index 424197b..227e03f 100644 --- a/version_build +++ b/version_build @@ -1 +1 @@ -0.2.0.25g-beta \ No newline at end of file +0.2.0.25h-beta \ No newline at end of file From dd937ab198a92efaaef9251e0134feff0e03ecf8 Mon Sep 17 00:00:00 2001 From: pbca26 Date: Mon, 25 Dec 2017 22:54:17 +0300 Subject: [PATCH 09/67] tx decoder wrapper; spv pos coins support --- gui/EasyDEX-GUI | 2 +- package.json | 5 +- routes/electrumjs/electrumjs.networks.js | 1 + routes/electrumjs/electrumjs.txdecoder-pos.js | 124 ++++++++++++++++++ routes/shepherd.js | 2 - routes/shepherd/electrum/balance.js | 2 +- routes/shepherd/electrum/createtx.js | 30 ++++- routes/shepherd/electrum/interest.js | 2 +- routes/shepherd/electrum/listunspent.js | 2 +- routes/shepherd/electrum/network.js | 27 +++- routes/shepherd/electrum/transactions.js | 14 +- version | 4 +- version_build | 2 +- 13 files changed, 194 insertions(+), 23 deletions(-) create mode 100644 routes/electrumjs/electrumjs.txdecoder-pos.js diff --git a/gui/EasyDEX-GUI b/gui/EasyDEX-GUI index 0092ac5..ba9ec3a 160000 --- a/gui/EasyDEX-GUI +++ b/gui/EasyDEX-GUI @@ -1 +1 @@ -Subproject commit 0092ac50871b6964e6462f3ba68ac7d1cd8c1421 +Subproject commit ba9ec3ad4d56a9454648b7396afcd16aadc61456 diff --git a/package.json b/package.json index 2c76e0e..5041db4 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,9 @@ "agama", "SuperNET", "komodo", - "pax" + "multicoin", + "wallet", + "spv" ], "author": "SuperNET", "license": "MIT", @@ -33,6 +35,7 @@ "bitcoinforksjs-lib": "git://github.com/bitcoinjs/bitcoinjs-lib#opt-in-bitcoincash-sighash", "bitcoinjs-lib": "^3.2.0", "bitcoinjs-lib-zcash": "git://github.com/karel-3d/bitcoinjs-lib#zcash", + "bitcoinjs-lib-pos": "git://github.com/KomodoPlatform/bitcoinjs-lib-pos", "bluebird": "^3.4.7", "body-parser": "^1.15.2", "buffer-reverse": "^1.0.1", diff --git a/routes/electrumjs/electrumjs.networks.js b/routes/electrumjs/electrumjs.networks.js index e82295c..fcb3848 100644 --- a/routes/electrumjs/electrumjs.networks.js +++ b/routes/electrumjs/electrumjs.networks.js @@ -226,6 +226,7 @@ networks.blk = { scriptHash: 0x55, wif: 0x99, dustThreshold: 1000, + isPoS: true, }; networks.sib = { diff --git a/routes/electrumjs/electrumjs.txdecoder-pos.js b/routes/electrumjs/electrumjs.txdecoder-pos.js new file mode 100644 index 0000000..849a1ad --- /dev/null +++ b/routes/electrumjs/electrumjs.txdecoder-pos.js @@ -0,0 +1,124 @@ +/* +MIT License + +Copyright (c) 2017 Yuki Akiyama, SuperNET + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +var bitcoin = require('bitcoinjs-lib-pos'); +var script = require('bitcoinjs-lib-pos/src/script'); +var address = require('bitcoinjs-lib-pos/src/address'); +var bitcoinJS = require('bitcoinjs-lib'); + +var decodeFormat = function(tx) { + var result = { + txid: tx.getId(), + version: tx.version, + locktime: tx.locktime, + }; + + return result; +} + +var decodeInput = function(tx) { + var result = []; + + tx.ins.forEach(function(input, n) { + var vin = { + txid: input.hash.reverse().toString('hex'), + n: input.index, + script: script.fromHex(input.hash), + sequence: input.sequence, + }; + + result.push(vin); + }); + + return result; +} + +var decodeOutput = function(tx, network) { + var format = function(out, n, network) { + var vout = { + satoshi: out.value, + value: (1e-8 * out.value).toFixed(8), + n: n, + scriptPubKey: { + asm: bitcoinJS.script.toASM(out.script.chunks), + hex: out.script.toHex(), + type: bitcoin.scripts.classifyOutput(out.script), + addresses: [], + }, + }; + + switch(vout.scriptPubKey.type) { + case 'pubkeyhash': + vout.scriptPubKey.addresses.push(address.fromOutputScript(out.script, network)); + break; + case 'pubkey': + const pubKeyBuffer = new Buffer(vout.scriptPubKey.asm.split(' ')[0], 'hex'); + vout.scriptPubKey.addresses.push(bitcoin.ECPair.fromPublicKeyBuffer(pubKeyBuffer, network).getAddress()); + break; + case 'scripthash': + vout.scriptPubKey.addresses.push(address.fromOutputScript(out.script, network)); + break; + } + +console.log(vout); + return vout; + } + + var result = []; + + tx.outs.forEach(function(out, n) { + result.push(format(out, n, network)); + }); + + return result; +} + +var TxDecoder = module.exports = function(rawtx, network) { + try { + const _tx = bitcoin.Transaction.fromHex(rawtx, network); + + return { + tx: _tx, + network: network, + format: decodeFormat(_tx), + inputs: decodeInput(_tx), + outputs: decodeOutput(_tx, network), + }; + } catch (e) { + return false; + } +} + +TxDecoder.prototype.decode = function() { + var result = {}; + var self = this; + + Object.keys(self.format).forEach(function(key) { + result[key] = self.format[key]; + }); + + result.outputs = self.outputs; + + return result; +} \ No newline at end of file diff --git a/routes/shepherd.js b/routes/shepherd.js index fa38930..9d5c26b 100644 --- a/routes/shepherd.js +++ b/routes/shepherd.js @@ -61,8 +61,6 @@ shepherd.electrumKeys = {}; shepherd.electrumJSCore = require('./electrumjs/electrumjs.core.js'); shepherd.electrumJSNetworks = require('./electrumjs/electrumjs.networks.js'); -shepherd.electrumJSTxDecoder = require('./electrumjs/electrumjs.txdecoder.js'); -shepherd.electrumJSTxDecoderZ = require('./electrumjs/electrumjs.txdecoder-2bytes.js'); shepherd.electrumServers = require('./electrumjs/electrumServers.js'); shepherd.CONNECTION_ERROR_OR_INCOMPLETE_DATA = 'connection error or incomplete data'; diff --git a/routes/shepherd/electrum/balance.js b/routes/shepherd/electrum/balance.js index 5f9b099..f77bd60 100644 --- a/routes/shepherd/electrum/balance.js +++ b/routes/shepherd/electrum/balance.js @@ -45,7 +45,7 @@ module.exports = (shepherd) => { // decode tx const _network = shepherd.getNetworkData(network); - const decodedTx = shepherd.isZcash(network) ? shepherd.electrumJSTxDecoderZ(_rawtxJSON, _network) : shepherd.electrumJSTxDecoder(_rawtxJSON, _network); + const decodedTx = shepherd.electrumJSTxDecoder(_rawtxJSON, network, _network); if (decodedTx && decodedTx.format && diff --git a/routes/shepherd/electrum/createtx.js b/routes/shepherd/electrum/createtx.js index f109f84..376248f 100644 --- a/routes/shepherd/electrum/createtx.js +++ b/routes/shepherd/electrum/createtx.js @@ -1,11 +1,13 @@ const bitcoinJSForks = require('bitcoinforksjs-lib'); const bitcoinZcash = require('bitcoinjs-lib-zcash'); +const bitcoinPos = require('bitcoinjs-lib-pos'); module.exports = (shepherd) => { // unsigned tx shepherd.buildUnsignedTx = (sendTo, changeAddress, network, utxo, changeValue, spendValue) => { let tx; + // TODO: finish unsigned for zcash, btc forks and pos coins if (network === 'btg') { shepherd.log('enable btg'); tx = new bitcoinJSForks.TransactionBuilder(shepherd.getNetworkData(network)); @@ -54,7 +56,15 @@ module.exports = (shepherd) => { // single sig shepherd.buildSignedTx = (sendTo, changeAddress, wif, network, utxo, changeValue, spendValue) => { let key = shepherd.isZcash(network) ? bitcoinZcash.ECPair.fromWIF(wif, shepherd.getNetworkData(network)) : shepherd.bitcoinJS.ECPair.fromWIF(wif, shepherd.getNetworkData(network)); - let tx = shepherd.isZcash(network) ? new bitcoinZcash.TransactionBuilder(shepherd.getNetworkData(network)) : new shepherd.bitcoinJS.TransactionBuilder(shepherd.getNetworkData(network)); + let tx; + + if (shepherd.isZcash(network)) { + tx = new bitcoinZcash.TransactionBuilder(shepherd.getNetworkData(network)); + } else if (shepherd.isPos(network)) { + tx = new bitcoinPos.TransactionBuilder(shepherd.getNetworkData(network)); + } else { + tx = new shepherd.bitcoinJS.TransactionBuilder(shepherd.getNetworkData(network)); + } shepherd.log('buildSignedTx'); // console.log(`buildSignedTx priv key ${wif}`); @@ -65,10 +75,18 @@ module.exports = (shepherd) => { tx.addInput(utxo[i].txid, utxo[i].vout); } - tx.addOutput(sendTo, Number(spendValue)); + if (shepherd.isPos(network)) { + tx.addOutput(sendTo, Number(spendValue), shepherd.getNetworkData(network)); + } else { + tx.addOutput(sendTo, Number(spendValue)); + } if (changeValue > 0) { - tx.addOutput(changeAddress, Number(changeValue)); + if (shepherd.isPos(network)) { + tx.addOutput(changeAddress, Number(changeValue), shepherd.getNetworkData(network)); + } else { + tx.addOutput(changeAddress, Number(changeValue)); + } } if (network === 'komodo' || @@ -86,7 +104,11 @@ module.exports = (shepherd) => { shepherd.log(tx, true); for (let i = 0; i < utxo.length; i++) { - tx.sign(i, key); + if (shepherd.isPos(network)) { + tx.sign(shepherd.getNetworkData(network), i, key); + } else { + tx.sign(i, key); + } } const rawtx = tx.build().toHex(); diff --git a/routes/shepherd/electrum/interest.js b/routes/shepherd/electrum/interest.js index 8a954e7..aaeef34 100644 --- a/routes/shepherd/electrum/interest.js +++ b/routes/shepherd/electrum/interest.js @@ -19,7 +19,7 @@ module.exports = (shepherd) => { } timestampDiffMinutes -= 59; - shepherd.log(`minutes if statement ${timestampDiffMinutes}`, true); + // shepherd.log(`minutes if statement ${timestampDiffMinutes}`, true); // TODO: check if interest is > 5% yr // calc ytd and 5% for 1 yr diff --git a/routes/shepherd/electrum/listunspent.js b/routes/shepherd/electrum/listunspent.js index b3262e0..180135f 100644 --- a/routes/shepherd/electrum/listunspent.js +++ b/routes/shepherd/electrum/listunspent.js @@ -36,7 +36,7 @@ module.exports = (shepherd) => { // decode tx const _network = shepherd.getNetworkData(network); - const decodedTx = shepherd.isZcash(network) ? shepherd.electrumJSTxDecoderZ(_rawtxJSON, _network) : shepherd.electrumJSTxDecoder(_rawtxJSON, _network); + const decodedTx = shepherd.electrumJSTxDecoder(_rawtxJSON, network, _network); shepherd.log('decoded tx =>', true); shepherd.log(decodedTx, true); diff --git a/routes/shepherd/electrum/network.js b/routes/shepherd/electrum/network.js index 0937079..e201cfa 100644 --- a/routes/shepherd/electrum/network.js +++ b/routes/shepherd/electrum/network.js @@ -1,3 +1,9 @@ +const txDecoder = { + default: require('../../electrumjs/electrumjs.txdecoder.js'), + zcash: require('../../electrumjs/electrumjs.txdecoder-2bytes.js'), + pos: require('../../electrumjs/electrumjs.txdecoder-pos.js'), +}; + module.exports = (shepherd) => { shepherd.isZcash = (network) => { if (network === 'ZEC' || @@ -5,13 +11,28 @@ module.exports = (shepherd) => { network === 'zcash' || network === 'ZCASH' || network === 'HUSH' || - network === 'hush' || - network === 'blk' || - network === 'BLK') { + network === 'hush') { + return true; + } + }; + + shepherd.isPos = (network) => { + if (network === 'BLK' || + network === 'blk') { return true; } }; + shepherd.electrumJSTxDecoder = (rawtx, networkName, network) => { + if (shepherd.isZcash(networkName)) { + return txDecoder.zcash(rawtx, network); + } else if (shepherd.isPos(networkName)) { + return txDecoder.pos(rawtx, network); + } else { + return txDecoder.default(rawtx, network); + } + }; + shepherd.getNetworkData = (network) => { const coin = shepherd.findNetworkObj(network) || shepherd.findNetworkObj(network.toUpperCase()) || shepherd.findNetworkObj(network.toLowerCase()); const coinUC = coin ? coin.toUpperCase() : null; diff --git a/routes/shepherd/electrum/transactions.js b/routes/shepherd/electrum/transactions.js index 8142f0f..a309d7d 100644 --- a/routes/shepherd/electrum/transactions.js +++ b/routes/shepherd/electrum/transactions.js @@ -69,7 +69,7 @@ module.exports = (shepherd) => { // decode tx const _network = shepherd.getNetworkData(network); - const decodedTx = shepherd.isZcash(network) ? shepherd.electrumJSTxDecoderZ(_rawtxJSON, _network) : shepherd.electrumJSTxDecoder(_rawtxJSON, _network); + const decodedTx = shepherd.electrumJSTxDecoder(_rawtxJSON, network, _network); let txInputs = []; shepherd.log(`decodedtx network ${network}`, true); @@ -84,7 +84,7 @@ module.exports = (shepherd) => { if (_decodedInput.txid !== '0000000000000000000000000000000000000000000000000000000000000000') { ecl.blockchainTransactionGet(_decodedInput.txid) .then((rawInput) => { - const decodedVinVout = shepherd.isZcash(network) ? shepherd.electrumJSTxDecoderZ(rawInput, _network) : shepherd.electrumJSTxDecoder(rawInput, _network); + const decodedVinVout = shepherd.electrumJSTxDecoder(rawInput, network, _network); shepherd.log('electrum raw input tx ==>', true); @@ -348,12 +348,12 @@ module.exports = (shepherd) => { shepherd.get('/electrum/decoderawtx', (req, res, next) => { const _network = shepherd.getNetworkData(req.query.network); const _rawtx = req.query.rawtx; - // const _rawtx = '0100000001dd6d064f5665f8454293ecaa9dbb55accf4f7e443d35f3b5ab7760f54b6c15fe000000006a473044022056355585a4a501ec9afc96aa5df124cf29ad3ac6454b47cd07cd7d89ec95ec2b022074c4604ee349d30e5336f210598e4dc576bf16ebeb67eeac3f4e82f56e930fee012103b90ba01af308757054e0484bb578765d5df59c4a57adbb94e2419df5e7232a63feffffff0289fc923b000000001976a91424af38fcb13bbc171b0b42bb017244a53b6bb2fa88ac20a10700000000001976a9142f4c0f91fc06ac228c120aee41741d0d3909683288ac49258b58'; - const decodedTx = shepherd.electrumJSTxDecoder(_rawtx, _network); + console.log(_network); + //const _rawtx = '010000006f2c395a02d81487fc7f9d1be3ea900316730133c044af70cd76d21e988e71de0e9e85918f010000006a47304402202097acd391e1d0eaaf91844bd596e918fb71320e3e0c51554acb71a39e4ee98b0220548fd61d4ae77a08d70b01bf5340983a1ba63f6b71ad71d478af77011f96fd510121031ffc010d8abc4180b4c1a13962bf9153a78082e7f2ac18f7d14cb6a6634ca218feffffff2b31f6c9a7916f7cf128cae94b3fc10e4c74ca3a740e1a7a6fd6624e4e9a5c8b010000006a473044022063f014c5fbaa7614732e0ae486179a854215fc32c02230e13f69b7e81fa000e50220236a2ba6373b1854aafc59c5391ab7505062067f3d293c016cbb5d252b35a56a012102f307f17d282fc0eabf99227c2e0f3122ae9ecd7da0de099f0c6007d4c941b57bfeffffff021b797ad7120000001976a914c7a7142d743b3e6eebe76923f43bae477d3ce31a88acff086d66000000001976a91463800ff36b9c52b2ffe5564af1c2a38df4f0126788ac16381d00'; + const decodedTx = shepherd.electrumJSTxDecoder(_rawtx, req.query.network, _network); shepherd.log('electrum decoderawtx input tx ==>', true); - if (req.query.parseonly || decodedTx.inputs[0].txid === '0000000000000000000000000000000000000000000000000000000000000000') { const successObj = { @@ -373,12 +373,14 @@ module.exports = (shepherd) => { const ecl = new shepherd.electrumJSCore(shepherd.electrumServers[req.query.network].port, shepherd.electrumServers[req.query.network].address, shepherd.electrumServers[req.query.network].proto); // tcp or tls ecl.connect(); + shepherd.log(decodedTx.inputs[0]); + shepherd.log(decodedTx.inputs[0].txid); ecl.blockchainTransactionGet(decodedTx.inputs[0].txid) .then((json) => { ecl.close(); shepherd.log(json, true); - const decodedVin = shepherd.electrumJSTxDecoder(json, _network); + const decodedVin = shepherd.electrumJSTxDecoder(json, req.query.network, _network); const successObj = { msg: 'success', diff --git a/version b/version index 2ded27d..ef2859a 100644 --- a/version +++ b/version @@ -1,3 +1,3 @@ -version=0.2.0.25h -type=h-beta +version=0.2.0.25i +type=i-beta minversion=0.2.0.2 \ No newline at end of file diff --git a/version_build b/version_build index 227e03f..abb893b 100644 --- a/version_build +++ b/version_build @@ -1 +1 @@ -0.2.0.25h-beta \ No newline at end of file +0.2.0.25i-beta \ No newline at end of file From 3f313277b004f13088bfcc8f62d483d9580c78a9 Mon Sep 17 00:00:00 2001 From: pbca26 Date: Tue, 26 Dec 2017 20:11:32 +0300 Subject: [PATCH 10/67] spv export keys fix --- routes/shepherd/electrum/balance.js | 1 + routes/shepherd/electrum/keys.js | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/routes/shepherd/electrum/balance.js b/routes/shepherd/electrum/balance.js index f77bd60..2f2be33 100644 --- a/routes/shepherd/electrum/balance.js +++ b/routes/shepherd/electrum/balance.js @@ -141,5 +141,6 @@ module.exports = (shepherd) => { } }); }); + return shepherd; }; \ No newline at end of file diff --git a/routes/shepherd/electrum/keys.js b/routes/shepherd/electrum/keys.js index 6ad3eb5..6c4b3ca 100644 --- a/routes/shepherd/electrum/keys.js +++ b/routes/shepherd/electrum/keys.js @@ -69,6 +69,7 @@ module.exports = (shepherd) => { shepherd.post('/electrum/keys', (req, res, next) => { let _matchingKeyPairs = 0; + let _totalKeys = 0; let _electrumKeys = {}; for (let key in shepherd.electrumServers) { @@ -79,6 +80,7 @@ module.exports = (shepherd) => { shepherd.electrumKeys[_abbr].priv === priv) { _matchingKeyPairs++; } + _totalKeys++; } if (req.body.active) { @@ -93,11 +95,9 @@ module.exports = (shepherd) => { _electrumKeys = shepherd.electrumKeys; } - // shepherd.log(JSON.stringify(_electrumKeys, null, '\t'), true); - const successObj = { msg: 'success', - result: _matchingKeyPairs === Object.keys(shepherd.electrumKeys).length ? _electrumKeys : false, + result: _matchingKeyPairs === _totalKeys ? _electrumKeys : false, }; res.end(JSON.stringify(successObj)); From 8f8627e27f09bd20f35dde5f2bb01fb529b508de Mon Sep 17 00:00:00 2001 From: pbca26 Date: Wed, 27 Dec 2017 14:02:03 +0300 Subject: [PATCH 11/67] lang settings option --- routes/appConfig.js | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/routes/appConfig.js b/routes/appConfig.js index 7cb1ef5..a298ef7 100644 --- a/routes/appConfig.js +++ b/routes/appConfig.js @@ -17,6 +17,7 @@ const appConfig = { cliStopTimeout: 1000, failedRPCAttemptsThreshold: 10, stopNativeDaemonsOnQuit: true, + lang: 'EN', }, schema: { host: { @@ -105,6 +106,15 @@ const appConfig = { info: 'Number of allowed consequent RPC connect failures before the app marks native coin daemon as not running properly', type: 'number', }, + lang: { + display: true, + displayName: 'Language', + type: 'select', + data: [ + { name: 'EN', label: 'English' }, + { name: 'DE', label: 'German' } + ], + }, }, }; From ef35fcf913ccc9d99bf12a2cd7926d4e805b8f5d Mon Sep 17 00:00:00 2001 From: pbca26 Date: Thu, 28 Dec 2017 01:03:39 +0300 Subject: [PATCH 12/67] seed to wif update, wif to wif conversion --- package.json | 4 ++-- routes/electrumjs/electrumjs.networks.js | 10 +++++++++- routes/shepherd/electrum/auth.js | 18 ++++++++++++++---- routes/shepherd/electrum/keys.js | 2 +- version | 4 ++-- version_build | 2 +- 6 files changed, 29 insertions(+), 11 deletions(-) diff --git a/package.json b/package.json index 5041db4..698bdc8 100644 --- a/package.json +++ b/package.json @@ -33,8 +33,8 @@ "bigi": "^1.4.2", "bip39": "^2.4.0", "bitcoinforksjs-lib": "git://github.com/bitcoinjs/bitcoinjs-lib#opt-in-bitcoincash-sighash", - "bitcoinjs-lib": "^3.2.0", - "bitcoinjs-lib-zcash": "git://github.com/karel-3d/bitcoinjs-lib#zcash", + "bitcoinjs-lib": "git://github.com/SuperNETorg/bitcoinjs-lib", + "bitcoinjs-lib-zcash": "git://github.com/pbca26/bitcoinjs-lib#zcash", "bitcoinjs-lib-pos": "git://github.com/KomodoPlatform/bitcoinjs-lib-pos", "bluebird": "^3.4.7", "body-parser": "^1.15.2", diff --git a/routes/electrumjs/electrumjs.networks.js b/routes/electrumjs/electrumjs.networks.js index fcb3848..6a8157b 100644 --- a/routes/electrumjs/electrumjs.networks.js +++ b/routes/electrumjs/electrumjs.networks.js @@ -269,4 +269,12 @@ networks.btc = networks.bitcoin; networks.crw = networks.crown; networks.dgb = networks.digibyte; networks.arg = networks.argentum; -networks.zec = networks.zcash; \ No newline at end of file +networks.zec = networks.zcash; +networks.nmc = networks.namecoin; +networks.ltc = networks.litecoin; +networks.vtc = networks.vertcoin; +networks.via = networks.viacoin; +networks.fair = networks.faircoin; +networks.doge = networks.dogecoin; +networks.kmd = networks.komodo; +networks.mona = networks.monacoin; \ No newline at end of file diff --git a/routes/shepherd/electrum/auth.js b/routes/shepherd/electrum/auth.js index 9351529..d7bed0a 100644 --- a/routes/shepherd/electrum/auth.js +++ b/routes/shepherd/electrum/auth.js @@ -1,18 +1,28 @@ +const bs58check = require('bs58check'); +const bitcoinZcash = require('bitcoinjs-lib-zcash'); + module.exports = (shepherd) => { shepherd.post('/electrum/login', (req, res, next) => { for (let key in shepherd.electrumServers) { const _abbr = shepherd.electrumServers[key].abbr; const _seed = req.body.seed; let keys; + let isWif = false; + + console.log(_seed); + + try { + bs58check.decode(_seed); + isWif = true; + } catch (e) {} - if ((_seed.length === 51 || _seed.length === 52) && - _seed.indexOf(' ') === -1 && - _seed.match(/^[a-zA-Z0-9]*$/)) { - let key = shepherd.bitcoinJS.ECPair.fromWIF(_seed, shepherd.electrumJSNetworks.komodo); + if (isWif) { + let key = shepherd.isZcash(_abbr.toLowerCase()) ? bitcoinZcash.ECPair.fromWIF(_seed, shepherd.getNetworkData(_abbr.toLowerCase()), true) : shepherd.bitcoinJS.ECPair.fromWIF(_seed, shepherd.getNetworkData(_abbr.toLowerCase()), true); keys = { priv: key.toWIF(), pub: key.getAddress(), }; + console.log(keys); } else { keys = shepherd.seedToWif(_seed, shepherd.findNetworkObj(_abbr), req.body.iguana); } diff --git a/routes/shepherd/electrum/keys.js b/routes/shepherd/electrum/keys.js index 6c4b3ca..735ab63 100644 --- a/routes/shepherd/electrum/keys.js +++ b/routes/shepherd/electrum/keys.js @@ -38,7 +38,7 @@ module.exports = (shepherd) => { } shepherd.get('/electrum/wiftopub', (req, res, next) => { - let key = shepherd.bitcoinJS.ECPair.fromWIF(req.query.wif, shepherd.electrumJSNetworks[req.query.coin]); + let key = shepherd.isZcash(req.query.coin.toLowerCase()) ? bitcoinZcash.ECPair.fromWIF(req.query.wif, shepherd.electrumJSNetworks[req.query.coin], true) : shepherd.bitcoinJS.ECPair.fromWIF(req.query.wif, shepherd.electrumJSNetworks[req.query.coin], true); keys = { priv: key.toWIF(), pub: key.getAddress(), diff --git a/version b/version index ef2859a..b5c5eda 100644 --- a/version +++ b/version @@ -1,3 +1,3 @@ -version=0.2.0.25i -type=i-beta +version=0.2.0.25j +type=j-beta minversion=0.2.0.2 \ No newline at end of file diff --git a/version_build b/version_build index abb893b..1432935 100644 --- a/version_build +++ b/version_build @@ -1 +1 @@ -0.2.0.25i-beta \ No newline at end of file +0.2.0.25j-beta \ No newline at end of file From 06599079ef98ee0bee3888c4aaf2fa23e41fdd3f Mon Sep 17 00:00:00 2001 From: pbca26 Date: Thu, 28 Dec 2017 13:28:11 +0300 Subject: [PATCH 13/67] wif export fix --- routes/shepherd/electrum/auth.js | 3 --- routes/shepherd/electrum/keys.js | 21 ++++++++++++++++++++- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/routes/shepherd/electrum/auth.js b/routes/shepherd/electrum/auth.js index d7bed0a..cd5795a 100644 --- a/routes/shepherd/electrum/auth.js +++ b/routes/shepherd/electrum/auth.js @@ -9,8 +9,6 @@ module.exports = (shepherd) => { let keys; let isWif = false; - console.log(_seed); - try { bs58check.decode(_seed); isWif = true; @@ -22,7 +20,6 @@ module.exports = (shepherd) => { priv: key.toWIF(), pub: key.getAddress(), }; - console.log(keys); } else { keys = shepherd.seedToWif(_seed, shepherd.findNetworkObj(_abbr), req.body.iguana); } diff --git a/routes/shepherd/electrum/keys.js b/routes/shepherd/electrum/keys.js index 735ab63..c780ca0 100644 --- a/routes/shepherd/electrum/keys.js +++ b/routes/shepherd/electrum/keys.js @@ -4,6 +4,7 @@ const crypto = require('crypto'); const bigi = require('bigi'); const bitcoinZcash = require('bitcoinjs-lib-zcash'); const bitcoin = require('bitcoinjs-lib'); +const bs58check = require('bs58check'); module.exports = (shepherd) => { shepherd.seedToWif = (seed, network, iguana) => { @@ -71,10 +72,28 @@ module.exports = (shepherd) => { let _matchingKeyPairs = 0; let _totalKeys = 0; let _electrumKeys = {}; + let _seed = req.body.seed; for (let key in shepherd.electrumServers) { const _abbr = shepherd.electrumServers[key].abbr; - const { priv, pub } = shepherd.seedToWif(req.body.seed, shepherd.findNetworkObj(_abbr), req.body.iguana); + let isWif = false; + let priv; + let pub; + + try { + bs58check.decode(_seed); + isWif = true; + } catch (e) {} + + if (isWif) { + let key = shepherd.isZcash(_abbr.toLowerCase()) ? bitcoinZcash.ECPair.fromWIF(_seed, shepherd.getNetworkData(_abbr.toLowerCase()), true) : shepherd.bitcoinJS.ECPair.fromWIF(_seed, shepherd.getNetworkData(_abbr.toLowerCase()), true); + priv = key.toWIF(); + pub = key.getAddress(); + } else { + let _keys = shepherd.seedToWif(_seed, shepherd.findNetworkObj(_abbr), req.body.iguana); + priv = _keys.priv; + pub = _keys.pub; + } if (shepherd.electrumKeys[_abbr].pub === pub && shepherd.electrumKeys[_abbr].priv === priv) { From 6d280cfbaf299f93293e21b3dd9aedd183c7ed49 Mon Sep 17 00:00:00 2001 From: pbca26 Date: Thu, 28 Dec 2017 21:21:32 +0300 Subject: [PATCH 14/67] kmd conf var name typo fix --- routes/shepherd/daemonControl.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/routes/shepherd/daemonControl.js b/routes/shepherd/daemonControl.js index 9bb0143..b936e80 100644 --- a/routes/shepherd/daemonControl.js +++ b/routes/shepherd/daemonControl.js @@ -669,7 +669,7 @@ module.exports = (shepherd) => { shepherd.log('rpcport: NOT FOUND'); shepherd.writeLog('rpcport: NOT FOUND'); - fs.appendFile(DaemonConfPath, '\rpcport=7771', (err) => { + fs.appendFile(DaemonConfPath, '\nrpcport=7771', (err) => { if (err) { shepherd.writeLog(`append daemon conf err: ${err}`); shepherd.log(`append daemon conf err: ${err}`); From dc15cd70d1f6dad2eeeca230d9ea6faf7da16cbb Mon Sep 17 00:00:00 2001 From: pbca26 Date: Thu, 28 Dec 2017 22:20:57 +0300 Subject: [PATCH 15/67] spv wrong wif format login/export error --- routes/shepherd/electrum/auth.js | 19 +++++++++++++------ routes/shepherd/electrum/keys.js | 16 +++++++++++----- 2 files changed, 24 insertions(+), 11 deletions(-) diff --git a/routes/shepherd/electrum/auth.js b/routes/shepherd/electrum/auth.js index cd5795a..60554fc 100644 --- a/routes/shepherd/electrum/auth.js +++ b/routes/shepherd/electrum/auth.js @@ -3,6 +3,8 @@ const bitcoinZcash = require('bitcoinjs-lib-zcash'); module.exports = (shepherd) => { shepherd.post('/electrum/login', (req, res, next) => { + let _wifError = false; + for (let key in shepherd.electrumServers) { const _abbr = shepherd.electrumServers[key].abbr; const _seed = req.body.seed; @@ -15,11 +17,16 @@ module.exports = (shepherd) => { } catch (e) {} if (isWif) { - let key = shepherd.isZcash(_abbr.toLowerCase()) ? bitcoinZcash.ECPair.fromWIF(_seed, shepherd.getNetworkData(_abbr.toLowerCase()), true) : shepherd.bitcoinJS.ECPair.fromWIF(_seed, shepherd.getNetworkData(_abbr.toLowerCase()), true); - keys = { - priv: key.toWIF(), - pub: key.getAddress(), - }; + try { + let key = shepherd.isZcash(_abbr.toLowerCase()) ? bitcoinZcash.ECPair.fromWIF(_seed, shepherd.getNetworkData(_abbr.toLowerCase()), true) : shepherd.bitcoinJS.ECPair.fromWIF(_seed, shepherd.getNetworkData(_abbr.toLowerCase()), true); + keys = { + priv: key.toWIF(), + pub: key.getAddress(), + }; + } catch (e) { + _wifError = true; + break; + } } else { keys = shepherd.seedToWif(_seed, shepherd.findNetworkObj(_abbr), req.body.iguana); } @@ -35,7 +42,7 @@ module.exports = (shepherd) => { // shepherd.log(JSON.stringify(shepherd.electrumKeys, null, '\t'), true); const successObj = { - msg: 'success', + msg: _wifError ? 'error' : 'success', result: 'true', }; diff --git a/routes/shepherd/electrum/keys.js b/routes/shepherd/electrum/keys.js index c780ca0..0fa2e58 100644 --- a/routes/shepherd/electrum/keys.js +++ b/routes/shepherd/electrum/keys.js @@ -73,6 +73,7 @@ module.exports = (shepherd) => { let _totalKeys = 0; let _electrumKeys = {}; let _seed = req.body.seed; + let _wifError = false; for (let key in shepherd.electrumServers) { const _abbr = shepherd.electrumServers[key].abbr; @@ -86,9 +87,14 @@ module.exports = (shepherd) => { } catch (e) {} if (isWif) { - let key = shepherd.isZcash(_abbr.toLowerCase()) ? bitcoinZcash.ECPair.fromWIF(_seed, shepherd.getNetworkData(_abbr.toLowerCase()), true) : shepherd.bitcoinJS.ECPair.fromWIF(_seed, shepherd.getNetworkData(_abbr.toLowerCase()), true); - priv = key.toWIF(); - pub = key.getAddress(); + try { + let key = shepherd.isZcash(_abbr.toLowerCase()) ? bitcoinZcash.ECPair.fromWIF(_seed, shepherd.getNetworkData(_abbr.toLowerCase()), true) : shepherd.bitcoinJS.ECPair.fromWIF(_seed, shepherd.getNetworkData(_abbr.toLowerCase()), true); + priv = key.toWIF(); + pub = key.getAddress(); + } catch (e) { + _wifError = true; + break; + } } else { let _keys = shepherd.seedToWif(_seed, shepherd.findNetworkObj(_abbr), req.body.iguana); priv = _keys.priv; @@ -115,8 +121,8 @@ module.exports = (shepherd) => { } const successObj = { - msg: 'success', - result: _matchingKeyPairs === _totalKeys ? _electrumKeys : false, + msg: _wifError ? 'error' : 'success', + result: _wifError ? false : (_matchingKeyPairs === _totalKeys ? _electrumKeys : false), }; res.end(JSON.stringify(successObj)); From d31ce569b1321bb016fefa6682e5bf9452101dc4 Mon Sep 17 00:00:00 2001 From: pbca26 Date: Fri, 29 Dec 2017 19:11:21 +0300 Subject: [PATCH 16/67] rpc/cli config switch --- routes/appConfig.js | 6 + routes/shepherd/dashboardUpdate.js | 2 + routes/shepherd/rpc.js | 260 +++++++++++++++++++++-------- version | 4 +- version_build | 2 +- 5 files changed, 198 insertions(+), 76 deletions(-) diff --git a/routes/appConfig.js b/routes/appConfig.js index a298ef7..2c0dddd 100644 --- a/routes/appConfig.js +++ b/routes/appConfig.js @@ -18,6 +18,7 @@ const appConfig = { failedRPCAttemptsThreshold: 10, stopNativeDaemonsOnQuit: true, lang: 'EN', + rpc2cli: false, }, schema: { host: { @@ -115,6 +116,11 @@ const appConfig = { { name: 'DE', label: 'German' } ], }, + rpc2cli: { + display: true, + displayName: 'Use CLI instead of RPC JSON server', + type: 'boolean', + }, }, }; diff --git a/routes/shepherd/dashboardUpdate.js b/routes/shepherd/dashboardUpdate.js index 9138138..99ecfb4 100644 --- a/routes/shepherd/dashboardUpdate.js +++ b/routes/shepherd/dashboardUpdate.js @@ -244,12 +244,14 @@ module.exports = (shepherd) => { chain: coin, cmd: cmd, params: params, + rpc2cli: req.body.rpc2cli, }; } else { _payload = { mode: null, chain: coin, cmd: cmd, + rpc2cli: req.body.rpc2cli, }; } diff --git a/routes/shepherd/rpc.js b/routes/shepherd/rpc.js index 5a89a45..8b78c70 100644 --- a/routes/shepherd/rpc.js +++ b/routes/shepherd/rpc.js @@ -77,7 +77,7 @@ module.exports = (shepherd) => { } else { const _mode = req.body.payload.mode === 'passthru' ? 'passthru' : 'default'; const _chain = req.body.payload.chain === 'KMD' ? null : req.body.payload.chain; - const _params = req.body.payload.params ? ` ${req.body.payload.params}` : ''; + let _params = req.body.payload.params ? ` ${req.body.payload.params}` : ''; let _cmd = req.body.payload.cmd; if (!shepherd.rpcConf[_chain]) { @@ -85,91 +85,205 @@ module.exports = (shepherd) => { } if (_mode === 'default') { - if (_cmd === 'debug' && - _chain !== 'CHIPS') { - if (shepherd.nativeCoindList[_chain.toLowerCase()]) { - const _osHome = os.platform === 'win32' ? process.env.APPDATA : process.env.HOME; - let coindDebugLogLocation; - - if (_chain === 'CHIPS') { - coindDebugLogLocation = `${shepherd.chipsDir}/debug.log`; - } else { - coindDebugLogLocation = `${_osHome}/.${shepherd.nativeCoindList[_chain.toLowerCase()].bin.toLowerCase()}/debug.log`; - } + if (req.body.payload.rpc2cli) { + let _coindCliBin = shepherd.komodocliBin; - shepherd.readDebugLog(coindDebugLogLocation, 1) - .then((result) => { - const _obj = { - msg: 'success', - result: result, - }; + if (shepherd.nativeCoindList && + _chain && + shepherd.nativeCoindList[_chain.toLowerCase()]) { + _coindCliBin = `${shepherd.coindRootDir}/${_chain.toLowerCase()}/${shepherd.nativeCoindList[_chain.toLowerCase()].bin.toLowerCase()}-cli`; + } - // shepherd.log('bitcoinrpc debug ====>'); - // console.log(result); + console.log(`cmd ${_cmd}`); + if (_params.indexOf('*')) { + _params = _params.replace('*', '"*"'); + } + if (_params.indexOf(',') > -1) { + _params = _params.split(','); + } + if (_cmd.indexOf('getaddressesbyaccount') > -1) { + _cmd = 'getaddressesbyaccount ""'; + } - res.end(JSON.stringify(_obj)); - }, (result) => { - const _obj = { - error: result, - result: 'error', - }; + console.log(typeof _params); - res.end(JSON.stringify(_obj)); - }); - } else { - res.end({ - error: 'bitcoinrpc debug error', - result: 'error', - }); - // console.log('bitcoinrpc debug error'); + let _arg = (_chain ? ' -ac_name=' + _chain : '') + ' ' + _cmd + (typeof _params === 'object' ? _params.join(' ') : _params); + + console.log(_arg); + + if (shepherd.appConfig.dataDir.length) { + _arg = `${_arg} -datadir=${shepherd.appConfig.dataDir + (_chain ? '/' + key : '')}`; } + + /*_arg = _arg.trim().split(' '); + + for (let i = 0; i < _arg.length; i++) { + if (_arg[i].indexOf('getaddressesbyaccount') > -1) { + _arg[i] = 'getaddressesbyaccount ""'; + } + }*/ + + shepherd.exec(`"${_coindCliBin}" ${_arg}`, (error, stdout, stderr) => { + shepherd.log(`stdout: ${stdout}`); + shepherd.log(`stderr: ${stderr}`); + + if (error !== null) { + shepherd.log(`exec error: ${error}`); + } + + let responseObj; + +/*error code: -5 +error message: +Invalid Komodo address*/ + + + if (stderr) { + let _res; + let _error; + + if ((stderr.indexOf('{') > -1 && stderr.indexOf('}') > -1) || + (stderr.indexOf('[') > -1 && stderr.indexOf(']') > -1)) { + _res = JSON.parse(stderr); + } else { + _res = stderr.trim(); + } + + if (stderr.indexOf('error code:') > -1) { + _error = { + code: stderr.substring(stderr.indexOf('error code:') + 11, stderr.indexOf('error message:') - stderr.indexOf('error code:')).trim(), + message: stderr.substring(stderr.indexOf('error message:') + 15, stderr.length).trim(), + }; + } + + if (_error) { + responseObj = { + error: _error, + }; + } else { + responseObj = { + result: _res, + }; + } + } else { + let _res; + let _error; + + if ((stdout.indexOf('{') > -1 && stdout.indexOf('}') > -1) || + (stdout.indexOf('[') > -1 && stdout.indexOf(']') > -1)) { + _res = JSON.parse(stdout); + } else { + _res = stdout.trim(); + } + + if (stdout.indexOf('error code:') > -1) { + _error = { + code: stdout.substring(stdout.indexOf('error code:') + 11, stdout.indexOf('error message:') - stdout.indexOf('error code:')).trim(), + message: stdout.substring(stdout.indexOf('error message:') + 15, stdout.length).trim(), + }; + } + + if (_error) { + responseObj = { + error: _error, + }; + } else { + responseObj = { + result: _res, + }; + } + } + + res.end(JSON.stringify(responseObj)); + shepherd.killRogueProcess('komodo-cli'); + }); } else { - if (_chain === 'CHIPS' && - _cmd === 'debug') { - _cmd = 'getblockchaininfo'; - } + if (_cmd === 'debug' && + _chain !== 'CHIPS') { + if (shepherd.nativeCoindList[_chain.toLowerCase()]) { + const _osHome = os.platform === 'win32' ? process.env.APPDATA : process.env.HOME; + let coindDebugLogLocation; + + if (_chain === 'CHIPS') { + coindDebugLogLocation = `${shepherd.chipsDir}/debug.log`; + } else { + coindDebugLogLocation = `${_osHome}/.${shepherd.nativeCoindList[_chain.toLowerCase()].bin.toLowerCase()}/debug.log`; + } - let _body = { - agent: 'bitcoinrpc', - method: _cmd, - }; + shepherd.readDebugLog(coindDebugLogLocation, 1) + .then((result) => { + const _obj = { + msg: 'success', + result: result, + }; + + // shepherd.log('bitcoinrpc debug ====>'); + // console.log(result); + + res.end(JSON.stringify(_obj)); + }, (result) => { + const _obj = { + error: result, + result: 'error', + }; - if (req.body.payload.params) { - _body = { + res.end(JSON.stringify(_obj)); + }); + } else { + res.end({ + error: 'bitcoinrpc debug error', + result: 'error', + }); + // console.log('bitcoinrpc debug error'); + } + } else { + if (_chain === 'CHIPS' && + _cmd === 'debug') { + _cmd = 'getblockchaininfo'; + } + + let _body = { agent: 'bitcoinrpc', method: _cmd, - params: req.body.payload.params === ' ' ? [''] : req.body.payload.params, }; - } - if (req.body.payload.chain) { - const options = { - url: `http://localhost:${shepherd.rpcConf[req.body.payload.chain].port}`, - method: 'POST', - auth: { - user: shepherd.rpcConf[req.body.payload.chain].user, - pass: shepherd.rpcConf[req.body.payload.chain].pass, - }, - body: JSON.stringify(_body), - }; + if (req.body.payload.params) { + _body = { + agent: 'bitcoinrpc', + method: _cmd, + params: req.body.payload.params === ' ' ? [''] : req.body.payload.params, + }; + } - // send back body on both success and error - // this bit replicates iguana core's behaviour - shepherd.request(options, (error, response, body) => { - if (response && - response.statusCode && - response.statusCode === 200) { - res.end(body); - } else { - res.end(body ? body : JSON.stringify({ - result: 'error', - error: { - code: -777, - message: `unable to call method ${_cmd} at port ${shepherd.rpcConf[req.body.payload.chain].port}`, - }, - })); - } - }); + if (req.body.payload.chain) { + const options = { + url: `http://localhost:${shepherd.rpcConf[req.body.payload.chain].port}`, + method: 'POST', + auth: { + user: shepherd.rpcConf[req.body.payload.chain].user, + pass: shepherd.rpcConf[req.body.payload.chain].pass, + }, + body: JSON.stringify(_body), + }; + + // send back body on both success and error + // this bit replicates iguana core's behaviour + shepherd.request(options, (error, response, body) => { + if (response && + response.statusCode && + response.statusCode === 200) { + res.end(body); + } else { + res.end(body ? body : JSON.stringify({ + result: 'error', + error: { + code: -777, + message: `unable to call method ${_cmd} at port ${shepherd.rpcConf[req.body.payload.chain].port}`, + }, + })); + } + }); + } } } } else { diff --git a/version b/version index b5c5eda..13db294 100644 --- a/version +++ b/version @@ -1,3 +1,3 @@ -version=0.2.0.25j -type=j-beta +version=0.2.0.26a +type=a-beta minversion=0.2.0.2 \ No newline at end of file diff --git a/version_build b/version_build index 1432935..729d403 100644 --- a/version_build +++ b/version_build @@ -1 +1 @@ -0.2.0.25j-beta \ No newline at end of file +0.2.0.26a-beta \ No newline at end of file From d91b458820a1cd675c3b7054bedc101e6ccbb2c1 Mon Sep 17 00:00:00 2001 From: pbca26 Date: Sat, 30 Dec 2017 02:48:30 -0800 Subject: [PATCH 17/67] rpc2cli fix --- routes/shepherd/rpc.js | 42 +++++++++++++++++++----------------------- 1 file changed, 19 insertions(+), 23 deletions(-) diff --git a/routes/shepherd/rpc.js b/routes/shepherd/rpc.js index 8b78c70..7258df1 100644 --- a/routes/shepherd/rpc.js +++ b/routes/shepherd/rpc.js @@ -94,7 +94,6 @@ module.exports = (shepherd) => { _coindCliBin = `${shepherd.coindRootDir}/${_chain.toLowerCase()}/${shepherd.nativeCoindList[_chain.toLowerCase()].bin.toLowerCase()}-cli`; } - console.log(`cmd ${_cmd}`); if (_params.indexOf('*')) { _params = _params.replace('*', '"*"'); } @@ -105,27 +104,15 @@ module.exports = (shepherd) => { _cmd = 'getaddressesbyaccount ""'; } - console.log(typeof _params); - let _arg = (_chain ? ' -ac_name=' + _chain : '') + ' ' + _cmd + (typeof _params === 'object' ? _params.join(' ') : _params); - console.log(_arg); - if (shepherd.appConfig.dataDir.length) { _arg = `${_arg} -datadir=${shepherd.appConfig.dataDir + (_chain ? '/' + key : '')}`; } - /*_arg = _arg.trim().split(' '); - - for (let i = 0; i < _arg.length; i++) { - if (_arg[i].indexOf('getaddressesbyaccount') > -1) { - _arg[i] = 'getaddressesbyaccount ""'; - } - }*/ - shepherd.exec(`"${_coindCliBin}" ${_arg}`, (error, stdout, stderr) => { - shepherd.log(`stdout: ${stdout}`); - shepherd.log(`stderr: ${stderr}`); + //shepherd.log(`stdout: ${stdout}`); + //shepherd.log(`stderr: ${stderr}`); if (error !== null) { shepherd.log(`exec error: ${error}`); @@ -133,15 +120,17 @@ module.exports = (shepherd) => { let responseObj; -/*error code: -5 -error message: -Invalid Komodo address*/ - - if (stderr) { let _res; let _error; + if (_chain !== 'komodod' && + stderr.indexOf(`error creating`) > -1) { + shepherd.log(`replace error creating (gen${_chain})`); + stderr = stderr.replace(`error creating (gen${_chain})`, ''); + shepherd.log(stderr); + } + if ((stderr.indexOf('{') > -1 && stderr.indexOf('}') > -1) || (stderr.indexOf('[') > -1 && stderr.indexOf(']') > -1)) { _res = JSON.parse(stderr); @@ -151,7 +140,7 @@ Invalid Komodo address*/ if (stderr.indexOf('error code:') > -1) { _error = { - code: stderr.substring(stderr.indexOf('error code:') + 11, stderr.indexOf('error message:') - stderr.indexOf('error code:')).trim(), + code: Number(stderr.substring(stderr.indexOf('error code:') + 11, stderr.indexOf('error message:') - stderr.indexOf('error code:')).trim()), message: stderr.substring(stderr.indexOf('error message:') + 15, stderr.length).trim(), }; } @@ -169,6 +158,13 @@ Invalid Komodo address*/ let _res; let _error; + if (_chain !== 'komodod' && + stdout.indexOf(`error creating`) > -1) { + shepherd.log(`replace error creating (gen${_chain})`); + stdout = stdout.replace(`error creating (gen${_chain})`, ''); + shepherd.log(stdout); + } + if ((stdout.indexOf('{') > -1 && stdout.indexOf('}') > -1) || (stdout.indexOf('[') > -1 && stdout.indexOf(']') > -1)) { _res = JSON.parse(stdout); @@ -178,7 +174,7 @@ Invalid Komodo address*/ if (stdout.indexOf('error code:') > -1) { _error = { - code: stdout.substring(stdout.indexOf('error code:') + 11, stdout.indexOf('error message:') - stdout.indexOf('error code:')).trim(), + code: Number(stdout.substring(stdout.indexOf('error code:') + 11, stdout.indexOf('error message:') - stdout.indexOf('error code:')).trim()), message: stdout.substring(stdout.indexOf('error message:') + 15, stdout.length).trim(), }; } @@ -195,7 +191,7 @@ Invalid Komodo address*/ } res.end(JSON.stringify(responseObj)); - shepherd.killRogueProcess('komodo-cli'); + // shepherd.killRogueProcess('komodo-cli'); }); } else { if (_cmd === 'debug' && From fd8bef982022311605862142a10bc21ecca22bbd Mon Sep 17 00:00:00 2001 From: pbca26 Date: Fri, 5 Jan 2018 15:46:36 +0300 Subject: [PATCH 18/67] btch, axo, etomic --- package.json | 6 +++--- routes/appConfig.js | 3 ++- routes/ports.js | 3 +++ routes/shepherd/electrum/keys.js | 2 ++ version | 6 +++--- version_build | 2 +- 6 files changed, 14 insertions(+), 8 deletions(-) diff --git a/package.json b/package.json index 698bdc8..9dc2b4e 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "agama-app", "productName": "Agama", - "version": "0.2.25", + "version": "0.2.26", "description": "Agama Wallet Desktop App", "main": "main.js", "scripts": { @@ -10,7 +10,7 @@ "make-rpm": "node make-rpm.js", "make-deb": "node make-deb.js" }, - "repository": "https://github.com/SuperNETorg/Agama/", + "repository": "https://github.com/KomodoPlatform/Agama/", "homepage": "http://supernet.org", "keywords": [ "agama", @@ -20,7 +20,7 @@ "wallet", "spv" ], - "author": "SuperNET", + "author": "SuperNET Team", "license": "MIT", "devDependencies": { "electron": "1.6.5", diff --git a/routes/appConfig.js b/routes/appConfig.js index 2c0dddd..fb76654 100644 --- a/routes/appConfig.js +++ b/routes/appConfig.js @@ -118,7 +118,8 @@ const appConfig = { }, rpc2cli: { display: true, - displayName: 'Use CLI instead of RPC JSON server', + displayName: 'Disable RPC', + info: 'Use CLI instead of RPC JSON server in native mode', type: 'boolean', }, }, diff --git a/routes/ports.js b/routes/ports.js index 2fce5ca..0646b6e 100644 --- a/routes/ports.js +++ b/routes/ports.js @@ -20,6 +20,9 @@ const assetChainPorts = { 'KV': '8299', 'CEAL': '11116', 'MESH': '9455', + 'AXO': '12927', + 'ETOMIC': '10271', + 'BTCH': '8800', 'USD': '13967', 'CHF': '15312', 'CAD': '8720', diff --git a/routes/shepherd/electrum/keys.js b/routes/shepherd/electrum/keys.js index 0fa2e58..960021e 100644 --- a/routes/shepherd/electrum/keys.js +++ b/routes/shepherd/electrum/keys.js @@ -6,6 +6,8 @@ const bitcoinZcash = require('bitcoinjs-lib-zcash'); const bitcoin = require('bitcoinjs-lib'); const bs58check = require('bs58check'); +// TODO: keys gen refactor + module.exports = (shepherd) => { shepherd.seedToWif = (seed, network, iguana) => { let bytes; diff --git a/version b/version index 13db294..9bbeb03 100644 --- a/version +++ b/version @@ -1,3 +1,3 @@ -version=0.2.0.26a -type=a-beta -minversion=0.2.0.2 \ No newline at end of file +version=0.2.0.26b +type=b-beta +minversion=0.2.0.26 \ No newline at end of file diff --git a/version_build b/version_build index 729d403..7b9ed5d 100644 --- a/version_build +++ b/version_build @@ -1 +1 @@ -0.2.0.26a-beta \ No newline at end of file +0.2.0.26b-beta \ No newline at end of file From 6cac0eef94dfc326e3e173c8b2548be5362c7fc9 Mon Sep 17 00:00:00 2001 From: pbca26 Date: Sat, 6 Jan 2018 17:07:07 +0300 Subject: [PATCH 19/67] fiat rates, wif2wif --- routes/appConfig.js | 7 +++++++ routes/shepherd/electrum/createtx.js | 2 +- routes/shepherd/electrum/keys.js | 11 +++++++++-- 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/routes/appConfig.js b/routes/appConfig.js index fb76654..fcfeb60 100644 --- a/routes/appConfig.js +++ b/routes/appConfig.js @@ -19,6 +19,7 @@ const appConfig = { stopNativeDaemonsOnQuit: true, lang: 'EN', rpc2cli: false, + fiatRates: false, }, schema: { host: { @@ -122,6 +123,12 @@ const appConfig = { info: 'Use CLI instead of RPC JSON server in native mode', type: 'boolean', }, + fiatRates: { + display: true, + displayName: 'Fetch fiat rates', + info: 'Get coin fiat rates from atomicexplorer.com', + type: 'boolean', + }, }, }; diff --git a/routes/shepherd/electrum/createtx.js b/routes/shepherd/electrum/createtx.js index 376248f..e7cf8ad 100644 --- a/routes/shepherd/electrum/createtx.js +++ b/routes/shepherd/electrum/createtx.js @@ -360,7 +360,7 @@ module.exports = (shepherd) => { shepherd.log(`current change amount ${_change} (${_change * 0.00000001}), boosted change amount ${_change + (totalInterest - _feeOverhead)} (${(_change + (totalInterest - _feeOverhead)) * 0.00000001})`, true); if (_maxSpend === value) { - _change = totalInterest -_change - _feeOverhead; + _change = totalInterest - _change - _feeOverhead; if (outputAddress === changeAddress) { value += _change; diff --git a/routes/shepherd/electrum/keys.js b/routes/shepherd/electrum/keys.js index 960021e..ff3fe2b 100644 --- a/routes/shepherd/electrum/keys.js +++ b/routes/shepherd/electrum/keys.js @@ -6,9 +6,16 @@ const bitcoinZcash = require('bitcoinjs-lib-zcash'); const bitcoin = require('bitcoinjs-lib'); const bs58check = require('bs58check'); -// TODO: keys gen refactor - module.exports = (shepherd) => { + shepherd.wifToWif = (wif, network) => { + const key = shepherd.isZcash(network) ? new bitcoinZcash.ECPair(d, null, { network: shepherd.getNetworkData(network) }) : new bitcoinZcash.ECPair(d, null, { network: shepherd.getNetworkData(network) }); + + return { + pub: key.getAddress(), + priv: key.toWIF(), + }; + } + shepherd.seedToWif = (seed, network, iguana) => { let bytes; From 969d58e7652b0604cc6eb5e243958ecfc02da92d Mon Sep 17 00:00:00 2001 From: pbca26 Date: Sun, 7 Jan 2018 16:45:36 +0300 Subject: [PATCH 20/67] faster spv login --- main.js | 20 +--------- package.json | 4 +- routes/shepherd/electrum/auth.js | 55 +++++++++++++------------- routes/shepherd/electrum/coins.js | 10 +++++ routes/shepherd/electrum/keys.js | 65 +++++-------------------------- 5 files changed, 52 insertions(+), 102 deletions(-) diff --git a/main.js b/main.js index 9cb3651..44ffc41 100644 --- a/main.js +++ b/main.js @@ -17,7 +17,6 @@ const express = require('express'); const bodyParser = require('body-parser'); const fsnode = require('fs'); const fs = require('fs-extra'); -const numCPUs = require('os').cpus().length; const Promise = require('bluebird'); const arch = require('arch'); @@ -364,7 +363,6 @@ function createWindow(status, hideLoadingWindow) { if (closeAppAfterLoading) { mainWindow = null; loadingWindow = null; - pm2Exit(); } const staticMenu = Menu.buildFromTemplate([ // if static @@ -510,7 +508,7 @@ function createWindow(status, hideLoadingWindow) { } } - // if window closed we kill iguana proc + // close app mainWindow.on('closed', () => { appExit(); }); @@ -534,18 +532,6 @@ app.on('before-quit', (event) => { if (process.argv.indexOf('dexonly') > -1) { shepherd.killRogueProcess('marketmaker'); } - /*if (!forceQuitApp && - mainWindow === null && - loadingWindow != null) { // mainWindow not intitialised and loadingWindow not dereferenced - // loading window is still open - shepherd.log('before-quit prevented'); - shepherd.writeLog('quit app after loading is done'); - closeAppAfterLoading = true; - // obsolete(?) - let code = `$('#loading_status_text').html('Preparing to shutdown the wallet.
Please wait while all daemons are closed...')`; - loadingWindow.webContents.executeJavaScript(code); - event.preventDefault(); - }*/ }); // Emitted when all windows have been closed and the application will quit. @@ -571,10 +557,6 @@ app.on('quit', (event) => { } }) -app.on('activate', () => { - if (mainWindow === null) {} -}); - app.commandLine.appendSwitch('ignore-certificate-errors'); // dirty hack function formatBytes(bytes, decimals) { diff --git a/package.json b/package.json index 9dc2b4e..c9a73a2 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "author": "SuperNET Team", "license": "MIT", "devDependencies": { - "electron": "1.6.5", + "electron": "1.7.10", "electron-installer-debian": "^0.6.0", "electron-installer-redhat": "^0.5.0" }, @@ -40,7 +40,7 @@ "body-parser": "^1.15.2", "buffer-reverse": "^1.0.1", "coinselect": "github:bitcoinjs/coinselect", - "electron": "1.6.5", + "electron": "1.7.10", "express": "^4.14.0", "fix-path": "^2.1.0", "fs-extra": "^4.0.2", diff --git a/routes/shepherd/electrum/auth.js b/routes/shepherd/electrum/auth.js index 60554fc..f017c30 100644 --- a/routes/shepherd/electrum/auth.js +++ b/routes/shepherd/electrum/auth.js @@ -1,40 +1,43 @@ const bs58check = require('bs58check'); const bitcoinZcash = require('bitcoinjs-lib-zcash'); +const bitcoin = require('bitcoinjs-lib'); module.exports = (shepherd) => { shepherd.post('/electrum/login', (req, res, next) => { let _wifError = false; - for (let key in shepherd.electrumServers) { - const _abbr = shepherd.electrumServers[key].abbr; - const _seed = req.body.seed; - let keys; - let isWif = false; + for (let key in shepherd.electrumCoins) { + if (key !== 'auth') { + const _abbr = key; + const _seed = req.body.seed; + let keys; + let isWif = false; - try { - bs58check.decode(_seed); - isWif = true; - } catch (e) {} - - if (isWif) { try { - let key = shepherd.isZcash(_abbr.toLowerCase()) ? bitcoinZcash.ECPair.fromWIF(_seed, shepherd.getNetworkData(_abbr.toLowerCase()), true) : shepherd.bitcoinJS.ECPair.fromWIF(_seed, shepherd.getNetworkData(_abbr.toLowerCase()), true); - keys = { - priv: key.toWIF(), - pub: key.getAddress(), - }; - } catch (e) { - _wifError = true; - break; + bs58check.decode(_seed); + isWif = true; + } catch (e) {} + + if (isWif) { + try { + let key = shepherd.isZcash(_abbr.toLowerCase()) ? bitcoinZcash.ECPair.fromWIF(_seed, shepherd.getNetworkData(_abbr.toLowerCase()), true) : bitcoin.ECPair.fromWIF(_seed, shepherd.getNetworkData(_abbr.toLowerCase()), true); + keys = { + priv: key.toWIF(), + pub: key.getAddress(), + }; + } catch (e) { + _wifError = true; + break; + } + } else { + keys = shepherd.seedToWif(_seed, shepherd.findNetworkObj(_abbr), req.body.iguana); } - } else { - keys = shepherd.seedToWif(_seed, shepherd.findNetworkObj(_abbr), req.body.iguana); - } - shepherd.electrumKeys[_abbr] = { - priv: keys.priv, - pub: keys.pub, - }; + shepherd.electrumKeys[_abbr] = { + priv: keys.priv, + pub: keys.pub, + }; + } } shepherd.electrumCoins.auth = true; diff --git a/routes/shepherd/electrum/coins.js b/routes/shepherd/electrum/coins.js index 1130163..bc73562 100644 --- a/routes/shepherd/electrum/coins.js +++ b/routes/shepherd/electrum/coins.js @@ -54,6 +54,16 @@ module.exports = (shepherd) => { shepherd.log(`${coin} doesnt have any backup electrum servers`, true); } + if (Object.keys(shepherd.electrumKeys).length > 0) { + const _keys = shepherd.wifToWif(shepherd.electrumKeys[Object.keys(shepherd.electrumKeys)[0]].priv, coin); + + shepherd.electrumKeys[coin] = { + priv: _keys.priv, + pub: _keys.pub, + }; + console.log(shepherd.electrumKeys[coin]); + } + return true; } } diff --git a/routes/shepherd/electrum/keys.js b/routes/shepherd/electrum/keys.js index ff3fe2b..de01cc8 100644 --- a/routes/shepherd/electrum/keys.js +++ b/routes/shepherd/electrum/keys.js @@ -1,4 +1,5 @@ const sha256 = require('js-sha256'); +const buggySha256 = require('sha256'); const bip39 = require('bip39'); const crypto = require('crypto'); const bigi = require('bigi'); @@ -8,8 +9,10 @@ const bs58check = require('bs58check'); module.exports = (shepherd) => { shepherd.wifToWif = (wif, network) => { - const key = shepherd.isZcash(network) ? new bitcoinZcash.ECPair(d, null, { network: shepherd.getNetworkData(network) }) : new bitcoinZcash.ECPair(d, null, { network: shepherd.getNetworkData(network) }); - + network = network === 'KMD' ? 'komodo' : network.toLowerCase(); + console.log(shepherd.getNetworkData(network)); + const key = shepherd.isZcash(network) ? new bitcoinZcash.ECPair.fromWIF(wif, shepherd.getNetworkData(network), true) : new bitcoin.ECPair.fromWIF(wif, shepherd.getNetworkData(network), true); + return { pub: key.getAddress(), priv: key.toWIF(), @@ -20,7 +23,7 @@ module.exports = (shepherd) => { let bytes; if (process.argv.indexOf('spvold=true') > -1) { - bytes = shepherd.sha256(seed, { asBytes: true }); + bytes = buggySha256(seed, { asBytes: true }); } else { const hash = sha256.create().update(seed); bytes = hash.array(); @@ -33,7 +36,7 @@ module.exports = (shepherd) => { } const d = bigi.fromBuffer(bytes); - const keyPair = shepherd.isZcash(network) ? new bitcoinZcash.ECPair(d, null, { network: shepherd.getNetworkData(network) }) : new bitcoinZcash.ECPair(d, null, { network: shepherd.getNetworkData(network) }); + const keyPair = shepherd.isZcash(network) ? new bitcoinZcash.ECPair(d, null, { network: shepherd.getNetworkData(network) }) : new bitcoin.ECPair(d, null, { network: shepherd.getNetworkData(network) }); const keys = { pub: keyPair.getAddress(), priv: keyPair.toWIF(), @@ -48,7 +51,7 @@ module.exports = (shepherd) => { } shepherd.get('/electrum/wiftopub', (req, res, next) => { - let key = shepherd.isZcash(req.query.coin.toLowerCase()) ? bitcoinZcash.ECPair.fromWIF(req.query.wif, shepherd.electrumJSNetworks[req.query.coin], true) : shepherd.bitcoinJS.ECPair.fromWIF(req.query.wif, shepherd.electrumJSNetworks[req.query.coin], true); + let key = shepherd.isZcash(req.query.coin.toLowerCase()) ? bitcoinZcash.ECPair.fromWIF(req.query.wif, shepherd.electrumJSNetworks[req.query.coin], true) : bitcoin.ECPair.fromWIF(req.query.wif, shepherd.electrumJSNetworks[req.query.coin], true); keys = { priv: key.toWIF(), pub: key.getAddress(), @@ -97,7 +100,7 @@ module.exports = (shepherd) => { if (isWif) { try { - let key = shepherd.isZcash(_abbr.toLowerCase()) ? bitcoinZcash.ECPair.fromWIF(_seed, shepherd.getNetworkData(_abbr.toLowerCase()), true) : shepherd.bitcoinJS.ECPair.fromWIF(_seed, shepherd.getNetworkData(_abbr.toLowerCase()), true); + let key = shepherd.isZcash(_abbr.toLowerCase()) ? bitcoinZcash.ECPair.fromWIF(_seed, shepherd.getNetworkData(_abbr.toLowerCase()), true) : bitcoin.ECPair.fromWIF(_seed, shepherd.getNetworkData(_abbr.toLowerCase()), true); priv = key.toWIF(); pub = key.getAddress(); } catch (e) { @@ -151,7 +154,7 @@ module.exports = (shepherd) => { shepherd.post('/electrum/seed/bip39/match', (req, res, next) => { const seed = bip39.mnemonicToSeed(req.body.seed); - const hdMaster = shepherd.bitcoinJS.HDNode.fromSeedBuffer(seed, shepherd.electrumJSNetworks.komodo); // seed from above + const hdMaster = bitcoin.HDNode.fromSeedBuffer(seed, shepherd.electrumJSNetworks.komodo); // seed from above const matchPattern = req.body.match; const _defaultAddressDepth = req.body.addressdepth; const _defaultAccountCount = req.body.accounts; @@ -169,10 +172,6 @@ module.exports = (shepherd) => { priv: _key.keyPair.toWIF(), }; } - /*_addresses.push({ - pub: _key.keyPair.getAddress(), - priv: _key.keyPair.toWIF(), - });*/ } } } @@ -185,49 +184,5 @@ module.exports = (shepherd) => { res.end(JSON.stringify(successObj)); }); - // spv v2 - /*shepherd.get('/electrum/bip39/seed', (req, res, next) => { - const _seed = ''; - // TODO - const bip39 = require('bip39'); // npm i -S bip39 - const crypto = require('crypto'); - - // what you describe as 'seed' - const randomBytes = crypto.randomBytes(16); // 128 bits is enough - - // your 12 word phrase - const mnemonic = bip39.entropyToMnemonic(randomBytes.toString('hex')); - - // what is accurately described as the wallet seed - // var seed = bip39.mnemonicToSeed(mnemonic) // you'll use this in #3 below - const seed = bip39.mnemonicToSeed(_seed); - - console.log(seed); - - const successObj = { - msg: 'success', - result: { - servers: shepherd.electrumServers, - }, - }; - - res.end(JSON.stringify(successObj)); - - console.log(shepherd.bitcoinJS.networks.komodo); - const hdMaster = shepherd.bitcoinJS.HDNode.fromSeedBuffer(seed, shepherd.electrumJSNetworks.komodo); // seed from above - - const key1 = hdMaster.derivePath("m/44'/141'/0'/0/0"); - const key2 = hdMaster.derivePath('m/1'); - console.log(hdMaster); - - console.log(key1.keyPair.toWIF()); - console.log(key1.keyPair.getAddress()); - console.log(key2.keyPair.toWIF()); - - const hdnode = shepherd.bitcoinJS.HDNode.fromSeedBuffer(seed, shepherd.electrumJSNetworks.komodo).deriveHardened(0).derive(0).derive(1); - console.log(`address: ${hdnode.getAddress()}`); - console.log(`priv (WIF): ${hdnode.keyPair.toWIF()}`); - });*/ - return shepherd; }; \ No newline at end of file From 381cc54fd3a90139662b4d4548fd35ddfad528f1 Mon Sep 17 00:00:00 2001 From: pbca26 Date: Mon, 8 Jan 2018 21:25:48 +0300 Subject: [PATCH 21/67] cleanup --- main.js | 5 +- routes/shepherd.js | 1 - routes/shepherd/addCoinShortcuts.js | 6 +- routes/shepherd/appInfo.js | 27 +- routes/shepherd/auth.js | 48 +- routes/shepherd/binsTestUtil.js | 239 -------- routes/shepherd/coindWalletKeys.js | 141 +++-- routes/shepherd/coins.js | 41 +- routes/shepherd/coinsList.js | 94 +-- routes/shepherd/config.js | 65 +- routes/shepherd/daemonControl.js | 199 +++--- routes/shepherd/dashboardUpdate.js | 518 ++++++++-------- routes/shepherd/debugLog.js | 122 ++-- routes/shepherd/downloadBins.js | 208 ++++--- routes/shepherd/downloadPatch.js | 147 +++-- routes/shepherd/downloadZcparams.js | 107 ++-- routes/shepherd/electrum/auth.js | 139 +++-- routes/shepherd/electrum/balance.js | 201 ++++--- routes/shepherd/electrum/block.js | 46 +- routes/shepherd/electrum/coins.js | 73 ++- routes/shepherd/electrum/createtx.js | 735 ++++++++++++----------- routes/shepherd/electrum/estimate.js | 31 +- routes/shepherd/electrum/keys.js | 219 ++++--- routes/shepherd/electrum/listunspent.js | 73 ++- routes/shepherd/electrum/merkle.js | 27 +- routes/shepherd/electrum/network.js | 147 +++-- routes/shepherd/electrum/transactions.js | 454 +++++++------- routes/shepherd/kickstart.js | 59 +- routes/shepherd/log.js | 127 ++-- routes/shepherd/pin.js | 209 ++++--- routes/shepherd/quitDaemon.js | 132 ++-- routes/shepherd/rpc.js | 451 +++++++------- 32 files changed, 2688 insertions(+), 2403 deletions(-) delete mode 100644 routes/shepherd/binsTestUtil.js diff --git a/main.js b/main.js index 44ffc41..3c03822 100644 --- a/main.js +++ b/main.js @@ -57,7 +57,6 @@ shepherd.createAgamaDirs(); const appSessionHash = md5(Date.now().toString()); const _spvFees = shepherd.getSpvFees(); -shepherd.writeLog(`app init ${appSessionHash}`); shepherd.writeLog(`app info: ${appBasicInfo.name} ${appBasicInfo.version}`); shepherd.writeLog('sys info:'); shepherd.writeLog(`totalmem_readable: ${formatBytes(os.totalmem())}`); @@ -68,7 +67,9 @@ shepherd.writeLog(`platform: ${osPlatform}`); shepherd.writeLog(`os_release: ${os.release()}`); shepherd.writeLog(`os_type: ${os.type()}`); -shepherd.log(`app init ${appSessionHash}`); +if (process.argv.indexOf('devmode') > -1) { + shepherd.log(`app init ${appSessionHash}`); +} shepherd.log(`app info: ${appBasicInfo.name} ${appBasicInfo.version}`); shepherd.log('sys info:'); shepherd.log(`totalmem_readable: ${formatBytes(os.totalmem())}`); diff --git a/routes/shepherd.js b/routes/shepherd.js index 9d5c26b..8c3c0d8 100644 --- a/routes/shepherd.js +++ b/routes/shepherd.js @@ -107,7 +107,6 @@ shepherd = require('./shepherd/dex/electrumServersList.js')(shepherd); // core shepherd = require('./shepherd/addCoinShortcuts.js')(shepherd); shepherd = require('./shepherd/dashboardUpdate.js')(shepherd); -shepherd = require('./shepherd/binsTestUtil.js')(shepherd); shepherd = require('./shepherd/binsUtils.js')(shepherd); shepherd = require('./shepherd/downloadUtil.js')(shepherd); shepherd = require('./shepherd/init.js')(shepherd); diff --git a/routes/shepherd/addCoinShortcuts.js b/routes/shepherd/addCoinShortcuts.js index d3af01e..02ede31 100644 --- a/routes/shepherd/addCoinShortcuts.js +++ b/routes/shepherd/addCoinShortcuts.js @@ -40,7 +40,8 @@ module.exports = (shepherd) => { body: JSON.stringify({ herd: 'komodod', options: herdData, - }) + token: shepherd.appSessionHash, + }), }; shepherd.request(options, (error, response, body) => { @@ -90,7 +91,8 @@ module.exports = (shepherd) => { body: JSON.stringify({ herd: 'komodod', options: herdData[i], - }) + token: shepherd.appSessionHash, + }), }; shepherd.request(options, (error, response, body) => { diff --git a/routes/shepherd/appInfo.js b/routes/shepherd/appInfo.js index d22f7b1..206fc6d 100644 --- a/routes/shepherd/appInfo.js +++ b/routes/shepherd/appInfo.js @@ -52,7 +52,6 @@ module.exports = (shepherd) => { sysInfo, releaseInfo, dirs, - appSession: shepherd.appSessionHash, }; } @@ -61,8 +60,17 @@ module.exports = (shepherd) => { * */ shepherd.get('/sysinfo', (req, res, next) => { - const obj = shepherd.SystemInfo(); - res.send(obj); + if (shepherd.checkToken(req.query.token)) { + const obj = shepherd.SystemInfo(); + res.send(obj); + } else { + const errorObj = { + msg: 'error', + result: 'unauthorized access', + }; + + res.end(JSON.stringify(errorObj)); + } }); /* @@ -70,8 +78,17 @@ module.exports = (shepherd) => { * */ shepherd.get('/appinfo', (req, res, next) => { - const obj = shepherd.appInfo(); - res.send(obj); + if (shepherd.checkToken(req.query.token)) { + const obj = shepherd.appInfo(); + res.send(obj); + } else { + const errorObj = { + msg: 'error', + result: 'unauthorized access', + }; + + res.end(JSON.stringify(errorObj)); + } }); return shepherd; diff --git a/routes/shepherd/auth.js b/routes/shepherd/auth.js index 25f9cc0..12c4aa6 100644 --- a/routes/shepherd/auth.js +++ b/routes/shepherd/auth.js @@ -3,29 +3,45 @@ module.exports = (shepherd) => { * type: GET * */ - shepherd.get('/auth/status', (req, res, next) => { // not finished - let successObj; - let _status = false; + shepherd.get('/auth/status', (req, res, next) => { + if (shepherd.checkToken(req.query.token)) { + let successObj; + let _status = false; - if (Object.keys(shepherd.coindInstanceRegistry).length) { - if (Object.keys(shepherd.electrumCoins).length > 1 && - shepherd.electrumCoins.auth) { + if (Object.keys(shepherd.coindInstanceRegistry).length) { + if (Object.keys(shepherd.electrumCoins).length > 1 && + shepherd.electrumCoins.auth) { + _status = true; + } else if (Object.keys(shepherd.electrumCoins).length === 1 && !shepherd.electrumCoins.auth) { + _status = true; + } + } else if (Object.keys(shepherd.electrumCoins).length > 1 && shepherd.electrumCoins.auth) { _status = true; - } else if (Object.keys(shepherd.electrumCoins).length === 1 && !shepherd.electrumCoins.auth) { + } else if (Object.keys(shepherd.electrumCoins).length === 1 && !Object.keys(shepherd.coindInstanceRegistry).length) { _status = true; } - } else if (Object.keys(shepherd.electrumCoins).length > 1 && shepherd.electrumCoins.auth) { - _status = true; - } else if (Object.keys(shepherd.electrumCoins).length === 1 && !Object.keys(shepherd.coindInstanceRegistry).length) { - _status = true; - } - successObj = { - status: _status ? 'unlocked' : 'locked', - }; + successObj = { + status: _status ? 'unlocked' : 'locked', + }; + + res.end(JSON.stringify(successObj)); + } else { + const errorObj = { + msg: 'error', + result: 'unauthorized access', + }; - res.end(JSON.stringify(successObj)); + res.end(JSON.stringify(errorObj)); + } }); + shepherd.checkToken = (token) => { + if (token === shepherd.appSessionHash || + process.argv.indexOf('devmode') > -1) { + return true; + } + }; + return shepherd; }; \ No newline at end of file diff --git a/routes/shepherd/binsTestUtil.js b/routes/shepherd/binsTestUtil.js deleted file mode 100644 index df0e509..0000000 --- a/routes/shepherd/binsTestUtil.js +++ /dev/null @@ -1,239 +0,0 @@ -module.exports = (shepherd) => { - shepherd.testClearAll = () => { - return new shepherd.Promise((resolve, reject) => { - shepherd.fs.removeSync(`${iguanaTestDir}`); - resolve('done'); - }); - } - - shepherd.testBins = (daemonName) => { - return new shepherd.Promise((resolve, reject) => { - const _bins = { - komodod: shepherd.komododBin, - komodoCli: shepherd.komodocliBin, - }; - const _arg = null; - let _pid; - - shepherd.log('testBins exec ' + _bins[daemonName]); - - if (!shepherd.fs.existsSync(shepherd.agamaTestDir)) { - shepherd.fs.mkdirSync(shepherd.agamaTestDir); - } - - try { - shepherd._fs.access(`${shepherd.agamaTestDir}/${daemonName}Test.log`, shepherd.fs.constants.R_OK, (err) => { - if (!err) { - try { - shepherd._fs.unlinkSync(`${shepherd.agamaTestDir}/${daemonName}Test.log`); - } catch (e) {} - } else { - shepherd.log(`path ${shepherd.agamaTestDir}/${daemonName}Test.log doesnt exist`); - } - }); - } catch (e) {} - - if (daemonName === 'komodod') { - try { - shepherd._fs.access(`${iguanaTestDir}/debug.log`, shepherd.fs.constants.R_OK, (err) => { - if (!err) { - shepherd._fs.unlinkSync(`${iguanaTestDir}/db.log`); - shepherd._fs.unlinkSync(`${iguanaTestDir}/debug.log`); - shepherd._fs.unlinkSync(`${iguanaTestDir}/komodo.conf`); - shepherd._fs.unlinkSync(`${iguanaTestDir}/komodod.pid`); - shepherd._fs.unlinkSync(`${iguanaTestDir}/komodostate`); - shepherd._fs.unlinkSync(`${iguanaTestDir}/realtime`); - shepherd._fs.unlinkSync(`${iguanaTestDir}/wallet.dat`); - shepherd._fs.unlinkSync(`${iguanaTestDir}/.lock`); - shepherd.fs.removeSync(`${iguanaTestDir}/blocks`); - shepherd.fs.removeSync(`${iguanaTestDir}/chainstate`); - shepherd.fs.removeSync(`${iguanaTestDir}/database`); - execKomodod(); - } else { - shepherd.log(`test: nothing to remove in ${iguanaTestDir}`); - execKomodod(); - } - }); - } catch (e) {} - - const execKomodod = () => { - let _komododTest = { - port: 'unknown', - start: 'unknown', - getinfo: 'unknown', - errors: { - assertFailed: false, - zcashParams: false, - }, - }; - const _komodoConf = 'rpcuser=user83f3afba8d714993\n' + - 'rpcpassword=0d4430ca1543833e35bce5a0cc9e16b3\n' + - 'server=1\n' + - 'addnode=78.47.196.146\n' + - 'addnode=5.9.102.210\n' + - 'addnode=178.63.69.164\n' + - 'addnode=88.198.65.74\n' + - 'addnode=5.9.122.241\n' + - 'addnode=144.76.94.3\n' + - 'addnode=144.76.94.38\n' + - 'addnode=89.248.166.91\n' + - 'addnode=148.251.57.148\n' + - 'addnode=149.56.28.84\n' + - 'addnode=176.9.26.39\n' + - 'addnode=94.102.63.199\n' + - 'addnode=94.102.63.200\n' + - 'addnode=104.255.64.3\n' + - 'addnode=221.121.144.140\n' + - 'addnode=103.18.58.150\n' + - 'addnode=103.18.58.146\n' + - 'addnode=213.202.253.10\n' + - 'addnode=185.106.121.32\n' + - 'addnode=27.100.36.201\n'; - - shepherd.fs.writeFile(`${iguanaTestDir}/komodo.conf`, _komodoConf, (err) => { - if (err) { - shepherd.log(`test: error writing komodo conf in ${iguanaTestDir}`); - } - }); - - shepherd.portscanner.checkPortStatus('7771', '127.0.0.1', (error, status) => { - // Status is 'open' if currently in use or 'closed' if available - if (status === 'closed') { - _komododTest.port = 'passed'; - } else { - _komododTest.port = 'failed'; - } - }); - - /*pm2.connect(true,function(err) { //start up pm2 god - if (err) { - shepherd.error(err); - process.exit(2); - } - - pm2.start({ - script: shepherd.komododBin, // path to binary - name: 'komodod', - exec_mode : 'fork', - args: [ - '-daemon=0', - '-addnode=78.47.196.146', - `-datadir=${iguanaTestDir}/` - ], - output: `${iguanaTestDir}/komododTest.log`, - mergeLogs: true, - }, function(err, apps) { - if (apps[0] && - apps[0].process && - apps[0].process.pid) { - _komododTest.start = 'success'; - shepherd.log(`test: got komodod instance pid = ${apps[0].process.pid}`); - shepherd.writeLog(`test: komodod started with pid ${apps[0].process.pid}`); - } else { - _komododTest.start = 'failed'; - shepherd.log(`unable to start komodod`); - } - - pm2.disconnect(); // Disconnect from PM2 - if (err) { - shepherd.writeLog(`test: error starting komodod`); - shepherd.log(`komodod fork err: ${err}`); - // throw err; - } - }); - });*/ - - setTimeout(() => { - const options = { - url: `http://localhost:7771`, - method: 'POST', - auth: { - user: 'user83f3afba8d714993', - pass: '0d4430ca1543833e35bce5a0cc9e16b3', - }, - body: JSON.stringify({ - agent: 'bitcoinrpc', - method: 'getinfo', - }), - }; - - shepherd.request(options, (error, response, body) => { - if (response && - response.statusCode && - response.statusCode === 200) { - // res.end(body); - shepherd.log(JSON.stringify(body, null, '\t')); - } else { - // res.end(body); - shepherd.log(JSON.stringify(body, null, '\t')); - } - }); - }, 10000); - - setTimeout(() => { - pm2.delete('komodod'); - resolve(_komododTest); - }, 20000); - } - // komodod debug.log hooks - - //"{\"result\":{\"version\":1000850,\"protocolversion\":170002,\"KMDversion\":\"0.1.1\",\"notarized\":0,\"notarizedhash\":\"0000000000000000000000000000000000000000000000000000000000000000\",\"notarizedtxid\":\"0000000000000000000000000000000000000000000000000000000000000000\",\"notarizedtxid_height\":\"mempool\",\"notarized_confirms\":0,\"walletversion\":60000,\"balance\":0.00000000,\"interest\":0.00000000,\"blocks\":128,\"longestchain\":472331,\"timeoffset\":0,\"tiptime\":1473827710,\"connections\":1,\"proxy\":\"\",\"difficulty\":1,\"testnet\":false,\"keypoololdest\":1504118047,\"keypoolsize\":101,\"paytxfee\":0.00000000,\"relayfee\":0.00000100,\"errors\":\"\"},\"error\":null,\"id\":null}\n" - - //2017-08-30 17:51:33 Error: Cannot find the Zcash network parameters in the following directory: - //"/home/pbca/.zcash-params" - //Please run 'zcash-fetch-params' or './zcutil/fetch-params.sh' and then restart. - //EXCEPTION: St13runtime_error - //Assertion failed. - //2017-08-30 17:51:14 Using config file /home/pbca/.iguana/test/komodo.conf - //2017-08-30 18:23:43 UpdateTip: new best=0a47c1323f393650f7221c217d19d149d002d35444f47fde61be2dd90fbde8e6 height=1 log2_work=5.0874628 tx=2 date=2016-09-13 19:04:01 progress=0.000001 cache=0.0MiB(1tx) - //2017-08-30 18:23:43 UpdateTip: new best=05076a4e1fc9af0f5fda690257b17ae20c12d4796dfba1624804d012c9ec00be height=2 log2_work=5.6724253 tx=3 date=2016-09-13 19:05:28 progress=0.000001 cache=0.0MiB(2tx) - - /*shepherd.execFile(`${shepherd.komododBin}`, _arg, { - maxBuffer: 1024 * 10000 // 10 mb - }, function(error, stdout, stderr) { - shepherd.writeLog(`stdout: ${stdout}`); - shepherd.writeLog(`stderr: ${stderr}`); - - if (error !== null) { - console.log(`exec error: ${error}`); - shepherd.writeLog(`exec error: ${error}`); - - if (error.toString().indexOf('using -reindex') > -1) { - shepherd.io.emit('service', { - komodod: { - error: 'run -reindex', - } - }); - } - } - });*/ - } - }); - } - - // komodod datadir location test - shepherd.testLocation = (path) => { - return new shepherd.Promise((resolve, reject) => { - if (path.indexOf(' ') > -1) { - shepherd.log(`error testing path ${path}`); - resolve(-1); - } else { - shepherd.fs.lstat(path, (err, stats) => { - if (err) { - shepherd.log(`error testing path ${path}`); - resolve(-1); - } else { - if (stats.isDirectory()) { - resolve(true); - } else { - shepherd.log(`error testing path ${path} not a folder`); - resolve(false); - } - } - }); - } - }); - } - - return shepherd; -}; \ No newline at end of file diff --git a/routes/shepherd/coindWalletKeys.js b/routes/shepherd/coindWalletKeys.js index e82ff74..e8c1d3b 100644 --- a/routes/shepherd/coindWalletKeys.js +++ b/routes/shepherd/coindWalletKeys.js @@ -4,94 +4,103 @@ module.exports = (shepherd) => { * */ shepherd.get('/coindwalletkeys', (req, res, next) => { - const wif = require('wif'); - const fs = require('fs'); - const chain = req.query.chain; + if (shepherd.checkToken(req.query.token)) { + const wif = require('wif'); + const fs = require('fs'); + const chain = req.query.chain; - // ref: https://gist.github.com/kendricktan/1e62495150ad236b38616d733aac4eb9 - let _walletDatLocation = chain === 'komodo' || chain === 'null' ? `${shepherd.komodoDir}/wallet.dat` : `${shepherd.komodoDir}/${chain}/wallet.dat`; - _walletDatLocation = chain === 'CHIPS' ? `${shepherd.chipsDir}/wallet.dat` : _walletDatLocation; + // ref: https://gist.github.com/kendricktan/1e62495150ad236b38616d733aac4eb9 + let _walletDatLocation = chain === 'komodo' || chain === 'null' ? `${shepherd.komodoDir}/wallet.dat` : `${shepherd.komodoDir}/${chain}/wallet.dat`; + _walletDatLocation = chain === 'CHIPS' ? `${shepherd.chipsDir}/wallet.dat` : _walletDatLocation; - try { - shepherd._fs.access(_walletDatLocation, shepherd.fs.constants.R_OK, (err) => { - if (err) { - shepherd.log(`error reading ${_walletDatLocation}`); - successObj = { - msg: 'error', - result: `error reading ${_walletDatLocation}`, - }; - - res.end(JSON.stringify(successObj)); - } else { - shepherd.log(`reading ${_walletDatLocation}`); - fs.readFile(_walletDatLocation, (err, data) => { - if (err) { - shepherd.log(`read wallet.dat err: ${err}`); - successObj = { - msg: 'error', - result: `error reading ${_walletDatLocation}`, - }; - - res.end(JSON.stringify(successObj)); - } else { - const re = /\x30\x81\xD3\x02\x01\x01\x04\x20(.{32})/gm; - const dataHexStr = data.toString('latin1'); - privateKeys = dataHexStr.match(re); - - if (!privateKeys) { - shepherd.log('wallet is encrypted?'); + try { + shepherd._fs.access(_walletDatLocation, shepherd.fs.constants.R_OK, (err) => { + if (err) { + shepherd.log(`error reading ${_walletDatLocation}`); + successObj = { + msg: 'error', + result: `error reading ${_walletDatLocation}`, + }; + res.end(JSON.stringify(successObj)); + } else { + shepherd.log(`reading ${_walletDatLocation}`); + fs.readFile(_walletDatLocation, (err, data) => { + if (err) { + shepherd.log(`read wallet.dat err: ${err}`); successObj = { msg: 'error', - result: 'wallet is encrypted?', + result: `error reading ${_walletDatLocation}`, }; res.end(JSON.stringify(successObj)); } else { - let _keys = []; - privateKeys = privateKeys.map(x => x.replace('\x30\x81\xD3\x02\x01\x01\x04\x20', '')); - privateKeys = privateKeys.filter((v, i, a) => a.indexOf(v) === i); - shepherd.log(`found ${privateKeys.length} keys`); + const re = /\x30\x81\xD3\x02\x01\x01\x04\x20(.{32})/gm; + const dataHexStr = data.toString('latin1'); + privateKeys = dataHexStr.match(re); - for (let i = 0; i < privateKeys.length; i++) { - const privateKey = new Buffer(Buffer.from(privateKeys[i], 'latin1').toString('hex'), 'hex'); - const key = wif.encode(0xbc, privateKey, true); - const keyObj = wif.decode(key); - const wifKey = wif.encode(keyObj); + if (!privateKeys) { + shepherd.log('wallet is encrypted?'); - const keyPair = shepherd.bitcoinJS.ECPair.fromWIF(wifKey, shepherd.electrumJSNetworks.komodo); - const _keyPair = { - priv: keyPair.toWIF(), - pub: keyPair.getAddress(), + successObj = { + msg: 'error', + result: 'wallet is encrypted?', }; - if (req.query.search) { - if (_keyPair.pub.indexOf(req.query.search) > -1) { + res.end(JSON.stringify(successObj)); + } else { + let _keys = []; + privateKeys = privateKeys.map(x => x.replace('\x30\x81\xD3\x02\x01\x01\x04\x20', '')); + privateKeys = privateKeys.filter((v, i, a) => a.indexOf(v) === i); + shepherd.log(`found ${privateKeys.length} keys`); + + for (let i = 0; i < privateKeys.length; i++) { + const privateKey = new Buffer(Buffer.from(privateKeys[i], 'latin1').toString('hex'), 'hex'); + const key = wif.encode(0xbc, privateKey, true); + const keyObj = wif.decode(key); + const wifKey = wif.encode(keyObj); + + const keyPair = shepherd.bitcoinJS.ECPair.fromWIF(wifKey, shepherd.electrumJSNetworks.komodo); + const _keyPair = { + priv: keyPair.toWIF(), + pub: keyPair.getAddress(), + }; + + if (req.query.search) { + if (_keyPair.pub.indexOf(req.query.search) > -1) { + _keys.push(_keyPair); + } + } else { _keys.push(_keyPair); } - } else { - _keys.push(_keyPair); } - } - successObj = { - msg: 'success', - result: _keys, - }; + successObj = { + msg: 'success', + result: _keys, + }; - res.end(JSON.stringify(successObj)); + res.end(JSON.stringify(successObj)); + } } - } - }); - } - }); - } catch (e) { - successObj = { + }); + } + }); + } catch (e) { + successObj = { + msg: 'error', + result: `error reading ${_walletDatLocation}`, + }; + + res.end(JSON.stringify(successObj)); + } + } else { + const errorObj = { msg: 'error', - result: `error reading ${_walletDatLocation}`, + result: 'unauthorized access', }; - res.end(JSON.stringify(successObj)); + res.end(JSON.stringify(errorObj)); } }); diff --git a/routes/shepherd/coins.js b/routes/shepherd/coins.js index f74e778..aa614f2 100644 --- a/routes/shepherd/coins.js +++ b/routes/shepherd/coins.js @@ -4,27 +4,36 @@ module.exports = (shepherd) => { * */ shepherd.get('/InstantDEX/allcoins', (req, res, next) => { - let successObj; - let nativeCoindList = []; - let electrumCoinsList = []; + if (shepherd.checkToken(req.query.token)) { + let successObj; + let nativeCoindList = []; + let electrumCoinsList = []; - for (let key in shepherd.electrumCoins) { - if (key !== 'auth') { - electrumCoinsList.push(shepherd.electrumCoins[key].abbr); + for (let key in shepherd.electrumCoins) { + if (key !== 'auth') { + electrumCoinsList.push(shepherd.electrumCoins[key].abbr); + } } - } - for (let key in shepherd.coindInstanceRegistry) { - nativeCoindList.push(key === 'komodod' ? 'KMD' : key); - } + for (let key in shepherd.coindInstanceRegistry) { + nativeCoindList.push(key === 'komodod' ? 'KMD' : key); + } - successObj = { - native: nativeCoindList, - spv: electrumCoinsList, - total: Object.keys(shepherd.electrumCoins).length - 1 + Object.keys(nativeCoindList).length, - }; + successObj = { + native: nativeCoindList, + spv: electrumCoinsList, + total: Object.keys(shepherd.electrumCoins).length - 1 + Object.keys(nativeCoindList).length, + }; - res.end(JSON.stringify(successObj)); + res.end(JSON.stringify(successObj)); + } else { + const errorObj = { + msg: 'error', + result: 'unauthorized access', + }; + + res.end(JSON.stringify(errorObj)); + } }); return shepherd; diff --git a/routes/shepherd/coinsList.js b/routes/shepherd/coinsList.js index dfe13e1..de4f6e3 100644 --- a/routes/shepherd/coinsList.js +++ b/routes/shepherd/coinsList.js @@ -4,28 +4,37 @@ module.exports = (shepherd) => { * */ shepherd.get('/coinslist', (req, res, next) => { - if (shepherd.fs.existsSync(`${shepherd.agamaDir}/shepherd/coinslist.json`)) { - shepherd.fs.readFile(`${shepherd.agamaDir}/shepherd/coinslist.json`, 'utf8', (err, data) => { - if (err) { - const errorObj = { - msg: 'error', - result: err, - }; + if (shepherd.checkToken(req.query.token)) { + if (shepherd.fs.existsSync(`${shepherd.agamaDir}/shepherd/coinslist.json`)) { + shepherd.fs.readFile(`${shepherd.agamaDir}/shepherd/coinslist.json`, 'utf8', (err, data) => { + if (err) { + const errorObj = { + msg: 'error', + result: err, + }; - res.end(JSON.stringify(errorObj)); - } else { - const successObj = { - msg: 'success', - result: data ? JSON.parse(data) : '', - }; + res.end(JSON.stringify(errorObj)); + } else { + const successObj = { + msg: 'success', + result: data ? JSON.parse(data) : '', + }; - res.end(JSON.stringify(successObj)); - } - }); + res.end(JSON.stringify(successObj)); + } + }); + } else { + const errorObj = { + msg: 'error', + result: 'coin list doesn\'t exist', + }; + + res.end(JSON.stringify(errorObj)); + } } else { const errorObj = { msg: 'error', - result: 'coin list doesn\'t exist', + result: 'unauthorized access', }; res.end(JSON.stringify(errorObj)); @@ -37,33 +46,42 @@ module.exports = (shepherd) => { * params: payload */ shepherd.post('/coinslist', (req, res, next) => { - const _payload = req.body.payload; + if (shepherd.checkToken(req.body.token)) { + const _payload = req.body.payload; + + if (!_payload) { + const errorObj = { + msg: 'error', + result: 'no payload provided', + }; + + res.end(JSON.stringify(errorObj)); + } else { + shepherd.fs.writeFile(`${shepherd.agamaDir}/shepherd/coinslist.json`, JSON.stringify(_payload), (err) => { + if (err) { + const errorObj = { + msg: 'error', + result: err, + }; + + res.end(JSON.stringify(errorObj)); + } else { + const successObj = { + msg: 'success', + result: 'done', + }; - if (!_payload) { + res.end(JSON.stringify(successObj)); + } + }); + } + } else { const errorObj = { msg: 'error', - result: 'no payload provided', + result: 'unauthorized access', }; res.end(JSON.stringify(errorObj)); - } else { - shepherd.fs.writeFile(`${shepherd.agamaDir}/shepherd/coinslist.json`, JSON.stringify(_payload), (err) => { - if (err) { - const errorObj = { - msg: 'error', - result: err, - }; - - res.end(JSON.stringify(errorObj)); - } else { - const successObj = { - msg: 'success', - result: 'done', - }; - - res.end(JSON.stringify(successObj)); - } - }); } }); diff --git a/routes/shepherd/config.js b/routes/shepherd/config.js index 6d4f06c..30629d7 100644 --- a/routes/shepherd/config.js +++ b/routes/shepherd/config.js @@ -105,22 +105,31 @@ module.exports = (shepherd) => { * params: payload */ shepherd.post('/appconf', (req, res, next) => { - if (!req.body.payload) { + if (shepherd.checkToken(req.body.token)) { + if (!req.body.payload) { + const errorObj = { + msg: 'error', + result: 'no payload provided', + }; + + res.end(JSON.stringify(errorObj)); + } else { + shepherd.saveLocalAppConf(req.body.payload); + + const successObj = { + msg: 'success', + result: 'config saved', + }; + + res.end(JSON.stringify(successObj)); + } + } else { const errorObj = { msg: 'error', - result: 'no payload provided', + result: 'unauthorized access', }; res.end(JSON.stringify(errorObj)); - } else { - shepherd.saveLocalAppConf(req.body.payload); - - const successObj = { - msg: 'success', - result: 'config saved', - }; - - res.end(JSON.stringify(successObj)); } }); @@ -129,14 +138,23 @@ module.exports = (shepherd) => { * params: none */ shepherd.post('/appconf/reset', (req, res, next) => { - shepherd.saveLocalAppConf(shepherd.defaultAppConfig); + if (shepherd.checkToken(req.body.token)) { + shepherd.saveLocalAppConf(shepherd.defaultAppConfig); + + const successObj = { + msg: 'success', + result: 'config saved', + }; - const successObj = { - msg: 'success', - result: 'config saved', - }; + res.end(JSON.stringify(successObj)); + } else { + const errorObj = { + msg: 'error', + result: 'unauthorized access', + }; - res.end(JSON.stringify(successObj)); + res.end(JSON.stringify(errorObj)); + } }); /* @@ -144,8 +162,17 @@ module.exports = (shepherd) => { * */ shepherd.get('/appconf', (req, res, next) => { - const obj = shepherd.loadLocalConfig(); - res.send(obj); + if (shepherd.checkToken(req.query.token)) { + const obj = shepherd.loadLocalConfig(); + res.send(obj); + } else { + const errorObj = { + msg: 'error', + result: 'unauthorized access', + }; + + res.end(JSON.stringify(errorObj)); + } }); return shepherd; diff --git a/routes/shepherd/daemonControl.js b/routes/shepherd/daemonControl.js index b936e80..67eade4 100644 --- a/routes/shepherd/daemonControl.js +++ b/routes/shepherd/daemonControl.js @@ -792,69 +792,81 @@ module.exports = (shepherd) => { * params: herd */ shepherd.post('/herd', (req, res) => { - const _body = req.body; - shepherd.log('herd req.body =>'); - shepherd.log(_body); - - if (_body.options && - !shepherd.kmdMainPassiveMode) { - const testCoindPort = (skipError) => { - const _acName = req.body.options.ac_name; - - if (!shepherd.lockDownAddCoin) { - const _port = shepherd.assetChainPorts[_acName]; - - portscanner.checkPortStatus(_port, '127.0.0.1', (error, status) => { - // Status is 'open' if currently in use or 'closed' if available - if (status === 'open' && - shepherd.appConfig.stopNativeDaemonsOnQuit) { - if (!skipError) { - shepherd.log(`komodod service start error at port ${_port}, reason: port is closed`); - shepherd.writeLog(`komodod service start error at port ${_port}, reason: port is closed`); - shepherd.io.emit('service', { - komodod: { - error: `error starting ${_body.herd} ${_acName} daemon. Port ${_port} is already taken!`, - }, - }); + if (shepherd.checkToken(req.body.token)) { + const _body = req.body; + shepherd.log('herd req.body =>'); + shepherd.log(_body); + + if (_body.options && + !shepherd.kmdMainPassiveMode) { + const testCoindPort = (skipError) => { + const _acName = req.body.options.ac_name; + + if (!shepherd.lockDownAddCoin) { + const _port = shepherd.assetChainPorts[_acName]; + + portscanner.checkPortStatus(_port, '127.0.0.1', (error, status) => { + // Status is 'open' if currently in use or 'closed' if available + if (status === 'open' && + shepherd.appConfig.stopNativeDaemonsOnQuit) { + if (!skipError) { + shepherd.log(`komodod service start error at port ${_port}, reason: port is closed`); + shepherd.writeLog(`komodod service start error at port ${_port}, reason: port is closed`); + shepherd.io.emit('service', { + komodod: { + error: `error starting ${_body.herd} ${_acName} daemon. Port ${_port} is already taken!`, + }, + }); - const obj = { - msg: 'error', - result: `error starting ${_body.herd} ${_acName} daemon. Port ${_port} is already taken!`, - }; + const obj = { + msg: 'error', + result: `error starting ${_body.herd} ${_acName} daemon. Port ${_port} is already taken!`, + }; - res.status(500); - res.end(JSON.stringify(obj)); + res.status(500); + res.end(JSON.stringify(obj)); + } else { + shepherd.log(`komodod service start success at port ${_port}`); + shepherd.writeLog(`komodod service start success at port ${_port}`); + } } else { - shepherd.log(`komodod service start success at port ${_port}`); - shepherd.writeLog(`komodod service start success at port ${_port}`); - } - } else { - if (!skipError) { - herder(_body.herd, _body.options); + if (!skipError) { + herder(_body.herd, _body.options); - const obj = { - msg: 'success', - result: 'result', - }; + const obj = { + msg: 'success', + result: 'result', + }; - res.end(JSON.stringify(obj)); - } else { - shepherd.log(`komodod service start error at port ${_port}, reason: unknown`); - shepherd.writeLog(`komodod service start error at port ${_port}, reason: unknown`); + res.end(JSON.stringify(obj)); + } else { + shepherd.log(`komodod service start error at port ${_port}, reason: unknown`); + shepherd.writeLog(`komodod service start error at port ${_port}, reason: unknown`); + } } - } - }); + }); + } } - } - if (_body.herd === 'komodod') { - // check if komodod instance is already running - testCoindPort(); - setTimeout(() => { - testCoindPort(true); - }, 10000); + if (_body.herd === 'komodod') { + // check if komodod instance is already running + testCoindPort(); + setTimeout(() => { + testCoindPort(true); + }, 10000); + } else { + herder(_body.herd, _body.options, _body.coind); + + const obj = { + msg: 'success', + result: 'result', + }; + + res.end(JSON.stringify(obj)); + } } else { - herder(_body.herd, _body.options, _body.coind); + // (?) + herder(_body.herd, _body.options); const obj = { msg: 'success', @@ -864,15 +876,12 @@ module.exports = (shepherd) => { res.end(JSON.stringify(obj)); } } else { - // (?) - herder(_body.herd, _body.options); - - const obj = { - msg: 'success', - result: 'result', + const errorObj = { + msg: 'error', + result: 'unauthorized access', }; - res.end(JSON.stringify(obj)); + res.end(JSON.stringify(errorObj)); } }); @@ -880,46 +889,64 @@ module.exports = (shepherd) => { * type: POST */ shepherd.post('/setconf', (req, res) => { - const _body = req.body; + if (shepherd.checkToken(req.body.token)) { + const _body = req.body; - shepherd.log('setconf req.body =>'); - shepherd.log(_body); + shepherd.log('setconf req.body =>'); + shepherd.log(_body); - if (os.platform() === 'win32' && - _body.chain == 'komodod') { - setkomodoconf = spawn(path.join(__dirname, '../assets/bin/win64/genkmdconf.bat')); - } else { - shepherd.setConf(_body.chain); - } + if (os.platform() === 'win32' && + _body.chain == 'komodod') { + setkomodoconf = spawn(path.join(__dirname, '../assets/bin/win64/genkmdconf.bat')); + } else { + shepherd.setConf(_body.chain); + } - const obj = { - msg: 'success', - result: 'result', - }; + const obj = { + msg: 'success', + result: 'result', + }; + + res.end(JSON.stringify(obj)); + } else { + const errorObj = { + msg: 'error', + result: 'unauthorized access', + }; - res.end(JSON.stringify(obj)); + res.end(JSON.stringify(errorObj)); + } }); /* * type: POST */ shepherd.post('/getconf', (req, res) => { - const _body = req.body; + if (shepherd.checkToken(req.body.token)) { + const _body = req.body; - shepherd.log('getconf req.body =>'); - shepherd.log(_body); + shepherd.log('getconf req.body =>'); + shepherd.log(_body); - const confpath = getConf(_body.chain, _body.coind); + const confpath = getConf(_body.chain, _body.coind); - shepherd.log(`getconf path is: ${confpath}`); - shepherd.writeLog(`getconf path is: ${confpath}`); + shepherd.log(`getconf path is: ${confpath}`); + shepherd.writeLog(`getconf path is: ${confpath}`); - const obj = { - msg: 'success', - result: confpath, - }; + const obj = { + msg: 'success', + result: confpath, + }; - res.end(JSON.stringify(obj)); + res.end(JSON.stringify(obj)); + } else { + const errorObj = { + msg: 'error', + result: 'unauthorized access', + }; + + res.end(JSON.stringify(errorObj)); + } }); shepherd.setConfKMD = (isChips) => { diff --git a/routes/shepherd/dashboardUpdate.js b/routes/shepherd/dashboardUpdate.js index 99ecfb4..f87abd7 100644 --- a/routes/shepherd/dashboardUpdate.js +++ b/routes/shepherd/dashboardUpdate.js @@ -7,171 +7,186 @@ module.exports = (shepherd) => { * params: coin */ shepherd.post('/native/dashboard/update', (req, res, next) => { - const _coin = req.body.coin; - let _returnObj; - let _promiseStack; - - if (_coin === 'CHIPS') { - _returnObj = { - getinfo: {}, - listtransactions: [], - getbalance: {}, - listunspent: {}, - addresses: {}, - }; - _promiseStack = [ - 'getinfo', - 'listtransactions', - 'getbalance', - ]; - } else { - _returnObj = { - getinfo: {}, - listtransactions: [], - z_gettotalbalance: {}, - z_getoperationstatus: {}, - listunspent: {}, - addresses: {}, - }; - _promiseStack = [ - 'getinfo', - 'listtransactions', - 'z_gettotalbalance', - 'z_getoperationstatus' - ]; - } + if (shepherd.checkToken(req.body.token)) { + const _coin = req.body.coin; + const _token = req.body.token; + let _returnObj; + let _promiseStack; + + if (_coin === 'CHIPS') { + _returnObj = { + getinfo: {}, + listtransactions: [], + getbalance: {}, + listunspent: {}, + addresses: {}, + }; + _promiseStack = [ + 'getinfo', + 'listtransactions', + 'getbalance', + ]; + } else { + _returnObj = { + getinfo: {}, + listtransactions: [], + z_gettotalbalance: {}, + z_getoperationstatus: {}, + listunspent: {}, + addresses: {}, + }; + _promiseStack = [ + 'getinfo', + 'listtransactions', + 'z_gettotalbalance', + 'z_getoperationstatus' + ]; + } - const getAddressesNative = (coin) => { - const type = [ - 'public', - 'private' - ]; + const getAddressesNative = (coin) => { + const type = [ + 'public', + 'private' + ]; - if (coin === 'CHIPS') { - type.pop(); - } + if (coin === 'CHIPS') { + type.pop(); + } - Promise.all(type.map((_type, index) => { - return new Promise((resolve, reject) => { - _bitcoinRPC( - coin, - _type === 'public' ? 'getaddressesbyaccount' : 'z_listaddresses', - [''] - ).then((_json) => { - if (_json === 'Work queue depth exceeded' || - !_json) { - resolve({ error: 'daemon is busy' }); - } else { - resolve(JSON.parse(_json).result); - } + Promise.all(type.map((_type, index) => { + return new Promise((resolve, reject) => { + _bitcoinRPC( + coin, + _type === 'public' ? 'getaddressesbyaccount' : 'z_listaddresses', + [''] + ).then((_json) => { + if (_json === 'Work queue depth exceeded' || + !_json) { + resolve({ error: 'daemon is busy' }); + } else { + resolve(JSON.parse(_json).result); + } + }); }); - }); - })) - .then(result => { - if (result[0] && - result[0].length && - result[0][0].length && - result[0][0].length > 10) { - const calcBalance = (result, json) => { - if (json && - json.length && - json[0] && - json[0].address) { - const allAddrArray = json.map(res => res.address).filter((x, i, a) => a.indexOf(x) == i); - - for (let a = 0; a < allAddrArray.length; a++) { - const filteredArray = json.filter(res => res.address === allAddrArray[a]).map(res => res.amount); - - let isNewAddr = true; - for (let x = 0; x < result.length && isNewAddr; x++) { - for (let y = 0; y < result[x].length && isNewAddr; y++) { - if (allAddrArray[a] === result[x][y]) { - isNewAddr = false; + })) + .then(result => { + if (result[0] && + result[0].length && + result[0][0].length && + result[0][0].length > 10) { + const calcBalance = (result, json) => { + if (json && + json.length && + json[0] && + json[0].address) { + const allAddrArray = json.map(res => res.address).filter((x, i, a) => a.indexOf(x) == i); + + for (let a = 0; a < allAddrArray.length; a++) { + const filteredArray = json.filter(res => res.address === allAddrArray[a]).map(res => res.amount); + + let isNewAddr = true; + for (let x = 0; x < result.length && isNewAddr; x++) { + for (let y = 0; y < result[x].length && isNewAddr; y++) { + if (allAddrArray[a] === result[x][y]) { + isNewAddr = false; + } } } - } - if (isNewAddr && - (allAddrArray[a].substring(0, 2) === 'zc' || - allAddrArray[a].substring(0, 2) === 'zt')) { - result[1][result[1].length] = allAddrArray[a]; - } else { - result[0][result[0].length] = allAddrArray[a]; + if (isNewAddr && + (allAddrArray[a].substring(0, 2) === 'zc' || + allAddrArray[a].substring(0, 2) === 'zt')) { + result[1][result[1].length] = allAddrArray[a]; + } else { + result[0][result[0].length] = allAddrArray[a]; + } } } - } - // remove addr duplicates - if (result[0] && - result[0].length) { - result[0] = result[0].filter((elem, pos) => { - return result[0].indexOf(elem) === pos; - }); - } - if (result[1] && - result[1].length) { - result[1] = result[1].filter((elem, pos) => { - return result[1].indexOf(elem) === pos; - }); - } + // remove addr duplicates + if (result[0] && + result[0].length) { + result[0] = result[0].filter((elem, pos) => { + return result[0].indexOf(elem) === pos; + }); + } + if (result[1] && + result[1].length) { + result[1] = result[1].filter((elem, pos) => { + return result[1].indexOf(elem) === pos; + }); + } - let newAddressArray = []; - for (let a = 0; a < result.length; a++) { - newAddressArray[a] = []; + let newAddressArray = []; + for (let a = 0; a < result.length; a++) { + newAddressArray[a] = []; - if (result[a]) { - for (let b = 0; b < result[a].length; b++) { - const filteredArraySpends = json.filter(res => res.address === result[a][b]); - const filteredArray = json.filter(res => res.address === result[a][b]).map(res => res.amount); + if (result[a]) { + for (let b = 0; b < result[a].length; b++) { + const filteredArraySpends = json.filter(res => res.address === result[a][b]); + const filteredArray = json.filter(res => res.address === result[a][b]).map(res => res.amount); - let sum = 0; - let spendableSum = 0; - let canspend = true; + let sum = 0; + let spendableSum = 0; + let canspend = true; - for (let i = 0; i < filteredArray.length; i++) { - sum += filteredArray[i]; + for (let i = 0; i < filteredArray.length; i++) { + sum += filteredArray[i]; - if (filteredArraySpends[i].spendable) { - spendableSum += filteredArray[i]; - } else { - canspend = false; + if (filteredArraySpends[i].spendable) { + spendableSum += filteredArray[i]; + } else { + canspend = false; + } } - } - newAddressArray[a][b] = { - address: result[a][b], - amount: sum, - spendable: spendableSum, - canspend, - type: a === 0 ? 'public': 'private', - }; + newAddressArray[a][b] = { + address: result[a][b], + amount: sum, + spendable: spendableSum, + canspend, + type: a === 0 ? 'public': 'private', + }; + } } } - } - // get zaddr balance - if (result[1] && - result[1].length) { - Promise.all(result[1].map((_address, index) => { - return new Promise((resolve, reject) => { - _bitcoinRPC(coin, 'z_getbalance', [_address]) - .then((__json) => { - __json = JSON.parse(__json); - if (__json && - __json.error) { - resolve(0); - } else { - resolve(__json.result); - newAddressArray[1][index] = { - address: _address, - amount: __json.result, - type: 'private', - }; - } + // get zaddr balance + if (result[1] && + result[1].length) { + Promise.all(result[1].map((_address, index) => { + return new Promise((resolve, reject) => { + _bitcoinRPC(coin, 'z_getbalance', [_address]) + .then((__json) => { + __json = JSON.parse(__json); + if (__json && + __json.error) { + resolve(0); + } else { + resolve(__json.result); + newAddressArray[1][index] = { + address: _address, + amount: __json.result, + type: 'private', + }; + } + }); }); + })) + .then(zresult => { + _returnObj.addresses = { + public: newAddressArray[0], + private: newAddressArray[1], + }; + + const returnObj = { + msg: 'success', + result: _returnObj, + }; + + res.end(JSON.stringify(returnObj)); }); - })) - .then(zresult => { + } else { _returnObj.addresses = { public: newAddressArray[0], private: newAddressArray[1], @@ -183,131 +198,128 @@ module.exports = (shepherd) => { }; res.end(JSON.stringify(returnObj)); - }); - } else { - _returnObj.addresses = { - public: newAddressArray[0], - private: newAddressArray[1], - }; - - const returnObj = { - msg: 'success', - result: _returnObj, - }; - - res.end(JSON.stringify(returnObj)); + } } - } - - _bitcoinRPC(coin, 'listunspent') - .then((__json) => { - if (__json === 'Work queue depth exceeded' || - !__json) { - const returnObj = { - msg: 'success', - result: _returnObj, - }; - - res.end(JSON.stringify(returnObj)); - } else { - _returnObj.listunspent = JSON.parse(__json); - calcBalance( - result, - JSON.parse(__json).result - ); - } - }); - } else { - _returnObj.addresses = { - public: {}, - private: {}, - }; + _bitcoinRPC(coin, 'listunspent') + .then((__json) => { + if (__json === 'Work queue depth exceeded' || + !__json) { + const returnObj = { + msg: 'success', + result: _returnObj, + }; - const returnObj = { - msg: 'success', - result: _returnObj, - }; + res.end(JSON.stringify(returnObj)); + } else { + _returnObj.listunspent = JSON.parse(__json); - res.end(JSON.stringify(returnObj)); - } - }) - } + calcBalance( + result, + JSON.parse(__json).result + ); + } + }); + } else { + _returnObj.addresses = { + public: {}, + private: {}, + }; - const _bitcoinRPC = (coin, cmd, params) => { - return new Promise((resolve, reject) => { - let _payload; - - if (params) { - _payload = { - mode: null, - chain: coin, - cmd: cmd, - params: params, - rpc2cli: req.body.rpc2cli, - }; - } else { - _payload = { - mode: null, - chain: coin, - cmd: cmd, - rpc2cli: req.body.rpc2cli, - }; - } + const returnObj = { + msg: 'success', + result: _returnObj, + }; - const options = { - url: `http://127.0.0.1:${shepherd.appConfig.agamaPort}/shepherd/cli`, - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ payload: _payload }), - timeout: 120000, - }; + res.end(JSON.stringify(returnObj)); + } + }) + } - shepherd.request(options, (error, response, body) => { - if (response && - response.statusCode && - response.statusCode === 200) { - resolve(body); + const _bitcoinRPC = (coin, cmd, params) => { + return new Promise((resolve, reject) => { + let _payload; + + if (params) { + _payload = { + mode: null, + chain: coin, + cmd: cmd, + params: params, + rpc2cli: req.body.rpc2cli, + token: _token, + }; } else { - resolve(body); + _payload = { + mode: null, + chain: coin, + cmd: cmd, + rpc2cli: req.body.rpc2cli, + token: _token, + }; } - }); - }); - } - Promise.all(_promiseStack.map((_call, index) => { - let _params; + const options = { + url: `http://127.0.0.1:${shepherd.appConfig.agamaPort}/shepherd/cli`, + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ payload: _payload }), + timeout: 120000, + }; - if (_call === 'listtransactions') { - _params = [ - '*', - 300, - 0 - ]; + shepherd.request(options, (error, response, body) => { + if (response && + response.statusCode && + response.statusCode === 200) { + resolve(body); + } else { + resolve(body); + } + }); + }); } - return new Promise((resolve, reject) => { - _bitcoinRPC( - _coin, - _call, - _params - ) - .then((json) => { - if (json === 'Work queue depth exceeded' || - !json) { - _returnObj[_call] = { error: 'daemon is busy' }; - } else { - _returnObj[_call] = JSON.parse(json); - } - resolve(json); + Promise.all(_promiseStack.map((_call, index) => { + let _params; + + if (_call === 'listtransactions') { + _params = [ + '*', + 300, + 0 + ]; + } + + return new Promise((resolve, reject) => { + _bitcoinRPC( + _coin, + _call, + _params + ) + .then((json) => { + if (json === 'Work queue depth exceeded' || + !json) { + _returnObj[_call] = { error: 'daemon is busy' }; + } else { + _returnObj[_call] = JSON.parse(json); + } + resolve(json); + }); }); + })) + .then(result => { + getAddressesNative(_coin); }); - })) - .then(result => { - getAddressesNative(_coin); - }); + } else { + const errorObj = { + msg: 'error', + result: 'unauthorized access', + }; + + res.end(JSON.stringify(errorObj)); + } }); return shepherd; diff --git a/routes/shepherd/debugLog.js b/routes/shepherd/debugLog.js index 5fd0c88..9970e8b 100644 --- a/routes/shepherd/debugLog.js +++ b/routes/shepherd/debugLog.js @@ -4,74 +4,92 @@ module.exports = (shepherd) => { * params: herd, lastLines */ shepherd.post('/debuglog', (req, res) => { - let _herd = req.body.herdname; - let _ac = req.body.ac; - let _lastNLines = req.body.lastLines; - let _location; - - if (shepherd.os.platform() === 'darwin') { - shepherd.komodoDir = shepherd.appConfig.dataDir.length ? shepherd.appConfig.dataDir : `${process.env.HOME}/Library/Application Support/Komodo`; - } + if (shepherd.checkToken(req.body.token)) { + let _herd = req.body.herdname; + let _ac = req.body.ac; + let _lastNLines = req.body.lastLines; + let _location; + + if (shepherd.os.platform() === 'darwin') { + shepherd.komodoDir = shepherd.appConfig.dataDir.length ? shepherd.appConfig.dataDir : `${process.env.HOME}/Library/Application Support/Komodo`; + } - if (shepherd.os.platform() === 'linux') { - shepherd.komodoDir = shepherd.appConfig.dataDir.length ? shepherd.appConfig.dataDir : `${process.env.HOME}/.komodo`; - } + if (shepherd.os.platform() === 'linux') { + shepherd.komodoDir = shepherd.appConfig.dataDir.length ? shepherd.appConfig.dataDir : `${process.env.HOME}/.komodo`; + } - if (shepherd.os.platform() === 'win32') { - shepherd.komodoDir = shepherd.appConfig.dataDir.length ? shepherd.appConfig.dataDir : `${process.env.APPDATA}/Komodo`; - shepherd.komodoDir = shepherd.path.normalize(shepherd.komodoDir); - } + if (shepherd.os.platform() === 'win32') { + shepherd.komodoDir = shepherd.appConfig.dataDir.length ? shepherd.appConfig.dataDir : `${process.env.APPDATA}/Komodo`; + shepherd.komodoDir = shepherd.path.normalize(shepherd.komodoDir); + } - if (_herd === 'komodo') { - _location = shepherd.komodoDir; - } + if (_herd === 'komodo') { + _location = shepherd.komodoDir; + } - if (_ac) { - _location = `${shepherd.komodoDir}/${_ac}`; + if (_ac) { + _location = `${shepherd.komodoDir}/${_ac}`; - if (_ac === 'CHIPS') { - _location = shepherd.chipsDir; + if (_ac === 'CHIPS') { + _location = shepherd.chipsDir; + } } - } - - shepherd.readDebugLog(`${_location}/debug.log`, _lastNLines) - .then((result) => { - const _obj = { - msg: 'success', - result: result, - }; - res.end(JSON.stringify(_obj)); - }, (result) => { - const _obj = { + shepherd.readDebugLog(`${_location}/debug.log`, _lastNLines) + .then((result) => { + const _obj = { + msg: 'success', + result: result, + }; + + res.end(JSON.stringify(_obj)); + }, (result) => { + const _obj = { + msg: 'error', + result: result, + }; + + res.end(JSON.stringify(_obj)); + }); + } else { + const errorObj = { msg: 'error', - result: result, + result: 'unauthorized access', }; - res.end(JSON.stringify(_obj)); - }); + res.end(JSON.stringify(errorObj)); + } }); shepherd.get('/coind/stdout', (req, res) => { - const _daemonName = req.query.chain !== 'komodod' ? req.query.chain : 'komodod'; - const _daemonLogName = `${shepherd.agamaDir}/${_daemonName}.log`; - - shepherd.readDebugLog(_daemonLogName, 'all') - .then((result) => { - const _obj = { - msg: 'success', - result: result, - }; - - res.end(JSON.stringify(_obj)); - }, (result) => { - const _obj = { + if (shepherd.checkToken(req.query.token)) { + const _daemonName = req.query.chain !== 'komodod' ? req.query.chain : 'komodod'; + const _daemonLogName = `${shepherd.agamaDir}/${_daemonName}.log`; + + shepherd.readDebugLog(_daemonLogName, 'all') + .then((result) => { + const _obj = { + msg: 'success', + result: result, + }; + + res.end(JSON.stringify(_obj)); + }, (result) => { + const _obj = { + msg: 'error', + result: result, + }; + + res.end(JSON.stringify(_obj)); + }); + } else { + const errorObj = { msg: 'error', - result: result, + result: 'unauthorized access', }; - res.end(JSON.stringify(_obj)); - }); + res.end(JSON.stringify(errorObj)); + } }); shepherd.readDebugLog = (fileLocation, lastNLines) => { diff --git a/routes/shepherd/downloadBins.js b/routes/shepherd/downloadBins.js index c3e48da..f4dcfe9 100644 --- a/routes/shepherd/downloadBins.js +++ b/routes/shepherd/downloadBins.js @@ -46,51 +46,60 @@ module.exports = (shepherd) => { */ // TODO: promises shepherd.get('/update/bins/check', (req, res, next) => { - const rootLocation = shepherd.path.join(__dirname, '../../'); - const successObj = { - msg: 'success', - result: 'bins', - }; - - res.end(JSON.stringify(successObj)); - - const _os = shepherd.os.platform(); - shepherd.log(`checking bins: ${_os}`); - - shepherd.io.emit('patch', { - patch: { - type: 'bins-check', - status: 'progress', - message: `checking bins: ${_os}`, - }, - }); - // get list of bins/dlls that can be updated to the latest - for (let i = 0; i < latestBins[_os].length; i++) { - shepherd.remoteFileSize(remoteBinLocation[_os] + latestBins[_os][i], (err, remoteBinSize) => { - const localBinSize = shepherd.fs.statSync(rootLocation + localBinLocation[_os] + latestBins[_os][i]).size; - - shepherd.log('remote url: ' + (remoteBinLocation[_os] + latestBins[_os][i]) + ' (' + remoteBinSize + ')'); - shepherd.log('local file: ' + (rootLocation + localBinLocation[_os] + latestBins[_os][i]) + ' (' + localBinSize + ')'); - - if (remoteBinSize !== localBinSize) { - shepherd.log(`${latestBins[_os][i]} can be updated`); - binsToUpdate.push({ - name: latestBins[_os][i], - rSize: remoteBinSize, - lSize: localBinSize, - }); - } - - if (i === latestBins[_os].length - 1) { - shepherd.io.emit('patch', { - patch: { - type: 'bins-check', - status: 'done', - fileList: binsToUpdate, - }, - }); - } + if (shepherd.checkToken(req.query.token)) { + const rootLocation = shepherd.path.join(__dirname, '../../'); + const successObj = { + msg: 'success', + result: 'bins', + }; + + res.end(JSON.stringify(successObj)); + + const _os = shepherd.os.platform(); + shepherd.log(`checking bins: ${_os}`); + + shepherd.io.emit('patch', { + patch: { + type: 'bins-check', + status: 'progress', + message: `checking bins: ${_os}`, + }, }); + // get list of bins/dlls that can be updated to the latest + for (let i = 0; i < latestBins[_os].length; i++) { + shepherd.remoteFileSize(remoteBinLocation[_os] + latestBins[_os][i], (err, remoteBinSize) => { + const localBinSize = shepherd.fs.statSync(rootLocation + localBinLocation[_os] + latestBins[_os][i]).size; + + shepherd.log('remote url: ' + (remoteBinLocation[_os] + latestBins[_os][i]) + ' (' + remoteBinSize + ')'); + shepherd.log('local file: ' + (rootLocation + localBinLocation[_os] + latestBins[_os][i]) + ' (' + localBinSize + ')'); + + if (remoteBinSize !== localBinSize) { + shepherd.log(`${latestBins[_os][i]} can be updated`); + binsToUpdate.push({ + name: latestBins[_os][i], + rSize: remoteBinSize, + lSize: localBinSize, + }); + } + + if (i === latestBins[_os].length - 1) { + shepherd.io.emit('patch', { + patch: { + type: 'bins-check', + status: 'done', + fileList: binsToUpdate, + }, + }); + } + }); + } + } else { + const errorObj = { + msg: 'error', + result: 'unauthorized access', + }; + + res.end(JSON.stringify(errorObj)); } }); @@ -100,64 +109,73 @@ module.exports = (shepherd) => { * params: */ shepherd.get('/update/bins', (req, res, next) => { - const rootLocation = shepherd.path.join(__dirname, '../../'); - const _os = shepherd.os.platform(); - const successObj = { - msg: 'success', - result: { - filesCount: binsToUpdate.length, - list: binsToUpdate, - }, - }; - - res.end(JSON.stringify(successObj)); - - for (let i = 0; i < binsToUpdate.length; i++) { - shepherd.downloadFile({ - remoteFile: remoteBinLocation[_os] + binsToUpdate[i].name, - localFile: `${rootLocation}${localBinLocation[_os]}patch/${binsToUpdate[i].name}`, - onProgress: (received, total) => { - const percentage = (received * 100) / total; - - if (percentage.toString().indexOf('.10') > -1) { + if (shepherd.checkToken(req.query.token)) { + const rootLocation = shepherd.path.join(__dirname, '../../'); + const _os = shepherd.os.platform(); + const successObj = { + msg: 'success', + result: { + filesCount: binsToUpdate.length, + list: binsToUpdate, + }, + }; + + res.end(JSON.stringify(successObj)); + + for (let i = 0; i < binsToUpdate.length; i++) { + shepherd.downloadFile({ + remoteFile: remoteBinLocation[_os] + binsToUpdate[i].name, + localFile: `${rootLocation}${localBinLocation[_os]}patch/${binsToUpdate[i].name}`, + onProgress: (received, total) => { + const percentage = (received * 100) / total; + + if (percentage.toString().indexOf('.10') > -1) { + shepherd.io.emit('patch', { + msg: { + type: 'bins-update', + status: 'progress', + file: binsToUpdate[i].name, + bytesTotal: total, + bytesReceived: received, + }, + }); + // shepherd.log(`${binsToUpdate[i].name} ${percentage}% | ${received} bytes out of ${total} bytes.`); + } + } + }) + .then(() => { + // verify that remote file is matching to DL'ed file + const localBinSize = shepherd.fs.statSync(`${rootLocation}${localBinLocation[_os]}patch/${binsToUpdate[i].name}`).size; + shepherd.log('compare dl file size'); + + if (localBinSize === binsToUpdate[i].rSize) { shepherd.io.emit('patch', { msg: { type: 'bins-update', - status: 'progress', file: binsToUpdate[i].name, - bytesTotal: total, - bytesReceived: received, + status: 'done', }, }); - // shepherd.log(`${binsToUpdate[i].name} ${percentage}% | ${received} bytes out of ${total} bytes.`); + shepherd.log(`file ${binsToUpdate[i].name} succesfully downloaded`); + } else { + shepherd.io.emit('patch', { + msg: { + type: 'bins-update', + file: binsToUpdate[i].name, + message: 'size mismatch', + }, + }); + shepherd.log(`error: ${binsToUpdate[i].name} file size doesnt match remote!`); } - } - }) - .then(() => { - // verify that remote file is matching to DL'ed file - const localBinSize = shepherd.fs.statSync(`${rootLocation}${localBinLocation[_os]}patch/${binsToUpdate[i].name}`).size; - shepherd.log('compare dl file size'); - - if (localBinSize === binsToUpdate[i].rSize) { - shepherd.io.emit('patch', { - msg: { - type: 'bins-update', - file: binsToUpdate[i].name, - status: 'done', - }, - }); - shepherd.log(`file ${binsToUpdate[i].name} succesfully downloaded`); - } else { - shepherd.io.emit('patch', { - msg: { - type: 'bins-update', - file: binsToUpdate[i].name, - message: 'size mismatch', - }, - }); - shepherd.log(`error: ${binsToUpdate[i].name} file size doesnt match remote!`); - } - }); + }); + } + } else { + const errorObj = { + msg: 'error', + result: 'unauthorized access', + }; + + res.end(JSON.stringify(errorObj)); } }); diff --git a/routes/shepherd/downloadPatch.js b/routes/shepherd/downloadPatch.js index f8be045..6cf6cd1 100644 --- a/routes/shepherd/downloadPatch.js +++ b/routes/shepherd/downloadPatch.js @@ -5,14 +5,23 @@ module.exports = (shepherd) => { * params: patchList */ shepherd.get('/update/patch', (req, res, next) => { - const successObj = { - msg: 'success', - result: 'dl started' - }; - - res.end(JSON.stringify(successObj)); - - shepherd.updateAgama(); + if (shepherd.checkToken(req.query.token)) { + const successObj = { + msg: 'success', + result: 'dl started' + }; + + res.end(JSON.stringify(successObj)); + + shepherd.updateAgama(); + } else { + const errorObj = { + msg: 'error', + result: 'unauthorized access', + }; + + res.end(JSON.stringify(errorObj)); + } }); shepherd.updateAgama = () => { @@ -85,51 +94,60 @@ module.exports = (shepherd) => { * params: */ shepherd.get('/update/patch/check', (req, res, next) => { - const rootLocation = shepherd.path.join(__dirname, '../../'); - const options = { - url: 'https://github.com/pbca26/dl-test/raw/master/version', - method: 'GET', - }; - - shepherd.request(options, (error, response, body) => { - if (response && - response.statusCode && - response.statusCode === 200) { - const remoteVersion = body.split('\n'); - const localVersionFile = shepherd.fs.readFileSync(`${rootLocation}version`, 'utf8'); - let localVersion; - - if (localVersionFile.indexOf('\r\n') > -1) { - localVersion = localVersionFile.split('\r\n'); - } else { - localVersion = localVersionFile.split('\n'); - } - - if (remoteVersion[0] === localVersion[0]) { - const successObj = { - msg: 'success', - result: 'latest', - }; + if (shepherd.checkToken(req.query.token)) { + const rootLocation = shepherd.path.join(__dirname, '../../'); + const options = { + url: 'https://github.com/pbca26/dl-test/raw/master/version', + method: 'GET', + }; + + shepherd.request(options, (error, response, body) => { + if (response && + response.statusCode && + response.statusCode === 200) { + const remoteVersion = body.split('\n'); + const localVersionFile = shepherd.fs.readFileSync(`${rootLocation}version`, 'utf8'); + let localVersion; + + if (localVersionFile.indexOf('\r\n') > -1) { + localVersion = localVersionFile.split('\r\n'); + } else { + localVersion = localVersionFile.split('\n'); + } - res.end(JSON.stringify(successObj)); + if (remoteVersion[0] === localVersion[0]) { + const successObj = { + msg: 'success', + result: 'latest', + }; + + res.end(JSON.stringify(successObj)); + } else { + const successObj = { + msg: 'success', + result: 'update', + version: { + local: localVersion[0], + remote: remoteVersion[0], + }, + }; + + res.end(JSON.stringify(successObj)); + } } else { - const successObj = { - msg: 'success', - result: 'update', - version: { - local: localVersion[0], - remote: remoteVersion[0], - }, - }; - - res.end(JSON.stringify(successObj)); + res.end({ + err: 'error getting update', + }); } - } else { - res.end({ - err: 'error getting update', - }); - } - }); + }); + } else { + const errorObj = { + msg: 'error', + result: 'unauthorized access', + }; + + res.end(JSON.stringify(errorObj)); + } }); /* @@ -138,16 +156,25 @@ module.exports = (shepherd) => { * params: */ shepherd.get('/unpack', (req, res, next) => { - const dlLocation = shepherd.path.join(__dirname, '../../'); - const zip = new shepherd.AdmZip(`${dlLocation}patch.zip`); - zip.extractAllTo(/*target path*/ `${dlLocation}/patch/unpack`, /*overwrite*/true); - - const successObj = { - msg: 'success', - result: 'unpack started', - }; - - res.end(JSON.stringify(successObj)); + if (shepherd.checkToken(req.query.token)) { + const dlLocation = shepherd.path.join(__dirname, '../../'); + const zip = new shepherd.AdmZip(`${dlLocation}patch.zip`); + zip.extractAllTo(/*target path*/ `${dlLocation}/patch/unpack`, /*overwrite*/true); + + const successObj = { + msg: 'success', + result: 'unpack started', + }; + + res.end(JSON.stringify(successObj)); + } else { + const errorObj = { + msg: 'error', + result: 'unauthorized access', + }; + + res.end(JSON.stringify(errorObj)); + } }); return shepherd; diff --git a/routes/shepherd/downloadZcparams.js b/routes/shepherd/downloadZcparams.js index 0e520d3..2cc8f8f 100644 --- a/routes/shepherd/downloadZcparams.js +++ b/routes/shepherd/downloadZcparams.js @@ -67,66 +67,75 @@ module.exports = (shepherd) => { * params: */ shepherd.get('/zcparamsdl', (req, res, next) => { - // const dlLocation = shepherd.zcashParamsDir + '/test'; - const dlLocation = shepherd.zcashParamsDir; - const dlOption = req.query.dloption; + if (shepherd.checkToken(req.query.token)) { + // const dlLocation = shepherd.zcashParamsDir + '/test'; + const dlLocation = shepherd.zcashParamsDir; + const dlOption = req.query.dloption; - const successObj = { - msg: 'success', - result: 'zcash params dl started', - }; + const successObj = { + msg: 'success', + result: 'zcash params dl started', + }; + + res.end(JSON.stringify(successObj)); - res.end(JSON.stringify(successObj)); + for (let key in shepherd.zcashParamsDownloadLinks[dlOption]) { + shepherd.downloadFile({ + remoteFile: shepherd.zcashParamsDownloadLinks[dlOption][key], + localFile: `${dlLocation}/sprout-${key}.key`, + onProgress: (received, total) => { + const percentage = (received * 100) / total; + + if (percentage.toString().indexOf('.10') > -1) { + shepherd.io.emit('zcparams', { + msg: { + type: 'zcpdownload', + status: 'progress', + file: key, + bytesTotal: total, + bytesReceived: received, + progress: percentage, + }, + }); + // shepherd.log(`${key} ${percentage}% | ${received} bytes out of ${total} bytes.`); + } + } + }) + .then(() => { + const checkZcashParams = shepherd.zcashParamsExist(); - for (let key in shepherd.zcashParamsDownloadLinks[dlOption]) { - shepherd.downloadFile({ - remoteFile: shepherd.zcashParamsDownloadLinks[dlOption][key], - localFile: `${dlLocation}/sprout-${key}.key`, - onProgress: (received, total) => { - const percentage = (received * 100) / total; + shepherd.log(`${key} dl done`); - if (percentage.toString().indexOf('.10') > -1) { + if (checkZcashParams.error) { shepherd.io.emit('zcparams', { msg: { type: 'zcpdownload', - status: 'progress', file: key, - bytesTotal: total, - bytesReceived: received, - progress: percentage, + status: 'error', + message: 'size mismatch', + progress: 100, }, }); - // shepherd.log(`${key} ${percentage}% | ${received} bytes out of ${total} bytes.`); + } else { + shepherd.io.emit('zcparams', { + msg: { + type: 'zcpdownload', + file: key, + progress: 100, + status: 'done', + }, + }); + shepherd.log(`file ${key} succesfully downloaded`); } - } - }) - .then(() => { - const checkZcashParams = shepherd.zcashParamsExist(); - - shepherd.log(`${key} dl done`); - - if (checkZcashParams.error) { - shepherd.io.emit('zcparams', { - msg: { - type: 'zcpdownload', - file: key, - status: 'error', - message: 'size mismatch', - progress: 100, - }, - }); - } else { - shepherd.io.emit('zcparams', { - msg: { - type: 'zcpdownload', - file: key, - progress: 100, - status: 'done', - }, - }); - shepherd.log(`file ${key} succesfully downloaded`); - } - }); + }); + } + } else { + const errorObj = { + msg: 'error', + result: 'unauthorized access', + }; + + res.end(JSON.stringify(errorObj)); } }); diff --git a/routes/shepherd/electrum/auth.js b/routes/shepherd/electrum/auth.js index f017c30..d214ab3 100644 --- a/routes/shepherd/electrum/auth.js +++ b/routes/shepherd/electrum/auth.js @@ -4,78 +4,105 @@ const bitcoin = require('bitcoinjs-lib'); module.exports = (shepherd) => { shepherd.post('/electrum/login', (req, res, next) => { - let _wifError = false; + if (shepherd.checkToken(req.body.token)) { + let _wifError = false; - for (let key in shepherd.electrumCoins) { - if (key !== 'auth') { - const _abbr = key; - const _seed = req.body.seed; - let keys; - let isWif = false; + for (let key in shepherd.electrumCoins) { + if (key !== 'auth') { + const _abbr = key; + const _seed = req.body.seed; + let keys; + let isWif = false; - try { - bs58check.decode(_seed); - isWif = true; - } catch (e) {} - - if (isWif) { try { - let key = shepherd.isZcash(_abbr.toLowerCase()) ? bitcoinZcash.ECPair.fromWIF(_seed, shepherd.getNetworkData(_abbr.toLowerCase()), true) : bitcoin.ECPair.fromWIF(_seed, shepherd.getNetworkData(_abbr.toLowerCase()), true); - keys = { - priv: key.toWIF(), - pub: key.getAddress(), - }; - } catch (e) { - _wifError = true; - break; + bs58check.decode(_seed); + isWif = true; + } catch (e) {} + + if (isWif) { + try { + let key = shepherd.isZcash(_abbr.toLowerCase()) ? bitcoinZcash.ECPair.fromWIF(_seed, shepherd.getNetworkData(_abbr.toLowerCase()), true) : bitcoin.ECPair.fromWIF(_seed, shepherd.getNetworkData(_abbr.toLowerCase()), true); + keys = { + priv: key.toWIF(), + pub: key.getAddress(), + }; + } catch (e) { + _wifError = true; + break; + } + } else { + keys = shepherd.seedToWif(_seed, shepherd.findNetworkObj(_abbr), req.body.iguana); } - } else { - keys = shepherd.seedToWif(_seed, shepherd.findNetworkObj(_abbr), req.body.iguana); - } - shepherd.electrumKeys[_abbr] = { - priv: keys.priv, - pub: keys.pub, - }; + shepherd.electrumKeys[_abbr] = { + priv: keys.priv, + pub: keys.pub, + }; + } } - } - shepherd.electrumCoins.auth = true; + shepherd.electrumCoins.auth = true; + + // shepherd.log(JSON.stringify(shepherd.electrumKeys, null, '\t'), true); - // shepherd.log(JSON.stringify(shepherd.electrumKeys, null, '\t'), true); + const successObj = { + msg: _wifError ? 'error' : 'success', + result: 'true', + }; - const successObj = { - msg: _wifError ? 'error' : 'success', - result: 'true', - }; + res.end(JSON.stringify(successObj)); + } else { + const errorObj = { + msg: 'error', + result: 'unauthorized access', + }; - res.end(JSON.stringify(successObj)); + res.end(JSON.stringify(errorObj)); + } }); shepherd.post('/electrum/lock', (req, res, next) => { - shepherd.electrumCoins.auth = false; - shepherd.electrumKeys = {}; - - const successObj = { - msg: 'success', - result: 'true', - }; - - res.end(JSON.stringify(successObj)); + if (shepherd.checkToken(req.body.token)) { + shepherd.electrumCoins.auth = false; + shepherd.electrumKeys = {}; + + const successObj = { + msg: 'success', + result: 'true', + }; + + res.end(JSON.stringify(successObj)); + } else { + const errorObj = { + msg: 'error', + result: 'unauthorized access', + }; + + res.end(JSON.stringify(errorObj)); + } }); shepherd.post('/electrum/logout', (req, res, next) => { - shepherd.electrumCoins = { - auth: false, - }; - shepherd.electrumKeys = {}; - - const obj = { - msg: 'success', - result: 'result', - }; - - res.end(JSON.stringify(obj)); + if (shepherd.checkToken(req.body.token)) { + shepherd.electrumCoins = { + auth: false, + }; + shepherd.electrumKeys = {}; + + const obj = { + msg: 'success', + result: 'result', + }; + + res.end(JSON.stringify(obj)); + } else { + const errorObj = { + msg: 'error', + result: 'unauthorized access', + }; + + res.end(JSON.stringify(errorObj)); + } }); return shepherd; diff --git a/routes/shepherd/electrum/balance.js b/routes/shepherd/electrum/balance.js index 2f2be33..ed1ec50 100644 --- a/routes/shepherd/electrum/balance.js +++ b/routes/shepherd/electrum/balance.js @@ -1,68 +1,86 @@ module.exports = (shepherd) => { shepherd.get('/electrum/getbalance', (req, res, next) => { - const network = req.query.network || shepherd.findNetworkObj(req.query.coin); - const ecl = new shepherd.electrumJSCore(shepherd.electrumServers[network].port, shepherd.electrumServers[network].address, shepherd.electrumServers[network].proto); // tcp or tls - - shepherd.log('electrum getbalance =>', true); - - ecl.connect(); - ecl.blockchainAddressGetBalance(req.query.address) - .then((json) => { - if (json && - json.hasOwnProperty('confirmed') && - json.hasOwnProperty('unconfirmed')) { - if (network === 'komodo') { - ecl.connect(); - ecl.blockchainAddressListunspent(req.query.address) - .then((utxoList) => { - if (utxoList && - utxoList.length) { - // filter out < 10 KMD amounts - let _utxo = []; - - for (let i = 0; i < utxoList.length; i++) { - shepherd.log(`utxo ${utxoList[i]['tx_hash']} sats ${utxoList[i].value} value ${Number(utxoList[i].value) * 0.00000001}`, true); - - if (Number(utxoList[i].value) * 0.00000001 >= 10) { - _utxo.push(utxoList[i]); + if (shepherd.checkToken(req.query.token)) { + const network = req.query.network || shepherd.findNetworkObj(req.query.coin); + const ecl = new shepherd.electrumJSCore(shepherd.electrumServers[network].port, shepherd.electrumServers[network].address, shepherd.electrumServers[network].proto); // tcp or tls + + shepherd.log('electrum getbalance =>', true); + + ecl.connect(); + ecl.blockchainAddressGetBalance(req.query.address) + .then((json) => { + if (json && + json.hasOwnProperty('confirmed') && + json.hasOwnProperty('unconfirmed')) { + if (network === 'komodo') { + ecl.connect(); + ecl.blockchainAddressListunspent(req.query.address) + .then((utxoList) => { + if (utxoList && + utxoList.length) { + // filter out < 10 KMD amounts + let _utxo = []; + + for (let i = 0; i < utxoList.length; i++) { + shepherd.log(`utxo ${utxoList[i]['tx_hash']} sats ${utxoList[i].value} value ${Number(utxoList[i].value) * 0.00000001}`, true); + + if (Number(utxoList[i].value) * 0.00000001 >= 10) { + _utxo.push(utxoList[i]); + } } - } - shepherd.log('filtered utxo list =>', true); - shepherd.log(_utxo, true); + shepherd.log('filtered utxo list =>', true); + shepherd.log(_utxo, true); - if (_utxo && - _utxo.length) { - let interestTotal = 0; + if (_utxo && + _utxo.length) { + let interestTotal = 0; - shepherd.Promise.all(_utxo.map((_utxoItem, index) => { - return new shepherd.Promise((resolve, reject) => { - ecl.blockchainTransactionGet(_utxoItem['tx_hash']) - .then((_rawtxJSON) => { - shepherd.log('electrum gettransaction ==>', true); - shepherd.log((index + ' | ' + (_rawtxJSON.length - 1)), true); - shepherd.log(_rawtxJSON, true); + shepherd.Promise.all(_utxo.map((_utxoItem, index) => { + return new shepherd.Promise((resolve, reject) => { + ecl.blockchainTransactionGet(_utxoItem['tx_hash']) + .then((_rawtxJSON) => { + shepherd.log('electrum gettransaction ==>', true); + shepherd.log((index + ' | ' + (_rawtxJSON.length - 1)), true); + shepherd.log(_rawtxJSON, true); - // decode tx - const _network = shepherd.getNetworkData(network); - const decodedTx = shepherd.electrumJSTxDecoder(_rawtxJSON, network, _network); + // decode tx + const _network = shepherd.getNetworkData(network); + const decodedTx = shepherd.electrumJSTxDecoder(_rawtxJSON, network, _network); - if (decodedTx && - decodedTx.format && - decodedTx.format.locktime > 0) { - interestTotal += shepherd.kmdCalcInterest(decodedTx.format.locktime, _utxoItem.value); - } + if (decodedTx && + decodedTx.format && + decodedTx.format.locktime > 0) { + interestTotal += shepherd.kmdCalcInterest(decodedTx.format.locktime, _utxoItem.value); + } - shepherd.log('decoded tx =>', true); - shepherd.log(decodedTx, true); + shepherd.log('decoded tx =>', true); + shepherd.log(decodedTx, true); - resolve(true); + resolve(true); + }); }); + })) + .then(promiseResult => { + ecl.close(); + + const successObj = { + msg: 'success', + result: { + balance: Number((0.00000001 * json.confirmed).toFixed(8)), + unconfirmed: Number((0.00000001 * json.unconfirmed).toFixed(8)), + unconfirmedSats: json.unconfirmed, + balanceSats: json.confirmed, + interest: Number(interestTotal.toFixed(8)), + interestSats: Math.floor(interestTotal * 100000000), + total: interestTotal > 0 ? Number((0.00000001 * json.confirmed + interestTotal).toFixed(8)) : 0, + totalSats: interestTotal > 0 ?json.confirmed + Math.floor(interestTotal * 100000000) : 0, + }, + }; + + res.end(JSON.stringify(successObj)); }); - })) - .then(promiseResult => { - ecl.close(); - + } else { const successObj = { msg: 'success', result: { @@ -70,15 +88,15 @@ module.exports = (shepherd) => { unconfirmed: Number((0.00000001 * json.unconfirmed).toFixed(8)), unconfirmedSats: json.unconfirmed, balanceSats: json.confirmed, - interest: Number(interestTotal.toFixed(8)), - interestSats: Math.floor(interestTotal * 100000000), - total: interestTotal > 0 ? Number((0.00000001 * json.confirmed + interestTotal).toFixed(8)) : 0, - totalSats: interestTotal > 0 ?json.confirmed + Math.floor(interestTotal * 100000000) : 0, + interest: 0, + interestSats: 0, + total: 0, + totalSats: 0, }, }; res.end(JSON.stringify(successObj)); - }); + } } else { const successObj = { msg: 'success', @@ -96,50 +114,41 @@ module.exports = (shepherd) => { res.end(JSON.stringify(successObj)); } - } else { - const successObj = { - msg: 'success', - result: { - balance: Number((0.00000001 * json.confirmed).toFixed(8)), - unconfirmed: Number((0.00000001 * json.unconfirmed).toFixed(8)), - unconfirmedSats: json.unconfirmed, - balanceSats: json.confirmed, - interest: 0, - interestSats: 0, - total: 0, - totalSats: 0, - }, - }; - - res.end(JSON.stringify(successObj)); - } - }); + }); + } else { + ecl.close(); + shepherd.log('electrum getbalance ==>', true); + shepherd.log(json, true); + + const successObj = { + msg: 'success', + result: { + balance: Number((0.00000001 * json.confirmed).toFixed(8)), + unconfirmed: Number((0.00000001 * json.unconfirmed).toFixed(8)), + unconfirmedSats: json.unconfirmed, + balanceSats: json.confirmed, + }, + }; + + res.end(JSON.stringify(successObj)); + } } else { - ecl.close(); - shepherd.log('electrum getbalance ==>', true); - shepherd.log(json, true); - const successObj = { - msg: 'success', - result: { - balance: Number((0.00000001 * json.confirmed).toFixed(8)), - unconfirmed: Number((0.00000001 * json.unconfirmed).toFixed(8)), - unconfirmedSats: json.unconfirmed, - balanceSats: json.confirmed, - }, + msg: 'error', + result: shepherd.CONNECTION_ERROR_OR_INCOMPLETE_DATA, }; res.end(JSON.stringify(successObj)); } - } else { - const successObj = { - msg: 'error', - result: shepherd.CONNECTION_ERROR_OR_INCOMPLETE_DATA, - }; - - res.end(JSON.stringify(successObj)); - } - }); + }); + } else { + const errorObj = { + msg: 'error', + result: 'unauthorized access', + }; + + res.end(JSON.stringify(errorObj)); + } }); return shepherd; diff --git a/routes/shepherd/electrum/block.js b/routes/shepherd/electrum/block.js index 3a92911..38e603d 100644 --- a/routes/shepherd/electrum/block.js +++ b/routes/shepherd/electrum/block.js @@ -1,14 +1,23 @@ module.exports = (shepherd) => { shepherd.get('/electrum/getblockinfo', (req, res, next) => { - shepherd.electrumGetBlockInfo(req.query.height, req.query.network) - .then((json) => { - const successObj = { - msg: 'success', - result: json, + if (shepherd.checkToken(req.query.token)) { + shepherd.electrumGetBlockInfo(req.query.height, req.query.network) + .then((json) => { + const successObj = { + msg: 'success', + result: json, + }; + + res.end(JSON.stringify(successObj)); + }); + } else { + const errorObj = { + msg: 'error', + result: 'unauthorized access', }; - res.end(JSON.stringify(successObj)); - }); + res.end(JSON.stringify(errorObj)); + } }); shepherd.electrumGetBlockInfo = (height, network) => { @@ -28,15 +37,24 @@ module.exports = (shepherd) => { } shepherd.get('/electrum/getcurrentblock', (req, res, next) => { - shepherd.electrumGetCurrentBlock(req.query.network) - .then((json) => { - const successObj = { - msg: 'success', - result: json, + if (shepherd.checkToken(req.query.token)) { + shepherd.electrumGetCurrentBlock(req.query.network) + .then((json) => { + const successObj = { + msg: 'success', + result: json, + }; + + res.end(JSON.stringify(successObj)); + }); + } else { + const errorObj = { + msg: 'error', + result: 'unauthorized access', }; - res.end(JSON.stringify(successObj)); - }); + res.end(JSON.stringify(errorObj)); + } }); shepherd.electrumGetCurrentBlock = (network) => { diff --git a/routes/shepherd/electrum/coins.js b/routes/shepherd/electrum/coins.js index bc73562..295fadb 100644 --- a/routes/shepherd/electrum/coins.js +++ b/routes/shepherd/electrum/coins.js @@ -61,7 +61,6 @@ module.exports = (shepherd) => { priv: _keys.priv, pub: _keys.pub, }; - console.log(shepherd.electrumKeys[coin]); } return true; @@ -69,32 +68,70 @@ module.exports = (shepherd) => { } } - shepherd.get('/electrum/coins/add', (req, res, next) => { - const result = shepherd.addElectrumCoin(req.query.coin); + shepherd.get('/electrum/coin/changepub', (req, res, next) => { + if (shepherd.checkToken(req.query.token)) { + shepherd.electrumKeys[req.query.coin].pub = req.query.pub; + + const successObj = { + msg: 'success', + result: 'true', + }; - const successObj = { - msg: 'success', - result, - }; + res.end(JSON.stringify(successObj)); + } else { + const errorObj = { + msg: 'error', + result: 'unauthorized access', + }; - res.end(JSON.stringify(successObj)); + res.end(JSON.stringify(errorObj)); + } + }); + + shepherd.get('/electrum/coins/add', (req, res, next) => { + if (shepherd.checkToken(req.query.token)) { + const result = shepherd.addElectrumCoin(req.query.coin); + + const successObj = { + msg: 'success', + result, + }; + + res.end(JSON.stringify(successObj)); + } else { + const errorObj = { + msg: 'error', + result: 'unauthorized access', + }; + + res.end(JSON.stringify(errorObj)); + } }); shepherd.get('/electrum/coins', (req, res, next) => { - let _electrumCoins = JSON.parse(JSON.stringify(shepherd.electrumCoins)); // deep cloning + if (shepherd.checkToken(req.query.token)) { + let _electrumCoins = JSON.parse(JSON.stringify(shepherd.electrumCoins)); // deep cloning - for (let key in _electrumCoins) { - if (shepherd.electrumKeys[key]) { - _electrumCoins[key].pub = shepherd.electrumKeys[key].pub; + for (let key in _electrumCoins) { + if (shepherd.electrumKeys[key]) { + _electrumCoins[key].pub = shepherd.electrumKeys[key].pub; + } } - } - const successObj = { - msg: 'success', - result: _electrumCoins, - }; + const successObj = { + msg: 'success', + result: _electrumCoins, + }; - res.end(JSON.stringify(successObj)); + res.end(JSON.stringify(successObj)); + } else { + const errorObj = { + msg: 'error', + result: 'unauthorized access', + }; + + res.end(JSON.stringify(errorObj)); + } }); return shepherd; diff --git a/routes/shepherd/electrum/createtx.js b/routes/shepherd/electrum/createtx.js index e7cf8ad..fe3a4a3 100644 --- a/routes/shepherd/electrum/createtx.js +++ b/routes/shepherd/electrum/createtx.js @@ -9,14 +9,14 @@ module.exports = (shepherd) => { // TODO: finish unsigned for zcash, btc forks and pos coins if (network === 'btg') { - shepherd.log('enable btg'); + shepherd.log('enable btg', true); tx = new bitcoinJSForks.TransactionBuilder(shepherd.getNetworkData(network)); tx.enableBitcoinGold(true); } else { tx = new shepherd.bitcoinJS.TransactionBuilder(shepherd.getNetworkData(network)); } - shepherd.log('buildSignedTx'); + shepherd.log('buildSignedTx', true); // console.log(`buildSignedTx priv key ${wif}`); shepherd.log(`buildSignedTx pub key ${changeAddress}`, true); // console.log('buildSignedTx std tx fee ' + shepherd.electrumServers[network].txfee); @@ -66,7 +66,7 @@ module.exports = (shepherd) => { tx = new shepherd.bitcoinJS.TransactionBuilder(shepherd.getNetworkData(network)); } - shepherd.log('buildSignedTx'); + shepherd.log('buildSignedTx', true); // console.log(`buildSignedTx priv key ${wif}`); shepherd.log(`buildSignedTx pub key ${key.getAddress().toString()}`, true); // console.log('buildSignedTx std tx fee ' + shepherd.electrumServers[network].txfee); @@ -132,7 +132,7 @@ module.exports = (shepherd) => { const pk = bitcoinJSForks.crypto.hash160(keyPair.getPublicKeyBuffer()); const spk = bitcoinJSForks.script.pubKeyHash.output.encode(pk); - shepherd.log(`buildSignedTx${network.toUpperCase()}`); + shepherd.log(`buildSignedTx${network.toUpperCase()}`, true); for (let i = 0; i < utxo.length; i++) { tx.addInput(utxo[i].txid, utxo[i].vout, bitcoinJSForks.Transaction.DEFAULT_SEQUENCE, spk); @@ -188,424 +188,443 @@ module.exports = (shepherd) => { } shepherd.get('/electrum/createrawtx', (req, res, next) => { - // TODO: unconf output(s) error message - const network = req.query.network || shepherd.findNetworkObj(req.query.coin); - const ecl = new shepherd.electrumJSCore(shepherd.electrumServers[network].port, shepherd.electrumServers[network].address, shepherd.electrumServers[network].proto); // tcp or tls - const outputAddress = req.query.address; - const changeAddress = req.query.change; - const push = req.query.push; - let fee = shepherd.electrumServers[network].txfee; - let value = Number(req.query.value); - let wif = req.query.wif; - - if (req.query.gui) { - wif = shepherd.electrumKeys[req.query.coin].priv; - } + if (shepherd.checkToken(req.query.token)) { + // TODO: unconf output(s) error message + const network = req.query.network || shepherd.findNetworkObj(req.query.coin); + const ecl = new shepherd.electrumJSCore(shepherd.electrumServers[network].port, shepherd.electrumServers[network].address, shepherd.electrumServers[network].proto); // tcp or tls + const outputAddress = req.query.address; + const changeAddress = req.query.change; + const push = req.query.push; + let fee = shepherd.electrumServers[network].txfee; + let value = Number(req.query.value); + let wif = req.query.wif; + + if (req.query.gui) { + wif = shepherd.electrumKeys[req.query.coin].priv; + } - shepherd.log('electrum createrawtx =>', true); - - ecl.connect(); - shepherd.listunspent(ecl, changeAddress, network, true, true) - .then((utxoList) => { - ecl.close(); - - if (utxoList && - utxoList.length && - utxoList[0] && - utxoList[0].txid) { - let utxoListFormatted = []; - let totalInterest = 0; - let totalInterestUTXOCount = 0; - let interestClaimThreshold = 200; - let utxoVerified = true; - - for (let i = 0; i < utxoList.length; i++) { - if (network === 'komodo') { - utxoListFormatted.push({ - txid: utxoList[i].txid, - vout: utxoList[i].vout, - value: Number(utxoList[i].amountSats), - interestSats: Number(utxoList[i].interestSats), - verified: utxoList[i].verified ? utxoList[i].verified : false, - }); - } else { - utxoListFormatted.push({ - txid: utxoList[i].txid, - vout: utxoList[i].vout, - value: Number(utxoList[i].amountSats), - verified: utxoList[i].verified ? utxoList[i].verified : false, - }); + shepherd.log('electrum createrawtx =>', true); + + ecl.connect(); + shepherd.listunspent(ecl, changeAddress, network, true, true) + .then((utxoList) => { + ecl.close(); + console.log(utxoList); + + if (utxoList && + utxoList.length && + utxoList[0] && + utxoList[0].txid) { + let utxoListFormatted = []; + let totalInterest = 0; + let totalInterestUTXOCount = 0; + let interestClaimThreshold = 200; + let utxoVerified = true; + + for (let i = 0; i < utxoList.length; i++) { + if (network === 'komodo') { + utxoListFormatted.push({ + txid: utxoList[i].txid, + vout: utxoList[i].vout, + value: Number(utxoList[i].amountSats), + interestSats: Number(utxoList[i].interestSats), + verified: utxoList[i].verified ? utxoList[i].verified : false, + }); + } else { + utxoListFormatted.push({ + txid: utxoList[i].txid, + vout: utxoList[i].vout, + value: Number(utxoList[i].amountSats), + verified: utxoList[i].verified ? utxoList[i].verified : false, + }); + } } - } - - shepherd.log('electrum listunspent unformatted ==>', true); - shepherd.log(utxoList, true); - - shepherd.log('electrum listunspent formatted ==>', true); - shepherd.log(utxoListFormatted, true); - const _maxSpendBalance = Number(shepherd.maxSpendBalance(utxoListFormatted)); - let targets = [{ - address: outputAddress, - value: value > _maxSpendBalance ? _maxSpendBalance : value, - }]; - shepherd.log('targets =>', true); - shepherd.log(targets, true); + shepherd.log('electrum listunspent unformatted ==>', true); + shepherd.log(utxoList, true); - const feeRate = shepherd.getNetworkData(network).messagePrefix === '\x19Komodo Signed Message:\n' || shepherd.getNetworkData(network).messagePrefix === '\x19Chips Signed Message:\n' ? 20 : 0; // sats/byte + shepherd.log('electrum listunspent formatted ==>', true); + shepherd.log(utxoListFormatted, true); - if (!feeRate) { - targets[0].value = targets[0].value + fee; - } - - shepherd.log(`fee rate ${feeRate}`, true); - shepherd.log(`default fee ${fee}`, true); - shepherd.log(`targets ==>`, true); - shepherd.log(targets, true); + const _maxSpendBalance = Number(shepherd.maxSpendBalance(utxoListFormatted)); + let targets = [{ + address: outputAddress, + value: value > _maxSpendBalance ? _maxSpendBalance : value, + }]; + shepherd.log('targets =>', true); + shepherd.log(targets, true); - // default coin selection algo blackjack with fallback to accumulative - // make a first run, calc approx tx fee - // if ins and outs are empty reduce max spend by txfee - const firstRun = shepherd.coinSelect(utxoListFormatted, targets, feeRate); - let inputs = firstRun.inputs; - let outputs = firstRun.outputs; + const feeRate = shepherd.getNetworkData(network).messagePrefix === '\x19Komodo Signed Message:\n' || shepherd.getNetworkData(network).messagePrefix === '\x19Chips Signed Message:\n' ? 20 : 0; // sats/byte - if (feeRate) { - fee = firstRun.fee; - } + if (!feeRate) { + targets[0].value = targets[0].value + fee; + } - shepherd.log('coinselect res =>', true); - shepherd.log('coinselect inputs =>', true); - shepherd.log(inputs, true); - shepherd.log('coinselect outputs =>', true); - shepherd.log(outputs, true); - shepherd.log('coinselect calculated fee =>', true); - shepherd.log(fee, true); - - if (!outputs) { - targets[0].value = targets[0].value - fee; - shepherd.log('second run', true); - shepherd.log('coinselect adjusted targets =>', true); + shepherd.log(`fee rate ${feeRate}`, true); + shepherd.log(`default fee ${fee}`, true); + shepherd.log(`targets ==>`, true); shepherd.log(targets, true); - const secondRun = shepherd.coinSelect(utxoListFormatted, targets, feeRate); - inputs = secondRun.inputs; - outputs = secondRun.outputs; - fee = secondRun.fee; + // default coin selection algo blackjack with fallback to accumulative + // make a first run, calc approx tx fee + // if ins and outs are empty reduce max spend by txfee + const firstRun = shepherd.coinSelect(utxoListFormatted, targets, feeRate); + let inputs = firstRun.inputs; + let outputs = firstRun.outputs; + + if (feeRate) { + fee = firstRun.fee; + } - shepherd.log('second run coinselect inputs =>', true); + shepherd.log('coinselect res =>', true); + shepherd.log('coinselect inputs =>', true); shepherd.log(inputs, true); - shepherd.log('second run coinselect outputs =>', true); + shepherd.log('coinselect outputs =>', true); shepherd.log(outputs, true); - shepherd.log('second run coinselect fee =>', true); + shepherd.log('coinselect calculated fee =>', true); shepherd.log(fee, true); - } - let _change = 0; + if (!outputs) { + targets[0].value = targets[0].value - fee; + shepherd.log('second run', true); + shepherd.log('coinselect adjusted targets =>', true); + shepherd.log(targets, true); + + const secondRun = shepherd.coinSelect(utxoListFormatted, targets, feeRate); + inputs = secondRun.inputs; + outputs = secondRun.outputs; + fee = secondRun.fee; + + shepherd.log('second run coinselect inputs =>', true); + shepherd.log(inputs, true); + shepherd.log('second run coinselect outputs =>', true); + shepherd.log(outputs, true); + shepherd.log('second run coinselect fee =>', true); + shepherd.log(fee, true); + } - if (outputs && - outputs.length === 2) { - _change = outputs[1].value; - } + let _change = 0; - // non komodo coins, subtract fee from output value - if (!feeRate) { - outputs[0].value = outputs[0].value - fee; + if (outputs && + outputs.length === 2) { + _change = outputs[1].value; + } - shepherd.log('non komodo adjusted outputs, value - default fee =>', true); - shepherd.log(outputs, true); - } + // non komodo coins, subtract fee from output value + if (!feeRate) { + outputs[0].value = outputs[0].value - fee; - // check if any outputs are unverified - if (inputs && - inputs.length) { - for (let i = 0; i < inputs.length; i++) { - if (!inputs[i].verified) { - utxoVerified = false; - break; - } + shepherd.log('non komodo adjusted outputs, value - default fee =>', true); + shepherd.log(outputs, true); } - for (let i = 0; i < inputs.length; i++) { - if (Number(inputs[i].interestSats) > interestClaimThreshold) { - totalInterest += Number(inputs[i].interestSats); - totalInterestUTXOCount++; + // check if any outputs are unverified + if (inputs && + inputs.length) { + for (let i = 0; i < inputs.length; i++) { + if (!inputs[i].verified) { + utxoVerified = false; + break; + } } - } - } - - const _maxSpend = shepherd.maxSpendBalance(utxoListFormatted); - if (value > _maxSpend) { - const successObj = { - msg: 'error', - result: `Spend value is too large. Max available amount is ${Number((_maxSpend * 0.00000001.toFixed(8)))}`, - }; - - res.end(JSON.stringify(successObj)); - } else { - shepherd.log(`maxspend ${_maxSpend} (${_maxSpend * 0.00000001})`, true); - shepherd.log(`value ${value}`, true); - shepherd.log(`sendto ${outputAddress} amount ${value} (${value * 0.00000001})`, true); - shepherd.log(`changeto ${changeAddress} amount ${_change} (${_change * 0.00000001})`, true); - - // account for KMD interest - if (network === 'komodo' && - totalInterest > 0) { - // account for extra vout - const _feeOverhead = outputs.length === 1 ? shepherd.estimateTxSize(0, 1) * feeRate : 0; - - shepherd.log(`max interest to claim ${totalInterest} (${totalInterest * 0.00000001})`, true); - shepherd.log(`estimated fee overhead ${_feeOverhead}`, true); - shepherd.log(`current change amount ${_change} (${_change * 0.00000001}), boosted change amount ${_change + (totalInterest - _feeOverhead)} (${(_change + (totalInterest - _feeOverhead)) * 0.00000001})`, true); - - if (_maxSpend === value) { - _change = totalInterest - _change - _feeOverhead; - - if (outputAddress === changeAddress) { - value += _change; - _change = 0; - shepherd.log(`send to self ${outputAddress} = ${changeAddress}`, true); - shepherd.log(`send to self old val ${value}, new val ${value + _change}`, true); + for (let i = 0; i < inputs.length; i++) { + if (Number(inputs[i].interestSats) > interestClaimThreshold) { + totalInterest += Number(inputs[i].interestSats); + totalInterestUTXOCount++; } - } else { - _change = _change + (totalInterest - _feeOverhead); } } - if (!inputs && - !outputs) { + const _maxSpend = shepherd.maxSpendBalance(utxoListFormatted); + + if (value > _maxSpend) { const successObj = { msg: 'error', - result: 'Can\'t find best fit utxo. Try lower amount.', + result: `Spend value is too large. Max available amount is ${Number((_maxSpend * 0.00000001.toFixed(8)))}`, }; res.end(JSON.stringify(successObj)); } else { - let vinSum = 0; - - for (let i = 0; i < inputs.length; i++) { - vinSum += inputs[i].value; + shepherd.log(`maxspend ${_maxSpend} (${_maxSpend * 0.00000001})`, true); + shepherd.log(`value ${value}`, true); + shepherd.log(`sendto ${outputAddress} amount ${value} (${value * 0.00000001})`, true); + shepherd.log(`changeto ${changeAddress} amount ${_change} (${_change * 0.00000001})`, true); + + // account for KMD interest + if (network === 'komodo' && + totalInterest > 0) { + // account for extra vout + const _feeOverhead = outputs.length === 1 ? shepherd.estimateTxSize(0, 1) * feeRate : 0; + + shepherd.log(`max interest to claim ${totalInterest} (${totalInterest * 0.00000001})`, true); + shepherd.log(`estimated fee overhead ${_feeOverhead}`, true); + shepherd.log(`current change amount ${_change} (${_change * 0.00000001}), boosted change amount ${_change + (totalInterest - _feeOverhead)} (${(_change + (totalInterest - _feeOverhead)) * 0.00000001})`, true); + + if (_maxSpend === value) { + _change = totalInterest - _change - _feeOverhead; + + if (outputAddress === changeAddress) { + value += _change; + _change = 0; + shepherd.log(`send to self ${outputAddress} = ${changeAddress}`, true); + shepherd.log(`send to self old val ${value}, new val ${value + _change}`, true); + } + } else { + _change = _change + (totalInterest - _feeOverhead); + } } - const _estimatedFee = vinSum - outputs[0].value - _change; + if (!inputs && + !outputs) { + const successObj = { + msg: 'error', + result: 'Can\'t find best fit utxo. Try lower amount.', + }; + + res.end(JSON.stringify(successObj)); + } else { + let vinSum = 0; - shepherd.log(`vin sum ${vinSum} (${vinSum * 0.00000001})`, true); - shepherd.log(`estimatedFee ${_estimatedFee} (${_estimatedFee * 0.00000001})`, true); + for (let i = 0; i < inputs.length; i++) { + vinSum += inputs[i].value; + } - let _rawtx; + const _estimatedFee = vinSum - outputs[0].value - _change; - if (req.query.unsigned) { - _rawtx = shepherd.buildUnsignedTx( - outputAddress, - changeAddress, - network, - inputs, - _change, - value - ); - } else { - if (network === 'btg' || - network === 'bch') { - _rawtx = shepherd.buildSignedTxForks( + shepherd.log(`vin sum ${vinSum} (${vinSum * 0.00000001})`, true); + shepherd.log(`estimatedFee ${_estimatedFee} (${_estimatedFee * 0.00000001})`, true); + + let _rawtx; + + if (req.query.unsigned) { + _rawtx = shepherd.buildUnsignedTx( outputAddress, changeAddress, - wif, network, inputs, _change, value ); } else { - _rawtx = shepherd.buildSignedTx( - outputAddress, - changeAddress, - wif, - network, - inputs, - _change, - value - ); + if (network === 'btg' || + network === 'bch') { + _rawtx = shepherd.buildSignedTxForks( + outputAddress, + changeAddress, + wif, + network, + inputs, + _change, + value + ); + } else { + _rawtx = shepherd.buildSignedTx( + outputAddress, + changeAddress, + wif, + network, + inputs, + _change, + value + ); + } } - } - if (!push || - push === 'false') { - const successObj = { - msg: 'success', - result: { - utxoSet: inputs, - change: _change, - changeAdjusted: _change, - totalInterest, - // wif, - fee, - value, - outputAddress, - changeAddress, - network, - rawtx: _rawtx, - utxoVerified, - }, - }; + if (!push || + push === 'false') { + const successObj = { + msg: 'success', + result: { + utxoSet: inputs, + change: _change, + changeAdjusted: _change, + totalInterest, + // wif, + fee, + value, + outputAddress, + changeAddress, + network, + rawtx: _rawtx, + utxoVerified, + }, + }; + + res.end(JSON.stringify(successObj)); + } else { + const ecl = new shepherd.electrumJSCore(shepherd.electrumServers[network].port, shepherd.electrumServers[network].address, shepherd.electrumServers[network].proto); // tcp or tls + + ecl.connect(); + ecl.blockchainTransactionBroadcast(_rawtx) + .then((txid) => { + ecl.close(); - res.end(JSON.stringify(successObj)); - } else { - const ecl = new shepherd.electrumJSCore(shepherd.electrumServers[network].port, shepherd.electrumServers[network].address, shepherd.electrumServers[network].proto); // tcp or tls - - ecl.connect(); - ecl.blockchainTransactionBroadcast(_rawtx) - .then((txid) => { - ecl.close(); - - if (txid && - txid.indexOf('bad-txns-inputs-spent') > -1) { - const successObj = { - msg: 'error', - result: 'Bad transaction inputs spent', - raw: { - utxoSet: inputs, - change: _change, - changeAdjusted: _change, - totalInterest, - fee, - value, - outputAddress, - changeAddress, - network, - rawtx: _rawtx, - txid, - utxoVerified, - }, - }; - - res.end(JSON.stringify(successObj)); - } else { if (txid && - txid.length === 64) { - if (txid.indexOf('bad-txns-in-belowout') > -1) { - const successObj = { - msg: 'error', - result: 'Bad transaction inputs spent', - raw: { - utxoSet: inputs, - change: _change, - changeAdjusted: _change, - totalInterest, - fee, - value, - outputAddress, - changeAddress, - network, - rawtx: _rawtx, - txid, - utxoVerified, - }, - }; - - res.end(JSON.stringify(successObj)); - } else { - const successObj = { - msg: 'success', - result: { - utxoSet: inputs, - change: _change, - changeAdjusted: _change, - totalInterest, - fee, - // wif, - value, - outputAddress, - changeAddress, - network, - rawtx: _rawtx, - txid, - utxoVerified, - }, - }; - - res.end(JSON.stringify(successObj)); - } + txid.indexOf('bad-txns-inputs-spent') > -1) { + const successObj = { + msg: 'error', + result: 'Bad transaction inputs spent', + raw: { + utxoSet: inputs, + change: _change, + changeAdjusted: _change, + totalInterest, + fee, + value, + outputAddress, + changeAddress, + network, + rawtx: _rawtx, + txid, + utxoVerified, + }, + }; + + res.end(JSON.stringify(successObj)); } else { if (txid && - txid.indexOf('bad-txns-in-belowout') > -1) { - const successObj = { - msg: 'error', - result: 'Bad transaction inputs spent', - raw: { - utxoSet: inputs, - change: _change, - changeAdjusted: _change, - totalInterest, - fee, - value, - outputAddress, - changeAddress, - network, - rawtx: _rawtx, - txid, - utxoVerified, - }, - }; - - res.end(JSON.stringify(successObj)); + txid.length === 64) { + if (txid.indexOf('bad-txns-in-belowout') > -1) { + const successObj = { + msg: 'error', + result: 'Bad transaction inputs spent', + raw: { + utxoSet: inputs, + change: _change, + changeAdjusted: _change, + totalInterest, + fee, + value, + outputAddress, + changeAddress, + network, + rawtx: _rawtx, + txid, + utxoVerified, + }, + }; + + res.end(JSON.stringify(successObj)); + } else { + const successObj = { + msg: 'success', + result: { + utxoSet: inputs, + change: _change, + changeAdjusted: _change, + totalInterest, + fee, + // wif, + value, + outputAddress, + changeAddress, + network, + rawtx: _rawtx, + txid, + utxoVerified, + }, + }; + + res.end(JSON.stringify(successObj)); + } } else { - const successObj = { - msg: 'error', - result: 'Can\'t broadcast transaction', - raw: { - utxoSet: inputs, - change: _change, - changeAdjusted: _change, - totalInterest, - fee, - value, - outputAddress, - changeAddress, - network, - rawtx: _rawtx, - txid, - utxoVerified, - }, - }; - - res.end(JSON.stringify(successObj)); + if (txid && + txid.indexOf('bad-txns-in-belowout') > -1) { + const successObj = { + msg: 'error', + result: 'Bad transaction inputs spent', + raw: { + utxoSet: inputs, + change: _change, + changeAdjusted: _change, + totalInterest, + fee, + value, + outputAddress, + changeAddress, + network, + rawtx: _rawtx, + txid, + utxoVerified, + }, + }; + + res.end(JSON.stringify(successObj)); + } else { + const successObj = { + msg: 'error', + result: 'Can\'t broadcast transaction', + raw: { + utxoSet: inputs, + change: _change, + changeAdjusted: _change, + totalInterest, + fee, + value, + outputAddress, + changeAddress, + network, + rawtx: _rawtx, + txid, + utxoVerified, + }, + }; + + res.end(JSON.stringify(successObj)); + } } } - } - }); + }); + } } } + } else { + const successObj = { + msg: 'error', + result: utxoList, + }; + + res.end(JSON.stringify(successObj)); } - } else { - const successObj = { - msg: 'error', - result: utxoList, - }; + }); + } else { + const errorObj = { + msg: 'error', + result: 'unauthorized access', + }; - res.end(JSON.stringify(successObj)); - } - }); + res.end(JSON.stringify(errorObj)); + } }); shepherd.get('/electrum/pushtx', (req, res, next) => { - const rawtx = req.query.rawtx; - const ecl = new shepherd.electrumJSCore(shepherd.electrumServers[req.query.network].port, shepherd.electrumServers[req.query.network].address, shepherd.electrumServers[req.query.network].proto); // tcp or tls - - ecl.connect(); - ecl.blockchainTransactionBroadcast(rawtx) - .then((json) => { - ecl.close(); - shepherd.log('electrum pushtx ==>', true); - shepherd.log(json, true); - - const successObj = { - msg: 'success', - result: json, + if (shepherd.checkToken(req.query.token)) { + const rawtx = req.query.rawtx; + const ecl = new shepherd.electrumJSCore(shepherd.electrumServers[req.query.network].port, shepherd.electrumServers[req.query.network].address, shepherd.electrumServers[req.query.network].proto); // tcp or tls + + ecl.connect(); + ecl.blockchainTransactionBroadcast(rawtx) + .then((json) => { + ecl.close(); + shepherd.log('electrum pushtx ==>', true); + shepherd.log(json, true); + + const successObj = { + msg: 'success', + result: json, + }; + + res.end(JSON.stringify(successObj)); + }); + } else { + const errorObj = { + msg: 'error', + result: 'unauthorized access', }; - res.end(JSON.stringify(successObj)); - }); + res.end(JSON.stringify(errorObj)); + } }); return shepherd; diff --git a/routes/shepherd/electrum/estimate.js b/routes/shepherd/electrum/estimate.js index fab2b98..f065414 100644 --- a/routes/shepherd/electrum/estimate.js +++ b/routes/shepherd/electrum/estimate.js @@ -1,20 +1,29 @@ module.exports = (shepherd) => { shepherd.get('/electrum/estimatefee', (req, res, next) => { - const ecl = new shepherd.electrumJSCore(shepherd.electrumServers[req.query.network].port, shepherd.electrumServers[req.query.network].address, shepherd.electrumServers[req.query.network].proto); // tcp or tls + if (shepherd.checkToken(req.query.token)) { + const ecl = new shepherd.electrumJSCore(shepherd.electrumServers[req.query.network].port, shepherd.electrumServers[req.query.network].address, shepherd.electrumServers[req.query.network].proto); // tcp or tls - ecl.connect(); - ecl.blockchainEstimatefee(req.query.blocks) - .then((json) => { - ecl.close(); - shepherd.log('electrum estimatefee ==>', true); + ecl.connect(); + ecl.blockchainEstimatefee(req.query.blocks) + .then((json) => { + ecl.close(); + shepherd.log('electrum estimatefee ==>', true); - const successObj = { - msg: 'success', - result: json, + const successObj = { + msg: 'success', + result: json, + }; + + res.end(JSON.stringify(successObj)); + }); + } else { + const errorObj = { + msg: 'error', + result: 'unauthorized access', }; - res.end(JSON.stringify(successObj)); - }); + res.end(JSON.stringify(errorObj)); + } }); shepherd.estimateTxSize = (numVins, numOuts) => { diff --git a/routes/shepherd/electrum/keys.js b/routes/shepherd/electrum/keys.js index de01cc8..52188fd 100644 --- a/routes/shepherd/electrum/keys.js +++ b/routes/shepherd/electrum/keys.js @@ -10,7 +10,6 @@ const bs58check = require('bs58check'); module.exports = (shepherd) => { shepherd.wifToWif = (wif, network) => { network = network === 'KMD' ? 'komodo' : network.toLowerCase(); - console.log(shepherd.getNetworkData(network)); const key = shepherd.isZcash(network) ? new bitcoinZcash.ECPair.fromWIF(wif, shepherd.getNetworkData(network), true) : new bitcoin.ECPair.fromWIF(wif, shepherd.getNetworkData(network), true); return { @@ -51,93 +50,120 @@ module.exports = (shepherd) => { } shepherd.get('/electrum/wiftopub', (req, res, next) => { - let key = shepherd.isZcash(req.query.coin.toLowerCase()) ? bitcoinZcash.ECPair.fromWIF(req.query.wif, shepherd.electrumJSNetworks[req.query.coin], true) : bitcoin.ECPair.fromWIF(req.query.wif, shepherd.electrumJSNetworks[req.query.coin], true); - keys = { - priv: key.toWIF(), - pub: key.getAddress(), - }; - - const successObj = { - msg: 'success', - result: { - keys, - }, - }; + if (shepherd.checkToken(req.query.token)) { + let key = shepherd.isZcash(req.query.coin.toLowerCase()) ? bitcoinZcash.ECPair.fromWIF(req.query.wif, shepherd.electrumJSNetworks[req.query.coin], true) : bitcoin.ECPair.fromWIF(req.query.wif, shepherd.electrumJSNetworks[req.query.coin], true); + keys = { + priv: key.toWIF(), + pub: key.getAddress(), + }; + + const successObj = { + msg: 'success', + result: { + keys, + }, + }; + + res.end(JSON.stringify(successObj)); + } else { + const errorObj = { + msg: 'error', + result: 'unauthorized access', + }; - res.end(JSON.stringify(successObj)); + res.end(JSON.stringify(errorObj)); + } }); shepherd.get('/electrum/seedtowif', (req, res, next) => { - let keys = shepherd.seedToWif(req.query.seed, req.query.network, req.query.iguana); + if (shepherd.checkToken(req.query.token)) { + let keys = shepherd.seedToWif(req.query.seed, req.query.network, req.query.iguana); - const successObj = { - msg: 'success', - result: { - keys, - }, - }; + const successObj = { + msg: 'success', + result: { + keys, + }, + }; - res.end(JSON.stringify(successObj)); + res.end(JSON.stringify(successObj)); + } else { + const errorObj = { + msg: 'error', + result: 'unauthorized access', + }; + + res.end(JSON.stringify(errorObj)); + } }); shepherd.post('/electrum/keys', (req, res, next) => { - let _matchingKeyPairs = 0; - let _totalKeys = 0; - let _electrumKeys = {}; - let _seed = req.body.seed; - let _wifError = false; - - for (let key in shepherd.electrumServers) { - const _abbr = shepherd.electrumServers[key].abbr; - let isWif = false; - let priv; - let pub; - - try { - bs58check.decode(_seed); - isWif = true; - } catch (e) {} + if (shepherd.checkToken(req.body.token)) { + let _matchingKeyPairs = 0; + let _totalKeys = 0; + let _electrumKeys = {}; + let _seed = req.body.seed; + let _wifError = false; + + for (let key in shepherd.electrumServers) { + const _abbr = shepherd.electrumServers[key].abbr; + let isWif = false; + let priv; + let pub; - if (isWif) { try { - let key = shepherd.isZcash(_abbr.toLowerCase()) ? bitcoinZcash.ECPair.fromWIF(_seed, shepherd.getNetworkData(_abbr.toLowerCase()), true) : bitcoin.ECPair.fromWIF(_seed, shepherd.getNetworkData(_abbr.toLowerCase()), true); - priv = key.toWIF(); - pub = key.getAddress(); - } catch (e) { - _wifError = true; - break; + bs58check.decode(_seed); + isWif = true; + } catch (e) {} + + if (isWif) { + try { + let key = shepherd.isZcash(_abbr.toLowerCase()) ? bitcoinZcash.ECPair.fromWIF(_seed, shepherd.getNetworkData(_abbr.toLowerCase()), true) : bitcoin.ECPair.fromWIF(_seed, shepherd.getNetworkData(_abbr.toLowerCase()), true); + priv = key.toWIF(); + pub = key.getAddress(); + } catch (e) { + _wifError = true; + break; + } + } else { + let _keys = shepherd.seedToWif(_seed, shepherd.findNetworkObj(_abbr), req.body.iguana); + priv = _keys.priv; + pub = _keys.pub; } - } else { - let _keys = shepherd.seedToWif(_seed, shepherd.findNetworkObj(_abbr), req.body.iguana); - priv = _keys.priv; - pub = _keys.pub; - } - if (shepherd.electrumKeys[_abbr].pub === pub && - shepherd.electrumKeys[_abbr].priv === priv) { - _matchingKeyPairs++; + if (shepherd.electrumKeys[_abbr].pub === pub && + shepherd.electrumKeys[_abbr].priv === priv) { + _matchingKeyPairs++; + } + _totalKeys++; } - _totalKeys++; - } - if (req.body.active) { - _electrumKeys = JSON.parse(JSON.stringify(shepherd.electrumKeys)); + if (req.body.active) { + _electrumKeys = JSON.parse(JSON.stringify(shepherd.electrumKeys)); - for (let key in _electrumKeys) { - if (!shepherd.electrumCoins[key]) { - delete _electrumKeys[key]; + for (let key in _electrumKeys) { + if (!shepherd.electrumCoins[key]) { + delete _electrumKeys[key]; + } } + } else { + _electrumKeys = shepherd.electrumKeys; } - } else { - _electrumKeys = shepherd.electrumKeys; - } - const successObj = { - msg: _wifError ? 'error' : 'success', - result: _wifError ? false : (_matchingKeyPairs === _totalKeys ? _electrumKeys : false), - }; + const successObj = { + msg: _wifError ? 'error' : 'success', + result: _wifError ? false : (_matchingKeyPairs === _totalKeys ? _electrumKeys : false), + }; - res.end(JSON.stringify(successObj)); + res.end(JSON.stringify(successObj)); + } else { + const errorObj = { + msg: 'error', + result: 'unauthorized access', + }; + + res.end(JSON.stringify(errorObj)); + } }); shepherd.getSpvFees = () => { @@ -153,35 +179,44 @@ module.exports = (shepherd) => { }; shepherd.post('/electrum/seed/bip39/match', (req, res, next) => { - const seed = bip39.mnemonicToSeed(req.body.seed); - const hdMaster = bitcoin.HDNode.fromSeedBuffer(seed, shepherd.electrumJSNetworks.komodo); // seed from above - const matchPattern = req.body.match; - const _defaultAddressDepth = req.body.addressdepth; - const _defaultAccountCount = req.body.accounts; - let _addresses = []; - let _matchingKey; - - for (let i = 0; i < _defaultAccountCount; i++) { - for (let j = 0; j < 1; j++) { - for (let k = 0; k < _defaultAddressDepth; k++) { - const _key = hdMaster.derivePath(`m/44'/141'/${i}'/${j}/${k}`); - - if (_key.keyPair.getAddress() === matchPattern) { - _matchingKey = { - pub: _key.keyPair.getAddress(), - priv: _key.keyPair.toWIF(), - }; + if (shepherd.checkToken(req.body.token)) { + const seed = bip39.mnemonicToSeed(req.body.seed); + const hdMaster = bitcoin.HDNode.fromSeedBuffer(seed, shepherd.electrumJSNetworks.komodo); // seed from above + const matchPattern = req.body.match; + const _defaultAddressDepth = req.body.addressdepth; + const _defaultAccountCount = req.body.accounts; + let _addresses = []; + let _matchingKey; + + for (let i = 0; i < _defaultAccountCount; i++) { + for (let j = 0; j < 1; j++) { + for (let k = 0; k < _defaultAddressDepth; k++) { + const _key = hdMaster.derivePath(`m/44'/141'/${i}'/${j}/${k}`); + + if (_key.keyPair.getAddress() === matchPattern) { + _matchingKey = { + pub: _key.keyPair.getAddress(), + priv: _key.keyPair.toWIF(), + }; + } } } } - } - const successObj = { - msg: 'success', - result: _matchingKey ? _matchingKey : 'address is not found', - }; + const successObj = { + msg: 'success', + result: _matchingKey ? _matchingKey : 'address is not found', + }; + + res.end(JSON.stringify(successObj)); + } else { + const errorObj = { + msg: 'error', + result: 'unauthorized access', + }; - res.end(JSON.stringify(successObj)); + res.end(JSON.stringify(errorObj)); + } }); return shepherd; diff --git a/routes/shepherd/electrum/listunspent.js b/routes/shepherd/electrum/listunspent.js index 180135f..7336115 100644 --- a/routes/shepherd/electrum/listunspent.js +++ b/routes/shepherd/electrum/listunspent.js @@ -155,40 +155,49 @@ module.exports = (shepherd) => { } shepherd.get('/electrum/listunspent', (req, res, next) => { - const network = req.query.network || shepherd.findNetworkObj(req.query.coin); - const ecl = new shepherd.electrumJSCore(shepherd.electrumServers[network].port, shepherd.electrumServers[network].address, shepherd.electrumServers[network].proto); // tcp or tls - - if (req.query.full && - req.query.full === 'true') { - shepherd.listunspent( - ecl, - req.query.address, - network, - true, - req.query.verify - ).then((listunspent) => { - shepherd.log('electrum listunspent ==>', true); - - const successObj = { - msg: 'success', - result: listunspent, - }; - - res.end(JSON.stringify(successObj)); - }); - } else { - shepherd.listunspent(ecl, req.query.address, network) - .then((listunspent) => { - ecl.close(); - shepherd.log('electrum listunspent ==>', true); + if (shepherd.checkToken(req.query.token)) { + const network = req.query.network || shepherd.findNetworkObj(req.query.coin); + const ecl = new shepherd.electrumJSCore(shepherd.electrumServers[network].port, shepherd.electrumServers[network].address, shepherd.electrumServers[network].proto); // tcp or tls + + if (req.query.full && + req.query.full === 'true') { + shepherd.listunspent( + ecl, + req.query.address, + network, + true, + req.query.verify + ).then((listunspent) => { + shepherd.log('electrum listunspent ==>', true); + + const successObj = { + msg: 'success', + result: listunspent, + }; + + res.end(JSON.stringify(successObj)); + }); + } else { + shepherd.listunspent(ecl, req.query.address, network) + .then((listunspent) => { + ecl.close(); + shepherd.log('electrum listunspent ==>', true); - const successObj = { - msg: 'success', - result: listunspent, - }; + const successObj = { + msg: 'success', + result: listunspent, + }; - res.end(JSON.stringify(successObj)); - }); + res.end(JSON.stringify(successObj)); + }); + } + } else { + const errorObj = { + msg: 'error', + result: 'unauthorized access', + }; + + res.end(JSON.stringify(errorObj)); } }); diff --git a/routes/shepherd/electrum/merkle.js b/routes/shepherd/electrum/merkle.js index 5f428e9..e7b6df7 100644 --- a/routes/shepherd/electrum/merkle.js +++ b/routes/shepherd/electrum/merkle.js @@ -128,17 +128,26 @@ module.exports = (shepherd) => { } shepherd.get('/electrum/merkle/verify', (req, res, next) => { - shepherd.verifyMerkleByCoin(req.query.coin, req.query.txid, req.query.height) - .then((verifyMerkleRes) => { - const successObj = { - msg: 'success', - result: { - merkleProof: verifyMerkleRes, - }, + if (shepherd.checkToken(req.query.token)) { + shepherd.verifyMerkleByCoin(req.query.coin, req.query.txid, req.query.height) + .then((verifyMerkleRes) => { + const successObj = { + msg: 'success', + result: { + merkleProof: verifyMerkleRes, + }, + }; + + res.end(JSON.stringify(successObj)); + }); + } else { + const errorObj = { + msg: 'error', + result: 'unauthorized access', }; - res.end(JSON.stringify(successObj)); - }); + res.end(JSON.stringify(errorObj)); + } }); return shepherd; diff --git a/routes/shepherd/electrum/network.js b/routes/shepherd/electrum/network.js index e201cfa..529642e 100644 --- a/routes/shepherd/electrum/network.js +++ b/routes/shepherd/electrum/network.js @@ -92,85 +92,112 @@ module.exports = (shepherd) => { } shepherd.get('/electrum/servers', (req, res, next) => { - if (req.query.abbr) { - let _electrumServers = {}; + if (shepherd.checkToken(req.query.token)) { + if (req.query.abbr) { + let _electrumServers = {}; - for (let key in shepherd.electrumServers) { - _electrumServers[shepherd.electrumServers[key].abbr] = shepherd.electrumServers[key]; - } + for (let key in shepherd.electrumServers) { + _electrumServers[shepherd.electrumServers[key].abbr] = shepherd.electrumServers[key]; + } - const successObj = { - msg: 'success', - result: { - servers: _electrumServers, - }, - }; + const successObj = { + msg: 'success', + result: { + servers: _electrumServers, + }, + }; - res.end(JSON.stringify(successObj)); + res.end(JSON.stringify(successObj)); + } else { + const successObj = { + msg: 'success', + result: { + servers: shepherd.electrumServers, + }, + }; + + res.end(JSON.stringify(successObj)); + } } else { - const successObj = { - msg: 'success', - result: { - servers: shepherd.electrumServers, - }, + const errorObj = { + msg: 'error', + result: 'unauthorized access', }; - res.end(JSON.stringify(successObj)); + res.end(JSON.stringify(errorObj)); } }); shepherd.get('/electrum/coins/server/set', (req, res, next) => { - shepherd.electrumCoins[req.query.coin].server = { - ip: req.query.address, - port: req.query.port, - }; + if (shepherd.checkToken(req.query.token)) { + shepherd.electrumCoins[req.query.coin].server = { + ip: req.query.address, + port: req.query.port, + }; - for (let key in shepherd.electrumServers) { - if (shepherd.electrumServers[key].abbr === req.query.coin) { // a bit risky - shepherd.electrumServers[key].address = req.query.address; - shepherd.electrumServers[key].port = req.query.port; - break; + for (let key in shepherd.electrumServers) { + if (shepherd.electrumServers[key].abbr === req.query.coin) { // a bit risky + shepherd.electrumServers[key].address = req.query.address; + shepherd.electrumServers[key].port = req.query.port; + break; + } } - } - shepherd.log(JSON.stringify(shepherd.electrumCoins[req.query.coin], null, '\t'), true); + // shepherd.log(JSON.stringify(shepherd.electrumCoins[req.query.coin], null, '\t'), true); - const successObj = { - msg: 'success', - result: true, - }; + const successObj = { + msg: 'success', + result: true, + }; - res.end(JSON.stringify(successObj)); + res.end(JSON.stringify(successObj)); + } else { + const errorObj = { + msg: 'error', + result: 'unauthorized access', + }; + + res.end(JSON.stringify(errorObj)); + } }); shepherd.get('/electrum/servers/test', (req, res, next) => { - const ecl = new shepherd.electrumJSCore(req.query.port, req.query.address, 'tcp'); // tcp or tls - - ecl.connect(); - ecl.serverVersion() - .then((serverData) => { - ecl.close(); - shepherd.log('serverData', true); - shepherd.log(serverData, true); - - if (serverData && - typeof serverData === 'string' && - serverData.indexOf('Electrum') > -1) { - const successObj = { - msg: 'success', - result: true, - }; - - res.end(JSON.stringify(successObj)); - } else { - const successObj = { - msg: 'error', - result: false, - }; + if (shepherd.checkToken(req.query.token)) { + const ecl = new shepherd.electrumJSCore(req.query.port, req.query.address, 'tcp'); // tcp or tls + + ecl.connect(); + ecl.serverVersion() + .then((serverData) => { + ecl.close(); + shepherd.log('serverData', true); + shepherd.log(serverData, true); + + if (serverData && + typeof serverData === 'string' && + serverData.indexOf('Electrum') > -1) { + const successObj = { + msg: 'success', + result: true, + }; + + res.end(JSON.stringify(successObj)); + } else { + const successObj = { + msg: 'error', + result: false, + }; + + res.end(JSON.stringify(successObj)); + } + }); + } else { + const errorObj = { + msg: 'error', + result: 'unauthorized access', + }; - res.end(JSON.stringify(successObj)); - } - }); + res.end(JSON.stringify(errorObj)); + } }); return shepherd; diff --git a/routes/shepherd/electrum/transactions.js b/routes/shepherd/electrum/transactions.js index a309d7d..f571962 100644 --- a/routes/shepherd/electrum/transactions.js +++ b/routes/shepherd/electrum/transactions.js @@ -14,218 +14,236 @@ module.exports = (shepherd) => { } shepherd.get('/electrum/listtransactions', (req, res, next) => { - const network = req.query.network || shepherd.findNetworkObj(req.query.coin); - const ecl = new shepherd.electrumJSCore(shepherd.electrumServers[network].port, shepherd.electrumServers[network].address, shepherd.electrumServers[network].proto); // tcp or tls + if (shepherd.checkToken(req.query.token)) { + const network = req.query.network || shepherd.findNetworkObj(req.query.coin); + const ecl = new shepherd.electrumJSCore(shepherd.electrumServers[network].port, shepherd.electrumServers[network].address, shepherd.electrumServers[network].proto); // tcp or tls - shepherd.log('electrum listtransactions ==>', true); + shepherd.log('electrum listtransactions ==>', true); - if (!req.query.full) { - ecl.connect(); - ecl.blockchainAddressGetHistory(req.query.address) - .then((json) => { - ecl.close(); - shepherd.log(json, true); - - json = shepherd.sortTransactions(json); + if (!req.query.full) { + ecl.connect(); + ecl.blockchainAddressGetHistory(req.query.address) + .then((json) => { + ecl.close(); + shepherd.log(json, true); - const successObj = { - msg: 'success', - result: json, - }; + json = shepherd.sortTransactions(json); - res.end(JSON.stringify(successObj)); - }); - } else { - // !expensive call! - // TODO: limit e.g. 1-10, 10-20 etc - const MAX_TX = req.query.maxlength || 10; - ecl.connect(); + const successObj = { + msg: 'success', + result: json, + }; - ecl.blockchainNumblocksSubscribe() - .then((currentHeight) => { - if (currentHeight && - Number(currentHeight) > 0) { - ecl.blockchainAddressGetHistory(req.query.address) - .then((json) => { - if (json && - json.length) { - json = shepherd.sortTransactions(json); - json = json.length > MAX_TX ? json.slice(0, MAX_TX) : json; - let _rawtx = []; - - shepherd.log(json.length, true); - - shepherd.Promise.all(json.map((transaction, index) => { - return new shepherd.Promise((resolve, reject) => { - ecl.blockchainBlockGetHeader(transaction.height) - .then((blockInfo) => { - if (blockInfo && - blockInfo.timestamp) { - ecl.blockchainTransactionGet(transaction['tx_hash']) - .then((_rawtxJSON) => { - shepherd.log('electrum gettransaction ==>', true); - shepherd.log((index + ' | ' + (_rawtxJSON.length - 1)), true); - shepherd.log(_rawtxJSON, true); - - // decode tx - const _network = shepherd.getNetworkData(network); - const decodedTx = shepherd.electrumJSTxDecoder(_rawtxJSON, network, _network); - - let txInputs = []; - shepherd.log(`decodedtx network ${network}`, true); - - shepherd.log('decodedtx =>', true); - shepherd.log(decodedTx.outputs, true); - - if (decodedTx && - decodedTx.inputs) { - shepherd.Promise.all(decodedTx.inputs.map((_decodedInput, index) => { - return new shepherd.Promise((_resolve, _reject) => { - if (_decodedInput.txid !== '0000000000000000000000000000000000000000000000000000000000000000') { - ecl.blockchainTransactionGet(_decodedInput.txid) - .then((rawInput) => { - const decodedVinVout = shepherd.electrumJSTxDecoder(rawInput, network, _network); - - shepherd.log('electrum raw input tx ==>', true); - - if (decodedVinVout) { - shepherd.log(decodedVinVout.outputs[_decodedInput.n], true); - txInputs.push(decodedVinVout.outputs[_decodedInput.n]); - _resolve(true); - } else { - _resolve(true); - } - }); + res.end(JSON.stringify(successObj)); + }); + } else { + // !expensive call! + // TODO: limit e.g. 1-10, 10-20 etc + const MAX_TX = req.query.maxlength || 10; + ecl.connect(); + + ecl.blockchainNumblocksSubscribe() + .then((currentHeight) => { + if (currentHeight && + Number(currentHeight) > 0) { + ecl.blockchainAddressGetHistory(req.query.address) + .then((json) => { + if (json && + json.length) { + json = shepherd.sortTransactions(json); + json = json.length > MAX_TX ? json.slice(0, MAX_TX) : json; + let _rawtx = []; + + shepherd.log(json.length, true); + + shepherd.Promise.all(json.map((transaction, index) => { + return new shepherd.Promise((resolve, reject) => { + ecl.blockchainBlockGetHeader(transaction.height) + .then((blockInfo) => { + if (blockInfo && + blockInfo.timestamp) { + ecl.blockchainTransactionGet(transaction['tx_hash']) + .then((_rawtxJSON) => { + shepherd.log('electrum gettransaction ==>', true); + shepherd.log((index + ' | ' + (_rawtxJSON.length - 1)), true); + shepherd.log(_rawtxJSON, true); + + // decode tx + const _network = shepherd.getNetworkData(network); + const decodedTx = shepherd.electrumJSTxDecoder(_rawtxJSON, network, _network); + + let txInputs = []; + shepherd.log(`decodedtx network ${network}`, true); + + shepherd.log('decodedtx =>', true); + shepherd.log(decodedTx.outputs, true); + + if (decodedTx && + decodedTx.inputs) { + shepherd.Promise.all(decodedTx.inputs.map((_decodedInput, index) => { + return new shepherd.Promise((_resolve, _reject) => { + if (_decodedInput.txid !== '0000000000000000000000000000000000000000000000000000000000000000') { + ecl.blockchainTransactionGet(_decodedInput.txid) + .then((rawInput) => { + const decodedVinVout = shepherd.electrumJSTxDecoder(rawInput, network, _network); + + shepherd.log('electrum raw input tx ==>', true); + + if (decodedVinVout) { + shepherd.log(decodedVinVout.outputs[_decodedInput.n], true); + txInputs.push(decodedVinVout.outputs[_decodedInput.n]); + _resolve(true); + } else { + _resolve(true); + } + }); + } else { + _resolve(true); + } + }); + })) + .then(promiseResult => { + const _parsedTx = { + network: decodedTx.network, + format: decodedTx.format, + inputs: txInputs, + outputs: decodedTx.outputs, + height: transaction.height, + timestamp: Number(transaction.height) === 0 ? Math.floor(Date.now() / 1000) : blockInfo.timestamp, + confirmations: Number(transaction.height) === 0 ? 0 : currentHeight - transaction.height, + }; + + const formattedTx = shepherd.parseTransactionAddresses(_parsedTx, req.query.address, network); + + if (formattedTx.type) { + formattedTx.height = transaction.height; + formattedTx.blocktime = blockInfo.timestamp; + formattedTx.timereceived = blockInfo.timereceived; + formattedTx.hex = _rawtxJSON; + formattedTx.inputs = decodedTx.inputs; + formattedTx.outputs = decodedTx.outputs; + formattedTx.locktime = decodedTx.format.locktime; + _rawtx.push(formattedTx); } else { - _resolve(true); + formattedTx[0].height = transaction.height; + formattedTx[0].blocktime = blockInfo.timestamp; + formattedTx[0].timereceived = blockInfo.timereceived; + formattedTx[0].hex = _rawtxJSON; + formattedTx[0].inputs = decodedTx.inputs; + formattedTx[0].outputs = decodedTx.outputs; + formattedTx[0].locktime = decodedTx.format.locktime; + formattedTx[1].height = transaction.height; + formattedTx[1].blocktime = blockInfo.timestamp; + formattedTx[1].timereceived = blockInfo.timereceived; + formattedTx[1].hex = _rawtxJSON; + formattedTx[1].inputs = decodedTx.inputs; + formattedTx[1].outputs = decodedTx.outputs; + formattedTx[1].locktime = decodedTx.format.locktime; + _rawtx.push(formattedTx[0]); + _rawtx.push(formattedTx[1]); } + resolve(true); }); - })) - .then(promiseResult => { + } else { const _parsedTx = { network: decodedTx.network, - format: decodedTx.format, - inputs: txInputs, - outputs: decodedTx.outputs, + format: 'cant parse', + inputs: 'cant parse', + outputs: 'cant parse', height: transaction.height, timestamp: Number(transaction.height) === 0 ? Math.floor(Date.now() / 1000) : blockInfo.timestamp, confirmations: Number(transaction.height) === 0 ? 0 : currentHeight - transaction.height, }; const formattedTx = shepherd.parseTransactionAddresses(_parsedTx, req.query.address, network); - - if (formattedTx.type) { - formattedTx.height = transaction.height; - formattedTx.blocktime = blockInfo.timestamp; - formattedTx.timereceived = blockInfo.timereceived; - formattedTx.hex = _rawtxJSON; - formattedTx.inputs = decodedTx.inputs; - formattedTx.outputs = decodedTx.outputs; - formattedTx.locktime = decodedTx.format.locktime; - _rawtx.push(formattedTx); - } else { - formattedTx[0].height = transaction.height; - formattedTx[0].blocktime = blockInfo.timestamp; - formattedTx[0].timereceived = blockInfo.timereceived; - formattedTx[0].hex = _rawtxJSON; - formattedTx[0].inputs = decodedTx.inputs; - formattedTx[0].outputs = decodedTx.outputs; - formattedTx[0].locktime = decodedTx.format.locktime; - formattedTx[1].height = transaction.height; - formattedTx[1].blocktime = blockInfo.timestamp; - formattedTx[1].timereceived = blockInfo.timereceived; - formattedTx[1].hex = _rawtxJSON; - formattedTx[1].inputs = decodedTx.inputs; - formattedTx[1].outputs = decodedTx.outputs; - formattedTx[1].locktime = decodedTx.format.locktime; - _rawtx.push(formattedTx[0]); - _rawtx.push(formattedTx[1]); - } + _rawtx.push(formattedTx); resolve(true); - }); - } else { - const _parsedTx = { - network: decodedTx.network, - format: 'cant parse', - inputs: 'cant parse', - outputs: 'cant parse', - height: transaction.height, - timestamp: Number(transaction.height) === 0 ? Math.floor(Date.now() / 1000) : blockInfo.timestamp, - confirmations: Number(transaction.height) === 0 ? 0 : currentHeight - transaction.height, - }; - - const formattedTx = shepherd.parseTransactionAddresses(_parsedTx, req.query.address, network); - _rawtx.push(formattedTx); - resolve(true); - } - }); - } else { - const _parsedTx = { - network: 'cant parse', - format: 'cant parse', - inputs: 'cant parse', - outputs: 'cant parse', - height: transaction.height, - timestamp: 'cant get block info', - confirmations: Number(transaction.height) === 0 ? 0 : currentHeight - transaction.height, - }; - const formattedTx = shepherd.parseTransactionAddresses(_parsedTx, req.query.address, network); - _rawtx.push(formattedTx); - resolve(true); - } + } + }); + } else { + const _parsedTx = { + network: 'cant parse', + format: 'cant parse', + inputs: 'cant parse', + outputs: 'cant parse', + height: transaction.height, + timestamp: 'cant get block info', + confirmations: Number(transaction.height) === 0 ? 0 : currentHeight - transaction.height, + }; + const formattedTx = shepherd.parseTransactionAddresses(_parsedTx, req.query.address, network); + _rawtx.push(formattedTx); + resolve(true); + } + }); }); - }); - })) - .then(promiseResult => { - ecl.close(); + })) + .then(promiseResult => { + ecl.close(); + const successObj = { + msg: 'success', + result: _rawtx, + }; + + res.end(JSON.stringify(successObj)); + }); + } else { const successObj = { msg: 'success', - result: _rawtx, + result: [], }; res.end(JSON.stringify(successObj)); - }); - } else { - const successObj = { - msg: 'success', - result: [], - }; - - res.end(JSON.stringify(successObj)); - } - }); - } else { - const successObj = { - msg: 'error', - result: 'cant get current height', - }; + } + }); + } else { + const successObj = { + msg: 'error', + result: 'cant get current height', + }; + + res.end(JSON.stringify(successObj)); + } + }); + } + } else { + const errorObj = { + msg: 'error', + result: 'unauthorized access', + }; - res.end(JSON.stringify(successObj)); - } - }); + res.end(JSON.stringify(errorObj)); } }); shepherd.get('/electrum/gettransaction', (req, res, next) => { - const network = req.query.network || shepherd.findNetworkObj(req.query.coin); - const ecl = new shepherd.electrumJSCore(shepherd.electrumServers[network].port, shepherd.electrumServers[network].address, shepherd.electrumServers[network].proto); // tcp or tls + if (shepherd.checkToken(req.query.token)) { + const network = req.query.network || shepherd.findNetworkObj(req.query.coin); + const ecl = new shepherd.electrumJSCore(shepherd.electrumServers[network].port, shepherd.electrumServers[network].address, shepherd.electrumServers[network].proto); // tcp or tls - shepherd.log('electrum gettransaction =>', true); + shepherd.log('electrum gettransaction =>', true); + + ecl.connect(); + ecl.blockchainTransactionGet(req.query.txid) + .then((json) => { + ecl.close(); + shepherd.log(json, true); - ecl.connect(); - ecl.blockchainTransactionGet(req.query.txid) - .then((json) => { - ecl.close(); - shepherd.log(json, true); + const successObj = { + msg: 'success', + result: json, + }; - const successObj = { - msg: 'success', - result: json, + res.end(JSON.stringify(successObj)); + }); + } else { + const errorObj = { + msg: 'error', + result: 'unauthorized access', }; - res.end(JSON.stringify(successObj)); - }); + res.end(JSON.stringify(errorObj)); + } }); shepherd.parseTransactionAddresses = (tx, targetAddress, network) => { @@ -346,54 +364,62 @@ module.exports = (shepherd) => { } shepherd.get('/electrum/decoderawtx', (req, res, next) => { - const _network = shepherd.getNetworkData(req.query.network); - const _rawtx = req.query.rawtx; - console.log(_network); - //const _rawtx = '010000006f2c395a02d81487fc7f9d1be3ea900316730133c044af70cd76d21e988e71de0e9e85918f010000006a47304402202097acd391e1d0eaaf91844bd596e918fb71320e3e0c51554acb71a39e4ee98b0220548fd61d4ae77a08d70b01bf5340983a1ba63f6b71ad71d478af77011f96fd510121031ffc010d8abc4180b4c1a13962bf9153a78082e7f2ac18f7d14cb6a6634ca218feffffff2b31f6c9a7916f7cf128cae94b3fc10e4c74ca3a740e1a7a6fd6624e4e9a5c8b010000006a473044022063f014c5fbaa7614732e0ae486179a854215fc32c02230e13f69b7e81fa000e50220236a2ba6373b1854aafc59c5391ab7505062067f3d293c016cbb5d252b35a56a012102f307f17d282fc0eabf99227c2e0f3122ae9ecd7da0de099f0c6007d4c941b57bfeffffff021b797ad7120000001976a914c7a7142d743b3e6eebe76923f43bae477d3ce31a88acff086d66000000001976a91463800ff36b9c52b2ffe5564af1c2a38df4f0126788ac16381d00'; - const decodedTx = shepherd.electrumJSTxDecoder(_rawtx, req.query.network, _network); - - shepherd.log('electrum decoderawtx input tx ==>', true); - - if (req.query.parseonly || - decodedTx.inputs[0].txid === '0000000000000000000000000000000000000000000000000000000000000000') { - const successObj = { - msg: 'success', - result: { - network: decodedTx.network, - format: decodedTx.format, - inputs: decodedTx.inputs, - outputs: decodedTx.outputs, - }, - }; + if (shepherd.checkToken(req.query.token)) { + const _network = shepherd.getNetworkData(req.query.network); + const _rawtx = req.query.rawtx; + //const _rawtx = '010000006f2c395a02d81487fc7f9d1be3ea900316730133c044af70cd76d21e988e71de0e9e85918f010000006a47304402202097acd391e1d0eaaf91844bd596e918fb71320e3e0c51554acb71a39e4ee98b0220548fd61d4ae77a08d70b01bf5340983a1ba63f6b71ad71d478af77011f96fd510121031ffc010d8abc4180b4c1a13962bf9153a78082e7f2ac18f7d14cb6a6634ca218feffffff2b31f6c9a7916f7cf128cae94b3fc10e4c74ca3a740e1a7a6fd6624e4e9a5c8b010000006a473044022063f014c5fbaa7614732e0ae486179a854215fc32c02230e13f69b7e81fa000e50220236a2ba6373b1854aafc59c5391ab7505062067f3d293c016cbb5d252b35a56a012102f307f17d282fc0eabf99227c2e0f3122ae9ecd7da0de099f0c6007d4c941b57bfeffffff021b797ad7120000001976a914c7a7142d743b3e6eebe76923f43bae477d3ce31a88acff086d66000000001976a91463800ff36b9c52b2ffe5564af1c2a38df4f0126788ac16381d00'; + const decodedTx = shepherd.electrumJSTxDecoder(_rawtx, req.query.network, _network); - shepherd.log(successObj.result, true); - - res.end(JSON.stringify(successObj)); - } else { - const ecl = new shepherd.electrumJSCore(shepherd.electrumServers[req.query.network].port, shepherd.electrumServers[req.query.network].address, shepherd.electrumServers[req.query.network].proto); // tcp or tls - - ecl.connect(); - shepherd.log(decodedTx.inputs[0]); - shepherd.log(decodedTx.inputs[0].txid); - ecl.blockchainTransactionGet(decodedTx.inputs[0].txid) - .then((json) => { - ecl.close(); - shepherd.log(json, true); - - const decodedVin = shepherd.electrumJSTxDecoder(json, req.query.network, _network); + shepherd.log('electrum decoderawtx input tx ==>', true); + if (req.query.parseonly || + decodedTx.inputs[0].txid === '0000000000000000000000000000000000000000000000000000000000000000') { const successObj = { msg: 'success', result: { network: decodedTx.network, format: decodedTx.format, - inputs: decodedVin.outputs[decodedTx.inputs[0].n], + inputs: decodedTx.inputs, outputs: decodedTx.outputs, }, }; + shepherd.log(successObj.result, true); + res.end(JSON.stringify(successObj)); - }); + } else { + const ecl = new shepherd.electrumJSCore(shepherd.electrumServers[req.query.network].port, shepherd.electrumServers[req.query.network].address, shepherd.electrumServers[req.query.network].proto); // tcp or tls + + ecl.connect(); + shepherd.log(decodedTx.inputs[0]); + shepherd.log(decodedTx.inputs[0].txid); + ecl.blockchainTransactionGet(decodedTx.inputs[0].txid) + .then((json) => { + ecl.close(); + shepherd.log(json, true); + + const decodedVin = shepherd.electrumJSTxDecoder(json, req.query.network, _network); + + const successObj = { + msg: 'success', + result: { + network: decodedTx.network, + format: decodedTx.format, + inputs: decodedVin.outputs[decodedTx.inputs[0].n], + outputs: decodedTx.outputs, + }, + }; + + res.end(JSON.stringify(successObj)); + }); + } + } else { + const errorObj = { + msg: 'error', + result: 'unauthorized access', + }; + + res.end(JSON.stringify(errorObj)); } }); diff --git a/routes/shepherd/kickstart.js b/routes/shepherd/kickstart.js index 99d26e5..c10ef56 100644 --- a/routes/shepherd/kickstart.js +++ b/routes/shepherd/kickstart.js @@ -7,37 +7,46 @@ module.exports = (shepherd) => { * params: coin, type */ shepherd.get('/kick', (req, res, next) => { - const _coin = req.query.coin; - const _keepWallet = req.query.keepwallet; + if (shepherd.checkToken(req.query.token)) { + const _coin = req.query.coin; + const _keepWallet = req.query.keepwallet; + + if (!_coin) { + const errorObj = { + msg: 'error', + result: 'no coin name provided', + }; + + res.end(JSON.stringify(errorObj)); + } else { + const _location = path.join(_coin === 'KMD' ? shepherd.komodoDir : `${shepherd.komodoDir}/${_coin}`); + + if (fs.existsSync(_location)) { + const items = fs.readdirSync(_location); + + for (let i = 0; i < items.length; i++) { + if (items[i].indexOf('wallet.dat') === -1) { + fs.removeSync(`${_location}/${items[i]}`); + } else if (!_keepWallet) { + fs.removeSync(`${_location}/${items[i]}`); + } + } + } - if (!_coin) { + const successObj = { + msg: 'success', + result: `${_coin} native is kicked`, + }; + + res.end(JSON.stringify(successObj)); + } + } else { const errorObj = { msg: 'error', - result: 'no coin name provided', + result: 'unauthorized access', }; res.end(JSON.stringify(errorObj)); - } else { - const _location = path.join(_coin === 'KMD' ? shepherd.komodoDir : `${shepherd.komodoDir}/${_coin}`); - - if (fs.existsSync(_location)) { - const items = fs.readdirSync(_location); - - for (let i = 0; i < items.length; i++) { - if (items[i].indexOf('wallet.dat') === -1) { - fs.removeSync(`${_location}/${items[i]}`); - } else if (!_keepWallet) { - fs.removeSync(`${_location}/${items[i]}`); - } - } - } - - const successObj = { - msg: 'success', - result: `${_coin} native is kicked`, - }; - - res.end(JSON.stringify(successObj)); } }); diff --git a/routes/shepherd/log.js b/routes/shepherd/log.js index 9bf8472..6ab2a9e 100644 --- a/routes/shepherd/log.js +++ b/routes/shepherd/log.js @@ -40,12 +40,21 @@ module.exports = (shepherd) => { } shepherd.get('/log/runtime', (req, res, next) => { - const successObj = { - msg: 'success', - result: req.query.spv && req.query.spv === 'true' ? shepherd.appRuntimeSPVLog : shepherd.appRuntimeLog, - }; + if (shepherd.checkToken(req.query.token)) { + const successObj = { + msg: 'success', + result: req.query.spv && req.query.spv === 'true' ? shepherd.appRuntimeSPVLog : shepherd.appRuntimeLog, + }; + + res.end(JSON.stringify(successObj)); + } else { + const errorObj = { + msg: 'error', + result: 'unauthorized access', + }; - res.end(JSON.stringify(successObj)); + res.end(JSON.stringify(errorObj)); + } }); shepherd.getAppRuntimeLog = () => { @@ -59,37 +68,46 @@ module.exports = (shepherd) => { * params: payload */ shepherd.post('/guilog', (req, res, next) => { - const logLocation = `${shepherd.agamaDir}/shepherd`; + if (shepherd.checkToken(req.body.token)) { + const logLocation = `${shepherd.agamaDir}/shepherd`; - if (!shepherd.guiLog[shepherd.appSessionHash]) { - shepherd.guiLog[shepherd.appSessionHash] = {}; - } - - if (shepherd.guiLog[shepherd.appSessionHash][req.body.timestamp]) { - shepherd.guiLog[shepherd.appSessionHash][req.body.timestamp].status = req.body.status; - shepherd.guiLog[shepherd.appSessionHash][req.body.timestamp].response = req.body.response; - } else { - shepherd.guiLog[shepherd.appSessionHash][req.body.timestamp] = { - function: req.body.function, - type: req.body.type, - url: req.body.url, - payload: req.body.payload, - status: req.body.status, - }; - } + if (!shepherd.guiLog[shepherd.appSessionHash]) { + shepherd.guiLog[shepherd.appSessionHash] = {}; + } - shepherd.fs.writeFile(`${logLocation}/agamalog.json`, JSON.stringify(shepherd.guiLog), (err) => { - if (err) { - shepherd.writeLog('error writing gui log file'); + if (shepherd.guiLog[shepherd.appSessionHash][req.body.timestamp]) { + shepherd.guiLog[shepherd.appSessionHash][req.body.timestamp].status = req.body.status; + shepherd.guiLog[shepherd.appSessionHash][req.body.timestamp].response = req.body.response; + } else { + shepherd.guiLog[shepherd.appSessionHash][req.body.timestamp] = { + function: req.body.function, + type: req.body.type, + url: req.body.url, + payload: req.body.payload, + status: req.body.status, + }; } - const returnObj = { - msg: 'success', - result: 'gui log entry is added', + shepherd.fs.writeFile(`${logLocation}/agamalog.json`, JSON.stringify(shepherd.guiLog), (err) => { + if (err) { + shepherd.writeLog('error writing gui log file'); + } + + const returnObj = { + msg: 'success', + result: 'gui log entry is added', + }; + + res.end(JSON.stringify(returnObj)); + }); + } else { + const errorObj = { + msg: 'error', + result: 'unauthorized access', }; - res.end(JSON.stringify(returnObj)); - }); + res.end(JSON.stringify(errorObj)); + } }); /* @@ -97,30 +115,39 @@ module.exports = (shepherd) => { * params: type */ shepherd.get('/getlog', (req, res, next) => { - const logExt = req.query.type === 'txt' ? 'txt' : 'json'; + if (shepherd.checkToken(req.query.token)) { + const logExt = req.query.type === 'txt' ? 'txt' : 'json'; - if (shepherd.fs.existsSync(`${shepherd.agamaDir}/shepherd/agamalog.${logExt}`)) { - shepherd.fs.readFile(`${shepherd.agamaDir}/shepherd/agamalog.${logExt}`, 'utf8', (err, data) => { - if (err) { - const errorObj = { - msg: 'error', - result: err, - }; - - res.end(JSON.stringify(errorObj)); - } else { - const successObj = { - msg: 'success', - result: data ? JSON.parse(data) : '', - }; - - res.end(JSON.stringify(successObj)); - } - }); + if (shepherd.fs.existsSync(`${shepherd.agamaDir}/shepherd/agamalog.${logExt}`)) { + shepherd.fs.readFile(`${shepherd.agamaDir}/shepherd/agamalog.${logExt}`, 'utf8', (err, data) => { + if (err) { + const errorObj = { + msg: 'error', + result: err, + }; + + res.end(JSON.stringify(errorObj)); + } else { + const successObj = { + msg: 'success', + result: data ? JSON.parse(data) : '', + }; + + res.end(JSON.stringify(successObj)); + } + }); + } else { + const errorObj = { + msg: 'error', + result: `agama.${logExt} doesnt exist`, + }; + + res.end(JSON.stringify(errorObj)); + } } else { const errorObj = { msg: 'error', - result: `agama.${logExt} doesnt exist`, + result: 'unauthorized access', }; res.end(JSON.stringify(errorObj)); diff --git a/routes/shepherd/pin.js b/routes/shepherd/pin.js index 6776b6c..3d9229f 100644 --- a/routes/shepherd/pin.js +++ b/routes/shepherd/pin.js @@ -7,93 +7,111 @@ module.exports = (shepherd) => { * params: none */ shepherd.post('/encryptkey', (req, res, next) => { - if (req.body.key && - req.body.string && - req.body.pubkey) { - const encryptedString = aes256.encrypt(req.body.key, req.body.string); - - // test pin security - // - at least 1 char in upper case - // - at least 1 digit - // - at least one special character - // - min length 8 - - const _pin = req.body.key; - const _pinTest = _pin.match('^(?=.*[A-Z])(?=.*[^<>{}\"/|;:.,~!?@#$%^=&*\\]\\\\()\\[_+]*$)(?=.*[0-9])(?=.*[a-z]).{8}$'); - - fs.writeFile(`${shepherd.agamaDir}/shepherd/pin/${req.body.pubkey}.pin`, encryptedString, (err) => { - if (err) { - shepherd.log('error writing pin file'); - } + if (shepherd.checkToken(req.body.token)) { + if (req.body.key && + req.body.string && + req.body.pubkey) { + const encryptedString = aes256.encrypt(req.body.key, req.body.string); + + // test pin security + // - at least 1 char in upper case + // - at least 1 digit + // - at least one special character + // - min length 8 + + const _pin = req.body.key; + const _pinTest = _pin.match('^(?=.*[A-Z])(?=.*[^<>{}\"/|;:.,~!?@#$%^=&*\\]\\\\()\\[_+]*$)(?=.*[0-9])(?=.*[a-z]).{8}$'); + + fs.writeFile(`${shepherd.agamaDir}/shepherd/pin/${req.body.pubkey}.pin`, encryptedString, (err) => { + if (err) { + shepherd.log('error writing pin file'); + } + + const returnObj = { + msg: 'success', + result: encryptedString, + }; - const returnObj = { - msg: 'success', - result: encryptedString, + res.end(JSON.stringify(returnObj)); + }); + } else { + const _paramsList = [ + 'key', + 'string', + 'pubkey' + ]; + let errorObj = { + msg: 'error', + result: '', }; + let _errorParamsList = []; + + for (let i = 0; i < _paramsList.length; i++) { + if (!req.query[_paramsList[i]]) { + _errorParamsList.push(_paramsList[i]); + } + } - res.end(JSON.stringify(returnObj)); - }); + errorObj.result = `missing param ${_errorParamsList.join(', ')}`; + res.end(JSON.stringify(errorObj)); + } } else { - let errorObj = { + const errorObj = { msg: 'error', - result: '', + result: 'unauthorized access', }; - const _paramsList = [ - 'key', - 'string', - 'pubkey' - ]; - let _errorParamsList = []; - - for (let i = 0; i < _paramsList.length; i++) { - if (!req.query[_paramsList[i]]) { - _errorParamsList.push(_paramsList[i]); - } - } - errorObj.result = `missing param ${_errorParamsList.join(', ')}`; res.end(JSON.stringify(errorObj)); } }); shepherd.post('/decryptkey', (req, res, next) => { - if (req.body.key && - req.body.pubkey) { - if (fs.existsSync(`${shepherd.agamaDir}/shepherd/pin/${req.body.pubkey}.pin`)) { - fs.readFile(`${shepherd.agamaDir}/shepherd/pin/${req.body.pubkey}.pin`, 'utf8', (err, data) => { - if (err) { - const errorObj = { - msg: 'error', - result: err, - }; - - res.end(JSON.stringify(errorObj)); - } else { - const encryptedKey = aes256.decrypt(req.body.key, data); - // test if stored encrypted passphrase is decrypted correctly - // if not then the key is wrong - const _regexTest = encryptedKey.match(/^[0-9a-zA-Z ]+$/g); - let returnObj; - - if (!_regexTest) { - returnObj = { + if (shepherd.checkToken(req.body.token)) { + if (req.body.key && + req.body.pubkey) { + if (fs.existsSync(`${shepherd.agamaDir}/shepherd/pin/${req.body.pubkey}.pin`)) { + fs.readFile(`${shepherd.agamaDir}/shepherd/pin/${req.body.pubkey}.pin`, 'utf8', (err, data) => { + if (err) { + const errorObj = { msg: 'error', - result: 'wrong key', + result: err, }; + + res.end(JSON.stringify(errorObj)); } else { - returnObj = { - msg: 'success', - result: encryptedKey, - }; + const encryptedKey = aes256.decrypt(req.body.key, data); + // test if stored encrypted passphrase is decrypted correctly + // if not then the key is wrong + const _regexTest = encryptedKey.match(/^[0-9a-zA-Z ]+$/g); + let returnObj; + + if (!_regexTest) { + returnObj = { + msg: 'error', + result: 'wrong key', + }; + } else { + returnObj = { + msg: 'success', + result: encryptedKey, + }; + } + + res.end(JSON.stringify(returnObj)); } + }); + } else { + const errorObj = { + msg: 'error', + result: `file ${req.query.pubkey}.pin doesnt exist`, + }; - res.end(JSON.stringify(returnObj)); - } - }); + res.end(JSON.stringify(errorObj)); + } } else { const errorObj = { msg: 'error', - result: `file ${req.query.pubkey}.pin doesnt exist`, + result: 'missing key or pubkey param', }; res.end(JSON.stringify(errorObj)); @@ -101,7 +119,7 @@ module.exports = (shepherd) => { } else { const errorObj = { msg: 'error', - result: 'missing key or pubkey param', + result: 'unauthorized access', }; res.end(JSON.stringify(errorObj)); @@ -109,36 +127,45 @@ module.exports = (shepherd) => { }); shepherd.get('/getpinlist', (req, res, next) => { - if (fs.existsSync(`${shepherd.agamaDir}/shepherd/pin`)) { - fs.readdir(`${shepherd.agamaDir}/shepherd/pin`, (err, items) => { - let _pins = []; - - for (let i = 0; i < items.length; i++) { - if (items[i].substr(items[i].length - 4, 4) === '.pin') { - _pins.push(items[i].substr(0, items[i].length - 4)); + if (shepherd.checkToken(req.body.token)) { + if (fs.existsSync(`${shepherd.agamaDir}/shepherd/pin`)) { + fs.readdir(`${shepherd.agamaDir}/shepherd/pin`, (err, items) => { + let _pins = []; + + for (let i = 0; i < items.length; i++) { + if (items[i].substr(items[i].length - 4, 4) === '.pin') { + _pins.push(items[i].substr(0, items[i].length - 4)); + } } - } - if (!items.length) { - const errorObj = { - msg: 'error', - result: 'no pins', - }; + if (!items.length) { + const errorObj = { + msg: 'error', + result: 'no pins', + }; - res.end(JSON.stringify(errorObj)); - } else { - const successObj = { - msg: 'success', - result: _pins, - }; + res.end(JSON.stringify(errorObj)); + } else { + const successObj = { + msg: 'success', + result: _pins, + }; - res.end(JSON.stringify(successObj)); - } - }); + res.end(JSON.stringify(successObj)); + } + }); + } else { + const errorObj = { + msg: 'error', + result: 'pin folder doesnt exist', + }; + + res.end(JSON.stringify(errorObj)); + } } else { const errorObj = { msg: 'error', - result: 'pin folder doesnt exist', + result: 'unauthorized access', }; res.end(JSON.stringify(errorObj)); diff --git a/routes/shepherd/quitDaemon.js b/routes/shepherd/quitDaemon.js index 4283d99..15c9021 100644 --- a/routes/shepherd/quitDaemon.js +++ b/routes/shepherd/quitDaemon.js @@ -82,41 +82,32 @@ module.exports = (shepherd) => { } shepherd.post('/coind/stop', (req, res) => { - const _chain = req.body.chain; - let _coindQuitCmd = shepherd.komodocliBin; - let _arg = []; + if (shepherd.checkToken(req.body.token)) { + const _chain = req.body.chain; + let _coindQuitCmd = shepherd.komodocliBin; + let _arg = []; - if (_chain) { - _arg.push(`-ac_name=${_chain}`); + if (_chain) { + _arg.push(`-ac_name=${_chain}`); - if (shepherd.appConfig.dataDir.length) { - _arg.push(`-datadir=${shepherd.appConfig.dataDir + (_chain ? '/' + _chain : '')}`); + if (shepherd.appConfig.dataDir.length) { + _arg.push(`-datadir=${shepherd.appConfig.dataDir + (_chain ? '/' + _chain : '')}`); + } + } else if (!_chain && shepherd.appConfig.dataDir.length) { + _arg.push(`-datadir=${shepherd.appConfig.dataDir}`); } - } else if (!_chain && shepherd.appConfig.dataDir.length) { - _arg.push(`-datadir=${shepherd.appConfig.dataDir}`); - } - - _arg.push('stop'); - execFile(`${_coindQuitCmd}`, _arg, (error, stdout, stderr) => { - shepherd.log(`stdout: ${stdout}`); - shepherd.log(`stderr: ${stderr}`); - shepherd.log(`send stop sig to ${_chain ? _chain : 'komodo'}`); - - if (stdout.indexOf('EOF reached') > -1 || - stderr.indexOf('EOF reached') > -1 || - (error && error.toString().indexOf('Command failed') > -1 && !stderr) || // win "special snowflake" case - stdout.indexOf('connect to server: unknown (code -1)') > -1 || - stderr.indexOf('connect to server: unknown (code -1)') > -1) { - delete shepherd.coindInstanceRegistry[_chain ? _chain : 'komodod']; - const obj = { - msg: 'success', - result: 'result', - }; - - res.end(JSON.stringify(obj)); - } else { - if (stdout.indexOf('Komodo server stopping') > -1) { + _arg.push('stop'); + execFile(`${_coindQuitCmd}`, _arg, (error, stdout, stderr) => { + shepherd.log(`stdout: ${stdout}`); + shepherd.log(`stderr: ${stderr}`); + shepherd.log(`send stop sig to ${_chain ? _chain : 'komodo'}`); + + if (stdout.indexOf('EOF reached') > -1 || + stderr.indexOf('EOF reached') > -1 || + (error && error.toString().indexOf('Command failed') > -1 && !stderr) || // win "special snowflake" case + stdout.indexOf('connect to server: unknown (code -1)') > -1 || + stderr.indexOf('connect to server: unknown (code -1)') > -1) { delete shepherd.coindInstanceRegistry[_chain ? _chain : 'komodod']; const obj = { @@ -126,43 +117,70 @@ module.exports = (shepherd) => { res.end(JSON.stringify(obj)); } else { - const obj = { - msg: 'error', - result: 'result', - }; - - res.end(JSON.stringify(obj)); + if (stdout.indexOf('Komodo server stopping') > -1) { + delete shepherd.coindInstanceRegistry[_chain ? _chain : 'komodod']; + + const obj = { + msg: 'success', + result: 'result', + }; + + res.end(JSON.stringify(obj)); + } else { + const obj = { + msg: 'error', + result: 'result', + }; + + res.end(JSON.stringify(obj)); + } } - } - }); + }); + } else { + const errorObj = { + msg: 'error', + result: 'unauthorized access', + }; + + res.end(JSON.stringify(errorObj)); + } }); shepherd.post('/coins/remove', (req, res) => { - const _chain = req.body.chain; + if (shepherd.checkToken(req.body.token)) { + const _chain = req.body.chain; - if (req.body.mode === 'native') { - delete shepherd.coindInstanceRegistry[_chain ? _chain : 'komodod']; + if (req.body.mode === 'native') { + delete shepherd.coindInstanceRegistry[_chain ? _chain : 'komodod']; - const obj = { - msg: 'success', - result: 'result', - }; + const obj = { + msg: 'success', + result: 'result', + }; - res.end(JSON.stringify(obj)); - } else { - delete shepherd.electrumCoins[_chain === 'komodo' ? 'KMD' : _chain]; + res.end(JSON.stringify(obj)); + } else { + delete shepherd.electrumCoins[_chain === 'komodo' ? 'KMD' : _chain]; - if (Object.keys(shepherd.electrumCoins).length - 1 === 0) { - shepherd.electrumCoins.auth = false; - shepherd.electrumKeys = {}; - } + if (Object.keys(shepherd.electrumCoins).length - 1 === 0) { + shepherd.electrumCoins.auth = false; + shepherd.electrumKeys = {}; + } + + const obj = { + msg: 'success', + result: 'result', + }; - const obj = { - msg: 'success', - result: 'result', + res.end(JSON.stringify(obj)); + } + } else { + const errorObj = { + msg: 'error', + result: 'unauthorized access', }; - res.end(JSON.stringify(obj)); + res.end(JSON.stringify(errorObj)); } }); diff --git a/routes/shepherd/rpc.js b/routes/shepherd/rpc.js index 7258df1..2e64bd9 100644 --- a/routes/shepherd/rpc.js +++ b/routes/shepherd/rpc.js @@ -60,270 +60,279 @@ module.exports = (shepherd) => { * params: payload */ shepherd.post('/cli', (req, res, next) => { - if (!req.body.payload) { - const errorObj = { - msg: 'error', - result: 'no payload provided', - }; + if (shepherd.checkToken(req.body.payload.token)) { + if (!req.body.payload) { + const errorObj = { + msg: 'error', + result: 'no payload provided', + }; + + res.end(JSON.stringify(errorObj)); + } else if (!req.body.payload.cmd.match(/^[0-9a-zA-Z _\,\.\[\]"'/\\]+$/g)) { + const errorObj = { + msg: 'error', + result: 'wrong cli string format', + }; + + res.end(JSON.stringify(errorObj)); + } else { + const _mode = req.body.payload.mode === 'passthru' ? 'passthru' : 'default'; + const _chain = req.body.payload.chain === 'KMD' ? null : req.body.payload.chain; + let _params = req.body.payload.params ? ` ${req.body.payload.params}` : ''; + let _cmd = req.body.payload.cmd; - res.end(JSON.stringify(errorObj)); - } else if (!req.body.payload.cmd.match(/^[0-9a-zA-Z _\,\.\[\]"'/\\]+$/g)) { - const errorObj = { - msg: 'error', - result: 'wrong cli string format', - }; + if (!shepherd.rpcConf[_chain]) { + shepherd.getConf(req.body.payload.chain === 'KMD' || !req.body.payload.chain && shepherd.kmdMainPassiveMode ? 'komodod' : req.body.payload.chain); + } - res.end(JSON.stringify(errorObj)); - } else { - const _mode = req.body.payload.mode === 'passthru' ? 'passthru' : 'default'; - const _chain = req.body.payload.chain === 'KMD' ? null : req.body.payload.chain; - let _params = req.body.payload.params ? ` ${req.body.payload.params}` : ''; - let _cmd = req.body.payload.cmd; + if (_mode === 'default') { + if (req.body.payload.rpc2cli) { + let _coindCliBin = shepherd.komodocliBin; - if (!shepherd.rpcConf[_chain]) { - shepherd.getConf(req.body.payload.chain === 'KMD' || !req.body.payload.chain && shepherd.kmdMainPassiveMode ? 'komodod' : req.body.payload.chain); - } + if (shepherd.nativeCoindList && + _chain && + shepherd.nativeCoindList[_chain.toLowerCase()]) { + _coindCliBin = `${shepherd.coindRootDir}/${_chain.toLowerCase()}/${shepherd.nativeCoindList[_chain.toLowerCase()].bin.toLowerCase()}-cli`; + } - if (_mode === 'default') { - if (req.body.payload.rpc2cli) { - let _coindCliBin = shepherd.komodocliBin; + if (_params.indexOf('*')) { + _params = _params.replace('*', '"*"'); + } + if (_params.indexOf(',') > -1) { + _params = _params.split(','); + } + if (_cmd.indexOf('getaddressesbyaccount') > -1) { + _cmd = 'getaddressesbyaccount ""'; + } - if (shepherd.nativeCoindList && - _chain && - shepherd.nativeCoindList[_chain.toLowerCase()]) { - _coindCliBin = `${shepherd.coindRootDir}/${_chain.toLowerCase()}/${shepherd.nativeCoindList[_chain.toLowerCase()].bin.toLowerCase()}-cli`; - } + let _arg = (_chain ? ' -ac_name=' + _chain : '') + ' ' + _cmd + (typeof _params === 'object' ? _params.join(' ') : _params); - if (_params.indexOf('*')) { - _params = _params.replace('*', '"*"'); - } - if (_params.indexOf(',') > -1) { - _params = _params.split(','); - } - if (_cmd.indexOf('getaddressesbyaccount') > -1) { - _cmd = 'getaddressesbyaccount ""'; - } + if (shepherd.appConfig.dataDir.length) { + _arg = `${_arg} -datadir=${shepherd.appConfig.dataDir + (_chain ? '/' + key : '')}`; + } - let _arg = (_chain ? ' -ac_name=' + _chain : '') + ' ' + _cmd + (typeof _params === 'object' ? _params.join(' ') : _params); + shepherd.exec(`"${_coindCliBin}" ${_arg}`, (error, stdout, stderr) => { + //shepherd.log(`stdout: ${stdout}`); + //shepherd.log(`stderr: ${stderr}`); - if (shepherd.appConfig.dataDir.length) { - _arg = `${_arg} -datadir=${shepherd.appConfig.dataDir + (_chain ? '/' + key : '')}`; - } + if (error !== null) { + shepherd.log(`exec error: ${error}`); + } - shepherd.exec(`"${_coindCliBin}" ${_arg}`, (error, stdout, stderr) => { - //shepherd.log(`stdout: ${stdout}`); - //shepherd.log(`stderr: ${stderr}`); + let responseObj; - if (error !== null) { - shepherd.log(`exec error: ${error}`); - } + if (stderr) { + let _res; + let _error; - let responseObj; + if (_chain !== 'komodod' && + stderr.indexOf(`error creating`) > -1) { + shepherd.log(`replace error creating (gen${_chain})`); + stderr = stderr.replace(`error creating (gen${_chain})`, ''); + shepherd.log(stderr); + } - if (stderr) { - let _res; - let _error; - - if (_chain !== 'komodod' && - stderr.indexOf(`error creating`) > -1) { - shepherd.log(`replace error creating (gen${_chain})`); - stderr = stderr.replace(`error creating (gen${_chain})`, ''); - shepherd.log(stderr); - } + if ((stderr.indexOf('{') > -1 && stderr.indexOf('}') > -1) || + (stderr.indexOf('[') > -1 && stderr.indexOf(']') > -1)) { + _res = JSON.parse(stderr); + } else { + _res = stderr.trim(); + } + + if (stderr.indexOf('error code:') > -1) { + _error = { + code: Number(stderr.substring(stderr.indexOf('error code:') + 11, stderr.indexOf('error message:') - stderr.indexOf('error code:')).trim()), + message: stderr.substring(stderr.indexOf('error message:') + 15, stderr.length).trim(), + }; + } - if ((stderr.indexOf('{') > -1 && stderr.indexOf('}') > -1) || - (stderr.indexOf('[') > -1 && stderr.indexOf(']') > -1)) { - _res = JSON.parse(stderr); + if (_error) { + responseObj = { + error: _error, + }; + } else { + responseObj = { + result: _res, + }; + } } else { - _res = stderr.trim(); - } + let _res; + let _error; + + if (_chain !== 'komodod' && + stdout.indexOf(`error creating`) > -1) { + shepherd.log(`replace error creating (gen${_chain})`); + stdout = stdout.replace(`error creating (gen${_chain})`, ''); + shepherd.log(stdout); + } - if (stderr.indexOf('error code:') > -1) { - _error = { - code: Number(stderr.substring(stderr.indexOf('error code:') + 11, stderr.indexOf('error message:') - stderr.indexOf('error code:')).trim()), - message: stderr.substring(stderr.indexOf('error message:') + 15, stderr.length).trim(), - }; + if ((stdout.indexOf('{') > -1 && stdout.indexOf('}') > -1) || + (stdout.indexOf('[') > -1 && stdout.indexOf(']') > -1)) { + _res = JSON.parse(stdout); + } else { + _res = stdout.trim(); + } + + if (stdout.indexOf('error code:') > -1) { + _error = { + code: Number(stdout.substring(stdout.indexOf('error code:') + 11, stdout.indexOf('error message:') - stdout.indexOf('error code:')).trim()), + message: stdout.substring(stdout.indexOf('error message:') + 15, stdout.length).trim(), + }; + } + + if (_error) { + responseObj = { + error: _error, + }; + } else { + responseObj = { + result: _res, + }; + } } - if (_error) { - responseObj = { - error: _error, - }; + res.end(JSON.stringify(responseObj)); + // shepherd.killRogueProcess('komodo-cli'); + }); + } else { + if (_cmd === 'debug' && + _chain !== 'CHIPS') { + if (shepherd.nativeCoindList[_chain.toLowerCase()]) { + const _osHome = os.platform === 'win32' ? process.env.APPDATA : process.env.HOME; + let coindDebugLogLocation; + + if (_chain === 'CHIPS') { + coindDebugLogLocation = `${shepherd.chipsDir}/debug.log`; + } else { + coindDebugLogLocation = `${_osHome}/.${shepherd.nativeCoindList[_chain.toLowerCase()].bin.toLowerCase()}/debug.log`; + } + + shepherd.readDebugLog(coindDebugLogLocation, 1) + .then((result) => { + const _obj = { + msg: 'success', + result: result, + }; + + // shepherd.log('bitcoinrpc debug ====>'); + // console.log(result); + + res.end(JSON.stringify(_obj)); + }, (result) => { + const _obj = { + error: result, + result: 'error', + }; + + res.end(JSON.stringify(_obj)); + }); } else { - responseObj = { - result: _res, - }; + res.end({ + error: 'bitcoinrpc debug error', + result: 'error', + }); + // console.log('bitcoinrpc debug error'); } } else { - let _res; - let _error; - - if (_chain !== 'komodod' && - stdout.indexOf(`error creating`) > -1) { - shepherd.log(`replace error creating (gen${_chain})`); - stdout = stdout.replace(`error creating (gen${_chain})`, ''); - shepherd.log(stdout); + if (_chain === 'CHIPS' && + _cmd === 'debug') { + _cmd = 'getblockchaininfo'; } - if ((stdout.indexOf('{') > -1 && stdout.indexOf('}') > -1) || - (stdout.indexOf('[') > -1 && stdout.indexOf(']') > -1)) { - _res = JSON.parse(stdout); - } else { - _res = stdout.trim(); - } + let _body = { + agent: 'bitcoinrpc', + method: _cmd, + }; - if (stdout.indexOf('error code:') > -1) { - _error = { - code: Number(stdout.substring(stdout.indexOf('error code:') + 11, stdout.indexOf('error message:') - stdout.indexOf('error code:')).trim()), - message: stdout.substring(stdout.indexOf('error message:') + 15, stdout.length).trim(), + if (req.body.payload.params) { + _body = { + agent: 'bitcoinrpc', + method: _cmd, + params: req.body.payload.params === ' ' ? [''] : req.body.payload.params, }; } - if (_error) { - responseObj = { - error: _error, - }; - } else { - responseObj = { - result: _res, + if (req.body.payload.chain) { + const options = { + url: `http://localhost:${shepherd.rpcConf[req.body.payload.chain].port}`, + method: 'POST', + auth: { + user: shepherd.rpcConf[req.body.payload.chain].user, + pass: shepherd.rpcConf[req.body.payload.chain].pass, + }, + body: JSON.stringify(_body), }; + + // send back body on both success and error + // this bit replicates iguana core's behaviour + shepherd.request(options, (error, response, body) => { + if (response && + response.statusCode && + response.statusCode === 200) { + res.end(body); + } else { + res.end(body ? body : JSON.stringify({ + result: 'error', + error: { + code: -777, + message: `unable to call method ${_cmd} at port ${shepherd.rpcConf[req.body.payload.chain].port}`, + }, + })); + } + }); } } - - res.end(JSON.stringify(responseObj)); - // shepherd.killRogueProcess('komodo-cli'); - }); + } } else { - if (_cmd === 'debug' && - _chain !== 'CHIPS') { - if (shepherd.nativeCoindList[_chain.toLowerCase()]) { - const _osHome = os.platform === 'win32' ? process.env.APPDATA : process.env.HOME; - let coindDebugLogLocation; - - if (_chain === 'CHIPS') { - coindDebugLogLocation = `${shepherd.chipsDir}/debug.log`; - } else { - coindDebugLogLocation = `${_osHome}/.${shepherd.nativeCoindList[_chain.toLowerCase()].bin.toLowerCase()}/debug.log`; - } + let _coindCliBin = shepherd.komodocliBin; - shepherd.readDebugLog(coindDebugLogLocation, 1) - .then((result) => { - const _obj = { - msg: 'success', - result: result, - }; + if (shepherd.nativeCoindList && + _chain && + shepherd.nativeCoindList[_chain.toLowerCase()]) { + _coindCliBin = `${shepherd.coindRootDir}/${_chain.toLowerCase()}/${shepherd.nativeCoindList[_chain.toLowerCase()].bin.toLowerCase()}-cli`; + } - // shepherd.log('bitcoinrpc debug ====>'); - // console.log(result); + let _arg = (_chain ? ' -ac_name=' + _chain : '') + ' ' + _cmd + _params; - res.end(JSON.stringify(_obj)); - }, (result) => { - const _obj = { - error: result, - result: 'error', - }; + if (shepherd.appConfig.dataDir.length) { + _arg = `${_arg} -datadir=${shepherd.appConfig.dataDir + (_chain ? '/' + key : '')}`; + } - res.end(JSON.stringify(_obj)); - }); - } else { - res.end({ - error: 'bitcoinrpc debug error', - result: 'error', - }); - // console.log('bitcoinrpc debug error'); - } - } else { - if (_chain === 'CHIPS' && - _cmd === 'debug') { - _cmd = 'getblockchaininfo'; + _arg = _arg.trim().split(' '); + shepherd.execFile(_coindCliBin, _arg, (error, stdout, stderr) => { + shepherd.log(`stdout: ${stdout}`); + shepherd.log(`stderr: ${stderr}`); + + if (error !== null) { + shepherd.log(`exec error: ${error}`); } - let _body = { - agent: 'bitcoinrpc', - method: _cmd, - }; + let responseObj; - if (req.body.payload.params) { - _body = { - agent: 'bitcoinrpc', - method: _cmd, - params: req.body.payload.params === ' ' ? [''] : req.body.payload.params, + if (stderr) { + responseObj = { + msg: 'error', + result: stderr, }; - } - - if (req.body.payload.chain) { - const options = { - url: `http://localhost:${shepherd.rpcConf[req.body.payload.chain].port}`, - method: 'POST', - auth: { - user: shepherd.rpcConf[req.body.payload.chain].user, - pass: shepherd.rpcConf[req.body.payload.chain].pass, - }, - body: JSON.stringify(_body), + } else { + responseObj = { + msg: 'success', + result: stdout, }; - - // send back body on both success and error - // this bit replicates iguana core's behaviour - shepherd.request(options, (error, response, body) => { - if (response && - response.statusCode && - response.statusCode === 200) { - res.end(body); - } else { - res.end(body ? body : JSON.stringify({ - result: 'error', - error: { - code: -777, - message: `unable to call method ${_cmd} at port ${shepherd.rpcConf[req.body.payload.chain].port}`, - }, - })); - } - }); } - } - } - } else { - let _coindCliBin = shepherd.komodocliBin; - - if (shepherd.nativeCoindList && - _chain && - shepherd.nativeCoindList[_chain.toLowerCase()]) { - _coindCliBin = `${shepherd.coindRootDir}/${_chain.toLowerCase()}/${shepherd.nativeCoindList[_chain.toLowerCase()].bin.toLowerCase()}-cli`; - } - - let _arg = (_chain ? ' -ac_name=' + _chain : '') + ' ' + _cmd + _params; - if (shepherd.appConfig.dataDir.length) { - _arg = `${_arg} -datadir=${shepherd.appConfig.dataDir + (_chain ? '/' + key : '')}`; + res.end(JSON.stringify(responseObj)); + shepherd.killRogueProcess('komodo-cli'); + }); } - - _arg = _arg.trim().split(' '); - shepherd.execFile(_coindCliBin, _arg, (error, stdout, stderr) => { - shepherd.log(`stdout: ${stdout}`); - shepherd.log(`stderr: ${stderr}`); - - if (error !== null) { - shepherd.log(`exec error: ${error}`); - } - - let responseObj; - - if (stderr) { - responseObj = { - msg: 'error', - result: stderr, - }; - } else { - responseObj = { - msg: 'success', - result: stdout, - }; - } - - res.end(JSON.stringify(responseObj)); - shepherd.killRogueProcess('komodo-cli'); - }); } + } else { + const errorObj = { + msg: 'error', + result: 'unauthorized access', + }; + + res.end(JSON.stringify(errorObj)); } }); From 1fc059de1c18cd8026268869826dd6f82f39d68f Mon Sep 17 00:00:00 2001 From: pbca26 Date: Tue, 9 Jan 2018 12:49:58 +0300 Subject: [PATCH 22/67] spv xmy, zcl --- routes/electrumjs/electrumServers.js | 24 +++++++++++++++++++++++- routes/electrumjs/electrumjs.networks.js | 24 ++++++++++++++++++++++++ routes/shepherd/electrum/network.js | 4 +++- 3 files changed, 50 insertions(+), 2 deletions(-) diff --git a/routes/electrumjs/electrumServers.js b/routes/electrumjs/electrumServers.js index 6cb351f..2049774 100644 --- a/routes/electrumjs/electrumServers.js +++ b/routes/electrumjs/electrumServers.js @@ -289,7 +289,7 @@ let electrumServers = { '94.130.224.11:10052' ], }, - blk: { // can't decode tx! + blk: { // pos address: 'electrum1.cipig.net', port: 10054, proto: 'tcp', @@ -366,6 +366,28 @@ let electrumServers = { '136.243.45.140:50013' ], }, + xmy: { + address: 'cetus.cryptap.us', + port: 50004, + proto: 'ssl', + txfee: 5000, + abbr: 'XMY', + serverList: [ + 'cetus.cryptap.us:50004', + 'kraken.cryptap.us:50004' + ], + }, + zcl: { + address: 'electrum1.cipig.net', + port: 50055, + proto: 'tcp', + txfee: 1000, + abbr: 'ZCL', + serverList: [ + 'electrum1.cipig.net:10055', + 'electrum2.cipig.net:10055' + ], + }, }; electrumServers.crw = electrumServers.crown; diff --git a/routes/electrumjs/electrumjs.networks.js b/routes/electrumjs/electrumjs.networks.js index 6a8157b..13611ee 100644 --- a/routes/electrumjs/electrumjs.networks.js +++ b/routes/electrumjs/electrumjs.networks.js @@ -265,6 +265,30 @@ networks.hush = { dustThreshold: 1000, }; +networks.zcl = { + messagePrefix: '\Zclassic Signed Message:\n', + bip32: { + public: 0x0488b21e, + private: 0x0488ade4, + }, + pubKeyHash: 0x1cb8, + scriptHash: 0x1cbd, + wif: 0x80, + dustThreshold: 1000, +}; + +networks.xmy = { + messagePrefix: '\Myriad Signed Message:\n', + bip32: { + public: 0x0488b21e, + private: 0x0488ade4, + }, + pubKeyHash: 0x32, + scriptHash: 0x9, + wif: 0xB2, + dustThreshold: 1000, +}; + networks.btc = networks.bitcoin; networks.crw = networks.crown; networks.dgb = networks.digibyte; diff --git a/routes/shepherd/electrum/network.js b/routes/shepherd/electrum/network.js index 529642e..7d33a3d 100644 --- a/routes/shepherd/electrum/network.js +++ b/routes/shepherd/electrum/network.js @@ -11,7 +11,9 @@ module.exports = (shepherd) => { network === 'zcash' || network === 'ZCASH' || network === 'HUSH' || - network === 'hush') { + network === 'hush' || + network === 'ZCL' || + network === 'zcl') { return true; } }; From 8e2b26d3f20d6b10480da421c3587e4452fbaae0 Mon Sep 17 00:00:00 2001 From: pbca26 Date: Wed, 10 Jan 2018 13:32:54 +0300 Subject: [PATCH 23/67] spv merkle verify proto fix --- routes/shepherd/electrum/merkle.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/routes/shepherd/electrum/merkle.js b/routes/shepherd/electrum/merkle.js index e7b6df7..07bfd29 100644 --- a/routes/shepherd/electrum/merkle.js +++ b/routes/shepherd/electrum/merkle.js @@ -44,7 +44,7 @@ module.exports = (shepherd) => { const _randomServer = randomServer.split(':'); const _mainServer = mainServer.split(':'); - let ecl = new shepherd.electrumJSCore(_mainServer[1], _mainServer[0], 'tcp'); // tcp or tls + let ecl = new shepherd.electrumJSCore(_mainServer[1], _mainServer[0], _mainServer[2]); // tcp or tls return new shepherd.Promise((resolve, reject) => { shepherd.log(`main server: ${mainServer}`, true); @@ -63,7 +63,7 @@ module.exports = (shepherd) => { const _res = shepherd.getMerkleRoot(txid, merkleData.merkle, merkleData.pos); shepherd.log(_res, true); - ecl = new shepherd.electrumJSCore(_randomServer[1], _randomServer[0], 'tcp'); + ecl = new shepherd.electrumJSCore(_randomServer[1], _randomServer[0], _mainServer[2]); ecl.connect(); ecl.blockchainBlockGetHeader(height) @@ -117,7 +117,7 @@ module.exports = (shepherd) => { txid, height, _filteredServerList, - shepherd.electrumCoins[coin].server.ip + ':' + shepherd.electrumCoins[coin].server.port + shepherd.electrumCoins[coin].server.ip + ':' + shepherd.electrumCoins[coin].server.port + ':' + shepherd.electrumServers[coin === 'KMD' || coin === 'komodo' ? 'komodo' : coin.toLowerCase()].proto ).then((proof) => { resolve(proof); }); From 8f2ffbd610c812edc2302ba070ae9e505cf8c316 Mon Sep 17 00:00:00 2001 From: pbca26 Date: Thu, 11 Jan 2018 00:27:36 +0300 Subject: [PATCH 24/67] btch, mgw spv --- routes/electrumjs/electrumServers.js | 22 ++++++++++++++++++++++ routes/shepherd/electrum/network.js | 4 +++- version | 4 ++-- version_build | 2 +- 4 files changed, 28 insertions(+), 4 deletions(-) diff --git a/routes/electrumjs/electrumServers.js b/routes/electrumjs/electrumServers.js index 2049774..d115c1b 100644 --- a/routes/electrumjs/electrumServers.js +++ b/routes/electrumjs/electrumServers.js @@ -136,6 +136,28 @@ let electrumServers = { 'electrum2.cipig.net:10014' ], }, + mgw: { // !estimatefee + address: 'electrum1.cipig.net', + port: 10015, + proto: 'tcp', + txfee: 10000, + abbr: 'MGW', + serverList: [ + 'electrum1.cipig.net:10015', + 'electrum2.cipig.net:10015' + ], + }, + btch: { // !estimatefee + address: 'electrum1.cipig.net', + port: 10020, + proto: 'tcp', + txfee: 10000, + abbr: 'BTCH', + serverList: [ + 'electrum1.cipig.net:10020', + 'electrum2.cipig.net:10020' + ], + }, jumblr: { // !estimatefee address: 'electrum1.cipig.net', port: 10004, diff --git a/routes/shepherd/electrum/network.js b/routes/shepherd/electrum/network.js index 7d33a3d..234da70 100644 --- a/routes/shepherd/electrum/network.js +++ b/routes/shepherd/electrum/network.js @@ -59,6 +59,7 @@ module.exports = (shepherd) => { coin === 'MESH' || coin === 'WLC' || coin === 'MNZ' || + coin === 'BTCH' || coinUC === 'SUPERNET' || coinUC === 'REVS' || coinUC === 'SUPERNET' || @@ -78,7 +79,8 @@ module.exports = (shepherd) => { coinUC === 'CEAL' || coinUC === 'MESH' || coinUC === 'WLC' || - coinUC === 'MNZ') { + coinUC === 'MNZ' || + coinUC === 'BTCH') { return shepherd.electrumJSNetworks.komodo; } else { return shepherd.electrumJSNetworks[network]; diff --git a/version b/version index 9bbeb03..443c3fd 100644 --- a/version +++ b/version @@ -1,3 +1,3 @@ -version=0.2.0.26b -type=b-beta +version=0.2.0.26c +type=c-beta minversion=0.2.0.26 \ No newline at end of file diff --git a/version_build b/version_build index 7b9ed5d..d26d77d 100644 --- a/version_build +++ b/version_build @@ -1 +1 @@ -0.2.0.26b-beta \ No newline at end of file +0.2.0.26c-beta \ No newline at end of file From 335cad57c583a9ab12a5b3085118a3616cdca43f Mon Sep 17 00:00:00 2001 From: pbca26 Date: Thu, 11 Jan 2018 21:57:35 +0300 Subject: [PATCH 25/67] spv keys export fix --- routes/shepherd/electrum/keys.js | 56 +++++++++++++++++--------------- 1 file changed, 29 insertions(+), 27 deletions(-) diff --git a/routes/shepherd/electrum/keys.js b/routes/shepherd/electrum/keys.js index 52188fd..435a6ac 100644 --- a/routes/shepherd/electrum/keys.js +++ b/routes/shepherd/electrum/keys.js @@ -105,37 +105,39 @@ module.exports = (shepherd) => { let _seed = req.body.seed; let _wifError = false; - for (let key in shepherd.electrumServers) { - const _abbr = shepherd.electrumServers[key].abbr; - let isWif = false; - let priv; - let pub; - - try { - bs58check.decode(_seed); - isWif = true; - } catch (e) {} - - if (isWif) { + for (let key in shepherd.electrumCoins) { + if (key !== 'auth') { + const _abbr = key; + let isWif = false; + let priv; + let pub; + try { - let key = shepherd.isZcash(_abbr.toLowerCase()) ? bitcoinZcash.ECPair.fromWIF(_seed, shepherd.getNetworkData(_abbr.toLowerCase()), true) : bitcoin.ECPair.fromWIF(_seed, shepherd.getNetworkData(_abbr.toLowerCase()), true); - priv = key.toWIF(); - pub = key.getAddress(); - } catch (e) { - _wifError = true; - break; + bs58check.decode(_seed); + isWif = true; + } catch (e) {} + + if (isWif) { + try { + let key = shepherd.isZcash(_abbr.toLowerCase()) ? bitcoinZcash.ECPair.fromWIF(_seed, shepherd.getNetworkData(_abbr.toLowerCase()), true) : bitcoin.ECPair.fromWIF(_seed, shepherd.getNetworkData(_abbr.toLowerCase()), true); + priv = key.toWIF(); + pub = key.getAddress(); + } catch (e) { + _wifError = true; + break; + } + } else { + let _keys = shepherd.seedToWif(_seed, shepherd.findNetworkObj(_abbr), req.body.iguana); + priv = _keys.priv; + pub = _keys.pub; } - } else { - let _keys = shepherd.seedToWif(_seed, shepherd.findNetworkObj(_abbr), req.body.iguana); - priv = _keys.priv; - pub = _keys.pub; - } - if (shepherd.electrumKeys[_abbr].pub === pub && - shepherd.electrumKeys[_abbr].priv === priv) { - _matchingKeyPairs++; + if (shepherd.electrumKeys[_abbr].pub === pub && + shepherd.electrumKeys[_abbr].priv === priv) { + _matchingKeyPairs++; + } + _totalKeys++; } - _totalKeys++; } if (req.body.active) { From 8544908cfcdaa5fcd91f618bbaeec15899106920 Mon Sep 17 00:00:00 2001 From: pbca26 Date: Sun, 14 Jan 2018 13:39:37 +0300 Subject: [PATCH 26/67] remove loading and settings wnd --- main.js | 450 +++++++++++++++++++------------------------------- version | 4 +- version_build | 2 +- 3 files changed, 169 insertions(+), 287 deletions(-) diff --git a/main.js b/main.js index 3c03822..b674386 100644 --- a/main.js +++ b/main.js @@ -150,9 +150,7 @@ const io = require('socket.io').listen(server); const _zcashParamsExist = shepherd.zcashParamsExist(); let willQuitApp = false; let mainWindow; -let loadingWindow; let appCloseWindow; -let appSettingsWindow; let closeAppAfterLoading = false; let forceQuitApp = false; @@ -166,123 +164,13 @@ if (os.platform() === 'win32') { agamaIcon = path.join(__dirname, '/assets/icons/agama_app_icon.ico'); } -function createLoadingWindow() { - mainWindow = null; - - // initialise window - try { - loadingWindow = new BrowserWindow({ - width: 500, - height: 355, - frame: false, - icon: agamaIcon, - show: false, - }); - } catch(e) {} - - loadingWindow.setResizable(false); - - // check if agama is already running - portscanner.checkPortStatus(appConfig.agamaPort, '127.0.0.1', (error, status) => { - // Status is 'open' if currently in use or 'closed' if available - if (status === 'closed') { - server.listen(appConfig.agamaPort, () => { - shepherd.log(`guiapp and sockets.io are listening on port ${appConfig.agamaPort}`); - shepherd.writeLog(`guiapp and sockets.io are listening on port ${appConfig.agamaPort}`); - // start sockets.io - io.set('origins', appConfig.dev ? 'http://127.0.0.1:3000' : `http://127.0.0.1:${appConfig.agamaPort}`); // set origin - - /*io.on('connection', function(client) { - shepherd.log('EDEX GUI is connected...'); - shepherd.writeLog('EDEX GUI is connected...'); - - client.on('event', function(data) { // listen for client requests - shepherd.log(data); - }); - client.on('disconnect', function(data) { - shepherd.log('EDEX GUI is disconnected'); - }); - client.on('join', function(data) { - shepherd.log(data); - client.emit('messages', 'Sockets server is listening'); - }); - });*/ - }); - } else { - willQuitApp = true; - server.listen(appConfig.agamaPort + 1, () => { - shepherd.log(`guiapp and sockets.io are listening on port ${appConfig.agamaPort + 1}`); - shepherd.writeLog(`guiapp and sockets.io are listening on port ${appConfig.agamaPort + 1}`); - }); - loadingWindow.loadURL(`http://${appConfig.host}:${appConfig.agamaPort + 1}/gui/startup/agama-instance-error.html`); - shepherd.log('another agama app is already running'); - } - }); - - shepherd.setIO(io); // pass sockets object to shepherd router - shepherd.setVar('appBasicInfo', appBasicInfo); - shepherd.setVar('appSessionHash', appSessionHash); - - loadingWindow.createWindow = createWindow; // expose createWindow to front-end scripts - loadingWindow.appConfig = appConfig; - loadingWindow.forseCloseApp = forseCloseApp; - loadingWindow.createAppSettingsWindow = createAppSettingsWindow; - loadingWindow.startKMDNative = shepherd.startKMDNative; - loadingWindow.startSPV = shepherd.startSPV; - loadingWindow.arch = arch(); - - // load our index.html (i.e. easyDEX GUI) - loadingWindow.loadURL(`http://${appConfig.host}:${appConfig.agamaPort}/gui/startup`); - loadingWindow.webContents.on('did-finish-load', () => { - setTimeout(() => { - loadingWindow.show(); - }, 40); - }); - shepherd.writeLog('show loading window'); - - loadingWindow.on('hide', () => { - // our app does not have multiwindow - so we dereference the window object instead of - // putting them into an window_arr - loadingWindow = null; - }); - - loadingWindow.on('close', (e) => { - if (!forseCloseApp) { - if (willQuitApp) { - /* the user tried to quit the app */ - loadingWindow = null; - } else { - /* the user only tried to close the window */ - closeAppAfterLoading = true; - e.preventDefault(); - } - } - }); -} - // close app function forseCloseApp() { forceQuitApp = true; app.quit(); } -function setDefaultAppSettings() { - shepherd.saveLocalAppConf(_defaultAppSettings); -} - -function updateAppSettings(_settings) { - shepherd.saveLocalAppConf(_settings); - appConfig = _settings; -} - -if (process.argv.indexOf('dexonly') > -1) { - app.on('ready', createLoadingWindow); - setTimeout(() => { - createWindow('open', true); - }, 500); -} else { - app.on('ready', createLoadingWindow); -} +app.on('ready', () => createWindow('open', process.argv.indexOf('dexonly') > -1 ? true : null)); function createAppCloseWindow() { // initialise window @@ -305,62 +193,10 @@ function createAppCloseWindow() { }); } -function reloadSettingsWindow() { - appSettingsWindow.loadURL(`http://${appConfig.host}:${appConfig.agamaPort}/gui/startup/app-settings.html`); -} - -function createAppSettingsWindow() { - // initialise window - appSettingsWindow = new BrowserWindow({ // dirty hack to prevent main window flash on quit - width: 750, - height: 610, - frame: false, - icon: agamaIcon, - show: false, - }); - - appSettingsWindow.setResizable(false); - - appSettingsWindow.appConfig = appConfig; - appSettingsWindow.appConfigSchema = shepherd.appConfigSchema; - appSettingsWindow.defaultAppSettings = _defaultAppSettings; - appSettingsWindow.destroyAppSettingsWindow = destroyAppSettingsWindow; - appSettingsWindow.reloadSettingsWindow = reloadSettingsWindow; - appSettingsWindow.testLocation = shepherd.testLocation; - appSettingsWindow.setDefaultAppSettings = setDefaultAppSettings; - appSettingsWindow.updateAppSettings = updateAppSettings; - appSettingsWindow.testBins = shepherd.testBins; - appSettingsWindow.zcashParamsExist = _zcashParamsExist; - appSettingsWindow.loadURL(`http://${appConfig.host}:${appConfig.agamaPort}/gui/startup/app-settings.html`); - - appSettingsWindow.webContents.on('did-finish-load', () => { - setTimeout(() => { - appSettingsWindow.show(); - }, 40); - }); -} - -function destroyAppSettingsWindow() { - appSettingsWindow.hide(); - appSettingsWindow = null; -} - function createWindow(status, hideLoadingWindow) { - if (appSettingsWindow) { - destroyAppSettingsWindow(); - } - if (status === 'open') { require(path.join(__dirname, 'private/mainmenu')); - // initialise window - mainWindow = new BrowserWindow({ // dirty hack to prevent main window flash on quit - width: closeAppAfterLoading ? 1 : 1280, - height: closeAppAfterLoading ? 1 : 800, - icon: agamaIcon, - show: false, - }); - if (closeAppAfterLoading) { mainWindow = null; loadingWindow = null; @@ -383,135 +219,185 @@ function createWindow(status, hideLoadingWindow) { { role: 'selectall' }, ]); - // load our index.html (i.e. easyDEX GUI) - shepherd.writeLog('show edex gui'); - mainWindow.appConfig = appConfig; - mainWindow.appConfigSchema = shepherd.appConfigSchema; - mainWindow.arch = arch(); - mainWindow.appBasicInfo = appBasicInfo; - mainWindow.appSessionHash = appSessionHash; - mainWindow.assetChainPorts = require('./routes/ports.js'); - mainWindow.agamaIcon = agamaIcon; - mainWindow.testLocation = shepherd.testLocation; - mainWindow.kmdMainPassiveMode = shepherd.kmdMainPassiveMode; - mainWindow.getAppRuntimeLog = shepherd.getAppRuntimeLog; - mainWindow.nativeCoindList = nativeCoindList; - mainWindow.zcashParamsExist = _zcashParamsExist; - mainWindow.zcashParamsExistPromise = shepherd.zcashParamsExistPromise; - mainWindow.zcashParamsDownloadLinks = shepherd.zcashParamsDownloadLinks; - mainWindow.isWindows = os.platform() === 'win32' ? true : false; // obsolete(?) - mainWindow.appExit = appExit; - mainWindow.getMaxconKMDConf = shepherd.getMaxconKMDConf; - mainWindow.setMaxconKMDConf = shepherd.setMaxconKMDConf; - mainWindow.getMMCacheData = shepherd.getMMCacheData; - mainWindow.activeSection = 'wallets'; - mainWindow.argv = process.argv; - mainWindow.getAssetChainPorts = shepherd.getAssetChainPorts; - mainWindow.spvFees = _spvFees; - - if (appConfig.dev) { - mainWindow.loadURL('http://127.0.0.1:3000'); - } else { - mainWindow.loadURL(`http://${appConfig.host}:${appConfig.agamaPort}/gui/EasyDEX-GUI/react/build`); - } + // check if agama is already running + portscanner.checkPortStatus(appConfig.agamaPort, '127.0.0.1', (error, status) => { + // Status is 'open' if currently in use or 'closed' if available + if (status === 'closed') { + server.listen(appConfig.agamaPort, () => { + shepherd.log(`guiapp and sockets.io are listening on port ${appConfig.agamaPort}`); + shepherd.writeLog(`guiapp and sockets.io are listening on port ${appConfig.agamaPort}`); + // start sockets.io + io.set('origins', appConfig.dev ? 'http://127.0.0.1:3000' : `http://127.0.0.1:${appConfig.agamaPort}`); // set origin + }); - mainWindow.webContents.on('did-finish-load', () => { - setTimeout(() => { - mainWindow.show(); + // initialise window + mainWindow = new BrowserWindow({ // dirty hack to prevent main window flash on quit + width: closeAppAfterLoading ? 1 : 1280, + height: closeAppAfterLoading ? 1 : 800, + icon: agamaIcon, + show: false, + }); - if (hideLoadingWindow && - loadingWindow) { - loadingWindow.hide(); - } - }, 40); - }); + if (appConfig.dev) { + mainWindow.loadURL('http://127.0.0.1:3000'); + } else { + mainWindow.loadURL(`http://${appConfig.host}:${appConfig.agamaPort}/gui/EasyDEX-GUI/react/build`); + } + + shepherd.setIO(io); // pass sockets object to shepherd router + shepherd.setVar('appBasicInfo', appBasicInfo); + shepherd.setVar('appSessionHash', appSessionHash); + + // load our index.html (i.e. easyDEX GUI) + shepherd.writeLog('show edex gui'); + mainWindow.appConfig = appConfig; + mainWindow.appConfigSchema = shepherd.appConfigSchema; + mainWindow.arch = arch(); + mainWindow.appBasicInfo = appBasicInfo; + mainWindow.appSessionHash = appSessionHash; + mainWindow.assetChainPorts = require('./routes/ports.js'); + mainWindow.agamaIcon = agamaIcon; + mainWindow.testLocation = shepherd.testLocation; + mainWindow.kmdMainPassiveMode = shepherd.kmdMainPassiveMode; + mainWindow.getAppRuntimeLog = shepherd.getAppRuntimeLog; + mainWindow.nativeCoindList = nativeCoindList; + mainWindow.zcashParamsExist = _zcashParamsExist; + mainWindow.zcashParamsExistPromise = shepherd.zcashParamsExistPromise; + mainWindow.zcashParamsDownloadLinks = shepherd.zcashParamsDownloadLinks; + mainWindow.isWindows = os.platform() === 'win32' ? true : false; // obsolete(?) + mainWindow.appExit = appExit; + mainWindow.getMaxconKMDConf = shepherd.getMaxconKMDConf; + mainWindow.setMaxconKMDConf = shepherd.setMaxconKMDConf; + mainWindow.getMMCacheData = shepherd.getMMCacheData; + mainWindow.activeSection = 'wallets'; + mainWindow.argv = process.argv; + mainWindow.getAssetChainPorts = shepherd.getAssetChainPorts; + mainWindow.spvFees = _spvFees; + } else { + mainWindow = new BrowserWindow({ + width: 500, + height: 355, + frame: false, + icon: agamaIcon, + show: false, + }); - mainWindow.webContents.on('context-menu', (e, params) => { // context-menu returns params - const { selectionText, isEditable } = params; // params obj + mainWindow.setResizable(false); + mainWindow.forseCloseApp = forseCloseApp; - if (isEditable) { - editMenu.popup(mainWindow); - } else if (selectionText && selectionText.trim() !== '') { - staticMenu.popup(mainWindow); + willQuitApp = true; + server.listen(appConfig.agamaPort + 1, () => { + shepherd.log(`guiapp and sockets.io are listening on port ${appConfig.agamaPort + 1}`); + shepherd.writeLog(`guiapp and sockets.io are listening on port ${appConfig.agamaPort + 1}`); + }); + mainWindow.loadURL(`http://${appConfig.host}:${appConfig.agamaPort + 1}/gui/startup/agama-instance-error.html`); + shepherd.log('another agama app is already running'); } - }); - // DEVTOOLS - only for dev purposes - ca333 - // mainWindow.webContents.openDevTools() + mainWindow.webContents.on('did-finish-load', () => { + setTimeout(() => { + mainWindow.show(); + }, 40); + }); + + /*loadingWindow.on('close', (e) => { + if (!forseCloseApp) { + if (willQuitApp) { + loadingWindow = null; + } else { + closeAppAfterLoading = true; + e.preventDefault(); + } + } + });*/ + + mainWindow.webContents.on('context-menu', (e, params) => { // context-menu returns params + const { selectionText, isEditable } = params; // params obj + + if (isEditable) { + editMenu.popup(mainWindow); + } else if (selectionText && selectionText.trim() !== '') { + staticMenu.popup(mainWindow); + } + }); - function appExit() { - const CloseDaemons = () => { - return new Promise((resolve, reject) => { - shepherd.log('Closing Main Window...'); - shepherd.writeLog('exiting app...'); + // DEVTOOLS - only for dev purposes - ca333 + // mainWindow.webContents.openDevTools() - shepherd.quitKomodod(appConfig.cliStopTimeout); + function appExit() { + const CloseDaemons = () => { + return new Promise((resolve, reject) => { + shepherd.log('Closing Main Window...'); + shepherd.writeLog('exiting app...'); - const result = 'Closing daemons: done'; + shepherd.quitKomodod(appConfig.cliStopTimeout); - shepherd.log(result); - shepherd.writeLog(result); - resolve(result); - }); - } + const result = 'Closing daemons: done'; - const HideMainWindow = () => { - return new Promise((resolve, reject) => { - const result = 'Hiding Main Window: done'; - - shepherd.log('Exiting App...'); - mainWindow = null; - shepherd.log(result); - resolve(result); - }); - } - - const HideAppClosingWindow = () => { - return new Promise((resolve, reject) => { - appCloseWindow = null; - resolve(true); - }); - } + shepherd.log(result); + shepherd.writeLog(result); + resolve(result); + }); + } - const QuitApp = () => { - return new Promise((resolve, reject) => { - const result = 'Quiting App: done'; + const HideMainWindow = () => { + return new Promise((resolve, reject) => { + const result = 'Hiding Main Window: done'; - app.quit(); - shepherd.log(result); - resolve(result); - }); - } + shepherd.log('Exiting App...'); + mainWindow = null; + shepherd.log(result); + resolve(result); + }); + } - const closeApp = () => { - CloseDaemons() - .then(HideMainWindow) - .then(HideAppClosingWindow) - .then(QuitApp); - } + const HideAppClosingWindow = () => { + return new Promise((resolve, reject) => { + appCloseWindow = null; + resolve(true); + }); + } - let _appClosingInterval; + const QuitApp = () => { + return new Promise((resolve, reject) => { + const result = 'Quiting App: done'; - if (process.argv.indexOf('dexonly') > -1) { - shepherd.killRogueProcess('marketmaker'); - } - if (!Object.keys(shepherd.coindInstanceRegistry).length || - !appConfig.stopNativeDaemonsOnQuit) { - closeApp(); - } else { - createAppCloseWindow(); - shepherd.quitKomodod(appConfig.cliStopTimeout); - _appClosingInterval = setInterval(() => { - if (!Object.keys(shepherd.coindInstanceRegistry).length) { - closeApp(); - } - }, 1000); + app.quit(); + shepherd.log(result); + resolve(result); + }); + } + + const closeApp = () => { + CloseDaemons() + .then(HideMainWindow) + .then(HideAppClosingWindow) + .then(QuitApp); + } + + let _appClosingInterval; + + if (process.argv.indexOf('dexonly') > -1) { + shepherd.killRogueProcess('marketmaker'); + } + if (!Object.keys(shepherd.coindInstanceRegistry).length || + !appConfig.stopNativeDaemonsOnQuit) { + closeApp(); + } else { + createAppCloseWindow(); + shepherd.quitKomodod(appConfig.cliStopTimeout); + _appClosingInterval = setInterval(() => { + if (!Object.keys(shepherd.coindInstanceRegistry).length) { + closeApp(); + } + }, 1000); + } } - } - // close app - mainWindow.on('closed', () => { - appExit(); + // close app + mainWindow.on('closed', () => { + appExit(); + }); }); } } @@ -538,23 +424,19 @@ app.on('before-quit', (event) => { // Emitted when all windows have been closed and the application will quit. // Calling event.preventDefault() will prevent the default behaviour, which is terminating the application. app.on('will-quit', (event) => { - if (!forceQuitApp && - mainWindow === null && - loadingWindow != null) { + if (!forceQuitApp) { // loading window is still open shepherd.log('will-quit while loading window active'); - event.preventDefault(); + //event.preventDefault(); } }); // Emitted when the application is quitting. // Calling event.preventDefault() will prevent the default behaviour, which is terminating the application. app.on('quit', (event) => { - if (!forceQuitApp && - mainWindow === null && - loadingWindow != null) { + if (!forceQuitApp) { shepherd.log('quit while loading window active'); - event.preventDefault(); + //event.preventDefault(); } }) diff --git a/version b/version index 443c3fd..3615aad 100644 --- a/version +++ b/version @@ -1,3 +1,3 @@ -version=0.2.0.26c -type=c-beta +version=0.2.0.26d +type=d-beta minversion=0.2.0.26 \ No newline at end of file diff --git a/version_build b/version_build index d26d77d..3aa3528 100644 --- a/version_build +++ b/version_build @@ -1 +1 @@ -0.2.0.26c-beta \ No newline at end of file +0.2.0.26d-beta \ No newline at end of file From 6ae5cbab10a44beb99eeb7edb42da8940daa52cd Mon Sep 17 00:00:00 2001 From: pbca26 Date: Mon, 15 Jan 2018 13:01:25 +0300 Subject: [PATCH 27/67] kmd fees dynamic -> static --- routes/shepherd/electrum/createtx.js | 28 ++++++++-------------------- routes/shepherd/electrum/network.js | 6 +++++- 2 files changed, 13 insertions(+), 21 deletions(-) diff --git a/routes/shepherd/electrum/createtx.js b/routes/shepherd/electrum/createtx.js index fe3a4a3..62b4e49 100644 --- a/routes/shepherd/electrum/createtx.js +++ b/routes/shepherd/electrum/createtx.js @@ -209,7 +209,6 @@ module.exports = (shepherd) => { shepherd.listunspent(ecl, changeAddress, network, true, true) .then((utxoList) => { ecl.close(); - console.log(utxoList); if (utxoList && utxoList.length && @@ -254,13 +253,8 @@ module.exports = (shepherd) => { shepherd.log('targets =>', true); shepherd.log(targets, true); - const feeRate = shepherd.getNetworkData(network).messagePrefix === '\x19Komodo Signed Message:\n' || shepherd.getNetworkData(network).messagePrefix === '\x19Chips Signed Message:\n' ? 20 : 0; // sats/byte + targets[0].value = targets[0].value + fee; - if (!feeRate) { - targets[0].value = targets[0].value + fee; - } - - shepherd.log(`fee rate ${feeRate}`, true); shepherd.log(`default fee ${fee}`, true); shepherd.log(`targets ==>`, true); shepherd.log(targets, true); @@ -268,14 +262,10 @@ module.exports = (shepherd) => { // default coin selection algo blackjack with fallback to accumulative // make a first run, calc approx tx fee // if ins and outs are empty reduce max spend by txfee - const firstRun = shepherd.coinSelect(utxoListFormatted, targets, feeRate); + const firstRun = shepherd.coinSelect(utxoListFormatted, targets, 0); let inputs = firstRun.inputs; let outputs = firstRun.outputs; - if (feeRate) { - fee = firstRun.fee; - } - shepherd.log('coinselect res =>', true); shepherd.log('coinselect inputs =>', true); shepherd.log(inputs, true); @@ -290,7 +280,7 @@ module.exports = (shepherd) => { shepherd.log('coinselect adjusted targets =>', true); shepherd.log(targets, true); - const secondRun = shepherd.coinSelect(utxoListFormatted, targets, feeRate); + const secondRun = shepherd.coinSelect(utxoListFormatted, targets, 0); inputs = secondRun.inputs; outputs = secondRun.outputs; fee = secondRun.fee; @@ -310,13 +300,10 @@ module.exports = (shepherd) => { _change = outputs[1].value; } - // non komodo coins, subtract fee from output value - if (!feeRate) { - outputs[0].value = outputs[0].value - fee; + outputs[0].value = outputs[0].value - fee; - shepherd.log('non komodo adjusted outputs, value - default fee =>', true); - shepherd.log(outputs, true); - } + shepherd.log('adjusted outputs, value - default fee =>', true); + shepherd.log(outputs, true); // check if any outputs are unverified if (inputs && @@ -355,7 +342,8 @@ module.exports = (shepherd) => { if (network === 'komodo' && totalInterest > 0) { // account for extra vout - const _feeOverhead = outputs.length === 1 ? shepherd.estimateTxSize(0, 1) * feeRate : 0; + // const _feeOverhead = outputs.length === 1 ? shepherd.estimateTxSize(0, 1) * feeRate : 0; + const _feeOverhead = 0; shepherd.log(`max interest to claim ${totalInterest} (${totalInterest * 0.00000001})`, true); shepherd.log(`estimated fee overhead ${_feeOverhead}`, true); diff --git a/routes/shepherd/electrum/network.js b/routes/shepherd/electrum/network.js index 234da70..594c6d5 100644 --- a/routes/shepherd/electrum/network.js +++ b/routes/shepherd/electrum/network.js @@ -60,6 +60,8 @@ module.exports = (shepherd) => { coin === 'WLC' || coin === 'MNZ' || coin === 'BTCH' || + coin === 'KMD' || + coin === 'KOMODO' || coinUC === 'SUPERNET' || coinUC === 'REVS' || coinUC === 'SUPERNET' || @@ -80,7 +82,9 @@ module.exports = (shepherd) => { coinUC === 'MESH' || coinUC === 'WLC' || coinUC === 'MNZ' || - coinUC === 'BTCH') { + coinUC === 'BTCH' || + coinUC === 'KMD' || + coinUC === 'KOMODO') { return shepherd.electrumJSNetworks.komodo; } else { return shepherd.electrumJSNetworks[network]; From f4c8a9eaf6d2638ebedec88914730c669e7efa14 Mon Sep 17 00:00:00 2001 From: pbca26 Date: Mon, 15 Jan 2018 17:45:40 +0300 Subject: [PATCH 28/67] extend shortcuts --- main.js | 6 ++ routes/shepherd/addCoinShortcuts.js | 136 ++++++++++++++++++++++++++++ 2 files changed, 142 insertions(+) diff --git a/main.js b/main.js index b674386..3c3c57d 100644 --- a/main.js +++ b/main.js @@ -194,6 +194,10 @@ function createAppCloseWindow() { } function createWindow(status, hideLoadingWindow) { + if (process.argv.indexOf('spvcoins=all/add-all') > -1) { + shepherd.startSPV('kmd'); + } + if (status === 'open') { require(path.join(__dirname, 'private/mainmenu')); @@ -273,6 +277,8 @@ function createWindow(status, hideLoadingWindow) { mainWindow.argv = process.argv; mainWindow.getAssetChainPorts = shepherd.getAssetChainPorts; mainWindow.spvFees = _spvFees; + mainWindow.startSPV = shepherd.startSPV; + mainWindow.startKMDNative = shepherd.startKMDNative; } else { mainWindow = new BrowserWindow({ width: 500, diff --git a/routes/shepherd/addCoinShortcuts.js b/routes/shepherd/addCoinShortcuts.js index 02ede31..6397de9 100644 --- a/routes/shepherd/addCoinShortcuts.js +++ b/routes/shepherd/addCoinShortcuts.js @@ -44,6 +44,142 @@ module.exports = (shepherd) => { }), }; + shepherd.request(options, (error, response, body) => { + if (response && + response.statusCode && + response.statusCode === 200) { + //resolve(body); + } else { + //resolve(body); + } + }); + } else if (selection === 'REVS') { + const herdData = { + 'ac_name': 'REVS', + 'ac_options': [ + '-daemon=0', + '-server', + `-ac_name=REVS`, + '-addnode=78.47.196.146', + '-ac_supply=1300000' + ] + }; + + const options = { + url: `http://127.0.0.1:${shepherd.appConfig.agamaPort}/shepherd/herd`, + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + herd: 'komodod', + options: herdData, + token: shepherd.appSessionHash, + }), + }; + + shepherd.request(options, (error, response, body) => { + if (response && + response.statusCode && + response.statusCode === 200) { + //resolve(body); + } else { + //resolve(body); + } + }); + } else if (selection === 'JUMRLR') { + const herdData = { + 'ac_name': 'JUMRLR', + 'ac_options': [ + '-daemon=0', + '-server', + `-ac_name=JUMRLR`, + '-addnode=78.47.196.146', + '-ac_supply=999999' + ] + }; + + const options = { + url: `http://127.0.0.1:${shepherd.appConfig.agamaPort}/shepherd/herd`, + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + herd: 'komodod', + options: herdData, + token: shepherd.appSessionHash, + }), + }; + + shepherd.request(options, (error, response, body) => { + if (response && + response.statusCode && + response.statusCode === 200) { + //resolve(body); + } else { + //resolve(body); + } + }); + } else if (selection === 'MNZ') { + const herdData = { + 'ac_name': 'MNZ', + 'ac_options': [ + '-daemon=0', + '-server', + `-ac_name=MNZ`, + '-addnode=78.47.196.146', + '-ac_supply=257142858' + ] + }; + + const options = { + url: `http://127.0.0.1:${shepherd.appConfig.agamaPort}/shepherd/herd`, + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + herd: 'komodod', + options: herdData, + token: shepherd.appSessionHash, + }), + }; + + shepherd.request(options, (error, response, body) => { + if (response && + response.statusCode && + response.statusCode === 200) { + //resolve(body); + } else { + //resolve(body); + } + }); + } else if (selection === 'BTCH') { + const herdData = { + 'ac_name': 'BTCH', + 'ac_options': [ + '-daemon=0', + '-server', + `-ac_name=BTCH`, + '-addnode=78.47.196.146', + '-ac_supply=20998641' + ] + }; + + const options = { + url: `http://127.0.0.1:${shepherd.appConfig.agamaPort}/shepherd/herd`, + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + herd: 'komodod', + options: herdData, + token: shepherd.appSessionHash, + }), + }; + shepherd.request(options, (error, response, body) => { if (response && response.statusCode && From 6d9bbad052d2ac36c812d209452d8a33c2b52a69 Mon Sep 17 00:00:00 2001 From: pbca26 Date: Sat, 20 Jan 2018 16:25:26 +0300 Subject: [PATCH 29/67] create tx spv verification param fix --- routes/shepherd/electrum/createtx.js | 55 +++++++++++++++------------- version | 6 +-- version_build | 2 +- 3 files changed, 33 insertions(+), 30 deletions(-) diff --git a/routes/shepherd/electrum/createtx.js b/routes/shepherd/electrum/createtx.js index 62b4e49..e264a6f 100644 --- a/routes/shepherd/electrum/createtx.js +++ b/routes/shepherd/electrum/createtx.js @@ -206,7 +206,7 @@ module.exports = (shepherd) => { shepherd.log('electrum createrawtx =>', true); ecl.connect(); - shepherd.listunspent(ecl, changeAddress, network, true, true) + shepherd.listunspent(ecl, changeAddress, network, true, req.query.verify === 'true' ? true : null) .then((utxoList) => { ecl.close(); @@ -395,27 +395,29 @@ module.exports = (shepherd) => { value ); } else { - if (network === 'btg' || - network === 'bch') { - _rawtx = shepherd.buildSignedTxForks( - outputAddress, - changeAddress, - wif, - network, - inputs, - _change, - value - ); - } else { - _rawtx = shepherd.buildSignedTx( - outputAddress, - changeAddress, - wif, - network, - inputs, - _change, - value - ); + if (!req.query.offline) { + if (network === 'btg' || + network === 'bch') { + _rawtx = shepherd.buildSignedTxForks( + outputAddress, + changeAddress, + wif, + network, + inputs, + _change, + value + ); + } else { + _rawtx = shepherd.buildSignedTx( + outputAddress, + changeAddress, + wif, + network, + inputs, + _change, + value + ); + } } } @@ -586,10 +588,11 @@ module.exports = (shepherd) => { } }); - shepherd.get('/electrum/pushtx', (req, res, next) => { - if (shepherd.checkToken(req.query.token)) { - const rawtx = req.query.rawtx; - const ecl = new shepherd.electrumJSCore(shepherd.electrumServers[req.query.network].port, shepherd.electrumServers[req.query.network].address, shepherd.electrumServers[req.query.network].proto); // tcp or tls + shepherd.post('/electrum/pushtx', (req, res, next) => { + if (shepherd.checkToken(req.body.token)) { + const rawtx = req.body.rawtx; + const _network = req.body.network; + const ecl = new shepherd.electrumJSCore(shepherd.electrumServers[_network].port, shepherd.electrumServers[_network].address, shepherd.electrumServers[_network].proto); // tcp or tls ecl.connect(); ecl.blockchainTransactionBroadcast(rawtx) diff --git a/version b/version index 3615aad..fc947fe 100644 --- a/version +++ b/version @@ -1,3 +1,3 @@ -version=0.2.0.26d -type=d-beta -minversion=0.2.0.26 \ No newline at end of file +version=0.2.0.27a +type=a-beta +minversion=0.2.0.27 \ No newline at end of file diff --git a/version_build b/version_build index 3aa3528..a8ffa87 100644 --- a/version_build +++ b/version_build @@ -1 +1 @@ -0.2.0.26d-beta \ No newline at end of file +0.2.0.27a-beta \ No newline at end of file From c29dc8e6674b934cecfa6df24a2e26b16fe092c4 Mon Sep 17 00:00:00 2001 From: pbca26 Date: Mon, 22 Jan 2018 13:59:01 +0300 Subject: [PATCH 30/67] license update --- LICENSE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE b/LICENSE index 05ad72a..55e2ff9 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2017 SuperNET +Copyright (c) 2017 - 2018 SuperNET Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal From 6af3918ecb31c04d38a8a0a87a23259ffbd33a64 Mon Sep 17 00:00:00 2001 From: pbca26 Date: Thu, 25 Jan 2018 16:01:24 +0300 Subject: [PATCH 31/67] bump electron version --- package.json | 2 +- routes/shepherd/downloadPatch.js | 2 +- routes/shepherd/electrum/keys.js | 6 +++--- routes/shepherd/electrum/listunspent.js | 3 ++- 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index c9a73a2..dddbab3 100644 --- a/package.json +++ b/package.json @@ -40,7 +40,7 @@ "body-parser": "^1.15.2", "buffer-reverse": "^1.0.1", "coinselect": "github:bitcoinjs/coinselect", - "electron": "1.7.10", + "electron": "1.7.11", "express": "^4.14.0", "fix-path": "^2.1.0", "fs-extra": "^4.0.2", diff --git a/routes/shepherd/downloadPatch.js b/routes/shepherd/downloadPatch.js index 6cf6cd1..58b3667 100644 --- a/routes/shepherd/downloadPatch.js +++ b/routes/shepherd/downloadPatch.js @@ -8,7 +8,7 @@ module.exports = (shepherd) => { if (shepherd.checkToken(req.query.token)) { const successObj = { msg: 'success', - result: 'dl started' + result: 'dl started', }; res.end(JSON.stringify(successObj)); diff --git a/routes/shepherd/electrum/keys.js b/routes/shepherd/electrum/keys.js index 435a6ac..ffbddf1 100644 --- a/routes/shepherd/electrum/keys.js +++ b/routes/shepherd/electrum/keys.js @@ -75,9 +75,9 @@ module.exports = (shepherd) => { } }); - shepherd.get('/electrum/seedtowif', (req, res, next) => { - if (shepherd.checkToken(req.query.token)) { - let keys = shepherd.seedToWif(req.query.seed, req.query.network, req.query.iguana); + shepherd.post('/electrum/seedtowif', (req, res, next) => { + if (shepherd.checkToken(req.body.token)) { + let keys = shepherd.seedToWif(req.body.seed, req.body.network, req.body.iguana); const successObj = { msg: 'success', diff --git a/routes/shepherd/electrum/listunspent.js b/routes/shepherd/electrum/listunspent.js index 7336115..411d495 100644 --- a/routes/shepherd/electrum/listunspent.js +++ b/routes/shepherd/electrum/listunspent.js @@ -167,7 +167,8 @@ module.exports = (shepherd) => { network, true, req.query.verify - ).then((listunspent) => { + ) + .then((listunspent) => { shepherd.log('electrum listunspent ==>', true); const successObj = { From fc3990ba3c42249c1adc11f2f40620fb4851dc6b Mon Sep 17 00:00:00 2001 From: pbca26 Date: Sat, 27 Jan 2018 14:52:05 +0300 Subject: [PATCH 32/67] beer, pizza test coins --- routes/ports.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/routes/ports.js b/routes/ports.js index 0646b6e..a792195 100644 --- a/routes/ports.js +++ b/routes/ports.js @@ -1,6 +1,8 @@ const assetChainPorts = { 'komodod': '7771', 'markermaker': '7783', + 'PIZZA': '11116', + 'BEER': '8923', 'CHIPS': '57776', 'SUPERNET': '11341', 'REVS': '10196', @@ -18,7 +20,7 @@ const assetChainPorts = { 'COQUI': '14276', 'MVP': '11676', 'KV': '8299', - 'CEAL': '11116', + // 'CEAL': '11116', 'MESH': '9455', 'AXO': '12927', 'ETOMIC': '10271', From a1e347902c24accff468de50f6d974948b7ba179 Mon Sep 17 00:00:00 2001 From: pbca26 Date: Sat, 27 Jan 2018 14:58:57 +0300 Subject: [PATCH 33/67] version bump --- version | 4 ++-- version_build | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/version b/version index fc947fe..6914741 100644 --- a/version +++ b/version @@ -1,3 +1,3 @@ -version=0.2.0.27a -type=a-beta +version=0.2.0.27b +type=b-beta minversion=0.2.0.27 \ No newline at end of file diff --git a/version_build b/version_build index a8ffa87..51d5fb9 100644 --- a/version_build +++ b/version_build @@ -1 +1 @@ -0.2.0.27a-beta \ No newline at end of file +0.2.0.27b-beta \ No newline at end of file From 7438f2b4d0b2806cafffca1d1bdf96853cc851de Mon Sep 17 00:00:00 2001 From: pbca26 Date: Sun, 28 Jan 2018 00:02:56 +0300 Subject: [PATCH 34/67] pizza port fix --- routes/ports.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/routes/ports.js b/routes/ports.js index a792195..9601893 100644 --- a/routes/ports.js +++ b/routes/ports.js @@ -1,7 +1,7 @@ const assetChainPorts = { 'komodod': '7771', 'markermaker': '7783', - 'PIZZA': '11116', + 'PIZZA': '11608', 'BEER': '8923', 'CHIPS': '57776', 'SUPERNET': '11341', @@ -20,7 +20,7 @@ const assetChainPorts = { 'COQUI': '14276', 'MVP': '11676', 'KV': '8299', - // 'CEAL': '11116', + 'CEAL': '11116', 'MESH': '9455', 'AXO': '12927', 'ETOMIC': '10271', From b57ae1ead3c7f5da9c6b6f4a62f21ce6f948a8d9 Mon Sep 17 00:00:00 2001 From: pbca26 Date: Sun, 28 Jan 2018 18:10:56 +0300 Subject: [PATCH 35/67] createtx test route --- routes/shepherd/electrum/createtx.js | 92 ++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) diff --git a/routes/shepherd/electrum/createtx.js b/routes/shepherd/electrum/createtx.js index e264a6f..3899068 100644 --- a/routes/shepherd/electrum/createtx.js +++ b/routes/shepherd/electrum/createtx.js @@ -618,5 +618,97 @@ module.exports = (shepherd) => { } }); + shepherd.post('/electrum/createrawtx-test', (req, res, next) => { + if (shepherd.checkToken(req.body.token)) { + const wif = req.body.payload.wif; + const utxo = req.body.payload.utxo; + const targets = req.body.payload.targets; + const network = req.body.payload.network; + const change = req.body.payload.change; + const outputAddress = req.body.payload.outputAddress; + const changeAddress = req.body.payload.changeAddress; + + let key = shepherd.isZcash(network) ? bitcoinZcash.ECPair.fromWIF(wif, shepherd.getNetworkData(network)) : shepherd.bitcoinJS.ECPair.fromWIF(wif, shepherd.getNetworkData(network)); + let tx; + + if (shepherd.isZcash(network)) { + tx = new bitcoinZcash.TransactionBuilder(shepherd.getNetworkData(network)); + } else if (shepherd.isPos(network)) { + tx = new bitcoinPos.TransactionBuilder(shepherd.getNetworkData(network)); + } else { + tx = new shepherd.bitcoinJS.TransactionBuilder(shepherd.getNetworkData(network)); + } + + shepherd.log('buildSignedTx', true); + // console.log(`buildSignedTx priv key ${wif}`); + shepherd.log(`buildSignedTx pub key ${key.getAddress().toString()}`, true); + // console.log('buildSignedTx std tx fee ' + shepherd.electrumServers[network].txfee); + + for (let i = 0; i < utxo.length; i++) { + tx.addInput(utxo[i].txid, utxo[i].vout); + } + + for (let i = 0; i < targets.length; i++) { + if (shepherd.isPos(network)) { + tx.addOutput(outputAddress, Number(targets[i]), shepherd.getNetworkData(network)); + } else { + tx.addOutput(outputAddress, Number(targets[i])); + } + } + + if (Number(change) > 0) { + if (shepherd.isPos(network)) { + tx.addOutput(changeAddress, Number(change), shepherd.getNetworkData(network)); + } else { + console.log(`change ${change}`); + tx.addOutput(changeAddress, Number(change)); + } + } + + if (network === 'komodo' || + network === 'KMD') { + const _locktime = Math.floor(Date.now() / 1000) - 777; + tx.setLockTime(_locktime); + shepherd.log(`kmd tx locktime set to ${_locktime}`, true); + } + + /*shepherd.log('buildSignedTx unsigned tx data vin', true); + shepherd.log(tx.tx.ins, true); + shepherd.log('buildSignedTx unsigned tx data vout', true); + shepherd.log(tx.tx.outs, true); + shepherd.log('buildSignedTx unsigned tx data', true); + shepherd.log(tx, true);*/ + + for (let i = 0; i < utxo.length; i++) { + if (shepherd.isPos(network)) { + tx.sign(shepherd.getNetworkData(network), i, key); + } else { + tx.sign(i, key); + } + } + + const rawtx = tx.build().toHex(); + + /*shepherd.log('buildSignedTx signed tx hex', true); + shepherd.log(rawtx, true);*/ + + // return rawtx; + + const successObj = { + msg: 'success', + result: rawtx, + }; + + res.end(JSON.stringify(successObj)); + } else { + const errorObj = { + msg: 'error', + result: 'unauthorized access', + }; + + res.end(JSON.stringify(errorObj)); + } + }); + return shepherd; }; \ No newline at end of file From b743b026c2b0b71e94b7c5b2e6faae8350d83ce2 Mon Sep 17 00:00:00 2001 From: pbca26 Date: Tue, 30 Jan 2018 19:26:42 +0300 Subject: [PATCH 36/67] version bump --- main.js | 12 ++++++------ routes/shepherd/electrum/createtx.js | 16 +--------------- version | 4 ++-- version_build | 2 +- 4 files changed, 10 insertions(+), 24 deletions(-) diff --git a/main.js b/main.js index 3c3c57d..88157f1 100644 --- a/main.js +++ b/main.js @@ -115,7 +115,7 @@ process.once('loaded', () => { applicationVersion: `${app.getVersion().replace('version=', '')}-beta`, copyright: 'Released under the MIT license', credits: 'SuperNET Team', - }) + }); } if (osPlatform === 'linux') { process.setFdLimit(appConfig.maxDescriptors.linux); @@ -409,14 +409,14 @@ function createWindow(status, hideLoadingWindow) { } app.on('window-all-closed', () => { - //if (os.platform() !== 'win32') { ig.kill(); } + // if (os.platform() !== 'win32') { ig.kill(); } // in osx apps stay active in menu bar until explictly closed or quitted by CMD Q // so we do not kill the app --> for the case user clicks again on the iguana icon // we open just a new window and respawn iguana proc /*if (process.platform !== 'darwin' || process.platform !== 'linux' || process.platform !== 'win32') { app.quit() }*/ -}) +}); // Emitted before the application starts closing its windows. // Calling event.preventDefault() will prevent the default behaviour, which is terminating the application. @@ -433,7 +433,7 @@ app.on('will-quit', (event) => { if (!forceQuitApp) { // loading window is still open shepherd.log('will-quit while loading window active'); - //event.preventDefault(); + // event.preventDefault(); } }); @@ -442,9 +442,9 @@ app.on('will-quit', (event) => { app.on('quit', (event) => { if (!forceQuitApp) { shepherd.log('quit while loading window active'); - //event.preventDefault(); + // event.preventDefault(); } -}) +}); app.commandLine.appendSwitch('ignore-certificate-errors'); // dirty hack diff --git a/routes/shepherd/electrum/createtx.js b/routes/shepherd/electrum/createtx.js index 3899068..70886c0 100644 --- a/routes/shepherd/electrum/createtx.js +++ b/routes/shepherd/electrum/createtx.js @@ -640,9 +640,7 @@ module.exports = (shepherd) => { } shepherd.log('buildSignedTx', true); - // console.log(`buildSignedTx priv key ${wif}`); shepherd.log(`buildSignedTx pub key ${key.getAddress().toString()}`, true); - // console.log('buildSignedTx std tx fee ' + shepherd.electrumServers[network].txfee); for (let i = 0; i < utxo.length; i++) { tx.addInput(utxo[i].txid, utxo[i].vout); @@ -660,7 +658,7 @@ module.exports = (shepherd) => { if (shepherd.isPos(network)) { tx.addOutput(changeAddress, Number(change), shepherd.getNetworkData(network)); } else { - console.log(`change ${change}`); + shepherd.log(`change ${change}`, true); tx.addOutput(changeAddress, Number(change)); } } @@ -672,13 +670,6 @@ module.exports = (shepherd) => { shepherd.log(`kmd tx locktime set to ${_locktime}`, true); } - /*shepherd.log('buildSignedTx unsigned tx data vin', true); - shepherd.log(tx.tx.ins, true); - shepherd.log('buildSignedTx unsigned tx data vout', true); - shepherd.log(tx.tx.outs, true); - shepherd.log('buildSignedTx unsigned tx data', true); - shepherd.log(tx, true);*/ - for (let i = 0; i < utxo.length; i++) { if (shepherd.isPos(network)) { tx.sign(shepherd.getNetworkData(network), i, key); @@ -689,11 +680,6 @@ module.exports = (shepherd) => { const rawtx = tx.build().toHex(); - /*shepherd.log('buildSignedTx signed tx hex', true); - shepherd.log(rawtx, true);*/ - - // return rawtx; - const successObj = { msg: 'success', result: rawtx, diff --git a/version b/version index 6914741..2fd6ceb 100644 --- a/version +++ b/version @@ -1,3 +1,3 @@ -version=0.2.0.27b -type=b-beta +version=0.2.0.27c +type=c-beta minversion=0.2.0.27 \ No newline at end of file diff --git a/version_build b/version_build index 51d5fb9..df21499 100644 --- a/version_build +++ b/version_build @@ -1 +1 @@ -0.2.0.27b-beta \ No newline at end of file +0.2.0.27c-beta \ No newline at end of file From d506d4caec9e24cdcda8e55d6a7f1dc615f9d630 Mon Sep 17 00:00:00 2001 From: pbca26 Date: Wed, 31 Jan 2018 16:22:47 +0300 Subject: [PATCH 37/67] audo seed verification method --- main.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/main.js b/main.js index 88157f1..f40b809 100644 --- a/main.js +++ b/main.js @@ -279,6 +279,11 @@ function createWindow(status, hideLoadingWindow) { mainWindow.spvFees = _spvFees; mainWindow.startSPV = shepherd.startSPV; mainWindow.startKMDNative = shepherd.startKMDNative; + mainWindow.createSeed = { + triggered: false, + firstLoginPH: null, + secondaryLoginPH: null, + }; } else { mainWindow = new BrowserWindow({ width: 500, From 2be4cf2d35c8d117e98f701593e3fbf79207db52 Mon Sep 17 00:00:00 2001 From: pbca26 Date: Tue, 6 Feb 2018 19:01:58 +0300 Subject: [PATCH 38/67] notary nodes elections --- main.js | 7 + private/kmdcli.js | 126 ----------------- private/mainmenu.js | 34 +---- routes/shepherd.js | 3 + routes/shepherd/elections.js | 200 +++++++++++++++++++++++++++ routes/shepherd/electrum/createtx.js | 17 ++- 6 files changed, 230 insertions(+), 157 deletions(-) delete mode 100644 private/kmdcli.js create mode 100644 routes/shepherd/elections.js diff --git a/main.js b/main.js index f40b809..cbfbd55 100644 --- a/main.js +++ b/main.js @@ -284,6 +284,13 @@ function createWindow(status, hideLoadingWindow) { firstLoginPH: null, secondaryLoginPH: null, }; + + for (let i = 0; i < process.argv.length; i++) { + if (process.argv[i].indexOf('nvote') > -1) { + console.log(`notary node elections chain ${process.argv[i].replace('nvote=', '')}`); + mainWindow.nnVoteChain = process.argv[i].replace('nvote=', ''); + } + } } else { mainWindow = new BrowserWindow({ width: 500, diff --git a/private/kmdcli.js b/private/kmdcli.js deleted file mode 100644 index cff8afd..0000000 --- a/private/kmdcli.js +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright (c) 2015 Satinderjit Singh - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - */ - - /* - * Agama komodo-cli paths - * - */ - -var child_process = require('child_process'), - path = require('path'), - os = require('os'); - -if (os.platform() === 'darwin') { - var komodocliBin = path.join(__dirname, '../assets/bin/osx/komodo-cli'), - zcashcliBin = '/Applications/ZCashSwingWalletUI.app/Contents/MacOS/zcash-cli'; -} - -if (os.platform() === 'linux') { - var komodocliBin = path.join(__dirname, '../assets/bin/linux64/komodo-cli'); -} - -if (os.platform() === 'win32') { - var komodocliBin = path.join(__dirname, '../assets/bin/win64/komodo-cli.exe'), - komodocliBin = path.normalize(komodocliBin); -} - -console.log(komodocliBin) - -/** - * The **komodo-cli** command is used to get komodo api calls answer. - * - * @private - * @category kmdcli - * - */ -var kmdcli = module.exports = { - exec: child_process.exec, - command: command -}; - -/** - * Parses komodo-cli commands. - * - * @private - * @static - * @category kmdcli - * @param {function} callback The callback function. - * - */ -function parse_kmdcli_commands(callback) { - return function(error, stdout, stderr) { - if (error) callback(error, stderr); - else callback(error, stdout); - //console.log(stdout) - }; -} - -/** - * Parses komodo-cli commands. - * - * @private - * @static - * @category kmdcli - * @param {function} callback The callback function. - * @example - * - * var kmdcli = require('./kmdcli'); - * - * kmdcli.command('getinfo', function(err, command) { - * console.log(command); - * }); - * - * // => - * { - * "version" : 1000550, - * "protocolversion" : 170002, - * "notarized" : 254740, - * "notarizedhash" : "01f4f1c46662ccca2e7fa9e7e38d4d2e4ced4402fa0f4fc116b8f004bb8cf272", - * "notarizedtxid" : "2b16e47a176f8c1886ca0268243f9b96f8b2db466ea26ae99873d5224bbf80b6", - * "walletversion" : 60000, - * "balance" : 32632.46167742, - * "interest" : 0.00478671, - * "blocks" : 254791, - * "longestchain" : 254791, - * "timeoffset" : 0, - * "tiptime" : 1490815616, - * "connections" : 8, - * "proxy" : "", - * "difficulty" : 707836.56791394, - * "testnet" : false, - * "keypoololdest" : 1482746526, - * "keypoolsize" : 101, - * "paytxfee" : 0.00000000, - * "relayfee" : 0.00001000, - * "errors" : "WARNING: check your network connection, 157 blocks received in the last 4 hours (240 expected)", - * "notaryid" : -1, - * "pubkey" : "000000000000000000000000000000000000000000000000000000000000000000" - * } - * - */ -function command(kmd_command, callback) { - if (callback) { - return this.exec(komodocliBin + " " + kmd_command, - parse_kmdcli_commands(callback)); - } -} diff --git a/private/mainmenu.js b/private/mainmenu.js index dd8780d..5d0981d 100644 --- a/private/mainmenu.js +++ b/private/mainmenu.js @@ -86,42 +86,18 @@ const template = [ } ] }, - /*{ + { role: 'help', - label: 'Support', + label: 'Debug', submenu: [ { - label: 'Supernet.org', - click () { - if (process.platform === 'linux') { - require('child_process').exec('xdg-open http://support.supernet.org'); - } else { - shell.openExternal('http://support.supernet.org'); - } - } - }, - { - label: 'Slack', + label: 'Reset settings', click () { - if (process.platform === 'linux') { - require('child_process').exec('xdg-open https://sprnt.slack.com/messages/support'); - } else { - shell.openExternal('https://sprnt.slack.com/messages/support'); - } + console.log(window.require('electron').remote.getCurrentWindow().appConfig); } }, - { - label: 'Github', - click () { - if (process.platform === 'linux') { - require('child_process').exec('xdg-open https://github.com/SuperNETorg/iguana/issues'); - } else { - shell.openExternal('https://github.com/SuperNETorg/iguana/issues'); - } - } - } ] - }*/ + } ] if (process.platform === 'darwin') { diff --git a/routes/shepherd.js b/routes/shepherd.js index 8c3c0d8..7e693ac 100644 --- a/routes/shepherd.js +++ b/routes/shepherd.js @@ -126,6 +126,9 @@ shepherd = require('./shepherd/auth.js')(shepherd); shepherd = require('./shepherd/coins.js')(shepherd); shepherd = require('./shepherd/coindWalletKeys.js')(shepherd); +// elections +shepherd = require('./shepherd/elections.js')(shepherd); + // explorer // shepherd = require('./shepherd/explorer/overview.js')(shepherd); diff --git a/routes/shepherd/elections.js b/routes/shepherd/elections.js new file mode 100644 index 0000000..6076918 --- /dev/null +++ b/routes/shepherd/elections.js @@ -0,0 +1,200 @@ +module.exports = (shepherd) => { + shepherd.elections = {}; + + shepherd.hex2str = (hexx) => { + const hex = hexx.toString(); //force conversion + let str = ''; + + for (let i = 0; i < hex.length; i += 2) { + str += String.fromCharCode(parseInt(hex.substr(i, 2), 16)); + } + + return str; + }; + + shepherd.post('/elections/status', (req, res, next) => { + if (shepherd.checkToken(req.body.token)) { + const successObj = { + msg: 'success', + result: shepherd.elections.pub ? shepherd.elections.pub : 'unauth', + }; + + res.end(JSON.stringify(successObj)); + } else { + const errorObj = { + msg: 'error', + result: 'unauthorized access', + }; + + res.end(JSON.stringify(errorObj)); + } + }); + + shepherd.post('/elections/login', (req, res, next) => { + if (shepherd.checkToken(req.body.token)) { + let keys = shepherd.seedToWif(req.body.seed, req.body.network, req.body.iguana); + + shepherd.elections = { + priv: keys.priv, + pub: keys.pub, + }; + + const successObj = { + msg: 'success', + result: keys.pub, + }; + + res.end(JSON.stringify(successObj)); + } else { + const errorObj = { + msg: 'error', + result: 'unauthorized access', + }; + + res.end(JSON.stringify(errorObj)); + } + }); + + shepherd.post('/elections/logout', (req, res, next) => { + if (shepherd.checkToken(req.body.token)) { + shepherd.elections = {}; + + const successObj = { + msg: 'success', + result: true, + }; + + res.end(JSON.stringify(successObj)); + } else { + const errorObj = { + msg: 'error', + result: 'unauthorized access', + }; + + res.end(JSON.stringify(errorObj)); + } + }); + + shepherd.get('/elections/listtransactions', (req, res, next) => { + if (shepherd.checkToken(req.query.token)) { + const network = req.query.network || shepherd.findNetworkObj(req.query.coin); + const ecl = new shepherd.electrumJSCore(shepherd.electrumServers[network].port, shepherd.electrumServers[network].address, shepherd.electrumServers[network].proto); // tcp or tls + const type = req.query.type; + const _address = req.query.address; + + shepherd.log('electrum elections listtransactions ==>', true); + + const MAX_TX = req.query.maxlength || 10; + ecl.connect(); + + ecl.blockchainAddressGetHistory(_address) + .then((json) => { + if (json && + json.length) { + json = shepherd.sortTransactions(json); + json = json.length > MAX_TX ? json.slice(0, MAX_TX) : json; + let _rawtx = []; + + shepherd.log(json.length, true); + + shepherd.Promise.all(json.map((transaction, index) => { + return new shepherd.Promise((resolve, reject) => { + ecl.blockchainBlockGetHeader(transaction.height) + .then((blockInfo) => { + if (blockInfo && + blockInfo.timestamp) { + ecl.blockchainTransactionGet(transaction['tx_hash']) + .then((_rawtxJSON) => { + shepherd.log('electrum gettransaction ==>', true); + shepherd.log((index + ' | ' + (_rawtxJSON.length - 1)), true); + shepherd.log(_rawtxJSON, true); + + // decode tx + const _network = shepherd.getNetworkData(network); + const decodedTx = shepherd.electrumJSTxDecoder(_rawtxJSON, network, _network); + let _res = {}; + let _opreturnFound = false; + let _region; + + for (let i = 0; i < decodedTx.outputs.length; i++) { + if (decodedTx.outputs[i].scriptPubKey.asm.indexOf('OP_RETURN') > -1) { + _opreturnFound = true; + _region = shepherd.hex2str(decodedTx.outputs[i].scriptPubKey.hex.substr(4, decodedTx.outputs[i].scriptPubKey.hex.length)); + shepherd.log(`found opreturn tag ${_region}`); + break; + } + } + + if (_opreturnFound) { + let _candidate = {}; + + for (let i = 0; i < decodedTx.outputs.length; i++) { + if (type === 'voter' && + decodedTx.outputs[i].scriptPubKey.addresses && + decodedTx.outputs[i].scriptPubKey.addresses[0] && + decodedTx.outputs[i].scriptPubKey.addresses[0] !== _address) { + shepherd.log(`i voted ${decodedTx.outputs[i].value} for ${decodedTx.outputs[i].scriptPubKey.addresses[0]}`); + _rawtx.push({ + address: decodedTx.outputs[i].scriptPubKey.addresses[0], + amount: decodedTx.outputs[i].value, + region: _region, + timestamp: blockInfo.timestamp, + }); + } + + if (type === 'candidate') { + if (decodedTx.outputs[i].scriptPubKey.addresses[0] === _address) { + _candidate.amount = decodedTx.outputs[i].value; + } else if (decodedTx.outputs[i].scriptPubKey.addresses[0] !== _address && decodedTx.outputs[i].scriptPubKey.asm.indexOf('OP_RETURN') === -1) { + _candidate.address = decodedTx.outputs[i].scriptPubKey.addresses[0]; + _candidate.region = _region; + _candidate.timestamp = blockInfo.timestamp; + } + + if (i === decodedTx.outputs.length - 1) { + shepherd.log(`i received ${_candidate.amount} from ${_candidate.address}`); + _rawtx.push(_candidate); + } + } + } + } + + resolve(true); + }); + } else { + resolve(false); + } + }); + }); + })) + .then(promiseResult => { + ecl.close(); + + const successObj = { + msg: 'success', + result: _rawtx, + }; + + res.end(JSON.stringify(successObj)); + }); + } else { + const successObj = { + msg: 'success', + result: [], + }; + + res.end(JSON.stringify(successObj)); + } + }); + } else { + const errorObj = { + msg: 'error', + result: 'unauthorized access', + }; + + res.end(JSON.stringify(errorObj)); + } + }); + + return shepherd; +} \ No newline at end of file diff --git a/routes/shepherd/electrum/createtx.js b/routes/shepherd/electrum/createtx.js index 70886c0..64d1b6b 100644 --- a/routes/shepherd/electrum/createtx.js +++ b/routes/shepherd/electrum/createtx.js @@ -54,7 +54,7 @@ module.exports = (shepherd) => { } // single sig - shepherd.buildSignedTx = (sendTo, changeAddress, wif, network, utxo, changeValue, spendValue) => { + shepherd.buildSignedTx = (sendTo, changeAddress, wif, network, utxo, changeValue, spendValue, opreturn) => { let key = shepherd.isZcash(network) ? bitcoinZcash.ECPair.fromWIF(wif, shepherd.getNetworkData(network)) : shepherd.bitcoinJS.ECPair.fromWIF(wif, shepherd.getNetworkData(network)); let tx; @@ -89,6 +89,13 @@ module.exports = (shepherd) => { } } + if (opreturn) { + console.log(`opreturn ${opreturn}`); + const data = Buffer.from(opreturn, 'utf8'); + const dataScript = shepherd.bitcoinJS.script.nullData.output.encode(data); + tx.addOutput(dataScript, 1000); + } + if (network === 'komodo' || network === 'KMD') { const _locktime = Math.floor(Date.now() / 1000) - 777; @@ -195,6 +202,7 @@ module.exports = (shepherd) => { const outputAddress = req.query.address; const changeAddress = req.query.change; const push = req.query.push; + const opreturn = req.query.opreturn; let fee = shepherd.electrumServers[network].txfee; let value = Number(req.query.value); let wif = req.query.wif; @@ -203,6 +211,10 @@ module.exports = (shepherd) => { wif = shepherd.electrumKeys[req.query.coin].priv; } + if (req.query.vote) { + wif = shepherd.elections.priv; + } + shepherd.log('electrum createrawtx =>', true); ecl.connect(); @@ -415,7 +427,8 @@ module.exports = (shepherd) => { network, inputs, _change, - value + value, + opreturn ); } } From f619e40fc305df885bbcaef828808f404877f24c Mon Sep 17 00:00:00 2001 From: pbca26 Date: Wed, 7 Feb 2018 13:22:14 +0300 Subject: [PATCH 39/67] spv watchonly login --- routes/shepherd/elections.js | 2 +- routes/shepherd/electrum/auth.js | 51 +++++++++++++++++++------------- version | 4 +-- version_build | 2 +- 4 files changed, 34 insertions(+), 25 deletions(-) diff --git a/routes/shepherd/elections.js b/routes/shepherd/elections.js index 6076918..a5bc870 100644 --- a/routes/shepherd/elections.js +++ b/routes/shepherd/elections.js @@ -2,7 +2,7 @@ module.exports = (shepherd) => { shepherd.elections = {}; shepherd.hex2str = (hexx) => { - const hex = hexx.toString(); //force conversion + const hex = hexx.toString(); // force conversion let str = ''; for (let i = 0; i < hex.length; i += 2) { diff --git a/routes/shepherd/electrum/auth.js b/routes/shepherd/electrum/auth.js index d214ab3..182a52b 100644 --- a/routes/shepherd/electrum/auth.js +++ b/routes/shepherd/electrum/auth.js @@ -14,30 +14,39 @@ module.exports = (shepherd) => { let keys; let isWif = false; - try { - bs58check.decode(_seed); - isWif = true; - } catch (e) {} - - if (isWif) { + if (req.body.seed.match('^[a-zA-Z0-9]{34}$') && + shepherd.appConfig.experimentalFeatures) { + shepherd.log('watchonly pub addr'); + shepherd.electrumKeys[_abbr] = { + priv: req.body.seed, + pub: req.body.seed, + }; + } else { try { - let key = shepherd.isZcash(_abbr.toLowerCase()) ? bitcoinZcash.ECPair.fromWIF(_seed, shepherd.getNetworkData(_abbr.toLowerCase()), true) : bitcoin.ECPair.fromWIF(_seed, shepherd.getNetworkData(_abbr.toLowerCase()), true); - keys = { - priv: key.toWIF(), - pub: key.getAddress(), - }; - } catch (e) { - _wifError = true; - break; + bs58check.decode(_seed); + isWif = true; + } catch (e) {} + + if (isWif) { + try { + let key = shepherd.isZcash(_abbr.toLowerCase()) ? bitcoinZcash.ECPair.fromWIF(_seed, shepherd.getNetworkData(_abbr.toLowerCase()), true) : bitcoin.ECPair.fromWIF(_seed, shepherd.getNetworkData(_abbr.toLowerCase()), true); + keys = { + priv: key.toWIF(), + pub: key.getAddress(), + }; + } catch (e) { + _wifError = true; + break; + } + } else { + keys = shepherd.seedToWif(_seed, shepherd.findNetworkObj(_abbr), req.body.iguana); } - } else { - keys = shepherd.seedToWif(_seed, shepherd.findNetworkObj(_abbr), req.body.iguana); - } - shepherd.electrumKeys[_abbr] = { - priv: keys.priv, - pub: keys.pub, - }; + shepherd.electrumKeys[_abbr] = { + priv: keys.priv, + pub: keys.pub, + }; + } } } diff --git a/version b/version index 2fd6ceb..009947e 100644 --- a/version +++ b/version @@ -1,3 +1,3 @@ -version=0.2.0.27c -type=c-beta +version=0.2.0.27d +type=d-beta minversion=0.2.0.27 \ No newline at end of file diff --git a/version_build b/version_build index df21499..eefedd4 100644 --- a/version_build +++ b/version_build @@ -1 +1 @@ -0.2.0.27c-beta \ No newline at end of file +0.2.0.27d-beta \ No newline at end of file From 7fef3c8c58c6138698babb78b6454dee342bac15 Mon Sep 17 00:00:00 2001 From: pbca26 Date: Wed, 7 Feb 2018 17:06:02 +0300 Subject: [PATCH 40/67] nn vote wif login --- routes/shepherd/elections.js | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/routes/shepherd/elections.js b/routes/shepherd/elections.js index a5bc870..58f2714 100644 --- a/routes/shepherd/elections.js +++ b/routes/shepherd/elections.js @@ -1,3 +1,6 @@ +const bs58check = require('bs58check'); +const bitcoin = require('bitcoinjs-lib'); + module.exports = (shepherd) => { shepherd.elections = {}; @@ -32,7 +35,29 @@ module.exports = (shepherd) => { shepherd.post('/elections/login', (req, res, next) => { if (shepherd.checkToken(req.body.token)) { - let keys = shepherd.seedToWif(req.body.seed, req.body.network, req.body.iguana); + const _seed = req.body.seed; + const _network = req.body.network; + let keys; + let isWif = false; + + try { + bs58check.decode(_seed); + isWif = true; + } catch (e) {} + + if (isWif) { + try { + let key = bitcoin.ECPair.fromWIF(_seed, shepherd.getNetworkData(_network.toLowerCase()), true); + keys = { + priv: key.toWIF(), + pub: key.getAddress(), + }; + } catch (e) { + _wifError = true; + } + } else { + keys = shepherd.seedToWif(_seed, _network, req.body.iguana); + } shepherd.elections = { priv: keys.priv, From 9fe8883afc98ed9d0032dc2262675837b2e0e055 Mon Sep 17 00:00:00 2001 From: pbca26 Date: Wed, 7 Feb 2018 18:39:16 +0300 Subject: [PATCH 41/67] app menu debug -> reset settings --- main.js | 1 + private/mainmenu.js | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/main.js b/main.js index cbfbd55..2f982c8 100644 --- a/main.js +++ b/main.js @@ -279,6 +279,7 @@ function createWindow(status, hideLoadingWindow) { mainWindow.spvFees = _spvFees; mainWindow.startSPV = shepherd.startSPV; mainWindow.startKMDNative = shepherd.startKMDNative; + mainWindow.resetSettings = function() { shepherd.saveLocalAppConf(__defaultAppSettings) }; mainWindow.createSeed = { triggered: false, firstLoginPH: null, diff --git a/private/mainmenu.js b/private/mainmenu.js index 5d0981d..0852661 100644 --- a/private/mainmenu.js +++ b/private/mainmenu.js @@ -92,8 +92,9 @@ const template = [ submenu: [ { label: 'Reset settings', - click () { - console.log(window.require('electron').remote.getCurrentWindow().appConfig); + click (item, focusedWindow) { + console.log(focusedWindow); + focusedWindow.resetSettings(); } }, ] From 24ef23ed04379b736f34c29256724d3885aa7377 Mon Sep 17 00:00:00 2001 From: pbca26 Date: Thu, 8 Feb 2018 11:58:10 +0300 Subject: [PATCH 42/67] wif 2 wif fix --- private/mainmenu.js | 1 - routes/shepherd/electrum/keys.js | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/private/mainmenu.js b/private/mainmenu.js index 0852661..7ad0a26 100644 --- a/private/mainmenu.js +++ b/private/mainmenu.js @@ -93,7 +93,6 @@ const template = [ { label: 'Reset settings', click (item, focusedWindow) { - console.log(focusedWindow); focusedWindow.resetSettings(); } }, diff --git a/routes/shepherd/electrum/keys.js b/routes/shepherd/electrum/keys.js index ffbddf1..3e1435e 100644 --- a/routes/shepherd/electrum/keys.js +++ b/routes/shepherd/electrum/keys.js @@ -77,7 +77,7 @@ module.exports = (shepherd) => { shepherd.post('/electrum/seedtowif', (req, res, next) => { if (shepherd.checkToken(req.body.token)) { - let keys = shepherd.seedToWif(req.body.seed, req.body.network, req.body.iguana); + let keys = shepherd.seedToWif(req.body.seed, req.body.network.toLowerCase(), req.body.iguana); const successObj = { msg: 'success', From df36d7224f29f7549c4f97072ad6eca2d4e0daca Mon Sep 17 00:00:00 2001 From: pbca26 Date: Mon, 12 Feb 2018 17:05:16 +0300 Subject: [PATCH 43/67] pub validation --- main.js | 2 + routes/shepherd/electrum/keys.js | 68 +++++++++++++++++++++++++++++++- version | 6 +-- version_build | 2 +- 4 files changed, 73 insertions(+), 5 deletions(-) diff --git a/main.js b/main.js index 2f982c8..dc1cccc 100644 --- a/main.js +++ b/main.js @@ -279,6 +279,8 @@ function createWindow(status, hideLoadingWindow) { mainWindow.spvFees = _spvFees; mainWindow.startSPV = shepherd.startSPV; mainWindow.startKMDNative = shepherd.startKMDNative; + mainWindow.addressVersionCheck = shepherd.addressVersionCheck; + mainWindow.getCoinByPub = shepherd.getCoinByPub; mainWindow.resetSettings = function() { shepherd.saveLocalAppConf(__defaultAppSettings) }; mainWindow.createSeed = { triggered: false, diff --git a/routes/shepherd/electrum/keys.js b/routes/shepherd/electrum/keys.js index 3e1435e..bfe5581 100644 --- a/routes/shepherd/electrum/keys.js +++ b/routes/shepherd/electrum/keys.js @@ -97,6 +97,72 @@ module.exports = (shepherd) => { } }); + shepherd.post('/electrum/seedtowif', (req, res, next) => { + if (shepherd.checkToken(req.body.token)) { + let keys = shepherd.seedToWif(req.body.seed, req.body.network.toLowerCase(), req.body.iguana); + + const successObj = { + msg: 'success', + result: { + keys, + }, + }; + + res.end(JSON.stringify(successObj)); + } else { + const errorObj = { + msg: 'error', + result: 'unauthorized access', + }; + + res.end(JSON.stringify(errorObj)); + } + }); + + shepherd.getCoinByPub = (address) => { + const _skipNetworks = ['btc', 'crw', 'dgb', 'arg', 'zec', 'nmc', 'ltc', 'vtc', 'via', 'fair', 'doge', 'kmd', 'mona']; + + try { + const _b58check = bitcoin.address.fromBase58Check(address); + let _coin = []; + let returnObj; + + for (let key in shepherd.electrumJSNetworks) { + if (_b58check.version === shepherd.electrumJSNetworks[key].pubKeyHash && + !_skipNetworks.find((item) => { return item === key ? true : false })) { + _coin.push(key); + } + } + + if (_coin.length) { + return { + coin: _coin, + version: _b58check.version, + }; + } else { + return 'Unable to find matching coin version'; + } + } catch(e) { + return 'Invalid pub address'; + } + }; + + shepherd.addressVersionCheck = (network, address) => { + const _network = shepherd.getNetworkData(network.toLowerCase()); + + try { + const _b58check = bitcoin.address.fromBase58Check(address); + + if (_b58check.version === _network.pubKeyHash) { + return true; + } else { + return false; + } + } catch(e) { + return 'Invalid pub address'; + } + }; + shepherd.post('/electrum/keys', (req, res, next) => { if (shepherd.checkToken(req.body.token)) { let _matchingKeyPairs = 0; @@ -183,7 +249,7 @@ module.exports = (shepherd) => { shepherd.post('/electrum/seed/bip39/match', (req, res, next) => { if (shepherd.checkToken(req.body.token)) { const seed = bip39.mnemonicToSeed(req.body.seed); - const hdMaster = bitcoin.HDNode.fromSeedBuffer(seed, shepherd.electrumJSNetworks.komodo); // seed from above + const hdMaster = bitcoin.HDNode.fromSeedBuffer(seed, shepherd.electrumJSNetworks.komodo); const matchPattern = req.body.match; const _defaultAddressDepth = req.body.addressdepth; const _defaultAccountCount = req.body.accounts; diff --git a/version b/version index 009947e..7bb8865 100644 --- a/version +++ b/version @@ -1,3 +1,3 @@ -version=0.2.0.27d -type=d-beta -minversion=0.2.0.27 \ No newline at end of file +version=0.2.0.28a +type=a-beta +minversion=0.2.0.28 \ No newline at end of file diff --git a/version_build b/version_build index eefedd4..b20a97e 100644 --- a/version_build +++ b/version_build @@ -1 +1 @@ -0.2.0.27d-beta \ No newline at end of file +0.2.0.28a-beta \ No newline at end of file From f76427922f00b2856c7116b0d5f352b063e21b84 Mon Sep 17 00:00:00 2001 From: pbca26 Date: Mon, 12 Feb 2018 19:13:43 +0300 Subject: [PATCH 44/67] spv beer, pizza, vote; elections missing var check --- routes/electrumjs/electrumServers.js | 33 ++++++++++++++++++++++++++++ routes/shepherd/elections.js | 16 +++++++++----- routes/shepherd/electrum/network.js | 6 +++++ 3 files changed, 49 insertions(+), 6 deletions(-) diff --git a/routes/electrumjs/electrumServers.js b/routes/electrumjs/electrumServers.js index d115c1b..19037d4 100644 --- a/routes/electrumjs/electrumServers.js +++ b/routes/electrumjs/electrumServers.js @@ -158,6 +158,39 @@ let electrumServers = { 'electrum2.cipig.net:10020' ], }, + beer: { // !estimatefee + address: 'electrum1.cipig.net', + port: 10022, + proto: 'tcp', + txfee: 10000, + abbr: 'BEER', + serverList: [ + 'electrum1.cipig.net:10022', + 'electrum2.cipig.net:10022' + ], + }, + pizza: { // !estimatefee + address: 'electrum1.cipig.net', + port: 10024, + proto: 'tcp', + txfee: 10000, + abbr: 'PIZZA', + serverList: [ + 'electrum1.cipig.net:10024', + 'electrum2.cipig.net:10024' + ], + }, + vote: { // !estimatefee + address: 'electrum1.cipig.net', + port: 10021, + proto: 'tcp', + txfee: 10000, + abbr: 'VOTE', + serverList: [ + 'electrum1.cipig.net:10021', + 'electrum2.cipig.net:10021' + ], + }, jumblr: { // !estimatefee address: 'electrum1.cipig.net', port: 10004, diff --git a/routes/shepherd/elections.js b/routes/shepherd/elections.js index 58f2714..d64ce5e 100644 --- a/routes/shepherd/elections.js +++ b/routes/shepherd/elections.js @@ -141,12 +141,16 @@ module.exports = (shepherd) => { let _opreturnFound = false; let _region; - for (let i = 0; i < decodedTx.outputs.length; i++) { - if (decodedTx.outputs[i].scriptPubKey.asm.indexOf('OP_RETURN') > -1) { - _opreturnFound = true; - _region = shepherd.hex2str(decodedTx.outputs[i].scriptPubKey.hex.substr(4, decodedTx.outputs[i].scriptPubKey.hex.length)); - shepherd.log(`found opreturn tag ${_region}`); - break; + if (decodedTx && + decodedTx.outputs && + decodedTx.outputs.length) { + for (let i = 0; i < decodedTx.outputs.length; i++) { + if (decodedTx.outputs[i].scriptPubKey.asm.indexOf('OP_RETURN') > -1) { + _opreturnFound = true; + _region = shepherd.hex2str(decodedTx.outputs[i].scriptPubKey.hex.substr(4, decodedTx.outputs[i].scriptPubKey.hex.length)); + shepherd.log(`found opreturn tag ${_region}`); + break; + } } } diff --git a/routes/shepherd/electrum/network.js b/routes/shepherd/electrum/network.js index 594c6d5..aa4bd98 100644 --- a/routes/shepherd/electrum/network.js +++ b/routes/shepherd/electrum/network.js @@ -61,6 +61,9 @@ module.exports = (shepherd) => { coin === 'MNZ' || coin === 'BTCH' || coin === 'KMD' || + coin === 'BEER' || + coin === 'PIZZA' || + coin === 'VOTE' || coin === 'KOMODO' || coinUC === 'SUPERNET' || coinUC === 'REVS' || @@ -83,6 +86,9 @@ module.exports = (shepherd) => { coinUC === 'WLC' || coinUC === 'MNZ' || coinUC === 'BTCH' || + coinUC === 'BEER' || + coinUC === 'PIZZA' || + coinUC === 'VOTE' || coinUC === 'KMD' || coinUC === 'KOMODO') { return shepherd.electrumJSNetworks.komodo; From d1edf0ebd9eb51bd7b284d3a3c30e7da8e6c8ecf Mon Sep 17 00:00:00 2001 From: pbca26 Date: Mon, 12 Feb 2018 20:01:59 +0300 Subject: [PATCH 45/67] increase initial win height by 50px --- main.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main.js b/main.js index dc1cccc..f2a9887 100644 --- a/main.js +++ b/main.js @@ -237,7 +237,7 @@ function createWindow(status, hideLoadingWindow) { // initialise window mainWindow = new BrowserWindow({ // dirty hack to prevent main window flash on quit width: closeAppAfterLoading ? 1 : 1280, - height: closeAppAfterLoading ? 1 : 800, + height: closeAppAfterLoading ? 1 : 850, icon: agamaIcon, show: false, }); From 550685bf0b14a0a14f8b79f0cc3f9125940b1f83 Mon Sep 17 00:00:00 2001 From: pbca26 Date: Tue, 13 Feb 2018 16:41:28 +0300 Subject: [PATCH 46/67] spv qutum, btx, btcz, hodlc --- routes/electrumjs/electrumServers.js | 55 ++++++++++++++++ routes/electrumjs/electrumjs.networks.js | 66 ++++++++++++++++++- routes/electrumjs/electrumjs.txdecoder-pos.js | 1 - routes/shepherd/electrum/network.js | 4 +- 4 files changed, 121 insertions(+), 5 deletions(-) diff --git a/routes/electrumjs/electrumServers.js b/routes/electrumjs/electrumServers.js index 19037d4..7a24cbe 100644 --- a/routes/electrumjs/electrumServers.js +++ b/routes/electrumjs/electrumServers.js @@ -443,6 +443,61 @@ let electrumServers = { 'electrum2.cipig.net:10055' ], }, + hodlc: { + address: 'hodl.amit177.cf', + port: 17989, + proto: 'tcp', + txfee: 5000, + abbr: 'HODLC', + serverList: [ + 'hodl.amit177.cf:17989', + 'hodl2.amit177.cf:17898' + ], + }, + btx: { + address: 'electrum1.cipig.net', + port: 10057, + proto: 'tcp', + txfee: 50000, + abbr: 'BTX', + serverList: [ + 'electrum1.cipig.net:10057', + 'electrum2.cipig.net:10057' + ], + }, + btcz: { + address: 'electrum1.cipig.net', + port: 10056, + proto: 'tcp', + txfee: 10000, + abbr: 'BTCZ', + serverList: [ + 'electrum1.cipig.net:10056', + 'electrum2.cipig.net:10056' + ], + }, + grs: { + address: 'electrum10.groestlcoin.org', + port: 50001, + proto: 'tcp', + txfee: 50000, + abbr: 'GRS', + serverList: [ + 'electrum10.groestlcoin.org:50001', + 'electrum11.groestlcoin.org:50001' + ], + }, + qtum: { + address: 's1.qtum.info', + port: 50001, + proto: 'tcp', + txfee: 400000, + abbr: 'QTUM', + serverList: [ + 's1.qtum.info:50001', + 's2.qtum.info:50001' + ], + }, }; electrumServers.crw = electrumServers.crown; diff --git a/routes/electrumjs/electrumjs.networks.js b/routes/electrumjs/electrumjs.networks.js index 13611ee..b54f0e4 100644 --- a/routes/electrumjs/electrumjs.networks.js +++ b/routes/electrumjs/electrumjs.networks.js @@ -254,7 +254,7 @@ networks.zcash = { }; networks.hush = { - messagePrefix: '\Hush Signed Message:\n', + messagePrefix: '\x19Hush Signed Message:\n', bip32: { public: 0x0488b21e, private: 0x0488ade4, @@ -266,7 +266,7 @@ networks.hush = { }; networks.zcl = { - messagePrefix: '\Zclassic Signed Message:\n', + messagePrefix: '\x19Zclassic Signed Message:\n', bip32: { public: 0x0488b21e, private: 0x0488ade4, @@ -278,7 +278,7 @@ networks.zcl = { }; networks.xmy = { - messagePrefix: '\Myriad Signed Message:\n', + messagePrefix: '\x19Myriad Signed Message:\n', bip32: { public: 0x0488b21e, private: 0x0488ade4, @@ -289,6 +289,66 @@ networks.xmy = { dustThreshold: 1000, }; +networks.hodlc = { + messagePrefix: '\x19Hodlc Signed Message:\n', + bip32: { + public: 0x0488b21e, + private: 0x0488ade4, + }, + pubKeyHash: 0x28, + scriptHash: 0x5, + wif: 0x28 + 128, + dustThreshold: 1000, +}; + +networks.qtum = { + messagePrefix: '\x19Qtum Signed Message:\n', + bip32: { + public: 0x0488b21e, + private: 0x0488ade4, + }, + pubKeyHash: 0x3A, + scriptHash: 0x32, + wif: 0x80, + dustThreshold: 1000, +}; + +networks.btx = { + messagePrefix: '\x19Bitcore Signed Message:\n', + bip32: { + public: 0x0488b21e, + private: 0x0488ade4, + }, + pubKeyHash: 0x0, + scriptHash: 0x5, + wif: 0x80, + dustThreshold: 1000, +}; + +networks.btcz = { + messagePrefix: '\x19BitcoinZ Signed Message:\n', + bip32: { + public: 0x0488b21e, + private: 0x0488ade4, + }, + pubKeyHash: 0x1cb8, + scriptHash: 0x1cbd, + wif: 0x80, + dustThreshold: 1000, +}; + +networks.grs = { // fails to gen a proper addr + messagePrefix: '\x19Groestlcoin Signed Message:\n', + bip32: { + public: 0x0488b21e, + private: 0x0488ade4, + }, + pubKeyHash: 0x24, + scriptHash: 0x5, + wif: 0x80, + dustThreshold: 1000, +}; + networks.btc = networks.bitcoin; networks.crw = networks.crown; networks.dgb = networks.digibyte; diff --git a/routes/electrumjs/electrumjs.txdecoder-pos.js b/routes/electrumjs/electrumjs.txdecoder-pos.js index 849a1ad..e0495a8 100644 --- a/routes/electrumjs/electrumjs.txdecoder-pos.js +++ b/routes/electrumjs/electrumjs.txdecoder-pos.js @@ -81,7 +81,6 @@ var decodeOutput = function(tx, network) { break; } -console.log(vout); return vout; } diff --git a/routes/shepherd/electrum/network.js b/routes/shepherd/electrum/network.js index aa4bd98..4a02652 100644 --- a/routes/shepherd/electrum/network.js +++ b/routes/shepherd/electrum/network.js @@ -13,7 +13,9 @@ module.exports = (shepherd) => { network === 'HUSH' || network === 'hush' || network === 'ZCL' || - network === 'zcl') { + network === 'zcl' || + network === 'BTCZ' || + network === 'btcz') { return true; } }; From 26ce131c9edf9b3e3aafcc0b19ee5c03ba8aeb6e Mon Sep 17 00:00:00 2001 From: pbca26 Date: Fri, 16 Feb 2018 21:50:33 +0300 Subject: [PATCH 47/67] enable btc, send vin/vout final check --- routes/electrumjs/electrumServers.js | 18 ++++++++---- routes/shepherd/electrum/balance.js | 2 +- routes/shepherd/electrum/createtx.js | 38 +++++++++++++++++++++---- routes/shepherd/electrum/listunspent.js | 2 ++ version | 4 +-- version_build | 2 +- 6 files changed, 51 insertions(+), 15 deletions(-) diff --git a/routes/electrumjs/electrumServers.js b/routes/electrumjs/electrumServers.js index 7a24cbe..e0d01cc 100644 --- a/routes/electrumjs/electrumServers.js +++ b/routes/electrumjs/electrumServers.js @@ -323,16 +323,22 @@ let electrumServers = { '136.243.45.140:50041' ], }, - /*btc: { - address: 'electrum1.cipig.net', - port: 10000, + btc: { + address: 'e-x.not.fyi', + port: 50001, proto: 'tcp', abbr: 'BTC', serverList: [ - 'electrum1.cipig.net:10000', - 'electrum2.cipig.net:10000' + 'mooo.not.fyi:50011', + 'e-x.not.fyi:50001', + 'vps.hsmiths.com:50001', + 'us.electrum.be:50001', + 'electrumx.bot.nu:50001', + 'btc.asis.io:50001', + 'electrum.backplanedns.org:50001', + 'electrum.festivaldelhumor.org:50001' ], - },*/ + }, btg: { address: '173.212.225.176', port: 10052, diff --git a/routes/shepherd/electrum/balance.js b/routes/shepherd/electrum/balance.js index ed1ec50..2c25708 100644 --- a/routes/shepherd/electrum/balance.js +++ b/routes/shepherd/electrum/balance.js @@ -74,7 +74,7 @@ module.exports = (shepherd) => { interest: Number(interestTotal.toFixed(8)), interestSats: Math.floor(interestTotal * 100000000), total: interestTotal > 0 ? Number((0.00000001 * json.confirmed + interestTotal).toFixed(8)) : 0, - totalSats: interestTotal > 0 ?json.confirmed + Math.floor(interestTotal * 100000000) : 0, + totalSats: interestTotal > 0 ? json.confirmed + Math.floor(interestTotal * 100000000) : 0, }, }; diff --git a/routes/shepherd/electrum/createtx.js b/routes/shepherd/electrum/createtx.js index 64d1b6b..f503e28 100644 --- a/routes/shepherd/electrum/createtx.js +++ b/routes/shepherd/electrum/createtx.js @@ -203,6 +203,7 @@ module.exports = (shepherd) => { const changeAddress = req.query.change; const push = req.query.push; const opreturn = req.query.opreturn; + const btcFee = req.query.btcfee ? Number(req.query.btcfee) : null; let fee = shepherd.electrumServers[network].txfee; let value = Number(req.query.value); let wif = req.query.wif; @@ -215,6 +216,10 @@ module.exports = (shepherd) => { wif = shepherd.elections.priv; } + if (btcFee) { + fee = 0; + } + shepherd.log('electrum createrawtx =>', true); ecl.connect(); @@ -274,10 +279,15 @@ module.exports = (shepherd) => { // default coin selection algo blackjack with fallback to accumulative // make a first run, calc approx tx fee // if ins and outs are empty reduce max spend by txfee - const firstRun = shepherd.coinSelect(utxoListFormatted, targets, 0); + const firstRun = shepherd.coinSelect(utxoListFormatted, targets, btcFee ? btcFee : 0); let inputs = firstRun.inputs; let outputs = firstRun.outputs; + if (btcFee) { + shepherd.log(`btc fee per byte ${btcFee}`, true); + fee = firstRun.fee; + } + shepherd.log('coinselect res =>', true); shepherd.log('coinselect inputs =>', true); shepherd.log(inputs, true); @@ -295,7 +305,7 @@ module.exports = (shepherd) => { const secondRun = shepherd.coinSelect(utxoListFormatted, targets, 0); inputs = secondRun.inputs; outputs = secondRun.outputs; - fee = secondRun.fee; + fee = fee ? fee : secondRun.fee; shepherd.log('second run coinselect inputs =>', true); shepherd.log(inputs, true); @@ -309,10 +319,21 @@ module.exports = (shepherd) => { if (outputs && outputs.length === 2) { - _change = outputs[1].value; + _change = outputs[1].value - fee; } - outputs[0].value = outputs[0].value - fee; + if (!btcFee && + _change === 0) { + outputs[0].value = outputs[0].value - fee; + } + + if (btcFee) { + value = outputs[0].value; + } else { + if (_change > 0) { + value = outputs[0].value - fee; + } + } shepherd.log('adjusted outputs, value - default fee =>', true); shepherd.log(outputs, true); @@ -361,7 +382,7 @@ module.exports = (shepherd) => { shepherd.log(`estimated fee overhead ${_feeOverhead}`, true); shepherd.log(`current change amount ${_change} (${_change * 0.00000001}), boosted change amount ${_change + (totalInterest - _feeOverhead)} (${(_change + (totalInterest - _feeOverhead)) * 0.00000001})`, true); - if (_maxSpend === value) { + if (_maxSpend - fee === value) { _change = totalInterest - _change - _feeOverhead; if (outputAddress === changeAddress) { @@ -394,6 +415,13 @@ module.exports = (shepherd) => { shepherd.log(`vin sum ${vinSum} (${vinSum * 0.00000001})`, true); shepherd.log(`estimatedFee ${_estimatedFee} (${_estimatedFee * 0.00000001})`, true); + // double check no extra fee is applied + shepherd.log(`vin - vout ${vinSum - value - _change}`); + + if ((vinSum - value - _change) > fee) { + _change += fee; + shepherd.log(`double fee, increase change by ${fee}`); + } let _rawtx; diff --git a/routes/shepherd/electrum/listunspent.js b/routes/shepherd/electrum/listunspent.js index 411d495..f8b2fe3 100644 --- a/routes/shepherd/electrum/listunspent.js +++ b/routes/shepherd/electrum/listunspent.js @@ -1,3 +1,5 @@ +// TODO: watchonly spendable switch + module.exports = (shepherd) => { shepherd.listunspent = (ecl, address, network, full, verify) => { let _atLeastOneDecodeTxFailed = false; diff --git a/version b/version index 7bb8865..0a74b63 100644 --- a/version +++ b/version @@ -1,3 +1,3 @@ -version=0.2.0.28a -type=a-beta +version=0.2.0.28b +type=b-beta minversion=0.2.0.28 \ No newline at end of file diff --git a/version_build b/version_build index b20a97e..fea66b8 100644 --- a/version_build +++ b/version_build @@ -1 +1 @@ -0.2.0.28a-beta \ No newline at end of file +0.2.0.28b-beta \ No newline at end of file From adcab7a160b4e2340c63e775ecee2c48f3a16708 Mon Sep 17 00:00:00 2001 From: pbca26 Date: Sat, 17 Feb 2018 00:07:00 +0300 Subject: [PATCH 48/67] donate change < 1000 sats --- routes/shepherd/electrum/createtx.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/routes/shepherd/electrum/createtx.js b/routes/shepherd/electrum/createtx.js index f503e28..ae2cb79 100644 --- a/routes/shepherd/electrum/createtx.js +++ b/routes/shepherd/electrum/createtx.js @@ -423,6 +423,12 @@ module.exports = (shepherd) => { shepherd.log(`double fee, increase change by ${fee}`); } + // TODO: use individual dust thresholds + if (_change < 1000) { + shepherd.log(`change is < 1000 sats, donate ${_change} sats to miners`, true); + _change = 0; + } + let _rawtx; if (req.query.unsigned) { From 5d4a7d623b8beeda5fa20779acd64fd4d6ac1aa9 Mon Sep 17 00:00:00 2001 From: pbca26 Date: Mon, 19 Feb 2018 21:32:35 +0300 Subject: [PATCH 49/67] spv close connections fix --- routes/shepherd/electrum/balance.js | 9 +++++++-- routes/shepherd/electrum/listunspent.js | 2 ++ routes/shepherd/electrum/merkle.js | 6 +++++- routes/shepherd/electrum/transactions.js | 2 ++ 4 files changed, 16 insertions(+), 3 deletions(-) diff --git a/routes/shepherd/electrum/balance.js b/routes/shepherd/electrum/balance.js index 2c25708..6b73d9b 100644 --- a/routes/shepherd/electrum/balance.js +++ b/routes/shepherd/electrum/balance.js @@ -13,9 +13,8 @@ module.exports = (shepherd) => { json.hasOwnProperty('confirmed') && json.hasOwnProperty('unconfirmed')) { if (network === 'komodo') { - ecl.connect(); ecl.blockchainAddressListunspent(req.query.address) - .then((utxoList) => { + .then((utxoList) => { if (utxoList && utxoList.length) { // filter out < 10 KMD amounts @@ -81,6 +80,8 @@ module.exports = (shepherd) => { res.end(JSON.stringify(successObj)); }); } else { + ecl.close(); + const successObj = { msg: 'success', result: { @@ -98,6 +99,8 @@ module.exports = (shepherd) => { res.end(JSON.stringify(successObj)); } } else { + ecl.close(); + const successObj = { msg: 'success', result: { @@ -133,6 +136,8 @@ module.exports = (shepherd) => { res.end(JSON.stringify(successObj)); } } else { + ecl.close(); + const successObj = { msg: 'error', result: shepherd.CONNECTION_ERROR_OR_INCOMPLETE_DATA, diff --git a/routes/shepherd/electrum/listunspent.js b/routes/shepherd/electrum/listunspent.js index f8b2fe3..b280ee4 100644 --- a/routes/shepherd/electrum/listunspent.js +++ b/routes/shepherd/electrum/listunspent.js @@ -26,6 +26,7 @@ module.exports = (shepherd) => { } if (!_utxo.length) { // no confirmed utxo + ecl.close(); resolve('no valid utxo'); } else { shepherd.Promise.all(_utxo.map((_utxoItem, index) => { @@ -129,6 +130,7 @@ module.exports = (shepherd) => { }); } } else { + ecl.close(); resolve('cant get current height'); } }); diff --git a/routes/shepherd/electrum/merkle.js b/routes/shepherd/electrum/merkle.js index 07bfd29..39cde0e 100644 --- a/routes/shepherd/electrum/merkle.js +++ b/routes/shepherd/electrum/merkle.js @@ -83,13 +83,16 @@ module.exports = (shepherd) => { resolve(false); } } else { + ecl.close(); resolve(shepherd.CONNECTION_ERROR_OR_INCOMPLETE_DATA); } } else { + ecl.close(); resolve(shepherd.CONNECTION_ERROR_OR_INCOMPLETE_DATA); } }); } else { + ecl.close(); resolve(shepherd.CONNECTION_ERROR_OR_INCOMPLETE_DATA); } }); @@ -118,7 +121,8 @@ module.exports = (shepherd) => { height, _filteredServerList, shepherd.electrumCoins[coin].server.ip + ':' + shepherd.electrumCoins[coin].server.port + ':' + shepherd.electrumServers[coin === 'KMD' || coin === 'komodo' ? 'komodo' : coin.toLowerCase()].proto - ).then((proof) => { + ) + .then((proof) => { resolve(proof); }); } else { diff --git a/routes/shepherd/electrum/transactions.js b/routes/shepherd/electrum/transactions.js index f571962..55d4463 100644 --- a/routes/shepherd/electrum/transactions.js +++ b/routes/shepherd/electrum/transactions.js @@ -188,6 +188,8 @@ module.exports = (shepherd) => { res.end(JSON.stringify(successObj)); }); } else { + ecl.close(); + const successObj = { msg: 'success', result: [], From 73c02ae61d921b180b655853a9e3cd1c90d25b07 Mon Sep 17 00:00:00 2001 From: pbca26 Date: Wed, 21 Feb 2018 16:22:13 +0300 Subject: [PATCH 50/67] spv better tx history categorization --- routes/shepherd/electrum/transactions.js | 118 ++++++++++++++++++----- 1 file changed, 94 insertions(+), 24 deletions(-) diff --git a/routes/shepherd/electrum/transactions.js b/routes/shepherd/electrum/transactions.js index 55d4463..4864e96 100644 --- a/routes/shepherd/electrum/transactions.js +++ b/routes/shepherd/electrum/transactions.js @@ -50,9 +50,10 @@ module.exports = (shepherd) => { .then((json) => { if (json && json.length) { + let _rawtx = []; + json = shepherd.sortTransactions(json); json = json.length > MAX_TX ? json.slice(0, MAX_TX) : json; - let _rawtx = []; shepherd.log(json.length, true); @@ -189,7 +190,7 @@ module.exports = (shepherd) => { }); } else { ecl.close(); - + const successObj = { msg: 'success', result: [], @@ -248,10 +249,11 @@ module.exports = (shepherd) => { } }); - shepherd.parseTransactionAddresses = (tx, targetAddress, network) => { + shepherd.parseTransactionAddresses = (tx, targetAddress, network, skipTargetAddress) => { // TODO: - sum vins / sum vouts to the same address // - multi vin multi vout // - detect change address + // - double check for exact sum input/output values let result = []; let _parse = { inputs: {}, @@ -265,6 +267,10 @@ module.exports = (shepherd) => { inputs: 0, outputs: 0, }; + let _addresses = { + inputs: [], + outputs: [], + }; shepherd.log('parseTransactionAddresses result ==>', true); @@ -294,39 +300,99 @@ module.exports = (shepherd) => { _total[key] += Number(_parse[key][i].value); + // ignore op return outputs if (_parse[key][i].scriptPubKey && _parse[key][i].scriptPubKey.addresses && + _parse[key][i].scriptPubKey.addresses[0] && _parse[key][i].scriptPubKey.addresses[0] === targetAddress && _parse[key][i].value) { _sum[key] += Number(_parse[key][i].value); } + + if (_parse[key][i].scriptPubKey && + _parse[key][i].scriptPubKey.addresses && + _parse[key][i].scriptPubKey.addresses[0]) { + _addresses[key].push(_parse[key][i].scriptPubKey.addresses[0]); + + if (_parse[key][i].scriptPubKey.addresses[0] === targetAddress && skipTargetAddress) { + _addresses[key].pop(); + } + } + } + } + + _addresses.inputs = [ ...new Set(_addresses.inputs) ]; + _addresses.outputs = [ ...new Set(_addresses.outputs) ]; + + shepherd.log('addresses in =>', true); + shepherd.log(_addresses.inputs, true); + shepherd.log('addresses out =>', true); + shepherd.log(_addresses.outputs, true); + + let isSelfSend = { + inputs: false, + outputs: false, + }; + + for (let key in _parse) { + for (let i = 0; i < _addresses[key].length; i++) { + if (_addresses[key][i] === targetAddress && _addresses[key].length === 1) { + isSelfSend[key] = true; + } } } if (_sum.inputs > 0 && _sum.outputs > 0) { // vin + change, break into two tx - result = [{ // reorder since tx sort by default is from newest to oldest - type: 'sent', - amount: Number(_sum.inputs.toFixed(8)), - address: targetAddress, - timestamp: tx.timestamp, - txid: tx.format.txid, - confirmations: tx.confirmations, - }, { - type: 'received', - amount: Number(_sum.outputs.toFixed(8)), - address: targetAddress, - timestamp: tx.timestamp, - txid: tx.format.txid, - confirmations: tx.confirmations, - }]; - if (network === 'komodo') { // calc claimed interest amount - const vinVoutDiff = _total.inputs - _total.outputs; + // send to self + if (isSelfSend.inputs && isSelfSend.outputs) { + result = { + type: 'self', + amount: Number(_sum.inputs - _sum.outputs).toFixed(8), + sumIn: _sum.inputs, + sumOut: _sum.outputs, + address: targetAddress, + timestamp: tx.timestamp, + txid: tx.format.txid, + confirmations: tx.confirmations, + }; - if (vinVoutDiff < 0) { - result[1].interest = Number(vinVoutDiff.toFixed(8)); + if (network === 'komodo') { // calc claimed interest amount + const vinVoutDiff = _total.inputs - _total.outputs; + + if (vinVoutDiff < 0) { + result.interest = Number(vinVoutDiff.toFixed(8)); + } + } + } else { + result = [{ // reorder since tx sort by default is from newest to oldest + type: 'sent', + amount: Number(_sum.inputs.toFixed(8)), + address: _addresses.outputs[0], + timestamp: tx.timestamp, + txid: tx.format.txid, + confirmations: tx.confirmations, + inputAddresses: _addresses.inputs, + outputAddresses: _addresses.outputs, + }, { + type: 'received', + amount: Number(_sum.outputs.toFixed(8)), + address: targetAddress, + timestamp: tx.timestamp, + txid: tx.format.txid, + confirmations: tx.confirmations, + inputAddresses: _addresses.inputs, + outputAddresses: _addresses.outputs, + }]; + + if (network === 'komodo') { // calc claimed interest amount + const vinVoutDiff = _total.inputs - _total.outputs; + + if (vinVoutDiff < 0) { + result[1].interest = Number(vinVoutDiff.toFixed(8)); + } } } } else if (_sum.inputs === 0 && _sum.outputs > 0) { @@ -337,22 +403,26 @@ module.exports = (shepherd) => { timestamp: tx.timestamp, txid: tx.format.txid, confirmations: tx.confirmations, + inputAddresses: _addresses.inputs, + outputAddresses: _addresses.outputs, }; } else if (_sum.inputs > 0 && _sum.outputs === 0) { result = { type: 'sent', amount: Number(_sum.inputs.toFixed(8)), - address: targetAddress, + address: isSelfSend.inputs && isSelfSend.outputs ? targetAddress : _addresses.outputs[0], timestamp: tx.timestamp, txid: tx.format.txid, confirmations: tx.confirmations, + inputAddresses: _addresses.inputs, + outputAddresses: _addresses.outputs, }; } else { // (?) result = { type: 'other', amount: 'unknown', - address: targetAddress, + address: 'unknown', timestamp: tx.timestamp, txid: tx.format.txid, confirmations: tx.confirmations, From e628f53e8bee4cdbd489f44ea2157fa46d3a8cd8 Mon Sep 17 00:00:00 2001 From: pbca26 Date: Wed, 21 Feb 2018 16:23:08 +0300 Subject: [PATCH 51/67] spv sendmany, elections update --- routes/shepherd.js | 2 + routes/shepherd/elections.js | 233 ++++++++-- routes/shepherd/electrum/createtx-multi.js | 500 +++++++++++++++++++++ routes/shepherd/electrum/createtx-split.js | 86 ++++ routes/shepherd/electrum/createtx.js | 172 +------ version | 4 +- version_build | 2 +- 7 files changed, 800 insertions(+), 199 deletions(-) create mode 100644 routes/shepherd/electrum/createtx-multi.js create mode 100644 routes/shepherd/electrum/createtx-split.js diff --git a/routes/shepherd.js b/routes/shepherd.js index 7e693ac..6564f53 100644 --- a/routes/shepherd.js +++ b/routes/shepherd.js @@ -94,6 +94,8 @@ shepherd = require('./shepherd/electrum/balance.js')(shepherd); shepherd = require('./shepherd/electrum/transactions.js')(shepherd); shepherd = require('./shepherd/electrum/block.js')(shepherd); shepherd = require('./shepherd/electrum/createtx.js')(shepherd); +shepherd = require('./shepherd/electrum/createtx-split.js')(shepherd); +shepherd = require('./shepherd/electrum/createtx-multi.js')(shepherd); shepherd = require('./shepherd/electrum/interest.js')(shepherd); shepherd = require('./shepherd/electrum/listunspent.js')(shepherd); shepherd = require('./shepherd/electrum/estimate.js')(shepherd); diff --git a/routes/shepherd/elections.js b/routes/shepherd/elections.js index d64ce5e..0b39369 100644 --- a/routes/shepherd/elections.js +++ b/routes/shepherd/elections.js @@ -40,33 +40,41 @@ module.exports = (shepherd) => { let keys; let isWif = false; - try { - bs58check.decode(_seed); - isWif = true; - } catch (e) {} - - if (isWif) { + if (_seed.match('^[a-zA-Z0-9]{34}$')) { + shepherd.log('watchonly elections pub addr'); + shepherd.elections = { + priv: _seed, + pub: _seed, + }; + } else { try { - let key = bitcoin.ECPair.fromWIF(_seed, shepherd.getNetworkData(_network.toLowerCase()), true); - keys = { - priv: key.toWIF(), - pub: key.getAddress(), - }; - } catch (e) { - _wifError = true; + bs58check.decode(_seed); + isWif = true; + } catch (e) {} + + if (isWif) { + try { + let key = bitcoin.ECPair.fromWIF(_seed, shepherd.getNetworkData(_network.toLowerCase()), true); + keys = { + priv: key.toWIF(), + pub: key.getAddress(), + }; + } catch (e) { + _wifError = true; + } + } else { + keys = shepherd.seedToWif(_seed, _network, req.body.iguana); } - } else { - keys = shepherd.seedToWif(_seed, _network, req.body.iguana); - } - shepherd.elections = { - priv: keys.priv, - pub: keys.pub, - }; + shepherd.elections = { + priv: keys.priv, + pub: keys.pub, + }; + } const successObj = { msg: 'success', - result: keys.pub, + result: shepherd.elections.pub, }; res.end(JSON.stringify(successObj)); @@ -100,6 +108,61 @@ module.exports = (shepherd) => { } }); + shepherd.electionsDecodeTx = (decodedTx, ecl, network, _network, transaction, blockInfo, address) => { + let txInputs = []; + + return new shepherd.Promise((resolve, reject) => { + if (decodedTx && + decodedTx.inputs) { + shepherd.Promise.all(decodedTx.inputs.map((_decodedInput, index) => { + return new shepherd.Promise((_resolve, _reject) => { + if (_decodedInput.txid !== '0000000000000000000000000000000000000000000000000000000000000000') { + ecl.blockchainTransactionGet(_decodedInput.txid) + .then((rawInput) => { + const decodedVinVout = shepherd.electrumJSTxDecoder(rawInput, network, _network); + + shepherd.log('electrum raw input tx ==>', true); + + if (decodedVinVout) { + shepherd.log(decodedVinVout.outputs[_decodedInput.n], true); + txInputs.push(decodedVinVout.outputs[_decodedInput.n]); + _resolve(true); + } else { + _resolve(true); + } + }); + } else { + _resolve(true); + } + }); + })) + .then(promiseResult => { + const _parsedTx = { + network: decodedTx.network, + format: decodedTx.format, + inputs: txInputs, + outputs: decodedTx.outputs, + height: transaction.height, + timestamp: Number(transaction.height) === 0 ? Math.floor(Date.now() / 1000) : blockInfo.timestamp, + }; + + resolve(shepherd.parseTransactionAddresses(_parsedTx, address, network, true)); + }); + } else { + const _parsedTx = { + network: decodedTx.network, + format: 'cant parse', + inputs: 'cant parse', + outputs: 'cant parse', + height: transaction.height, + timestamp: Number(transaction.height) === 0 ? Math.floor(Date.now() / 1000) : blockInfo.timestamp, + }; + + resolve(shepherd.parseTransactionAddresses(_parsedTx, address, network)); + } + }); + }; + shepherd.get('/elections/listtransactions', (req, res, next) => { if (shepherd.checkToken(req.query.token)) { const network = req.query.network || shepherd.findNetworkObj(req.query.coin); @@ -116,10 +179,11 @@ module.exports = (shepherd) => { .then((json) => { if (json && json.length) { - json = shepherd.sortTransactions(json); - json = json.length > MAX_TX ? json.slice(0, MAX_TX) : json; let _rawtx = []; + json = shepherd.sortTransactions(json); + // json = json.length > MAX_TX ? json.slice(0, MAX_TX) : json; + shepherd.log(json.length, true); shepherd.Promise.all(json.map((transaction, index) => { @@ -130,9 +194,9 @@ module.exports = (shepherd) => { blockInfo.timestamp) { ecl.blockchainTransactionGet(transaction['tx_hash']) .then((_rawtxJSON) => { - shepherd.log('electrum gettransaction ==>', true); - shepherd.log((index + ' | ' + (_rawtxJSON.length - 1)), true); - shepherd.log(_rawtxJSON, true); + //shepherd.log('electrum gettransaction ==>', true); + //shepherd.log((index + ' | ' + (_rawtxJSON.length - 1)), true); + //shepherd.log(_rawtxJSON, true); // decode tx const _network = shepherd.getNetworkData(network); @@ -162,35 +226,112 @@ module.exports = (shepherd) => { decodedTx.outputs[i].scriptPubKey.addresses && decodedTx.outputs[i].scriptPubKey.addresses[0] && decodedTx.outputs[i].scriptPubKey.addresses[0] !== _address) { - shepherd.log(`i voted ${decodedTx.outputs[i].value} for ${decodedTx.outputs[i].scriptPubKey.addresses[0]}`); - _rawtx.push({ - address: decodedTx.outputs[i].scriptPubKey.addresses[0], - amount: decodedTx.outputs[i].value, - region: _region, - timestamp: blockInfo.timestamp, - }); + if (_region === 'ne2k18-na-1-eu-2-ae-3-sh-4') { + const _regionsLookup = [ + 'ne2k18-na', + 'ne2k18-eu', + 'ne2k18-ae', + 'ne2k18-sh' + ]; + + shepherd.log(`i voted ${decodedTx.outputs[i].value} for ${decodedTx.outputs[i].scriptPubKey.addresses[0]}`); + _rawtx.push({ + address: decodedTx.outputs[i].scriptPubKey.addresses[0], + amount: decodedTx.outputs[i].value, + region: _regionsLookup[i], + timestamp: blockInfo.timestamp, + }); + resolve(true); + } else { + shepherd.log(`i voted ${decodedTx.outputs[i].value} for ${decodedTx.outputs[i].scriptPubKey.addresses[0]}`); + _rawtx.push({ + address: decodedTx.outputs[i].scriptPubKey.addresses[0], + amount: decodedTx.outputs[i].value, + region: _region, + timestamp: blockInfo.timestamp, + }); + resolve(true); + } } if (type === 'candidate') { - if (decodedTx.outputs[i].scriptPubKey.addresses[0] === _address) { - _candidate.amount = decodedTx.outputs[i].value; - } else if (decodedTx.outputs[i].scriptPubKey.addresses[0] !== _address && decodedTx.outputs[i].scriptPubKey.asm.indexOf('OP_RETURN') === -1) { - _candidate.address = decodedTx.outputs[i].scriptPubKey.addresses[0]; - _candidate.region = _region; - _candidate.timestamp = blockInfo.timestamp; - } - - if (i === decodedTx.outputs.length - 1) { - shepherd.log(`i received ${_candidate.amount} from ${_candidate.address}`); - _rawtx.push(_candidate); + if (_region === 'ne2k18-na-1-eu-2-ae-3-sh-4') { + if (decodedTx.outputs[i].scriptPubKey.addresses[0] === _address && decodedTx.outputs[i].scriptPubKey.asm.indexOf('OP_RETURN') === -1) { + const _regionsLookup = [ + 'ne2k18-na', + 'ne2k18-eu', + 'ne2k18-ae', + 'ne2k18-sh' + ]; + + shepherd.electionsDecodeTx(decodedTx, ecl, network, _network, transaction, blockInfo, _address) + .then((res) => { + shepherd.log(`i received ${decodedTx.outputs[i].value} from ${res.outputAddresses[0]} out ${i} region ${_regionsLookup[i]}`); + _rawtx.push({ + address: res.outputAddresses[0], + timestamp: blockInfo.timestamp, + amount: decodedTx.outputs[i].value, + region: _regionsLookup[i], + }); + resolve(true); + }); + } + } else { + shepherd.electionsDecodeTx(decodedTx, ecl, network, _network, transaction, blockInfo, _address) + .then((res) => { + if (decodedTx.outputs[i].scriptPubKey.addresses[0] === _address) { + _candidate.amount = decodedTx.outputs[i].value; + } else if (decodedTx.outputs[i].scriptPubKey.addresses[0] !== _address && decodedTx.outputs[i].scriptPubKey.asm.indexOf('OP_RETURN') === -1) { + _candidate.address = decodedTx.outputs[i].scriptPubKey.addresses[0]; + _candidate.region = _region; + _candidate.timestamp = blockInfo.timestamp; + } + + if (i === decodedTx.outputs.length - 1) { + shepherd.log(`i received ${_candidate.amount} from ${_candidate.address} region ${_region}`); + _rawtx.push(_candidate); + resolve(true); + } + }); } } } + } else { + shepherd.log('elections regular tx', true); + shepherd.electionsDecodeTx(decodedTx, ecl, network, _network, transaction, blockInfo, _address) + .then((_regularTx) => { + if (_regularTx[0] && + _regularTx[1]) { + _rawtx.push({ + address: _regularTx[type === 'voter' ? 0 : 1].address, + timestamp: _regularTx[type === 'voter' ? 0 : 1].timestamp, + amount: _regularTx[type === 'voter' ? 0 : 1].amount, + region: 'unknown', + regularTx: true, + hash: transaction['tx_hash'], + }); + } else { + _rawtx.push({ + address: _regularTx.address, + timestamp: _regularTx.timestamp, + amount: _regularTx.amount, + region: 'unknown', + regularTx: true, + hash: transaction['tx_hash'], + }); + } + resolve(true); + }); } - - resolve(true); }); } else { + _rawtx.push({ + address: 'unknown', + timestamp: 'cant get block info', + amount: 'unknown', + region: 'unknown', + regularTx: true, + }); resolve(false); } }); diff --git a/routes/shepherd/electrum/createtx-multi.js b/routes/shepherd/electrum/createtx-multi.js new file mode 100644 index 0000000..fbf613b --- /dev/null +++ b/routes/shepherd/electrum/createtx-multi.js @@ -0,0 +1,500 @@ +const bitcoinJSForks = require('bitcoinforksjs-lib'); +const bitcoinZcash = require('bitcoinjs-lib-zcash'); +const bitcoinPos = require('bitcoinjs-lib-pos'); + +// not prod ready, only for voting! +// needs a fix + +module.exports = (shepherd) => { + shepherd.post('/electrum/createrawtx-multiout', (req, res, next) => { + if (shepherd.checkToken(req.body.token)) { + // TODO: 1) unconf output(s) error message + // 2) check targets integrity + const network = req.body.network || shepherd.findNetworkObj(req.body.coin); + const ecl = new shepherd.electrumJSCore(shepherd.electrumServers[network].port, shepherd.electrumServers[network].address, shepherd.electrumServers[network].proto); // tcp or tls + const initTargets = JSON.parse(JSON.stringify(req.body.targets)); + let targets = req.body.targets; + const changeAddress = req.body.change; + const push = req.body.push; + const opreturn = req.body.opreturn; + const btcFee = req.body.btcfee ? Number(req.body.btcfee) : null; + let fee = shepherd.electrumServers[network].txfee; + let wif = req.body.wif; + + if (req.body.gui) { + wif = shepherd.electrumKeys[req.body.coin].priv; + } + + if (req.body.vote) { + wif = shepherd.elections.priv; + } + + if (btcFee) { + fee = 0; + } + + shepherd.log('electrum createrawtx =>', true); + + ecl.connect(); + shepherd.listunspent(ecl, changeAddress, network, true, req.body.verify === 'true' ? true : null) + .then((utxoList) => { + ecl.close(); + + if (utxoList && + utxoList.length && + utxoList[0] && + utxoList[0].txid) { + let utxoListFormatted = []; + let totalInterest = 0; + let totalInterestUTXOCount = 0; + let interestClaimThreshold = 200; + let utxoVerified = true; + + for (let i = 0; i < utxoList.length; i++) { + if (network === 'komodo') { + utxoListFormatted.push({ + txid: utxoList[i].txid, + vout: utxoList[i].vout, + value: Number(utxoList[i].amountSats), + interestSats: Number(utxoList[i].interestSats), + verified: utxoList[i].verified ? utxoList[i].verified : false, + }); + } else { + utxoListFormatted.push({ + txid: utxoList[i].txid, + vout: utxoList[i].vout, + value: Number(utxoList[i].amountSats), + verified: utxoList[i].verified ? utxoList[i].verified : false, + }); + } + } + + shepherd.log('electrum listunspent unformatted ==>', true); + shepherd.log(utxoList, true); + + shepherd.log('electrum listunspent formatted ==>', true); + shepherd.log(utxoListFormatted, true); + + const _maxSpendBalance = Number(shepherd.maxSpendBalance(utxoListFormatted)); + /*let targets = [{ + address: outputAddress, + value: value > _maxSpendBalance ? _maxSpendBalance : value, + }];*/ + shepherd.log('targets =>', true); + shepherd.log(targets, true); + + targets[0].value = targets[0].value + fee; + + shepherd.log(`default fee ${fee}`, true); + shepherd.log(`targets ==>`, true); + shepherd.log(targets, true); + + // default coin selection algo blackjack with fallback to accumulative + // make a first run, calc approx tx fee + // if ins and outs are empty reduce max spend by txfee + const firstRun = shepherd.coinSelect(utxoListFormatted, targets, btcFee ? btcFee : 0); + let inputs = firstRun.inputs; + let outputs = firstRun.outputs; + + if (btcFee) { + shepherd.log(`btc fee per byte ${btcFee}`, true); + fee = firstRun.fee; + } + + shepherd.log('coinselect res =>', true); + shepherd.log('coinselect inputs =>', true); + shepherd.log(inputs, true); + shepherd.log('coinselect outputs =>', true); + shepherd.log(outputs, true); + shepherd.log('coinselect calculated fee =>', true); + shepherd.log(fee, true); + + if (!outputs) { + targets[0].value = targets[0].value - fee; + shepherd.log('second run', true); + shepherd.log('coinselect adjusted targets =>', true); + shepherd.log(targets, true); + + const secondRun = shepherd.coinSelect(utxoListFormatted, targets, 0); + inputs = secondRun.inputs; + outputs = secondRun.outputs; + fee = fee ? fee : secondRun.fee; + + shepherd.log('second run coinselect inputs =>', true); + shepherd.log(inputs, true); + shepherd.log('second run coinselect outputs =>', true); + shepherd.log(outputs, true); + shepherd.log('second run coinselect fee =>', true); + shepherd.log(fee, true); + } + + let _change = 0; + + if (outputs && + outputs.length > 1) { + _change = outputs[outputs.length - 1].value - fee; + } + + if (!btcFee && + _change === 0) { + outputs[0].value = outputs[0].value - fee; + } + + shepherd.log('adjusted outputs'); + shepherd.log(outputs, true); + + shepherd.log('init targets', true); + shepherd.log(initTargets, true); + + if (initTargets[0].value < targets[0].value) { + targets[0].value = initTargets[0].value; + } + + let _targetsSum = 0; + + for (let i = 0; i < targets.length; i++) { + _targetsSum += Number(targets[i].value); + } + + shepherd.log(`total targets sum ${_targetsSum}`); + + /*if (btcFee) { + value = _targetsSum; + } else { + if (_change > 0) { + value = _targetsSum - fee; + } + }*/ + value = _targetsSum; + + shepherd.log('adjusted outputs, value - default fee =>', true); + shepherd.log(outputs, true); + + // check if any outputs are unverified + if (inputs && + inputs.length) { + for (let i = 0; i < inputs.length; i++) { + if (!inputs[i].verified) { + utxoVerified = false; + break; + } + } + + for (let i = 0; i < inputs.length; i++) { + if (Number(inputs[i].interestSats) > interestClaimThreshold) { + totalInterest += Number(inputs[i].interestSats); + totalInterestUTXOCount++; + } + } + } + + const _maxSpend = shepherd.maxSpendBalance(utxoListFormatted); + + if (value > _maxSpend) { + const successObj = { + msg: 'error', + result: `Spend value is too large. Max available amount is ${Number((_maxSpend * 0.00000001.toFixed(8)))}`, + }; + + res.end(JSON.stringify(successObj)); + } else { + shepherd.log(`maxspend ${_maxSpend} (${_maxSpend * 0.00000001})`, true); + shepherd.log(`value ${value}`, true); + // shepherd.log(`sendto ${outputAddress} amount ${value} (${value * 0.00000001})`, true); + shepherd.log(`changeto ${changeAddress} amount ${_change} (${_change * 0.00000001})`, true); + + // account for KMD interest + if (network === 'komodo' && + totalInterest > 0) { + // account for extra vout + // const _feeOverhead = outputs.length === 1 ? shepherd.estimateTxSize(0, 1) * feeRate : 0; + const _feeOverhead = 0; + + shepherd.log(`max interest to claim ${totalInterest} (${totalInterest * 0.00000001})`, true); + shepherd.log(`estimated fee overhead ${_feeOverhead}`, true); + shepherd.log(`current change amount ${_change} (${_change * 0.00000001}), boosted change amount ${_change + (totalInterest - _feeOverhead)} (${(_change + (totalInterest - _feeOverhead)) * 0.00000001})`, true); + + if (_maxSpend - fee === value) { + _change = totalInterest - _change - _feeOverhead; + + if (outputAddress === changeAddress) { + value += _change; + _change = 0; + shepherd.log(`send to self ${outputAddress} = ${changeAddress}`, true); + shepherd.log(`send to self old val ${value}, new val ${value + _change}`, true); + } + } else { + _change = _change + (totalInterest - _feeOverhead); + } + } + + if (!inputs && + !outputs) { + const successObj = { + msg: 'error', + result: 'Can\'t find best fit utxo. Try lower amount.', + }; + + res.end(JSON.stringify(successObj)); + } else { + let vinSum = 0; + + for (let i = 0; i < inputs.length; i++) { + vinSum += inputs[i].value; + } + + let voutSum = 0; + + for (let i = 0; i < outputs.length; i++) { + voutSum += outputs[i].value; + } + + const _estimatedFee = vinSum - voutSum; + + shepherd.log(`vin sum ${vinSum} (${vinSum * 0.00000001})`, true); + shepherd.log(`vout sum ${voutSum} (${voutSum * 0.00000001})`, true); + shepherd.log(`estimatedFee ${_estimatedFee} (${_estimatedFee * 0.00000001})`, true); + // double check no extra fee is applied + shepherd.log(`vin - vout - change ${vinSum - value - _change}`); + + if ((vinSum - value - _change) > fee) { + _change += fee; + shepherd.log(`double fee, increase change by ${fee}`); + shepherd.log(`adjusted vin - vout - change ${vinSum - value - _change}`); + } + + // TODO: use individual dust thresholds + if (_change > 0 && + _change <= 1000) { + shepherd.log(`change is < 1000 sats, donate ${_change} sats to miners`, true); + _change = 0; + } + + outputAddress = outputs; + + if (outputAddress.length > 1) { + outputAddress.pop(); + } + + let _rawtx; + + if (network === 'btg' || + network === 'bch') { + /*_rawtx = shepherd.buildSignedTxForks( + outputAddress, + changeAddress, + wif, + network, + inputs, + _change, + value + );*/ + } else { + _rawtx = shepherd.buildSignedTxMulti( + outputAddress, + changeAddress, + wif, + network, + inputs, + _change, + value, + opreturn + ); + } + + if (!push || + push === 'false') { + const successObj = { + msg: 'success', + result: { + utxoSet: inputs, + change: _change, + changeAdjusted: _change, + totalInterest, + // wif, + fee, + value, + outputAddress, + changeAddress, + network, + rawtx: _rawtx, + utxoVerified, + }, + }; + + res.end(JSON.stringify(successObj)); + } else { + const ecl = new shepherd.electrumJSCore(shepherd.electrumServers[network].port, shepherd.electrumServers[network].address, shepherd.electrumServers[network].proto); // tcp or tls + + ecl.connect(); + ecl.blockchainTransactionBroadcast(_rawtx) + .then((txid) => { + ecl.close(); + + const _rawObj = { + utxoSet: inputs, + change: _change, + changeAdjusted: _change, + totalInterest, + fee, + value, + outputAddress, + changeAddress, + network, + rawtx: _rawtx, + txid, + utxoVerified, + }; + + if (txid && + txid.indexOf('bad-txns-inputs-spent') > -1) { + const successObj = { + msg: 'error', + result: 'Bad transaction inputs spent', + raw: _rawObj, + }; + + res.end(JSON.stringify(successObj)); + } else { + if (txid && + txid.length === 64) { + if (txid.indexOf('bad-txns-in-belowout') > -1) { + const successObj = { + msg: 'error', + result: 'Bad transaction inputs spent', + raw: _rawObj, + }; + + res.end(JSON.stringify(successObj)); + } else { + const successObj = { + msg: 'success', + result: _rawObj, + }; + + res.end(JSON.stringify(successObj)); + } + } else { + if (txid && + txid.indexOf('bad-txns-in-belowout') > -1) { + const successObj = { + msg: 'error', + result: 'Bad transaction inputs spent', + raw: _rawObj, + }; + + res.end(JSON.stringify(successObj)); + } else { + const successObj = { + msg: 'error', + result: 'Can\'t broadcast transaction', + raw: _rawObj, + }; + + res.end(JSON.stringify(successObj)); + } + } + } + }); + } + } + } + } else { + const successObj = { + msg: 'error', + result: utxoList, + }; + + res.end(JSON.stringify(successObj)); + } + }); + } else { + const errorObj = { + msg: 'error', + result: 'unauthorized access', + }; + + res.end(JSON.stringify(errorObj)); + } + }); + + // single sig + shepherd.buildSignedTxMulti = (sendTo, changeAddress, wif, network, utxo, changeValue, spendValue, opreturn) => { + let key = shepherd.isZcash(network) ? bitcoinZcash.ECPair.fromWIF(wif, shepherd.getNetworkData(network)) : shepherd.bitcoinJS.ECPair.fromWIF(wif, shepherd.getNetworkData(network)); + let tx; + + if (shepherd.isZcash(network)) { + tx = new bitcoinZcash.TransactionBuilder(shepherd.getNetworkData(network)); + } else if (shepherd.isPos(network)) { + tx = new bitcoinPos.TransactionBuilder(shepherd.getNetworkData(network)); + } else { + tx = new shepherd.bitcoinJS.TransactionBuilder(shepherd.getNetworkData(network)); + } + + shepherd.log('buildSignedTx', true); + // console.log(`buildSignedTx priv key ${wif}`); + shepherd.log(`buildSignedTx pub key ${key.getAddress().toString()}`, true); + // console.log('buildSignedTx std tx fee ' + shepherd.electrumServers[network].txfee); + + for (let i = 0; i < utxo.length; i++) { + tx.addInput(utxo[i].txid, utxo[i].vout); + } + + for (let i = 0; i < sendTo.length; i++) { + if (shepherd.isPos(network)) { + tx.addOutput(sendTo[i].address, Number(sendTo[i].value), shepherd.getNetworkData(network)); + } else { + tx.addOutput(sendTo[i].address, Number(sendTo[i].value)); + } + } + + if (changeValue > 0) { + if (shepherd.isPos(network)) { + tx.addOutput(changeAddress, Number(changeValue), shepherd.getNetworkData(network)); + } else { + tx.addOutput(changeAddress, Number(changeValue)); + } + } + + if (opreturn && + opreturn.length) { + for (let i = 0; i < opreturn.length; i++) { + shepherd.log(`opreturn ${i} ${opreturn[i]}`); + const data = Buffer.from(opreturn[i], 'utf8'); + const dataScript = shepherd.bitcoinJS.script.nullData.output.encode(data); + tx.addOutput(dataScript, 1000); + } + } + + if (network === 'komodo' || + network === 'KMD') { + const _locktime = Math.floor(Date.now() / 1000) - 777; + tx.setLockTime(_locktime); + shepherd.log(`kmd tx locktime set to ${_locktime}`, true); + } + + shepherd.log('buildSignedTx unsigned tx data vin', true); + shepherd.log(tx.tx.ins, true); + shepherd.log('buildSignedTx unsigned tx data vout', true); + shepherd.log(tx.tx.outs, true); + shepherd.log('buildSignedTx unsigned tx data', true); + shepherd.log(tx, true); + + for (let i = 0; i < utxo.length; i++) { + if (shepherd.isPos(network)) { + tx.sign(shepherd.getNetworkData(network), i, key); + } else { + tx.sign(i, key); + } + } + + const rawtx = tx.build().toHex(); + + shepherd.log('buildSignedTx signed tx hex', true); + shepherd.log(rawtx, true); + + return rawtx; + } + + return shepherd; +}; \ No newline at end of file diff --git a/routes/shepherd/electrum/createtx-split.js b/routes/shepherd/electrum/createtx-split.js new file mode 100644 index 0000000..c161a62 --- /dev/null +++ b/routes/shepherd/electrum/createtx-split.js @@ -0,0 +1,86 @@ +const bitcoinJSForks = require('bitcoinforksjs-lib'); +const bitcoinZcash = require('bitcoinjs-lib-zcash'); +const bitcoinPos = require('bitcoinjs-lib-pos'); + +module.exports = (shepherd) => { + // utxo split 1 -> 1, multiple outputs + shepherd.post('/electrum/createrawtx-split', (req, res, next) => { + if (shepherd.checkToken(req.body.token)) { + const wif = req.body.payload.wif; + const utxo = req.body.payload.utxo; + const targets = req.body.payload.targets; + const network = req.body.payload.network; + const change = req.body.payload.change; + const outputAddress = req.body.payload.outputAddress; + const changeAddress = req.body.payload.changeAddress; + + let key = shepherd.isZcash(network) ? bitcoinZcash.ECPair.fromWIF(wif, shepherd.getNetworkData(network)) : shepherd.bitcoinJS.ECPair.fromWIF(wif, shepherd.getNetworkData(network)); + let tx; + + if (shepherd.isZcash(network)) { + tx = new bitcoinZcash.TransactionBuilder(shepherd.getNetworkData(network)); + } else if (shepherd.isPos(network)) { + tx = new bitcoinPos.TransactionBuilder(shepherd.getNetworkData(network)); + } else { + tx = new shepherd.bitcoinJS.TransactionBuilder(shepherd.getNetworkData(network)); + } + + shepherd.log('buildSignedTx', true); + shepherd.log(`buildSignedTx pub key ${key.getAddress().toString()}`, true); + + for (let i = 0; i < utxo.length; i++) { + tx.addInput(utxo[i].txid, utxo[i].vout); + } + + for (let i = 0; i < targets.length; i++) { + if (shepherd.isPos(network)) { + tx.addOutput(outputAddress, Number(targets[i]), shepherd.getNetworkData(network)); + } else { + tx.addOutput(outputAddress, Number(targets[i])); + } + } + + if (Number(change) > 0) { + if (shepherd.isPos(network)) { + tx.addOutput(changeAddress, Number(change), shepherd.getNetworkData(network)); + } else { + shepherd.log(`change ${change}`, true); + tx.addOutput(changeAddress, Number(change)); + } + } + + if (network === 'komodo' || + network === 'KMD') { + const _locktime = Math.floor(Date.now() / 1000) - 777; + tx.setLockTime(_locktime); + shepherd.log(`kmd tx locktime set to ${_locktime}`, true); + } + + for (let i = 0; i < utxo.length; i++) { + if (shepherd.isPos(network)) { + tx.sign(shepherd.getNetworkData(network), i, key); + } else { + tx.sign(i, key); + } + } + + const rawtx = tx.build().toHex(); + + const successObj = { + msg: 'success', + result: rawtx, + }; + + res.end(JSON.stringify(successObj)); + } else { + const errorObj = { + msg: 'error', + result: 'unauthorized access', + }; + + res.end(JSON.stringify(errorObj)); + } + }); + + return shepherd; +}; \ No newline at end of file diff --git a/routes/shepherd/electrum/createtx.js b/routes/shepherd/electrum/createtx.js index ae2cb79..04b9795 100644 --- a/routes/shepherd/electrum/createtx.js +++ b/routes/shepherd/electrum/createtx.js @@ -424,7 +424,8 @@ module.exports = (shepherd) => { } // TODO: use individual dust thresholds - if (_change < 1000) { + if (_change > 0 && + _change <= 1000) { shepherd.log(`change is < 1000 sats, donate ${_change} sats to miners`, true); _change = 0; } @@ -497,25 +498,27 @@ module.exports = (shepherd) => { .then((txid) => { ecl.close(); + const _rawObj = { + utxoSet: inputs, + change: _change, + changeAdjusted: _change, + totalInterest, + fee, + value, + outputAddress, + changeAddress, + network, + rawtx: _rawtx, + txid, + utxoVerified, + }; + if (txid && txid.indexOf('bad-txns-inputs-spent') > -1) { const successObj = { msg: 'error', result: 'Bad transaction inputs spent', - raw: { - utxoSet: inputs, - change: _change, - changeAdjusted: _change, - totalInterest, - fee, - value, - outputAddress, - changeAddress, - network, - rawtx: _rawtx, - txid, - utxoVerified, - }, + raw: _rawObj, }; res.end(JSON.stringify(successObj)); @@ -526,41 +529,14 @@ module.exports = (shepherd) => { const successObj = { msg: 'error', result: 'Bad transaction inputs spent', - raw: { - utxoSet: inputs, - change: _change, - changeAdjusted: _change, - totalInterest, - fee, - value, - outputAddress, - changeAddress, - network, - rawtx: _rawtx, - txid, - utxoVerified, - }, + raw: _rawObj, }; res.end(JSON.stringify(successObj)); } else { const successObj = { msg: 'success', - result: { - utxoSet: inputs, - change: _change, - changeAdjusted: _change, - totalInterest, - fee, - // wif, - value, - outputAddress, - changeAddress, - network, - rawtx: _rawtx, - txid, - utxoVerified, - }, + result: _rawObj, }; res.end(JSON.stringify(successObj)); @@ -571,20 +547,7 @@ module.exports = (shepherd) => { const successObj = { msg: 'error', result: 'Bad transaction inputs spent', - raw: { - utxoSet: inputs, - change: _change, - changeAdjusted: _change, - totalInterest, - fee, - value, - outputAddress, - changeAddress, - network, - rawtx: _rawtx, - txid, - utxoVerified, - }, + raw: _rawObj, }; res.end(JSON.stringify(successObj)); @@ -592,20 +555,7 @@ module.exports = (shepherd) => { const successObj = { msg: 'error', result: 'Can\'t broadcast transaction', - raw: { - utxoSet: inputs, - change: _change, - changeAdjusted: _change, - totalInterest, - fee, - value, - outputAddress, - changeAddress, - network, - rawtx: _rawtx, - txid, - utxoVerified, - }, + raw: _rawObj, }; res.end(JSON.stringify(successObj)); @@ -665,83 +615,5 @@ module.exports = (shepherd) => { } }); - shepherd.post('/electrum/createrawtx-test', (req, res, next) => { - if (shepherd.checkToken(req.body.token)) { - const wif = req.body.payload.wif; - const utxo = req.body.payload.utxo; - const targets = req.body.payload.targets; - const network = req.body.payload.network; - const change = req.body.payload.change; - const outputAddress = req.body.payload.outputAddress; - const changeAddress = req.body.payload.changeAddress; - - let key = shepherd.isZcash(network) ? bitcoinZcash.ECPair.fromWIF(wif, shepherd.getNetworkData(network)) : shepherd.bitcoinJS.ECPair.fromWIF(wif, shepherd.getNetworkData(network)); - let tx; - - if (shepherd.isZcash(network)) { - tx = new bitcoinZcash.TransactionBuilder(shepherd.getNetworkData(network)); - } else if (shepherd.isPos(network)) { - tx = new bitcoinPos.TransactionBuilder(shepherd.getNetworkData(network)); - } else { - tx = new shepherd.bitcoinJS.TransactionBuilder(shepherd.getNetworkData(network)); - } - - shepherd.log('buildSignedTx', true); - shepherd.log(`buildSignedTx pub key ${key.getAddress().toString()}`, true); - - for (let i = 0; i < utxo.length; i++) { - tx.addInput(utxo[i].txid, utxo[i].vout); - } - - for (let i = 0; i < targets.length; i++) { - if (shepherd.isPos(network)) { - tx.addOutput(outputAddress, Number(targets[i]), shepherd.getNetworkData(network)); - } else { - tx.addOutput(outputAddress, Number(targets[i])); - } - } - - if (Number(change) > 0) { - if (shepherd.isPos(network)) { - tx.addOutput(changeAddress, Number(change), shepherd.getNetworkData(network)); - } else { - shepherd.log(`change ${change}`, true); - tx.addOutput(changeAddress, Number(change)); - } - } - - if (network === 'komodo' || - network === 'KMD') { - const _locktime = Math.floor(Date.now() / 1000) - 777; - tx.setLockTime(_locktime); - shepherd.log(`kmd tx locktime set to ${_locktime}`, true); - } - - for (let i = 0; i < utxo.length; i++) { - if (shepherd.isPos(network)) { - tx.sign(shepherd.getNetworkData(network), i, key); - } else { - tx.sign(i, key); - } - } - - const rawtx = tx.build().toHex(); - - const successObj = { - msg: 'success', - result: rawtx, - }; - - res.end(JSON.stringify(successObj)); - } else { - const errorObj = { - msg: 'error', - result: 'unauthorized access', - }; - - res.end(JSON.stringify(errorObj)); - } - }); - return shepherd; }; \ No newline at end of file diff --git a/version b/version index 0a74b63..77d4194 100644 --- a/version +++ b/version @@ -1,3 +1,3 @@ -version=0.2.0.28b -type=b-beta +version=0.2.0.28c +type=c-beta minversion=0.2.0.28 \ No newline at end of file diff --git a/version_build b/version_build index fea66b8..64427e2 100644 --- a/version_build +++ b/version_build @@ -1 +1 @@ -0.2.0.28b-beta \ No newline at end of file +0.2.0.28c-beta \ No newline at end of file From 320d2a83528b9b152ed9b7c15f226b69bb404ad0 Mon Sep 17 00:00:00 2001 From: pbca26 Date: Wed, 21 Feb 2018 20:17:45 +0300 Subject: [PATCH 52/67] elections listtransactions non op return tx fix --- routes/shepherd/elections.js | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/routes/shepherd/elections.js b/routes/shepherd/elections.js index 0b39369..8f65f7f 100644 --- a/routes/shepherd/elections.js +++ b/routes/shepherd/elections.js @@ -303,7 +303,7 @@ module.exports = (shepherd) => { if (_regularTx[0] && _regularTx[1]) { _rawtx.push({ - address: _regularTx[type === 'voter' ? 0 : 1].address, + address: _regularTx[type === 'voter' ? 0 : 1].address || 'self', timestamp: _regularTx[type === 'voter' ? 0 : 1].timestamp, amount: _regularTx[type === 'voter' ? 0 : 1].amount, region: 'unknown', @@ -311,14 +311,16 @@ module.exports = (shepherd) => { hash: transaction['tx_hash'], }); } else { - _rawtx.push({ - address: _regularTx.address, - timestamp: _regularTx.timestamp, - amount: _regularTx.amount, - region: 'unknown', - regularTx: true, - hash: transaction['tx_hash'], - }); + if ((type === 'voter' && _regularTx.type !== 'received') && (type === 'candidate' && _regularTx.type !== 'sent')) { + _rawtx.push({ + address: _regularTx.address || 'self', + timestamp: _regularTx.timestamp, + amount: _regularTx.amount, + region: 'unknown', + regularTx: true, + hash: transaction['tx_hash'], + }); + } } resolve(true); }); From 2da2893874a529cb12bc04e9e41be31693dde109 Mon Sep 17 00:00:00 2001 From: pbca26 Date: Thu, 22 Feb 2018 18:15:56 +0300 Subject: [PATCH 53/67] vote port --- routes/ports.js | 1 + 1 file changed, 1 insertion(+) diff --git a/routes/ports.js b/routes/ports.js index 9601893..4bbf44c 100644 --- a/routes/ports.js +++ b/routes/ports.js @@ -24,6 +24,7 @@ const assetChainPorts = { 'MESH': '9455', 'AXO': '12927', 'ETOMIC': '10271', + 'VOTE': '8012', 'BTCH': '8800', 'USD': '13967', 'CHF': '15312', From 9be667edaff8f6325d9e905777cfa4750d5228bf Mon Sep 17 00:00:00 2001 From: pbca26 Date: Thu, 22 Feb 2018 19:08:20 +0300 Subject: [PATCH 54/67] bump ltc fee to 100k --- routes/electrumjs/electrumServers.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/routes/electrumjs/electrumServers.js b/routes/electrumjs/electrumServers.js index e0d01cc..0548596 100644 --- a/routes/electrumjs/electrumServers.js +++ b/routes/electrumjs/electrumServers.js @@ -272,7 +272,7 @@ let electrumServers = { address: '173.212.225.176', port: 50012, proto: 'tcp', - txfee: 30000, + txfee: 100000, abbr: 'LTC', serverList: [ '173.212.225.176:50012', From 00c1617e82ba6a93ed2bc20f2499e8031282ccfb Mon Sep 17 00:00:00 2001 From: pbca26 Date: Fri, 23 Feb 2018 23:16:44 +0300 Subject: [PATCH 55/67] refactor spv tx history to use async series --- package.json | 1 + routes/shepherd/electrum/transactions.js | 193 +++++++++++++++-------- 2 files changed, 132 insertions(+), 62 deletions(-) diff --git a/package.json b/package.json index dddbab3..9dbf4fe 100644 --- a/package.json +++ b/package.json @@ -30,6 +30,7 @@ "dependencies": { "adm-zip": "^0.4.7", "arch": "^2.1.0", + "async": "^2.6.0", "bigi": "^1.4.2", "bip39": "^2.4.0", "bitcoinforksjs-lib": "git://github.com/bitcoinjs/bitcoinjs-lib#opt-in-bitcoincash-sighash", diff --git a/routes/shepherd/electrum/transactions.js b/routes/shepherd/electrum/transactions.js index 4864e96..4b2209e 100644 --- a/routes/shepherd/electrum/transactions.js +++ b/routes/shepherd/electrum/transactions.js @@ -1,3 +1,5 @@ +const async = require('async'); + module.exports = (shepherd) => { shepherd.sortTransactions = (transactions) => { return transactions.sort((b, a) => { @@ -51,14 +53,16 @@ module.exports = (shepherd) => { if (json && json.length) { let _rawtx = []; + let _inputTxs = {}; json = shepherd.sortTransactions(json); json = json.length > MAX_TX ? json.slice(0, MAX_TX) : json; shepherd.log(json.length, true); - - shepherd.Promise.all(json.map((transaction, index) => { - return new shepherd.Promise((resolve, reject) => { + let index = 0; + async.eachOfSeries(json, (transaction, ind, callback) => { + console.log(`index ${index}`); + //return new shepherd.Promise((resolve, reject) => { ecl.blockchainBlockGetHeader(transaction.height) .then((blockInfo) => { if (blockInfo && @@ -79,72 +83,113 @@ module.exports = (shepherd) => { shepherd.log('decodedtx =>', true); shepherd.log(decodedTx.outputs, true); + let index2 = 0; if (decodedTx && decodedTx.inputs) { - shepherd.Promise.all(decodedTx.inputs.map((_decodedInput, index) => { - return new shepherd.Promise((_resolve, _reject) => { + async.eachOfSeries(decodedTx.inputs, (_decodedInput, index2, callback2) => { + //shepherd.Promise.all(decodedTx.inputs.map((_decodedInput, index) => { + //return new shepherd.Promise((_resolve, _reject) => { if (_decodedInput.txid !== '0000000000000000000000000000000000000000000000000000000000000000') { - ecl.blockchainTransactionGet(_decodedInput.txid) - .then((rawInput) => { - const decodedVinVout = shepherd.electrumJSTxDecoder(rawInput, network, _network); - - shepherd.log('electrum raw input tx ==>', true); + if (!_inputTxs[_decodedInput.txid]) { + ecl.blockchainTransactionGet(_decodedInput.txid) + .then((rawInput) => { + _inputTxs[_decodedInput.txid] = rawInput; + + const decodedVinVout = shepherd.electrumJSTxDecoder(rawInput, network, _network); + + shepherd.log(`electrum raw input tx ${_decodedInput.txid} ==>`, true); + + if (decodedVinVout) { + shepherd.log(decodedVinVout.outputs[_decodedInput.n], true); + txInputs.push(decodedVinVout.outputs[_decodedInput.n]); + index2++; + callback2(); + } else { + index2++; + callback2(); + } + }); + } else { + const decodedVinVout = shepherd.electrumJSTxDecoder(_inputTxs[_decodedInput.txid], network, _network); + + shepherd.log(`electrum raw one time cached input tx ${_decodedInput.txid} ==>`, true); if (decodedVinVout) { shepherd.log(decodedVinVout.outputs[_decodedInput.n], true); txInputs.push(decodedVinVout.outputs[_decodedInput.n]); - _resolve(true); + index2++; + callback2(); } else { - _resolve(true); + index2++; + callback2(); } - }); + } } else { - _resolve(true); + index2++; + callback2(); + } + + console.log(`${index2} | ${decodedTx.inputs.length - 1} => main callback`); + if (index2 === decodedTx.inputs.length - 1) { + index++; + const _parsedTx = { + network: decodedTx.network, + format: decodedTx.format, + inputs: txInputs, + outputs: decodedTx.outputs, + height: transaction.height, + timestamp: Number(transaction.height) === 0 ? Math.floor(Date.now() / 1000) : blockInfo.timestamp, + confirmations: Number(transaction.height) === 0 ? 0 : currentHeight - transaction.height, + }; + + const formattedTx = shepherd.parseTransactionAddresses(_parsedTx, req.query.address, network); + + if (formattedTx.type) { + formattedTx.height = transaction.height; + formattedTx.blocktime = blockInfo.timestamp; + formattedTx.timereceived = blockInfo.timereceived; + formattedTx.hex = _rawtxJSON; + formattedTx.inputs = decodedTx.inputs; + formattedTx.outputs = decodedTx.outputs; + formattedTx.locktime = decodedTx.format.locktime; + _rawtx.push(formattedTx); + } else { + formattedTx[0].height = transaction.height; + formattedTx[0].blocktime = blockInfo.timestamp; + formattedTx[0].timereceived = blockInfo.timereceived; + formattedTx[0].hex = _rawtxJSON; + formattedTx[0].inputs = decodedTx.inputs; + formattedTx[0].outputs = decodedTx.outputs; + formattedTx[0].locktime = decodedTx.format.locktime; + formattedTx[1].height = transaction.height; + formattedTx[1].blocktime = blockInfo.timestamp; + formattedTx[1].timereceived = blockInfo.timereceived; + formattedTx[1].hex = _rawtxJSON; + formattedTx[1].inputs = decodedTx.inputs; + formattedTx[1].outputs = decodedTx.outputs; + formattedTx[1].locktime = decodedTx.format.locktime; + _rawtx.push(formattedTx[0]); + _rawtx.push(formattedTx[1]); + } + callback(); } - }); - })) - .then(promiseResult => { - const _parsedTx = { - network: decodedTx.network, - format: decodedTx.format, - inputs: txInputs, - outputs: decodedTx.outputs, - height: transaction.height, - timestamp: Number(transaction.height) === 0 ? Math.floor(Date.now() / 1000) : blockInfo.timestamp, - confirmations: Number(transaction.height) === 0 ? 0 : currentHeight - transaction.height, - }; - const formattedTx = shepherd.parseTransactionAddresses(_parsedTx, req.query.address, network); - - if (formattedTx.type) { - formattedTx.height = transaction.height; - formattedTx.blocktime = blockInfo.timestamp; - formattedTx.timereceived = blockInfo.timereceived; - formattedTx.hex = _rawtxJSON; - formattedTx.inputs = decodedTx.inputs; - formattedTx.outputs = decodedTx.outputs; - formattedTx.locktime = decodedTx.format.locktime; - _rawtx.push(formattedTx); - } else { - formattedTx[0].height = transaction.height; - formattedTx[0].blocktime = blockInfo.timestamp; - formattedTx[0].timereceived = blockInfo.timereceived; - formattedTx[0].hex = _rawtxJSON; - formattedTx[0].inputs = decodedTx.inputs; - formattedTx[0].outputs = decodedTx.outputs; - formattedTx[0].locktime = decodedTx.format.locktime; - formattedTx[1].height = transaction.height; - formattedTx[1].blocktime = blockInfo.timestamp; - formattedTx[1].timereceived = blockInfo.timereceived; - formattedTx[1].hex = _rawtxJSON; - formattedTx[1].inputs = decodedTx.inputs; - formattedTx[1].outputs = decodedTx.outputs; - formattedTx[1].locktime = decodedTx.format.locktime; - _rawtx.push(formattedTx[0]); - _rawtx.push(formattedTx[1]); - } - resolve(true); + if (index === json.length) { + ecl.close(); + + const successObj = { + msg: 'success', + result: _rawtx, + }; + + res.end(JSON.stringify(successObj)); + } + //}); }); + /*.then(promiseResult => { + + resolve(true); + });*/ } else { const _parsedTx = { network: decodedTx.network, @@ -158,7 +203,19 @@ module.exports = (shepherd) => { const formattedTx = shepherd.parseTransactionAddresses(_parsedTx, req.query.address, network); _rawtx.push(formattedTx); - resolve(true); + index++; + callback(); + + if (index === json.length) { + ecl.close(); + + const successObj = { + msg: 'success', + result: _rawtx, + }; + + res.end(JSON.stringify(successObj)); + } } }); } else { @@ -173,12 +230,24 @@ module.exports = (shepherd) => { }; const formattedTx = shepherd.parseTransactionAddresses(_parsedTx, req.query.address, network); _rawtx.push(formattedTx); - resolve(true); + callback(); + index++; } }); - }); - })) - .then(promiseResult => { + //}); + + if (index === json.length) { + ecl.close(); + + const successObj = { + msg: 'success', + result: _rawtx, + }; + + res.end(JSON.stringify(successObj)); + } + }); + /*.then(promiseResult => { ecl.close(); const successObj = { @@ -187,7 +256,7 @@ module.exports = (shepherd) => { }; res.end(JSON.stringify(successObj)); - }); + });*/ } else { ecl.close(); From 8f2efde62925d7bdb569bde6660604b629d26ba4 Mon Sep 17 00:00:00 2001 From: pbca26 Date: Sat, 24 Feb 2018 20:16:51 +0300 Subject: [PATCH 56/67] spv transaction history use one time caching --- routes/shepherd/electrum/transactions.js | 348 +++++++++++------------ 1 file changed, 173 insertions(+), 175 deletions(-) diff --git a/routes/shepherd/electrum/transactions.js b/routes/shepherd/electrum/transactions.js index 4b2209e..68a66d6 100644 --- a/routes/shepherd/electrum/transactions.js +++ b/routes/shepherd/electrum/transactions.js @@ -60,119 +60,94 @@ module.exports = (shepherd) => { shepherd.log(json.length, true); let index = 0; + + const _getTransaction = (txid) => { + return new shepherd.Promise((resolve, reject) => { + if (!_inputTxs[txid]) { + ecl.blockchainTransactionGet(txid) + .then((_rawtxJSON) => { + resolve(_rawtxJSON); + }); + } else { + resolve(_inputTxs[txid]); + } + }); + } ; + async.eachOfSeries(json, (transaction, ind, callback) => { - console.log(`index ${index}`); - //return new shepherd.Promise((resolve, reject) => { - ecl.blockchainBlockGetHeader(transaction.height) - .then((blockInfo) => { - if (blockInfo && - blockInfo.timestamp) { - ecl.blockchainTransactionGet(transaction['tx_hash']) - .then((_rawtxJSON) => { - shepherd.log('electrum gettransaction ==>', true); - shepherd.log((index + ' | ' + (_rawtxJSON.length - 1)), true); - shepherd.log(_rawtxJSON, true); - - // decode tx - const _network = shepherd.getNetworkData(network); - const decodedTx = shepherd.electrumJSTxDecoder(_rawtxJSON, network, _network); - - let txInputs = []; - shepherd.log(`decodedtx network ${network}`, true); - - shepherd.log('decodedtx =>', true); - shepherd.log(decodedTx.outputs, true); - - let index2 = 0; - if (decodedTx && - decodedTx.inputs) { - async.eachOfSeries(decodedTx.inputs, (_decodedInput, index2, callback2) => { - //shepherd.Promise.all(decodedTx.inputs.map((_decodedInput, index) => { - //return new shepherd.Promise((_resolve, _reject) => { - if (_decodedInput.txid !== '0000000000000000000000000000000000000000000000000000000000000000') { - if (!_inputTxs[_decodedInput.txid]) { - ecl.blockchainTransactionGet(_decodedInput.txid) - .then((rawInput) => { - _inputTxs[_decodedInput.txid] = rawInput; - - const decodedVinVout = shepherd.electrumJSTxDecoder(rawInput, network, _network); - - shepherd.log(`electrum raw input tx ${_decodedInput.txid} ==>`, true); - - if (decodedVinVout) { - shepherd.log(decodedVinVout.outputs[_decodedInput.n], true); - txInputs.push(decodedVinVout.outputs[_decodedInput.n]); - index2++; - callback2(); - } else { - index2++; - callback2(); - } - }); - } else { - const decodedVinVout = shepherd.electrumJSTxDecoder(_inputTxs[_decodedInput.txid], network, _network); - - shepherd.log(`electrum raw one time cached input tx ${_decodedInput.txid} ==>`, true); - - if (decodedVinVout) { - shepherd.log(decodedVinVout.outputs[_decodedInput.n], true); - txInputs.push(decodedVinVout.outputs[_decodedInput.n]); - index2++; - callback2(); - } else { - index2++; - callback2(); - } - } - } else { - index2++; - callback2(); - } + ecl.blockchainBlockGetHeader(transaction.height) + .then((blockInfo) => { + if (blockInfo && + blockInfo.timestamp) { + _getTransaction(transaction['tx_hash']) + .then((_rawtxJSON) => { + if (!_inputTxs[transaction['tx_hash']]) { + _inputTxs[transaction['tx_hash']] = _rawtxJSON; + } + shepherd.log('electrum gettransaction ==>', true); + shepherd.log((index + ' | ' + (_rawtxJSON.length - 1)), true); + // shepherd.log(_rawtxJSON, true); + + // decode tx + const _network = shepherd.getNetworkData(network); + const decodedTx = shepherd.electrumJSTxDecoder(_rawtxJSON, network, _network); + + let txInputs = []; + shepherd.log(`decodedtx network ${network}`, true); + + shepherd.log('decodedtx =>', true); + // shepherd.log(decodedTx.outputs, true); + + let index2 = 0; + if (decodedTx && + decodedTx.inputs && + decodedTx.inputs.length) { + async.eachOfSeries(decodedTx.inputs, (_decodedInput, ind2, callback2) => { + function checkLoop() { + index2++; - console.log(`${index2} | ${decodedTx.inputs.length - 1} => main callback`); - if (index2 === decodedTx.inputs.length - 1) { - index++; - const _parsedTx = { - network: decodedTx.network, - format: decodedTx.format, - inputs: txInputs, - outputs: decodedTx.outputs, - height: transaction.height, - timestamp: Number(transaction.height) === 0 ? Math.floor(Date.now() / 1000) : blockInfo.timestamp, - confirmations: Number(transaction.height) === 0 ? 0 : currentHeight - transaction.height, - }; - - const formattedTx = shepherd.parseTransactionAddresses(_parsedTx, req.query.address, network); - - if (formattedTx.type) { - formattedTx.height = transaction.height; - formattedTx.blocktime = blockInfo.timestamp; - formattedTx.timereceived = blockInfo.timereceived; - formattedTx.hex = _rawtxJSON; - formattedTx.inputs = decodedTx.inputs; - formattedTx.outputs = decodedTx.outputs; - formattedTx.locktime = decodedTx.format.locktime; - _rawtx.push(formattedTx); - } else { - formattedTx[0].height = transaction.height; - formattedTx[0].blocktime = blockInfo.timestamp; - formattedTx[0].timereceived = blockInfo.timereceived; - formattedTx[0].hex = _rawtxJSON; - formattedTx[0].inputs = decodedTx.inputs; - formattedTx[0].outputs = decodedTx.outputs; - formattedTx[0].locktime = decodedTx.format.locktime; - formattedTx[1].height = transaction.height; - formattedTx[1].blocktime = blockInfo.timestamp; - formattedTx[1].timereceived = blockInfo.timereceived; - formattedTx[1].hex = _rawtxJSON; - formattedTx[1].inputs = decodedTx.inputs; - formattedTx[1].outputs = decodedTx.outputs; - formattedTx[1].locktime = decodedTx.format.locktime; - _rawtx.push(formattedTx[0]); - _rawtx.push(formattedTx[1]); - } - callback(); + if (index2 === decodedTx.inputs.length) { + shepherd.log(`tx history decode inputs ${decodedTx.inputs.length} | ${index2} => main callback`, true); + const _parsedTx = { + network: decodedTx.network, + format: decodedTx.format, + inputs: txInputs, + outputs: decodedTx.outputs, + height: transaction.height, + timestamp: Number(transaction.height) === 0 ? Math.floor(Date.now() / 1000) : blockInfo.timestamp, + confirmations: Number(transaction.height) === 0 ? 0 : currentHeight - transaction.height, + }; + + const formattedTx = shepherd.parseTransactionAddresses(_parsedTx, req.query.address, network); + + if (formattedTx.type) { + formattedTx.height = transaction.height; + formattedTx.blocktime = blockInfo.timestamp; + formattedTx.timereceived = blockInfo.timereceived; + formattedTx.hex = _rawtxJSON; + formattedTx.inputs = decodedTx.inputs; + formattedTx.outputs = decodedTx.outputs; + formattedTx.locktime = decodedTx.format.locktime; + _rawtx.push(formattedTx); + } else { + formattedTx[0].height = transaction.height; + formattedTx[0].blocktime = blockInfo.timestamp; + formattedTx[0].timereceived = blockInfo.timereceived; + formattedTx[0].hex = _rawtxJSON; + formattedTx[0].inputs = decodedTx.inputs; + formattedTx[0].outputs = decodedTx.outputs; + formattedTx[0].locktime = decodedTx.format.locktime; + formattedTx[1].height = transaction.height; + formattedTx[1].blocktime = blockInfo.timestamp; + formattedTx[1].timereceived = blockInfo.timereceived; + formattedTx[1].hex = _rawtxJSON; + formattedTx[1].inputs = decodedTx.inputs; + formattedTx[1].outputs = decodedTx.outputs; + formattedTx[1].locktime = decodedTx.format.locktime; + _rawtx.push(formattedTx[0]); + _rawtx.push(formattedTx[1]); } + index++; if (index === json.length) { ecl.close(); @@ -181,82 +156,105 @@ module.exports = (shepherd) => { msg: 'success', result: _rawtx, }; - + res.end(JSON.stringify(successObj)); } - //}); - }); - /*.then(promiseResult => { - resolve(true); - });*/ - } else { - const _parsedTx = { - network: decodedTx.network, - format: 'cant parse', - inputs: 'cant parse', - outputs: 'cant parse', - height: transaction.height, - timestamp: Number(transaction.height) === 0 ? Math.floor(Date.now() / 1000) : blockInfo.timestamp, - confirmations: Number(transaction.height) === 0 ? 0 : currentHeight - transaction.height, - }; + callback(); + shepherd.log(`tx history main loop ${json.length} | ${index}`, true); + } + callback2(); + } - const formattedTx = shepherd.parseTransactionAddresses(_parsedTx, req.query.address, network); - _rawtx.push(formattedTx); - index++; - callback(); + if (_decodedInput.txid !== '0000000000000000000000000000000000000000000000000000000000000000') { + if (!_inputTxs[_decodedInput.txid]) { + ecl.blockchainTransactionGet(_decodedInput.txid) + .then((rawInput) => { + _inputTxs[_decodedInput.txid] = rawInput; - if (index === json.length) { - ecl.close(); - - const successObj = { - msg: 'success', - result: _rawtx, - }; - - res.end(JSON.stringify(successObj)); + const decodedVinVout = shepherd.electrumJSTxDecoder(rawInput, network, _network); + + shepherd.log(`electrum raw input tx ${_decodedInput.txid} ==>`, true); + + if (decodedVinVout) { + shepherd.log(decodedVinVout.outputs[_decodedInput.n], true); + txInputs.push(decodedVinVout.outputs[_decodedInput.n]); + } + checkLoop(); + }); + } else { + const decodedVinVout = shepherd.electrumJSTxDecoder(_inputTxs[_decodedInput.txid], network, _network); + + shepherd.log(`electrum raw one time cached input tx ${_decodedInput.txid} ==>`, true); + + if (decodedVinVout) { + shepherd.log(decodedVinVout.outputs[_decodedInput.n], true); + txInputs.push(decodedVinVout.outputs[_decodedInput.n]); + } + checkLoop(); + } + } else { + checkLoop(); } + }); + } else { + const _parsedTx = { + network: decodedTx.network, + format: 'cant parse', + inputs: 'cant parse', + outputs: 'cant parse', + height: transaction.height, + timestamp: Number(transaction.height) === 0 ? Math.floor(Date.now() / 1000) : blockInfo.timestamp, + confirmations: Number(transaction.height) === 0 ? 0 : currentHeight - transaction.height, + }; + + const formattedTx = shepherd.parseTransactionAddresses(_parsedTx, req.query.address, network); + _rawtx.push(formattedTx); + index++; + + if (index === json.length) { + ecl.close(); + + const successObj = { + msg: 'success', + result: _rawtx, + }; + + res.end(JSON.stringify(successObj)); + } else { + callback(); } - }); - } else { - const _parsedTx = { - network: 'cant parse', - format: 'cant parse', - inputs: 'cant parse', - outputs: 'cant parse', - height: transaction.height, - timestamp: 'cant get block info', - confirmations: Number(transaction.height) === 0 ? 0 : currentHeight - transaction.height, + } + }); + } else { + const _parsedTx = { + network: 'cant parse', + format: 'cant parse', + inputs: 'cant parse', + outputs: 'cant parse', + height: transaction.height, + timestamp: 'cant get block info', + confirmations: Number(transaction.height) === 0 ? 0 : currentHeight - transaction.height, + }; + const formattedTx = shepherd.parseTransactionAddresses(_parsedTx, req.query.address, network); + _rawtx.push(formattedTx); + index++; + + if (index === json.length) { + ecl.close(); + + const successObj = { + msg: 'success', + result: _rawtx, }; - const formattedTx = shepherd.parseTransactionAddresses(_parsedTx, req.query.address, network); - _rawtx.push(formattedTx); + + res.end(JSON.stringify(successObj)); + } else { callback(); - index++; } - }); - //}); - - if (index === json.length) { - ecl.close(); - - const successObj = { - msg: 'success', - result: _rawtx, - }; - - res.end(JSON.stringify(successObj)); - } + } + }); }); - /*.then(promiseResult => { - ecl.close(); - - const successObj = { - msg: 'success', - result: _rawtx, - }; - - res.end(JSON.stringify(successObj)); - });*/ } else { ecl.close(); From 008d8d3b24e299b765d53ee3ce07e216dd01925c Mon Sep 17 00:00:00 2001 From: pbca26 Date: Sun, 25 Feb 2018 14:39:39 +0300 Subject: [PATCH 57/67] rename addr categorization prop in/out -> from/to --- routes/shepherd/electrum/transactions.js | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/routes/shepherd/electrum/transactions.js b/routes/shepherd/electrum/transactions.js index 68a66d6..cb42615 100644 --- a/routes/shepherd/electrum/transactions.js +++ b/routes/shepherd/electrum/transactions.js @@ -418,8 +418,6 @@ module.exports = (shepherd) => { result = { type: 'self', amount: Number(_sum.inputs - _sum.outputs).toFixed(8), - sumIn: _sum.inputs, - sumOut: _sum.outputs, address: targetAddress, timestamp: tx.timestamp, txid: tx.format.txid, @@ -441,8 +439,8 @@ module.exports = (shepherd) => { timestamp: tx.timestamp, txid: tx.format.txid, confirmations: tx.confirmations, - inputAddresses: _addresses.inputs, - outputAddresses: _addresses.outputs, + from: _addresses.inputs, + to: _addresses.outputs, }, { type: 'received', amount: Number(_sum.outputs.toFixed(8)), @@ -450,8 +448,8 @@ module.exports = (shepherd) => { timestamp: tx.timestamp, txid: tx.format.txid, confirmations: tx.confirmations, - inputAddresses: _addresses.inputs, - outputAddresses: _addresses.outputs, + from: _addresses.inputs, + to: _addresses.outputs, }]; if (network === 'komodo') { // calc claimed interest amount @@ -470,8 +468,8 @@ module.exports = (shepherd) => { timestamp: tx.timestamp, txid: tx.format.txid, confirmations: tx.confirmations, - inputAddresses: _addresses.inputs, - outputAddresses: _addresses.outputs, + from: _addresses.inputs, + to: _addresses.outputs, }; } else if (_sum.inputs > 0 && _sum.outputs === 0) { result = { @@ -481,8 +479,8 @@ module.exports = (shepherd) => { timestamp: tx.timestamp, txid: tx.format.txid, confirmations: tx.confirmations, - inputAddresses: _addresses.inputs, - outputAddresses: _addresses.outputs, + from: _addresses.inputs, + to: _addresses.outputs, }; } else { // (?) From eb111e85a8c19dbb539b6ebc6308ce20cdfb27da Mon Sep 17 00:00:00 2001 From: pbca26 Date: Sun, 25 Feb 2018 20:32:43 +0300 Subject: [PATCH 58/67] spv listtransactions cache raw txs --- routes/shepherd.js | 4 ++++ routes/shepherd/electrum/transactions.js | 26 ++++++++++++++---------- 2 files changed, 19 insertions(+), 11 deletions(-) diff --git a/routes/shepherd.js b/routes/shepherd.js index 6564f53..929e1ba 100644 --- a/routes/shepherd.js +++ b/routes/shepherd.js @@ -59,6 +59,10 @@ shepherd.electrumCoins = { }; shepherd.electrumKeys = {}; +shepherd.electrumCache = { + rawtx: {}, +}; + shepherd.electrumJSCore = require('./electrumjs/electrumjs.core.js'); shepherd.electrumJSNetworks = require('./electrumjs/electrumjs.networks.js'); shepherd.electrumServers = require('./electrumjs/electrumServers.js'); diff --git a/routes/shepherd/electrum/transactions.js b/routes/shepherd/electrum/transactions.js index cb42615..d5c08af 100644 --- a/routes/shepherd/electrum/transactions.js +++ b/routes/shepherd/electrum/transactions.js @@ -53,7 +53,6 @@ module.exports = (shepherd) => { if (json && json.length) { let _rawtx = []; - let _inputTxs = {}; json = shepherd.sortTransactions(json); json = json.length > MAX_TX ? json.slice(0, MAX_TX) : json; @@ -63,16 +62,20 @@ module.exports = (shepherd) => { const _getTransaction = (txid) => { return new shepherd.Promise((resolve, reject) => { - if (!_inputTxs[txid]) { + if (!shepherd.electrumCache[network]) { + shepherd.electrumCache[network] = {}; + } + + if (!shepherd.electrumCache[network][txid]) { ecl.blockchainTransactionGet(txid) .then((_rawtxJSON) => { resolve(_rawtxJSON); }); } else { - resolve(_inputTxs[txid]); + resolve(shepherd.electrumCache[network][txid]); } }); - } ; + } async.eachOfSeries(json, (transaction, ind, callback) => { ecl.blockchainBlockGetHeader(transaction.height) @@ -81,8 +84,8 @@ module.exports = (shepherd) => { blockInfo.timestamp) { _getTransaction(transaction['tx_hash']) .then((_rawtxJSON) => { - if (!_inputTxs[transaction['tx_hash']]) { - _inputTxs[transaction['tx_hash']] = _rawtxJSON; + if (!shepherd.electrumCache[network][transaction['tx_hash']]) { + shepherd.electrumCache[network][transaction['tx_hash']] = _rawtxJSON; } shepherd.log('electrum gettransaction ==>', true); shepherd.log((index + ' | ' + (_rawtxJSON.length - 1)), true); @@ -167,10 +170,10 @@ module.exports = (shepherd) => { } if (_decodedInput.txid !== '0000000000000000000000000000000000000000000000000000000000000000') { - if (!_inputTxs[_decodedInput.txid]) { + if (!shepherd.electrumCache[network][_decodedInput.txid]) { ecl.blockchainTransactionGet(_decodedInput.txid) .then((rawInput) => { - _inputTxs[_decodedInput.txid] = rawInput; + shepherd.electrumCache[network][_decodedInput.txid] = rawInput; const decodedVinVout = shepherd.electrumJSTxDecoder(rawInput, network, _network); @@ -183,9 +186,9 @@ module.exports = (shepherd) => { checkLoop(); }); } else { - const decodedVinVout = shepherd.electrumJSTxDecoder(_inputTxs[_decodedInput.txid], network, _network); + const decodedVinVout = shepherd.electrumJSTxDecoder(shepherd.electrumCache[network][_decodedInput.txid], network, _network); - shepherd.log(`electrum raw one time cached input tx ${_decodedInput.txid} ==>`, true); + shepherd.log(`electrum raw cached input tx ${_decodedInput.txid} ==>`, true); if (decodedVinVout) { shepherd.log(decodedVinVout.outputs[_decodedInput.n], true); @@ -527,9 +530,10 @@ module.exports = (shepherd) => { } else { const ecl = new shepherd.electrumJSCore(shepherd.electrumServers[req.query.network].port, shepherd.electrumServers[req.query.network].address, shepherd.electrumServers[req.query.network].proto); // tcp or tls - ecl.connect(); shepherd.log(decodedTx.inputs[0]); shepherd.log(decodedTx.inputs[0].txid); + + ecl.connect(); ecl.blockchainTransactionGet(decodedTx.inputs[0].txid) .then((json) => { ecl.close(); From 8fac5145476014714fb455483c9193b0567cb82e Mon Sep 17 00:00:00 2001 From: pbca26 Date: Sun, 25 Feb 2018 23:32:09 +0300 Subject: [PATCH 59/67] spv listtransactions improved raw tx caching --- routes/shepherd.js | 4 +- routes/shepherd/electrum/transactions.js | 75 ++++++++++-------------- 2 files changed, 33 insertions(+), 46 deletions(-) diff --git a/routes/shepherd.js b/routes/shepherd.js index 929e1ba..7978257 100644 --- a/routes/shepherd.js +++ b/routes/shepherd.js @@ -59,9 +59,7 @@ shepherd.electrumCoins = { }; shepherd.electrumKeys = {}; -shepherd.electrumCache = { - rawtx: {}, -}; +shepherd.electrumCache = {}; shepherd.electrumJSCore = require('./electrumjs/electrumjs.core.js'); shepherd.electrumJSNetworks = require('./electrumjs/electrumjs.networks.js'); diff --git a/routes/shepherd/electrum/transactions.js b/routes/shepherd/electrum/transactions.js index d5c08af..fef94af 100644 --- a/routes/shepherd/electrum/transactions.js +++ b/routes/shepherd/electrum/transactions.js @@ -14,6 +14,27 @@ module.exports = (shepherd) => { return 0; }); } + + shepherd.getTransaction = (txid, network, ecl) => { + return new shepherd.Promise((resolve, reject) => { + if (!shepherd.electrumCache[network]) { + shepherd.electrumCache[network] = { + tx: {}, + blocksHeaders: {}, + }; + } + + if (!shepherd.electrumCache[network].tx[txid]) { + ecl.blockchainTransactionGet(txid) + .then((_rawtxJSON) => { + shepherd.electrumCache[network].tx[txid] = _rawtxJSON; + resolve(_rawtxJSON); + }); + } else { + resolve(shepherd.electrumCache[network].tx[txid]); + } + }); + } shepherd.get('/electrum/listtransactions', (req, res, next) => { if (shepherd.checkToken(req.query.token)) { @@ -60,33 +81,13 @@ module.exports = (shepherd) => { shepherd.log(json.length, true); let index = 0; - const _getTransaction = (txid) => { - return new shepherd.Promise((resolve, reject) => { - if (!shepherd.electrumCache[network]) { - shepherd.electrumCache[network] = {}; - } - - if (!shepherd.electrumCache[network][txid]) { - ecl.blockchainTransactionGet(txid) - .then((_rawtxJSON) => { - resolve(_rawtxJSON); - }); - } else { - resolve(shepherd.electrumCache[network][txid]); - } - }); - } - async.eachOfSeries(json, (transaction, ind, callback) => { ecl.blockchainBlockGetHeader(transaction.height) .then((blockInfo) => { if (blockInfo && blockInfo.timestamp) { - _getTransaction(transaction['tx_hash']) + shepherd.getTransaction(transaction['tx_hash'], network, ecl) .then((_rawtxJSON) => { - if (!shepherd.electrumCache[network][transaction['tx_hash']]) { - shepherd.electrumCache[network][transaction['tx_hash']] = _rawtxJSON; - } shepherd.log('electrum gettransaction ==>', true); shepherd.log((index + ' | ' + (_rawtxJSON.length - 1)), true); // shepherd.log(_rawtxJSON, true); @@ -170,32 +171,18 @@ module.exports = (shepherd) => { } if (_decodedInput.txid !== '0000000000000000000000000000000000000000000000000000000000000000') { - if (!shepherd.electrumCache[network][_decodedInput.txid]) { - ecl.blockchainTransactionGet(_decodedInput.txid) - .then((rawInput) => { - shepherd.electrumCache[network][_decodedInput.txid] = rawInput; - - const decodedVinVout = shepherd.electrumJSTxDecoder(rawInput, network, _network); - - shepherd.log(`electrum raw input tx ${_decodedInput.txid} ==>`, true); - - if (decodedVinVout) { - shepherd.log(decodedVinVout.outputs[_decodedInput.n], true); - txInputs.push(decodedVinVout.outputs[_decodedInput.n]); - } - checkLoop(); - }); - } else { - const decodedVinVout = shepherd.electrumJSTxDecoder(shepherd.electrumCache[network][_decodedInput.txid], network, _network); - - shepherd.log(`electrum raw cached input tx ${_decodedInput.txid} ==>`, true); + shepherd.getTransaction(_decodedInput.txid, network, ecl) + .then((rawInput) => { + const decodedVinVout = shepherd.electrumJSTxDecoder(rawInput, network, _network); + + shepherd.log(`electrum raw input tx ${_decodedInput.txid} ==>`, true); if (decodedVinVout) { shepherd.log(decodedVinVout.outputs[_decodedInput.n], true); txInputs.push(decodedVinVout.outputs[_decodedInput.n]); } checkLoop(); - } + }); } else { checkLoop(); } @@ -384,7 +371,8 @@ module.exports = (shepherd) => { _parse[key][i].scriptPubKey.addresses[0]) { _addresses[key].push(_parse[key][i].scriptPubKey.addresses[0]); - if (_parse[key][i].scriptPubKey.addresses[0] === targetAddress && skipTargetAddress) { + if (_parse[key][i].scriptPubKey.addresses[0] === targetAddress && + skipTargetAddress) { _addresses[key].pop(); } } @@ -406,7 +394,8 @@ module.exports = (shepherd) => { for (let key in _parse) { for (let i = 0; i < _addresses[key].length; i++) { - if (_addresses[key][i] === targetAddress && _addresses[key].length === 1) { + if (_addresses[key][i] === targetAddress && + _addresses[key].length === 1) { isSelfSend[key] = true; } } From d446f7c1ef30335879510c9454cabd5a72a7342d Mon Sep 17 00:00:00 2001 From: pbca26 Date: Mon, 26 Feb 2018 13:13:04 +0300 Subject: [PATCH 60/67] zec address check fix --- routes/shepherd/electrum/keys.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/routes/shepherd/electrum/keys.js b/routes/shepherd/electrum/keys.js index bfe5581..a795327 100644 --- a/routes/shepherd/electrum/keys.js +++ b/routes/shepherd/electrum/keys.js @@ -151,7 +151,7 @@ module.exports = (shepherd) => { const _network = shepherd.getNetworkData(network.toLowerCase()); try { - const _b58check = bitcoin.address.fromBase58Check(address); + const _b58check = shepherd.isZcash(network.toLowerCase()) ? bitcoinZcash.address.fromBase58Check(address) : bitcoin.address.fromBase58Check(address); if (_b58check.version === _network.pubKeyHash) { return true; From 163a7e0156d9b30c656851727af5690222c07098 Mon Sep 17 00:00:00 2001 From: pbca26 Date: Mon, 26 Feb 2018 13:13:56 +0300 Subject: [PATCH 61/67] spv cache block headers, use cache in linstunspent and merkle --- routes/shepherd/electrum/balance.js | 2 +- routes/shepherd/electrum/listunspent.js | 6 ++-- routes/shepherd/electrum/merkle.js | 7 +++-- routes/shepherd/electrum/transactions.js | 39 +++++++++++++++++++----- 4 files changed, 40 insertions(+), 14 deletions(-) diff --git a/routes/shepherd/electrum/balance.js b/routes/shepherd/electrum/balance.js index 6b73d9b..9c4aa25 100644 --- a/routes/shepherd/electrum/balance.js +++ b/routes/shepherd/electrum/balance.js @@ -37,7 +37,7 @@ module.exports = (shepherd) => { shepherd.Promise.all(_utxo.map((_utxoItem, index) => { return new shepherd.Promise((resolve, reject) => { - ecl.blockchainTransactionGet(_utxoItem['tx_hash']) + shepherd.getTransaction(_utxoItem['tx_hash'], network, ecl) .then((_rawtxJSON) => { shepherd.log('electrum gettransaction ==>', true); shepherd.log((index + ' | ' + (_rawtxJSON.length - 1)), true); diff --git a/routes/shepherd/electrum/listunspent.js b/routes/shepherd/electrum/listunspent.js index b280ee4..0e662a7 100644 --- a/routes/shepherd/electrum/listunspent.js +++ b/routes/shepherd/electrum/listunspent.js @@ -31,7 +31,7 @@ module.exports = (shepherd) => { } else { shepherd.Promise.all(_utxo.map((_utxoItem, index) => { return new shepherd.Promise((resolve, reject) => { - ecl.blockchainTransactionGet(_utxoItem['tx_hash']) + shepherd.getTransaction(_utxoItem['tx_hash'], network, ecl) .then((_rawtxJSON) => { shepherd.log('electrum gettransaction ==>', true); shepherd.log(index + ' | ' + (_rawtxJSON.length - 1), true); @@ -70,7 +70,7 @@ module.exports = (shepherd) => { verified: false, }; - // merkle root verification agains another electrum server + // merkle root verification against another electrum server if (verify) { shepherd.verifyMerkleByCoin(shepherd.findCoinName(network), _utxoItem['tx_hash'], _utxoItem.height) .then((verifyMerkleRes) => { @@ -97,7 +97,7 @@ module.exports = (shepherd) => { verified: false, }; - // merkle root verification agains another electrum server + // merkle root verification against another electrum server if (verify) { shepherd.verifyMerkleByCoin(shepherd.findCoinName(network), _utxoItem['tx_hash'], _utxoItem.height) .then((verifyMerkleRes) => { diff --git a/routes/shepherd/electrum/merkle.js b/routes/shepherd/electrum/merkle.js index 39cde0e..2385d67 100644 --- a/routes/shepherd/electrum/merkle.js +++ b/routes/shepherd/electrum/merkle.js @@ -30,7 +30,7 @@ module.exports = (shepherd) => { return hash; } - shepherd.verifyMerkle = (txid, height, serverList, mainServer) => { + shepherd.verifyMerkle = (txid, height, serverList, mainServer, network) => { // select random server const getRandomIntInclusive = (min, max) => { min = Math.ceil(min); @@ -66,7 +66,7 @@ module.exports = (shepherd) => { ecl = new shepherd.electrumJSCore(_randomServer[1], _randomServer[0], _mainServer[2]); ecl.connect(); - ecl.blockchainBlockGetHeader(height) + shepherd.getBlockHeader(height, network, ecl) .then((blockInfo) => { if (blockInfo && blockInfo['merkle_root']) { @@ -120,7 +120,8 @@ module.exports = (shepherd) => { txid, height, _filteredServerList, - shepherd.electrumCoins[coin].server.ip + ':' + shepherd.electrumCoins[coin].server.port + ':' + shepherd.electrumServers[coin === 'KMD' || coin === 'komodo' ? 'komodo' : coin.toLowerCase()].proto + shepherd.electrumCoins[coin].server.ip + ':' + shepherd.electrumCoins[coin].server.port + ':' + shepherd.electrumServers[coin === 'KMD' || coin === 'komodo' ? 'komodo' : coin.toLowerCase()].proto, + coin ) .then((proof) => { resolve(proof); diff --git a/routes/shepherd/electrum/transactions.js b/routes/shepherd/electrum/transactions.js index fef94af..cd15b05 100644 --- a/routes/shepherd/electrum/transactions.js +++ b/routes/shepherd/electrum/transactions.js @@ -18,24 +18,51 @@ module.exports = (shepherd) => { shepherd.getTransaction = (txid, network, ecl) => { return new shepherd.Promise((resolve, reject) => { if (!shepherd.electrumCache[network]) { - shepherd.electrumCache[network] = { - tx: {}, - blocksHeaders: {}, - }; + shepherd.electrumCache[network] = {}; + } + if (!shepherd.electrumCache[network].tx) { + shepherd.electrumCache[network]['tx'] = {}; } if (!shepherd.electrumCache[network].tx[txid]) { + shepherd.log(`electrum raw input tx ${txid}`, true); + ecl.blockchainTransactionGet(txid) .then((_rawtxJSON) => { shepherd.electrumCache[network].tx[txid] = _rawtxJSON; resolve(_rawtxJSON); }); } else { + shepherd.log(`electrum cached raw input tx ${txid}`, true); resolve(shepherd.electrumCache[network].tx[txid]); } }); } + shepherd.getBlockHeader = (height, network, ecl) => { + return new shepherd.Promise((resolve, reject) => { + if (!shepherd.electrumCache[network]) { + shepherd.electrumCache[network] = {}; + } + if (!shepherd.electrumCache[network].blockHeader) { + shepherd.electrumCache[network]['blockHeader'] = {}; + } + + if (!shepherd.electrumCache[network].blockHeader[height]) { + shepherd.log(`electrum raw block ${height}`, true); + + ecl.blockchainBlockGetHeader(height) + .then((_rawtxJSON) => { + shepherd.electrumCache[network].blockHeader[height] = _rawtxJSON; + resolve(_rawtxJSON); + }); + } else { + shepherd.log(`electrum cached raw block ${height}`, true); + resolve(shepherd.electrumCache[network].blockHeader[height]); + } + }); + } + shepherd.get('/electrum/listtransactions', (req, res, next) => { if (shepherd.checkToken(req.query.token)) { const network = req.query.network || shepherd.findNetworkObj(req.query.coin); @@ -82,7 +109,7 @@ module.exports = (shepherd) => { let index = 0; async.eachOfSeries(json, (transaction, ind, callback) => { - ecl.blockchainBlockGetHeader(transaction.height) + shepherd.getBlockHeader(transaction.height, network, ecl) .then((blockInfo) => { if (blockInfo && blockInfo.timestamp) { @@ -175,8 +202,6 @@ module.exports = (shepherd) => { .then((rawInput) => { const decodedVinVout = shepherd.electrumJSTxDecoder(rawInput, network, _network); - shepherd.log(`electrum raw input tx ${_decodedInput.txid} ==>`, true); - if (decodedVinVout) { shepherd.log(decodedVinVout.outputs[_decodedInput.n], true); txInputs.push(decodedVinVout.outputs[_decodedInput.n]); From 4732b7b61a9ebb5f9e46f9429d79360f45dac25a Mon Sep 17 00:00:00 2001 From: pbca26 Date: Mon, 26 Feb 2018 14:37:40 +0300 Subject: [PATCH 62/67] version bump --- version | 6 +++--- version_build | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/version b/version index 77d4194..57f9527 100644 --- a/version +++ b/version @@ -1,3 +1,3 @@ -version=0.2.0.28c -type=c-beta -minversion=0.2.0.28 \ No newline at end of file +version=0.2.0.29a +type=a-beta +minversion=0.2.0.29 \ No newline at end of file diff --git a/version_build b/version_build index 64427e2..3366a55 100644 --- a/version_build +++ b/version_build @@ -1 +1 @@ -0.2.0.28c-beta \ No newline at end of file +0.2.0.29a-beta \ No newline at end of file From 55bd6a3e99c8535930a086aa363c5c626c0388af Mon Sep 17 00:00:00 2001 From: pbca26 Date: Sun, 4 Mar 2018 16:45:19 +0300 Subject: [PATCH 63/67] version bump --- package.json | 2 +- routes/shepherd/electrum/keys.js | 2 +- version | 4 ++-- version_build | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 9dbf4fe..dbe0934 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "agama-app", "productName": "Agama", - "version": "0.2.26", + "version": "0.2.29", "description": "Agama Wallet Desktop App", "main": "main.js", "scripts": { diff --git a/routes/shepherd/electrum/keys.js b/routes/shepherd/electrum/keys.js index a795327..8edb339 100644 --- a/routes/shepherd/electrum/keys.js +++ b/routes/shepherd/electrum/keys.js @@ -123,7 +123,7 @@ module.exports = (shepherd) => { const _skipNetworks = ['btc', 'crw', 'dgb', 'arg', 'zec', 'nmc', 'ltc', 'vtc', 'via', 'fair', 'doge', 'kmd', 'mona']; try { - const _b58check = bitcoin.address.fromBase58Check(address); + const _b58check = shepherd.isZcash(network.toLowerCase()) ? bitcoinZcash.address.fromBase58Check(address) : bitcoin.address.fromBase58Check(address); let _coin = []; let returnObj; diff --git a/version b/version index 57f9527..34e8395 100644 --- a/version +++ b/version @@ -1,3 +1,3 @@ -version=0.2.0.29a -type=a-beta +version=0.2.0.29b +type=b-beta minversion=0.2.0.29 \ No newline at end of file diff --git a/version_build b/version_build index 3366a55..f0877ef 100644 --- a/version_build +++ b/version_build @@ -1 +1 @@ -0.2.0.29a-beta \ No newline at end of file +0.2.0.29b-beta \ No newline at end of file From d3aa298bfab2cd3286339e4eb781a9684ccc9c19 Mon Sep 17 00:00:00 2001 From: pbca26 Date: Sun, 4 Mar 2018 16:50:04 +0300 Subject: [PATCH 64/67] bump electron version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index dbe0934..a6df1aa 100644 --- a/package.json +++ b/package.json @@ -41,7 +41,7 @@ "body-parser": "^1.15.2", "buffer-reverse": "^1.0.1", "coinselect": "github:bitcoinjs/coinselect", - "electron": "1.7.11", + "electron": "1.8.2", "express": "^4.14.0", "fix-path": "^2.1.0", "fs-extra": "^4.0.2", From 0b0ac95e92331e398add9e07d20b3c3fe7667581 Mon Sep 17 00:00:00 2001 From: pbca26 Date: Thu, 8 Mar 2018 20:56:55 +0300 Subject: [PATCH 65/67] version bump --- main.js | 5 ++--- routes/electrumjs/electrumjs.networks.js | 6 +++--- routes/shepherd.js | 2 ++ routes/shepherd/dashboardUpdate.js | 6 +++++- version | 4 ++-- version_build | 2 +- 6 files changed, 15 insertions(+), 10 deletions(-) diff --git a/main.js b/main.js index f2a9887..c67022b 100644 --- a/main.js +++ b/main.js @@ -90,7 +90,7 @@ shepherd.log(`app started in ${(appConfig.dev ? 'dev mode' : ' user mode')}`); shepherd.writeLog(`app started in ${(appConfig.dev ? 'dev mode' : ' user mode')}`); shepherd.setConfKMD(); -shepherd.setConfKMD('CHIPS'); +// shepherd.setConfKMD('CHIPS'); guiapp.use((req, res, next) => { res.header('Access-Control-Allow-Origin', appConfig.dev ? '*' : 'http://127.0.0.1:3000'); @@ -116,8 +116,7 @@ process.once('loaded', () => { copyright: 'Released under the MIT license', credits: 'SuperNET Team', }); - } - if (osPlatform === 'linux') { + } else if (osPlatform === 'linux') { process.setFdLimit(appConfig.maxDescriptors.linux); } }); diff --git a/routes/electrumjs/electrumjs.networks.js b/routes/electrumjs/electrumjs.networks.js index b54f0e4..0686d85 100644 --- a/routes/electrumjs/electrumjs.networks.js +++ b/routes/electrumjs/electrumjs.networks.js @@ -15,8 +15,8 @@ networks.litecoin = { pubKeyHash: 0x30, scriptHash: 0x32, wif: 0xb0, - dustThreshold: 0, // https://github.com/litecoin-project/litecoin/blob/v0.8.7.2/src/main.cpp#L360-L365 -} + dustThreshold: 0 // https://github.com/litecoin-project/litecoin/blob/v0.8.7.2/src/main.cpp#L360-L365 +}; networks.dogecoin = { messagePrefix: '\x19Dogecoin Signed Message:\n', @@ -27,7 +27,7 @@ networks.dogecoin = { pubKeyHash: 0x1e, scriptHash: 0x16, wif: 0x9e, - dustThreshold: 0 // https://github.com/dogecoin/dogecoin/blob/v1.7.1/src/core.h#L155-L160 + dustThreshold: 0, // https://github.com/dogecoin/dogecoin/blob/v1.7.1/src/core.h#L155-L160 }; // https://github.com/monacoinproject/monacoin/blob/master-0.10/src/chainparams.cpp#L161 diff --git a/routes/shepherd.js b/routes/shepherd.js index 7978257..6e4f612 100644 --- a/routes/shepherd.js +++ b/routes/shepherd.js @@ -37,6 +37,8 @@ shepherd.rpcConf = {}; shepherd.appRuntimeLog = []; shepherd.appRuntimeSPVLog = []; shepherd.lockDownAddCoin = false; + +// dex cache shepherd.mmupass = null; shepherd.mmRatesInterval = null; shepherd.mmPublic = { diff --git a/routes/shepherd/dashboardUpdate.js b/routes/shepherd/dashboardUpdate.js index f87abd7..2cca1f6 100644 --- a/routes/shepherd/dashboardUpdate.js +++ b/routes/shepherd/dashboardUpdate.js @@ -59,7 +59,8 @@ module.exports = (shepherd) => { coin, _type === 'public' ? 'getaddressesbyaccount' : 'z_listaddresses', [''] - ).then((_json) => { + ) + .then((_json) => { if (_json === 'Work queue depth exceeded' || !_json) { resolve({ error: 'daemon is busy' }); @@ -110,6 +111,7 @@ module.exports = (shepherd) => { return result[0].indexOf(elem) === pos; }); } + if (result[1] && result[1].length) { result[1] = result[1].filter((elem, pos) => { @@ -118,6 +120,7 @@ module.exports = (shepherd) => { } let newAddressArray = []; + for (let a = 0; a < result.length; a++) { newAddressArray[a] = []; @@ -305,6 +308,7 @@ module.exports = (shepherd) => { } else { _returnObj[_call] = JSON.parse(json); } + resolve(json); }); }); diff --git a/version b/version index 34e8395..a28399c 100644 --- a/version +++ b/version @@ -1,3 +1,3 @@ -version=0.2.0.29b -type=b-beta +version=0.2.0.29c +type=c-beta minversion=0.2.0.29 \ No newline at end of file diff --git a/version_build b/version_build index f0877ef..de6ec95 100644 --- a/version_build +++ b/version_build @@ -1 +1 @@ -0.2.0.29b-beta \ No newline at end of file +0.2.0.29c-beta \ No newline at end of file From d3b002c5ce463b6914054251dadacf6e07edbca8 Mon Sep 17 00:00:00 2001 From: pbca26 Date: Thu, 8 Mar 2018 20:58:41 +0300 Subject: [PATCH 66/67] submodule update --- gui/EasyDEX-GUI | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gui/EasyDEX-GUI b/gui/EasyDEX-GUI index ba9ec3a..54f9dfc 160000 --- a/gui/EasyDEX-GUI +++ b/gui/EasyDEX-GUI @@ -1 +1 @@ -Subproject commit ba9ec3ad4d56a9454648b7396afcd16aadc61456 +Subproject commit 54f9dfc6e7b519a5a2295b49813cfd99be131cae From ffb4c77c6951525fa2ed96cf3bfbd9b3d5aa8a89 Mon Sep 17 00:00:00 2001 From: pbca26 Date: Thu, 8 Mar 2018 23:24:00 +0300 Subject: [PATCH 67/67] remove fiat ports --- routes/ports.js | 34 ++-------------------------------- 1 file changed, 2 insertions(+), 32 deletions(-) diff --git a/routes/ports.js b/routes/ports.js index 4bbf44c..9364db0 100644 --- a/routes/ports.js +++ b/routes/ports.js @@ -1,3 +1,5 @@ +// default daemon ports + const assetChainPorts = { 'komodod': '7771', 'markermaker': '7783', @@ -26,38 +28,6 @@ const assetChainPorts = { 'ETOMIC': '10271', 'VOTE': '8012', 'BTCH': '8800', - 'USD': '13967', - 'CHF': '15312', - 'CAD': '8720', - 'BRL': '9914', - 'BGN': '9110', - 'AUD': '8045', - 'PLN': '13493', - 'PHP': '11181', - 'NZD': '10915', - 'NOK': '11588', - 'MYR': '10688', - 'MXN': '13970', - 'KRW': '14020', - 'JPY': '13145', - 'INR': '10536', - 'ILS': '14638', - 'IDR': '14459', - 'HKD': '15409', - 'HUF': '13699', - 'HRK': '12617', - 'GBP': '11505', - 'EUR': '8065', - 'DKK': '13830', - 'CNY': '10384', - 'ZAR': '15160', - 'TRY': '13924', - 'THB': '11847', - 'SGD': '14475', - 'SEK': '11447', - 'RON': '8675', - 'RUB': '8199', - 'CZK': '9482' }; module.exports = assetChainPorts; \ No newline at end of file