|
|
@ -3,63 +3,91 @@ const fs = require('fs-extra'), |
|
|
|
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) { |
|
|
|
console.log('dumping cache before exit'); |
|
|
|
fs.writeFileSync(cache.iguanaDir + '/shepherd/cache-' + inMemPubkey + '.json', JSON.stringify(inMemCache), 'utf8'); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
cache.get = function(req, res, next) { |
|
|
|
var pubkey = req.query.pubkey; |
|
|
|
const pubkey = req.query.pubkey; |
|
|
|
|
|
|
|
if (pubkey) { |
|
|
|
if (fs.existsSync(cache.iguanaDir + '/shepherd/cache-' + pubkey + '.json')) { |
|
|
|
fs.readFile(cache.iguanaDir + '/shepherd/cache-' + pubkey + '.json', 'utf8', function (err, data) { |
|
|
|
if (err) { |
|
|
|
var errorObj = { |
|
|
|
'msg': 'error', |
|
|
|
'result': err |
|
|
|
}; |
|
|
|
inMemPubkey = pubkey; |
|
|
|
|
|
|
|
res.end(JSON.stringify(errorObj)); |
|
|
|
} else { |
|
|
|
try { |
|
|
|
var parsedJSON = JSON.parse(data), |
|
|
|
successObj = { |
|
|
|
'msg': 'success', |
|
|
|
'result': parsedJSON |
|
|
|
}; |
|
|
|
|
|
|
|
res.end(JSON.stringify(successObj)); |
|
|
|
} catch (e) { |
|
|
|
console.log(e); |
|
|
|
if (e.toString().indexOf('at position') > -1) { |
|
|
|
const errorPos = e.toString().split(' '); |
|
|
|
//console.log(errorPos[errorPos.length - 1]);
|
|
|
|
//JSON.parse(data.substring(0, errorPos[errorPos.length - 1]));
|
|
|
|
console.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)); |
|
|
|
console.log('attempting to recover JSON data'); |
|
|
|
fs.writeFile(cache.iguanaDir + '/shepherd/cache-' + pubkey + '.json', data.substring(0, errorPos[errorPos.length - 1]), function(err) { |
|
|
|
var successObj = { |
|
|
|
'msg': 'success', |
|
|
|
'result': data.substring(0, errorPos[errorPos.length - 1]) |
|
|
|
}; |
|
|
|
|
|
|
|
res.end(JSON.stringify(successObj)); |
|
|
|
}); |
|
|
|
if (!inMemCache) { |
|
|
|
console.log('serving cache from disk'); |
|
|
|
|
|
|
|
if (fs.existsSync(cache.iguanaDir + '/shepherd/cache-' + pubkey + '.json')) { |
|
|
|
fs.readFile(cache.iguanaDir + '/shepherd/cache-' + pubkey + '.json', 'utf8', function (err, data) { |
|
|
|
if (err) { |
|
|
|
const errorObj = { |
|
|
|
'msg': 'error', |
|
|
|
'result': err |
|
|
|
}; |
|
|
|
|
|
|
|
res.end(JSON.stringify(errorObj)); |
|
|
|
} else { |
|
|
|
try { |
|
|
|
const parsedJSON = JSON.parse(data), |
|
|
|
successObj = { |
|
|
|
'msg': 'success', |
|
|
|
'result': parsedJSON |
|
|
|
}; |
|
|
|
|
|
|
|
inMemCache = parsedJSON; |
|
|
|
res.end(JSON.stringify(successObj)); |
|
|
|
} catch (e) { |
|
|
|
console.log('JSON parse error while reading cache data from disk:'); |
|
|
|
console.log(e); |
|
|
|
if (e.toString().indexOf('at position') > -1) { |
|
|
|
const errorPos = e.toString().split(' '); |
|
|
|
|
|
|
|
console.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)); |
|
|
|
console.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 { |
|
|
|
var errorObj = { |
|
|
|
'msg': 'error', |
|
|
|
'result': 'no file with handle ' + pubkey |
|
|
|
const successObj = { |
|
|
|
'msg': 'success', |
|
|
|
'result': inMemCache |
|
|
|
}; |
|
|
|
|
|
|
|
res.end(JSON.stringify(errorObj)); |
|
|
|
res.end(JSON.stringify(successObj)); |
|
|
|
} |
|
|
|
} else { |
|
|
|
var errorObj = { |
|
|
|
const errorObj = { |
|
|
|
'msg': 'error', |
|
|
|
'result': 'no pubkey provided' |
|
|
|
}; |
|
|
@ -69,20 +97,20 @@ cache.get = function(req, res, next) { |
|
|
|
} |
|
|
|
|
|
|
|
cache.groomGet = function(req, res, next) { |
|
|
|
var _filename = req.query.filename; |
|
|
|
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) { |
|
|
|
var errorObj = { |
|
|
|
const errorObj = { |
|
|
|
'msg': 'error', |
|
|
|
'result': err |
|
|
|
}; |
|
|
|
|
|
|
|
res.end(JSON.stringify(errorObj)); |
|
|
|
} else { |
|
|
|
var successObj = { |
|
|
|
const successObj = { |
|
|
|
'msg': 'success', |
|
|
|
'result': data ? JSON.parse(data) : '' |
|
|
|
}; |
|
|
@ -91,7 +119,7 @@ cache.groomGet = function(req, res, next) { |
|
|
|
} |
|
|
|
}); |
|
|
|
} else { |
|
|
|
var errorObj = { |
|
|
|
const errorObj = { |
|
|
|
'msg': 'error', |
|
|
|
'result': 'no file with name ' + _filename |
|
|
|
}; |
|
|
@ -99,7 +127,7 @@ cache.groomGet = function(req, res, next) { |
|
|
|
res.end(JSON.stringify(errorObj)); |
|
|
|
} |
|
|
|
} else { |
|
|
|
var errorObj = { |
|
|
|
const errorObj = { |
|
|
|
'msg': 'error', |
|
|
|
'result': 'no file name provided' |
|
|
|
}; |
|
|
@ -109,20 +137,20 @@ cache.groomGet = function(req, res, next) { |
|
|
|
} |
|
|
|
|
|
|
|
cache.groomDelete = function(req, res, next) { |
|
|
|
var _filename = req.body.filename; |
|
|
|
const _filename = req.body.filename; |
|
|
|
|
|
|
|
if (_filename) { |
|
|
|
if (fs.existsSync(cache.iguanaDir + '/shepherd/cache-' + _filename + '.json')) { |
|
|
|
fs.unlink(cache.iguanaDir + '/shepherd/cache-' + _filename + '.json', function(err) { |
|
|
|
if (err) { |
|
|
|
var errorObj = { |
|
|
|
const errorObj = { |
|
|
|
'msg': 'error', |
|
|
|
'result': err |
|
|
|
}; |
|
|
|
|
|
|
|
res.end(JSON.stringify(errorObj)); |
|
|
|
} else { |
|
|
|
var successObj = { |
|
|
|
const successObj = { |
|
|
|
'msg': 'success', |
|
|
|
'result': 'deleted' |
|
|
|
}; |
|
|
@ -131,7 +159,7 @@ cache.groomDelete = function(req, res, next) { |
|
|
|
} |
|
|
|
}); |
|
|
|
} else { |
|
|
|
var errorObj = { |
|
|
|
const errorObj = { |
|
|
|
'msg': 'error', |
|
|
|
'result': 'no file with name ' + _filename |
|
|
|
}; |
|
|
@ -139,7 +167,7 @@ cache.groomDelete = function(req, res, next) { |
|
|
|
res.end(JSON.stringify(errorObj)); |
|
|
|
} |
|
|
|
} else { |
|
|
|
var errorObj = { |
|
|
|
const errorObj = { |
|
|
|
'msg': 'error', |
|
|
|
'result': 'no file name provided' |
|
|
|
}; |
|
|
@ -149,39 +177,47 @@ cache.groomDelete = function(req, res, next) { |
|
|
|
} |
|
|
|
|
|
|
|
cache.groomPost = function(req, res) { |
|
|
|
var _filename = req.body.filename, |
|
|
|
_payload = req.body.payload; |
|
|
|
const _filename = req.body.filename, |
|
|
|
_payload = req.body.payload; |
|
|
|
|
|
|
|
if (!cacheCallInProgress) { |
|
|
|
if (_filename) { |
|
|
|
if (!_payload) { |
|
|
|
var errorObj = { |
|
|
|
const errorObj = { |
|
|
|
'msg': 'error', |
|
|
|
'result': 'no payload provided' |
|
|
|
}; |
|
|
|
|
|
|
|
res.end(JSON.stringify(errorObj)); |
|
|
|
} else { |
|
|
|
fs.writeFile(cache.iguanaDir + '/shepherd/cache-' + _filename + '.json', _payload, function (err) { |
|
|
|
if (err) { |
|
|
|
var errorObj = { |
|
|
|
'msg': 'error', |
|
|
|
'result': err |
|
|
|
}; |
|
|
|
if (inMemCache) { |
|
|
|
inMemCache = JSON.parse(_payload); |
|
|
|
|
|
|
|
res.end(JSON.stringify(errorObj)); |
|
|
|
} else { |
|
|
|
var successObj = { |
|
|
|
'msg': 'success', |
|
|
|
'result': 'done' |
|
|
|
}; |
|
|
|
console.log('appending groom post to in mem cache'); |
|
|
|
} else { |
|
|
|
console.log('appending groom post to on disk cache'); |
|
|
|
|
|
|
|
res.end(JSON.stringify(successObj)); |
|
|
|
} |
|
|
|
}); |
|
|
|
fs.writeFile(cache.iguanaDir + '/shepherd/cache-' + _filename + '.json', _payload, function (err) { |
|
|
|
if (err) { |
|
|
|
const errorObj = { |
|
|
|
'msg': 'error', |
|
|
|
'result': err |
|
|
|
}; |
|
|
|
|
|
|
|
res.end(JSON.stringify(errorObj)); |
|
|
|
} else { |
|
|
|
const successObj = { |
|
|
|
'msg': 'success', |
|
|
|
'result': 'done' |
|
|
|
}; |
|
|
|
|
|
|
|
res.end(JSON.stringify(successObj)); |
|
|
|
} |
|
|
|
}); |
|
|
|
} |
|
|
|
} |
|
|
|
} else { |
|
|
|
var errorObj = { |
|
|
|
const errorObj = { |
|
|
|
'msg': 'error', |
|
|
|
'result': 'no file name provided' |
|
|
|
}; |
|
|
@ -189,7 +225,7 @@ cache.groomPost = function(req, res) { |
|
|
|
res.end(JSON.stringify(errorObj)); |
|
|
|
} |
|
|
|
} else { |
|
|
|
var errorObj = { |
|
|
|
const errorObj = { |
|
|
|
'msg': 'error', |
|
|
|
'result': 'another job is in progress' |
|
|
|
}; |
|
|
@ -199,11 +235,43 @@ cache.groomPost = function(req, res) { |
|
|
|
} |
|
|
|
|
|
|
|
var cacheCallInProgress = false, |
|
|
|
cacheGlobLifetime = 300; // sec
|
|
|
|
cacheGlobLifetime = 600; // sec
|
|
|
|
|
|
|
|
// TODO: reset calls' states on new /cache call start
|
|
|
|
var mock = require('./mock'); |
|
|
|
|
|
|
|
var callStack = {}, |
|
|
|
checkCallStack = function() { |
|
|
|
var total = 0; |
|
|
|
|
|
|
|
for (var coin in callStack) { |
|
|
|
total =+ callStack[coin]; |
|
|
|
} |
|
|
|
|
|
|
|
if (total / Object.keys(callStack).length === 1) { |
|
|
|
cache.dumpCacheBeforeExit(); |
|
|
|
/*fs.writeFile(cache.iguanaDir + '/shepherd/cache-' + pubkey + '.json', JSON.stringify(inMemCache), function(err) { |
|
|
|
if (err) { |
|
|
|
return console.log(err); |
|
|
|
} |
|
|
|
|
|
|
|
console.log('file ' + cache.iguanaDir + '/shepherd/cache-' + pubkey + '.json is updated'); |
|
|
|
});*/ |
|
|
|
cacheCallInProgress = false; |
|
|
|
cache.io.emit('messages', { |
|
|
|
'message': { |
|
|
|
'shepherd': { |
|
|
|
'method': 'cache-one', |
|
|
|
'status': 'done', |
|
|
|
'resp': 'success' |
|
|
|
} |
|
|
|
} |
|
|
|
}); |
|
|
|
// add timestamp to cache file
|
|
|
|
// writeCache(Date.now());
|
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
/* |
|
|
|
* type: GET |
|
|
|
* params: userpass, pubkey, coin, address, skip |
|
|
@ -213,12 +281,19 @@ cache.one = function(req, res, next) { |
|
|
|
cacheCallInProgress = false; |
|
|
|
} |
|
|
|
|
|
|
|
if (cacheCallInProgress) { |
|
|
|
checkCallStack(); |
|
|
|
} |
|
|
|
|
|
|
|
if (!cacheCallInProgress) { |
|
|
|
cache.dumpCacheBeforeExit(); |
|
|
|
fs.readFile(cache.iguanaDir + '/shepherd/cache-' + req.query.pubkey + '.json', 'utf8', function (err, data) { |
|
|
|
if (data) { |
|
|
|
inMemCache = JSON.parse(data); |
|
|
|
data = data.replace('waiting', 'failed'); |
|
|
|
fs.writeFile(cache.iguanaDir + '/shepherd/cache-' + req.query.pubkey + '.json', data, function(err) { |
|
|
|
}); |
|
|
|
/*fs.writeFile(cache.iguanaDir + '/shepherd/cache-' + req.query.pubkey + '.json', data, function(err) { |
|
|
|
});*/ |
|
|
|
cache.dumpCacheBeforeExit(); |
|
|
|
} |
|
|
|
}); |
|
|
|
// TODO: add check to allow only one cache call/sequence in progress
|
|
|
@ -244,7 +319,8 @@ cache.one = function(req, res, next) { |
|
|
|
outObj.timestamp = timeStamp; |
|
|
|
} |
|
|
|
|
|
|
|
fs.writeFile(cache.iguanaDir + '/shepherd/cache-' + pubkey + '.json', JSON.stringify(outObj), function(err) { |
|
|
|
inMemCache = outObj; |
|
|
|
/*fs.writeFile(cache.iguanaDir + '/shepherd/cache-' + pubkey + '.json', JSON.stringify(outObj), function(err) { |
|
|
|
if (err) { |
|
|
|
return console.log(err); |
|
|
|
} |
|
|
@ -253,30 +329,7 @@ cache.one = function(req, res, next) { |
|
|
|
if (timeStamp) { |
|
|
|
console.log('file ' + cache.iguanaDir + '/shepherd/cache-' + pubkey + '.json is timestamped'); |
|
|
|
} |
|
|
|
}); |
|
|
|
}, |
|
|
|
callStack = {}, |
|
|
|
checkCallStack = function() { |
|
|
|
var total = 0; |
|
|
|
|
|
|
|
for (var coin in callStack) { |
|
|
|
total =+ callStack[coin]; |
|
|
|
} |
|
|
|
|
|
|
|
if (total / Object.keys(callStack).length === 1) { |
|
|
|
cacheCallInProgress = false; |
|
|
|
cache.io.emit('messages', { |
|
|
|
'message': { |
|
|
|
'shepherd': { |
|
|
|
'method': 'cache-one', |
|
|
|
'status': 'done', |
|
|
|
'resp': 'success' |
|
|
|
} |
|
|
|
} |
|
|
|
}); |
|
|
|
// add timestamp to cache file
|
|
|
|
// writeCache(Date.now());
|
|
|
|
} |
|
|
|
});*/ |
|
|
|
}, |
|
|
|
checkTimestamp = function(dateToCheck) { |
|
|
|
var currentEpochTime = new Date(Date.now()) / 1000, |
|
|
@ -286,12 +339,13 @@ cache.one = function(req, res, next) { |
|
|
|
}, |
|
|
|
internalError = false; |
|
|
|
|
|
|
|
inMemPubkey = pubkey; |
|
|
|
callStack[coin] = 1; |
|
|
|
console.log(callsArray); |
|
|
|
console.log('iguana core port ' + iguanaCorePort); |
|
|
|
|
|
|
|
if (!sessionKey) { |
|
|
|
var errorObj = { |
|
|
|
const errorObj = { |
|
|
|
'msg': 'error', |
|
|
|
'result': 'no session key provided' |
|
|
|
}; |
|
|
@ -301,7 +355,7 @@ cache.one = function(req, res, next) { |
|
|
|
} |
|
|
|
|
|
|
|
if (!pubkey) { |
|
|
|
var errorObj = { |
|
|
|
const errorObj = { |
|
|
|
'msg': 'error', |
|
|
|
'result': 'no pubkey provided' |
|
|
|
}; |
|
|
@ -313,7 +367,6 @@ cache.one = function(req, res, next) { |
|
|
|
console.log('cache-one call started'); |
|
|
|
|
|
|
|
function fixJSON(data) { |
|
|
|
console.log(data); |
|
|
|
if (data && data.length) { |
|
|
|
try { |
|
|
|
var parsedJSON = JSON.parse(data); |
|
|
@ -338,9 +391,13 @@ cache.one = function(req, res, next) { |
|
|
|
} |
|
|
|
|
|
|
|
if (fs.existsSync(cache.iguanaDir + '/shepherd/cache-' + pubkey + '.json') && coin !== 'all') { |
|
|
|
var _file = fs.readFileSync(cache.iguanaDir + '/shepherd/cache-' + pubkey + '.json', 'utf8'); |
|
|
|
//outObj = _file ? JSON.parse(_file) : {};
|
|
|
|
outObj = fixJSON(_file); |
|
|
|
if (inMemCache) { |
|
|
|
outObj = inMemCache; |
|
|
|
} else { |
|
|
|
var _file = fs.readFileSync(cache.iguanaDir + '/shepherd/cache-' + pubkey + '.json', 'utf8'); |
|
|
|
//outObj = _file ? JSON.parse(_file) : {};
|
|
|
|
outObj = fixJSON(_file); |
|
|
|
} |
|
|
|
|
|
|
|
if (!outObj || !outObj.basilisk) { |
|
|
|
console.log('no local basilisk info'); |
|
|
@ -550,8 +607,10 @@ cache.one = function(req, res, next) { |
|
|
|
outObj.basilisk[coin].addresses = addrArray; |
|
|
|
console.log(addrArray); |
|
|
|
writeCache(); |
|
|
|
var addrCount = outObj.basilisk[coin].addresses ? outObj.basilisk[coin].addresses.length : 0; |
|
|
|
|
|
|
|
const addrCount = outObj.basilisk[coin].addresses ? outObj.basilisk[coin].addresses.length : 0; |
|
|
|
var callsArrayBTC = callsArray.length; |
|
|
|
|
|
|
|
if (callsArray.indexOf('getbalance') > - 1) { |
|
|
|
callsArrayBTC--; |
|
|
|
} |
|
|
@ -581,7 +640,7 @@ cache.one = function(req, res, next) { |
|
|
|
if (addresses) { |
|
|
|
parseAddresses(coin, addresses); |
|
|
|
} else { |
|
|
|
var tempUrl = 'http://' + cache.appConfig.host + ':' + cache.appConfig.iguanaCorePort /*iguanaCorePort*/ + '/api/bitcoinrpc/getaddressesbyaccount?userpass=' + sessionKey + '&coin=' + coin + '&account=*'; |
|
|
|
const tempUrl = 'http://' + cache.appConfig.host + ':' + cache.appConfig.iguanaCorePort /*iguanaCorePort*/ + '/api/bitcoinrpc/getaddressesbyaccount?userpass=' + sessionKey + '&coin=' + coin + '&account=*'; |
|
|
|
request({ |
|
|
|
url: mock ? 'http://localhost:17777/shepherd/mock?url=' + tempUrl : tempUrl, |
|
|
|
method: 'GET' |
|
|
@ -612,7 +671,7 @@ cache.one = function(req, res, next) { |
|
|
|
}); |
|
|
|
|
|
|
|
if (coin === 'all') { |
|
|
|
var tempUrl = 'http://' + cache.appConfig.host + ':' + /*iguanaCorePort*/ cache.appConfig.iguanaCorePort + '/api/InstantDEX/allcoins?userpass=' + sessionKey; |
|
|
|
const tempUrl = 'http://' + cache.appConfig.host + ':' + /*iguanaCorePort*/ cache.appConfig.iguanaCorePort + '/api/InstantDEX/allcoins?userpass=' + sessionKey; |
|
|
|
request({ |
|
|
|
url: mock ? 'http://localhost:17777/shepherd/mock?url=' + tempUrl : tempUrl, |
|
|
|
method: 'GET' |
|
|
|