Browse Source

cleanup

pkg_automation_electrum
pbca26 7 years ago
parent
commit
381cc54fd3
  1. 5
      main.js
  2. 1
      routes/shepherd.js
  3. 6
      routes/shepherd/addCoinShortcuts.js
  4. 27
      routes/shepherd/appInfo.js
  5. 48
      routes/shepherd/auth.js
  6. 239
      routes/shepherd/binsTestUtil.js
  7. 141
      routes/shepherd/coindWalletKeys.js
  8. 41
      routes/shepherd/coins.js
  9. 94
      routes/shepherd/coinsList.js
  10. 65
      routes/shepherd/config.js
  11. 199
      routes/shepherd/daemonControl.js
  12. 518
      routes/shepherd/dashboardUpdate.js
  13. 122
      routes/shepherd/debugLog.js
  14. 208
      routes/shepherd/downloadBins.js
  15. 147
      routes/shepherd/downloadPatch.js
  16. 107
      routes/shepherd/downloadZcparams.js
  17. 139
      routes/shepherd/electrum/auth.js
  18. 201
      routes/shepherd/electrum/balance.js
  19. 46
      routes/shepherd/electrum/block.js
  20. 73
      routes/shepherd/electrum/coins.js
  21. 735
      routes/shepherd/electrum/createtx.js
  22. 31
      routes/shepherd/electrum/estimate.js
  23. 219
      routes/shepherd/electrum/keys.js
  24. 73
      routes/shepherd/electrum/listunspent.js
  25. 27
      routes/shepherd/electrum/merkle.js
  26. 147
      routes/shepherd/electrum/network.js
  27. 454
      routes/shepherd/electrum/transactions.js
  28. 59
      routes/shepherd/kickstart.js
  29. 127
      routes/shepherd/log.js
  30. 209
      routes/shepherd/pin.js
  31. 132
      routes/shepherd/quitDaemon.js
  32. 451
      routes/shepherd/rpc.js

5
main.js

@ -57,7 +57,6 @@ shepherd.createAgamaDirs();
const appSessionHash = md5(Date.now().toString()); const appSessionHash = md5(Date.now().toString());
const _spvFees = shepherd.getSpvFees(); const _spvFees = shepherd.getSpvFees();
shepherd.writeLog(`app init ${appSessionHash}`);
shepherd.writeLog(`app info: ${appBasicInfo.name} ${appBasicInfo.version}`); shepherd.writeLog(`app info: ${appBasicInfo.name} ${appBasicInfo.version}`);
shepherd.writeLog('sys info:'); shepherd.writeLog('sys info:');
shepherd.writeLog(`totalmem_readable: ${formatBytes(os.totalmem())}`); shepherd.writeLog(`totalmem_readable: ${formatBytes(os.totalmem())}`);
@ -68,7 +67,9 @@ shepherd.writeLog(`platform: ${osPlatform}`);
shepherd.writeLog(`os_release: ${os.release()}`); shepherd.writeLog(`os_release: ${os.release()}`);
shepherd.writeLog(`os_type: ${os.type()}`); 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(`app info: ${appBasicInfo.name} ${appBasicInfo.version}`);
shepherd.log('sys info:'); shepherd.log('sys info:');
shepherd.log(`totalmem_readable: ${formatBytes(os.totalmem())}`); shepherd.log(`totalmem_readable: ${formatBytes(os.totalmem())}`);

1
routes/shepherd.js

@ -107,7 +107,6 @@ shepherd = require('./shepherd/dex/electrumServersList.js')(shepherd);
// core // core
shepherd = require('./shepherd/addCoinShortcuts.js')(shepherd); shepherd = require('./shepherd/addCoinShortcuts.js')(shepherd);
shepherd = require('./shepherd/dashboardUpdate.js')(shepherd); shepherd = require('./shepherd/dashboardUpdate.js')(shepherd);
shepherd = require('./shepherd/binsTestUtil.js')(shepherd);
shepherd = require('./shepherd/binsUtils.js')(shepherd); shepherd = require('./shepherd/binsUtils.js')(shepherd);
shepherd = require('./shepherd/downloadUtil.js')(shepherd); shepherd = require('./shepherd/downloadUtil.js')(shepherd);
shepherd = require('./shepherd/init.js')(shepherd); shepherd = require('./shepherd/init.js')(shepherd);

6
routes/shepherd/addCoinShortcuts.js

