Browse Source

Merge pull request #4 from KomodoPlatform/dev

Dev
dev
siulynot 7 years ago
committed by GitHub
parent
commit
5e78877f2b
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      gui/EasyDEX-GUI
  2. 34
      main.js
  3. 10
      package.json
  4. 301
      routes/electrumjs/electrumServers.js
  5. 23
      routes/electrumjs/electrumjs.networks.js
  6. 61
      routes/electrumjs/electrumjs.txdecoder-2bytes.js
  7. 61
      routes/electrumjs/electrumjs.txdecoder.js
  8. 4
      routes/shepherd.js
  9. 209
      routes/shepherd/addCoinShortcuts.js
  10. 42
      routes/shepherd/auth.js
  11. 2
      routes/shepherd/coindWalletKeys.js
  12. 13
      routes/shepherd/daemonControl.js
  13. 8
      routes/shepherd/dashboardUpdate.js
  14. 96
      routes/shepherd/debugLog.js
  15. 19
      routes/shepherd/elections.js
  16. 15
      routes/shepherd/electrum/auth.js
  17. 7
      routes/shepherd/electrum/balance.js
  18. 12
      routes/shepherd/electrum/block.js
  19. 13
      routes/shepherd/electrum/btcFees.js
  20. 4
      routes/shepherd/electrum/coins.js
  21. 54
      routes/shepherd/electrum/createtx-multi.js
  22. 18
      routes/shepherd/electrum/createtx-split.js
  23. 71
      routes/shepherd/electrum/createtx.js
  24. 6
      routes/shepherd/electrum/estimate.js
  25. 23
      routes/shepherd/electrum/keys.js
  26. 17
      routes/shepherd/electrum/network.js
  27. 57
      routes/shepherd/electrum/transactions.js
  28. 24
      routes/shepherd/log.js
  29. 175
      routes/shepherd/pin.js
  30. 19
      routes/shepherd/quitDaemon.js
  31. 4
      version
  32. 2
      version_build

2
gui/EasyDEX-GUI

@ -1 +1 @@
Subproject commit b9b1283f55561064794a7ba58bc8ae4371b106fc
Subproject commit 88a8bcf78b2c8d5e400f8a58512195383dd4db8f

34
main.js

