diff --git a/README.md b/README.md index d7dba05..e16f974 100644 --- a/README.md +++ b/README.md @@ -374,7 +374,7 @@ BTC: 1KRotMnQpxu3sePQnsVLRy3EraRFYfJQFR Credits ------- * [vekexasia](https://github.com/vekexasia) - co-developer & great tester -* [TheSeven](https://github.com/TheSeven) - answering an absurd amount of my questions and being a very helpful and king gentleman +* [TheSeven](https://github.com/TheSeven) - answering an absurd amount of my questions and being a very helpful gentleman * Those that contributed to [node-stratum](/zone117x/node-stratum) diff --git a/libs/api.js b/libs/api.js new file mode 100644 index 0000000..84636c4 --- /dev/null +++ b/libs/api.js @@ -0,0 +1 @@ +//create the stats object in here. then let the website use this object. that way we can have a config for stats and website separate :D \ No newline at end of file diff --git a/libs/paymentProcessor.js b/libs/paymentProcessor.js index ab1bde7..087b02c 100644 --- a/libs/paymentProcessor.js +++ b/libs/paymentProcessor.js @@ -335,7 +335,7 @@ function SetupForPool(logger, poolOptions){ ); finalRedisCommands.push(deleteRoundsCommand); - finalRedisCommands.push(['hincrby', coin + '_stats', 'totalPaid', toBePaid]); + finalRedisCommands.push(['hincrby', coin + '_stats', 'totalPaid', toBePaid / magnitude]); callback(null, magnitude, workerPayments, finalRedisCommands); @@ -356,18 +356,21 @@ function SetupForPool(logger, poolOptions){ console.log(JSON.stringify(workerPayments, null, 4)); console.log(JSON.stringify(sendManyCmd, null, 4)); - //return callback('not yet...'); daemon.cmd('sendmany', sendManyCmd, function(results){ if (results[0].error){ callback('done - error with sendmany ' + JSON.stringify(results[0].error)); return; } + + //This does the final all-or-nothing atom transaction if block deamon sent payments redisClient.multi(finalRedisCommands).exec(function(error, results){ if (error){ callback('done - error with final redis commands for cleaning up ' + JSON.stringify(error)); return; } - callback(null, 'Payments sent'); + var totalWorkers = Object.keys(workerPayments).length; + var totalAmount = Object.keys(workerPayments).reduce(function(p, c){return p + workerPayments[c]}, 0); + callback(null, 'Payments sent, a total of ' + totalAmount + ' was sent to ' + totalWorkers); }); }); diff --git a/libs/stats.js b/libs/stats.js index 0493e20..4fe73a9 100644 --- a/libs/stats.js +++ b/libs/stats.js @@ -35,26 +35,37 @@ module.exports = function(logger, portalConfig, poolConfigs){ this.stats = {}; + this.statsString = ''; this.getStats = function(callback){ - var allCoinStats = []; + var allCoinStats = {}; async.each(redisClients, function(client, callback){ var windowTime = (((Date.now() / 1000) - portalConfig.website.hashrateWindow) | 0).toString(); var redisCommands = []; - var commandsPerCoin = 4; - //Clear out old hashrate stats for each coin from redis - client.coins.forEach(function(coin){ - redisCommands.push(['zremrangebyscore', coin + '_hashrate', '-inf', '(' + windowTime]); - redisCommands.push(['zrangebyscore', coin + '_hashrate', windowTime, '+inf']); - redisCommands.push(['hgetall', coin + '_stats']); - redisCommands.push(['scard', coin + '_blocksPending']); + + var redisComamndTemplates = [ + ['zremrangebyscore', '_hashrate', '-inf', '(' + windowTime], + ['zrangebyscore', '_hashrate', windowTime, '+inf'], + ['hgetall', '_stats'], + ['scard', '_blocksPending'], + ['scard', '_blocksConfirmed'], + ['scard', '_blocksOrphaned'] + ]; + + var commandsPerCoin = redisComamndTemplates.length; + + client.coins.map(function(coin){ + redisComamndTemplates.map(function(t){ + var clonedTemplates = t.slice(0); + clonedTemplates[1] = coin + clonedTemplates [1]; + redisCommands.push(clonedTemplates); + }); }); - client.client.multi(redisCommands).exec(function(err, replies){ if (err){ console.log('error with getting hashrate stats ' + JSON.stringify(err)); @@ -62,14 +73,20 @@ module.exports = function(logger, portalConfig, poolConfigs){ } else{ for(var i = 0; i < replies.length; i += commandsPerCoin){ + var coinName = client.coins[i / commandsPerCoin | 0]; var coinStats = { - coinName: client.coins[i / commandsPerCoin | 0], + name: coinName, + symbol: poolConfigs[coinName].coin.symbol, + algorithm: poolConfigs[coinName].coin.algorithm, hashrates: replies[i + 1], poolStats: replies[i + 2], - poolPendingBlocks: replies[i + 3] + blocks: { + pending: replies[i + 3], + confirmed: replies[i + 4], + orphaned: replies[i + 5] + } }; - allCoinStats.push(coinStats) - + allCoinStats[coinStats.name] = (coinStats); } callback(); } @@ -89,7 +106,8 @@ module.exports = function(logger, portalConfig, poolConfigs){ pools: allCoinStats }; - allCoinStats.forEach(function(coinStats){ + Object.keys(allCoinStats).forEach(function(coin){ + var coinStats = allCoinStats[coin]; coinStats.workers = {}; coinStats.shares = 0; coinStats.hashrates.forEach(function(ins){ @@ -102,14 +120,18 @@ module.exports = function(logger, portalConfig, poolConfigs){ else coinStats.workers[worker] = workerShares }); - var shareMultiplier = algoMultipliers[poolConfigs[coinStats.coinName].coin.algorithm]; + var shareMultiplier = algoMultipliers[coinStats.algorithm]; var hashratePre = shareMultiplier * coinStats.shares / portalConfig.website.hashrateWindow; coinStats.hashrate = hashratePre / 1e3 | 0; delete coinStats.hashrates; + delete coinStats.shares; portalStats.global.hashrate += coinStats.hashrate; portalStats.global.workers += Object.keys(coinStats.workers).length; }); + _this.stats = portalStats; + _this.statsString = JSON.stringify(portalStats); + console.log(JSON.stringify(portalStats, null, 4)); callback(); }); diff --git a/libs/website.js b/libs/website.js index da3ba4a..82a6834 100644 --- a/libs/website.js +++ b/libs/website.js @@ -183,6 +183,9 @@ module.exports = function(logger){ res.end(requestedPage); return; } + case 'stats': + res.end(portalStats.statsString); + return; case 'live_stats': res.writeHead(200, { 'Content-Type': 'text/event-stream',