Browse Source

iguana core cleanup

v0.25
pbca26 7 years ago
parent
commit
b9fbc5851e
  1. 3
      gui/startup/agama-instance-error.html
  2. 4
      gui/startup/app-closing.html
  3. 2
      gui/startup/app-settings.html
  4. 9
      gui/startup/index.html
  5. 119
      gui/startup/main.html
  6. 18
      index.html
  7. 94
      main.js
  8. 9
      package.json
  9. 86
      routes/appConfig.js
  10. 962
      routes/cache.js
  11. 45
      routes/mock.js
  12. 683
      routes/shepherd.js
  13. 2
      version
  14. 2
      version_build

3
gui/startup/agama-instance-error.html

@ -3,14 +3,12 @@
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<link rel="stylesheet" href="../EasyDEX-GUI/assets/global/css/bootstrap.min.css">
<link rel="stylesheet" href="../EasyDEX-GUI/assets/mainWindow/css/jRoll.min.css">
<link rel="stylesheet" href="../EasyDEX-GUI/assets/mainWindow/css/loading.css">
<script type="text/javascript" src="../EasyDEX-GUI/assets/mainWindow/js/module-hack.js"></script>
<script type="text/javascript" src="../EasyDEX-GUI/assets/global/vendor/jquery/jquery.min.js"></script>
<script type="text/javascript" src="../EasyDEX-GUI/assets/scripts/config.js"></script>
<script type="text/javascript" src="../EasyDEX-GUI/assets/mainWindow/js/bluebird.min.js"></script>
<script type="text/javascript" src="../EasyDEX-GUI/assets/mainWindow/js/loading.js"></script>
<script type="text/javascript" src="../EasyDEX-GUI/assets/mainWindow/js/jRoll.min.js"></script>
<script>if (window.module) module = window.module;</script>
</head>
<body class="agamaMode agama-default-window-height">
@ -30,6 +28,5 @@
class="btn btn-primary btn-close-app">Quit</button>
</div>
</div>
<script type="text/javascript" src="../EasyDEX-GUI/assets/mainWindow/js/init.js"></script>
</body>
</html>

4
gui/startup/app-closing.html

@ -3,17 +3,15 @@
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<link rel="stylesheet" href="../EasyDEX-GUI/assets/global/css/bootstrap.min.css">
<link rel="stylesheet" href="../EasyDEX-GUI/assets/mainWindow/css/jRoll.min.css">
<link rel="stylesheet" href="../EasyDEX-GUI/assets/mainWindow/css/loading.css">
<script type="text/javascript" src="../EasyDEX-GUI/assets/mainWindow/js/module-hack.js"></script>
<script type="text/javascript" src="../EasyDEX-GUI/assets/global/vendor/jquery/jquery.min.js"></script>
<script type="text/javascript" src="../EasyDEX-GUI/assets/scripts/config.js"></script>
<script type="text/javascript" src="../EasyDEX-GUI/assets/mainWindow/js/bluebird.min.js"></script>
<script type="text/javascript" src="../EasyDEX-GUI/assets/mainWindow/js/loading.js"></script>
<script type="text/javascript" src="../EasyDEX-GUI/assets/mainWindow/js/jRoll.min.js"></script>
<script>if (window.module) module = window.module;</script>
</head>
<body class="agamaMode agama-default-window-height">
<body class="agamaMode closing-window-height">
<div class="text-center">
<div
id="agamaMode"

2
gui/startup/app-settings.html

@ -3,14 +3,12 @@
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<link rel="stylesheet" href="../EasyDEX-GUI/assets/global/css/bootstrap.min.css">
<link rel="stylesheet" href="../EasyDEX-GUI/assets/mainWindow/css/jRoll.min.css">
<link rel="stylesheet" href="../EasyDEX-GUI/assets/mainWindow/css/loading.css">
<script type="text/javascript" src="../EasyDEX-GUI/assets/mainWindow/js/module-hack.js"></script>
<script type="text/javascript" src="../EasyDEX-GUI/assets/global/vendor/jquery/jquery.min.js"></script>
<script type="text/javascript" src="../EasyDEX-GUI/assets/scripts/config.js"></script>
<script type="text/javascript" src="../EasyDEX-GUI/assets/mainWindow/js/bluebird.min.js"></script>
<script type="text/javascript" src="../EasyDEX-GUI/assets/mainWindow/js/loading.js"></script>
<script type="text/javascript" src="../EasyDEX-GUI/assets/mainWindow/js/jRoll.min.js"></script>
<script>if (window.module) module = window.module;</script>
</head>
<body class="agamaMode agama-app-settings-window">

9
gui/startup/index.html

@ -3,14 +3,12 @@
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<link rel="stylesheet" href="../EasyDEX-GUI/assets/global/css/bootstrap.min.css">
<link rel="stylesheet" href="../EasyDEX-GUI/assets/mainWindow/css/jRoll.min.css">
<link rel="stylesheet" href="../EasyDEX-GUI/assets/mainWindow/css/loading.css">
<script type="text/javascript" src="../EasyDEX-GUI/assets/mainWindow/js/module-hack.js"></script>
<script type="text/javascript" src="../EasyDEX-GUI/assets/global/vendor/jquery/jquery.min.js"></script>
<script type="text/javascript" src="../EasyDEX-GUI/assets/scripts/config.js"></script>
<script type="text/javascript" src="../EasyDEX-GUI/assets/mainWindow/js/bluebird.min.js"></script>
<script type="text/javascript" src="../EasyDEX-GUI/assets/mainWindow/js/loading.js"></script>
<script type="text/javascript" src="../EasyDEX-GUI/assets/mainWindow/js/jRoll.min.js"></script>
<script>if (window.module) module = window.module;</script>
</head>
<body class="agamaMode loading-window">
@ -51,12 +49,6 @@
<a>KMD (passive)</a>
</li>
</ul>
<button
id="normalStartBtn"
onClick="normalStart()"
class="btn btn-primary btn-mode">
<img src="../EasyDEX-GUI/assets/mainWindow/img/fa-cubes.png"> All modes
</button>
<div class="margin-top-20 settings-stick-to-right">
<button
id="settingsBtn"
@ -67,6 +59,5 @@
</div>
</div>
</div>
<script type="text/javascript" src="../EasyDEX-GUI/assets/mainWindow/js/init.js"></script>
</body>
</html>

119
gui/startup/main.html

@ -1,119 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<link rel="stylesheet" href="EasyDEX-GUI/assets/global/css/bootstrap.min.css">
<script>if (typeof module === 'object') {window.module = module; module = undefined;}</script>
<script type="text/javascript" src="EasyDEX-GUI/assets/global/vendor/jquery/jquery.min.js"></script>
<script>if (window.module) module = window.module;</script>
<script type="text/javascript">
function resizeMainWindow() {
/* set default map height */
var mapH = $(window).height();
$(".page-main").outerHeight(mapH);
}
function StartIguana() {
var ajax_data = {"herd":"iguana"};
console.log(ajax_data);
$.ajax({
type: 'POST',
data: JSON.stringify(ajax_data),
url: 'http://127.0.0.1:17777/shepherd/herd',
dataType: "xml/html/script/json", // expected format for response
contentType: "application/json", // send as JSON
success: function(data, textStatus, jqXHR) {
var AjaxOutputData = JSON.parse(data);
console.log('== ActiveHandle Data OutPut ==');
console.log(AjaxOutputData);
},
error: function(xhr, textStatus, error) {
console.log(xhr.statusText);
if ( xhr.readyState == 0 ) {
}
console.log(textStatus);
console.log(error);
}
});
}
function StartCorsproxy() {
var ajax_data = {"herd":"corsproxy"};
console.log(ajax_data);
$.ajax({
type: 'POST',
data: JSON.stringify(ajax_data),
url: 'http://127.0.0.1:17777/shepherd/herd',
dataType: "xml/html/script/json", // expected format for response
contentType: "application/json", // send as JSON
success: function(data, textStatus, jqXHR) {
var AjaxOutputData = JSON.parse(data);
console.log('== ActiveHandle Data OutPut ==');
console.log(AjaxOutputData);
},
error: function(xhr, textStatus, error) {
console.log(xhr.statusText);
if ( xhr.readyState == 0 ) {
}
console.log(textStatus);
console.log(error);
}
});
}
function StartKomodod() {
var ajax_data = {"herd":"komodod"};
console.log(ajax_data);
$.ajax({
type: 'POST',
data: JSON.stringify(ajax_data),
url: 'http://127.0.0.1:17777/shepherd/herd',
dataType: "xml/html/script/json", // expected format for response
contentType: "application/json", // send as JSON
success: function(data, textStatus, jqXHR) {
var AjaxOutputData = JSON.parse(data);
console.log('== ActiveHandle Data OutPut ==');
console.log(AjaxOutputData);
},
error: function(xhr, textStatus, error) {
console.log(xhr.statusText);
if ( xhr.readyState == 0 ) {
}
console.log(textStatus);
console.log(error);
}
});
}
function StartKMDNativeIGUI() {
var secToLaunch = 60;
$('#kmdNativeBtn').text('Starting Komodo in ' + secToLaunch + 's');
StartCorsproxy();
StartKomodod();
setInterval(function() {
$('#kmdNativeBtn').text('Starting Komodo in ' + secToLaunch + 's');
secToLaunch--;
}, 1000);
setTimeout(function() {
document.location = 'Iguana-GUI/index.html';
}, secToLaunch * 1000);
}
jQuery(document).ready(function() {
resizeMainWindow();
window.onresize = function(event) { resizeMainWindow(); };
});
</script>
</head>
<body>
<div class="page-main">
<div class="col-xs-6 text-center" style="height: 100%; background: url(bg.jpg) no-repeat fixed; background-color: #c7c7c7; vertical-align: middle;" id="iguanaGuiStart">
<h1 style="color: white;">Iguana Wallet<h1>
<a type="button" class="btn btn-default btn-lg" href="Iguana-GUI/index.html">Open Iguana Wallet</a><br/><br/>
<a type="button" class="btn btn-default btn-lg" href="#" onclick="StartCorsproxy()">Launch proxy server</a><br/><br/>
<a type="button" class="btn btn-default btn-lg" href="#" onclick="StartKMDNativeIGUI()" id="kmdNativeBtn">Komodo Native</a><br/><br/>
<a type="button" class="btn btn-default btn-lg" href="#" onclick="StartIguana()">Start Iguana Core</a>
</div>
<div class="col-xs-6 text-center" style="height: 100%; background: url(bg2.jpg) no-repeat fixed; background-color: #d8d8d8; vertical-align: middle;" id="edexGuiStart">
<h1 style="color: white;">EasyDEX</h1>
<a type="button" class="btn btn-default btn-lg" href="EasyDEX-GUI/index.html">Open EasyDEX</a>
</div>
</div>
</body>
</html>