@ -20,11 +20,14 @@ const fsnode = require('fs');
const fs = require('fs-extra');
const Promise = require('bluebird');
const arch = require('arch');
const bip39 = require('bip39');
if (osPlatform === 'linux') {
process.env.ELECTRON_RUN_AS_NODE = true;
}
process.env.ELECTRON_DISABLE_SECURITY_WARNINGS = true;
// GUI APP settings and starting gui on address http://120.0.0.1:17777
let shepherd = require('./routes/shepherd');
let guiapp = express();
@ -124,8 +127,7 @@ process.once('loaded', () => {
});
// silent errors
if (!appConfig.debug ||
!appConfig.dev) {
if (!appConfig.dev) {
process.on('uncaughtException', (err) => {
shepherd.log(`${(new Date).toUTCString()} uncaughtException: ${err.message}`);
shepherd.log(err.stack);
@ -185,7 +187,7 @@ function createAppCloseWindow() {
appCloseWindow.setResizable(false);
appCloseWindow.loadURL(`http://${appConfig.host}:${appConfig.agamaPort}/gui/startup/app-closing.html`);
appCloseWindow.loadURL(appConfig.dev ? `http://${appConfig.host}:${appConfig.agamaPort}/gui/startup/app-closing.html` : `file://${__dirname}/gui/startup/app-closing.html`);
appCloseWindow.webContents.on('did-finish-load', () => {
setTimeout(() => {
@ -232,7 +234,7 @@ function createWindow(status, hideLoadingWindow) {
shepherd.log(`guiapp and sockets.io are listening on port ${appConfig.agamaPort}`);
shepherd.writeLog(`guiapp and sockets.io are listening on port ${appConfig.agamaPort}`);
// start sockets.io
io.set('origins', appConfig.dev ? 'http://127.0.0.1:3000' : `http://127.0.0.1:${appConfig.agamaPort}`); // set origin
io.set('origins', appConfig.dev ? 'http://127.0.0.1:3000' : null); // set origin
});
// initialise window
@ -246,15 +248,15 @@ function createWindow(status, hideLoadingWindow) {
if (appConfig.dev) {
mainWindow.loadURL('http://127.0.0.1:3000');
} else {
mainWindow.loadURL(`http://${appConfig.host}:${appConfig.agamaPort}/gui/EasyDEX-GUI/react/build`);
mainWindow.loadURL(`file://${__dirname}/gui/EasyDEX-GUI/react/build/index.html`);
}
shepherd.setIO(io); // pass sockets object to shepherd router
shepherd.setVar('appBasicInfo', appBasicInfo);
shepherd.setVar('appSessionHash', appSessionHash);
// load our index.html (i.e. easyDEX GUI)
shepherd.writeLog('show edex gui');
// load our index.html (i.e. Agama GUI)
shepherd.writeLog('show agama gui');
mainWindow.appConfig = appConfig;
mainWindow.appConfigSchema = shepherd.appConfigSchema;
mainWindow.arch = arch();
@ -288,15 +290,19 @@ function createWindow(status, hideLoadingWindow) {
firstLoginPH: null,
secondaryLoginPH: null,
};
mainWindow.nnVoteChain = 'VOTE2018';
mainWindow.checkStringEntropy = shepherd.checkStringEntropy;
mainWindow.pinAccess = false;
mainWindow.bip39 = bip39;
mainWindow.isWatchOnly = shepherd.isWatchOnly;
mainWindow.setPubkey = shepherd.setPubkey;
mainWindow.getPubkeys = shepherd.getPubkeys;
/*for (let i = 0; i < process.argv.length; i++) {
for (let i = 0; i < process.argv.length; i++) {
if (process.argv[i].indexOf('nvote') > -1) {
console.log(`notary node elections chain ${process.argv[i].replace('nvote=', '')}`);
mainWindow.nnVoteChain = process.argv[i].replace('nvote=', '');
console.log(`enable notary node elections ui`);
mainWindow.nnVoteChain = 'VOTE2018';
}
}*/
}
} else {
mainWindow = new BrowserWindow({
width: 500,
@ -314,7 +320,7 @@ function createWindow(status, hideLoadingWindow) {
shepherd.log(`guiapp and sockets.io are listening on port ${appConfig.agamaPort + 1}`);
shepherd.writeLog(`guiapp and sockets.io are listening on port ${appConfig.agamaPort + 1}`);
});
mainWindow.loadURL(`http://${appConfig.host}:${appConfig.agamaPort + 1}/gui/startup/agama-instance-error.html`);
mainWindow.loadURL(appConfig.dev ? `http://${appConfig.host}:${appConfig.agamaPort + 1}/gui/startup/agama-instance-error.html` : `file://${__dirname}/gui/startup/agama-instance-error.html`);
shepherd.log('another agama app is already running');
}
@ -485,4 +491,4 @@ function formatBytes(bytes, decimals) {
const i = Math.floor(Math.log(bytes) / Math.log(k));
return `${parseFloat((bytes / Math.pow(k, i)).toFixed(dm))} ${sizes[i]}`;
}
}

10
package.json

@ -1,7 +1,7 @@
{
"name": "agama-app",
"productName": "Agama",
"version": "0.2.32",
"version": "0.2.35",
"description": "Agama Wallet Desktop App",
"main": "main.js",
"scripts": {
@ -31,11 +31,12 @@
"arch": "^2.1.0",
"async": "^2.6.0",
"bigi": "^1.4.2",
"bip39": "^2.4.0",
"bip39": "^2.5.0",
"bitcoinforksjs-lib": "git://github.com/SuperNETorg/bitcoinjs-lib#opt-in-bitcoincash-sighash",
"bitcoinjs-lib": "git://github.com/SuperNETorg/bitcoinjs-lib",
"bitcoinjs-lib-zcash": "git://github.com/pbca26/bitcoinjs-lib#zcash",
"bitcoinjs-lib-pos": "git://github.com/KomodoPlatform/bitcoinjs-lib-pos",
"bitcoinjs-lib-zcash": "git://github.com/pbca26/bitcoinjs-lib#zcash",
"tx-decoder": "git://github.com/pbca26/tx-decoder",
"bluebird": "^3.4.7",
"body-parser": "^1.15.2",
"buffer-reverse": "^1.0.1",
@ -46,9 +47,10 @@
"fs-extra": "^4.0.2",
"graceful-fs": "^4.1.11",
"js-sha256": "^0.7.1",
"lz-string": "^1.4.4",
"marketmaker": "git://github.com/pbca26/marketmaker",
"nodejs-aes256": "^1.0.1",
"passwd-strength": "https://github.com/pbca26/passwd-strength",
"passwd-strength": "git+https://github.com/pbca26/passwd-strength.git",
"portscanner": "^2.1.1",
"ps-node": "^0.1.5",
"remote-file-size": "^3.0.3",

301
routes/electrumjs/electrumServers.js

@ -1,4 +1,15 @@
let electrumServers = {
kv: { // !estimatefee
address: 'electrum1.cipig.net',
port: 10016,
proto: 'tcp',
txfee: 10000,
abbr: 'KV',
serverList: [
'electrum1.cipig.net:10016',
'electrum2.cipig.net:10016'
],
},
bntn: { // !estimatefee
address: 'electrum1.cipig.net',
port: 10026,
@ -280,113 +291,113 @@ let electrumServers = {
],
},
dogecoin: { // !estimatefee
address: '173.212.225.176',
port: 50015,
address: 'electrum1.cipig.net',
port: 10060,
proto: 'tcp',
txfee: 100000000,
abbr: 'DOGE',
serverList: [
'173.212.225.176:50015',
'136.243.45.140:50015'
'electrum1.cipig.net:10060',
'electrum2.cipig.net:10060'
],
},
viacoin: { // !estimatefee
address: '173.212.225.176',
port: 50033,
address: 'electrum1.cipig.net',
port: 10067,
proto: 'tcp',
txfee: 100000,
abbr: 'VIA',
serverList: [
'173.212.225.176:50033',
'136.243.45.140:50033'
'electrum1.cipig.net:10067',
'electrum2.cipig.net:10067'
],
},
vertcoin: {
address: '173.212.225.176',
port: 50088,
address: 'electrum1.cipig.net',
port: 10071,
proto: 'tcp',
txfee: 100000,
abbr: 'VTC',
serverList: [
'173.212.225.176:50088',
'136.243.45.140:50088'
'electrum1.cipig.net:10071',
'electrum2.cipig.net:10071'
],
},
namecoin: {
address: '173.212.225.176',
port: 50036,
address: 'electrum1.cipig.net',
port: 10066,
proto: 'tcp',
txfee: 100000,
abbr: 'NMC',
serverList: [
'173.212.225.176:50036',
'136.243.45.140:50036'
'electrum1.cipig.net:10066',
'electrum2.cipig.net:10066'
],
},
monacoin: { // !estimatefee
address: '173.212.225.176',
port: 50002,
address: 'electrum1.cipig.net',
port: 10070,
proto: 'tcp',
txfee: 100000,
abbr: 'MONA',
serverList: [
'173.212.225.176:50002',
'136.243.45.140:50002'
'electrum1.cipig.net:10070',
'electrum2.cipig.net:10070'
],
},
litecoin: {
address: '173.212.225.176',
port: 50012,
address: 'electrum1.cipig.net',
port: 10065,
proto: 'tcp',
txfee: 100000,
abbr: 'LTC',
serverList: [
'173.212.225.176:50012',
'136.243.45.140:50012'
'electrum1.cipig.net:10065',
'electrum2.cipig.net:10065'
],
},
faircoin: {
address: '173.212.225.176',
port: 50005,
address: 'electrum1.cipig.net',
port: 10063,
proto: 'tcp',
txfee: 1000000,
abbr: 'FAIR',
serverList: [
'173.212.225.176:50005',
'136.243.45.140:50005'
'electrum1.cipig.net:10063',
'electrum2.cipig.net:10063'
],
},
dgb: {
address: '173.212.225.176',
port: 50022,
address: 'electrum1.cipig.net',
port: 10059,
proto: 'tcp',
txfee: 100000,
abbr: 'DGB',
serverList: [
'173.212.225.176:50022',
'136.243.45.140:50022'
'electrum1.cipig.net:10059',
'electrum2.cipig.net:10059'
],
},
dash: {
address: '173.212.225.176',
port: 50098,
address: 'electrum1.cipig.net',
port: 10061,
proto: 'tcp',
txfee: 10000,
abbr: 'DASH',
serverList: [
'173.212.225.176:50098',
'136.243.45.140:50098'
'electrum1.cipig.net:10061',
'electrum2.cipig.net:10061'
],
},
crown: {
address: '173.212.225.176',
port: 50041,
address: 'electrum1.cipig.net',
port: 10069,
proto: 'tcp',
txfee: 10000,
abbr: 'CRW',
serverList: [
'173.212.225.176:50041',
'136.243.45.140:50041'
'electrum1.cipig.net:10069',
'electrum2.cipig.net:10069'
],
},
btc: {
@ -395,6 +406,8 @@ let electrumServers = {
proto: 'tcp',
abbr: 'BTC',
serverList: [
'electrum1.cipig.net:10000',
'electrum2.cipig.net:10000',
'mooo.not.fyi:50011',
'e-x.not.fyi:50001',
'vps.hsmiths.com:50001',
@ -450,14 +463,14 @@ let electrumServers = {
],
},
argentum: { // !estimatefee
address: '173.212.225.176',
port: 50081,
address: 'electrum1.cipig.net',
port: 10069,
proto: 'tcp',
txfee: 50000,
abbr: 'ARG',
serverList: [
'173.212.225.176:50081',
'136.243.45.140:50081'
'electrum1.cipig.net:10069',
'electrum2.cipig.net:10069'
],
},
chips: { // !estimatefee
@ -472,25 +485,25 @@ let electrumServers = {
],
},
zec: {
address: '173.212.225.176',
port: 50032,
address: 'electrum1.cipig.net',
port: 10058,
proto: 'tcp',
txfee: 10000,
abbr: 'ZEC',
serverList: [
'173.212.225.176:50032',
'136.243.45.140:50032'
'electrum1.cipig.net:10058',
'electrum2.cipig.net:10058'
],
},
hush: {
address: '173.212.225.176',
port: 50013,
address: 'electrum1.cipig.net',
port: 10064,
proto: 'tcp',
txfee: 10000,
abbr: 'HUSH',
serverList: [
'173.212.225.176:50013',
'136.243.45.140:50013'
'electrum1.cipig.net:10064',
'electrum2.cipig.net:10064'
],
},
sng: { // ssl 50002
@ -581,6 +594,188 @@ let electrumServers = {
's2.qtum.info:50001'
],
},
// TODO: figure out fees
btcp: { // multisig?
address: 'electrum.btcprivate.org',
port: 5222,
proto: 'tcp',
txfee: 10000,
abbr: 'BTCP',
serverList: [
'electrum.btcprivate.org:5222',
'electrum2.btcprivate.org:5222'
],
},
emc2: {
address: 'electrum1.cipig.net',
port: 10062,
proto: 'tcp',
txfee: 100000,
abbr: 'EMC2',
serverList: [
'electrum1.cipig.net:10062',
'electrum2.cipig.net:10062'
],
},
bcbc: {
address: 'bsmn0.cleanblockchain.io',
port: 50001,
proto: 'tcp',
txfee: 10000,
abbr: 'BCBC',
serverList: [
'bsmn0.cleanblockchain.io:50001',
'bsmn1.cleanblockchain.io:50001'
],
},
zen: {
txfee: 10000,
abbr: 'ZEN',
},
xzc: {
txfee: 10000,
abbr: 'XZC',
},
game: {
txfee: 100000,
abbr: 'GAME',
},
iop: {
txfee: 10000,
abbr: 'IOP',
},
sys: {
txfee: 10000,
abbr: 'SYS',
},
bta: {
txfee: 100000,
abbr: 'BTA',
},
erc: {
txfee: 10000,
abbr: 'ERC',
},
lbc: {
txfee: 1000,
abbr: 'LBC',
},
bsd: {
txfee: 10000,
abbr: 'BSD',
},
gbx: {
txfee: 10000,
abbr: 'GBX',
},
efl: {
txfee: 100000,
abbr: 'EFL',
},
xwc: {
txfee: 10000,
abbr: 'XWC',
},
vivo: {
txfee: 10000,
abbr: 'VIVO',
},
xvg: {
txfee: 10000,
abbr: 'XVG',
},
xvc: {
txfee: 10000,
abbr: 'XVC',
},
uno: {
txfee: 10000,
abbr: 'UNO',
},
smart: {
txfee: 10000,
abbr: 'SMART',
},
rdd: {
txfee: 10000,
abbr: 'RDD',
},
pivx: {
txfee: 10000,
abbr: 'PIVX',
},
omni: {
txfee: 10000,
abbr: 'OMNI',
},
ok: {
txfee: 10000,
abbr: 'OK',
},
neos: {
txfee: 10000,
abbr: 'NEOS',
},
nav: {
txfee: 10000,
abbr: 'NAV',
},
mnx: {
txfee: 10000,
abbr: 'MNX',
},
lcc: {
txfee: 10000,
abbr: 'LCC',
},
nlg: {
txfee: 10000,
abbr: 'NLG',
},
fjc: {
txfee: 10000,
abbr: 'FJC',
},
flash: {
txfee: 10000,
abbr: 'FLASH',
},
ftc: {
proto: 'tcp',
txfee: 10000,
},
excl: {
txfee: 10000,
abbr: 'EXCL',
},
dmd: {
proto: 'tcp',
txfee: 10000,
},
crave: {
txfee: 10000,
abbr: 'CRAVE',
},
club: {
txfee: 10000,
abbr: 'CLUB',
},
clam: {
txfee: 10000,
abbr: 'CLAM',
},
bca: {
txfee: 10000,
abbr: 'BCA',
},
aur: {
txfee: 10000,
abbr: 'AUR',
},
acc: {
txfee: 10000,
abbr: 'ACC',
},
// insight
aby: {
address: 'http://explorer.artbyte.me/api/',
@ -620,7 +815,7 @@ electrumServers.crw = electrumServers.crown;
electrumServers.fair = electrumServers.faircoin;
electrumServers.arg = electrumServers.argentum;
electrumServers.ltc = electrumServers.litecoin;
electrumServers.mona = electrumServers.litecoin;
electrumServers.mona = electrumServers.monacoin;
electrumServers.nmc = electrumServers.namecoin;
electrumServers.vtc = electrumServers.vertcoin;
electrumServers.via = electrumServers.viacoin;

23
routes/electrumjs/electrumjs.networks.js

@ -92,6 +92,7 @@ networks.xzc = {
scriptHash: 0x07,
wif: 0x52 + 128,
dustThreshold: 1000, // https://github.com/zcoinofficial/zcoin/blob/f755f95a036eedfef7c96bcfb6769cb79278939f/src/main.h#L59
isZcash: true,
};
// https://raw.githubusercontent.com/jl777/komodo/beta/src/chainparams.cpp
@ -105,6 +106,7 @@ networks.komodo = {
scriptHash: 0x55,
wif: 0xbc,
dustThreshold: 1000,
isZcash: true,
};
networks.viacoin = {
@ -262,6 +264,7 @@ networks.zcash = {
scriptHash: 0x1cbd,
wif: 0x80,
dustThreshold: 1000,
isZcash: true,
};
networks.hush = {
@ -274,6 +277,7 @@ networks.hush = {
scriptHash: 0x1cbd,
wif: 0x80,
dustThreshold: 1000,
isZcash: true,
};
networks.zcl = {
@ -286,6 +290,7 @@ networks.zcl = {
scriptHash: 0x1cbd,
wif: 0x80,
dustThreshold: 1000,
isZcash: true,
};
networks.sng = {
@ -298,6 +303,7 @@ networks.sng = {
scriptHash: 0x1c2D,
wif: 0x80,
dustThreshold: 1000,
isZcash: true,
};
networks.xmy = {
@ -358,6 +364,7 @@ networks.btcz = {
scriptHash: 0x1cbd,
wif: 0x80,
dustThreshold: 1000,
isZcash: true,
};
networks.grs = { // fails to gen a proper addr
@ -406,6 +413,7 @@ networks.vot = {
scriptHash: 0x1cbd,
wif: 0x80,
dustThreshold: 1000,
isZcash: true,
};
networks.iop = {
@ -455,6 +463,7 @@ networks.zen = { // new address type
scriptHash: 0x2086,
wif: 0x80,
dustThreshold: 1000,
isZcash: true,
};
networks.sys = { // zec based
@ -467,6 +476,7 @@ networks.sys = { // zec based
scriptHash: 0x5,
wif: 0x80,
dustThreshold: 1000,
isZcash: true,
};
networks.emc2 = {
@ -632,6 +642,7 @@ networks.smart = { // wrong address generated
scriptHash: 0x12,
wif: 0xBF,
dustThreshold: 1000,
isZcash: true,
};
// https://github.com/reddcoin-project/reddcoin/blob/master/src/chainparams.cpp#L79
@ -891,6 +902,18 @@ networks.acc = {
dustThreshold: 1000,
};
networks.bcbc = {
messagePrefix: '\x19Bitcoin CBC Signed Message:\n',
bip32: {
public: 0x0488b21e,
private: 0x0488ade4,
},
pubKeyHash: 0x0,
scriptHash: 0x5,
wif: 0x80,
dustThreshold: 1000,
};
networks.btc = networks.bitcoin;
networks.crw = networks.crown;
networks.dgb = networks.digibyte;

61
routes/electrumjs/electrumjs.txdecoder-2bytes.js

@ -1,7 +1,8 @@
/*
MIT License
Copyright (c) 2017 Yuki Akiyama, SuperNET
Copyright (c) 2017 Yuki Akiyama
Copyright (c) 2017 - 2018 SuperNET
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@ -23,6 +24,26 @@ SOFTWARE.
*/
var bitcoin = require('bitcoinjs-lib-zcash');
// zcash fallback
const Buffer = require('safe-buffer').Buffer;
const {
readSlice,
readInt32,
readUInt32,
} = require('tx-decoder/src/buffer-utils');
const {
compose,
addProp,
} = require('tx-decoder/src/compose');
const {
readInputs,
readInput,
readOutput,
} = require('tx-decoder/src/tx-decoder');
const crypto = require('crypto');
const _sha256 = (data) => {
return crypto.createHash('sha256').update(data).digest();
};
var decodeFormat = function(tx) {
var result = {
@ -39,7 +60,7 @@ var decodeInput = function(tx) {
tx.ins.forEach(function(input, n) {
var vin = {
txid: input.hash.reverse().toString('hex'),
txid: !input.hash.reverse ? input.hash : input.hash.reverse().toString('hex'),
n: input.index,
script: bitcoin.script.toASM(input.script),
sequence: input.sequence,
@ -102,7 +123,41 @@ var TxDecoder = module.exports = function(rawtx, network) {
outputs: decodeOutput(_tx, network),
};
} catch (e) {
return false;
if (network.isZcash) {
console.log('z tx decode fallback');
const buffer = Buffer.from(rawtx, 'hex');
const decodeTx = buffer => (
compose([
addProp('version', readInt32), // 4 bytes
addProp('ins', readInputs(readInput)), // 1-9 bytes (VarInt), Input counter; Variable, Inputs
addProp('outs', readInputs(readOutput)), // 1-9 bytes (VarInt), Output counter; Variable, Outputs
addProp('locktime', readUInt32) // 4 bytes
])({}, buffer)
);
const readHash = buffer => {
const [res, bufferLeft] = readSlice(32)(_sha256(_sha256(buffer)));
const hash = Buffer.from(res, 'hex').reverse().toString('hex');
return [hash, bufferLeft];
};
let decodedtx = decodeTx(buffer);
decodedtx[0].getId = () => {
return readHash(buffer)[0];
};
return {
tx: decodedtx[0],
network: network,
format: decodeFormat(decodedtx[0]),
inputs: !decodedtx[0].ins.length ? [{ txid: '0000000000000000000000000000000000000000000000000000000000000000' }] : decodeInput(decodedtx[0]),
outputs: decodeOutput(decodedtx[0], network),
};
} else {
return false;
}
}
}

61
routes/electrumjs/electrumjs.txdecoder.js

@ -1,7 +1,8 @@
/*
MIT License
Copyright (c) 2017 Yuki Akiyama, SuperNET
Copyright (c) 2017 Yuki Akiyama
Copyright (c) 2017 - 2018 SuperNET
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@ -23,6 +24,26 @@ SOFTWARE.
*/
var bitcoin = require('bitcoinjs-lib');
// zcash fallback
const Buffer = require('safe-buffer').Buffer;
const {
readSlice,
readInt32,
readUInt32,
} = require('tx-decoder/src/buffer-utils');
const {
compose,
addProp,
} = require('tx-decoder/src/compose');
const {
readInputs,
readInput,
readOutput,
} = require('tx-decoder/src/tx-decoder');
const crypto = require('crypto');
const _sha256 = (data) => {
return crypto.createHash('sha256').update(data).digest();
};
var decodeFormat = function(tx) {
var result = {
@ -39,7 +60,7 @@ var decodeInput = function(tx) {
tx.ins.forEach(function(input, n) {
var vin = {
txid: input.hash.reverse().toString('hex'),
txid: !input.hash.reverse ? input.hash : input.hash.reverse().toString('hex'),
n: input.index,
script: bitcoin.script.toASM(input.script),
sequence: input.sequence,
@ -102,7 +123,41 @@ var TxDecoder = module.exports = function(rawtx, network) {
outputs: decodeOutput(_tx, network),
};
} catch (e) {
return false;
if (network.isZcash) {
console.log('z tx decode fallback');
const buffer = Buffer.from(rawtx, 'hex');
const decodeTx = buffer => (
compose([
addProp('version', readInt32), // 4 bytes
addProp('ins', readInputs(readInput)), // 1-9 bytes (VarInt), Input counter; Variable, Inputs
addProp('outs', readInputs(readOutput)), // 1-9 bytes (VarInt), Output counter; Variable, Outputs
addProp('locktime', readUInt32) // 4 bytes
])({}, buffer)
);
const readHash = buffer => {
const [res, bufferLeft] = readSlice(32)(_sha256(_sha256(buffer)))
const hash = Buffer.from(res, 'hex').reverse().toString('hex')
return [hash, bufferLeft]
};
let decodedtx = decodeTx(buffer);
decodedtx[0].getId = () => {
return readHash(buffer)[0];
};
return {
tx: decodedtx[0],
network: network,
format: decodeFormat(decodedtx[0]),
inputs: !decodedtx[0].ins.length ? [{ txid: '0000000000000000000000000000000000000000000000000000000000000000' }] : decodeInput(decodedtx[0]),
outputs: decodeOutput(decodedtx[0], network),
};
} else {
return false;
}
}
}

4
routes/shepherd.js

@ -37,6 +37,9 @@ shepherd.rpcConf = {};
shepherd.appRuntimeLog = [];
shepherd.appRuntimeSPVLog = [];
shepherd.lockDownAddCoin = false;
shepherd.isWatchOnly = false;
shepherd.staking = {};
// dex cache
shepherd.mmupass = null;
@ -60,7 +63,6 @@ shepherd.electrumCoins = {
auth: false,
};
shepherd.electrumKeys = {};
shepherd.electrumCache = {};
shepherd.electrumJSCore = require('./electrumjs/electrumjs.core.js');

209
routes/shepherd/addCoinShortcuts.js

@ -21,19 +21,30 @@ module.exports = (shepherd) => {
}
shepherd.startKMDNative = (selection, isManual) => {
if (isManual) {
shepherd.kmdMainPassiveMode = true;
}
if (selection === 'KMD') {
const herdData = {
'ac_name': 'komodod',
'ac_options': [
'-daemon=0',
'-addnode=78.47.196.146',
],
};
let herdData;
const acHerdData = {
REVS: {
name: 'REVS',
seedNode: '78.47.196.146',
supply: 1300000,
},
JUMBLR: {
name: 'JUMBLR',
seedNode: '78.47.196.146',
supply: 999999,
},
MNZ: {
name: 'MNZ',
seedNode: '78.47.196.146',
supply: 257142858,
},
BTCH: {
name: 'BTCH',
seedNode: '78.47.196.146',
supply: 20998641,
},
};
const httpRequest = () => {
const options = {
url: `http://127.0.0.1:${shepherd.appConfig.agamaPort}/shepherd/herd`,
method: 'POST',
@ -48,157 +59,49 @@ module.exports = (shepherd) => {
};
request(options, (error, response, body) => {
if (response &&
response.statusCode &&
response.statusCode === 200) {
//resolve(body);
} else {
//resolve(body);
}
// resolve(body);
});
} else if (selection === 'REVS') {
const herdData = {
'ac_name': 'REVS',
'ac_options': [
'-daemon=0',
'-server',
`-ac_name=REVS`,
'-addnode=78.47.196.146',
'-ac_supply=1300000'
]
};
};
const options = {
url: `http://127.0.0.1:${shepherd.appConfig.agamaPort}/shepherd/herd`,
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
herd: 'komodod',
options: herdData,
token: shepherd.appSessionHash,
}),
};
request(options, (error, response, body) => {
if (response &&
response.statusCode &&
response.statusCode === 200) {
//resolve(body);
} else {
//resolve(body);
}
});
} else if (selection === 'JUMRLR') {
const herdData = {
'ac_name': 'JUMRLR',
'ac_options': [
'-daemon=0',
'-server',
`-ac_name=JUMRLR`,
'-addnode=78.47.196.146',
'-ac_supply=999999'
]
};
const options = {
url: `http://127.0.0.1:${shepherd.appConfig.agamaPort}/shepherd/herd`,
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
herd: 'komodod',
options: herdData,
token: shepherd.appSessionHash,
}),
};
if (isManual) {
shepherd.kmdMainPassiveMode = true;
}
request(options, (error, response, body) => {
if (response &&
response.statusCode &&
response.statusCode === 200) {
//resolve(body);
} else {
//resolve(body);
}
});
} else if (selection === 'MNZ') {
const herdData = {
'ac_name': 'MNZ',
if (selection === 'KMD') {
herdData = {
'ac_name': 'komodod',
'ac_options': [
'-daemon=0',
'-server',
`-ac_name=MNZ`,
'-addnode=78.47.196.146',
'-ac_supply=257142858'
]
};
const options = {
url: `http://127.0.0.1:${shepherd.appConfig.agamaPort}/shepherd/herd`,
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
herd: 'komodod',
options: herdData,
token: shepherd.appSessionHash,
}),
],
};
request(options, (error, response, body) => {
if (response &&
response.statusCode &&
response.statusCode === 200) {
//resolve(body);
} else {
//resolve(body);
}
});
} else if (selection === 'BTCH') {
const herdData = {
'ac_name': 'BTCH',
httpRequest();
} else if (
selection === 'REVS' ||
selection === 'JUMRLR' ||
selection === 'MNZ' ||
selection === 'BTCH'
) {
herdData = {
'ac_name': acHerdData[selection].name,
'ac_options': [
'-daemon=0',
'-server',
`-ac_name=BTCH`,
'-addnode=78.47.196.146',
'-ac_supply=20998641'
]
};
const options = {
url: `http://127.0.0.1:${shepherd.appConfig.agamaPort}/shepherd/herd`,
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
herd: 'komodod',
options: herdData,
token: shepherd.appSessionHash,
}),
`-ac_name=${acHerdData[selection].name}`,
`-addnode=${acHerdData[selection].seedNode}`,
`-ac_supply=${acHerdData[selection].supply}`,
],
};
request(options, (error, response, body) => {
if (response &&
response.statusCode &&
response.statusCode === 200) {
//resolve(body);
} else {
//resolve(body);
}
});
httpRequest();
} else {
const herdData = [{
'ac_name': 'komodod',
'ac_options': [
'-daemon=0',
'-addnode=78.47.196.146',
]
],
}, {
'ac_name': 'REVS',
'ac_options': [
@ -206,8 +109,8 @@ module.exports = (shepherd) => {
'-server',
`-ac_name=REVS`,
'-addnode=78.47.196.146',
'-ac_supply=1300000'
]
'-ac_supply=1300000',
],
}, {
'ac_name': 'JUMBLR',
'ac_options': [
@ -215,8 +118,8 @@ module.exports = (shepherd) => {
'-server',
`-ac_name=JUMBLR`,
'-addnode=78.47.196.146',
'-ac_supply=999999'
]
'-ac_supply=999999',
],
}];
for (let i = 0; i < herdData.length; i++) {
@ -235,13 +138,7 @@ module.exports = (shepherd) => {
};
request(options, (error, response, body) => {
if (response &&
response.statusCode &&
response.statusCode === 200) {
//resolve(body);
} else {
//resolve(body);
}
// resolve(body);
});
}, 100);
}

42
routes/shepherd/auth.js

@ -14,12 +14,21 @@ module.exports = (shepherd) => {
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 &&
!shepherd.electrumCoins.auth
) {
_status = true;
}
} else if (Object.keys(shepherd.electrumCoins).length > 1 && shepherd.electrumCoins.auth) {
} 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) {
} else if (
Object.keys(shepherd.electrumCoins).length === 1 &&
!Object.keys(shepherd.coindInstanceRegistry).length
) {
_status = true;
}
@ -50,5 +59,32 @@ module.exports = (shepherd) => {
return passwdStrength(str) < 29 ? false : true;
};
shepherd.isWatchOnly = () => {
return shepherd.isWatchOnly;
};
shepherd.setPubkey = (seed, coin) => {
const {
pub,
pubHex,
} = shepherd.seedToWif(seed, 'komodo', true);
shepherd.staking[coin] = {
pub,
pubHex,
};
shepherd.log(`pub key for ${coin} is set`);
shepherd.log(shepherd.staking[coin]);
};
shepherd.getPubkeys = () => {
return shepherd.staking;
};
shepherd.removePubkey = (coin) => {
delete shepherd.staking[coin];
};
return shepherd;
};

2
routes/shepherd/coindWalletKeys.js

@ -13,7 +13,7 @@ module.exports = (shepherd) => {
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`;
let _walletDatLocation = chain === 'komodo' || chain === 'KMD' || chain === 'null' ? `${shepherd.komodoDir}/wallet.dat` : `${shepherd.komodoDir}/${chain}/wallet.dat`;
_walletDatLocation = chain === 'CHIPS' ? `${shepherd.chipsDir}/wallet.dat` : _walletDatLocation;
try {

13
routes/shepherd/daemonControl.js

@ -187,12 +187,14 @@ module.exports = (shepherd) => {
change: '-pubkey=',
datadir: '-datadir=',
rescan: '-rescan',
gen: '-gen',
};
let _customParam = '';
if (data.ac_custom_param === 'silent' ||
data.ac_custom_param === 'reindex' ||
data.ac_custom_param === 'rescan') {
data.ac_custom_param === 'rescan' ||
data.ac_custom_param === 'gen') {
_customParam = ` ${_customParamDict[data.ac_custom_param]}`;
} else if (data.ac_custom_param === 'change' && data.ac_custom_param_value) {
_customParam = ` ${_customParamDict[data.ac_custom_param]}${data.ac_custom_param_value}`;
@ -359,14 +361,14 @@ module.exports = (shepherd) => {
shepherd.log(`daemon param ${data.ac_custom_param}`);
shepherd.coindInstanceRegistry['CHIPS'] = true;
shepherd.coindInstanceRegistry.CHIPS = true;
let _arg = `${_customParam}`;
_arg = _arg.trim().split(' ');
if (_arg &&
_arg.length > 1) {
execFile(`${shepherd.chipsBin}`, _arg, {
maxBuffer: 1024 * 1000000 // 1000 mb
maxBuffer: 1024 * 1000000, // 1000 mb
}, (error, stdout, stderr) => {
shepherd.writeLog(`stdout: ${stdout}`);
shepherd.writeLog(`stderr: ${stderr}`);
@ -464,7 +466,7 @@ module.exports = (shepherd) => {
let _arg = `${data.ac_options.join(' ')}`;
_arg = _arg.trim().split(' ');
execFile(`${coindBin}`, _arg, {
maxBuffer: 1024 * 1000000 // 1000 mb
maxBuffer: 1024 * 1000000, // 1000 mb
}, (error, stdout, stderr) => {
shepherd.writeLog(`stdout: ${stdout}`);
shepherd.writeLog(`stderr: ${stderr}`);
@ -651,7 +653,6 @@ module.exports = (shepherd) => {
shepherd.writeLog(`append daemon conf err: ${err}`);
shepherd.log(`append daemon conf err: ${err}`);
}
// throw err;
shepherd.log('rpcpassword: ADDED');
shepherd.writeLog('rpcpassword: ADDED');
});
@ -678,7 +679,6 @@ module.exports = (shepherd) => {
shepherd.writeLog(`append daemon conf err: ${err}`);
shepherd.log(`append daemon conf err: ${err}`);
}
// throw err;
shepherd.log('rpcport: ADDED');
shepherd.writeLog('rpcport: ADDED');
});
@ -754,7 +754,6 @@ module.exports = (shepherd) => {
shepherd.writeLog(`append daemon conf err: ${err}`);
shepherd.log(`append daemon conf err: ${err}`);
}
// throw err;
shepherd.log('addnode: ADDED');
shepherd.writeLog('addnode: ADDED');
});

8
routes/shepherd/dashboardUpdate.js

@ -277,13 +277,7 @@ module.exports = (shepherd) => {
};
request(options, (error, response, body) => {
if (response &&
response.statusCode &&
response.statusCode === 200) {
resolve(body);
} else {
resolve(body);
}
resolve(body);
});
});
}

96
routes/shepherd/debugLog.js

@ -1,6 +1,7 @@
const path = require('path');
const _fs = require('graceful-fs');
const Promise = require('bluebird');
const os = require('os');
module.exports = (shepherd) => {
/*
@ -13,18 +14,19 @@ module.exports = (shepherd) => {
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() === 'win32') {
shepherd.komodoDir = shepherd.appConfig.dataDir.length ? shepherd.appConfig.dataDir : `${process.env.APPDATA}/Komodo`;
shepherd.komodoDir = path.normalize(shepherd.komodoDir);
const _platform = os.platform();
switch (_platform) {
case 'darwin':
shepherd.komodoDir = shepherd.appConfig.dataDir.length ? shepherd.appConfig.dataDir : `${process.env.HOME}/Library/Application Support/Komodo`;
break;
case 'linux':
shepherd.komodoDir = shepherd.appConfig.dataDir.length ? shepherd.appConfig.dataDir : `${process.env.HOME}/.komodo`;
break;
case 'win32':
shepherd.komodoDir = shepherd.appConfig.dataDir.length ? shepherd.appConfig.dataDir : `${process.env.APPDATA}/Komodo`;
shepherd.komodoDir = path.normalize(shepherd.komodoDir);
break;
}
if (_herd === 'komodo') {
@ -97,44 +99,42 @@ module.exports = (shepherd) => {
});
shepherd.readDebugLog = (fileLocation, lastNLines) => {
return new Promise(
(resolve, reject) => {
if (lastNLines) {
try {
_fs.access(fileLocation, shepherd.fs.constants.R_OK, (err) => {
if (err) {
shepherd.log(`error reading ${fileLocation}`);
shepherd.writeLog(`error reading ${fileLocation}`);
reject(`readDebugLog error: ${err}`);
} else {
shepherd.log(`reading ${fileLocation}`);
_fs.readFile(fileLocation, 'utf-8', (err, data) => {
if (err) {
shepherd.writeLog(`readDebugLog err: ${err}`);
shepherd.log(`readDebugLog err: ${err}`);
}
const lines = data.trim().split('\n');
let lastLine;
if (lastNLines === 'all') {
lastLine = data.trim();
} else {
lastLine = lines.slice(lines.length - lastNLines, lines.length).join('\n');
}
resolve(lastLine);
});
}
});
} catch (e) {
reject(`readDebugLog error: ${e}`);
}
} else {
reject('readDebugLog error: lastNLines param is not provided!');
return new Promise((resolve, reject) => {
if (lastNLines) {
try {
_fs.access(fileLocation, shepherd.fs.constants.R_OK, (err) => {
if (err) {
shepherd.log(`error reading ${fileLocation}`);
shepherd.writeLog(`error reading ${fileLocation}`);
reject(`readDebugLog error: ${err}`);
} else {
shepherd.log(`reading ${fileLocation}`);
_fs.readFile(fileLocation, 'utf-8', (err, data) => {
if (err) {
shepherd.writeLog(`readDebugLog err: ${err}`);
shepherd.log(`readDebugLog err: ${err}`);
}
const lines = data.trim().split('\n');
let lastLine;
if (lastNLines === 'all') {
lastLine = data.trim();
} else {
lastLine = lines.slice(lines.length - lastNLines, lines.length).join('\n');
}
resolve(lastLine);
});
}
});
} catch (e) {
reject(`readDebugLog error: ${e}`);
}
} else {
reject('readDebugLog error: lastNLines param is not provided!');
}
);
});
};
return shepherd;

19
routes/shepherd/elections.js

@ -5,12 +5,12 @@ const Promise = require('bluebird');
module.exports = (shepherd) => {
shepherd.elections = {};
shepherd.hex2str = (hexx) => {
const hex = hexx.toString(); // force conversion
shepherd.hex2str = (hex) => {
const _hex = hex.toString(); // force conversion
let str = '';
for (let i = 0; i < hex.length; i += 2) {
str += String.fromCharCode(parseInt(hex.substr(i, 2), 16));
for (let i = 0; i < _hex.length; i += 2) {
str += String.fromCharCode(parseInt(_hex.substr(i, 2), 16));
}
return str;
@ -167,7 +167,11 @@ module.exports = (shepherd) => {
shepherd.get('/elections/listtransactions', (req, res, next) => {
if (shepherd.checkToken(req.query.token)) {
const network = req.query.network || shepherd.findNetworkObj(req.query.coin);
const ecl = new shepherd.electrumJSCore(shepherd.electrumServers[network].port, shepherd.electrumServers[network].address, shepherd.electrumServers[network].proto); // tcp or tls
const ecl = new shepherd.electrumJSCore(
shepherd.electrumServers[network].port,
shepherd.electrumServers[network].address,
shepherd.electrumServers[network].proto
); // tcp or tls
const type = req.query.type;
const _address = req.query.address;
@ -299,7 +303,10 @@ module.exports = (shepherd) => {
.then((res) => {
if (decodedTx.outputs[i].scriptPubKey.addresses[0] === _address) {
_candidate.amount = decodedTx.outputs[i].value;
} else if (decodedTx.outputs[i].scriptPubKey.addresses[0] !== _address && decodedTx.outputs[i].scriptPubKey.asm.indexOf('OP_RETURN') === -1) {
} else if (
decodedTx.outputs[i].scriptPubKey.addresses[0] !== _address &&
decodedTx.outputs[i].scriptPubKey.asm.indexOf('OP_RETURN') === -1
) {
_candidate.address = decodedTx.outputs[i].scriptPubKey.addresses[0];
_candidate.region = _region;
_candidate.timestamp = blockInfo.timestamp;

15
routes/shepherd/electrum/auth.js

@ -14,14 +14,17 @@ module.exports = (shepherd) => {
let keys;
let isWif = false;
if (req.body.seed.match('^[a-zA-Z0-9]{34}$') &&
if (_seed.match('^[a-zA-Z0-9]{34}$') &&
shepherd.appConfig.experimentalFeatures) {
shepherd.log('watchonly pub addr');
shepherd.electrumKeys[_abbr] = {
priv: req.body.seed,
pub: req.body.seed,
priv: _seed,
pub: _seed,
};
shepherd.isWatchOnly = true;
} else {
shepherd.isWatchOnly = false;
try {
bs58check.decode(_seed);
isWif = true;
@ -39,7 +42,11 @@ module.exports = (shepherd) => {
break;
}
} else {
keys = shepherd.seedToWif(_seed, shepherd.findNetworkObj(_abbr), req.body.iguana);
keys = shepherd.seedToWif(
_seed,
shepherd.findNetworkObj(_abbr),
req.body.iguana,
);
}
shepherd.electrumKeys[_abbr] = {

7
routes/shepherd/electrum/balance.js

@ -47,7 +47,12 @@ module.exports = (shepherd) => {
// decode tx
const _network = shepherd.getNetworkData(network);
const decodedTx = shepherd.electrumJSTxDecoder(_rawtxJSON, network, _network, shepherd.electrumServers[network].proto === 'insight');
const decodedTx = shepherd.electrumJSTxDecoder(
_rawtxJSON,
network,
_network,
shepherd.electrumServers[network].proto === 'insight'
);
if (decodedTx &&
decodedTx.format &&

12
routes/shepherd/electrum/block.js

@ -24,7 +24,11 @@ module.exports = (shepherd) => {
shepherd.electrumGetBlockInfo = (height, network) => {
return new Promise((resolve, reject) => {
const ecl = new shepherd.electrumJSCore(shepherd.electrumServers[network].port, shepherd.electrumServers[network].address, shepherd.electrumServers[network].proto); // tcp or tls
const ecl = new shepherd.electrumJSCore(
shepherd.electrumServers[network].port,
shepherd.electrumServers[network].address,
shepherd.electrumServers[network].proto
); // tcp or tls
ecl.connect();
ecl.blockchainBlockGetHeader(height)
@ -61,7 +65,11 @@ module.exports = (shepherd) => {
shepherd.electrumGetCurrentBlock = (network) => {
return new Promise((resolve, reject) => {
const ecl = new shepherd.electrumJSCore(shepherd.electrumServers[network].port, shepherd.electrumServers[network].address, shepherd.electrumServers[network].proto); // tcp or tls
const ecl = new shepherd.electrumJSCore(
shepherd.electrumServers[network].port,
shepherd.electrumServers[network].address,
shepherd.electrumServers[network].proto
); // tcp or tls
ecl.connect();
ecl.blockchainNumblocksSubscribe()

13
routes/shepherd/electrum/btcFees.js

@ -35,7 +35,11 @@ module.exports = (shepherd) => {
if (shepherd.checkToken(req.query.token)) {
if (checkTimestamp(btcFees.lastUpdated) > BTC_FEES_MIN_ELAPSED_TIME) {
const _randomServer = shepherd.electrumServers.btc.serverList[getRandomIntInclusive(0, shepherd.electrumServers.btc.serverList.length - 1)].split(':');
const ecl = new shepherd.electrumJSCore(_randomServer[1], _randomServer[0], 'tcp');
const ecl = new shepherd.electrumJSCore(
_randomServer[1],
_randomServer[0],
'tcp'
);
let _btcFeeEstimates = [];
console.log(`btc fees server ${_randomServer.join(':')}`);
@ -56,12 +60,7 @@ module.exports = (shepherd) => {
.then(result => {
ecl.close();
if (result &&
result.length) {
btcFees.electrum = _btcFeeEstimates;
} else {
btcFees.electrum = 'error';
}
btcFees.electrum = result && result.length ? _btcFeeEstimates : 'error';
let options = {
url: `https://bitcoinfees.earn.com/api/v1/fees/recommended`,

4
routes/shepherd/electrum/coins.js

@ -15,7 +15,7 @@ module.exports = (shepherd) => {
max = Math.floor(max);
return Math.floor(Math.random() * (max - min + 1)) + min; // the maximum is inclusive and the minimum is inclusive
}
};
let randomServer;
// pick a random server to communicate with
@ -43,7 +43,7 @@ module.exports = (shepherd) => {
port: randomServer ? randomServer.port : shepherd.electrumServers[key].port,
},
serverList: shepherd.electrumServers[key].serverList ? shepherd.electrumServers[key].serverList : 'none',
txfee: 'calculated' /*shepherd.electrumServers[key].txfee*/,
txfee: key === 'btc' ? 'calculated' : shepherd.electrumServers[key].txfee,
};
shepherd.log(`default ${coin} electrum server ${shepherd.electrumServers[key].address + ':' + shepherd.electrumServers[key].port}`, true);

54
routes/shepherd/electrum/createtx-multi.js

@ -15,16 +15,20 @@ module.exports = (shepherd) => {
// TODO: 1) unconf output(s) error message
// 2) check targets integrity
const network = req.body.network || shepherd.findNetworkObj(req.body.coin);
const ecl = new shepherd.electrumJSCore(shepherd.electrumServers[network].port, shepherd.electrumServers[network].address, shepherd.electrumServers[network].proto); // tcp or tls
const ecl = new shepherd.electrumJSCore(
shepherd.electrumServers[network].port,
shepherd.electrumServers[network].address,
shepherd.electrumServers[network].proto
); // tcp or tls
const initTargets = JSON.parse(JSON.stringify(req.body.targets));
let targets = req.body.targets;
const changeAddress = req.body.change;
const push = req.body.push;
const opreturn = req.body.opreturn;
const btcFee = req.body.btcfee ? Number(req.body.btcfee) : null;
let fee = shepherd.electrumServers[network].txfee;
let wif = req.body.wif;
let targets = req.body.targets;
if (req.body.gui) {
wif = shepherd.electrumKeys[req.body.coin].priv;
}
@ -40,7 +44,13 @@ module.exports = (shepherd) => {
shepherd.log('electrum createrawtx =>', true);
ecl.connect();
shepherd.listunspent(ecl, changeAddress, network, true, req.body.verify === 'true' ? true : null)
shepherd.listunspent(
ecl,
changeAddress,
network,
true,
req.body.verify === 'true' ? true : null
)
.then((utxoList) => {
ecl.close();
@ -96,7 +106,11 @@ module.exports = (shepherd) => {
// default coin selection algo blackjack with fallback to accumulative
// make a first run, calc approx tx fee
// if ins and outs are empty reduce max spend by txfee
const firstRun = coinSelect(utxoListFormatted, targets, btcFee ? btcFee : 0);
const firstRun = coinSelect(
utxoListFormatted,
targets,
btcFee ? btcFee : 0
);
let inputs = firstRun.inputs;
let outputs = firstRun.outputs;
@ -119,7 +133,11 @@ module.exports = (shepherd) => {
shepherd.log('coinselect adjusted targets =>', true);
shepherd.log(targets, true);
const secondRun = coinSelect(utxoListFormatted, targets, 0);
const secondRun = coinSelect(
utxoListFormatted,
targets,
0
);
inputs = secondRun.inputs;
outputs = secondRun.outputs;
fee = fee ? fee : secondRun.fee;
@ -333,7 +351,11 @@ module.exports = (shepherd) => {
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
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)
@ -451,7 +473,11 @@ module.exports = (shepherd) => {
for (let i = 0; i < sendTo.length; i++) {
if (shepherd.isPos(network)) {
tx.addOutput(sendTo[i].address, Number(sendTo[i].value), shepherd.getNetworkData(network));
tx.addOutput(
sendTo[i].address,
Number(sendTo[i].value),
shepherd.getNetworkData(network)
);
} else {
tx.addOutput(sendTo[i].address, Number(sendTo[i].value));
}
@ -459,7 +485,11 @@ module.exports = (shepherd) => {
if (changeValue > 0) {
if (shepherd.isPos(network)) {
tx.addOutput(changeAddress, Number(changeValue), shepherd.getNetworkData(network));
tx.addOutput(
changeAddress,
Number(changeValue),
shepherd.getNetworkData(network)
);
} else {
tx.addOutput(changeAddress, Number(changeValue));
}
@ -492,7 +522,11 @@ module.exports = (shepherd) => {
for (let i = 0; i < utxo.length; i++) {
if (shepherd.isPos(network)) {
tx.sign(shepherd.getNetworkData(network), i, key);
tx.sign(
shepherd.getNetworkData(network),
i,
key
);
} else {
tx.sign(i, key);
}

18
routes/shepherd/electrum/createtx-split.js

@ -35,7 +35,11 @@ module.exports = (shepherd) => {
for (let i = 0; i < targets.length; i++) {
if (shepherd.isPos(network)) {
tx.addOutput(outputAddress, Number(targets[i]), shepherd.getNetworkData(network));
tx.addOutput(
outputAddress,
Number(targets[i]),
shepherd.getNetworkData(network)
);
} else {
tx.addOutput(outputAddress, Number(targets[i]));
}
@ -43,7 +47,11 @@ module.exports = (shepherd) => {
if (Number(change) > 0) {
if (shepherd.isPos(network)) {
tx.addOutput(changeAddress, Number(change), shepherd.getNetworkData(network));
tx.addOutput(
changeAddress,
Number(change),
shepherd.getNetworkData(network)
);
} else {
shepherd.log(`change ${change}`, true);
tx.addOutput(changeAddress, Number(change));
@ -59,7 +67,11 @@ module.exports = (shepherd) => {
for (let i = 0; i < utxo.length; i++) {
if (shepherd.isPos(network)) {
tx.sign(shepherd.getNetworkData(network), i, key);
tx.sign(
shepherd.getNetworkData(network),
i,
key
);
} else {
tx.sign(i, key);
}

71
routes/shepherd/electrum/createtx.js

@ -78,14 +78,22 @@ module.exports = (shepherd) => {
}
if (shepherd.isPos(network)) {
tx.addOutput(sendTo, Number(spendValue), shepherd.getNetworkData(network));
tx.addOutput(
sendTo,
Number(spendValue),
shepherd.getNetworkData(network)
);
} else {
tx.addOutput(sendTo, Number(spendValue));
}
if (changeValue > 0) {
if (shepherd.isPos(network)) {
tx.addOutput(changeAddress, Number(changeValue), shepherd.getNetworkData(network));
tx.addOutput(
changeAddress,
Number(changeValue),
shepherd.getNetworkData(network)
);
} else {
tx.addOutput(changeAddress, Number(changeValue));
}
@ -114,7 +122,11 @@ module.exports = (shepherd) => {
for (let i = 0; i < utxo.length; i++) {
if (shepherd.isPos(network)) {
tx.sign(shepherd.getNetworkData(network), i, key);
tx.sign(
shepherd.getNetworkData(network),
i,
key
);
} else {
tx.sign(i, key);
}
@ -144,7 +156,12 @@ module.exports = (shepherd) => {
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);
tx.addInput(
utxo[i].txid,
utxo[i].vout,
bitcoinJSForks.Transaction.DEFAULT_SEQUENCE,
spk
);
}
tx.addOutput(sendTo, Number(spendValue));
@ -171,7 +188,13 @@ module.exports = (shepherd) => {
const hashType = bitcoinJSForks.Transaction.SIGHASH_ALL | bitcoinJSForks.Transaction.SIGHASH_BITCOINCASHBIP143;
for (let i = 0; i < utxo.length; i++) {
tx.sign(i, keyPair, null, hashType, utxo[i].value);
tx.sign(
i,
keyPair,
null,
hashType,
utxo[i].value
);
}
const rawtx = tx.build().toHex();
@ -200,7 +223,11 @@ module.exports = (shepherd) => {
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 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;
@ -225,7 +252,13 @@ module.exports = (shepherd) => {
shepherd.log('electrum createrawtx =>', true);
ecl.connect();
shepherd.listunspent(ecl, changeAddress, network, true, req.query.verify === 'true' ? true : null)
shepherd.listunspent(
ecl,
changeAddress,
network,
true,
req.query.verify === 'true' ? true : null
)
.then((utxoList) => {
ecl.close();
@ -281,7 +314,11 @@ module.exports = (shepherd) => {
// default coin selection algo blackjack with fallback to accumulative
// make a first run, calc approx tx fee
// if ins and outs are empty reduce max spend by txfee
const firstRun = coinSelect(utxoListFormatted, targets, btcFee ? btcFee : 0);
const firstRun = coinSelect(
utxoListFormatted,
targets,
btcFee ? btcFee : 0
);
let inputs = firstRun.inputs;
let outputs = firstRun.outputs;
@ -304,7 +341,11 @@ module.exports = (shepherd) => {
shepherd.log('coinselect adjusted targets =>', true);
shepherd.log(targets, true);
const secondRun = coinSelect(utxoListFormatted, targets, 0);
const secondRun = coinSelect(
utxoListFormatted,
targets,
0
);
inputs = secondRun.inputs;
outputs = secondRun.outputs;
fee = fee ? fee : secondRun.fee;
@ -493,7 +534,11 @@ module.exports = (shepherd) => {
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
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)
@ -591,7 +636,11 @@ module.exports = (shepherd) => {
if (shepherd.checkToken(req.body.token)) {
const rawtx = req.body.rawtx;
const _network = req.body.network;
const ecl = new shepherd.electrumJSCore(shepherd.electrumServers[_network].port, shepherd.electrumServers[_network].address, shepherd.electrumServers[_network].proto); // tcp or tls
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)

6
routes/shepherd/electrum/estimate.js

@ -1,7 +1,11 @@
module.exports = (shepherd) => {
shepherd.get('/electrum/estimatefee', (req, res, next) => {
if (shepherd.checkToken(req.query.token)) {
const ecl = new shepherd.electrumJSCore(shepherd.electrumServers[req.query.network].port, shepherd.electrumServers[req.query.network].address, shepherd.electrumServers[req.query.network].proto); // tcp or tls
const 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)

23
routes/shepherd/electrum/keys.js

@ -40,6 +40,7 @@ module.exports = (shepherd) => {
const keys = {
pub: keyPair.getAddress(),
priv: keyPair.toWIF(),
pubHex: keyPair.getPublicKeyBuffer().toString('hex'),
};
/*shepherd.log(`seed: ${seed}`, true);
@ -98,28 +99,6 @@ module.exports = (shepherd) => {
}
});
shepherd.post('/electrum/seedtowif', (req, res, next) => {
if (shepherd.checkToken(req.body.token)) {
let keys = shepherd.seedToWif(req.body.seed, req.body.network.toLowerCase(), req.body.iguana);
const successObj = {
msg: 'success',
result: {
keys,
},
};
res.end(JSON.stringify(successObj));
} else {
const errorObj = {
msg: 'error',
result: 'unauthorized access',
};
res.end(JSON.stringify(errorObj));
}
});
shepherd.getCoinByPub = (address) => {
const _skipNetworks = ['btc', 'crw', 'dgb', 'arg', 'zec', 'nmc', 'ltc', 'vtc', 'via', 'fair', 'doge', 'kmd', 'mona'];

17
routes/shepherd/electrum/network.js

@ -58,9 +58,14 @@ module.exports = (shepherd) => {
};
shepherd.getNetworkData = (network) => {
const coin = shepherd.findNetworkObj(network) || shepherd.findNetworkObj(network.toUpperCase()) || shepherd.findNetworkObj(network.toLowerCase());
let coin = shepherd.findNetworkObj(network) || shepherd.findNetworkObj(network.toUpperCase()) || shepherd.findNetworkObj(network.toLowerCase());
const coinUC = coin ? coin.toUpperCase() : null;
if (!coin &&
!coinUC) {
coin = network.toUpperCase();
}
if (coin === 'SUPERNET' ||
coin === 'REVS' ||
coin === 'SUPERNET' ||
@ -70,10 +75,10 @@ module.exports = (shepherd) => {
coin === 'BET' ||
coin === 'CRYPTO' ||
coin === 'COQUI' ||
coin === 'GLXT' ||
coin === 'GLXT' ||
coin === 'OOT' ||
coin === 'HODL' ||
coin === 'EQL' ||
coin === 'EQL' ||
coin === 'SHARK' ||
coin === 'MSHARK' ||
coin === 'BOTS' ||
@ -101,9 +106,9 @@ module.exports = (shepherd) => {
coinUC === 'BET' ||
coinUC === 'CRYPTO' ||
coinUC === 'COQUI' ||
coinUC === 'GLXT' ||
coinUC === 'GLXT' ||
coinUC === 'OOT' ||
coinUC === 'EQL' ||
coinUC === 'EQL' ||
coinUC === 'HODL' ||
coinUC === 'SHARK' ||
coinUC === 'MSHARK' ||
@ -182,7 +187,7 @@ module.exports = (shepherd) => {
};
for (let key in shepherd.electrumServers) {
if (shepherd.electrumServers[key].abbr === req.query.coin) { // a bit risky
if (shepherd.electrumServers[key].abbr === req.query.coin) {
shepherd.electrumServers[key].address = req.query.address;
shepherd.electrumServers[key].port = req.query.port;
break;

57
routes/shepherd/electrum/transactions.js

@ -1,7 +1,9 @@
const async = require('async');
const Promise = require('bluebird');
const MAX_VOUT_LENGTH = 10;
const MAX_VIN_LENGTH = 150; // parse up to MAX_VIN_LENGTH vins
// TODO: add z -> pub, pub -> z flag for zcash forks
module.exports = (shepherd) => {
shepherd.sortTransactions = (transactions, sortBy) => {
@ -131,6 +133,8 @@ module.exports = (shepherd) => {
const decodedTx = shepherd.electrumJSTxDecoder(_rawtxJSON, network, _network);
let txInputs = [];
let opreturn = false;
shepherd.log(`decodedtx network ${network}`, true);
shepherd.log('decodedtx =>', true);
@ -138,6 +142,16 @@ module.exports = (shepherd) => {
let index2 = 0;
if (decodedTx &&
decodedTx.outputs &&
decodedTx.outputs.length) {
for (let i = 0; i < decodedTx.outputs.length; i++) {
if (decodedTx.outputs[i].scriptPubKey.type === 'nulldata') {
opreturn = shepherd.hex2str(decodedTx.outputs[i].scriptPubKey.hex);
}
}
}
if (decodedTx &&
decodedTx.inputs &&
decodedTx.inputs.length) {
@ -145,7 +159,8 @@ module.exports = (shepherd) => {
const checkLoop = () => {
index2++;
if (index2 === decodedTx.inputs.length || index2 === MAX_VOUT_LENGTH) {
if (index2 === decodedTx.inputs.length ||
index2 === MAX_VIN_LENGTH) {
shepherd.log(`tx history decode inputs ${decodedTx.inputs.length} | ${index2} => main callback`, true);
const _parsedTx = {
network: decodedTx.network,
@ -153,36 +168,45 @@ module.exports = (shepherd) => {
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,
timestamp: Number(transaction.height) === 0 || Number(transaction.height) === -1 ? Math.floor(Date.now() / 1000) : blockInfo.timestamp,
confirmations: Number(transaction.height) === 0 || Number(transaction.height) === -1 ? 0 : currentHeight - transaction.height,
};
const formattedTx = shepherd.parseTransactionAddresses(_parsedTx, _address, network);
if (formattedTx.type) {
formattedTx.height = transaction.height;
formattedTx.blocktime = blockInfo.timestamp;
formattedTx.timereceived = blockInfo.timereceived;
formattedTx.blocktime = Number(transaction.height) === 0 || Number(transaction.height) === -1 ? Math.floor(Date.now() / 1000) : blockInfo.timestamp;
formattedTx.timereceived = Number(transaction.height) === 0 || Number(transaction.height) === -1 ? Math.floor(Date.now() / 1000) : blockInfo.timereceived;
formattedTx.hex = _rawtxJSON;
formattedTx.inputs = decodedTx.inputs;
formattedTx.outputs = decodedTx.outputs;
formattedTx.locktime = decodedTx.format.locktime;
formattedTx.vinLen = decodedTx.inputs.length;
formattedTx.vinMaxLen = MAX_VIN_LENGTH;
formattedTx.opreturn = opreturn;
_rawtx.push(formattedTx);
} else {
formattedTx[0].height = transaction.height;
formattedTx[0].blocktime = blockInfo.timestamp;
formattedTx[0].timereceived = blockInfo.timereceived;
formattedTx[0].blocktime = Number(transaction.height) === 0 || Number(transaction.height) === -1 ? Math.floor(Date.now() / 1000) : blockInfo.timestamp;
formattedTx[0].timereceived = Number(transaction.height) === 0 || Number(transaction.height) === -1 ? Math.floor(Date.now() / 1000) : blockInfo.timereceived;
formattedTx[0].hex = _rawtxJSON;
formattedTx[0].inputs = decodedTx.inputs;
formattedTx[0].outputs = decodedTx.outputs;
formattedTx[0].locktime = decodedTx.format.locktime;
formattedTx[0].vinLen = decodedTx.inputs.length;
formattedTx[0].vinMaxLen = MAX_VIN_LENGTH;
formattedTx[0].opreturn = opreturn[0];
formattedTx[1].height = transaction.height;
formattedTx[1].blocktime = blockInfo.timestamp;
formattedTx[1].timereceived = blockInfo.timereceived;
formattedTx[1].blocktime = Number(transaction.height) === 0 || Number(transaction.height) === -1 ? Math.floor(Date.now() / 1000) : blockInfo.timestamp;
formattedTx[1].timereceived = Number(transaction.height) === 0 || Number(transaction.height) === -1 ? Math.floor(Date.now() / 1000) : blockInfo.timereceived;
formattedTx[1].hex = _rawtxJSON;
formattedTx[1].inputs = decodedTx.inputs;
formattedTx[1].outputs = decodedTx.outputs;
formattedTx[1].locktime = decodedTx.format.locktime;
formattedTx[1].vinLen = decodedTx.inputs.length;
formattedTx[1].vinMaxLen = MAX_VIN_LENGTH;
formattedTx[1].opreturn = opreturn[1];
_rawtx.push(formattedTx[0]);
_rawtx.push(formattedTx[1]);
}
@ -230,6 +254,7 @@ module.exports = (shepherd) => {
height: transaction.height,
timestamp: Number(transaction.height) === 0 ? Math.floor(Date.now() / 1000) : blockInfo.timestamp,
confirmations: Number(transaction.height) === 0 ? 0 : currentHeight - transaction.height,
opreturn,
};
const formattedTx = shepherd.parseTransactionAddresses(_parsedTx, _address, network);
@ -313,7 +338,11 @@ module.exports = (shepherd) => {
shepherd.get('/electrum/gettransaction', (req, res, next) => {
if (shepherd.checkToken(req.query.token)) {
const network = req.query.network || shepherd.findNetworkObj(req.query.coin);
const ecl = new shepherd.electrumJSCore(shepherd.electrumServers[network].port, shepherd.electrumServers[network].address, shepherd.electrumServers[network].proto); // tcp or tls
const ecl = new shepherd.electrumJSCore(
shepherd.electrumServers[network].port,
shepherd.electrumServers[network].address,
shepherd.electrumServers[network].proto
); // tcp or tls
shepherd.log('electrum gettransaction =>', true);
@ -551,7 +580,11 @@ module.exports = (shepherd) => {
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
const ecl = new shepherd.electrumJSCore(
shepherd.electrumServers[req.query.network].port,
shepherd.electrumServers[req.query.network].address,
shepherd.electrumServers[req.query.network].proto
); // tcp or tls
shepherd.log(decodedTx.inputs[0]);
shepherd.log(decodedTx.inputs[0].txid);

24
routes/shepherd/log.js

@ -8,17 +8,10 @@ module.exports = (shepherd) => {
console.log(msg);
}
if (!isSpvOut) {
shepherd.appRuntimeLog.push({
time: Date.now(),
msg: msg,
});
} else {
shepherd.appRuntimeSPVLog.push({
time: Date.now(),
msg: msg,
});
}
shepherd[!isSpvOut ? 'appRuntimeLog' : 'appRuntimeSPVLog'].push({
time: Date.now(),
msg: msg,
});
}
shepherd.writeLog = (data) => {
@ -73,16 +66,17 @@ module.exports = (shepherd) => {
shepherd.post('/guilog', (req, res, next) => {
if (shepherd.checkToken(req.body.token)) {
const logLocation = `${shepherd.agamaDir}/shepherd`;
const timestamp = req.body.timestamp;
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;
if (shepherd.guiLog[shepherd.appSessionHash][timestamp]) {
shepherd.guiLog[shepherd.appSessionHash][timestamp].status = req.body.status;
shepherd.guiLog[shepherd.appSessionHash][timestamp].response = req.body.response;
} else {
shepherd.guiLog[shepherd.appSessionHash][req.body.timestamp] = {
shepherd.guiLog[shepherd.appSessionHash][timestamp] = {
function: req.body.function,
type: req.body.type,
url: req.body.url,

175
routes/shepherd/pin.js

@ -1,5 +1,9 @@
const fs = require('fs-extra');
const aes256 = require('nodejs-aes256');
const passwdStrength = require('passwd-strength');
const bitcoin = require('bitcoinjs-lib');
const sha256 = require('js-sha256');
const bigi = require('bigi');
module.exports = (shepherd) => {
/*
@ -9,36 +13,69 @@ module.exports = (shepherd) => {
shepherd.post('/encryptkey', (req, res, next) => {
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
req.body.string) {
const _pin = req.body.key;
const _pinTest = _pin.match('^(?=.*[A-Z])(?=.*[^<>{}\"/|;:.,~!?@#$%^=&*\\]\\\\()\\[_+]*$)(?=.*[0-9])(?=.*[a-z]).{8}$');
const hash = sha256.create().update(req.body.string);
let bytes = hash.array();
bytes[0] &= 248;
bytes[31] &= 127;
bytes[31] |= 64;
fs.writeFile(`${shepherd.agamaDir}/shepherd/pin/${req.body.pubkey}.pin`, encryptedString, (err) => {
if (err) {
shepherd.log('error writing pin file');
}
const d = bigi.fromBuffer(bytes);
const keyPair = new bitcoin.ECPair(d, null, { network: shepherd.getNetworkData('btc') });
const keys = {
pub: keyPair.getAddress(),
priv: keyPair.toWIF(),
};
let pubkey = req.body.pubkey ? req.body.pubkey : keyPair.getAddress();
if (passwdStrength(_pin) < 29) {
shepherd.log('seed storage weak pin!');
const returnObj = {
msg: 'success',
result: encryptedString,
msg: 'error',
result: false,
};
res.end(JSON.stringify(returnObj));
});
} else {
const _customPinFilenameTest = /^[0-9a-zA-Z-_]+$/g;
if (_customPinFilenameTest.test(pubkey)) {
const encryptedString = aes256.encrypt(req.body.key, req.body.string);
fs.writeFile(`${shepherd.agamaDir}/shepherd/pin/${pubkey}.pin`, encryptedString, (err) => {
if (err) {
shepherd.log('error writing pin file');
const returnObj = {
msg: 'error',
result: 'error writing pin file',
};
res.end(JSON.stringify(returnObj));
} else {
const returnObj = {
msg: 'success',
result: pubkey,
};
res.end(JSON.stringify(returnObj));
}
});
} else {
const returnObj = {
msg: 'error',
result: 'pin file name can only contain alphanumeric characters, dash "-" and underscore "_"',
};
res.end(JSON.stringify(returnObj));
}
}
} else {
const _paramsList = [
'key',
'string',
'pubkey'
'string'
];
let errorObj = {
msg: 'error',
@ -127,7 +164,7 @@ module.exports = (shepherd) => {
});
shepherd.get('/getpinlist', (req, res, next) => {
if (shepherd.checkToken(req.body.token)) {
if (shepherd.checkToken(req.query.token)) {
if (fs.existsSync(`${shepherd.agamaDir}/shepherd/pin`)) {
fs.readdir(`${shepherd.agamaDir}/shepherd/pin`, (err, items) => {
let _pins = [];
@ -172,5 +209,101 @@ module.exports = (shepherd) => {
}
});
shepherd.post('/modifypin', (req, res, next) => {
if (shepherd.checkToken(req.body.token)) {
const pubkey = req.body.pubkey;
if (pubkey) {
if (fs.existsSync(`${shepherd.agamaDir}/shepherd/pin/${pubkey}.pin`)) {
fs.readFile(`${shepherd.agamaDir}/shepherd/pin/${pubkey}.pin`, 'utf8', (err, data) => {
if (err) {
const errorObj = {
msg: 'error',
result: err,
};
res.end(JSON.stringify(errorObj));
} else {
if (req.body.delete) {
fs.unlinkSync(`${shepherd.agamaDir}/shepherd/pin/${pubkey}.pin`);
const returnObj = {
msg: 'success',
result: `${pubkey}.pin is removed`,
};
res.end(JSON.stringify(returnObj));
} else {
const pubkeynew = req.body.pubkeynew;
const _customPinFilenameTest = /^[0-9a-zA-Z-_]+$/g;
if (pubkeynew) {
if (_customPinFilenameTest.test(pubkeynew)) {
fs.writeFile(`${shepherd.agamaDir}/shepherd/pin/${pubkeynew}.pin`, data, (err) => {
if (err) {
shepherd.log('error writing pin file');
const returnObj = {
msg: 'error',
result: 'error writing pin file',
};
res.end(JSON.stringify(returnObj));
} else {
fs.unlinkSync(`${shepherd.agamaDir}/shepherd/pin/${pubkey}.pin`);
const returnObj = {
msg: 'success',
result: pubkeynew,
};
res.end(JSON.stringify(returnObj));
}
});
} else {
const returnObj = {
msg: 'error',
result: 'pin file name can only contain alphanumeric characters, dash "-" and underscore "_"',
};
res.end(JSON.stringify(returnObj));
}
} else {
const returnObj = {
msg: 'error',
result: 'missing param pubkeynew',
};
res.end(JSON.stringify(returnObj));
}
}
}
});
} else {
const errorObj = {
msg: 'error',
result: `file ${pubkey}.pin doesnt exist`,
};
res.end(JSON.stringify(errorObj));
}
} else {
const errorObj = {
msg: 'error',
result: 'missing pubkey param',
};
res.end(JSON.stringify(errorObj));
}
} else {
const errorObj = {
msg: 'error',
result: 'unauthorized access',
};
res.end(JSON.stringify(errorObj));
}
});
return shepherd;
};

19
routes/shepherd/quitDaemon.js

@ -25,13 +25,19 @@ module.exports = (shepherd) => {
let _arg = [];
if (chain &&
!shepherd.nativeCoindList[key.toLowerCase()] && key !== 'CHIPS') {
!shepherd.nativeCoindList[key.toLowerCase()] &&
key !== 'CHIPS') {
shepherd.removePubkey(chain.toLowerCase());
_arg.push(`-ac_name=${chain}`);
if (shepherd.appConfig.dataDir.length) {
_arg.push(`-datadir=${shepherd.appConfig.dataDir + (key !== 'komodod' ? '/' + key : '')}`);
}
} else if (key === 'komodod' && shepherd.appConfig.dataDir.length) {
} else if (
key === 'komodod' &&
shepherd.appConfig.dataDir.length
) {
_arg.push(`-datadir=${shepherd.appConfig.dataDir}`);
}
@ -43,7 +49,7 @@ module.exports = (shepherd) => {
if (stdout.indexOf('EOF reached') > -1 ||
stderr.indexOf('EOF reached') > -1 ||
(error && error.toString().indexOf('Command failed') > -1 && !stderr) || // win "special snowflake" case
(error && error.toString().indexOf('Command failed') > -1 && !stderr) || // windows
stdout.indexOf('connect to server: unknown (code -1)') > -1 ||
stderr.indexOf('connect to server: unknown (code -1)') > -1) {
delete shepherd.coindInstanceRegistry[key];
@ -88,7 +94,10 @@ module.exports = (shepherd) => {
let _coindQuitCmd = shepherd.komodocliBin;
let _arg = [];
if (_chain) {
shepherd.removePubkey(_chain.toLowerCase());
_arg.push(`-ac_name=${_chain}`);
if (shepherd.appConfig.dataDir.length) {
@ -154,6 +163,10 @@ module.exports = (shepherd) => {
if (req.body.mode === 'native') {
delete shepherd.coindInstanceRegistry[_chain ? _chain : 'komodod'];
if (_chain) {
shepherd.removePubkey(_chain.toLowerCase());
}
const obj = {
msg: 'success',
result: 'result',

4
version

@ -1,3 +1,3 @@
version=0.2.32
version=0.2.36
type=beta
minversion=0.2.32
minversion=0.2.36

2
version_build

@ -1 +1 @@
0.2.32-beta
0.2.36-beta
Loading…
Cancel
Save