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 _spvFees = shepherd.getSpvFees();
shepherd.writeLog(`app init ${appSessionHash}`);
shepherd.writeLog(`app info: ${appBasicInfo.name} ${appBasicInfo.version}`);
shepherd.writeLog('sys info:');
shepherd.writeLog(`totalmem_readable: ${formatBytes(os.totalmem())}`);
@ -68,7 +67,9 @@ shepherd.writeLog(`platform: ${osPlatform}`);
shepherd.writeLog(`os_release: ${os.release()}`);
shepherd.writeLog(`os_type: ${os.type()}`);
shepherd.log(`app init ${appSessionHash}`);
if (process.argv.indexOf('devmode') > -1) {
shepherd.log(`app init ${appSessionHash}`);
}
shepherd.log(`app info: ${appBasicInfo.name} ${appBasicInfo.version}`);
shepherd.log('sys info:');
shepherd.log(`totalmem_readable: ${formatBytes(os.totalmem())}`);

1
routes/shepherd.js

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

6
routes/shepherd/addCoinShortcuts.js

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

27
routes/shepherd/appInfo.js

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

48
routes/shepherd/auth.js

@ -3,29 +3,45 @@ module.exports = (shepherd) => {
* type: GET
*
*/
shepherd.get('/auth/status', (req, res, next) => { // not finished
let successObj;
let _status = false;
shepherd.get('/auth/status', (req, res, next) => {
if (shepherd.checkToken(req.query.token)) {
let successObj;
let _status = false;
if (Object.keys(shepherd.coindInstanceRegistry).length) {
if (Object.keys(shepherd.electrumCoins).length > 1 &&
shepherd.electrumCoins.auth) {
if (Object.keys(shepherd.coindInstanceRegistry).length) {
if (Object.keys(shepherd.electrumCoins).length > 1 &&
shepherd.electrumCoins.auth) {
_status = true;
} else if (Object.keys(shepherd.electrumCoins).length === 1 && !shepherd.electrumCoins.auth) {
_status = true;
}
} else if (Object.keys(shepherd.electrumCoins).length > 1 && shepherd.electrumCoins.auth) {
_status = true;
} else if (Object.keys(shepherd.electrumCoins).length === 1 && !shepherd.electrumCoins.auth) {
} else if (Object.keys(shepherd.electrumCoins).length === 1 && !Object.keys(shepherd.coindInstanceRegistry).length) {
_status = true;
}
} else if (Object.keys(shepherd.electrumCoins).length > 1 && shepherd.electrumCoins.auth) {
_status = true;
} else if (Object.keys(shepherd.electrumCoins).length === 1 && !Object.keys(shepherd.coindInstanceRegistry).length) {
_status = true;
}
successObj = {
status: _status ? 'unlocked' : 'locked',
};
successObj = {
status: _status ? 'unlocked' : 'locked',
};
res.end(JSON.stringify(successObj));
} else {
const errorObj = {
msg: 'error',
result: 'unauthorized access',
};
res.end(JSON.stringify(successObj));
res.end(JSON.stringify(errorObj));
}
});
shepherd.checkToken = (token) => {
if (token === shepherd.appSessionHash ||
process.argv.indexOf('devmode') > -1) {
return true;
}
};
return shepherd;
};

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

41
routes/shepherd/coins.js

@ -4,27 +4,36 @@ module.exports = (shepherd) => {
*
*/
shepherd.get('/InstantDEX/allcoins', (req, res, next) => {
let successObj;
let nativeCoindList = [];
let electrumCoinsList = [];
if (shepherd.checkToken(req.query.token)) {
let successObj;
let nativeCoindList = [];
let electrumCoinsList = [];
for (let key in shepherd.electrumCoins) {
if (key !== 'auth') {
electrumCoinsList.push(shepherd.electrumCoins[key].abbr);
for (let key in shepherd.electrumCoins) {
if (key !== 'auth') {
electrumCoinsList.push(shepherd.electrumCoins[key].abbr);
}
}
}
for (let key in shepherd.coindInstanceRegistry) {
nativeCoindList.push(key === 'komodod' ? 'KMD' : key);
}
for (let key in shepherd.coindInstanceRegistry) {
nativeCoindList.push(key === 'komodod' ? 'KMD' : key);
}
successObj = {
native: nativeCoindList,
spv: electrumCoinsList,
total: Object.keys(shepherd.electrumCoins).length - 1 + Object.keys(nativeCoindList).length,
};
successObj = {
native: nativeCoindList,
spv: electrumCoinsList,
total: Object.keys(shepherd.electrumCoins).length - 1 + Object.keys(nativeCoindList).length,
};
res.end(JSON.stringify(successObj));
res.end(JSON.stringify(successObj));
} else {
const errorObj = {
msg: 'error',
result: 'unauthorized access',
};
res.end(JSON.stringify(errorObj));
}
});
return shepherd;

94
routes/shepherd/coinsList.js

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

65
routes/shepherd/config.js

@ -105,22 +105,31 @@ module.exports = (shepherd) => {
* params: payload
*/
shepherd.post('/appconf', (req, res, next) => {
if (!req.body.payload) {
if (shepherd.checkToken(req.body.token)) {
if (!req.body.payload) {
const errorObj = {
msg: 'error',
result: 'no payload provided',
};
res.end(JSON.stringify(errorObj));
} else {
shepherd.saveLocalAppConf(req.body.payload);
const successObj = {
msg: 'success',
result: 'config saved',
};
res.end(JSON.stringify(successObj));
}
} else {
const errorObj = {
msg: 'error',
result: 'no payload provided',
result: 'unauthorized access',
};
res.end(JSON.stringify(errorObj));
} else {
shepherd.saveLocalAppConf(req.body.payload);
const successObj = {
msg: 'success',
result: 'config saved',
};
res.end(JSON.stringify(successObj));
}
});
@ -129,14 +138,23 @@ module.exports = (shepherd) => {
* params: none
*/
shepherd.post('/appconf/reset', (req, res, next) => {
shepherd.saveLocalAppConf(shepherd.defaultAppConfig);
if (shepherd.checkToken(req.body.token)) {
shepherd.saveLocalAppConf(shepherd.defaultAppConfig);
const successObj = {
msg: 'success',
result: 'config saved',
};
const successObj = {
msg: 'success',
result: 'config saved',
};
res.end(JSON.stringify(successObj));
} else {
const errorObj = {
msg: 'error',
result: 'unauthorized access',
};
res.end(JSON.stringify(successObj));
res.end(JSON.stringify(errorObj));
}
});
/*
@ -144,8 +162,17 @@ module.exports = (shepherd) => {
*
*/
shepherd.get('/appconf', (req, res, next) => {
const obj = shepherd.loadLocalConfig();
res.send(obj);
if (shepherd.checkToken(req.query.token)) {
const obj = shepherd.loadLocalConfig();
res.send(obj);
} else {
const errorObj = {
msg: 'error',
result: 'unauthorized access',
};
res.end(JSON.stringify(errorObj));
}
});
return shepherd;

199
routes/shepherd/daemonControl.js

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

518
routes/shepherd/dashboardUpdate.js

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

122
routes/shepherd/debugLog.js

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

208
routes/shepherd/downloadBins.js

@ -46,51 +46,60 @@ module.exports = (shepherd) => {
*/
// TODO: promises
shepherd.get('/update/bins/check', (req, res, next) => {
const rootLocation = shepherd.path.join(__dirname, '../../');
const successObj = {
msg: 'success',
result: 'bins',
};
res.end(JSON.stringify(successObj));
const _os = shepherd.os.platform();
shepherd.log(`checking bins: ${_os}`);
shepherd.io.emit('patch', {
patch: {
type: 'bins-check',
status: 'progress',
message: `checking bins: ${_os}`,
},
});
// get list of bins/dlls that can be updated to the latest
for (let i = 0; i < latestBins[_os].length; i++) {
shepherd.remoteFileSize(remoteBinLocation[_os] + latestBins[_os][i], (err, remoteBinSize) => {
const localBinSize = shepherd.fs.statSync(rootLocation + localBinLocation[_os] + latestBins[_os][i]).size;
shepherd.log('remote url: ' + (remoteBinLocation[_os] + latestBins[_os][i]) + ' (' + remoteBinSize + ')');
shepherd.log('local file: ' + (rootLocation + localBinLocation[_os] + latestBins[_os][i]) + ' (' + localBinSize + ')');
if (remoteBinSize !== localBinSize) {
shepherd.log(`${latestBins[_os][i]} can be updated`);
binsToUpdate.push({
name: latestBins[_os][i],
rSize: remoteBinSize,
lSize: localBinSize,
});
}
if (i === latestBins[_os].length - 1) {
shepherd.io.emit('patch', {
patch: {
type: 'bins-check',
status: 'done',
fileList: binsToUpdate,
},
});
}
if (shepherd.checkToken(req.query.token)) {
const rootLocation = shepherd.path.join(__dirname, '../../');
const successObj = {
msg: 'success',
result: 'bins',
};
res.end(JSON.stringify(successObj));
const _os = shepherd.os.platform();
shepherd.log(`checking bins: ${_os}`);
shepherd.io.emit('patch', {
patch: {
type: 'bins-check',
status: 'progress',
message: `checking bins: ${_os}`,
},
});
// get list of bins/dlls that can be updated to the latest
for (let i = 0; i < latestBins[_os].length; i++) {
shepherd.remoteFileSize(remoteBinLocation[_os] + latestBins[_os][i], (err, remoteBinSize) => {
const localBinSize = shepherd.fs.statSync(rootLocation + localBinLocation[_os] + latestBins[_os][i]).size;
shepherd.log('remote url: ' + (remoteBinLocation[_os] + latestBins[_os][i]) + ' (' + remoteBinSize + ')');
shepherd.log('local file: ' + (rootLocation + localBinLocation[_os] + latestBins[_os][i]) + ' (' + localBinSize + ')');
if (remoteBinSize !== localBinSize) {
shepherd.log(`${latestBins[_os][i]} can be updated`);
binsToUpdate.push({
name: latestBins[_os][i],
rSize: remoteBinSize,
lSize: localBinSize,
});
}
if (i === latestBins[_os].length - 1) {
shepherd.io.emit('patch', {
patch: {
type: 'bins-check',
status: 'done',
fileList: binsToUpdate,
},
});
}
});
}
} else {
const errorObj = {
msg: 'error',
result: 'unauthorized access',
};
res.end(JSON.stringify(errorObj));
}
});
@ -100,64 +109,73 @@ module.exports = (shepherd) => {
* params:
*/
shepherd.get('/update/bins', (req, res, next) => {
const rootLocation = shepherd.path.join(__dirname, '../../');
const _os = shepherd.os.platform();
const successObj = {
msg: 'success',
result: {
filesCount: binsToUpdate.length,
list: binsToUpdate,
},
};
res.end(JSON.stringify(successObj));
for (let i = 0; i < binsToUpdate.length; i++) {
shepherd.downloadFile({
remoteFile: remoteBinLocation[_os] + binsToUpdate[i].name,
localFile: `${rootLocation}${localBinLocation[_os]}patch/${binsToUpdate[i].name}`,
onProgress: (received, total) => {
const percentage = (received * 100) / total;
if (percentage.toString().indexOf('.10') > -1) {
if (shepherd.checkToken(req.query.token)) {
const rootLocation = shepherd.path.join(__dirname, '../../');
const _os = shepherd.os.platform();
const successObj = {
msg: 'success',
result: {
filesCount: binsToUpdate.length,
list: binsToUpdate,
},
};
res.end(JSON.stringify(successObj));
for (let i = 0; i < binsToUpdate.length; i++) {
shepherd.downloadFile({
remoteFile: remoteBinLocation[_os] + binsToUpdate[i].name,
localFile: `${rootLocation}${localBinLocation[_os]}patch/${binsToUpdate[i].name}`,
onProgress: (received, total) => {
const percentage = (received * 100) / total;
if (percentage.toString().indexOf('.10') > -1) {
shepherd.io.emit('patch', {
msg: {
type: 'bins-update',
status: 'progress',
file: binsToUpdate[i].name,
bytesTotal: total,
bytesReceived: received,
},
});
// shepherd.log(`${binsToUpdate[i].name} ${percentage}% | ${received} bytes out of ${total} bytes.`);
}
}
})
.then(() => {
// verify that remote file is matching to DL'ed file
const localBinSize = shepherd.fs.statSync(`${rootLocation}${localBinLocation[_os]}patch/${binsToUpdate[i].name}`).size;
shepherd.log('compare dl file size');
if (localBinSize === binsToUpdate[i].rSize) {
shepherd.io.emit('patch', {
msg: {
type: 'bins-update',
status: 'progress',
file: binsToUpdate[i].name,
bytesTotal: total,
bytesReceived: received,
status: 'done',
},
});
// shepherd.log(`${binsToUpdate[i].name} ${percentage}% | ${received} bytes out of ${total} bytes.`);
shepherd.log(`file ${binsToUpdate[i].name} succesfully downloaded`);
} else {
shepherd.io.emit('patch', {
msg: {
type: 'bins-update',
file: binsToUpdate[i].name,
message: 'size mismatch',
},
});
shepherd.log(`error: ${binsToUpdate[i].name} file size doesnt match remote!`);
}
}
})
.then(() => {
// verify that remote file is matching to DL'ed file
const localBinSize = shepherd.fs.statSync(`${rootLocation}${localBinLocation[_os]}patch/${binsToUpdate[i].name}`).size;
shepherd.log('compare dl file size');
if (localBinSize === binsToUpdate[i].rSize) {
shepherd.io.emit('patch', {
msg: {
type: 'bins-update',
file: binsToUpdate[i].name,
status: 'done',
},
});
shepherd.log(`file ${binsToUpdate[i].name} succesfully downloaded`);
} else {
shepherd.io.emit('patch', {
msg: {
type: 'bins-update',
file: binsToUpdate[i].name,
message: 'size mismatch',
},
});
shepherd.log(`error: ${binsToUpdate[i].name} file size doesnt match remote!`);
}
});
});
}
} else {
const errorObj = {
msg: 'error',
result: 'unauthorized access',
};
res.end(JSON.stringify(errorObj));
}
});

147
routes/shepherd/downloadPatch.js

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

107
routes/shepherd/downloadZcparams.js

@ -67,66 +67,75 @@ module.exports = (shepherd) => {
* params:
*/
shepherd.get('/zcparamsdl', (req, res, next) => {
// const dlLocation = shepherd.zcashParamsDir + '/test';
const dlLocation = shepherd.zcashParamsDir;
const dlOption = req.query.dloption;
if (shepherd.checkToken(req.query.token)) {
// const dlLocation = shepherd.zcashParamsDir + '/test';
const dlLocation = shepherd.zcashParamsDir;
const dlOption = req.query.dloption;
const successObj = {
msg: 'success',
result: 'zcash params dl started',
};
const successObj = {
msg: 'success',
result: 'zcash params dl started',
};
res.end(JSON.stringify(successObj));
res.end(JSON.stringify(successObj));
for (let key in shepherd.zcashParamsDownloadLinks[dlOption]) {
shepherd.downloadFile({
remoteFile: shepherd.zcashParamsDownloadLinks[dlOption][key],
localFile: `${dlLocation}/sprout-${key}.key`,
onProgress: (received, total) => {
const percentage = (received * 100) / total;
if (percentage.toString().indexOf('.10') > -1) {
shepherd.io.emit('zcparams', {
msg: {
type: 'zcpdownload',
status: 'progress',
file: key,
bytesTotal: total,
bytesReceived: received,
progress: percentage,
},
});
// shepherd.log(`${key} ${percentage}% | ${received} bytes out of ${total} bytes.`);
}
}
})
.then(() => {
const checkZcashParams = shepherd.zcashParamsExist();
for (let key in shepherd.zcashParamsDownloadLinks[dlOption]) {
shepherd.downloadFile({
remoteFile: shepherd.zcashParamsDownloadLinks[dlOption][key],
localFile: `${dlLocation}/sprout-${key}.key`,
onProgress: (received, total) => {
const percentage = (received * 100) / total;
shepherd.log(`${key} dl done`);
if (percentage.toString().indexOf('.10') > -1) {
if (checkZcashParams.error) {
shepherd.io.emit('zcparams', {
msg: {
type: 'zcpdownload',
status: 'progress',
file: key,
bytesTotal: total,
bytesReceived: received,
progress: percentage,
status: 'error',
message: 'size mismatch',
progress: 100,
},
});
// shepherd.log(`${key} ${percentage}% | ${received} bytes out of ${total} bytes.`);
} else {
shepherd.io.emit('zcparams', {
msg: {
type: 'zcpdownload',
file: key,
progress: 100,
status: 'done',
},
});
shepherd.log(`file ${key} succesfully downloaded`);
}
}
})
.then(() => {
const checkZcashParams = shepherd.zcashParamsExist();
shepherd.log(`${key} dl done`);
if (checkZcashParams.error) {
shepherd.io.emit('zcparams', {
msg: {
type: 'zcpdownload',
file: key,
status: 'error',
message: 'size mismatch',
progress: 100,
},
});
} else {
shepherd.io.emit('zcparams', {
msg: {
type: 'zcpdownload',
file: key,
progress: 100,
status: 'done',
},
});
shepherd.log(`file ${key} succesfully downloaded`);
}
});
});
}
} else {
const errorObj = {
msg: 'error',
result: 'unauthorized access',
};
res.end(JSON.stringify(errorObj));
}
});

139
routes/shepherd/electrum/auth.js

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

201
routes/shepherd/electrum/balance.js

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

46
routes/shepherd/electrum/block.js

@ -1,14 +1,23 @@
module.exports = (shepherd) => {
shepherd.get('/electrum/getblockinfo', (req, res, next) => {
shepherd.electrumGetBlockInfo(req.query.height, req.query.network)
.then((json) => {
const successObj = {
msg: 'success',
result: json,
if (shepherd.checkToken(req.query.token)) {
shepherd.electrumGetBlockInfo(req.query.height, req.query.network)
.then((json) => {
const successObj = {
msg: 'success',
result: json,
};
res.end(JSON.stringify(successObj));
});
} else {
const errorObj = {
msg: 'error',
result: 'unauthorized access',
};
res.end(JSON.stringify(successObj));
});
res.end(JSON.stringify(errorObj));
}
});
shepherd.electrumGetBlockInfo = (height, network) => {
@ -28,15 +37,24 @@ module.exports = (shepherd) => {
}
shepherd.get('/electrum/getcurrentblock', (req, res, next) => {
shepherd.electrumGetCurrentBlock(req.query.network)
.then((json) => {
const successObj = {
msg: 'success',
result: json,
if (shepherd.checkToken(req.query.token)) {
shepherd.electrumGetCurrentBlock(req.query.network)
.then((json) => {
const successObj = {
msg: 'success',
result: json,
};
res.end(JSON.stringify(successObj));
});
} else {
const errorObj = {
msg: 'error',
result: 'unauthorized access',
};
res.end(JSON.stringify(successObj));
});
res.end(JSON.stringify(errorObj));
}
});
shepherd.electrumGetCurrentBlock = (network) => {

73
routes/shepherd/electrum/coins.js

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

735
routes/shepherd/electrum/createtx.js

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

31
routes/shepherd/electrum/estimate.js

@ -1,20 +1,29 @@
module.exports = (shepherd) => {
shepherd.get('/electrum/estimatefee', (req, res, next) => {
const ecl = new shepherd.electrumJSCore(shepherd.electrumServers[req.query.network].port, shepherd.electrumServers[req.query.network].address, shepherd.electrumServers[req.query.network].proto); // tcp or tls
if (shepherd.checkToken(req.query.token)) {
const ecl = new shepherd.electrumJSCore(shepherd.electrumServers[req.query.network].port, shepherd.electrumServers[req.query.network].address, shepherd.electrumServers[req.query.network].proto); // tcp or tls
ecl.connect();
ecl.blockchainEstimatefee(req.query.blocks)
.then((json) => {
ecl.close();
shepherd.log('electrum estimatefee ==>', true);
ecl.connect();
ecl.blockchainEstimatefee(req.query.blocks)
.then((json) => {
ecl.close();
shepherd.log('electrum estimatefee ==>', true);
const successObj = {
msg: 'success',
result: json,
const successObj = {
msg: 'success',
result: json,
};
res.end(JSON.stringify(successObj));
});
} else {
const errorObj = {
msg: 'error',
result: 'unauthorized access',
};
res.end(JSON.stringify(successObj));
});
res.end(JSON.stringify(errorObj));
}
});
shepherd.estimateTxSize = (numVins, numOuts) => {

219
routes/shepherd/electrum/keys.js

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

73
routes/shepherd/electrum/listunspent.js

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

27
routes/shepherd/electrum/merkle.js

@ -128,17 +128,26 @@ module.exports = (shepherd) => {
}
shepherd.get('/electrum/merkle/verify', (req, res, next) => {
shepherd.verifyMerkleByCoin(req.query.coin, req.query.txid, req.query.height)
.then((verifyMerkleRes) => {
const successObj = {
msg: 'success',
result: {
merkleProof: verifyMerkleRes,
},
if (shepherd.checkToken(req.query.token)) {
shepherd.verifyMerkleByCoin(req.query.coin, req.query.txid, req.query.height)
.then((verifyMerkleRes) => {
const successObj = {
msg: 'success',
result: {
merkleProof: verifyMerkleRes,
},
};
res.end(JSON.stringify(successObj));
});
} else {
const errorObj = {
msg: 'error',
result: 'unauthorized access',
};
res.end(JSON.stringify(successObj));
});
res.end(JSON.stringify(errorObj));
}
});
return shepherd;

147
routes/shepherd/electrum/network.js

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

454
routes/shepherd/electrum/transactions.js

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

59
routes/shepherd/kickstart.js

@ -7,37 +7,46 @@ module.exports = (shepherd) => {
* params: coin, type
*/
shepherd.get('/kick', (req, res, next) => {
const _coin = req.query.coin;
const _keepWallet = req.query.keepwallet;
if (shepherd.checkToken(req.query.token)) {
const _coin = req.query.coin;
const _keepWallet = req.query.keepwallet;
if (!_coin) {
const errorObj = {
msg: 'error',
result: 'no coin name provided',
};
res.end(JSON.stringify(errorObj));
} else {
const _location = path.join(_coin === 'KMD' ? shepherd.komodoDir : `${shepherd.komodoDir}/${_coin}`);
if (fs.existsSync(_location)) {
const items = fs.readdirSync(_location);
for (let i = 0; i < items.length; i++) {
if (items[i].indexOf('wallet.dat') === -1) {
fs.removeSync(`${_location}/${items[i]}`);
} else if (!_keepWallet) {
fs.removeSync(`${_location}/${items[i]}`);
}
}
}
if (!_coin) {
const successObj = {
msg: 'success',
result: `${_coin} native is kicked`,
};
res.end(JSON.stringify(successObj));
}
} else {
const errorObj = {
msg: 'error',
result: 'no coin name provided',
result: 'unauthorized access',
};
res.end(JSON.stringify(errorObj));
} else {
const _location = path.join(_coin === 'KMD' ? shepherd.komodoDir : `${shepherd.komodoDir}/${_coin}`);
if (fs.existsSync(_location)) {
const items = fs.readdirSync(_location);
for (let i = 0; i < items.length; i++) {
if (items[i].indexOf('wallet.dat') === -1) {
fs.removeSync(`${_location}/${items[i]}`);
} else if (!_keepWallet) {
fs.removeSync(`${_location}/${items[i]}`);
}
}
}
const successObj = {
msg: 'success',
result: `${_coin} native is kicked`,
};
res.end(JSON.stringify(successObj));
}
});

127
routes/shepherd/log.js

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

209
routes/shepherd/pin.js

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

132
routes/shepherd/quitDaemon.js

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

451
routes/shepherd/rpc.js

@ -60,270 +60,279 @@ module.exports = (shepherd) => {
* params: payload
*/
shepherd.post('/cli', (req, res, next) => {
if (!req.body.payload) {
const errorObj = {
msg: 'error',
result: 'no payload provided',
};
if (shepherd.checkToken(req.body.payload.token)) {
if (!req.body.payload) {
const errorObj = {
msg: 'error',
result: 'no payload provided',
};
res.end(JSON.stringify(errorObj));
} else if (!req.body.payload.cmd.match(/^[0-9a-zA-Z _\,\.\[\]"'/\\]+$/g)) {
const errorObj = {
msg: 'error',
result: 'wrong cli string format',
};
res.end(JSON.stringify(errorObj));
} else {
const _mode = req.body.payload.mode === 'passthru' ? 'passthru' : 'default';
const _chain = req.body.payload.chain === 'KMD' ? null : req.body.payload.chain;
let _params = req.body.payload.params ? ` ${req.body.payload.params}` : '';
let _cmd = req.body.payload.cmd;
res.end(JSON.stringify(errorObj));
} else if (!req.body.payload.cmd.match(/^[0-9a-zA-Z _\,\.\[\]"'/\\]+$/g)) {
const errorObj = {
msg: 'error',
result: 'wrong cli string format',
};
if (!shepherd.rpcConf[_chain]) {
shepherd.getConf(req.body.payload.chain === 'KMD' || !req.body.payload.chain && shepherd.kmdMainPassiveMode ? 'komodod' : req.body.payload.chain);
}
res.end(JSON.stringify(errorObj));
} else {
const _mode = req.body.payload.mode === 'passthru' ? 'passthru' : 'default';
const _chain = req.body.payload.chain === 'KMD' ? null : req.body.payload.chain;
let _params = req.body.payload.params ? ` ${req.body.payload.params}` : '';
let _cmd = req.body.payload.cmd;
if (_mode === 'default') {
if (req.body.payload.rpc2cli) {
let _coindCliBin = shepherd.komodocliBin;
if (!shepherd.rpcConf[_chain]) {
shepherd.getConf(req.body.payload.chain === 'KMD' || !req.body.payload.chain && shepherd.kmdMainPassiveMode ? 'komodod' : req.body.payload.chain);
}
if (shepherd.nativeCoindList &&
_chain &&
shepherd.nativeCoindList[_chain.toLowerCase()]) {
_coindCliBin = `${shepherd.coindRootDir}/${_chain.toLowerCase()}/${shepherd.nativeCoindList[_chain.toLowerCase()].bin.toLowerCase()}-cli`;
}
if (_mode === 'default') {
if (req.body.payload.rpc2cli) {
let _coindCliBin = shepherd.komodocliBin;
if (_params.indexOf('*')) {
_params = _params.replace('*', '"*"');
}
if (_params.indexOf(',') > -1) {
_params = _params.split(',');
}
if (_cmd.indexOf('getaddressesbyaccount') > -1) {
_cmd = 'getaddressesbyaccount ""';
}
if (shepherd.nativeCoindList &&
_chain &&
shepherd.nativeCoindList[_chain.toLowerCase()]) {
_coindCliBin = `${shepherd.coindRootDir}/${_chain.toLowerCase()}/${shepherd.nativeCoindList[_chain.toLowerCase()].bin.toLowerCase()}-cli`;
}
let _arg = (_chain ? ' -ac_name=' + _chain : '') + ' ' + _cmd + (typeof _params === 'object' ? _params.join(' ') : _params);
if (_params.indexOf('*')) {
_params = _params.replace('*', '"*"');
}
if (_params.indexOf(',') > -1) {
_params = _params.split(',');
}
if (_cmd.indexOf('getaddressesbyaccount') > -1) {
_cmd = 'getaddressesbyaccount ""';
}
if (shepherd.appConfig.dataDir.length) {
_arg = `${_arg} -datadir=${shepherd.appConfig.dataDir + (_chain ? '/' + key : '')}`;
}
let _arg = (_chain ? ' -ac_name=' + _chain : '') + ' ' + _cmd + (typeof _params === 'object' ? _params.join(' ') : _params);
shepherd.exec(`"${_coindCliBin}" ${_arg}`, (error, stdout, stderr) => {
//shepherd.log(`stdout: ${stdout}`);
//shepherd.log(`stderr: ${stderr}`);
if (shepherd.appConfig.dataDir.length) {
_arg = `${_arg} -datadir=${shepherd.appConfig.dataDir + (_chain ? '/' + key : '')}`;
}
if (error !== null) {
shepherd.log(`exec error: ${error}`);
}
shepherd.exec(`"${_coindCliBin}" ${_arg}`, (error, stdout, stderr) => {
//shepherd.log(`stdout: ${stdout}`);
//shepherd.log(`stderr: ${stderr}`);
let responseObj;
if (error !== null) {
shepherd.log(`exec error: ${error}`);
}
if (stderr) {
let _res;
let _error;
let responseObj;
if (_chain !== 'komodod' &&
stderr.indexOf(`error creating`) > -1) {
shepherd.log(`replace error creating (gen${_chain})`);
stderr = stderr.replace(`error creating (gen${_chain})`, '');
shepherd.log(stderr);
}
if (stderr) {
let _res;
let _error;
if (_chain !== 'komodod' &&
stderr.indexOf(`error creating`) > -1) {
shepherd.log(`replace error creating (gen${_chain})`);
stderr = stderr.replace(`error creating (gen${_chain})`, '');
shepherd.log(stderr);
}
if ((stderr.indexOf('{') > -1 && stderr.indexOf('}') > -1) ||
(stderr.indexOf('[') > -1 && stderr.indexOf(']') > -1)) {
_res = JSON.parse(stderr);
} else {
_res = stderr.trim();
}
if (stderr.indexOf('error code:') > -1) {
_error = {
code: Number(stderr.substring(stderr.indexOf('error code:') + 11, stderr.indexOf('error message:') - stderr.indexOf('error code:')).trim()),
message: stderr.substring(stderr.indexOf('error message:') + 15, stderr.length).trim(),
};
}
if ((stderr.indexOf('{') > -1 && stderr.indexOf('}') > -1) ||
(stderr.indexOf('[') > -1 && stderr.indexOf(']') > -1)) {
_res = JSON.parse(stderr);
if (_error) {
responseObj = {
error: _error,
};
} else {
responseObj = {
result: _res,
};
}
} else {
_res = stderr.trim();
}
let _res;
let _error;
if (_chain !== 'komodod' &&
stdout.indexOf(`error creating`) > -1) {
shepherd.log(`replace error creating (gen${_chain})`);
stdout = stdout.replace(`error creating (gen${_chain})`, '');
shepherd.log(stdout);
}
if (stderr.indexOf('error code:') > -1) {
_error = {
code: Number(stderr.substring(stderr.indexOf('error code:') + 11, stderr.indexOf('error message:') - stderr.indexOf('error code:')).trim()),
message: stderr.substring(stderr.indexOf('error message:') + 15, stderr.length).trim(),
};
if ((stdout.indexOf('{') > -1 && stdout.indexOf('}') > -1) ||
(stdout.indexOf('[') > -1 && stdout.indexOf(']') > -1)) {
_res = JSON.parse(stdout);
} else {
_res = stdout.trim();
}
if (stdout.indexOf('error code:') > -1) {
_error = {
code: Number(stdout.substring(stdout.indexOf('error code:') + 11, stdout.indexOf('error message:') - stdout.indexOf('error code:')).trim()),
message: stdout.substring(stdout.indexOf('error message:') + 15, stdout.length).trim(),
};
}
if (_error) {
responseObj = {
error: _error,
};
} else {
responseObj = {
result: _res,
};
}
}
if (_error) {
responseObj = {
error: _error,
};
res.end(JSON.stringify(responseObj));
// shepherd.killRogueProcess('komodo-cli');
});
} else {
if (_cmd === 'debug' &&
_chain !== 'CHIPS') {
if (shepherd.nativeCoindList[_chain.toLowerCase()]) {
const _osHome = os.platform === 'win32' ? process.env.APPDATA : process.env.HOME;
let coindDebugLogLocation;
if (_chain === 'CHIPS') {
coindDebugLogLocation = `${shepherd.chipsDir}/debug.log`;
} else {
coindDebugLogLocation = `${_osHome}/.${shepherd.nativeCoindList[_chain.toLowerCase()].bin.toLowerCase()}/debug.log`;
}
shepherd.readDebugLog(coindDebugLogLocation, 1)
.then((result) => {
const _obj = {
msg: 'success',
result: result,
};
// shepherd.log('bitcoinrpc debug ====>');
// console.log(result);
res.end(JSON.stringify(_obj));
}, (result) => {
const _obj = {
error: result,
result: 'error',
};
res.end(JSON.stringify(_obj));
});
} else {
responseObj = {
result: _res,
};
res.end({
error: 'bitcoinrpc debug error',
result: 'error',
});
// console.log('bitcoinrpc debug error');
}
} else {
let _res;
let _error;
if (_chain !== 'komodod' &&
stdout.indexOf(`error creating`) > -1) {
shepherd.log(`replace error creating (gen${_chain})`);
stdout = stdout.replace(`error creating (gen${_chain})`, '');
shepherd.log(stdout);
if (_chain === 'CHIPS' &&
_cmd === 'debug') {
_cmd = 'getblockchaininfo';
}
if ((stdout.indexOf('{') > -1 && stdout.indexOf('}') > -1) ||
(stdout.indexOf('[') > -1 && stdout.indexOf(']') > -1)) {
_res = JSON.parse(stdout);
} else {
_res = stdout.trim();
}
let _body = {
agent: 'bitcoinrpc',
method: _cmd,
};
if (stdout.indexOf('error code:') > -1) {
_error = {
code: Number(stdout.substring(stdout.indexOf('error code:') + 11, stdout.indexOf('error message:') - stdout.indexOf('error code:')).trim()),
message: stdout.substring(stdout.indexOf('error message:') + 15, stdout.length).trim(),
if (req.body.payload.params) {
_body = {
agent: 'bitcoinrpc',
method: _cmd,
params: req.body.payload.params === ' ' ? [''] : req.body.payload.params,
};
}
if (_error) {
responseObj = {
error: _error,
};
} else {
responseObj = {
result: _res,
if (req.body.payload.chain) {
const options = {
url: `http://localhost:${shepherd.rpcConf[req.body.payload.chain].port}`,
method: 'POST',
auth: {
user: shepherd.rpcConf[req.body.payload.chain].user,
pass: shepherd.rpcConf[req.body.payload.chain].pass,
},
body: JSON.stringify(_body),
};
// send back body on both success and error
// this bit replicates iguana core's behaviour
shepherd.request(options, (error, response, body) => {
if (response &&
response.statusCode &&
response.statusCode === 200) {
res.end(body);
} else {
res.end(body ? body : JSON.stringify({
result: 'error',
error: {
code: -777,
message: `unable to call method ${_cmd} at port ${shepherd.rpcConf[req.body.payload.chain].port}`,
},
}));
}
});
}
}
res.end(JSON.stringify(responseObj));
// shepherd.killRogueProcess('komodo-cli');
});
}
} else {
if (_cmd === 'debug' &&
_chain !== 'CHIPS') {
if (shepherd.nativeCoindList[_chain.toLowerCase()]) {
const _osHome = os.platform === 'win32' ? process.env.APPDATA : process.env.HOME;
let coindDebugLogLocation;
if (_chain === 'CHIPS') {
coindDebugLogLocation = `${shepherd.chipsDir}/debug.log`;
} else {
coindDebugLogLocation = `${_osHome}/.${shepherd.nativeCoindList[_chain.toLowerCase()].bin.toLowerCase()}/debug.log`;
}
let _coindCliBin = shepherd.komodocliBin;
shepherd.readDebugLog(coindDebugLogLocation, 1)
.then((result) => {
const _obj = {
msg: 'success',
result: result,
};
if (shepherd.nativeCoindList &&
_chain &&
shepherd.nativeCoindList[_chain.toLowerCase()]) {
_coindCliBin = `${shepherd.coindRootDir}/${_chain.toLowerCase()}/${shepherd.nativeCoindList[_chain.toLowerCase()].bin.toLowerCase()}-cli`;
}
// shepherd.log('bitcoinrpc debug ====>');
// console.log(result);
let _arg = (_chain ? ' -ac_name=' + _chain : '') + ' ' + _cmd + _params;
res.end(JSON.stringify(_obj));
}, (result) => {
const _obj = {
error: result,
result: 'error',
};
if (shepherd.appConfig.dataDir.length) {
_arg = `${_arg} -datadir=${shepherd.appConfig.dataDir + (_chain ? '/' + key : '')}`;
}
res.end(JSON.stringify(_obj));
});
} else {
res.end({
error: 'bitcoinrpc debug error',
result: 'error',
});
// console.log('bitcoinrpc debug error');
}
} else {
if (_chain === 'CHIPS' &&
_cmd === 'debug') {
_cmd = 'getblockchaininfo';
_arg = _arg.trim().split(' ');
shepherd.execFile(_coindCliBin, _arg, (error, stdout, stderr) => {
shepherd.log(`stdout: ${stdout}`);
shepherd.log(`stderr: ${stderr}`);
if (error !== null) {
shepherd.log(`exec error: ${error}`);
}
let _body = {
agent: 'bitcoinrpc',
method: _cmd,
};
let responseObj;
if (req.body.payload.params) {
_body = {
agent: 'bitcoinrpc',
method: _cmd,
params: req.body.payload.params === ' ' ? [''] : req.body.payload.params,
if (stderr) {
responseObj = {
msg: 'error',
result: stderr,
};
}
if (req.body.payload.chain) {
const options = {
url: `http://localhost:${shepherd.rpcConf[req.body.payload.chain].port}`,
method: 'POST',
auth: {
user: shepherd.rpcConf[req.body.payload.chain].user,
pass: shepherd.rpcConf[req.body.payload.chain].pass,
},
body: JSON.stringify(_body),
} else {
responseObj = {
msg: 'success',
result: stdout,
};
// send back body on both success and error
// this bit replicates iguana core's behaviour
shepherd.request(options, (error, response, body) => {
if (response &&
response.statusCode &&
response.statusCode === 200) {
res.end(body);
} else {
res.end(body ? body : JSON.stringify({
result: 'error',
error: {
code: -777,
message: `unable to call method ${_cmd} at port ${shepherd.rpcConf[req.body.payload.chain].port}`,
},
}));
}
});
}
}
}
} else {
let _coindCliBin = shepherd.komodocliBin;
if (shepherd.nativeCoindList &&
_chain &&
shepherd.nativeCoindList[_chain.toLowerCase()]) {
_coindCliBin = `${shepherd.coindRootDir}/${_chain.toLowerCase()}/${shepherd.nativeCoindList[_chain.toLowerCase()].bin.toLowerCase()}-cli`;
}
let _arg = (_chain ? ' -ac_name=' + _chain : '') + ' ' + _cmd + _params;
if (shepherd.appConfig.dataDir.length) {
_arg = `${_arg} -datadir=${shepherd.appConfig.dataDir + (_chain ? '/' + key : '')}`;
res.end(JSON.stringify(responseObj));
shepherd.killRogueProcess('komodo-cli');
});
}
_arg = _arg.trim().split(' ');
shepherd.execFile(_coindCliBin, _arg, (error, stdout, stderr) => {
shepherd.log(`stdout: ${stdout}`);
shepherd.log(`stderr: ${stderr}`);
if (error !== null) {
shepherd.log(`exec error: ${error}`);
}
let responseObj;
if (stderr) {
responseObj = {
msg: 'error',
result: stderr,
};
} else {
responseObj = {
msg: 'success',
result: stdout,
};
}
res.end(JSON.stringify(responseObj));
shepherd.killRogueProcess('komodo-cli');
});
}
} else {
const errorObj = {
msg: 'error',
result: 'unauthorized access',
};
res.end(JSON.stringify(errorObj));
}
});

Loading…
Cancel
Save