18
index.html

@ -1,18 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>iguanaElectronApp</title>
</head>
<body>
<h3>some version information:</h3>
node.js <script>document.write(process.versions.node)</script>,
chromium <script>document.write(process.versions.chrome)</script>,
electron <script>document.write(process.versions.electron)</script>.
</body>
<script>
//bind other code refs
//require('./xxx.js')
</script>
</html>

94
main.js

@ -30,7 +30,6 @@ Promise = require('bluebird');
if (osPlatform === 'linux') {
process.env.ELECTRON_RUN_AS_NODE = true;
// console.log(process.env);
}
// GUI APP settings and starting gui on address http://120.0.0.1:17777
@ -55,7 +54,7 @@ app.setName(appBasicInfo.name);
app.setVersion(appBasicInfo.version);
shepherd.binFixRights();
shepherd.createIguanaDirs();
shepherd.createAgamaDirs();
const appSessionHash = md5(Date.now());
@ -81,10 +80,6 @@ shepherd.writeLog(`app started in ${(appConfig.dev ? 'dev mode' : ' user mode')}
shepherd.setConfKMD();
if (appConfig.killIguanaOnStart) {
shepherd.killRogueProcess('iguana');
}
guiapp.use(function(req, res, next) {
res.header('Access-Control-Allow-Origin', appConfig.dev ? '*' : 'http://127.0.0.1:3000');
res.header('Access-Control-Allow-Headers', 'X-Requested-With');
@ -151,13 +146,13 @@ let forceQuitApp = false;
const _zcashParamsExist = shepherd.zcashParamsExist();
module.exports = guiapp;
let iguanaIcon;
let agamaIcon;
if (os.platform() === 'linux') {
iguanaIcon = path.join(__dirname, '/assets/icons/agama_icons/128x128.png');
agamaIcon = path.join(__dirname, '/assets/icons/agama_icons/128x128.png');
}
if (os.platform() === 'win32') {
iguanaIcon = path.join(__dirname, '/assets/icons/agama_app_icon.ico');
agamaIcon = path.join(__dirname, '/assets/icons/agama_app_icon.ico');
}
function createLoadingWindow() {
@ -169,7 +164,7 @@ function createLoadingWindow() {
width: 500,
height: 355,
frame: false,
icon: iguanaIcon,
icon: agamaIcon,
show: false,
});
} catch(e) {}
@ -232,9 +227,6 @@ function createLoadingWindow() {
});
shepherd.writeLog('show loading window');
// DEVTOOLS - only for dev purposes - ca333
// loadingWindow.webContents.openDevTools()
// if window closed we kill iguana proc
loadingWindow.on('hide', function() {
// our app does not have multiwindow - so we dereference the window object instead of
@ -279,7 +271,7 @@ function createAppCloseWindow() {
width: 500,
height: 300,
frame: false,
icon: iguanaIcon,
icon: agamaIcon,
show: false,
});
@ -304,7 +296,7 @@ function createAppSettingsWindow() {
width: 750,
height: !appConfig.experimentalFeatures ? 570 : 700,
frame: false,
icon: iguanaIcon,
icon: agamaIcon,
show: false,
});
@ -346,7 +338,7 @@ function createWindow(status) {
mainWindow = new BrowserWindow({ // dirty hack to prevent main window flash on quit
width: closeAppAfterLoading ? 1 : 1280,
height: closeAppAfterLoading ? 1 : 800,
icon: iguanaIcon,
icon: agamaIcon,
show: false,
});
@ -374,39 +366,30 @@ function createWindow(status) {
]);
// load our index.html (i.e. easyDEX GUI)
if (appConfig.edexGuiOnly) {
if (appConfig.v2) {
shepherd.writeLog('show edex gui');
mainWindow.appConfig = appConfig;
mainWindow.appConfigSchema = shepherd.appConfigSchema;
mainWindow.appBasicInfo = appBasicInfo;
mainWindow.appSessionHash = appSessionHash;
mainWindow.assetChainPorts = require('./routes/ports.js');
mainWindow.zcashParamsExist = _zcashParamsExist;
mainWindow.iguanaIcon = iguanaIcon;
mainWindow.testLocation = shepherd.testLocation;
mainWindow.kmdMainPassiveMode = shepherd.kmdMainPassiveMode;
mainWindow.getAppRuntimeLog = shepherd.getAppRuntimeLog;
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.webContents.on('did-finish-load', function() {
setTimeout(function() {
mainWindow.show();
}, 40);
});
} else {
shepherd.writeLog('show edex gui');
mainWindow.loadURL(`http://${appConfig.host}:${appConfig.agamaPort}/gui/EasyDEX-GUI/`);
}
shepherd.writeLog('show edex gui');
mainWindow.appConfig = appConfig;
mainWindow.appConfigSchema = shepherd.appConfigSchema;
mainWindow.appBasicInfo = appBasicInfo;
mainWindow.appSessionHash = appSessionHash;
mainWindow.assetChainPorts = require('./routes/ports.js');
mainWindow.zcashParamsExist = _zcashParamsExist;
mainWindow.agamaIcon = agamaIcon;
mainWindow.testLocation = shepherd.testLocation;
mainWindow.kmdMainPassiveMode = shepherd.kmdMainPassiveMode;
mainWindow.getAppRuntimeLog = shepherd.getAppRuntimeLog;
if (appConfig.dev) {
mainWindow.loadURL('http://127.0.0.1:3000');
} else {
mainWindow.loadURL(`http://${appConfig.host}:${appConfig.agamaPort}/gui/startup/main.html`);
mainWindow.loadURL(`http://${appConfig.host}:${appConfig.agamaPort}/gui/EasyDEX-GUI/react/build`);
}
mainWindow.webContents.on('did-finish-load', function() {
setTimeout(function() {
mainWindow.show();
}, 40);
});
mainWindow.webContents.on('context-menu', (e, params) => { // context-menu returns params
const { selectionText, isEditable } = params; // params obj
@ -426,7 +409,6 @@ function createWindow(status) {
shepherd.log('Closing Main Window...');
shepherd.writeLog('exiting app...');
shepherd.dumpCacheBeforeExit();
shepherd.quitKomodod(1000);
pm2.connect(true, function(err) {
@ -546,13 +528,15 @@ app.on('window-all-closed', function() {
// Calling event.preventDefault() will prevent the default behaviour, which is terminating the application.
app.on('before-quit', function(event) {
shepherd.log('before-quit');
shepherd.killRogueProcess('iguana'); // kill any rogue iguana core instances
if (!forceQuitApp && mainWindow === null && loadingWindow != null) { // mainWindow not intitialised and loadingWindow not dereferenced
if (!forceQuitApp &&
mainWindow === null &&
loadingWindow != null) { // mainWindow not intitialised and loadingWindow not dereferenced
// loading window is still open
shepherd.log('before-quit prevented');
shepherd.writeLog('quit app after loading is done');
closeAppAfterLoading = true;
// obsolete(?)
let code = `$('#loading_status_text').html('Preparing to shutdown the wallet.<br/>Please wait while all daemons are closed...')`;
loadingWindow.webContents.executeJavaScript(code);
event.preventDefault();
@ -562,7 +546,9 @@ app.on('before-quit', function(event) {
// Emitted when all windows have been closed and the application will quit.
// Calling event.preventDefault() will prevent the default behaviour, which is terminating the application.
app.on('will-quit', function(event) {
if (!forceQuitApp && mainWindow === null && loadingWindow != null) {
if (!forceQuitApp &&
mainWindow === null &&
loadingWindow != null) {
// loading window is still open
shepherd.log('will-quit while loading window active');
event.preventDefault();
@ -572,16 +558,16 @@ app.on('will-quit', function(event) {
// Emitted when the application is quitting.
// Calling event.preventDefault() will prevent the default behaviour, which is terminating the application.
app.on('quit', function(event) {
if (!forceQuitApp && mainWindow === null && loadingWindow != null) {
if (!forceQuitApp &&
mainWindow === null &&
loadingWindow != null) {
shepherd.log('quit while loading window active');
event.preventDefault();
}
})
app.on('activate', function() {
if (mainWindow === null) {
// createWindow('open');
}
if (mainWindow === null) {}
});
function formatBytes(bytes, decimals) {

9
package.json

@ -1,7 +1,7 @@
{
"name": "agama_app",
"productName": "Agama",
"version": "0.2.22",
"version": "0.2.23",
"description": "Agama Desktop App",
"main": "main.js",
"scripts": {
@ -10,15 +10,12 @@
},
"repository": "https://github.com/SuperNETorg/Agama/",
"keywords": [
"iguana",
"agama",
"superNET",
"SuperNET",
"komodo",
"easydex",
"instantdex",
"pax"
],
"author": "ca333, grewalsatinder",
"author": "SuperNET",
"license": "MIT",
"devDependencies": {
"electron": "^1.4.1"

86
routes/appConfig.js

@ -1,58 +1,18 @@
const appConfig = {
config: { // default config
edexGuiOnly: true,
iguanaGuiOnly: false,
manualIguanaStart: false,
skipBasiliskNetworkCheck: true,
minNotaries: 8,
host: '127.0.0.1',
agamaPort: 17777,
iguanaCorePort: 7778,
maxDescriptors: {
darwin: 90000,
linux: 1000000,
},
killIguanaOnStart: true,
dev: false,
v2: true,
useBasiliskInstance: true,
debug: false,
cli: {
passthru: true,
default: true,
},
iguanaLessMode: true,
roundValues: false,
experimentalFeatures: false,
dataDir: '',
},
schema: {
edexGuiOnly: {
display: false,
type: 'boolean',
displayName: 'EDEX GUI only',
},
iguanaGuiOnly: {
display: false,
type: 'boolean',
displayName: 'Iguana GUI only',
},
manualIguanaStart: {
display: false,
type: 'boolean',
displayName: 'Manual Iguana Start',
},
skipBasiliskNetworkCheck: {
display: false,
type: 'boolean',
displayName: 'Skip Basilisk Network Check',
},
minNotaries: {
display: false,
type: 'number',
displayName: 'Minimum notaries count',
info: 'Minimum number of notaries to connect to on startup',
},
host: {
display: true,
type: 'string',
@ -65,13 +25,6 @@ const appConfig = {
displayName: 'Agama Port',
info: 'Agama HTTP port. Required to run GUI.',
},
iguanaCorePort: {
display: true,
initDisplay: true,
type: 'number',
displayName: 'Iguana Core Port',
info: 'Default Iguana Core Port. Change it if you have conflicts with other applications.',
},
maxDescriptors: {
display: false,
displayName: 'Max Descriptors per Process',
@ -86,12 +39,6 @@ const appConfig = {
type: 'number',
},
},
killIguanaOnStart: {
display: true,
displayName: 'Kill Iguana Core Processes on Startup',
info: 'Kill any rogue Iguana Core processes during app startup',
type: 'boolean',
},
dev: {
display: true,
initDisplay: true,
@ -99,17 +46,6 @@ const appConfig = {
info: 'Enable developer mode',
type: 'boolean',
},
v2: {
display: false,
type: 'boolean',
},
useBasiliskInstance: {
display: true,
initDisplay: true,
displayName: 'Iguana Core Basilisk Instance',
info: 'Enable dedicated Iguana Core instance to handle all Basilisk network requests',
type: 'boolean',
},
debug: {
display: true,
initDisplay: true,
@ -117,28 +53,6 @@ const appConfig = {
info: 'Enable debug output',
type: 'boolean',
},
cli: {
display: true,
displayName: 'Direct BitcoinRPC passthru interface',
info: 'Enable direct BitcoinRPC passthru interface. It will bypass Iguana Core and send requests directly to Bitcoin JSON server.',
passthru: {
display: true,
displayName: 'Enable Direct Passthru',
type: 'boolean',
},
default: {
display: true,
displayName: 'Enable CLI passthru',
info: 'Enable komodo-cli passthru. This allows you to send CLI compatible commands directly from UI to komodo-cli.',
type: 'boolean',
},
},
iguanaLessMode: {
display: true,
displayName: 'Enable Native Only mode',
info: 'Limited to only Komodo native mode to speed up loading and reduce hardware resources consumption.',
type: 'boolean',
},
roundValues: {
display: true,
displayName: 'Enable amount rounding',

962
routes/cache.js

@ -1,962 +0,0 @@
const fs = require('fs-extra');
const request = require('request');
const async = require('async');
var cache = {};
var inMemCache;
var inMemPubkey;
cache.setVar = function(variable, value) {
cache[variable] = value;
}
/*
* cache data is dumped to disk before app quit or after cache.one call is finished
*/
cache.dumpCacheBeforeExit = function() {
if (inMemCache) {
cache.shepherd.log('dumping cache before exit');
fs.writeFileSync(`${cache.iguanaDir}/shepherd/cache-${inMemPubkey}.json`, JSON.stringify(inMemCache), 'utf8');
}
}
cache.get = function(req, res, next) {
const pubkey = req.query.pubkey;
if (pubkey) {
inMemPubkey = pubkey;
if (!inMemCache) {
cache.shepherd.log('serving cache from disk');
if (fs.existsSync(`${cache.iguanaDir}/shepherd/cache-${pubkey}.json`)) {
fs.readFile(`${cache.iguanaDir}/shepherd/cache-${pubkey}.json`, 'utf8', function(err, data) {
if (err) {
const errorObj = {
msg: 'error',
result: err,
};
res.end(JSON.stringify(errorObj));
} else { // deprecated
try {
const parsedJSON = JSON.parse(data);
const successObj = {
msg: 'success',
result: parsedJSON,
};
inMemCache = parsedJSON;
res.end(JSON.stringify(successObj));
} catch (e) {
cache.shepherd.log('JSON parse error while reading cache data from disk:');
cache.shepherd.log(e);
if (e.toString().indexOf('at position') > -1) {
const errorPos = e.toString().split(' ');
cache.shepherd.log(`JSON error ---> ${data.substring(errorPos[errorPos.length - 1] - 20, errorPos[errorPos.length - 1] + 20)} | error sequence: ${data.substring(errorPos[errorPos.length - 1], errorPos[errorPos.length - 1] + 1)}`);
cache.shepherd.log('attempting to recover JSON data');
fs.writeFile(`${cache.iguanaDir}/shepherd/cache-${pubkey}.json`, data.substring(0, errorPos[errorPos.length - 1]), function(err) {
const successObj = {
msg: 'success',
result: data.substring(0, errorPos[errorPos.length - 1]),
};
inMemCache = JSON.parse(data.substring(0, errorPos[errorPos.length - 1]));
res.end(JSON.stringify(successObj));
});
}
}
}
});
} else {
const errorObj = {
msg: 'error',
result: `no file with handle ${pubkey}`,
};
res.end(JSON.stringify(errorObj));
}
} else {
const successObj = {
msg: 'success',
result: inMemCache,
};
res.end(JSON.stringify(successObj));
}
} else {
const errorObj = {
msg: 'error',
result: 'no pubkey provided',
};
res.end(JSON.stringify(errorObj));
}
}
cache.groomGet = function(req, res, next) {
const _filename = req.query.filename;
if (_filename) {
if (fs.existsSync(`${cache.iguanaDir}/shepherd/cache-${_filename}.json`)) {
fs.readFile(`${cache.iguanaDir}/shepherd/cache-${_filename}.json`, 'utf8', function(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: `no file with name ${_filename}`,
};
res.end(JSON.stringify(errorObj));
}
} else {
const errorObj = {
msg: 'error',
result: 'no file name provided',
};
res.end(JSON.stringify(errorObj));
}
}
cache.groomDelete = function(req, res, next) {
const _filename = req.body.filename;
if (_filename) {
if (fs.existsSync(`${cache.iguanaDir}/shepherd/cache-${_filename}.json`)) {
inMemCache = null;
fs.unlink(`${cache.iguanaDir}/shepherd/cache-${_filename}.json`, function(err) {
if (err) {
const errorObj = {
msg: 'error',
result: err,
};
res.end(JSON.stringify(errorObj));
} else {
const successObj = {
msg: 'success',
result: 'deleted',
};
res.end(JSON.stringify(successObj));
}
});
} else {
const errorObj = {
msg: 'error',
result: `no file with name ${_filename}`,
};
res.end(JSON.stringify(errorObj));
}
} else {
const errorObj = {
msg: 'error',
result: 'no file name provided',
};
res.end(JSON.stringify(errorObj));
}
}
cache.groomPost = function(req, res) {
const _filename = req.body.filename;
const _payload = req.body.payload;
if (!cacheCallInProgress) {
cacheCallInProgress = true;
if (_filename) {
if (!_payload) {
const errorObj = {
msg: 'error',
result: 'no payload provided',
};
res.end(JSON.stringify(errorObj));
} else {
inMemCache = JSON.parse(_payload);
cache.shepherd.log('appending groom post to in mem cache');
cache.shepherd.log('appending groom post to on disk cache');
fs.writeFile(`${cache.iguanaDir}/shepherd/cache-${_filename}.json`, _payload, function(err) {
if (err) {
const errorObj = {
msg: 'error',
result: err,
};
cacheCallInProgress = false;
res.end(JSON.stringify(errorObj));
} else {
const successObj = {
msg: 'success',
result: 'done',
};
cacheCallInProgress = false;
res.end(JSON.stringify(successObj));
}
});
}
} else {
const errorObj = {
msg: 'error',
result: 'no file name provided',
};
res.end(JSON.stringify(errorObj));
}
} else {
const errorObj = {
msg: 'error',
result: 'another job is in progress',
};
res.end(JSON.stringify(errorObj));
}
}
var cacheCallInProgress = false;
const cacheGlobLifetime = 600; // sec
// TODO: reset calls' states on new /cache call start
var mock = require('./mock');
var callStack = {};
const checkCallStack = function() {
let total = 0;
for (let coin in callStack) {
total =+ callStack[coin];
}
if (total / Object.keys(callStack).length === 1) {
cache.dumpCacheBeforeExit();
cacheCallInProgress = false;
cache.io.emit('messages', {
message: {
shepherd: {
method: 'cache-one',
status: 'done',
resp: 'success',
},
},
});
}
};
/*
* type: GET
* params: userpass, pubkey, coin, address, skip
*/
cache.one = function(req, res, next) {
if (req.query.pubkey &&
!fs.existsSync(`${cache.iguanaDir}/shepherd/cache-${req.query.pubkey}.json`)) {
cacheCallInProgress = false;
}
if (cacheCallInProgress) {
checkCallStack();
}
if (!cacheCallInProgress) {
cache.dumpCacheBeforeExit();
if (fs.existsSync(`${cache.iguanaDir}/shepherd/cache-${req.query.pubkey}.json`)) {
let _data = fs.readFileSync(`${cache.iguanaDir}/shepherd/cache-${req.query.pubkey}.json`, 'utf8');
if (_data) {
inMemCache = JSON.parse(_data);
_data = _data.replace('waiting', 'failed');
cache.dumpCacheBeforeExit();
}
}
// TODO: add check to allow only one cache call/sequence in progress
cacheCallInProgress = true;
let sessionKey = req.query.userpass;
let coin = req.query.coin;
let address = req.query.address;
let addresses = req.query.addresses && req.query.addresses.indexOf(':') > -1 ? req.query.addresses.split(':') : null;
let pubkey = req.query.pubkey;
let mock = req.query.mock;
let skipTimeout = req.query.skip;
let callsArray = req.query.calls.split(':');
let iguanaCorePort = req.query.port ? req.query.port : cache.appConfig.iguanaCorePort;
let errorObj = {
msg: 'error',
result: 'error',
};
let outObj = {};
const writeCache = function(timeStamp) {
if (timeStamp) {
outObj.timestamp = timeStamp;
}
inMemCache = outObj;
};
const checkTimestamp = function(dateToCheck) {
const currentEpochTime = new Date(Date.now()) / 1000;
const secondsElapsed = Number(currentEpochTime) - Number(dateToCheck / 1000);
return Math.floor(secondsElapsed);
};
let internalError = false;
inMemPubkey = pubkey;
callStack[coin] = 1;
cache.shepherd.log(callsArray);
cache.shepherd.log(`iguana core port ${iguanaCorePort}`);
if (!sessionKey) {
const errorObj = {
msg: 'error',
result: 'no session key provided',
};
res.end(JSON.stringify(errorObj));
internalError = true;
}
if (!pubkey) {
const errorObj = {
msg: 'error',
result: 'no pubkey provided',
};
res.end(JSON.stringify(errorObj));
internalError = true;
}
cache.shepherd.log('cache-one call started');
function fixJSON(data) {
if (data &&
data.length) {
try {
const parsedJSON = JSON.parse(data);
return parsedJSON;
} catch (e) {
cache.shepherd.log(e);
if (e.toString().indexOf('at position') > -1) {
const errorPos = e.toString().split(' ');
cache.shepherd.log(`JSON error ---> ${data.substring(errorPos[errorPos.length - 1] - 20, errorPos[errorPos.length - 1] + 20)} | error sequence: ${data.substring(errorPos[errorPos.length - 1], errorPos[errorPos.length - 1] + 1)}`);
cache.shepherd.log('attempting to recover JSON data');
return JSON.parse(data.substring(0, errorPos[errorPos.length - 1]));
}
if (e.toString().indexOf('Unexpected end of JSON input')) {
return {};
}
}
} else {
return {};
}
}
if (fs.existsSync(`${cache.iguanaDir}/shepherd/cache-${pubkey}.json`) &&
coin !== 'all') {
if (inMemCache) {
cache.shepherd.log('cache one from mem');
outObj = inMemCache;
} else {
const _file = fs.readFileSync(`${cache.iguanaDir}/shepherd/cache-${pubkey}.json`, 'utf8');
cache.shepherd.log('cache one from disk');
outObj = fixJSON(_file);
}
if (!outObj ||
!outObj.basilisk) {
cache.shepherd.log('no local basilisk info');
outObj['basilisk'] = {};
outObj['basilisk'][coin] = {};
} else {
if (!outObj['basilisk'][coin]) {
cache.shepherd.log('no local coin info');
outObj['basilisk'][coin] = {};
}
}
} else {
outObj['basilisk'] = {};
outObj['basilisk'][coin] = {};
}
res.end(JSON.stringify({
msg: 'success',
result: 'call is initiated',
}));
if (!internalError) {
cache.io.emit('messages', {
message: {
shepherd: {
method: 'cache-one',
status: 'in progress',
},
},
});
function execDEXRequests(coin, address) {
let dexUrls = {
listunspent: `http://${cache.appConfig.host}:${iguanaCorePort}/api/dex/listunspent?userpass=${sessionKey}&symbol=${coin}&address=${address}`,
listtransactions: `http://${cache.appConfig.host}:${iguanaCorePort}/api/dex/listtransactions?userpass=${sessionKey}&count=100&skip=0&symbol=${coin}&address=${address}`,
getbalance: `http://${cache.appConfig.host}:${iguanaCorePort}/api/dex/getbalance?userpass=${sessionKey}&symbol=${coin}&address=${address}`,
refresh: `http://${cache.appConfig.host}:${iguanaCorePort}/api/basilisk/refresh?userpass=${sessionKey}&symbol=${coin}&address=${address}`
};
let _dexUrls = {};
for (let a = 0; a < callsArray.length; a++) {
_dexUrls[callsArray[a]] = dexUrls[callsArray[a]];
}
if (coin === 'BTC' ||
coin === 'SYS') {
delete _dexUrls.refresh;
delete _dexUrls.getbalance;
}
cache.shepherd.log(`${coin} address ${address}`);
if (!outObj.basilisk[coin][address]) {
outObj.basilisk[coin][address] = {};
writeCache();
}
// set current call status
async.forEachOf(_dexUrls, function(dexUrl, key) {
if (!outObj.basilisk[coin][address][key]) {
outObj.basilisk[coin][address][key] = {};
outObj.basilisk[coin][address][key].status = 'waiting';
} else {
outObj.basilisk[coin][address][key].status = 'waiting';
}
});
writeCache();
async.forEachOf(_dexUrls, function(dexUrl, key) {
var tooEarly = false;
if (outObj.basilisk[coin][address][key] &&
outObj.basilisk[coin][address][key].timestamp &&
(!skipTimeout && checkTimestamp(outObj.basilisk[coin][address][key].timestamp) < cacheGlobLifetime)) {
tooEarly = true;
outObj.basilisk[coin][address][key].status = 'done';
cache.io.emit('messages', {
message: {
shepherd: {
method: 'cache-one',
status: 'in progress',
iguanaAPI: {
method: key,
coin: coin,
address: address,
status: 'done',
resp: 'too early',
},
},
},
});
}
if (!tooEarly) {
cache.io.emit('messages', {
message: {
shepherd: {
method: 'cache-one',
status: 'in progress',
iguanaAPI: {
method: key,
coin: coin,
address: address,
status: 'in progress',
},
},
},
});
outObj.basilisk[coin][address][key].status = 'in progress';
request({
url: mock ? `http://localhost:17777/shepherd/mock?url=${dexUrl}` : dexUrl,
method: 'GET',
timeout: 30000,
}, function(error, response, body) {
if (response &&
response.statusCode &&
response.statusCode === 200) {
cache.io.emit('messages', {
message: {
shepherd: {
method: 'cache-one',
status: 'in progress',
iguanaAPI: {
method: key,
coin: coin,
address: address,
status: 'done',
resp: body,
},
},
},
});
// basilisk fallback
const _parsedJSON = JSON.parse(body);
_explorerURL = {
getbalance: `http://kmd.explorer.supernet.org/api/addr/${address}/?noTxList=1`,
listtransactions: `https://kmd.explorer.supernet.org/api/txs?address=${address}&pageNum=0`
};
if ((key === 'getbalance' &&
coin === 'KMD' &&
((_parsedJSON && _parsedJSON.balance === 0) || body === [])) ||
(key === 'listtransactions' &&
coin === 'KMD' &&
(_parsedJSON === [] || !_parsedJSON.length))) {
cache.shepherd.log('fallback to kmd explorer ======>');
request({
url: _explorerURL[key],
method: 'GET'
}, function(error, response, _body) {
if (response &&
response.statusCode &&
response.statusCode === 200) {
let _parsedExplorerJSON = JSON.parse(_body);
_parsedExplorerJSON['source'] = 'explorer';
let _formattedTxs = [];
if (key === 'listtransactions' &&
_parsedExplorerJSON['txs'] &&
_parsedExplorerJSON['txs'].length) {
const _txList = _parsedExplorerJSON['txs'];
for (let i = 0; i < _txList.length; i++) {
_formattedTxs.push({
type: 'unknown',
height: _txList[i].blockheight,
confirmations: _txList[i].confirmations,
timestamp: _txList[i].time,
amount: _txList[i].vout[1].value,
txid: _txList[i].txid,
source: 'explorer',
});
}
_parsedExplorerJSON = _formattedTxs;
}
if ((key === 'getbalance' &&
Number(_parsedExplorerJSON.balance) !== Number(_parsedJSON.balance) &&
Number(_parsedExplorerJSON.txApperances) < 500) || key === 'listtransactions') {
body = JSON.stringify(_parsedExplorerJSON);
}
cache.io.emit('messages', {
'message': {
'shepherd': {
'method': 'cache-one',
'status': 'in progress',
'iguanaAPI': {
'method': key,
'coin': coin,
'address': address,
'status': 'done',
'resp': _body
}
}
}
});
outObj.basilisk[coin][address][key] = {};
outObj.basilisk[coin][address][key].data = JSON.parse(body);
outObj.basilisk[coin][address][key].timestamp = Date.now(); // add timestamp
outObj.basilisk[coin][address][key].status = 'done';
cache.shepherd.log(dexUrl);
cache.shepherd.log(body);
callStack[coin]--;
cache.shepherd.log(`${coin} _stack len ${callStack[coin]}`);
cache.io.emit('messages', {
message: {
shepherd: {
method: 'cache-one',
status: 'in progress',
iguanaAPI: {
currentStackLength: callStack[coin],
},
},
},
});
checkCallStack();
writeCache();
} else {
cache.shepherd.log(`explorer ${key} for address ${address} fallback failed`);
}
});
} else {
outObj.basilisk[coin][address][key] = {};
outObj.basilisk[coin][address][key].data = JSON.parse(body);
outObj.basilisk[coin][address][key].timestamp = Date.now(); // add timestamp
outObj.basilisk[coin][address][key].status = 'done';
cache.shepherd.log(dexUrl);
cache.shepherd.log(body);
callStack[coin]--;
cache.shepherd.log(`${coin} _stack len ${callStack[coin]}`);
cache.io.emit('messages', {
message: {
shepherd: {
method: 'cache-one',
status: 'in progress',
iguanaAPI: {
currentStackLength: callStack[coin],
},
},
},
});
checkCallStack();
writeCache();
}
}
if (error ||
!body ||
!response) {
// basilisk fallback
_explorerURL = {
getbalance: `http://kmd.explorer.supernet.org/api/addr/${address}/?noTxList=1`,
listtransactions: `https://kmd.explorer.supernet.org/api/txs?address=${address}&pageNum=0`
};
if ((key === 'getbalance' &&
coin === 'KMD') ||
(key === 'listtransactions' &&
coin === 'KMD')) {
cache.shepherd.log('fallback to kmd explorer ======>');
request({
url: _explorerURL[key],
method: 'GET'
}, function(error, response, _body) {
if (response &&
response.statusCode &&
response.statusCode === 200) {
let _parsedExplorerJSON = JSON.parse(_body);
_parsedExplorerJSON['source'] = 'explorer';
if ((key === 'getbalance' &&
Number(_parsedExplorerJSON.balance) !== Number(_parsedJSON.balance) &&
Number(_parsedExplorerJSON.txApperances) < 500) || key === 'listtransactions') {
body = JSON.stringify(_parsedExplorerJSON);
}
cache.io.emit('messages', {
'message': {
'shepherd': {
'method': 'cache-one',
'status': 'in progress',
'iguanaAPI': {
'method': key,
'coin': coin,
'address': address,
'status': 'done',
'resp': _body
}
}
}
});
outObj.basilisk[coin][address][key] = {};
outObj.basilisk[coin][address][key].data = JSON.parse(body);
outObj.basilisk[coin][address][key].timestamp = Date.now(); // add timestamp
outObj.basilisk[coin][address][key].status = 'done';
cache.shepherd.log(dexUrl);
cache.shepherd.log(body);
callStack[coin]--;
cache.shepherd.log(`${coin} _stack len ${callStack[coin]}`);
cache.io.emit('messages', {
message: {
shepherd: {
method: 'cache-one',
status: 'in progress',
iguanaAPI: {
currentStackLength: callStack[coin],
},
},
},
});
checkCallStack();
writeCache();
} else {
cache.shepherd.log(`explorer ${key} for address ${address} fallback failed`);
outObj.basilisk[coin][address][key] = {};
outObj.basilisk[coin][address][key].data = { 'error': 'request failed' };
outObj.basilisk[coin][address][key].timestamp = 1471620867 // add timestamp
outObj.basilisk[coin][address][key].status = 'done';
callStack[coin]--;
cache.shepherd.log(`${coin} request ${key} for address ${address} failed`);
cache.shepherd.log(`${coin} _stack len ${callStack[coin]}`);
cache.io.emit('messages', {
message: {
shepherd: {
method: 'cache-one',
status: 'in progress',
iguanaAPI: {
currentStackLength: callStack[coin],
},
},
},
});
checkCallStack();
writeCache();
}
});
} else {
outObj.basilisk[coin][address][key] = {};
outObj.basilisk[coin][address][key].data = { 'error': 'request failed' };
outObj.basilisk[coin][address][key].timestamp = 1471620867 // add timestamp
outObj.basilisk[coin][address][key].status = 'done';
callStack[coin]--;
cache.shepherd.log(`${coin} request ${key} for address ${address} failed`);
cache.shepherd.log(`${coin} _stack len ${callStack[coin]}`);
cache.io.emit('messages', {
message: {
shepherd: {
method: 'cache-one',
status: 'in progress',
iguanaAPI: {
currentStackLength: callStack[coin],
},
},
},
});
checkCallStack();
writeCache();
}
}
});
} else {
cache.shepherd.log(`${key} is fresh, check back in ${(cacheGlobLifetime - checkTimestamp(outObj.basilisk[coin][address][key].timestamp))}s`);
callStack[coin]--;
cache.shepherd.log(`${coin} _stack len ${callStack[coin]}`);
cache.io.emit('messages', {
message: {
shepherd: {
method: 'cache-one',
status: 'in progress',
iguanaAPI: {
currentStackLength: callStack[coin],
},
},
},
});
checkCallStack();
}
});
}
function parseAddresses(coin, addrArray) {
cache.io.emit('messages', {
message: {
shepherd: {
method: 'cache-one',
status: 'in progress',
iguanaAPI: {
method: 'getaddressesbyaccount',
coin: coin,
status: 'done',
resp: addrArray,
},
},
},
});
outObj.basilisk[coin].addresses = addrArray;
cache.shepherd.log(addrArray);
writeCache();
const addrCount = outObj.basilisk[coin].addresses ? outObj.basilisk[coin].addresses.length : 0;
let callsArrayBTC = callsArray.length;
if (callsArray.indexOf('getbalance') > - 1) {
callsArrayBTC--;
}
if (callsArray.indexOf('refresh') > - 1) {
callsArrayBTC--;
}
callStack[coin] = callStack[coin] + addrCount * (coin === 'BTC' || coin === 'SYS' ? callsArrayBTC : callsArray.length);
cache.shepherd.log(`${coin} stack len ${callStack[coin]}`);
cache.io.emit('messages', {
message: {
shepherd: {
method: 'cache-one',
status: 'in progress',
iguanaAPI: {
totalStackLength: callStack[coin],
},
},
},
});
async.each(outObj.basilisk[coin].addresses, function(address) {
execDEXRequests(coin, address);
});
}
function getAddresses(coin) {
if (addresses) {
parseAddresses(coin, addresses);
} else {
const tempUrl = `http://${cache.appConfig.host}:${cache.appConfig.iguanaCorePort}/api/bitcoinrpc/getaddressesbyaccount?userpass=${sessionKey}&coin=${coin}&account=*`;
request({
url: mock ? `http://localhost:17777/shepherd/mock?url=${tempUrl}` : tempUrl,
method: 'GET'
}, function(error, response, body) {
if (response &&
response.statusCode &&
response.statusCode === 200) {
parseAddresses(coin, JSON.parse(body).result);
} else {
// TODO: error
}
});
}
}
// update all available coin addresses
if (!address) {
cache.io.emit('messages', {
message: {
shepherd: {
method: 'cache-one',
status: 'in progress',
iguanaAPI: {
method: 'getaddressesbyaccount',
coin: coin,
status: 'in progress',
},
},
},
});
if (coin === 'all') {
const tempUrl = `http://${cache.appConfig.host}:${cache.appConfig.iguanaCorePort}/api/InstantDEX/allcoins?userpass=${sessionKey}`;
request({
url: mock ? `http://localhost:17777/shepherd/mock?url=${tempUrl}` : tempUrl,
method: 'GET'
}, function(error, response, body) {
if (response &&
response.statusCode &&
response.statusCode === 200) {
cache.shepherd.log(JSON.parse(body).basilisk);
cache.io.emit('messages', {
message: {
shepherd: {
method: 'cache-one',
status: 'in progress',
iguanaAPI: {
method: 'allcoins',
status: 'done',
resp: body,
},
},
},
});
body = JSON.parse(body);
// basilisk coins
if (body.basilisk &&
body.basilisk.length) {
// get coin addresses
async.each(body.basilisk, function(coin) {
callStack[coin] = 1;
});
async.each(body.basilisk, function(coin) {
outObj.basilisk[coin] = {};
writeCache();
cache.io.emit('messages', {
message: {
shepherd: {
method: 'cache-one',
status: 'in progress',
iguanaAPI: {
method: 'getaddressesbyaccount',
coin: coin,
status: 'in progress',
},
},
},
});
getAddresses(coin);
});
}
}
if (error) { // stop further requests on failure, exit
callStack[coin] = 1;
checkCallStack();
}
});
} else {
getAddresses(coin);
}
} else {
let callsArrayBTC = callsArray.length; // restrict BTC and SYS only to listunspent and listtransactions calls
if (callsArray.indexOf('getbalance') > - 1) {
callsArrayBTC--;
}
if (callsArray.indexOf('refresh') > - 1) {
callsArrayBTC--;
}
callStack[coin] = callStack[coin] + (coin === 'BTC' || coin === 'SYS' ? callsArrayBTC : callsArray.length);
cache.shepherd.log(`${coin} stack len ${callStack[coin]}`);
cache.io.emit('messages', {
message: {
shepherd: {
method: 'cache-one',
status: 'in progress',
iguanaAPI: {
totalStackLength: callStack[coin],
currentStackLength: callStack[coin],
},
},
},
});
execDEXRequests(coin, address);
}
} else {
cache.io.emit('messages', {
message: {
shepherd: {
method: 'cache-all',
status: 'done',
resp: 'internal error',
},
},
});
cacheCallInProgress = false;
}
} else {
res.end(JSON.stringify({
msg: 'error',
result: 'another call is in progress already',
}));
}
};
module.exports = cache;

45
routes/mock.js

@ -1,45 +0,0 @@
const fs = require('fs-extra'),
request = require('request'),
async = require('async'),
url = require('url');
let mock = {};
mock.setVar = function(variable, value) {
mock[variable] = value;
}
mock.get = function(req, res, next) {
const _url = req.query.url;
if (_url.indexOf('/InstantDEX/allcoins') > -1) {
res.end(JSON.stringify({
'native': [],
'basilisk': [ 'KMD', 'BTC'],
'full':[],
'tag': '18430609759584422959'
}));
}
if (_url.indexOf('/bitcoinrpc/getaddressesbyaccount') > -1) {
console.log(_url.indexOf('/bitcoinrpc/getaddressesbyaccount'));
res.end(JSON.stringify({
'result': [
"RDbGxL8QYdEp8sMULaVZS2E6XThcTKT9Jd",
"RL4orv22Xch7PhM5w9jUHhVQhX6kF6GkfS",
"RUrxvPTEKGWEDTvAtgiqbUTTFE53Xdpj8a",
"RPJoLDa7RezvfUUBr7R3U8wrP16AgUsNw3",
"RQPTpRJEeafNx5hkDzgjcsPyU4E8RFVApT"
]
}));
}
if (_url.indexOf('/api/dex/listunspent') > -1 ||
_url.indexOf('/api/dex/listtransactions') > -1 ||
_url.indexOf('/api/ss/getbalance') > -1 ||
_url.indexOf('/api/ww/refresh') > -1) {
res.end(JSON.stringify({
'some key': 'some value'
}));
}
}
module.exports = mock;

683
routes/shepherd.js

@ -30,10 +30,7 @@ var ps = require('ps-node'),
assetChainPorts = require('./ports.js'),
_appConfig = require('./appConfig.js'),
shepherd = express.Router(),
iguanaInstanceRegistry = {},
coindInstanceRegistry = {},
syncOnlyIguanaInstanceInfo = {},
syncOnlyInstanceInterval = -1,
guiLog = {},
rpcConf = {},
appRuntimeLog = [],
@ -41,17 +38,10 @@ var ps = require('ps-node'),
shepherd.appConfig = _appConfig.config;
// IGUANA FILES AND CONFIG SETTINGS
var iguanaConfsDirSrc = path.join(__dirname, '../assets/deps/confs');
// SETTING OS DIR TO RUN IGUANA FROM
// SETTING APP ICON FOR LINUX AND WINDOWS
if (os.platform() === 'darwin') {
fixPath();
var iguanaBin = path.join(__dirname, '../assets/bin/osx/iguana'),
iguanaDir = `${process.env.HOME}/Library/Application Support/iguana`,
iguanaTestDir = `${process.env.HOME}/Library/Application Support/iguana/test`,
iguanaConfsDir = `${iguanaDir}/confs`,
var agamaDir = `${process.env.HOME}/Library/Application Support/agama`,
agamaTestDir = `${process.env.HOME}/Library/Application Support/agama/test`,
komododBin = path.join(__dirname, '../assets/bin/osx/komodod'),
komodocliBin = path.join(__dirname, '../assets/bin/osx/komodo-cli'),
komodoDir = shepherd.appConfig.dataDir.length ? shepherd.appConfig.dataDir : `${process.env.HOME}/Library/Application Support/Komodo`,
@ -62,11 +52,8 @@ if (os.platform() === 'darwin') {
}
if (os.platform() === 'linux') {
var iguanaBin = path.join(__dirname, '../assets/bin/linux64/iguana'),
iguanaDir = `${process.env.HOME}/.iguana`,
iguanaTestDir = `${process.env.HOME}/.iguana/test`,
iguanaConfsDir = `${iguanaDir}/confs`,
iguanaIcon = path.join(__dirname, '/assets/icons/agama_icons/128x128.png'),
var agamaDir = `${process.env.HOME}/.agama`,
agamaTestDir = `${process.env.HOME}/.agama/test`,
komododBin = path.join(__dirname, '../assets/bin/linux64/komodod'),
komodocliBin = path.join(__dirname, '../assets/bin/linux64/komodo-cli'),
komodoDir = shepherd.appConfig.dataDir.length ? shepherd.appConfig.dataDir : `${process.env.HOME}/.komodo`,
@ -74,16 +61,10 @@ if (os.platform() === 'linux') {
}
if (os.platform() === 'win32') {
var iguanaBin = path.join(__dirname, '../assets/bin/win64/iguana.exe');
iguanaBin = path.normalize(iguanaBin);
iguanaDir = `${process.env.APPDATA}/iguana`;
iguanaDir = path.normalize(iguanaDir);
iguanaTestDir = `${process.env.APPDATA}/iguana/test`;
iguanaTestDir = path.normalize(iguanaTestDir);
iguanaConfsDir = `${process.env.APPDATA}/iguana/confs`;
iguanaConfsDir = path.normalize(iguanaConfsDir);
iguanaIcon = path.join(__dirname, '/assets/icons/agama_icons/agama_app_icon.ico'),
iguanaConfsDirSrc = path.normalize(iguanaConfsDirSrc),
var agamaDir = `${process.env.APPDATA}/agama`;
agamaDir = path.normalize(agamaDir);
agamaTestDir = `${process.env.APPDATA}/agama/test`;
agamaTestDir = path.normalize(agamaTestDir);
komododBin = path.join(__dirname, '../assets/bin/win64/komodod.exe'),
komododBin = path.normalize(komododBin),
komodocliBin = path.join(__dirname, '../assets/bin/win64/komodo-cli.exe'),
@ -475,16 +456,6 @@ shepherd.post('/native/dashboard/update', function(req, res, next) {
});
});
// TODO: test functions are wip
shepherd.testNearestIguanaPort = function() {
return new Promise(function(resolve, reject) {
const port = shepherd.appConfig.iguanaCorePort;
portscanner.findAPortNotInUse(port, port + 100, '127.0.0.1', function(error, _port) {
resolve(_port);
});
});
}
shepherd.testClearAll = function() {
return new Promise(function(resolve, reject) {
fs.removeSync(`${iguanaTestDir}`);
@ -497,96 +468,29 @@ shepherd.testBins = function(daemonName) {
const _bins = {
komodod: komododBin,
komodoCli: komodocliBin,
iguana: iguanaBin,
};
const _arg = null;
let _pid;
shepherd.log('testBins exec ' + _bins[daemonName]);
if (!fs.existsSync(iguanaTestDir)) {
fs.mkdirSync(iguanaTestDir);
}
if (daemonName === 'iguana') {
shepherd.killRogueProcess('iguana');
if (!fs.existsSync(agamaTestDir)) {
fs.mkdirSync(agamaTestDir);
}
try {
_fs.access(`${iguanaTestDir}/${daemonName}Test.log`, fs.constants.R_OK, function(err) {
_fs.access(`${agamaTestDir}/${daemonName}Test.log`, fs.constants.R_OK, function(err) {
if (!err) {
try {
_fs.unlinkSync(`${iguanaTestDir}/${daemonName}Test.log`);
_fs.unlinkSync(`${agamaTestDir}/${daemonName}Test.log`);
} catch (e) {}
} else {
shepherd.log(`path ${iguanaTestDir}/${daemonName}Test.log doesnt exist`);
shepherd.log(`path ${agamaTestDir}/${daemonName}Test.log doesnt exist`);
}
});
} catch (e) {}
if (daemonName === 'iguana') {
pm2.connect(true,function(err) { //start up pm2 god
if (err) {
shepherd.error(err);
process.exit(2);
}
shepherd.log(`iguana core port ${shepherd.appConfig.iguanaCorePort}`);
shepherd.writeLog(`iguana core port ${shepherd.appConfig.iguanaCorePort}`);
pm2.start({
script: iguanaBin, // path to binary
name: 'iguana',
exec_mode : 'fork',
args: [`-port=${shepherd.appConfig.iguanaCorePort}`],
output: `${iguanaTestDir}/iguanaTest.log`,
mergeLogs: true,
cwd: iguanaDir // set correct iguana directory
}, function(err, apps) {
if (apps[0] &&
apps[0].process &&
apps[0].process.pid) {
shepherd.log(`test: got iguana instance pid = ${apps[0].process.pid}`);
shepherd.writeLog(`test: iguana core started at port ${shepherd.appConfig.iguanaCorePort} pid ${apps[0].process.pid}`);
} else {
shepherd.log(`test: unable to start iguana core at port ${shepherd.appConfig.iguanaCorePort}`);
}
pm2.disconnect(); // Disconnect from PM2
if (err) {
shepherd.writeLog(`test: iguana core port ${shepherd.appConfig.iguanaCorePort}`);
shepherd.log(`test: iguana fork error: ${err}`);
// throw err;
}
});
});
setTimeout(function() {
pm2.delete('iguana');
const _iguanaTestRunLog = fs.readFileSync(`${iguanaTestDir}/iguanaTest.log`, 'utf8');
if (_iguanaTestRunLog.indexOf('iguana main') > -1 &&
_iguanaTestRunLog.indexOf('Basilisk initialized') > -1) {
let _portTest = 'unknown';
if (_iguanaTestRunLog.indexOf(`iguana_rpcloop 127.0.0.1:${shepherd.appConfig.iguanaCorePort}`) > -1) {
_portTest = 'passed';
}
if (_iguanaTestRunLog.indexOf(`ERROR BINDING PORT.${shepherd.appConfig.iguanaCorePort}`) > -1) {
_portTest = 'failed';
}
resolve({
res: 'success',
port: _portTest,
iguanaPort: shepherd.appConfig.iguanaCorePort,
});
} else {
resolve({ res: 'error' });
}
}, 30000);
} else if (daemonName === 'komodod') {
if (daemonName === 'komodod') {
try {
_fs.access(`${iguanaTestDir}/debug.log`, fs.constants.R_OK, function(err) {
if (!err) {
@ -764,6 +668,7 @@ shepherd.testBins = function(daemonName) {
});
}
// komodod datadir location test
shepherd.testLocation = function(path) {
return new Promise(function(resolve, reject) {
fs.lstat(path, (err, stats) => {
@ -786,7 +691,6 @@ shepherd.testLocation = function(path) {
shepherd.binFixRights = function() {
const osPlatform = os.platform();
const _bins = [
iguanaBin,
komododBin,
komodocliBin
];
@ -899,7 +803,7 @@ shepherd.readVersionFile = function() {
}
shepherd.writeLog = function(data) {
const logLocation = `${iguanaDir}/shepherd`;
const logLocation = `${agamaDir}/shepherd`;
const timeFormatted = new Date(Date.now()).toLocaleString('en-US', { hour12: false });
if (shepherd.appConfig.debug) {
@ -919,35 +823,35 @@ shepherd.writeLog = function(data) {
}
}
shepherd.createIguanaDirs = function() {
if (!fs.existsSync(iguanaDir)) {
fs.mkdirSync(iguanaDir);
shepherd.createAgamaDirs = function() {
if (!fs.existsSync(agamaDir)) {
fs.mkdirSync(agamaDir);
if (fs.existsSync(iguanaDir)) {
shepherd.log(`created iguana folder at ${iguanaDir}`);
shepherd.writeLog(`created iguana folder at ${iguanaDir}`);
if (fs.existsSync(agamaDir)) {
shepherd.log(`created agama folder at ${agamaDir}`);
shepherd.writeLog(`created agama folder at ${agamaDir}`);
}
} else {
shepherd.log('iguana folder already exists');
shepherd.log('agama folder already exists');
}
if (!fs.existsSync(`${iguanaDir}/shepherd`)) {
fs.mkdirSync(`${iguanaDir}/shepherd`);
if (!fs.existsSync(`${agamaDir}/shepherd`)) {
fs.mkdirSync(`${agamaDir}/shepherd`);
if (fs.existsSync(`${iguanaDir}/shepherd`)) {
shepherd.log(`created shepherd folder at ${iguanaDir}/shepherd`);
shepherd.writeLog(`create shepherd folder at ${iguanaDir}/shepherd`);
if (fs.existsSync(`${agamaDir}/shepherd`)) {
shepherd.log(`created shepherd folder at ${agamaDir}/shepherd`);
shepherd.writeLog(`create shepherd folder at ${agamaDir}/shepherd`);
}
} else {
shepherd.log('iguana/shepherd folder already exists');
shepherd.log('agama/shepherd folder already exists');
}
if (!fs.existsSync(`${iguanaDir}/shepherd/pin`)) {
fs.mkdirSync(`${iguanaDir}/shepherd/pin`);
if (!fs.existsSync(`${agamaDir}/shepherd/pin`)) {
fs.mkdirSync(`${agamaDir}/shepherd/pin`);
if (fs.existsSync(`${iguanaDir}/shepherd/pin`)) {
shepherd.log(`created pin folder at ${iguanaDir}/shepherd/pin`);
shepherd.writeLog(`create pin folder at ${iguanaDir}/shepherd/pin`);
if (fs.existsSync(`${agamaDir}/shepherd/pin`)) {
shepherd.log(`created pin folder at ${agamaDir}/shepherd/pin`);
shepherd.writeLog(`create pin folder at ${agamaDir}/shepherd/pin`);
}
} else {
shepherd.log('shepherd/pin folder already exists');
@ -973,7 +877,7 @@ shepherd.post('/encryptkey', function(req, res, next) {
const _pin = req.body.key;
const _pinTest = _pin.match('^(?=.*[A-Z])(?=.*[^<>{}\"/|;:.,~!?@#$%^=&*\\]\\\\()\\[_+]*$)(?=.*[0-9])(?=.*[a-z]).{8}$');
fs.writeFile(`${iguanaDir}/shepherd/pin/${req.body.pubkey}.pin`, encryptedString, function(err) {
fs.writeFile(`${agamaDir}/shepherd/pin/${req.body.pubkey}.pin`, encryptedString, function(err) {
if (err) {
shepherd.log('error writing pin file');
}
@ -1011,8 +915,8 @@ shepherd.post('/encryptkey', function(req, res, next) {
shepherd.post('/decryptkey', function(req, res, next) {
if (req.body.key &&
req.body.pubkey) {
if (fs.existsSync(`${iguanaDir}/shepherd/pin/${req.body.pubkey}.pin`)) {
fs.readFile(`${iguanaDir}/shepherd/pin/${req.body.pubkey}.pin`, 'utf8', function(err, data) {
if (fs.existsSync(`${agamaDir}/shepherd/pin/${req.body.pubkey}.pin`)) {
fs.readFile(`${agamaDir}/shepherd/pin/${req.body.pubkey}.pin`, 'utf8', function(err, data) {
if (err) {
const errorObj = {
msg: 'error',
@ -1061,8 +965,8 @@ shepherd.post('/decryptkey', function(req, res, next) {
});
shepherd.get('/getpinlist', function(req, res, next) {
if (fs.existsSync(`${iguanaDir}/shepherd/pin`)) {
fs.readdir(`${iguanaDir}/shepherd/pin`, function(err, items) {
if (fs.existsSync(`${agamaDir}/shepherd/pin`)) {
fs.readdir(`${agamaDir}/shepherd/pin`, function(err, items) {
let _pins = [];
for (let i = 0; i < items.length; i++) {
@ -1096,6 +1000,7 @@ shepherd.get('/getpinlist', function(req, res, next) {
res.end(JSON.stringify(errorObj));
}
});
/**
* Promise based download file method
*/
@ -1154,7 +1059,6 @@ const localBinLocation = {
};
const latestBins = {
win32: [
'iguana.exe',
'komodo-cli.exe',
'komodod.exe',
'libcrypto-1_1.dll',
@ -1168,7 +1072,6 @@ const latestBins = {
'pthreadvc2.dll',
],
darwin: [
'iguana',
'komodo-cli',
'komodod',
'libgcc_s.1.dylib',
@ -1177,10 +1080,9 @@ const latestBins = {
'libstdc++.6.dylib', // encode %2B
],
linux: [
'iguana',
'komodo-cli',
'komodod',
]
],
};
let binsToUpdate = [];
@ -1227,7 +1129,7 @@ shepherd.get('/update/bins/check', function(req, res, next) {
}
if (i === latestBins[_os].length - 1) {
cache.io.emit('patch', {
shepherd.io.emit('patch', {
patch: {
type: 'bins-check',
status: 'done',
@ -1263,7 +1165,7 @@ shepherd.get('/update/bins', function(req, res, next) {
localFile: `${rootLocation}${localBinLocation[_os]}patch/${binsToUpdate[i].name}`,
onProgress: function(received, total) {
const percentage = (received * 100) / total;
cache.io.emit('patch', {
shepherd.io.emit('patch', {
msg: {
type: 'bins-update',
status: 'progress',
@ -1281,7 +1183,7 @@ shepherd.get('/update/bins', function(req, res, next) {
shepherd.log('compare dl file size');
if (localBinSize === binsToUpdate[i].rSize) {
cache.io.emit('patch', {
shepherd.io.emit('patch', {
msg: {
type: 'bins-update',
file: binsToUpdate[i].name,
@ -1290,7 +1192,7 @@ shepherd.get('/update/bins', function(req, res, next) {
});
shepherd.log(`file ${binsToUpdate[i].name} succesfully downloaded`);
} else {
cache.io.emit('patch', {
shepherd.io.emit('patch', {
msg: {
type: 'bins-update',
file: binsToUpdate[i].name,
@ -1324,13 +1226,13 @@ shepherd.updateAgama = function() {
downloadFile({
remoteFile: 'https://github.com/pbca26/dl-test/raw/master/patch.zip',
localFile: rootLocation + 'patch.zip',
localFile: `${rootLocation}patch.zip`,
onProgress: function(received, total) {
const percentage = (received * 100) / total;
if (Math.floor(percentage) % 5 === 0 ||
Math.floor(percentage) % 10 === 0) {
shepherd.log(`patch ${percentage}% | ${received} bytes out of ${total} bytes.`);
cache.io.emit('patch', {
shepherd.io.emit('patch', {
msg: {
status: 'progress',
type: 'ui',
@ -1362,7 +1264,7 @@ shepherd.updateAgama = function() {
zip.extractAllTo(/*target path*/rootLocation + (shepherd.appConfig.dev ? '/patch' : ''), /*overwrite*/true);
// TODO: extract files in chunks
cache.io.emit('patch', {
shepherd.io.emit('patch', {
msg: {
type: 'ui',
status: 'done',
@ -1370,7 +1272,7 @@ shepherd.updateAgama = function() {
});
fs.unlinkSync(`${rootLocation}patch.zip`);
} else {
cache.io.emit('patch', {
shepherd.io.emit('patch', {
msg: {
type: 'ui',
status: 'error',
@ -1459,8 +1361,8 @@ shepherd.get('/unpack', function(req, res, next) {
*
*/
shepherd.get('/coinslist', function(req, res, next) {
if (fs.existsSync(`${iguanaDir}/shepherd/coinslist.json`)) {
fs.readFile(`${iguanaDir}/shepherd/coinslist.json`, 'utf8', function(err, data) {
if (fs.existsSync(`${agamaDir}/shepherd/coinslist.json`)) {
fs.readFile(`${agamaDir}/shepherd/coinslist.json`, 'utf8', function(err, data) {
if (err) {
const errorObj = {
msg: 'error',
@ -1492,7 +1394,7 @@ shepherd.get('/coinslist', function(req, res, next) {
* params: payload
*/
shepherd.post('/guilog', function(req, res, next) {
const logLocation = `${iguanaDir}/shepherd`;
const logLocation = `${agamaDir}/shepherd`;
if (!guiLog[shepherd.appSessionHash]) {
guiLog[shepherd.appSessionHash] = {};
@ -1532,8 +1434,8 @@ shepherd.post('/guilog', function(req, res, next) {
shepherd.get('/getlog', function(req, res, next) {
const logExt = req.query.type === 'txt' ? 'txt' : 'json';
if (fs.existsSync(`${iguanaDir}/shepherd/agamalog.${logExt}`)) {
fs.readFile(`${iguanaDir}/shepherd/agamalog.${logExt}`, 'utf8', function(err, data) {
if (fs.existsSync(`${agamaDir}/shepherd/agamalog.${logExt}`)) {
fs.readFile(`${agamaDir}/shepherd/agamalog.${logExt}`, 'utf8', function(err, data) {
if (err) {
const errorObj = {
msg: 'error',
@ -1575,7 +1477,7 @@ shepherd.post('/coinslist', function(req, res, next) {
res.end(JSON.stringify(errorObj));
} else {
fs.writeFile(`${cache.iguanaDir}/shepherd/coinslist.json`, JSON.stringify(_payload), function(err) {
fs.writeFile(`${agamaDir}/shepherd/coinslist.json`, JSON.stringify(_payload), function(err) {
if (err) {
const errorObj = {
msg: 'error',
@ -1808,9 +1710,9 @@ shepherd.post('/appconf/reset', function(req, res, next) {
});
shepherd.saveLocalAppConf = function(appSettings) {
let appConfFileName = `${iguanaDir}/config.json`;
let appConfFileName = `${agamaDir}/config.json`;
_fs.access(iguanaDir, fs.constants.R_OK, function(err) {
_fs.access(agamaDir, fs.constants.R_OK, function(err) {
if (!err) {
const FixFilePermissions = function() {
@ -1844,8 +1746,8 @@ shepherd.saveLocalAppConf = function(appSettings) {
fsnode.chmodSync(appConfFileName, '0666');
setTimeout(function() {
shepherd.log(result);
shepherd.log(`app conf.json file is created successfully at: ${iguanaConfsDir}`);
shepherd.writeLog(`app conf.json file is created successfully at: ${iguanaConfsDir}`);
shepherd.log(`app conf.json file is created successfully at: ${agamaDir}`);
shepherd.writeLog(`app conf.json file is created successfully at: ${agamaDir}`);
resolve(result);
}, 2000);
});
@ -1858,8 +1760,8 @@ shepherd.saveLocalAppConf = function(appSettings) {
}
shepherd.loadLocalConfig = function() {
if (fs.existsSync(`${iguanaDir}/config.json`)) {
let localAppConfig = fs.readFileSync(`${iguanaDir}/config.json`, 'utf8');
if (fs.existsSync(`${agamaDir}/config.json`)) {
let localAppConfig = fs.readFileSync(`${agamaDir}/config.json`, 'utf8');
shepherd.log('app config set from local file');
shepherd.writeLog('app config set from local file');
@ -1910,20 +1812,17 @@ shepherd.loadLocalConfig = function() {
shepherd.appConfig = shepherd.loadLocalConfig();
shepherd.log(`iguana dir: ${iguanaDir}`);
shepherd.log(`iguana bin: ${iguanaBin}`);
shepherd.log(`agama dir: ${agamaDir}`);
shepherd.log('--------------------------')
shepherd.log(`iguana dir: ${komododBin}`);
shepherd.log(`iguana bin: ${komodoDir}`);
shepherd.writeLog(`iguana dir: ${iguanaDir}`);
shepherd.writeLog(`iguana bin: ${iguanaBin}`);
shepherd.writeLog(`iguana dir: ${komododBin}`);
shepherd.writeLog(`iguana bin: ${komodoDir}`);
// END IGUANA FILES AND CONFIG SETTINGS
shepherd.log(`komodo dir: ${komododBin}`);
shepherd.log(`komodo bin: ${komodoDir}`);
shepherd.writeLog(`agama dir: ${agamaDir}`);
shepherd.writeLog(`komodo dir: ${komododBin}`);
shepherd.writeLog(`komodo bin: ${komodoDir}`);
// default route
shepherd.get('/', function(req, res, next) {
res.send('Iguana app server');
res.send('Agama app server');
});
/*
@ -1953,248 +1852,20 @@ shepherd.get('/appinfo', function(req, res, next) {
res.send(obj);
});
shepherd.dumpCacheBeforeExit = function() {
cache.dumpCacheBeforeExit();
}
var cache = require('./cache');
var mock = require('./mock');
// expose sockets obj
shepherd.setIO = function(io) {
shepherd.io = io;
cache.setVar('io', io);
cache.setVar('shepherd', shepherd);
};
shepherd.setVar = function(_name, _body) {
shepherd[_name] = _body;
};
cache.setVar('iguanaDir', iguanaDir);
cache.setVar('appConfig', shepherd.appConfig);
// fetch sync only forks info
shepherd.getSyncOnlyForksInfo = function() {
async.forEachOf(iguanaInstanceRegistry, function(data, port) {
if (iguanaInstanceRegistry[port].mode.indexOf('/sync') > -1) {
syncOnlyIguanaInstanceInfo[port] = {};
request({
url: `http://localhost:${port}/api/bitcoinrpc/getinfo?userpass=tmpIgRPCUser@${shepherd.appSessionHash}`,
method: 'GET'
}, function(error, response, body) {
if (response &&
response.statusCode &&
response.statusCode === 200) {
// console.log(body);
try {
syncOnlyIguanaInstanceInfo[port].getinfo = JSON.parse(body);
} catch(e) {}
} else {
// TODO: error
}
});
request({
url: `http://localhost:${port}/api/SuperNET/activehandle?userpass=${shepherd.appSessionHash}`,
method: 'GET'
}, function(error, response, body) {
if (response &&
response.statusCode &&
response.statusCode === 200) {
// console.log(body);
try {
syncOnlyIguanaInstanceInfo[port].activehandle = JSON.parse(body);
} catch(e) {}
} else {
// TODO: error
}
});
syncOnlyIguanaInstanceInfo[port].registry = iguanaInstanceRegistry[port];
}
});
}
/*
* type: GET
*
*/
shepherd.get('/forks/info/start', function(req, res, next) {
const successObj = {
msg: 'success',
result: 'started',
};
res.end(JSON.stringify(successObj));
shepherd.getSyncOnlyForksInfo();
});
/*
* type: GET
*
*/
shepherd.get('/forks/info/show', function(req, res, next) {
const successObj = {
msg: 'success',
result: JSON.stringify(syncOnlyIguanaInstanceInfo),
};
res.end(JSON.stringify(successObj));
});
/*
* type: GET
*
*/
shepherd.get('/forks/restart', function(req, res, next) {
const _pmid = req.query.pmid;
pm2.connect(function(err) {
if (err) {
shepherd.error(err);
}
pm2.restart(_pmid, function(err, ret) {
if (err) {
shepherd.error(err);
}
pm2.disconnect();
const successObj = {
msg: 'success',
result: 'restarted',
};
shepherd.writeLog(`iguana fork pmid ${_pmid} restarted`);
res.end(JSON.stringify(successObj));
});
});
});
/*
* type: GET
*
*/
shepherd.get('/forks/stop', function(req, res, next) {
const _pmid = req.query.pmid;
pm2.connect(function(err) {
if (err) {
shepherd.error(err);
}
pm2.stop(_pmid, function(err, ret) {
if (err) {
shepherd.error(err);
}
pm2.disconnect();
const successObj = {
msg: 'success',
result: 'stopped',
};
shepherd.writeLog(`iguana fork pmid ${_pmid} stopped`);
res.end(JSON.stringify(successObj));
});
});
});
/*
* type: GET
*
*/
shepherd.get('/forks', function(req, res, next) {
const successObj = {
msg: 'success',
result: iguanaInstanceRegistry,
};
res.end(JSON.stringify(successObj));
});
/*
* type: POST
* params: name
*/
shepherd.post('/forks', function(req, res, next) {
const mode = req.body.mode;
const coin = req.body.coin;
const port = shepherd.appConfig.iguanaCorePort;
portscanner.findAPortNotInUse(port, port + 100, '127.0.0.1', function(error, _port) {
pm2.connect(true, function(err) { //start up pm2 god
if (err) {
shepherd.error(err);
process.exit(2);
}
shepherd.log(`iguana core fork port ${_port}`);
shepherd.writeLog(`iguana core fork port ${_port}`);
pm2.start({
script: iguanaBin, // path to binary
name: `IGUANA ${_port} ${mode} / ${coin}`,
exec_mode : 'fork',
args: [`-port=${_port}`],
cwd: iguanaDir //set correct iguana directory
}, function(err, apps) {
if (apps &&
apps[0] &&
apps[0].process &&
apps[0].process.pid) {
iguanaInstanceRegistry[_port] = {
mode: mode,
coin: coin,
pid: apps[0].process && apps[0].process.pid,
pmid: apps[0].pm2_env.pm_id,
};
cache.setVar('iguanaInstances', iguanaInstanceRegistry);
const successObj = {
msg: 'success',
result: _port,
};
res.end(JSON.stringify(successObj));
} else {
const errorObj = {
msg: 'success',
error: 'iguana start error',
};
res.end(JSON.stringify(errorObj));
}
// get sync only forks info
if (syncOnlyInstanceInterval === -1) {
setTimeout(function() {
shepherd.getSyncOnlyForksInfo();
}, 5000);
setInterval(function() {
shepherd.getSyncOnlyForksInfo();
}, 20000);
}
pm2.disconnect(); // Disconnect from PM2
if (err) {
shepherd.writeLog(`iguana fork error: ${err}`);
shepherd.log(`iguana fork error: ${err}`);
// throw err;
}
});
});
});
});
/*
* type: GET
*
*/
shepherd.get('/InstantDEX/allcoins', function(req, res, next) {
// TODO: if only native return obj
// else query main iguana instance and return combined response
// http://localhost:7778/api/InstantDEX/allcoins?userpass=tmpIgRPCUser@1234
let successObj;
let nativeCoindList = [];
@ -2202,33 +1873,11 @@ shepherd.get('/InstantDEX/allcoins', function(req, res, next) {
nativeCoindList.push(key === 'komodod' ? 'KMD' : key);
}
if (Object.keys(iguanaInstanceRegistry).length) {
// call to iguana
request({
url: `http://localhost:${shepherd.appConfig.iguanaCorePort}/api/InstantDEX/allcoins?userpass=${req.query.userpass}`,
method: 'GET'
}, function(error, response, body) {
if (response &&
response.statusCode &&
response.statusCode === 200) {
const _body = JSON.parse(body);
_body.native = nativeCoindList;
shepherd.log(_body);
} else {
shepherd.log('main iguana instance is not ready yet');
}
res.send(body);
});
} else {
successObj = {
native: nativeCoindList,
basilisk: [],
full: [],
};
successObj = {
native: nativeCoindList,
};
res.end(JSON.stringify(successObj));
}
res.end(JSON.stringify(successObj));
});
/*
@ -2236,93 +1885,17 @@ shepherd.get('/InstantDEX/allcoins', function(req, res, next) {
*
*/
shepherd.get('/SuperNET/activehandle', function(req, res, next) { // not finished
// TODO: if only native return obj
// else query main iguana instance and return combined response
// http://localhost:7778/api/SuperNET/activehandle?userpass=tmpIgRPCUser@1234
let successObj;
if (Object.keys(iguanaInstanceRegistry).length) {
// call to iguana
request({
url: `http://localhost:${shepherd.appConfig.iguanaCorePort}/api/SuperNET/activehandle?userpass=${req.query.userpass}`,
method: 'GET'
}, function(error, response, body) {
if (response &&
response.statusCode &&
response.statusCode === 200) {
shepherd.log(body);
} else {
shepherd.log('main iguana instance is not ready yet');
}
res.send(body);
});
} else {
successObj = {
pubkey: 'nativeonly',
result: 'success',
handle: '',
status: Object.keys(coindInstanceRegistry).length ? 'unlocked' : 'locked',
duration: 2507830,
};
res.end(JSON.stringify(successObj));
}
});
/*
* type: GET
* params: pubkey
*/
shepherd.get('/cache', function(req, res, next) {
cache.get(req, res, next);
});
/*
* type: GET
* params: filename
*/
shepherd.get('/groom', function(req, res, next) {
cache.groomGet(req, res, next);
})
/*
* type: DELETE
* params: filename
*/
shepherd.delete('/groom', function(req, res, next) {
cache.groomDelete(req, res, next);
});
/*
* type: POST
* params: filename, payload
*/
shepherd.post('/groom', function(req, res, next) {
cache.groomPost(req, res, next);
});
/*
* type: GET
* params: userpass, pubkey, skip
*/
shepherd.get('/cache-all', function(req, res, next) {
cache.all(req, res, next);
});
/*
* type: GET
* params: userpass, pubkey, coin, address, skip
*/
shepherd.get('/cache-one', function(req, res, next) {
cache.one(req, res, next);
});
successObj = {
pubkey: 'nativeonly',
result: 'success',
handle: '',
status: Object.keys(coindInstanceRegistry).length ? 'unlocked' : 'locked',
duration: 2507830,
};
/*
* type: GET
*/
shepherd.get('/mock', function(req, res, next) {
mock.get(req, res, next);
res.end(JSON.stringify(successObj));
});
/*
@ -2348,9 +1921,7 @@ shepherd.post('/debuglog', function(req, res) {
komodoDir = path.normalize(komodoDir);
}
if (_herd === 'iguana') {
_location = iguanaDir;
} else if (_herd === 'komodo') {
if (_herd === 'komodo') {
_location = komodoDir;
}
@ -2560,6 +2131,7 @@ shepherd.post('/getconf', function(req, res) {
/*
* type: GET
* params: coin, type
* TODO: reoganize to work with coind
*/
shepherd.get('/kick', function(req, res, next) {
const _coin = req.query.coin;
@ -2744,86 +2316,6 @@ function herder(flock, data) {
shepherd.log('it is undefined');
}
if (flock === 'iguana') {
shepherd.log('iguana flock selected...');
shepherd.log(`selected data: ${data}`);
shepherd.writeLog('iguana flock selected...');
shepherd.writeLog(`selected data: ${data}`);
// MAKE SURE IGUANA DIR IS THERE FOR USER
mkdirp(iguanaDir, function(err) {
if (err)
shepherd.error(err);
else
fs.readdir(iguanaDir, (err, files) => {
files.forEach(file => {
//console.log(file);
});
})
});
// ADD SHEPHERD FOLDER
mkdirp(`${iguanaDir}/shepherd`, function(err) {
if (err)
console.error(err);
else
fs.readdir(iguanaDir, (err, files) => {
files.forEach(file => {
//console.log(file);
});
})
});
// COPY CONFS DIR WITH PEERS FILE TO IGUANA DIR, AND KEEP IT IN SYNC
fs.copy(iguanaConfsDirSrc, iguanaConfsDir, function(err) {
if (err)
return shepherd.error(err);
shepherd.log(`confs files copied successfully at: ${iguanaConfsDir}`);
shepherd.writeLog(`confs files copied successfully at: ${iguanaConfsDir}`);
});
pm2.connect(true,function(err) { //start up pm2 god
if (err) {
shepherd.error(err);
process.exit(2);
}
shepherd.log(`iguana core port ${shepherd.appConfig.iguanaCorePort}`);
shepherd.writeLog(`iguana core port ${shepherd.appConfig.iguanaCorePort}`);
pm2.start({
script: iguanaBin, // path to binary
name: 'IGUANA',
exec_mode : 'fork',
args: [`-port=${shepherd.appConfig.iguanaCorePort}`],
cwd: iguanaDir // set correct iguana directory
}, function(err, apps) {
if (apps[0] &&
apps[0].process &&
apps[0].process.pid) {
iguanaInstanceRegistry[shepherd.appConfig.iguanaCorePort] = {
mode: 'main',
coin: 'none',
pid: apps[0].process.pid,
pmid: apps[0].pm2_env.pm_id,
};
shepherd.writeLog(`iguana core started at port ${shepherd.appConfig.iguanaCorePort} pid ${apps[0].process.pid}`);
} else {
shepherd.writeLog(`unable to start iguana core at port ${shepherd.appConfig.iguanaCorePort}`);
shepherd.log(`unable to start iguana core at port ${shepherd.appConfig.iguanaCorePort}`);
}
pm2.disconnect(); // Disconnect from PM2
if (err) {
shepherd.writeLog(`iguana core port ${shepherd.appConfig.iguanaCorePort}`);
shepherd.log(`iguana fork error: ${err}`);
// throw err;
}
});
});
}
// TODO: notify gui that reindex/rescan param is used to reflect on the screen
// asset chain debug.log unlink
if (flock === 'komodod') {
@ -3403,19 +2895,18 @@ shepherd.appInfo = function() {
const sysInfo = shepherd.SystemInfo();
const releaseInfo = shepherd.appBasicInfo;
const dirs = {
iguanaDir,
iguanaBin,
agamaDir,
komodoDir,
komododBin,
configLocation: `${iguanaDir}/config.json`,
cacheLocation: `${iguanaDir}/shepherd`,
configLocation: `${agamaDir}/config.json`,
cacheLocation: `${agamaDir}/shepherd`,
};
return {
sysInfo,
releaseInfo,
dirs,
appSession: shepherd.appSessionHash
appSession: shepherd.appSessionHash,
};
}

2
version

@ -1,3 +1,3 @@
version=0.2.0.22a
version=0.2.0.23a
type=e-beta
minversion=0.2.0.2

2
version_build

@ -1 +1 @@
0.2.0.22a-beta
0.2.0.23a-beta

Loading…
Cancel
Save