@ -40,7 +40,8 @@ module.exports = (shepherd) => {
body: JSON.stringify({ body: JSON.stringify({
herd: 'komodod', herd: 'komodod',
options: herdData, options: herdData,
}) token: shepherd.appSessionHash,
}),
}; };
shepherd.request(options, (error, response, body) => { shepherd.request(options, (error, response, body) => {
@ -90,7 +91,8 @@ module.exports = (shepherd) => {
body: JSON.stringify({ body: JSON.stringify({
herd: 'komodod', herd: 'komodod',
options: herdData[i], options: herdData[i],
}) token: shepherd.appSessionHash,
}),
}; };
shepherd.request(options, (error, response, body) => { shepherd.request(options, (error, response, body) => {

27
routes/shepherd/appInfo.js

@ -52,7 +52,6 @@ module.exports = (shepherd) => {
sysInfo, sysInfo,
releaseInfo, releaseInfo,
dirs, dirs,
appSession: shepherd.appSessionHash,
}; };
} }
@ -61,8 +60,17 @@ module.exports = (shepherd) => {
* *
*/ */
shepherd.get('/sysinfo', (req, res, next) => { shepherd.get('/sysinfo', (req, res, next) => {
const obj = shepherd.SystemInfo(); if (shepherd.checkToken(req.query.token)) {
res.send(obj); 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) => { shepherd.get('/appinfo', (req, res, next) => {
const obj = shepherd.appInfo(); if (shepherd.checkToken(req.query.token)) {
res.send(obj); const obj = shepherd.appInfo();
res.send(obj);
} else {
const errorObj = {
msg: 'error',
result: 'unauthorized access',
};
res.end(JSON.stringify(errorObj));
}
}); });
return shepherd; return shepherd;

48
routes/shepherd/auth.js

@ -3,29 +3,45 @@ module.exports = (shepherd) => {
* type: GET * type: GET
* *
*/ */
shepherd.get('/auth/status', (req, res, next) => { // not finished shepherd.get('/auth/status', (req, res, next) => {
let successObj; if (shepherd.checkToken(req.query.token)) {
let _status = false; let successObj;
let _status = false;
if (Object.keys(shepherd.coindInstanceRegistry).length) { if (Object.keys(shepherd.coindInstanceRegistry).length) {
if (Object.keys(shepherd.electrumCoins).length > 1 && if (Object.keys(shepherd.electrumCoins).length > 1 &&
shepherd.electrumCoins.auth) { 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; _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; _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 = { successObj = {
status: _status ? 'unlocked' : 'locked', 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; return shepherd;
}; };

239
routes/shepherd/binsTestUtil.js

@ -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;
};

141
routes/shepherd/coindWalletKeys.js

@ -4,94 +4,103 @@ module.exports = (shepherd) => {
* *
*/ */
shepherd.get('/coindwalletkeys', (req, res, next) => { shepherd.get('/coindwalletkeys', (req, res, next) => {
const wif = require('wif'); if (shepherd.checkToken(req.query.token)) {
const fs = require('fs'); const wif = require('wif');
const chain = req.query.chain; const fs = require('fs');
const chain = req.query.chain;
// ref: https://gist.github.com/kendricktan/1e62495150ad236b38616d733aac4eb9 // ref: https://gist.github.com/kendricktan/1e62495150ad236b38616d733aac4eb9
let _walletDatLocation = chain === 'komodo' || chain === 'null' ? `${shepherd.komodoDir}/wallet.dat` : `${shepherd.komodoDir}/${chain}/wallet.dat`; let _walletDatLocation = chain === 'komodo' || chain === 'null' ? `${shepherd.komodoDir}/wallet.dat` : `${shepherd.komodoDir}/${chain}/wallet.dat`;
_walletDatLocation = chain === 'CHIPS' ? `${shepherd.chipsDir}/wallet.dat` : _walletDatLocation; _walletDatLocation = chain === 'CHIPS' ? `${shepherd.chipsDir}/wallet.dat` : _walletDatLocation;
try { try {
shepherd._fs.access(_walletDatLocation, shepherd.fs.constants.R_OK, (err) => { shepherd._fs.access(_walletDatLocation, shepherd.fs.constants.R_OK, (err) => {
if (err) { if (err) {
shepherd.log(`error reading ${_walletDatLocation}`); shepherd.log(`error reading ${_walletDatLocation}`);
successObj = { successObj = {
msg: 'error', msg: 'error',
result: `error reading ${_walletDatLocation}`, 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?');
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 = { successObj = {
msg: 'error', msg: 'error',
result: 'wallet is encrypted?', result: `error reading ${_walletDatLocation}`,
}; };
res.end(JSON.stringify(successObj)); res.end(JSON.stringify(successObj));
} else { } else {
let _keys = []; const re = /\x30\x81\xD3\x02\x01\x01\x04\x20(.{32})/gm;
privateKeys = privateKeys.map(x => x.replace('\x30\x81\xD3\x02\x01\x01\x04\x20', '')); const dataHexStr = data.toString('latin1');
privateKeys = privateKeys.filter((v, i, a) => a.indexOf(v) === i); privateKeys = dataHexStr.match(re);
shepherd.log(`found ${privateKeys.length} keys`);
for (let i = 0; i < privateKeys.length; i++) { if (!privateKeys) {
const privateKey = new Buffer(Buffer.from(privateKeys[i], 'latin1').toString('hex'), 'hex'); shepherd.log('wallet is encrypted?');
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); successObj = {
const _keyPair = { msg: 'error',
priv: keyPair.toWIF(), result: 'wallet is encrypted?',
pub: keyPair.getAddress(),
}; };
if (req.query.search) { res.end(JSON.stringify(successObj));
if (_keyPair.pub.indexOf(req.query.search) > -1) { } 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); _keys.push(_keyPair);
} }
} else {
_keys.push(_keyPair);
} }
}
successObj = { successObj = {
msg: 'success', msg: 'success',
result: _keys, result: _keys,
}; };
res.end(JSON.stringify(successObj)); res.end(JSON.stringify(successObj));
}
} }
} });
}); }
} });
}); } catch (e) {
} catch (e) { successObj = {
successObj = { msg: 'error',
result: `error reading ${_walletDatLocation}`,
};
res.end(JSON.stringify(successObj));
}
} else {
const errorObj = {
msg: 'error', msg: 'error',
result: `error reading ${_walletDatLocation}`, result: 'unauthorized access',
}; };
res.end(JSON.stringify(successObj)); res.end(JSON.stringify(errorObj));
} }
}); });

41
routes/shepherd/coins.js

@ -4,27 +4,36 @@ module.exports = (shepherd) => {
* *
*/ */
shepherd.get('/InstantDEX/allcoins', (req, res, next) => { shepherd.get('/InstantDEX/allcoins', (req, res, next) => {
let successObj; if (shepherd.checkToken(req.query.token)) {
let nativeCoindList = []; let successObj;
let electrumCoinsList = []; let nativeCoindList = [];
let electrumCoinsList = [];
for (let key in shepherd.electrumCoins) { for (let key in shepherd.electrumCoins) {
if (key !== 'auth') { if (key !== 'auth') {
electrumCoinsList.push(shepherd.electrumCoins[key].abbr); electrumCoinsList.push(shepherd.electrumCoins[key].abbr);
}
} }
}
for (let key in shepherd.coindInstanceRegistry) { for (let key in shepherd.coindInstanceRegistry) {
nativeCoindList.push(key === 'komodod' ? 'KMD' : key); nativeCoindList.push(key === 'komodod' ? 'KMD' : key);
} }
successObj = { successObj = {
native: nativeCoindList, native: nativeCoindList,
spv: electrumCoinsList, spv: electrumCoinsList,
total: Object.keys(shepherd.electrumCoins).length - 1 + Object.keys(nativeCoindList).length, 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; return shepherd;

94
routes/shepherd/coinsList.js

@ -4,28 +4,37 @@ module.exports = (shepherd) => {
* *
*/ */
shepherd.get('/coinslist', (req, res, next) => { shepherd.get('/coinslist', (req, res, next) => {
if (shepherd.fs.existsSync(`${shepherd.agamaDir}/shepherd/coinslist.json`)) { if (shepherd.checkToken(req.query.token)) {
shepherd.fs.readFile(`${shepherd.agamaDir}/shepherd/coinslist.json`, 'utf8', (err, data) => { if (shepherd.fs.existsSync(`${shepherd.agamaDir}/shepherd/coinslist.json`)) {
if (err) { shepherd.fs.readFile(`${shepherd.agamaDir}/shepherd/coinslist.json`, 'utf8', (err, data) => {
const errorObj = { if (err) {
msg: 'error', const errorObj = {
result: err, msg: 'error',
}; result: err,
};
res.end(JSON.stringify(errorObj)); res.end(JSON.stringify(errorObj));
} else { } else {
const successObj = { const successObj = {
msg: 'success', msg: 'success',
result: data ? JSON.parse(data) : '', 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 { } else {
const errorObj = { const errorObj = {
msg: 'error', msg: 'error',
result: 'coin list doesn\'t exist', result: 'unauthorized access',
}; };
res.end(JSON.stringify(errorObj)); res.end(JSON.stringify(errorObj));
@ -37,33 +46,42 @@ module.exports = (shepherd) => {
* params: payload * params: payload
*/ */
shepherd.post('/coinslist', (req, res, next) => { 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 = { const errorObj = {
msg: 'error', msg: 'error',
result: 'no payload provided', result: 'unauthorized access',
}; };
res.end(JSON.stringify(errorObj)); 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));
}
});
} }
}); });

65
routes/shepherd/config.js

@ -105,22 +105,31 @@ module.exports = (shepherd) => {
* params: payload * params: payload
*/ */
shepherd.post('/appconf', (req, res, next) => { 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 = { const errorObj = {
msg: 'error', msg: 'error',
result: 'no payload provided', result: 'unauthorized access',
}; };
res.end(JSON.stringify(errorObj)); 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 * params: none
*/ */
shepherd.post('/appconf/reset', (req, res, next) => { 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 = { res.end(JSON.stringify(successObj));
msg: 'success', } else {
result: 'config saved', 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) => { shepherd.get('/appconf', (req, res, next) => {
const obj = shepherd.loadLocalConfig(); if (shepherd.checkToken(req.query.token)) {
res.send(obj); const obj = shepherd.loadLocalConfig();
res.send(obj);
} else {
const errorObj = {
msg: 'error',
result: 'unauthorized access',
};
res.end(JSON.stringify(errorObj));
}
}); });
return shepherd; return shepherd;

199
routes/shepherd/daemonControl.js

@ -792,69 +792,81 @@ module.exports = (shepherd) => {
* params: herd * params: herd
*/ */
shepherd.post('/herd', (req, res) => { shepherd.post('/herd', (req, res) => {
const _body = req.body; if (shepherd.checkToken(req.body.token)) {
shepherd.log('herd req.body =>'); const _body = req.body;
shepherd.log(_body); shepherd.log('herd req.body =>');
shepherd.log(_body);
if (_body.options &&
!shepherd.kmdMainPassiveMode) { if (_body.options &&
const testCoindPort = (skipError) => { !shepherd.kmdMainPassiveMode) {
const _acName = req.body.options.ac_name; const testCoindPort = (skipError) => {
const _acName = req.body.options.ac_name;
if (!shepherd.lockDownAddCoin) {
const _port = shepherd.assetChainPorts[_acName]; 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 portscanner.checkPortStatus(_port, '127.0.0.1', (error, status) => {
if (status === 'open' && // Status is 'open' if currently in use or 'closed' if available
shepherd.appConfig.stopNativeDaemonsOnQuit) { if (status === 'open' &&
if (!skipError) { shepherd.appConfig.stopNativeDaemonsOnQuit) {
shepherd.log(`komodod service start error at port ${_port}, reason: port is closed`); if (!skipError) {
shepherd.writeLog(`komodod service start error at port ${_port}, reason: port is closed`); shepherd.log(`komodod service start error at port ${_port}, reason: port is closed`);
shepherd.io.emit('service', { shepherd.writeLog(`komodod service start error at port ${_port}, reason: port is closed`);
komodod: { shepherd.io.emit('service', {
error: `error starting ${_body.herd} ${_acName} daemon. Port ${_port} is already taken!`, komodod: {
}, error: `error starting ${_body.herd} ${_acName} daemon. Port ${_port} is already taken!`,
}); },
});
const obj = { const obj = {
msg: 'error', msg: 'error',
result: `error starting ${_body.herd} ${_acName} daemon. Port ${_port} is already taken!`, result: `error starting ${_body.herd} ${_acName} daemon. Port ${_port} is already taken!`,
}; };
res.status(500); res.status(500);
res.end(JSON.stringify(obj)); 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 { } else {
shepherd.log(`komodod service start success at port ${_port}`); if (!skipError) {
shepherd.writeLog(`komodod service start success at port ${_port}`); herder(_body.herd, _body.options);
}
} else {
if (!skipError) {
herder(_body.herd, _body.options);
const obj = { const obj = {
msg: 'success', msg: 'success',
result: 'result', result: 'result',
}; };
res.end(JSON.stringify(obj)); res.end(JSON.stringify(obj));
} else { } else {
shepherd.log(`komodod service start error at port ${_port}, reason: unknown`); shepherd.log(`komodod service start error at port ${_port}, reason: unknown`);
shepherd.writeLog(`komodod service start error at port ${_port}, reason: unknown`); shepherd.writeLog(`komodod service start error at port ${_port}, reason: unknown`);
}
} }
} });
}); }
} }
}
if (_body.herd === 'komodod') { if (_body.herd === 'komodod') {
// check if komodod instance is already running // check if komodod instance is already running
testCoindPort(); testCoindPort();
setTimeout(() => { setTimeout(() => {
testCoindPort(true); testCoindPort(true);
}, 10000); }, 10000);
} else {
herder(_body.herd, _body.options, _body.coind);
const obj = {
msg: 'success',
result: 'result',
};
res.end(JSON.stringify(obj));
}
} else { } else {
herder(_body.herd, _body.options, _body.coind); // (?)
herder(_body.herd, _body.options);
const obj = { const obj = {
msg: 'success', msg: 'success',
@ -864,15 +876,12 @@ module.exports = (shepherd) => {
res.end(JSON.stringify(obj)); res.end(JSON.stringify(obj));
} }
} else { } else {
// (?) const errorObj = {
herder(_body.herd, _body.options); msg: 'error',
result: 'unauthorized access',
const obj = {
msg: 'success',
result: 'result',
}; };
res.end(JSON.stringify(obj)); res.end(JSON.stringify(errorObj));
} }
}); });
@ -880,46 +889,64 @@ module.exports = (shepherd) => {
* type: POST * type: POST
*/ */
shepherd.post('/setconf', (req, res) => { 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('setconf req.body =>');
shepherd.log(_body); shepherd.log(_body);
if (os.platform() === 'win32' && if (os.platform() === 'win32' &&
_body.chain == 'komodod') { _body.chain == 'komodod') {
setkomodoconf = spawn(path.join(__dirname, '../assets/bin/win64/genkmdconf.bat')); setkomodoconf = spawn(path.join(__dirname, '../assets/bin/win64/genkmdconf.bat'));
} else { } else {
shepherd.setConf(_body.chain); shepherd.setConf(_body.chain);
} }
const obj = { const obj = {
msg: 'success', msg: 'success',
result: 'result', 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 * type: POST
*/ */
shepherd.post('/getconf', (req, res) => { 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('getconf req.body =>');
shepherd.log(_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.log(`getconf path is: ${confpath}`);
shepherd.writeLog(`getconf path is: ${confpath}`); shepherd.writeLog(`getconf path is: ${confpath}`);
const obj = { const obj = {
msg: 'success', msg: 'success',
result: confpath, 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) => { shepherd.setConfKMD = (isChips) => {

518
routes/shepherd/dashboardUpdate.js

@ -7,171 +7,186 @@ module.exports = (shepherd) => {
* params: coin * params: coin
*/ */
shepherd.post('/native/dashboard/update', (req, res, next) => { shepherd.post('/native/dashboard/update', (req, res, next) => {
const _coin = req.body.coin; if (shepherd.checkToken(req.body.token)) {
let _returnObj; const _coin = req.body.coin;
let _promiseStack; const _token = req.body.token;
let _returnObj;
if (_coin === 'CHIPS') { let _promiseStack;
_returnObj = {
getinfo: {}, if (_coin === 'CHIPS') {
listtransactions: [], _returnObj = {
getbalance: {}, getinfo: {},
listunspent: {}, listtransactions: [],
addresses: {}, getbalance: {},
}; listunspent: {},
_promiseStack = [ addresses: {},
'getinfo', };
'listtransactions', _promiseStack = [
'getbalance', 'getinfo',
]; 'listtransactions',
} else { 'getbalance',
_returnObj = { ];
getinfo: {}, } else {
listtransactions: [], _returnObj = {
z_gettotalbalance: {}, getinfo: {},
z_getoperationstatus: {}, listtransactions: [],
listunspent: {}, z_gettotalbalance: {},
addresses: {}, z_getoperationstatus: {},
}; listunspent: {},
_promiseStack = [ addresses: {},
'getinfo', };
'listtransactions', _promiseStack = [
'z_gettotalbalance', 'getinfo',
'z_getoperationstatus' 'listtransactions',
]; 'z_gettotalbalance',
} 'z_getoperationstatus'
];
}
const getAddressesNative = (coin) => { const getAddressesNative = (coin) => {
const type = [ const type = [
'public', 'public',
'private' 'private'
]; ];
if (coin === 'CHIPS') { if (coin === 'CHIPS') {
type.pop(); type.pop();
} }
Promise.all(type.map((_type, index) => { Promise.all(type.map((_type, index) => {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
_bitcoinRPC( _bitcoinRPC(
coin, coin,
_type === 'public' ? 'getaddressesbyaccount' : 'z_listaddresses', _type === 'public' ? 'getaddressesbyaccount' : 'z_listaddresses',
[''] ['']
).then((_json) => { ).then((_json) => {
if (_json === 'Work queue depth exceeded' || if (_json === 'Work queue depth exceeded' ||
!_json) { !_json) {
resolve({ error: 'daemon is busy' }); resolve({ error: 'daemon is busy' });
} else { } else {
resolve(JSON.parse(_json).result); resolve(JSON.parse(_json).result);
} }
});
}); });
}); }))
})) .then(result => {
.then(result => { if (result[0] &&
if (result[0] && result[0].length &&
result[0].length && result[0][0].length &&
result[0][0].length && result[0][0].length > 10) {
result[0][0].length > 10) { const calcBalance = (result, json) => {
const calcBalance = (result, json) => { if (json &&
if (json && json.length &&
json.length && json[0] &&
json[0] && json[0].address) {
json[0].address) { const allAddrArray = json.map(res => res.address).filter((x, i, a) => a.indexOf(x) == i);
const allAddrArray = json.map(res => res.address).filter((x, i, a) => a.indexOf(x) == i);
for (let a = 0; a < allAddrArray.length; a++) {
for (let a = 0; a < allAddrArray.length; a++) { const filteredArray = json.filter(res => res.address === allAddrArray[a]).map(res => res.amount);
const filteredArray = json.filter(res => res.address === allAddrArray[a]).map(res => res.amount);
let isNewAddr = true;
let isNewAddr = true; for (let x = 0; x < result.length && isNewAddr; x++) {
for (let x = 0; x < result.length && isNewAddr; x++) { for (let y = 0; y < result[x].length && isNewAddr; y++) {
for (let y = 0; y < result[x].length && isNewAddr; y++) { if (allAddrArray[a] === result[x][y]) {
if (allAddrArray[a] === result[x][y]) { isNewAddr = false;
isNewAddr = false; }
} }
} }
}
if (isNewAddr && if (isNewAddr &&
(allAddrArray[a].substring(0, 2) === 'zc' || (allAddrArray[a].substring(0, 2) === 'zc' ||
allAddrArray[a].substring(0, 2) === 'zt')) { allAddrArray[a].substring(0, 2) === 'zt')) {
result[1][result[1].length] = allAddrArray[a]; result[1][result[1].length] = allAddrArray[a];
} else { } else {
result[0][result[0].length] = allAddrArray[a]; result[0][result[0].length] = allAddrArray[a];
}
} }
} }
}
// remove addr duplicates // remove addr duplicates
if (result[0] && if (result[0] &&
result[0].length) { result[0].length) {
result[0] = result[0].filter((elem, pos) => { result[0] = result[0].filter((elem, pos) => {
return result[0].indexOf(elem) === pos; return result[0].indexOf(elem) === pos;
}); });
} }
if (result[1] && if (result[1] &&
result[1].length) { result[1].length) {
result[1] = result[1].filter((elem, pos) => { result[1] = result[1].filter((elem, pos) => {
return result[1].indexOf(elem) === pos; return result[1].indexOf(elem) === pos;
}); });
} }
let newAddressArray = []; let newAddressArray = [];
for (let a = 0; a < result.length; a++) { for (let a = 0; a < result.length; a++) {
newAddressArray[a] = []; newAddressArray[a] = [];
if (result[a]) { if (result[a]) {
for (let b = 0; b < result[a].length; b++) { for (let b = 0; b < result[a].length; b++) {
const filteredArraySpends = json.filter(res => res.address === result[a][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); const filteredArray = json.filter(res => res.address === result[a][b]).map(res => res.amount);
let sum = 0; let sum = 0;
let spendableSum = 0; let spendableSum = 0;
let canspend = true; let canspend = true;
for (let i = 0; i < filteredArray.length; i++) { for (let i = 0; i < filteredArray.length; i++) {
sum += filteredArray[i]; sum += filteredArray[i];
if (filteredArraySpends[i].spendable) { if (filteredArraySpends[i].spendable) {
spendableSum += filteredArray[i]; spendableSum += filteredArray[i];
} else { } else {
canspend = false; canspend = false;
}
} }
}
newAddressArray[a][b] = { newAddressArray[a][b] = {
address: result[a][b], address: result[a][b],
amount: sum, amount: sum,
spendable: spendableSum, spendable: spendableSum,
canspend, canspend,
type: a === 0 ? 'public': 'private', type: a === 0 ? 'public': 'private',
}; };
}
} }
} }
}
// get zaddr balance // get zaddr balance
if (result[1] && if (result[1] &&
result[1].length) { result[1].length) {
Promise.all(result[1].map((_address, index) => { Promise.all(result[1].map((_address, index) => {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
_bitcoinRPC(coin, 'z_getbalance', [_address]) _bitcoinRPC(coin, 'z_getbalance', [_address])
.then((__json) => { .then((__json) => {
__json = JSON.parse(__json); __json = JSON.parse(__json);
if (__json && if (__json &&
__json.error) { __json.error) {
resolve(0); resolve(0);
} else { } else {
resolve(__json.result); resolve(__json.result);
newAddressArray[1][index] = { newAddressArray[1][index] = {
address: _address, address: _address,
amount: __json.result, amount: __json.result,
type: 'private', type: 'private',
}; };
} }
});
}); });
}))
.then(zresult => {
_returnObj.addresses = {
public: newAddressArray[0],
private: newAddressArray[1],
};
const returnObj = {
msg: 'success',
result: _returnObj,
};
res.end(JSON.stringify(returnObj));
}); });
})) } else {
.then(zresult => {
_returnObj.addresses = { _returnObj.addresses = {
public: newAddressArray[0], public: newAddressArray[0],
private: newAddressArray[1], private: newAddressArray[1],
@ -183,131 +198,128 @@ module.exports = (shepherd) => {
}; };
res.end(JSON.stringify(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((__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( _bitcoinRPC(coin, 'listunspent')
result, .then((__json) => {
JSON.parse(__json).result if (__json === 'Work queue depth exceeded' ||
); !__json) {
} const returnObj = {
}); msg: 'success',
} else { result: _returnObj,
_returnObj.addresses = { };
public: {},
private: {},
};
const returnObj = { res.end(JSON.stringify(returnObj));
msg: 'success', } else {
result: _returnObj, _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) => { const returnObj = {
return new Promise((resolve, reject) => { msg: 'success',
let _payload; result: _returnObj,
};
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 options = { res.end(JSON.stringify(returnObj));
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,
};
shepherd.request(options, (error, response, body) => { const _bitcoinRPC = (coin, cmd, params) => {
if (response && return new Promise((resolve, reject) => {
response.statusCode && let _payload;
response.statusCode === 200) {
resolve(body); if (params) {
_payload = {
mode: null,
chain: coin,
cmd: cmd,
params: params,
rpc2cli: req.body.rpc2cli,
token: _token,
};
} else { } else {
resolve(body); _payload = {
mode: null,
chain: coin,
cmd: cmd,
rpc2cli: req.body.rpc2cli,
token: _token,
};
} }
});
});
}
Promise.all(_promiseStack.map((_call, index) => { const options = {
let _params; 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') { shepherd.request(options, (error, response, body) => {
_params = [ if (response &&
'*', response.statusCode &&
300, response.statusCode === 200) {
0 resolve(body);
]; } else {
resolve(body);
}
});
});
} }
return new Promise((resolve, reject) => { Promise.all(_promiseStack.map((_call, index) => {
_bitcoinRPC( let _params;
_coin,
_call, if (_call === 'listtransactions') {
_params _params = [
) '*',
.then((json) => { 300,
if (json === 'Work queue depth exceeded' || 0
!json) { ];
_returnObj[_call] = { error: 'daemon is busy' }; }
} else {
_returnObj[_call] = JSON.parse(json); return new Promise((resolve, reject) => {
} _bitcoinRPC(
resolve(json); _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);
}); });
})) } else {
.then(result => { const errorObj = {
getAddressesNative(_coin); msg: 'error',
}); result: 'unauthorized access',
};
res.end(JSON.stringify(errorObj));
}
}); });
return shepherd; return shepherd;

122
routes/shepherd/debugLog.js

@ -4,74 +4,92 @@ module.exports = (shepherd) => {
* params: herd, lastLines * params: herd, lastLines
*/ */
shepherd.post('/debuglog', (req, res) => { shepherd.post('/debuglog', (req, res) => {
let _herd = req.body.herdname; if (shepherd.checkToken(req.body.token)) {
let _ac = req.body.ac; let _herd = req.body.herdname;
let _lastNLines = req.body.lastLines; let _ac = req.body.ac;
let _location; 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() === 'darwin') {
} shepherd.komodoDir = shepherd.appConfig.dataDir.length ? shepherd.appConfig.dataDir : `${process.env.HOME}/Library/Application Support/Komodo`;
}
if (shepherd.os.platform() === 'linux') { if (shepherd.os.platform() === 'linux') {
shepherd.komodoDir = shepherd.appConfig.dataDir.length ? shepherd.appConfig.dataDir : `${process.env.HOME}/.komodo`; shepherd.komodoDir = shepherd.appConfig.dataDir.length ? shepherd.appConfig.dataDir : `${process.env.HOME}/.komodo`;
} }
if (shepherd.os.platform() === 'win32') { if (shepherd.os.platform() === 'win32') {
shepherd.komodoDir = shepherd.appConfig.dataDir.length ? shepherd.appConfig.dataDir : `${process.env.APPDATA}/Komodo`; shepherd.komodoDir = shepherd.appConfig.dataDir.length ? shepherd.appConfig.dataDir : `${process.env.APPDATA}/Komodo`;
shepherd.komodoDir = shepherd.path.normalize(shepherd.komodoDir); shepherd.komodoDir = shepherd.path.normalize(shepherd.komodoDir);
} }
if (_herd === 'komodo') { if (_herd === 'komodo') {
_location = shepherd.komodoDir; _location = shepherd.komodoDir;
} }
if (_ac) { if (_ac) {
_location = `${shepherd.komodoDir}/${_ac}`; _location = `${shepherd.komodoDir}/${_ac}`;
if (_ac === 'CHIPS') { if (_ac === 'CHIPS') {
_location = shepherd.chipsDir; _location = shepherd.chipsDir;
}
} }
}
shepherd.readDebugLog(`${_location}/debug.log`, _lastNLines)
.then((result) => {
const _obj = {
msg: 'success',
result: result,
};
res.end(JSON.stringify(_obj)); shepherd.readDebugLog(`${_location}/debug.log`, _lastNLines)
}, (result) => { .then((result) => {
const _obj = { 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', msg: 'error',
result: result, result: 'unauthorized access',
}; };
res.end(JSON.stringify(_obj)); res.end(JSON.stringify(errorObj));
}); }
}); });
shepherd.get('/coind/stdout', (req, res) => { shepherd.get('/coind/stdout', (req, res) => {
const _daemonName = req.query.chain !== 'komodod' ? req.query.chain : 'komodod'; if (shepherd.checkToken(req.query.token)) {
const _daemonLogName = `${shepherd.agamaDir}/${_daemonName}.log`; const _daemonName = req.query.chain !== 'komodod' ? req.query.chain : 'komodod';
const _daemonLogName = `${shepherd.agamaDir}/${_daemonName}.log`;
shepherd.readDebugLog(_daemonLogName, 'all')
.then((result) => { shepherd.readDebugLog(_daemonLogName, 'all')
const _obj = { .then((result) => {
msg: 'success', const _obj = {
result: result, msg: 'success',
}; result: result,
};
res.end(JSON.stringify(_obj));
}, (result) => { res.end(JSON.stringify(_obj));
const _obj = { }, (result) => {
const _obj = {
msg: 'error',
result: result,
};
res.end(JSON.stringify(_obj));
});
} else {
const errorObj = {
msg: 'error', msg: 'error',
result: result, result: 'unauthorized access',
}; };
res.end(JSON.stringify(_obj)); res.end(JSON.stringify(errorObj));
}); }
}); });
shepherd.readDebugLog = (fileLocation, lastNLines) => { shepherd.readDebugLog = (fileLocation, lastNLines) => {

208
routes/shepherd/downloadBins.js

@ -46,51 +46,60 @@ module.exports = (shepherd) => {
*/ */
// TODO: promises // TODO: promises
shepherd.get('/update/bins/check', (req, res, next) => { shepherd.get('/update/bins/check', (req, res, next) => {
const rootLocation = shepherd.path.join(__dirname, '../../'); if (shepherd.checkToken(req.query.token)) {
const successObj = { const rootLocation = shepherd.path.join(__dirname, '../../');
msg: 'success', const successObj = {
result: 'bins', msg: 'success',
}; result: 'bins',
};
res.end(JSON.stringify(successObj));
res.end(JSON.stringify(successObj));
const _os = shepherd.os.platform();
shepherd.log(`checking bins: ${_os}`); const _os = shepherd.os.platform();
shepherd.log(`checking bins: ${_os}`);
shepherd.io.emit('patch', {
patch: { shepherd.io.emit('patch', {
type: 'bins-check', patch: {
status: 'progress', type: 'bins-check',
message: `checking bins: ${_os}`, 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,
},
});
}
}); });
// 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: * params:
*/ */
shepherd.get('/update/bins', (req, res, next) => { shepherd.get('/update/bins', (req, res, next) => {
const rootLocation = shepherd.path.join(__dirname, '../../'); if (shepherd.checkToken(req.query.token)) {
const _os = shepherd.os.platform(); const rootLocation = shepherd.path.join(__dirname, '../../');
const successObj = { const _os = shepherd.os.platform();
msg: 'success', const successObj = {
result: { msg: 'success',
filesCount: binsToUpdate.length, result: {
list: binsToUpdate, filesCount: binsToUpdate.length,
}, list: binsToUpdate,
}; },
};
res.end(JSON.stringify(successObj));
res.end(JSON.stringify(successObj));
for (let i = 0; i < binsToUpdate.length; i++) {
shepherd.downloadFile({ for (let i = 0; i < binsToUpdate.length; i++) {
remoteFile: remoteBinLocation[_os] + binsToUpdate[i].name, shepherd.downloadFile({
localFile: `${rootLocation}${localBinLocation[_os]}patch/${binsToUpdate[i].name}`, remoteFile: remoteBinLocation[_os] + binsToUpdate[i].name,
onProgress: (received, total) => { localFile: `${rootLocation}${localBinLocation[_os]}patch/${binsToUpdate[i].name}`,
const percentage = (received * 100) / total; onProgress: (received, total) => {
const percentage = (received * 100) / total;
if (percentage.toString().indexOf('.10') > -1) {
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', { shepherd.io.emit('patch', {
msg: { msg: {
type: 'bins-update', type: 'bins-update',
status: 'progress',
file: binsToUpdate[i].name, file: binsToUpdate[i].name,
bytesTotal: total, status: 'done',
bytesReceived: received,
}, },
}); });
// 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(() => { } else {
// verify that remote file is matching to DL'ed file const errorObj = {
const localBinSize = shepherd.fs.statSync(`${rootLocation}${localBinLocation[_os]}patch/${binsToUpdate[i].name}`).size; msg: 'error',
shepherd.log('compare dl file size'); result: 'unauthorized access',
};
if (localBinSize === binsToUpdate[i].rSize) {
shepherd.io.emit('patch', { res.end(JSON.stringify(errorObj));
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!`);
}
});
} }
}); });

147
routes/shepherd/downloadPatch.js

@ -5,14 +5,23 @@ module.exports = (shepherd) => {
* params: patchList * params: patchList
*/ */
shepherd.get('/update/patch', (req, res, next) => { shepherd.get('/update/patch', (req, res, next) => {
const successObj = { if (shepherd.checkToken(req.query.token)) {
msg: 'success', const successObj = {
result: 'dl started' msg: 'success',
}; result: 'dl started'
};
res.end(JSON.stringify(successObj));
res.end(JSON.stringify(successObj));
shepherd.updateAgama();
shepherd.updateAgama();
} else {
const errorObj = {
msg: 'error',
result: 'unauthorized access',
};
res.end(JSON.stringify(errorObj));
}
}); });
shepherd.updateAgama = () => { shepherd.updateAgama = () => {
@ -85,51 +94,60 @@ module.exports = (shepherd) => {
* params: * params:
*/ */
shepherd.get('/update/patch/check', (req, res, next) => { shepherd.get('/update/patch/check', (req, res, next) => {
const rootLocation = shepherd.path.join(__dirname, '../../'); if (shepherd.checkToken(req.query.token)) {
const options = { const rootLocation = shepherd.path.join(__dirname, '../../');
url: 'https://github.com/pbca26/dl-test/raw/master/version', const options = {
method: 'GET', url: 'https://github.com/pbca26/dl-test/raw/master/version',
}; method: 'GET',
};
shepherd.request(options, (error, response, body) => {
if (response && shepherd.request(options, (error, response, body) => {
response.statusCode && if (response &&
response.statusCode === 200) { response.statusCode &&
const remoteVersion = body.split('\n'); response.statusCode === 200) {
const localVersionFile = shepherd.fs.readFileSync(`${rootLocation}version`, 'utf8'); const remoteVersion = body.split('\n');
let localVersion; const localVersionFile = shepherd.fs.readFileSync(`${rootLocation}version`, 'utf8');
let localVersion;
if (localVersionFile.indexOf('\r\n') > -1) {
localVersion = localVersionFile.split('\r\n'); if (localVersionFile.indexOf('\r\n') > -1) {
} else { localVersion = localVersionFile.split('\r\n');
localVersion = localVersionFile.split('\n'); } else {
} localVersion = localVersionFile.split('\n');
}
if (remoteVersion[0] === localVersion[0]) {
const successObj = {
msg: 'success',
result: 'latest',
};
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 { } else {
const successObj = { res.end({
msg: 'success', err: 'error getting update',
result: 'update', });
version: {
local: localVersion[0],
remote: remoteVersion[0],
},
};
res.end(JSON.stringify(successObj));
} }
} else { });
res.end({ } else {
err: 'error getting update', const errorObj = {
}); msg: 'error',
} result: 'unauthorized access',
}); };
res.end(JSON.stringify(errorObj));
}
}); });
/* /*
@ -138,16 +156,25 @@ module.exports = (shepherd) => {
* params: * params:
*/ */
shepherd.get('/unpack', (req, res, next) => { shepherd.get('/unpack', (req, res, next) => {
const dlLocation = shepherd.path.join(__dirname, '../../'); if (shepherd.checkToken(req.query.token)) {
const zip = new shepherd.AdmZip(`${dlLocation}patch.zip`); const dlLocation = shepherd.path.join(__dirname, '../../');
zip.extractAllTo(/*target path*/ `${dlLocation}/patch/unpack`, /*overwrite*/true); const zip = new shepherd.AdmZip(`${dlLocation}patch.zip`);
zip.extractAllTo(/*target path*/ `${dlLocation}/patch/unpack`, /*overwrite*/true);
const successObj = {
msg: 'success', const successObj = {
result: 'unpack started', msg: 'success',
}; result: 'unpack started',
};
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; return shepherd;

107
routes/shepherd/downloadZcparams.js

@ -67,66 +67,75 @@ module.exports = (shepherd) => {
* params: * params:
*/ */
shepherd.get('/zcparamsdl', (req, res, next) => { shepherd.get('/zcparamsdl', (req, res, next) => {
// const dlLocation = shepherd.zcashParamsDir + '/test'; if (shepherd.checkToken(req.query.token)) {
const dlLocation = shepherd.zcashParamsDir; // const dlLocation = shepherd.zcashParamsDir + '/test';
const dlOption = req.query.dloption; const dlLocation = shepherd.zcashParamsDir;
const dlOption = req.query.dloption;
const successObj = { const successObj = {
msg: 'success', msg: 'success',
result: 'zcash params dl started', 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.log(`${key} dl done`);
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) { if (checkZcashParams.error) {
shepherd.io.emit('zcparams', { shepherd.io.emit('zcparams', {
msg: { msg: {
type: 'zcpdownload', type: 'zcpdownload',
status: 'progress',
file: key, file: key,
bytesTotal: total, status: 'error',
bytesReceived: received, message: 'size mismatch',
progress: percentage, 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(() => { } else {
const checkZcashParams = shepherd.zcashParamsExist(); const errorObj = {
msg: 'error',
shepherd.log(`${key} dl done`); result: 'unauthorized access',
};
if (checkZcashParams.error) {
shepherd.io.emit('zcparams', { res.end(JSON.stringify(errorObj));
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`);
}
});
} }
}); });

139
routes/shepherd/electrum/auth.js

@ -4,78 +4,105 @@ const bitcoin = require('bitcoinjs-lib');
module.exports = (shepherd) => { module.exports = (shepherd) => {
shepherd.post('/electrum/login', (req, res, next) => { 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) { for (let key in shepherd.electrumCoins) {
if (key !== 'auth') { if (key !== 'auth') {
const _abbr = key; const _abbr = key;
const _seed = req.body.seed; const _seed = req.body.seed;
let keys; let keys;
let isWif = false; let isWif = false;
try {
bs58check.decode(_seed);
isWif = true;
} catch (e) {}
if (isWif) {
try { 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); bs58check.decode(_seed);
keys = { isWif = true;
priv: key.toWIF(), } catch (e) {}
pub: key.getAddress(),
}; if (isWif) {
} catch (e) { try {
_wifError = 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);
break; 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] = { shepherd.electrumKeys[_abbr] = {
priv: keys.priv, priv: keys.priv,
pub: keys.pub, 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 = { res.end(JSON.stringify(successObj));
msg: _wifError ? 'error' : 'success', } else {
result: 'true', 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.post('/electrum/lock', (req, res, next) => {
shepherd.electrumCoins.auth = false; if (shepherd.checkToken(req.body.token)) {
shepherd.electrumKeys = {}; shepherd.electrumCoins.auth = false;
shepherd.electrumKeys = {};
const successObj = {
msg: 'success', const successObj = {
result: 'true', 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.post('/electrum/logout', (req, res, next) => { shepherd.post('/electrum/logout', (req, res, next) => {
shepherd.electrumCoins = { if (shepherd.checkToken(req.body.token)) {
auth: false, shepherd.electrumCoins = {
}; auth: false,
shepherd.electrumKeys = {}; };
shepherd.electrumKeys = {};
const obj = {
msg: 'success', const obj = {
result: 'result', msg: 'success',
}; result: 'result',
};
res.end(JSON.stringify(obj));
res.end(JSON.stringify(obj));
} else {
const errorObj = {
msg: 'error',
result: 'unauthorized access',
};
res.end(JSON.stringify(errorObj));
}
}); });
return shepherd; return shepherd;

201
routes/shepherd/electrum/balance.js

@ -1,68 +1,86 @@
module.exports = (shepherd) => { module.exports = (shepherd) => {
shepherd.get('/electrum/getbalance', (req, res, next) => { shepherd.get('/electrum/getbalance', (req, res, next) => {
const network = req.query.network || shepherd.findNetworkObj(req.query.coin); if (shepherd.checkToken(req.query.token)) {
const ecl = new shepherd.electrumJSCore(shepherd.electrumServers[network].port, shepherd.electrumServers[network].address, shepherd.electrumServers[network].proto); // tcp or tls 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);
shepherd.log('electrum getbalance =>', true);
ecl.connect();
ecl.blockchainAddressGetBalance(req.query.address) ecl.connect();
.then((json) => { ecl.blockchainAddressGetBalance(req.query.address)
if (json && .then((json) => {
json.hasOwnProperty('confirmed') && if (json &&
json.hasOwnProperty('unconfirmed')) { json.hasOwnProperty('confirmed') &&
if (network === 'komodo') { json.hasOwnProperty('unconfirmed')) {
ecl.connect(); if (network === 'komodo') {
ecl.blockchainAddressListunspent(req.query.address) ecl.connect();
.then((utxoList) => { ecl.blockchainAddressListunspent(req.query.address)
if (utxoList && .then((utxoList) => {
utxoList.length) { if (utxoList &&
// filter out < 10 KMD amounts utxoList.length) {
let _utxo = []; // 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); 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 (Number(utxoList[i].value) * 0.00000001 >= 10) {
_utxo.push(utxoList[i]);
}
} }
}
shepherd.log('filtered utxo list =>', true); shepherd.log('filtered utxo list =>', true);
shepherd.log(_utxo, true); shepherd.log(_utxo, true);
if (_utxo && if (_utxo &&
_utxo.length) { _utxo.length) {
let interestTotal = 0; let interestTotal = 0;
shepherd.Promise.all(_utxo.map((_utxoItem, index) => { shepherd.Promise.all(_utxo.map((_utxoItem, index) => {
return new shepherd.Promise((resolve, reject) => { return new shepherd.Promise((resolve, reject) => {
ecl.blockchainTransactionGet(_utxoItem['tx_hash']) ecl.blockchainTransactionGet(_utxoItem['tx_hash'])
.then((_rawtxJSON) => { .then((_rawtxJSON) => {
shepherd.log('electrum gettransaction ==>', true); shepherd.log('electrum gettransaction ==>', true);
shepherd.log((index + ' | ' + (_rawtxJSON.length - 1)), true); shepherd.log((index + ' | ' + (_rawtxJSON.length - 1)), true);
shepherd.log(_rawtxJSON, true); shepherd.log(_rawtxJSON, true);
// decode tx // decode tx
const _network = shepherd.getNetworkData(network); const _network = shepherd.getNetworkData(network);
const decodedTx = shepherd.electrumJSTxDecoder(_rawtxJSON, network, _network); const decodedTx = shepherd.electrumJSTxDecoder(_rawtxJSON, network, _network);
if (decodedTx && if (decodedTx &&
decodedTx.format && decodedTx.format &&
decodedTx.format.locktime > 0) { decodedTx.format.locktime > 0) {
interestTotal += shepherd.kmdCalcInterest(decodedTx.format.locktime, _utxoItem.value); interestTotal += shepherd.kmdCalcInterest(decodedTx.format.locktime, _utxoItem.value);
} }
shepherd.log('decoded tx =>', true); shepherd.log('decoded tx =>', true);
shepherd.log(decodedTx, 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));
}); });
})) } else {
.then(promiseResult => {
ecl.close();
const successObj = { const successObj = {
msg: 'success', msg: 'success',
result: { result: {
@ -70,15 +88,15 @@ module.exports = (shepherd) => {
unconfirmed: Number((0.00000001 * json.unconfirmed).toFixed(8)), unconfirmed: Number((0.00000001 * json.unconfirmed).toFixed(8)),
unconfirmedSats: json.unconfirmed, unconfirmedSats: json.unconfirmed,
balanceSats: json.confirmed, balanceSats: json.confirmed,
interest: Number(interestTotal.toFixed(8)), interest: 0,
interestSats: Math.floor(interestTotal * 100000000), interestSats: 0,
total: interestTotal > 0 ? Number((0.00000001 * json.confirmed + interestTotal).toFixed(8)) : 0, total: 0,
totalSats: interestTotal > 0 ?json.confirmed + Math.floor(interestTotal * 100000000) : 0, totalSats: 0,
}, },
}; };
res.end(JSON.stringify(successObj)); res.end(JSON.stringify(successObj));
}); }
} else { } else {
const successObj = { const successObj = {
msg: 'success', msg: 'success',
@ -96,50 +114,41 @@ module.exports = (shepherd) => {
res.end(JSON.stringify(successObj)); res.end(JSON.stringify(successObj));
} }
} else { });
const successObj = { } else {
msg: 'success', ecl.close();
result: { shepherd.log('electrum getbalance ==>', true);
balance: Number((0.00000001 * json.confirmed).toFixed(8)), shepherd.log(json, true);
unconfirmed: Number((0.00000001 * json.unconfirmed).toFixed(8)),
unconfirmedSats: json.unconfirmed, const successObj = {
balanceSats: json.confirmed, msg: 'success',
interest: 0, result: {
interestSats: 0, balance: Number((0.00000001 * json.confirmed).toFixed(8)),
total: 0, unconfirmed: Number((0.00000001 * json.unconfirmed).toFixed(8)),
totalSats: 0, unconfirmedSats: json.unconfirmed,
}, balanceSats: json.confirmed,
}; },
};
res.end(JSON.stringify(successObj));
} res.end(JSON.stringify(successObj));
}); }
} else { } else {
ecl.close();
shepherd.log('electrum getbalance ==>', true);
shepherd.log(json, true);
const successObj = { const successObj = {
msg: 'success', msg: 'error',
result: { result: shepherd.CONNECTION_ERROR_OR_INCOMPLETE_DATA,
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)); res.end(JSON.stringify(successObj));
} }
} else { });
const successObj = { } else {
msg: 'error', const errorObj = {
result: shepherd.CONNECTION_ERROR_OR_INCOMPLETE_DATA, msg: 'error',
}; result: 'unauthorized access',
};
res.end(JSON.stringify(successObj));
} res.end(JSON.stringify(errorObj));
}); }
}); });
return shepherd; return shepherd;

46
routes/shepherd/electrum/block.js

@ -1,14 +1,23 @@
module.exports = (shepherd) => { module.exports = (shepherd) => {
shepherd.get('/electrum/getblockinfo', (req, res, next) => { shepherd.get('/electrum/getblockinfo', (req, res, next) => {
shepherd.electrumGetBlockInfo(req.query.height, req.query.network) if (shepherd.checkToken(req.query.token)) {
.then((json) => { shepherd.electrumGetBlockInfo(req.query.height, req.query.network)
const successObj = { .then((json) => {
msg: 'success', const successObj = {
result: json, 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) => { shepherd.electrumGetBlockInfo = (height, network) => {
@ -28,15 +37,24 @@ module.exports = (shepherd) => {
} }
shepherd.get('/electrum/getcurrentblock', (req, res, next) => { shepherd.get('/electrum/getcurrentblock', (req, res, next) => {
shepherd.electrumGetCurrentBlock(req.query.network) if (shepherd.checkToken(req.query.token)) {
.then((json) => { shepherd.electrumGetCurrentBlock(req.query.network)
const successObj = { .then((json) => {
msg: 'success', const successObj = {
result: json, 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) => { shepherd.electrumGetCurrentBlock = (network) => {

73
routes/shepherd/electrum/coins.js

@ -61,7 +61,6 @@ module.exports = (shepherd) => {
priv: _keys.priv, priv: _keys.priv,
pub: _keys.pub, pub: _keys.pub,
}; };
console.log(shepherd.electrumKeys[coin]);
} }
return true; return true;
@ -69,32 +68,70 @@ module.exports = (shepherd) => {
} }
} }
shepherd.get('/electrum/coins/add', (req, res, next) => { shepherd.get('/electrum/coin/changepub', (req, res, next) => {
const result = shepherd.addElectrumCoin(req.query.coin); if (shepherd.checkToken(req.query.token)) {
shepherd.electrumKeys[req.query.coin].pub = req.query.pub;
const successObj = {
msg: 'success',
result: 'true',
};
const successObj = { res.end(JSON.stringify(successObj));
msg: 'success', } else {
result, 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) => { 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) { for (let key in _electrumCoins) {
if (shepherd.electrumKeys[key]) { if (shepherd.electrumKeys[key]) {
_electrumCoins[key].pub = shepherd.electrumKeys[key].pub; _electrumCoins[key].pub = shepherd.electrumKeys[key].pub;
}
} }
}
const successObj = { const successObj = {
msg: 'success', msg: 'success',
result: _electrumCoins, 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; return shepherd;

735
routes/shepherd/electrum/createtx.js

@ -9,14 +9,14 @@ module.exports = (shepherd) => {
// TODO: finish unsigned for zcash, btc forks and pos coins // TODO: finish unsigned for zcash, btc forks and pos coins
if (network === 'btg') { if (network === 'btg') {
shepherd.log('enable btg'); shepherd.log('enable btg', true);
tx = new bitcoinJSForks.TransactionBuilder(shepherd.getNetworkData(network)); tx = new bitcoinJSForks.TransactionBuilder(shepherd.getNetworkData(network));
tx.enableBitcoinGold(true); tx.enableBitcoinGold(true);
} else { } else {
tx = new shepherd.bitcoinJS.TransactionBuilder(shepherd.getNetworkData(network)); tx = new shepherd.bitcoinJS.TransactionBuilder(shepherd.getNetworkData(network));
} }
shepherd.log('buildSignedTx'); shepherd.log('buildSignedTx', true);
// console.log(`buildSignedTx priv key ${wif}`); // console.log(`buildSignedTx priv key ${wif}`);
shepherd.log(`buildSignedTx pub key ${changeAddress}`, true); shepherd.log(`buildSignedTx pub key ${changeAddress}`, true);
// console.log('buildSignedTx std tx fee ' + shepherd.electrumServers[network].txfee); // 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)); tx = new shepherd.bitcoinJS.TransactionBuilder(shepherd.getNetworkData(network));
} }
shepherd.log('buildSignedTx'); shepherd.log('buildSignedTx', true);
// console.log(`buildSignedTx priv key ${wif}`); // console.log(`buildSignedTx priv key ${wif}`);
shepherd.log(`buildSignedTx pub key ${key.getAddress().toString()}`, true); shepherd.log(`buildSignedTx pub key ${key.getAddress().toString()}`, true);
// console.log('buildSignedTx std tx fee ' + shepherd.electrumServers[network].txfee); // 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 pk = bitcoinJSForks.crypto.hash160(keyPair.getPublicKeyBuffer());
const spk = bitcoinJSForks.script.pubKeyHash.output.encode(pk); 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++) { for (let i = 0; i < utxo.length; i++) {
tx.addInput(utxo[i].txid, utxo[i].vout, bitcoinJSForks.Transaction.DEFAULT_SEQUENCE, spk); 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) => { shepherd.get('/electrum/createrawtx', (req, res, next) => {
// TODO: unconf output(s) error message if (shepherd.checkToken(req.query.token)) {
const network = req.query.network || shepherd.findNetworkObj(req.query.coin); // TODO: unconf output(s) error message
const ecl = new shepherd.electrumJSCore(shepherd.electrumServers[network].port, shepherd.electrumServers[network].address, shepherd.electrumServers[network].proto); // tcp or tls const network = req.query.network || shepherd.findNetworkObj(req.query.coin);
const outputAddress = req.query.address; const ecl = new shepherd.electrumJSCore(shepherd.electrumServers[network].port, shepherd.electrumServers[network].address, shepherd.electrumServers[network].proto); // tcp or tls
const changeAddress = req.query.change; const outputAddress = req.query.address;
const push = req.query.push; const changeAddress = req.query.change;
let fee = shepherd.electrumServers[network].txfee; const push = req.query.push;
let value = Number(req.query.value); let fee = shepherd.electrumServers[network].txfee;
let wif = req.query.wif; let value = Number(req.query.value);
let wif = req.query.wif;
if (req.query.gui) {
wif = shepherd.electrumKeys[req.query.coin].priv; if (req.query.gui) {
} wif = shepherd.electrumKeys[req.query.coin].priv;
}
shepherd.log('electrum createrawtx =>', true); shepherd.log('electrum createrawtx =>', true);
ecl.connect(); ecl.connect();
shepherd.listunspent(ecl, changeAddress, network, true, true) shepherd.listunspent(ecl, changeAddress, network, true, true)
.then((utxoList) => { .then((utxoList) => {
ecl.close(); ecl.close();
console.log(utxoList);
if (utxoList &&
utxoList.length && if (utxoList &&
utxoList[0] && utxoList.length &&
utxoList[0].txid) { utxoList[0] &&
let utxoListFormatted = []; utxoList[0].txid) {
let totalInterest = 0; let utxoListFormatted = [];
let totalInterestUTXOCount = 0; let totalInterest = 0;
let interestClaimThreshold = 200; let totalInterestUTXOCount = 0;
let utxoVerified = true; let interestClaimThreshold = 200;
let utxoVerified = true;
for (let i = 0; i < utxoList.length; i++) {
if (network === 'komodo') { for (let i = 0; i < utxoList.length; i++) {
utxoListFormatted.push({ if (network === 'komodo') {
txid: utxoList[i].txid, utxoListFormatted.push({
vout: utxoList[i].vout, txid: utxoList[i].txid,
value: Number(utxoList[i].amountSats), vout: utxoList[i].vout,
interestSats: Number(utxoList[i].interestSats), value: Number(utxoList[i].amountSats),
verified: utxoList[i].verified ? utxoList[i].verified : false, interestSats: Number(utxoList[i].interestSats),
}); verified: utxoList[i].verified ? utxoList[i].verified : false,
} else { });
utxoListFormatted.push({ } else {
txid: utxoList[i].txid, utxoListFormatted.push({
vout: utxoList[i].vout, txid: utxoList[i].txid,
value: Number(utxoList[i].amountSats), vout: utxoList[i].vout,
verified: utxoList[i].verified ? utxoList[i].verified : false, 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)); shepherd.log('electrum listunspent unformatted ==>', true);
let targets = [{ shepherd.log(utxoList, true);
address: outputAddress,
value: value > _maxSpendBalance ? _maxSpendBalance : value,
}];
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 shepherd.log('electrum listunspent formatted ==>', true);
shepherd.log(utxoListFormatted, true);
if (!feeRate) { const _maxSpendBalance = Number(shepherd.maxSpendBalance(utxoListFormatted));
targets[0].value = targets[0].value + fee; let targets = [{
} address: outputAddress,
value: value > _maxSpendBalance ? _maxSpendBalance : value,
shepherd.log(`fee rate ${feeRate}`, true); }];
shepherd.log(`default fee ${fee}`, true); shepherd.log('targets =>', true);
shepherd.log(`targets ==>`, true); shepherd.log(targets, true);
shepherd.log(targets, true);
// default coin selection algo blackjack with fallback to accumulative const feeRate = shepherd.getNetworkData(network).messagePrefix === '\x19Komodo Signed Message:\n' || shepherd.getNetworkData(network).messagePrefix === '\x19Chips Signed Message:\n' ? 20 : 0; // sats/byte
// 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) { if (!feeRate) {
fee = firstRun.fee; targets[0].value = targets[0].value + fee;
} }
shepherd.log('coinselect res =>', true); shepherd.log(`fee rate ${feeRate}`, true);
shepherd.log('coinselect inputs =>', true); shepherd.log(`default fee ${fee}`, true);
shepherd.log(inputs, true); shepherd.log(`targets ==>`, 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); shepherd.log(targets, true);
const secondRun = shepherd.coinSelect(utxoListFormatted, targets, feeRate); // default coin selection algo blackjack with fallback to accumulative
inputs = secondRun.inputs; // make a first run, calc approx tx fee
outputs = secondRun.outputs; // if ins and outs are empty reduce max spend by txfee
fee = secondRun.fee; 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(inputs, true);
shepherd.log('second run coinselect outputs =>', true); shepherd.log('coinselect outputs =>', true);
shepherd.log(outputs, true); shepherd.log(outputs, true);
shepherd.log('second run coinselect fee =>', true); shepherd.log('coinselect calculated fee =>', true);
shepherd.log(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 && let _change = 0;
outputs.length === 2) {
_change = outputs[1].value;
}
// non komodo coins, subtract fee from output value if (outputs &&
if (!feeRate) { outputs.length === 2) {
outputs[0].value = outputs[0].value - fee; _change = outputs[1].value;
}
shepherd.log('non komodo adjusted outputs, value - default fee =>', true); // non komodo coins, subtract fee from output value
shepherd.log(outputs, true); if (!feeRate) {
} outputs[0].value = outputs[0].value - fee;
// check if any outputs are unverified shepherd.log('non komodo adjusted outputs, value - default fee =>', true);
if (inputs && shepherd.log(outputs, true);
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++) { // check if any outputs are unverified
if (Number(inputs[i].interestSats) > interestClaimThreshold) { if (inputs &&
totalInterest += Number(inputs[i].interestSats); inputs.length) {
totalInterestUTXOCount++; for (let i = 0; i < inputs.length; i++) {
if (!inputs[i].verified) {
utxoVerified = false;
break;
}
} }
}
}
const _maxSpend = shepherd.maxSpendBalance(utxoListFormatted);
if (value > _maxSpend) { for (let i = 0; i < inputs.length; i++) {
const successObj = { if (Number(inputs[i].interestSats) > interestClaimThreshold) {
msg: 'error', totalInterest += Number(inputs[i].interestSats);
result: `Spend value is too large. Max available amount is ${Number((_maxSpend * 0.00000001.toFixed(8)))}`, totalInterestUTXOCount++;
};
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);
} }
} else {
_change = _change + (totalInterest - _feeOverhead);
} }
} }
if (!inputs && const _maxSpend = shepherd.maxSpendBalance(utxoListFormatted);
!outputs) {
if (value > _maxSpend) {
const successObj = { const successObj = {
msg: 'error', 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)); res.end(JSON.stringify(successObj));
} else { } else {
let vinSum = 0; shepherd.log(`maxspend ${_maxSpend} (${_maxSpend * 0.00000001})`, true);
shepherd.log(`value ${value}`, true);
for (let i = 0; i < inputs.length; i++) { shepherd.log(`sendto ${outputAddress} amount ${value} (${value * 0.00000001})`, true);
vinSum += inputs[i].value; 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); for (let i = 0; i < inputs.length; i++) {
shepherd.log(`estimatedFee ${_estimatedFee} (${_estimatedFee * 0.00000001})`, true); vinSum += inputs[i].value;
}
let _rawtx; const _estimatedFee = vinSum - outputs[0].value - _change;
if (req.query.unsigned) { shepherd.log(`vin sum ${vinSum} (${vinSum * 0.00000001})`, true);
_rawtx = shepherd.buildUnsignedTx( shepherd.log(`estimatedFee ${_estimatedFee} (${_estimatedFee * 0.00000001})`, true);
outputAddress,
changeAddress, let _rawtx;
network,
inputs, if (req.query.unsigned) {
_change, _rawtx = shepherd.buildUnsignedTx(
value
);
} else {
if (network === 'btg' ||
network === 'bch') {
_rawtx = shepherd.buildSignedTxForks(
outputAddress, outputAddress,
changeAddress, changeAddress,
wif,
network, network,
inputs, inputs,
_change, _change,
value value
); );
} else { } else {
_rawtx = shepherd.buildSignedTx( if (network === 'btg' ||
outputAddress, network === 'bch') {
changeAddress, _rawtx = shepherd.buildSignedTxForks(
wif, outputAddress,
network, changeAddress,
inputs, wif,
_change, network,
value inputs,
); _change,
value
);
} else {
_rawtx = shepherd.buildSignedTx(
outputAddress,
changeAddress,
wif,
network,
inputs,
_change,
value
);
}
} }
}
if (!push || if (!push ||
push === 'false') { push === 'false') {
const successObj = { const successObj = {
msg: 'success', msg: 'success',
result: { result: {
utxoSet: inputs, utxoSet: inputs,
change: _change, change: _change,
changeAdjusted: _change, changeAdjusted: _change,
totalInterest, totalInterest,
// wif, // wif,
fee, fee,
value, value,
outputAddress, outputAddress,
changeAddress, changeAddress,
network, network,
rawtx: _rawtx, rawtx: _rawtx,
utxoVerified, 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 && if (txid &&
txid.length === 64) { txid.indexOf('bad-txns-inputs-spent') > -1) {
if (txid.indexOf('bad-txns-in-belowout') > -1) { const successObj = {
const successObj = { msg: 'error',
msg: 'error', result: 'Bad transaction inputs spent',
result: 'Bad transaction inputs spent', raw: {
raw: { utxoSet: inputs,
utxoSet: inputs, change: _change,
change: _change, changeAdjusted: _change,
changeAdjusted: _change, totalInterest,
totalInterest, fee,
fee, value,
value, outputAddress,
outputAddress, changeAddress,
changeAddress, network,
network, rawtx: _rawtx,
rawtx: _rawtx, txid,
txid, utxoVerified,
utxoVerified, },
}, };
};
res.end(JSON.stringify(successObj));
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 { } else {
if (txid && if (txid &&
txid.indexOf('bad-txns-in-belowout') > -1) { txid.length === 64) {
const successObj = { if (txid.indexOf('bad-txns-in-belowout') > -1) {
msg: 'error', const successObj = {
result: 'Bad transaction inputs spent', msg: 'error',
raw: { result: 'Bad transaction inputs spent',
utxoSet: inputs, raw: {
change: _change, utxoSet: inputs,
changeAdjusted: _change, change: _change,
totalInterest, changeAdjusted: _change,
fee, totalInterest,
value, fee,
outputAddress, value,
changeAddress, outputAddress,
network, changeAddress,
rawtx: _rawtx, network,
txid, rawtx: _rawtx,
utxoVerified, txid,
}, utxoVerified,
}; },
};
res.end(JSON.stringify(successObj));
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 { } else {
const successObj = { if (txid &&
msg: 'error', txid.indexOf('bad-txns-in-belowout') > -1) {
result: 'Can\'t broadcast transaction', const successObj = {
raw: { msg: 'error',
utxoSet: inputs, result: 'Bad transaction inputs spent',
change: _change, raw: {
changeAdjusted: _change, utxoSet: inputs,
totalInterest, change: _change,
fee, changeAdjusted: _change,
value, totalInterest,
outputAddress, fee,
changeAddress, value,
network, outputAddress,
rawtx: _rawtx, changeAddress,
txid, network,
utxoVerified, rawtx: _rawtx,
}, txid,
}; utxoVerified,
},
res.end(JSON.stringify(successObj)); };
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 = { } else {
msg: 'error', const errorObj = {
result: utxoList, msg: 'error',
}; result: 'unauthorized access',
};
res.end(JSON.stringify(successObj)); res.end(JSON.stringify(errorObj));
} }
});
}); });
shepherd.get('/electrum/pushtx', (req, res, next) => { shepherd.get('/electrum/pushtx', (req, res, next) => {
const rawtx = req.query.rawtx; 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 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) ecl.connect();
.then((json) => { ecl.blockchainTransactionBroadcast(rawtx)
ecl.close(); .then((json) => {
shepherd.log('electrum pushtx ==>', true); ecl.close();
shepherd.log(json, true); shepherd.log('electrum pushtx ==>', true);
shepherd.log(json, true);
const successObj = {
msg: 'success', const successObj = {
result: json, 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; return shepherd;

31
routes/shepherd/electrum/estimate.js

@ -1,20 +1,29 @@
module.exports = (shepherd) => { module.exports = (shepherd) => {
shepherd.get('/electrum/estimatefee', (req, res, next) => { 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.connect();
ecl.blockchainEstimatefee(req.query.blocks) ecl.blockchainEstimatefee(req.query.blocks)
.then((json) => { .then((json) => {
ecl.close(); ecl.close();
shepherd.log('electrum estimatefee ==>', true); shepherd.log('electrum estimatefee ==>', true);
const successObj = { const successObj = {
msg: 'success', msg: 'success',
result: json, 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) => { shepherd.estimateTxSize = (numVins, numOuts) => {

219
routes/shepherd/electrum/keys.js

@ -10,7 +10,6 @@ const bs58check = require('bs58check');
module.exports = (shepherd) => { module.exports = (shepherd) => {
shepherd.wifToWif = (wif, network) => { shepherd.wifToWif = (wif, network) => {
network = network === 'KMD' ? 'komodo' : network.toLowerCase(); 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); const key = shepherd.isZcash(network) ? new bitcoinZcash.ECPair.fromWIF(wif, shepherd.getNetworkData(network), true) : new bitcoin.ECPair.fromWIF(wif, shepherd.getNetworkData(network), true);
return { return {
@ -51,93 +50,120 @@ module.exports = (shepherd) => {
} }
shepherd.get('/electrum/wiftopub', (req, res, next) => { 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); if (shepherd.checkToken(req.query.token)) {
keys = { 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);
priv: key.toWIF(), keys = {
pub: key.getAddress(), priv: key.toWIF(),
}; pub: key.getAddress(),
};
const successObj = {
msg: 'success', const successObj = {
result: { msg: 'success',
keys, 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) => { 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 = { const successObj = {
msg: 'success', msg: 'success',
result: { result: {
keys, 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) => { shepherd.post('/electrum/keys', (req, res, next) => {
let _matchingKeyPairs = 0; if (shepherd.checkToken(req.body.token)) {
let _totalKeys = 0; let _matchingKeyPairs = 0;
let _electrumKeys = {}; let _totalKeys = 0;
let _seed = req.body.seed; let _electrumKeys = {};
let _wifError = false; let _seed = req.body.seed;
let _wifError = false;
for (let key in shepherd.electrumServers) {
const _abbr = shepherd.electrumServers[key].abbr; for (let key in shepherd.electrumServers) {
let isWif = false; const _abbr = shepherd.electrumServers[key].abbr;
let priv; let isWif = false;
let pub; let priv;
let pub;
try {
bs58check.decode(_seed);
isWif = true;
} catch (e) {}
if (isWif) {
try { 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); bs58check.decode(_seed);
priv = key.toWIF(); isWif = true;
pub = key.getAddress(); } catch (e) {}
} catch (e) {
_wifError = true; if (isWif) {
break; 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 && if (shepherd.electrumKeys[_abbr].pub === pub &&
shepherd.electrumKeys[_abbr].priv === priv) { shepherd.electrumKeys[_abbr].priv === priv) {
_matchingKeyPairs++; _matchingKeyPairs++;
}
_totalKeys++;
} }
_totalKeys++;
}
if (req.body.active) { if (req.body.active) {
_electrumKeys = JSON.parse(JSON.stringify(shepherd.electrumKeys)); _electrumKeys = JSON.parse(JSON.stringify(shepherd.electrumKeys));
for (let key in _electrumKeys) { for (let key in _electrumKeys) {
if (!shepherd.electrumCoins[key]) { if (!shepherd.electrumCoins[key]) {
delete _electrumKeys[key]; delete _electrumKeys[key];
}
} }
} else {
_electrumKeys = shepherd.electrumKeys;
} }
} else {
_electrumKeys = shepherd.electrumKeys;
}
const successObj = { const successObj = {
msg: _wifError ? 'error' : 'success', msg: _wifError ? 'error' : 'success',
result: _wifError ? false : (_matchingKeyPairs === _totalKeys ? _electrumKeys : false), 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 = () => { shepherd.getSpvFees = () => {
@ -153,35 +179,44 @@ module.exports = (shepherd) => {
}; };
shepherd.post('/electrum/seed/bip39/match', (req, res, next) => { shepherd.post('/electrum/seed/bip39/match', (req, res, next) => {
const seed = bip39.mnemonicToSeed(req.body.seed); if (shepherd.checkToken(req.body.token)) {
const hdMaster = bitcoin.HDNode.fromSeedBuffer(seed, shepherd.electrumJSNetworks.komodo); // seed from above const seed = bip39.mnemonicToSeed(req.body.seed);
const matchPattern = req.body.match; const hdMaster = bitcoin.HDNode.fromSeedBuffer(seed, shepherd.electrumJSNetworks.komodo); // seed from above
const _defaultAddressDepth = req.body.addressdepth; const matchPattern = req.body.match;
const _defaultAccountCount = req.body.accounts; const _defaultAddressDepth = req.body.addressdepth;
let _addresses = []; const _defaultAccountCount = req.body.accounts;
let _matchingKey; let _addresses = [];
let _matchingKey;
for (let i = 0; i < _defaultAccountCount; i++) {
for (let j = 0; j < 1; j++) { for (let i = 0; i < _defaultAccountCount; i++) {
for (let k = 0; k < _defaultAddressDepth; k++) { for (let j = 0; j < 1; j++) {
const _key = hdMaster.derivePath(`m/44'/141'/${i}'/${j}/${k}`); for (let k = 0; k < _defaultAddressDepth; k++) {
const _key = hdMaster.derivePath(`m/44'/141'/${i}'/${j}/${k}`);
if (_key.keyPair.getAddress() === matchPattern) {
_matchingKey = { if (_key.keyPair.getAddress() === matchPattern) {
pub: _key.keyPair.getAddress(), _matchingKey = {
priv: _key.keyPair.toWIF(), pub: _key.keyPair.getAddress(),
}; priv: _key.keyPair.toWIF(),
};
}
} }
} }
} }
}
const successObj = { const successObj = {
msg: 'success', msg: 'success',
result: _matchingKey ? _matchingKey : 'address is not found', 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; return shepherd;

73
routes/shepherd/electrum/listunspent.js

@ -155,40 +155,49 @@ module.exports = (shepherd) => {
} }
shepherd.get('/electrum/listunspent', (req, res, next) => { shepherd.get('/electrum/listunspent', (req, res, next) => {
const network = req.query.network || shepherd.findNetworkObj(req.query.coin); if (shepherd.checkToken(req.query.token)) {
const ecl = new shepherd.electrumJSCore(shepherd.electrumServers[network].port, shepherd.electrumServers[network].address, shepherd.electrumServers[network].proto); // tcp or tls 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') { if (req.query.full &&
shepherd.listunspent( req.query.full === 'true') {
ecl, shepherd.listunspent(
req.query.address, ecl,
network, req.query.address,
true, network,
req.query.verify true,
).then((listunspent) => { req.query.verify
shepherd.log('electrum listunspent ==>', true); ).then((listunspent) => {
shepherd.log('electrum listunspent ==>', true);
const successObj = {
msg: 'success', const successObj = {
result: listunspent, msg: 'success',
}; result: listunspent,
};
res.end(JSON.stringify(successObj));
}); res.end(JSON.stringify(successObj));
} else { });
shepherd.listunspent(ecl, req.query.address, network) } else {
.then((listunspent) => { shepherd.listunspent(ecl, req.query.address, network)
ecl.close(); .then((listunspent) => {
shepherd.log('electrum listunspent ==>', true); ecl.close();
shepherd.log('electrum listunspent ==>', true);
const successObj = { const successObj = {
msg: 'success', msg: 'success',
result: listunspent, 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));
} }
}); });

27
routes/shepherd/electrum/merkle.js

@ -128,17 +128,26 @@ module.exports = (shepherd) => {
} }
shepherd.get('/electrum/merkle/verify', (req, res, next) => { shepherd.get('/electrum/merkle/verify', (req, res, next) => {
shepherd.verifyMerkleByCoin(req.query.coin, req.query.txid, req.query.height) if (shepherd.checkToken(req.query.token)) {
.then((verifyMerkleRes) => { shepherd.verifyMerkleByCoin(req.query.coin, req.query.txid, req.query.height)
const successObj = { .then((verifyMerkleRes) => {
msg: 'success', const successObj = {
result: { msg: 'success',
merkleProof: verifyMerkleRes, 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; return shepherd;

147
routes/shepherd/electrum/network.js

@ -92,85 +92,112 @@ module.exports = (shepherd) => {
} }
shepherd.get('/electrum/servers', (req, res, next) => { shepherd.get('/electrum/servers', (req, res, next) => {
if (req.query.abbr) { if (shepherd.checkToken(req.query.token)) {
let _electrumServers = {}; if (req.query.abbr) {
let _electrumServers = {};
for (let key in shepherd.electrumServers) { for (let key in shepherd.electrumServers) {
_electrumServers[shepherd.electrumServers[key].abbr] = shepherd.electrumServers[key]; _electrumServers[shepherd.electrumServers[key].abbr] = shepherd.electrumServers[key];
} }
const successObj = { const successObj = {
msg: 'success', msg: 'success',
result: { result: {
servers: _electrumServers, 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 { } else {
const successObj = { const errorObj = {
msg: 'success', msg: 'error',
result: { result: 'unauthorized access',
servers: shepherd.electrumServers,
},
}; };
res.end(JSON.stringify(successObj)); res.end(JSON.stringify(errorObj));
} }
}); });
shepherd.get('/electrum/coins/server/set', (req, res, next) => { shepherd.get('/electrum/coins/server/set', (req, res, next) => {
shepherd.electrumCoins[req.query.coin].server = { if (shepherd.checkToken(req.query.token)) {
ip: req.query.address, shepherd.electrumCoins[req.query.coin].server = {
port: req.query.port, ip: req.query.address,
}; port: req.query.port,
};
for (let key in shepherd.electrumServers) { for (let key in shepherd.electrumServers) {
if (shepherd.electrumServers[key].abbr === req.query.coin) { // a bit risky if (shepherd.electrumServers[key].abbr === req.query.coin) { // a bit risky
shepherd.electrumServers[key].address = req.query.address; shepherd.electrumServers[key].address = req.query.address;
shepherd.electrumServers[key].port = req.query.port; shepherd.electrumServers[key].port = req.query.port;
break; 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 = { const successObj = {
msg: 'success', msg: 'success',
result: true, 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) => { shepherd.get('/electrum/servers/test', (req, res, next) => {
const ecl = new shepherd.electrumJSCore(req.query.port, req.query.address, 'tcp'); // tcp or tls 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() ecl.connect();
.then((serverData) => { ecl.serverVersion()
ecl.close(); .then((serverData) => {
shepherd.log('serverData', true); ecl.close();
shepherd.log(serverData, true); shepherd.log('serverData', true);
shepherd.log(serverData, true);
if (serverData &&
typeof serverData === 'string' && if (serverData &&
serverData.indexOf('Electrum') > -1) { typeof serverData === 'string' &&
const successObj = { serverData.indexOf('Electrum') > -1) {
msg: 'success', const successObj = {
result: true, msg: 'success',
}; result: true,
};
res.end(JSON.stringify(successObj));
} else { res.end(JSON.stringify(successObj));
const successObj = { } else {
msg: 'error', const successObj = {
result: false, 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; return shepherd;

454
routes/shepherd/electrum/transactions.js

@ -14,218 +14,236 @@ module.exports = (shepherd) => {
} }
shepherd.get('/electrum/listtransactions', (req, res, next) => { shepherd.get('/electrum/listtransactions', (req, res, next) => {
const network = req.query.network || shepherd.findNetworkObj(req.query.coin); if (shepherd.checkToken(req.query.token)) {
const ecl = new shepherd.electrumJSCore(shepherd.electrumServers[network].port, shepherd.electrumServers[network].address, shepherd.electrumServers[network].proto); // tcp or tls 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) { if (!req.query.full) {
ecl.connect(); ecl.connect();
ecl.blockchainAddressGetHistory(req.query.address) ecl.blockchainAddressGetHistory(req.query.address)
.then((json) => { .then((json) => {
ecl.close(); ecl.close();
shepherd.log(json, true); shepherd.log(json, true);
json = shepherd.sortTransactions(json);
const successObj = { json = shepherd.sortTransactions(json);
msg: 'success',
result: json,
};
res.end(JSON.stringify(successObj)); const successObj = {
}); msg: 'success',
} else { result: json,
// !expensive call! };
// TODO: limit e.g. 1-10, 10-20 etc
const MAX_TX = req.query.maxlength || 10;
ecl.connect();
ecl.blockchainNumblocksSubscribe() res.end(JSON.stringify(successObj));
.then((currentHeight) => { });
if (currentHeight && } else {
Number(currentHeight) > 0) { // !expensive call!
ecl.blockchainAddressGetHistory(req.query.address) // TODO: limit e.g. 1-10, 10-20 etc
.then((json) => { const MAX_TX = req.query.maxlength || 10;
if (json && ecl.connect();
json.length) {
json = shepherd.sortTransactions(json); ecl.blockchainNumblocksSubscribe()
json = json.length > MAX_TX ? json.slice(0, MAX_TX) : json; .then((currentHeight) => {
let _rawtx = []; if (currentHeight &&
Number(currentHeight) > 0) {
shepherd.log(json.length, true); ecl.blockchainAddressGetHistory(req.query.address)
.then((json) => {
shepherd.Promise.all(json.map((transaction, index) => { if (json &&
return new shepherd.Promise((resolve, reject) => { json.length) {
ecl.blockchainBlockGetHeader(transaction.height) json = shepherd.sortTransactions(json);
.then((blockInfo) => { json = json.length > MAX_TX ? json.slice(0, MAX_TX) : json;
if (blockInfo && let _rawtx = [];
blockInfo.timestamp) {
ecl.blockchainTransactionGet(transaction['tx_hash']) shepherd.log(json.length, true);
.then((_rawtxJSON) => {
shepherd.log('electrum gettransaction ==>', true); shepherd.Promise.all(json.map((transaction, index) => {
shepherd.log((index + ' | ' + (_rawtxJSON.length - 1)), true); return new shepherd.Promise((resolve, reject) => {
shepherd.log(_rawtxJSON, true); ecl.blockchainBlockGetHeader(transaction.height)
.then((blockInfo) => {
// decode tx if (blockInfo &&
const _network = shepherd.getNetworkData(network); blockInfo.timestamp) {
const decodedTx = shepherd.electrumJSTxDecoder(_rawtxJSON, network, _network); ecl.blockchainTransactionGet(transaction['tx_hash'])
.then((_rawtxJSON) => {
let txInputs = []; shepherd.log('electrum gettransaction ==>', true);
shepherd.log(`decodedtx network ${network}`, true); shepherd.log((index + ' | ' + (_rawtxJSON.length - 1)), true);
shepherd.log(_rawtxJSON, true);
shepherd.log('decodedtx =>', true);
shepherd.log(decodedTx.outputs, true); // decode tx
const _network = shepherd.getNetworkData(network);
if (decodedTx && const decodedTx = shepherd.electrumJSTxDecoder(_rawtxJSON, network, _network);
decodedTx.inputs) {
shepherd.Promise.all(decodedTx.inputs.map((_decodedInput, index) => { let txInputs = [];
return new shepherd.Promise((_resolve, _reject) => { shepherd.log(`decodedtx network ${network}`, true);
if (_decodedInput.txid !== '0000000000000000000000000000000000000000000000000000000000000000') {
ecl.blockchainTransactionGet(_decodedInput.txid) shepherd.log('decodedtx =>', true);
.then((rawInput) => { shepherd.log(decodedTx.outputs, true);
const decodedVinVout = shepherd.electrumJSTxDecoder(rawInput, network, _network);
if (decodedTx &&
shepherd.log('electrum raw input tx ==>', true); decodedTx.inputs) {
shepherd.Promise.all(decodedTx.inputs.map((_decodedInput, index) => {
if (decodedVinVout) { return new shepherd.Promise((_resolve, _reject) => {
shepherd.log(decodedVinVout.outputs[_decodedInput.n], true); if (_decodedInput.txid !== '0000000000000000000000000000000000000000000000000000000000000000') {
txInputs.push(decodedVinVout.outputs[_decodedInput.n]); ecl.blockchainTransactionGet(_decodedInput.txid)
_resolve(true); .then((rawInput) => {
} else { const decodedVinVout = shepherd.electrumJSTxDecoder(rawInput, network, _network);
_resolve(true);
} 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 { } 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);
}); });
})) } else {
.then(promiseResult => {
const _parsedTx = { const _parsedTx = {
network: decodedTx.network, network: decodedTx.network,
format: decodedTx.format, format: 'cant parse',
inputs: txInputs, inputs: 'cant parse',
outputs: decodedTx.outputs, outputs: 'cant parse',
height: transaction.height, height: transaction.height,
timestamp: Number(transaction.height) === 0 ? Math.floor(Date.now() / 1000) : blockInfo.timestamp, timestamp: Number(transaction.height) === 0 ? Math.floor(Date.now() / 1000) : blockInfo.timestamp,
confirmations: Number(transaction.height) === 0 ? 0 : currentHeight - transaction.height, confirmations: Number(transaction.height) === 0 ? 0 : currentHeight - transaction.height,
}; };
const formattedTx = shepherd.parseTransactionAddresses(_parsedTx, req.query.address, network); const formattedTx = shepherd.parseTransactionAddresses(_parsedTx, req.query.address, network);
_rawtx.push(formattedTx);
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); resolve(true);
}); }
} else { });
const _parsedTx = { } else {
network: decodedTx.network, const _parsedTx = {
format: 'cant parse', network: 'cant parse',
inputs: 'cant parse', format: 'cant parse',
outputs: 'cant parse', inputs: 'cant parse',
height: transaction.height, outputs: 'cant parse',
timestamp: Number(transaction.height) === 0 ? Math.floor(Date.now() / 1000) : blockInfo.timestamp, height: transaction.height,
confirmations: Number(transaction.height) === 0 ? 0 : currentHeight - 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); const formattedTx = shepherd.parseTransactionAddresses(_parsedTx, req.query.address, network);
_rawtx.push(formattedTx); _rawtx.push(formattedTx);
resolve(true); 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 => {
.then(promiseResult => { ecl.close();
ecl.close();
const successObj = {
msg: 'success',
result: _rawtx,
};
res.end(JSON.stringify(successObj));
});
} else {
const successObj = { const successObj = {
msg: 'success', msg: 'success',
result: _rawtx, result: [],
}; };
res.end(JSON.stringify(successObj)); res.end(JSON.stringify(successObj));
}); }
} else { });
const successObj = { } else {
msg: 'success', const successObj = {
result: [], msg: 'error',
}; result: 'cant get current height',
};
res.end(JSON.stringify(successObj));
} res.end(JSON.stringify(successObj));
}); }
} else { });
const successObj = { }
msg: 'error', } else {
result: 'cant get current height', const errorObj = {
}; msg: 'error',
result: 'unauthorized access',
};
res.end(JSON.stringify(successObj)); res.end(JSON.stringify(errorObj));
}
});
} }
}); });
shepherd.get('/electrum/gettransaction', (req, res, next) => { shepherd.get('/electrum/gettransaction', (req, res, next) => {
const network = req.query.network || shepherd.findNetworkObj(req.query.coin); if (shepherd.checkToken(req.query.token)) {
const ecl = new shepherd.electrumJSCore(shepherd.electrumServers[network].port, shepherd.electrumServers[network].address, shepherd.electrumServers[network].proto); // tcp or tls 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(); const successObj = {
ecl.blockchainTransactionGet(req.query.txid) msg: 'success',
.then((json) => { result: json,
ecl.close(); };
shepherd.log(json, true);
const successObj = { res.end(JSON.stringify(successObj));
msg: 'success', });
result: json, } else {
const errorObj = {
msg: 'error',
result: 'unauthorized access',
}; };
res.end(JSON.stringify(successObj)); res.end(JSON.stringify(errorObj));
}); }
}); });
shepherd.parseTransactionAddresses = (tx, targetAddress, network) => { shepherd.parseTransactionAddresses = (tx, targetAddress, network) => {
@ -346,54 +364,62 @@ module.exports = (shepherd) => {
} }
shepherd.get('/electrum/decoderawtx', (req, res, next) => { shepherd.get('/electrum/decoderawtx', (req, res, next) => {
const _network = shepherd.getNetworkData(req.query.network); if (shepherd.checkToken(req.query.token)) {
const _rawtx = req.query.rawtx; const _network = shepherd.getNetworkData(req.query.network);
console.log(_network); const _rawtx = req.query.rawtx;
//const _rawtx = '010000006f2c395a02d81487fc7f9d1be3ea900316730133c044af70cd76d21e988e71de0e9e85918f010000006a47304402202097acd391e1d0eaaf91844bd596e918fb71320e3e0c51554acb71a39e4ee98b0220548fd61d4ae77a08d70b01bf5340983a1ba63f6b71ad71d478af77011f96fd510121031ffc010d8abc4180b4c1a13962bf9153a78082e7f2ac18f7d14cb6a6634ca218feffffff2b31f6c9a7916f7cf128cae94b3fc10e4c74ca3a740e1a7a6fd6624e4e9a5c8b010000006a473044022063f014c5fbaa7614732e0ae486179a854215fc32c02230e13f69b7e81fa000e50220236a2ba6373b1854aafc59c5391ab7505062067f3d293c016cbb5d252b35a56a012102f307f17d282fc0eabf99227c2e0f3122ae9ecd7da0de099f0c6007d4c941b57bfeffffff021b797ad7120000001976a914c7a7142d743b3e6eebe76923f43bae477d3ce31a88acff086d66000000001976a91463800ff36b9c52b2ffe5564af1c2a38df4f0126788ac16381d00'; //const _rawtx = '010000006f2c395a02d81487fc7f9d1be3ea900316730133c044af70cd76d21e988e71de0e9e85918f010000006a47304402202097acd391e1d0eaaf91844bd596e918fb71320e3e0c51554acb71a39e4ee98b0220548fd61d4ae77a08d70b01bf5340983a1ba63f6b71ad71d478af77011f96fd510121031ffc010d8abc4180b4c1a13962bf9153a78082e7f2ac18f7d14cb6a6634ca218feffffff2b31f6c9a7916f7cf128cae94b3fc10e4c74ca3a740e1a7a6fd6624e4e9a5c8b010000006a473044022063f014c5fbaa7614732e0ae486179a854215fc32c02230e13f69b7e81fa000e50220236a2ba6373b1854aafc59c5391ab7505062067f3d293c016cbb5d252b35a56a012102f307f17d282fc0eabf99227c2e0f3122ae9ecd7da0de099f0c6007d4c941b57bfeffffff021b797ad7120000001976a914c7a7142d743b3e6eebe76923f43bae477d3ce31a88acff086d66000000001976a91463800ff36b9c52b2ffe5564af1c2a38df4f0126788ac16381d00';
const decodedTx = shepherd.electrumJSTxDecoder(_rawtx, req.query.network, _network); 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,
},
};
shepherd.log(successObj.result, true); shepherd.log('electrum decoderawtx input tx ==>', 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);
if (req.query.parseonly ||
decodedTx.inputs[0].txid === '0000000000000000000000000000000000000000000000000000000000000000') {
const successObj = { const successObj = {
msg: 'success', msg: 'success',
result: { result: {
network: decodedTx.network, network: decodedTx.network,
format: decodedTx.format, format: decodedTx.format,
inputs: decodedVin.outputs[decodedTx.inputs[0].n], inputs: decodedTx.inputs,
outputs: decodedTx.outputs, outputs: decodedTx.outputs,
}, },
}; };
shepherd.log(successObj.result, true);
res.end(JSON.stringify(successObj)); 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));
} }
}); });

59
routes/shepherd/kickstart.js

@ -7,37 +7,46 @@ module.exports = (shepherd) => {
* params: coin, type * params: coin, type
*/ */
shepherd.get('/kick', (req, res, next) => { shepherd.get('/kick', (req, res, next) => {
const _coin = req.query.coin; if (shepherd.checkToken(req.query.token)) {
const _keepWallet = req.query.keepwallet; 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 = { const errorObj = {
msg: 'error', msg: 'error',
result: 'no coin name provided', result: 'unauthorized access',
}; };
res.end(JSON.stringify(errorObj)); 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));
} }
}); });

127
routes/shepherd/log.js

@ -40,12 +40,21 @@ module.exports = (shepherd) => {
} }
shepherd.get('/log/runtime', (req, res, next) => { shepherd.get('/log/runtime', (req, res, next) => {
const successObj = { if (shepherd.checkToken(req.query.token)) {
msg: 'success', const successObj = {
result: req.query.spv && req.query.spv === 'true' ? shepherd.appRuntimeSPVLog : shepherd.appRuntimeLog, 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 = () => { shepherd.getAppRuntimeLog = () => {
@ -59,37 +68,46 @@ module.exports = (shepherd) => {
* params: payload * params: payload
*/ */
shepherd.post('/guilog', (req, res, next) => { 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]) { if (!shepherd.guiLog[shepherd.appSessionHash]) {
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,
};
}
shepherd.fs.writeFile(`${logLocation}/agamalog.json`, JSON.stringify(shepherd.guiLog), (err) => { if (shepherd.guiLog[shepherd.appSessionHash][req.body.timestamp]) {
if (err) { shepherd.guiLog[shepherd.appSessionHash][req.body.timestamp].status = req.body.status;
shepherd.writeLog('error writing gui log file'); 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 = { shepherd.fs.writeFile(`${logLocation}/agamalog.json`, JSON.stringify(shepherd.guiLog), (err) => {
msg: 'success', if (err) {
result: 'gui log entry is added', 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 * params: type
*/ */
shepherd.get('/getlog', (req, res, next) => { 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}`)) { if (shepherd.fs.existsSync(`${shepherd.agamaDir}/shepherd/agamalog.${logExt}`)) {
shepherd.fs.readFile(`${shepherd.agamaDir}/shepherd/agamalog.${logExt}`, 'utf8', (err, data) => { shepherd.fs.readFile(`${shepherd.agamaDir}/shepherd/agamalog.${logExt}`, 'utf8', (err, data) => {
if (err) { if (err) {
const errorObj = { const errorObj = {
msg: 'error', msg: 'error',
result: err, result: err,
}; };
res.end(JSON.stringify(errorObj)); res.end(JSON.stringify(errorObj));
} else { } else {
const successObj = { const successObj = {
msg: 'success', msg: 'success',
result: data ? JSON.parse(data) : '', result: data ? JSON.parse(data) : '',
}; };
res.end(JSON.stringify(successObj)); res.end(JSON.stringify(successObj));
} }
}); });
} else {
const errorObj = {
msg: 'error',
result: `agama.${logExt} doesnt exist`,
};
res.end(JSON.stringify(errorObj));
}
} else { } else {
const errorObj = { const errorObj = {
msg: 'error', msg: 'error',
result: `agama.${logExt} doesnt exist`, result: 'unauthorized access',
}; };
res.end(JSON.stringify(errorObj)); res.end(JSON.stringify(errorObj));

209
routes/shepherd/pin.js

@ -7,93 +7,111 @@ module.exports = (shepherd) => {
* params: none * params: none
*/ */
shepherd.post('/encryptkey', (req, res, next) => { shepherd.post('/encryptkey', (req, res, next) => {
if (req.body.key && if (shepherd.checkToken(req.body.token)) {
req.body.string && if (req.body.key &&
req.body.pubkey) { req.body.string &&
const encryptedString = aes256.encrypt(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 // test pin security
// - at least 1 digit // - at least 1 char in upper case
// - at least one special character // - at least 1 digit
// - min length 8 // - at least one special character
// - min length 8
const _pin = req.body.key;
const _pinTest = _pin.match('^(?=.*[A-Z])(?=.*[^<>{}\"/|;:.,~!?@#$%^=&*\\]\\\\()\\[_+]*$)(?=.*[0-9])(?=.*[a-z]).{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) { fs.writeFile(`${shepherd.agamaDir}/shepherd/pin/${req.body.pubkey}.pin`, encryptedString, (err) => {
shepherd.log('error writing pin file'); if (err) {
} shepherd.log('error writing pin file');
}
const returnObj = {
msg: 'success',
result: encryptedString,
};
const returnObj = { res.end(JSON.stringify(returnObj));
msg: 'success', });
result: encryptedString, } 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 { } else {
let errorObj = { const errorObj = {
msg: 'error', 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)); res.end(JSON.stringify(errorObj));
} }
}); });
shepherd.post('/decryptkey', (req, res, next) => { shepherd.post('/decryptkey', (req, res, next) => {
if (req.body.key && if (shepherd.checkToken(req.body.token)) {
req.body.pubkey) { if (req.body.key &&
if (fs.existsSync(`${shepherd.agamaDir}/shepherd/pin/${req.body.pubkey}.pin`)) { req.body.pubkey) {
fs.readFile(`${shepherd.agamaDir}/shepherd/pin/${req.body.pubkey}.pin`, 'utf8', (err, data) => { if (fs.existsSync(`${shepherd.agamaDir}/shepherd/pin/${req.body.pubkey}.pin`)) {
if (err) { fs.readFile(`${shepherd.agamaDir}/shepherd/pin/${req.body.pubkey}.pin`, 'utf8', (err, data) => {
const errorObj = { if (err) {
msg: 'error', const errorObj = {
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 = {
msg: 'error', msg: 'error',
result: 'wrong key', result: err,
}; };
res.end(JSON.stringify(errorObj));
} else { } else {
returnObj = { const encryptedKey = aes256.decrypt(req.body.key, data);
msg: 'success', // test if stored encrypted passphrase is decrypted correctly
result: encryptedKey, // 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 { } else {
const errorObj = { const errorObj = {
msg: 'error', msg: 'error',
result: `file ${req.query.pubkey}.pin doesnt exist`, result: 'missing key or pubkey param',
}; };
res.end(JSON.stringify(errorObj)); res.end(JSON.stringify(errorObj));
@ -101,7 +119,7 @@ module.exports = (shepherd) => {
} else { } else {
const errorObj = { const errorObj = {
msg: 'error', msg: 'error',
result: 'missing key or pubkey param', result: 'unauthorized access',
}; };
res.end(JSON.stringify(errorObj)); res.end(JSON.stringify(errorObj));
@ -109,36 +127,45 @@ module.exports = (shepherd) => {
}); });
shepherd.get('/getpinlist', (req, res, next) => { shepherd.get('/getpinlist', (req, res, next) => {
if (fs.existsSync(`${shepherd.agamaDir}/shepherd/pin`)) { if (shepherd.checkToken(req.body.token)) {
fs.readdir(`${shepherd.agamaDir}/shepherd/pin`, (err, items) => { if (fs.existsSync(`${shepherd.agamaDir}/shepherd/pin`)) {
let _pins = []; 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') { for (let i = 0; i < items.length; i++) {
_pins.push(items[i].substr(0, items[i].length - 4)); if (items[i].substr(items[i].length - 4, 4) === '.pin') {
_pins.push(items[i].substr(0, items[i].length - 4));
}
} }
}
if (!items.length) { if (!items.length) {
const errorObj = { const errorObj = {
msg: 'error', msg: 'error',
result: 'no pins', result: 'no pins',
}; };
res.end(JSON.stringify(errorObj)); res.end(JSON.stringify(errorObj));
} else { } else {
const successObj = { const successObj = {
msg: 'success', msg: 'success',
result: _pins, 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 { } else {
const errorObj = { const errorObj = {
msg: 'error', msg: 'error',
result: 'pin folder doesnt exist', result: 'unauthorized access',
}; };
res.end(JSON.stringify(errorObj)); res.end(JSON.stringify(errorObj));

132
routes/shepherd/quitDaemon.js

@ -82,41 +82,32 @@ module.exports = (shepherd) => {
} }
shepherd.post('/coind/stop', (req, res) => { shepherd.post('/coind/stop', (req, res) => {
const _chain = req.body.chain; if (shepherd.checkToken(req.body.token)) {
let _coindQuitCmd = shepherd.komodocliBin; const _chain = req.body.chain;
let _arg = []; let _coindQuitCmd = shepherd.komodocliBin;
let _arg = [];
if (_chain) { if (_chain) {
_arg.push(`-ac_name=${_chain}`); _arg.push(`-ac_name=${_chain}`);
if (shepherd.appConfig.dataDir.length) { if (shepherd.appConfig.dataDir.length) {
_arg.push(`-datadir=${shepherd.appConfig.dataDir + (_chain ? '/' + _chain : '')}`); _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 = { _arg.push('stop');
msg: 'success', execFile(`${_coindQuitCmd}`, _arg, (error, stdout, stderr) => {
result: 'result', shepherd.log(`stdout: ${stdout}`);
}; shepherd.log(`stderr: ${stderr}`);
shepherd.log(`send stop sig to ${_chain ? _chain : 'komodo'}`);
res.end(JSON.stringify(obj));
} else { if (stdout.indexOf('EOF reached') > -1 ||
if (stdout.indexOf('Komodo server stopping') > -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']; delete shepherd.coindInstanceRegistry[_chain ? _chain : 'komodod'];
const obj = { const obj = {
@ -126,43 +117,70 @@ module.exports = (shepherd) => {
res.end(JSON.stringify(obj)); res.end(JSON.stringify(obj));
} else { } else {
const obj = { if (stdout.indexOf('Komodo server stopping') > -1) {
msg: 'error', delete shepherd.coindInstanceRegistry[_chain ? _chain : 'komodod'];
result: 'result',
}; const obj = {
msg: 'success',
res.end(JSON.stringify(obj)); 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) => { 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') { if (req.body.mode === 'native') {
delete shepherd.coindInstanceRegistry[_chain ? _chain : 'komodod']; delete shepherd.coindInstanceRegistry[_chain ? _chain : 'komodod'];
const obj = { const obj = {
msg: 'success', msg: 'success',
result: 'result', result: 'result',
}; };
res.end(JSON.stringify(obj)); res.end(JSON.stringify(obj));
} else { } else {
delete shepherd.electrumCoins[_chain === 'komodo' ? 'KMD' : _chain]; delete shepherd.electrumCoins[_chain === 'komodo' ? 'KMD' : _chain];
if (Object.keys(shepherd.electrumCoins).length - 1 === 0) { if (Object.keys(shepherd.electrumCoins).length - 1 === 0) {
shepherd.electrumCoins.auth = false; shepherd.electrumCoins.auth = false;
shepherd.electrumKeys = {}; shepherd.electrumKeys = {};
} }
const obj = {
msg: 'success',
result: 'result',
};
const obj = { res.end(JSON.stringify(obj));
msg: 'success', }
result: 'result', } else {
const errorObj = {
msg: 'error',
result: 'unauthorized access',
}; };
res.end(JSON.stringify(obj)); res.end(JSON.stringify(errorObj));
} }
}); });

451
routes/shepherd/rpc.js

@ -60,270 +60,279 @@ module.exports = (shepherd) => {
* params: payload * params: payload
*/ */
shepherd.post('/cli', (req, res, next) => { shepherd.post('/cli', (req, res, next) => {
if (!req.body.payload) { if (shepherd.checkToken(req.body.payload.token)) {
const errorObj = { if (!req.body.payload) {
msg: 'error', const errorObj = {
result: 'no payload provided', 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)); if (!shepherd.rpcConf[_chain]) {
} else if (!req.body.payload.cmd.match(/^[0-9a-zA-Z _\,\.\[\]"'/\\]+$/g)) { shepherd.getConf(req.body.payload.chain === 'KMD' || !req.body.payload.chain && shepherd.kmdMainPassiveMode ? 'komodod' : req.body.payload.chain);
const errorObj = { }
msg: 'error',
result: 'wrong cli string format',
};
res.end(JSON.stringify(errorObj)); if (_mode === 'default') {
} else { if (req.body.payload.rpc2cli) {
const _mode = req.body.payload.mode === 'passthru' ? 'passthru' : 'default'; let _coindCliBin = shepherd.komodocliBin;
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 (!shepherd.rpcConf[_chain]) { if (shepherd.nativeCoindList &&
shepherd.getConf(req.body.payload.chain === 'KMD' || !req.body.payload.chain && shepherd.kmdMainPassiveMode ? 'komodod' : req.body.payload.chain); _chain &&
} shepherd.nativeCoindList[_chain.toLowerCase()]) {
_coindCliBin = `${shepherd.coindRootDir}/${_chain.toLowerCase()}/${shepherd.nativeCoindList[_chain.toLowerCase()].bin.toLowerCase()}-cli`;
}
if (_mode === 'default') { if (_params.indexOf('*')) {
if (req.body.payload.rpc2cli) { _params = _params.replace('*', '"*"');
let _coindCliBin = shepherd.komodocliBin; }
if (_params.indexOf(',') > -1) {
_params = _params.split(',');
}
if (_cmd.indexOf('getaddressesbyaccount') > -1) {
_cmd = 'getaddressesbyaccount ""';
}
if (shepherd.nativeCoindList && let _arg = (_chain ? ' -ac_name=' + _chain : '') + ' ' + _cmd + (typeof _params === 'object' ? _params.join(' ') : _params);
_chain &&
shepherd.nativeCoindList[_chain.toLowerCase()]) {
_coindCliBin = `${shepherd.coindRootDir}/${_chain.toLowerCase()}/${shepherd.nativeCoindList[_chain.toLowerCase()].bin.toLowerCase()}-cli`;
}
if (_params.indexOf('*')) { if (shepherd.appConfig.dataDir.length) {
_params = _params.replace('*', '"*"'); _arg = `${_arg} -datadir=${shepherd.appConfig.dataDir + (_chain ? '/' + key : '')}`;
} }
if (_params.indexOf(',') > -1) {
_params = _params.split(',');
}
if (_cmd.indexOf('getaddressesbyaccount') > -1) {
_cmd = 'getaddressesbyaccount ""';
}
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) { if (error !== null) {
_arg = `${_arg} -datadir=${shepherd.appConfig.dataDir + (_chain ? '/' + key : '')}`; shepherd.log(`exec error: ${error}`);
} }
shepherd.exec(`"${_coindCliBin}" ${_arg}`, (error, stdout, stderr) => { let responseObj;
//shepherd.log(`stdout: ${stdout}`);
//shepherd.log(`stderr: ${stderr}`);
if (error !== null) { if (stderr) {
shepherd.log(`exec error: ${error}`); 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) { if ((stderr.indexOf('{') > -1 && stderr.indexOf('}') > -1) ||
let _res; (stderr.indexOf('[') > -1 && stderr.indexOf(']') > -1)) {
let _error; _res = JSON.parse(stderr);
} else {
if (_chain !== 'komodod' && _res = stderr.trim();
stderr.indexOf(`error creating`) > -1) { }
shepherd.log(`replace error creating (gen${_chain})`);
stderr = stderr.replace(`error creating (gen${_chain})`, ''); if (stderr.indexOf('error code:') > -1) {
shepherd.log(stderr); _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) || if (_error) {
(stderr.indexOf('[') > -1 && stderr.indexOf(']') > -1)) { responseObj = {
_res = JSON.parse(stderr); error: _error,
};
} else {
responseObj = {
result: _res,
};
}
} else { } 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) { if ((stdout.indexOf('{') > -1 && stdout.indexOf('}') > -1) ||
_error = { (stdout.indexOf('[') > -1 && stdout.indexOf(']') > -1)) {
code: Number(stderr.substring(stderr.indexOf('error code:') + 11, stderr.indexOf('error message:') - stderr.indexOf('error code:')).trim()), _res = JSON.parse(stdout);
message: stderr.substring(stderr.indexOf('error message:') + 15, stderr.length).trim(), } 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) { res.end(JSON.stringify(responseObj));
responseObj = { // shepherd.killRogueProcess('komodo-cli');
error: _error, });
}; } 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 { } else {
responseObj = { res.end({
result: _res, error: 'bitcoinrpc debug error',
}; result: 'error',
});
// console.log('bitcoinrpc debug error');
} }
} else { } else {
let _res; if (_chain === 'CHIPS' &&
let _error; _cmd === 'debug') {
_cmd = 'getblockchaininfo';
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) || let _body = {
(stdout.indexOf('[') > -1 && stdout.indexOf(']') > -1)) { agent: 'bitcoinrpc',
_res = JSON.parse(stdout); method: _cmd,
} else { };
_res = stdout.trim();
}
if (stdout.indexOf('error code:') > -1) { if (req.body.payload.params) {
_error = { _body = {
code: Number(stdout.substring(stdout.indexOf('error code:') + 11, stdout.indexOf('error message:') - stdout.indexOf('error code:')).trim()), agent: 'bitcoinrpc',
message: stdout.substring(stdout.indexOf('error message:') + 15, stdout.length).trim(), method: _cmd,
params: req.body.payload.params === ' ' ? [''] : req.body.payload.params,
}; };
} }
if (_error) { if (req.body.payload.chain) {
responseObj = { const options = {
error: _error, url: `http://localhost:${shepherd.rpcConf[req.body.payload.chain].port}`,
}; method: 'POST',
} else { auth: {
responseObj = { user: shepherd.rpcConf[req.body.payload.chain].user,
result: _res, 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 { } else {
if (_cmd === 'debug' && let _coindCliBin = shepherd.komodocliBin;
_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) if (shepherd.nativeCoindList &&
.then((result) => { _chain &&
const _obj = { shepherd.nativeCoindList[_chain.toLowerCase()]) {
msg: 'success', _coindCliBin = `${shepherd.coindRootDir}/${_chain.toLowerCase()}/${shepherd.nativeCoindList[_chain.toLowerCase()].bin.toLowerCase()}-cli`;
result: result, }
};
// shepherd.log('bitcoinrpc debug ====>'); let _arg = (_chain ? ' -ac_name=' + _chain : '') + ' ' + _cmd + _params;
// console.log(result);
res.end(JSON.stringify(_obj)); if (shepherd.appConfig.dataDir.length) {
}, (result) => { _arg = `${_arg} -datadir=${shepherd.appConfig.dataDir + (_chain ? '/' + key : '')}`;
const _obj = { }
error: result,
result: 'error',
};
res.end(JSON.stringify(_obj)); _arg = _arg.trim().split(' ');
}); shepherd.execFile(_coindCliBin, _arg, (error, stdout, stderr) => {
} else { shepherd.log(`stdout: ${stdout}`);
res.end({ shepherd.log(`stderr: ${stderr}`);
error: 'bitcoinrpc debug error',
result: 'error', if (error !== null) {
}); shepherd.log(`exec error: ${error}`);
// console.log('bitcoinrpc debug error');
}
} else {
if (_chain === 'CHIPS' &&
_cmd === 'debug') {
_cmd = 'getblockchaininfo';
} }
let _body = { let responseObj;
agent: 'bitcoinrpc',
method: _cmd,
};
if (req.body.payload.params) { if (stderr) {
_body = { responseObj = {
agent: 'bitcoinrpc', msg: 'error',
method: _cmd, result: stderr,
params: req.body.payload.params === ' ' ? [''] : req.body.payload.params,
}; };
} } else {
responseObj = {
if (req.body.payload.chain) { msg: 'success',
const options = { result: stdout,
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 {
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) { res.end(JSON.stringify(responseObj));
_arg = `${_arg} -datadir=${shepherd.appConfig.dataDir + (_chain ? '/' + key : '')}`; 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));
} }
}); });

Loading…
Cancel
Save