diff --git a/package.json b/package.json index 9ceb755..a307b80 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "agama_app", "productName": "Agama", - "version": "0.1.6", + "version": "0.2.22", "description": "Agama Desktop App", "main": "main.js", "scripts": { diff --git a/routes/cache.js b/routes/cache.js index 91379ae..428c94d 100644 --- a/routes/cache.js +++ b/routes/cache.js @@ -30,7 +30,7 @@ cache.get = function(req, res, next) { console.log('serving cache from disk'); if (fs.existsSync(`${cache.iguanaDir}/shepherd/cache-${pubkey}.json`)) { - fs.readFile(`${cache.iguanaDir}/shepherd/cache-${pubkey}.json`, 'utf8', function (err, data) { + fs.readFile(`${cache.iguanaDir}/shepherd/cache-${pubkey}.json`, 'utf8', function(err, data) { if (err) { const errorObj = { msg: 'error', @@ -101,7 +101,7 @@ cache.groomGet = function(req, res, next) { if (_filename) { if (fs.existsSync(`${cache.iguanaDir}/shepherd/cache-${_filename}.json`)) { - fs.readFile(`${cache.iguanaDir}/shepherd/cache-${_filename}.json`, 'utf8', function (err, data) { + fs.readFile(`${cache.iguanaDir}/shepherd/cache-${_filename}.json`, 'utf8', function(err, data) { if (err) { const errorObj = { msg: 'error', @@ -198,7 +198,7 @@ cache.groomPost = function(req, res) { console.log('appending groom post to in mem cache'); console.log('appending groom post to on disk cache'); - fs.writeFile(`${cache.iguanaDir}/shepherd/cache-${_filename}.json`, _payload, function (err) { + fs.writeFile(`${cache.iguanaDir}/shepherd/cache-${_filename}.json`, _payload, function(err) { if (err) { const errorObj = { msg: 'error', @@ -499,7 +499,7 @@ cache.one = function(req, res, next) { request({ url: mock ? `http://localhost:17777/shepherd/mock?url=${dexUrl}` : dexUrl, method: 'GET' - }, function (error, response, body) { + }, function(error, response, body) { if (response && response.statusCode && response.statusCode === 200) { @@ -528,7 +528,7 @@ cache.one = function(req, res, next) { request({ url: `http://kmd.explorer.supernet.org/api/addr/${address}/?noTxList=1`, method: 'GET' - }, function (error, response, body) { + }, function(error, response, body) { if (response && response.statusCode && response.statusCode === 200) { @@ -676,7 +676,7 @@ cache.one = function(req, res, next) { request({ url: mock ? `http://localhost:17777/shepherd/mock?url=${tempUrl}` : tempUrl, method: 'GET' - }, function (error, response, body) { + }, function(error, response, body) { if (response && response.statusCode && response.statusCode === 200) { @@ -709,7 +709,7 @@ cache.one = function(req, res, next) { request({ url: mock ? `http://localhost:17777/shepherd/mock?url=${tempUrl}` : tempUrl, method: 'GET' - }, function (error, response, body) { + }, function(error, response, body) { if (response && response.statusCode && response.statusCode === 200) { diff --git a/routes/shepherd.js b/routes/shepherd.js index 33e6998..a5523b4 100644 --- a/routes/shepherd.js +++ b/routes/shepherd.js @@ -98,6 +98,229 @@ shepherd.defaultAppConfig = Object.assign({}, shepherd.appConfig); shepherd.coindInstanceRegistry = coindInstanceRegistry; +/* + * Combined native dashboard update same as in gui + * type: GET + * params: coin + */ +shepherd.post('/native/dashboard/update', function(req, res, next) { + let _returnObj = { + getinfo: {}, + listtransactions: [], + z_gettotalbalance: {}, + z_getoperationstatus: {}, + listunspent: {}, + addresses: {}, + }; + const _promiseStack = [ + 'getinfo', + 'listtransactions', + 'z_gettotalbalance', + 'z_getoperationstatus' + ]; + const _coin = req.body.coin; + + function getAddressesNative(coin) { + const type = [ + 'public', + 'private' + ]; + + Promise.all(type.map((_type, index) => { + return new Promise((resolve, reject) => { + _bitcoinRPC( + coin, + _type === 'public' ? 'getaddressesbyaccount' : 'z_listaddresses', + [''] + ).then(function(_json) { + resolve(JSON.parse(_json).result); + }); + }); + })) + .then(result => { + function calcBalance(result, json) { + if (json && + json.length) { + 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]; + } + } + } + + // remove addr duplicates + if (result[0]) { + result[0] = result[0].filter(function(elem, pos) { + return result[0].indexOf(elem) === pos; + }); + } + if (result[1]) { + result[1] = result[1].filter(function(elem, pos) { + return result[1].indexOf(elem) === pos; + }); + } + + let newAddressArray = []; + for (let a = 0; a < result.length; a++) { + newAddressArray[a] = []; + + if (result[a]) { + for (let b = 0; b < result[a].length; b++) { + let filteredArray; + + filteredArray = json.filter(res => res.address === result[a][b]).map(res => res.amount); + + let sum = 0; + for (let i = 0; i < filteredArray.length; i++) { + sum += filteredArray[i]; + } + + newAddressArray[a][b] = { + address: result[a][b], + amount: sum, + 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(function(__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)); + }); + } else { + _returnObj.addresses = { + public: newAddressArray[0], + private: newAddressArray[1], + }; + + const returnObj = { + msg: 'success', + result: _returnObj, + }; + + res.end(JSON.stringify(returnObj)); + } + } + + _bitcoinRPC(coin, 'listunspent') + .then(function(__json) { + _returnObj.listunspent = JSON.parse(__json); + + calcBalance( + result, + JSON.parse(__json).result + ); + }); + }) + } + + function _bitcoinRPC(coin, cmd, params) { + return new Promise(function(resolve, reject) { + let _payload; + + if (params) { + _payload = { + mode: null, + chain: coin, + cmd: cmd, + params: params, + }; + } else { + _payload = { + mode: null, + chain: coin, + cmd: cmd, + }; + } + + 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 }) + }; + + request(options, function(error, response, body) { + if (response && + response.statusCode && + response.statusCode === 200) { + resolve(body); + } else { + resolve(body); + } + }); + }); + } + + Promise.all(_promiseStack.map((_call, index) => { + return new Promise((resolve, reject) => { + _bitcoinRPC( + _coin, + _call + ) + .then(function(json) { + _returnObj[_call] = JSON.parse(json); + resolve(json); + }); + }); + })) + .then(result => { + getAddressesNative(_coin); + }); +}); + +// TODO: test functions are wip shepherd.testNearestIguanaPort = function() { return new Promise(function(resolve, reject) { const port = shepherd.appConfig.iguanaCorePort; @@ -263,7 +486,7 @@ shepherd.testBins = function(daemonName) { 'addnode=185.106.121.32\n' + 'addnode=27.100.36.201\n'; - fs.writeFile(`${iguanaTestDir}/komodo.conf`, _komodoConf, function (err) { + fs.writeFile(`${iguanaTestDir}/komodo.conf`, _komodoConf, function(err) { if (err) { console.log(`test: error writing komodo conf in ${iguanaTestDir}`); } @@ -330,7 +553,7 @@ shepherd.testBins = function(daemonName) { }), }; - request(options, function (error, response, body) { + request(options, function(error, response, body) { if (response && response.statusCode && response.statusCode === 200) { @@ -524,13 +747,13 @@ shepherd.writeLog = function(data) { if (shepherd.appConfig.debug) { if (fs.existsSync(`${logLocation}/agamalog.txt`)) { - fs.appendFile(`${logLocation}/agamalog.txt`, `${timeFormatted} ${data}\r\n`, function (err) { + fs.appendFile(`${logLocation}/agamalog.txt`, `${timeFormatted} ${data}\r\n`, function(err) { if (err) { console.log('error writing log file'); } }); } else { - fs.writeFile(`${logLocation}/agamalog.txt`, `${timeFormatted} ${data}\r\n`, function (err) { + fs.writeFile(`${logLocation}/agamalog.txt`, `${timeFormatted} ${data}\r\n`, function(err) { if (err) { console.log('error writing log file'); } @@ -593,7 +816,7 @@ shepherd.post('/encryptkey', function(req, res, next) { const _pin = req.body.key; const _pinTest = _pin.match('^(?=.*[A-Z])(?=.*[^<>{}\"/|;:.,~!?@#$%^=&*\\]\\\\()\\[_+]*$)(?=.*[0-9])(?=.*[a-z]).{8}$'); - fs.writeFile(`${iguanaDir}/shepherd/pin/${req.body.pubkey}.pin`, encryptedString, function (err) { + fs.writeFile(`${iguanaDir}/shepherd/pin/${req.body.pubkey}.pin`, encryptedString, function(err) { if (err) { console.log('error writing pin file'); } @@ -632,7 +855,7 @@ shepherd.post('/decryptkey', function(req, res, next) { if (req.body.key && req.body.pubkey) { if (fs.existsSync(`${iguanaDir}/shepherd/pin/${req.body.pubkey}.pin`)) { - fs.readFile(`${iguanaDir}/shepherd/pin/${req.body.pubkey}.pin`, 'utf8', function (err, data) { + fs.readFile(`${iguanaDir}/shepherd/pin/${req.body.pubkey}.pin`, 'utf8', function(err, data) { if (err) { const errorObj = { msg: 'error', @@ -890,7 +1113,7 @@ shepherd.get('/update/bins', function(req, res, next) { file: binsToUpdate[i].name, bytesTotal: total, bytesReceived: received, - } + }, }); console.log(`${binsToUpdate[i].name} ${percentage}% | ${received} bytes out of ${total} bytes.`); } @@ -906,7 +1129,7 @@ shepherd.get('/update/bins', function(req, res, next) { type: 'bins-update', file: binsToUpdate[i].name, status: 'done', - } + }, }); console.log(`file ${binsToUpdate[i].name} succesfully downloaded`); } else { @@ -915,7 +1138,7 @@ shepherd.get('/update/bins', function(req, res, next) { type: 'bins-update', file: binsToUpdate[i].name, message: 'size mismatch', - } + }, }); console.log(`error: ${binsToUpdate[i].name} file size doesnt match remote!`); } @@ -925,7 +1148,7 @@ shepherd.get('/update/bins', function(req, res, next) { /* * DL app patch - * type: + * type: GET * params: patchList */ shepherd.get('/update/patch', function(req, res, next) { @@ -1015,7 +1238,7 @@ shepherd.get('/update/patch/check', function(req, res, next) { method: 'GET', }; - request(options, function (error, response, body) { + request(options, function(error, response, body) { if (response && response.statusCode && response.statusCode === 200) { @@ -1080,7 +1303,7 @@ shepherd.get('/unpack', function(req, res, next) { */ shepherd.get('/coinslist', function(req, res, next) { if (fs.existsSync(`${iguanaDir}/shepherd/coinslist.json`)) { - fs.readFile(`${iguanaDir}/shepherd/coinslist.json`, 'utf8', function (err, data) { + fs.readFile(`${iguanaDir}/shepherd/coinslist.json`, 'utf8', function(err, data) { if (err) { const errorObj = { msg: 'error', @@ -1131,7 +1354,7 @@ shepherd.post('/guilog', function(req, res, next) { }; } - fs.writeFile(`${logLocation}/agamalog.json`, JSON.stringify(guiLog), function (err) { + fs.writeFile(`${logLocation}/agamalog.json`, JSON.stringify(guiLog), function(err) { if (err) { shepherd.writeLog('error writing gui log file'); } @@ -1153,7 +1376,7 @@ shepherd.get('/getlog', function(req, res, next) { const logExt = req.query.type === 'txt' ? 'txt' : 'json'; if (fs.existsSync(`${iguanaDir}/shepherd/agamalog.${logExt}`)) { - fs.readFile(`${iguanaDir}/shepherd/agamalog.${logExt}`, 'utf8', function (err, data) { + fs.readFile(`${iguanaDir}/shepherd/agamalog.${logExt}`, 'utf8', function(err, data) { if (err) { const errorObj = { msg: 'error', @@ -1195,7 +1418,7 @@ shepherd.post('/coinslist', function(req, res, next) { res.end(JSON.stringify(errorObj)); } else { - fs.writeFile(`${cache.iguanaDir}/shepherd/coinslist.json`, JSON.stringify(_payload), function (err) { + fs.writeFile(`${cache.iguanaDir}/shepherd/coinslist.json`, JSON.stringify(_payload), function(err) { if (err) { const errorObj = { msg: 'error', @@ -1259,7 +1482,8 @@ shepherd.quitKomodod = function(timeout = 100) { } shepherd.getConf = function(chain) { - const _confLocation = chain === 'komodod' ? `${komodoDir}/komodo.conf` : `${komodoDir}/${chain}/${chain}.conf`; + const _confLocation = chain === 'komodod' ? (os.platform() === 'darwin' ? `${komodoDir}/Komodo.conf` : `${komodoDir}/komodo.conf`) : `${komodoDir}/${chain}/${chain}.conf`; + // komodoDir if (fs.existsSync(_confLocation)) { const _port = assetChainPorts[chain]; @@ -1296,6 +1520,8 @@ shepherd.getConf = function(chain) { * params: payload */ shepherd.post('/cli', function(req, res, next) { + console.log('cli payload ->'); + console.log(req.body.payload); if (!req.body.payload) { const errorObj = { msg: 'error', @@ -1346,7 +1572,7 @@ shepherd.post('/cli', function(req, res, next) { // send back body on both success and error // this bit replicates iguana core's behaviour - request(options, function (error, response, body) { + request(options, function(error, response, body) { if (response && response.statusCode && response.statusCode === 200) { @@ -1600,7 +1826,7 @@ shepherd.getSyncOnlyForksInfo = function() { request({ url: `http://localhost:${port}/api/bitcoinrpc/getinfo?userpass=tmpIgRPCUser@${shepherd.appSessionHash}`, method: 'GET' - }, function (error, response, body) { + }, function(error, response, body) { if (response && response.statusCode && response.statusCode === 200) { @@ -1615,7 +1841,7 @@ shepherd.getSyncOnlyForksInfo = function() { request({ url: `http://localhost:${port}/api/SuperNET/activehandle?userpass=${shepherd.appSessionHash}`, method: 'GET' - }, function (error, response, body) { + }, function(error, response, body) { if (response && response.statusCode && response.statusCode === 200) { @@ -1825,7 +2051,7 @@ shepherd.get('/InstantDEX/allcoins', function(req, res, next) { request({ url: `http://localhost:${shepherd.appConfig.iguanaCorePort}/api/InstantDEX/allcoins?userpass=${req.query.userpass}`, method: 'GET' - }, function (error, response, body) { + }, function(error, response, body) { if (response && response.statusCode && response.statusCode === 200) { @@ -1864,7 +2090,7 @@ shepherd.get('/SuperNET/activehandle', function(req, res, next) { // not finishe request({ url: `http://localhost:${shepherd.appConfig.iguanaCorePort}/api/SuperNET/activehandle?userpass=${req.query.userpass}`, method: 'GET' - }, function (error, response, body) { + }, function(error, response, body) { if (response && response.statusCode && response.statusCode === 200) { @@ -2363,7 +2589,7 @@ function herder(flock, data) { }); // COPY CONFS DIR WITH PEERS FILE TO IGUANA DIR, AND KEEP IT IN SYNC - fs.copy(iguanaConfsDirSrc, iguanaConfsDir, function (err) { + fs.copy(iguanaConfsDirSrc, iguanaConfsDir, function(err) { if (err) return console.error(err); @@ -2576,7 +2802,7 @@ shepherd.setConfKMD = function() { } // check if kmd conf exists - _fs.access(`${komodoDir}/komodo.conf`, fs.constants.R_OK, function(err) { + _fs.access(os.platform() === 'darwin' ? `${komodoDir}/Komodo.conf` : `${komodoDir}/komodo.conf`, fs.constants.R_OK, function(err) { if (err) { console.log('creating komodo conf'); shepherd.writeLog(`creating komodo conf in ${komodoDir}/komodo.conf`); @@ -2613,7 +2839,7 @@ function setConf(flock) { let DaemonConfPath; switch (flock) { case 'komodod': - DaemonConfPath = `${komodoDir}/komodo.conf`; + DaemonConfPath = os.platform() === 'darwin' ? `${komodoDir}/Komodo.conf` : `${komodoDir}/komodo.conf`; if (os.platform() === 'win32') { DaemonConfPath = path.normalize(DaemonConfPath); diff --git a/version b/version index 19b92d7..9ce0cf2 100644 --- a/version +++ b/version @@ -1,3 +1,3 @@ -version=0.2.0.21a +version=0.2.0.22a type=e-beta minversion=0.2.0.2 \ No newline at end of file diff --git a/version_build b/version_build index 9028718..34b9960 100644 --- a/version_build +++ b/version_build @@ -1 +1 @@ -0.2.0.1a-beta +0.2.0.22a-beta