added support for difficulty and blockreward

This commit is contained in:
Jerry Brady 2014-04-13 23:17:40 +00:00
parent 550b09767e
commit 93274f907b
1 changed files with 198 additions and 146 deletions

View File

@ -1,6 +1,7 @@
var async = require('async'); var async = require('async');
var Poloniex = require('./apiPoloniex.js'); var Poloniex = require('./apiPoloniex.js');
var Stratum = require('stratum-pool');
module.exports = function(logger){ module.exports = function(logger){
@ -19,25 +20,22 @@ module.exports = function(logger){
Object.keys(poolConfigs).forEach(function(coin){ Object.keys(poolConfigs).forEach(function(coin){
var poolConfig = poolConfigs[coin]; var poolConfig = poolConfigs[coin];
var algo = poolConfig.coin.algorithm; var algo = poolConfig.coin.algorithm;
if (!profitStatus.hasOwnProperty(algo)) { if (!profitStatus.hasOwnProperty(algo)) {
profitStatus[algo] = {}; profitStatus[algo] = {};
} }
var coinStatus = { var coinStatus = {
name: poolConfig.coin.name, name: poolConfig.coin.name,
symbol: poolConfig.coin.symbol, symbol: poolConfig.coin.symbol,
difficulty: 0, difficulty: 0,
reward: 0, reward: 0,
avgPrice: { BTC: 0, LTC: 0 }, prices: {},
avgDepth: { BTC: 0, LTC: 0 }, depths: {},
avgVolume: { BTC: 0, LTC: 0 }, volumes: {},
prices: {}, };
depths: {}, profitStatus[algo][poolConfig.coin.symbol] = coinStatus;
volumes: {}, profitSymbols[poolConfig.coin.symbol] = algo;
};
profitStatus[algo][poolConfig.coin.symbol] = coinStatus;
profitSymbols[poolConfig.coin.symbol] = algo;
}); });
@ -46,13 +44,13 @@ module.exports = function(logger){
// //
var isMoreThanOneCoin = false; var isMoreThanOneCoin = false;
Object.keys(profitStatus).forEach(function(algo){ Object.keys(profitStatus).forEach(function(algo){
if (Object.keys(profitStatus[algo]).length > 1) { if (Object.keys(profitStatus[algo]).length > 1) {
isMoreThanOneCoin = true; isMoreThanOneCoin = true;
} }
}); });
if (!isMoreThanOneCoin){ if (!isMoreThanOneCoin){
logger.debug(logSystem, 'Config', 'No alternative coins to switch to in current config, switching disabled.'); logger.debug(logSystem, 'Config', 'No alternative coins to switch to in current config, switching disabled.');
return; return;
} }
logger.debug(logSystem, 'profitStatus', JSON.stringify(profitStatus)); logger.debug(logSystem, 'profitStatus', JSON.stringify(profitStatus));
logger.debug(logSystem, 'profitStatus', JSON.stringify(profitSymbols)); logger.debug(logSystem, 'profitStatus', JSON.stringify(profitSymbols));
@ -63,143 +61,143 @@ module.exports = function(logger){
// //
var poloApi = new Poloniex( var poloApi = new Poloniex(
// 'API_KEY', // 'API_KEY',
// 'API_SECRET' // 'API_SECRET'
); );
// //
// market data collection from Poloniex // market data collection from Poloniex
// //
this.getProfitDataPoloniex = function(callback){ this.getProfitDataPoloniex = function(callback){
async.series([ async.series([
function(taskCallback){ function(taskCallback){
poloApi.getTicker(function(err, data){ poloApi.getTicker(function(err, data){
if (err){ if (err){
taskCallback(err); taskCallback(err);
return; return;
} }
Object.keys(profitSymbols).forEach(function(symbol){ Object.keys(profitSymbols).forEach(function(symbol){
var btcPrice = new Number(0); var btcPrice = new Number(0);
var ltcPrice = new Number(0); var ltcPrice = new Number(0);
if (data.hasOwnProperty('BTC_' + symbol)) { if (data.hasOwnProperty('BTC_' + symbol)) {
btcPrice = new Number(data['BTC_' + symbol]); btcPrice = new Number(data['BTC_' + symbol]);
} }
if (data.hasOwnProperty('LTC_' + symbol)) { if (data.hasOwnProperty('LTC_' + symbol)) {
ltcPrice = new Number(data['LTC_' + symbol]); ltcPrice = new Number(data['LTC_' + symbol]);
} }
if (btcPrice > 0 || ltcPrice > 0) { if (btcPrice > 0 || ltcPrice > 0) {
var prices = { var prices = {
BTC: btcPrice, BTC: btcPrice,
LTC: ltcPrice LTC: ltcPrice
}; };
profitStatus[profitSymbols[symbol]][symbol].prices['Poloniex'] = prices; profitStatus[profitSymbols[symbol]][symbol].prices['Poloniex'] = prices;
} }
}); });
taskCallback(); taskCallback();
}); });
}, },
function(taskCallback){ function(taskCallback){
poloApi.get24hVolume(function(err, data){ poloApi.get24hVolume(function(err, data){
if (err){ if (err){
taskCallback(err); taskCallback(err);
return; return;
} }
Object.keys(profitSymbols).forEach(function(symbol){ Object.keys(profitSymbols).forEach(function(symbol){
var btcVolume = new Number(0); var btcVolume = new Number(0);
var ltcVolume = new Number(0); var ltcVolume = new Number(0);
if (data.hasOwnProperty('BTC_' + symbol)) { if (data.hasOwnProperty('BTC_' + symbol)) {
btcVolume = new Number(data['BTC_' + symbol].BTC); btcVolume = new Number(data['BTC_' + symbol].BTC);
} }
if (data.hasOwnProperty('LTC_' + symbol)) { if (data.hasOwnProperty('LTC_' + symbol)) {
ltcVolume = new Number(data['LTC_' + symbol].LTC); ltcVolume = new Number(data['LTC_' + symbol].LTC);
} }
if (btcVolume > 0 || ltcVolume > 0) { if (btcVolume > 0 || ltcVolume > 0) {
var volumes = { var volumes = {
BTC: btcVolume, BTC: btcVolume,
LTC: ltcVolume LTC: ltcVolume
}; };
profitStatus[profitSymbols[symbol]][symbol].volumes['Poloniex'] = volumes; profitStatus[profitSymbols[symbol]][symbol].volumes['Poloniex'] = volumes;
} }
}); });
taskCallback(); taskCallback();
}); });
}, },
function(taskCallback){ function(taskCallback){
var depthTasks = []; var depthTasks = [];
Object.keys(profitSymbols).forEach(function(symbol){ Object.keys(profitSymbols).forEach(function(symbol){
var coinVolumes = profitStatus[profitSymbols[symbol]][symbol].volumes; var coinVolumes = profitStatus[profitSymbols[symbol]][symbol].volumes;
var coinPrices = profitStatus[profitSymbols[symbol]][symbol].prices; var coinPrices = profitStatus[profitSymbols[symbol]][symbol].prices;
if (coinVolumes.hasOwnProperty('Poloniex') && coinPrices.hasOwnProperty('Poloniex')){ if (coinVolumes.hasOwnProperty('Poloniex') && coinPrices.hasOwnProperty('Poloniex')){
var btcDepth = new Number(0); var btcDepth = new Number(0);
var ltcDepth = new Number(0); var ltcDepth = new Number(0);
if (coinVolumes['Poloniex']['BTC'] > 0 && coinPrices['Poloniex']['BTC'] > 0){ if (coinVolumes['Poloniex']['BTC'] > 0 && coinPrices['Poloniex']['BTC'] > 0){
var coinPrice = new Number(coinPrices['Poloniex']['BTC']); var coinPrice = new Number(coinPrices['Poloniex']['BTC']);
depthTasks.push(function(callback){ depthTasks.push(function(callback){
_this.getMarketDepthFromPoloniex('BTC', symbol, coinPrice, callback) _this.getMarketDepthFromPoloniex('BTC', symbol, coinPrice, callback)
}); });
} }
if (coinVolumes['Poloniex']['LTC'] > 0 && coinPrices['Poloniex']['LTC'] > 0){ if (coinVolumes['Poloniex']['LTC'] > 0 && coinPrices['Poloniex']['LTC'] > 0){
var coinPrice = new Number(coinPrices['Poloniex']['LTC']); var coinPrice = new Number(coinPrices['Poloniex']['LTC']);
depthTasks.push(function(callback){ depthTasks.push(function(callback){
_this.getMarketDepthFromPoloniex('LTC', symbol, coinPrice, callback) _this.getMarketDepthFromPoloniex('LTC', symbol, coinPrice, callback)
}); });
} }
} }
}); });
if (depthTasks.length == 0){ if (depthTasks.length == 0){
taskCallback; taskCallback;
return; return;
} }
async.parallel(depthTasks, function(err){ async.parallel(depthTasks, function(err){
if (err){ if (err){
logger.error(logSystem, 'Check', 'Error while checking profitability: ' + err); taskCallback(err);
return; return;
} }
taskCallback(); taskCallback();
}); });
} }
], function(err){ ], function(err){
if (err){ if (err){
callback(err); callback(err);
return; return;
} }
callback(null); callback(null);
}); });
}; };
this.getMarketDepthFromPoloniex = function(symbolA, symbolB, coinPrice, callback){ this.getMarketDepthFromPoloniex = function(symbolA, symbolB, coinPrice, callback){
poloApi.getOrderBook(symbolA, symbolB, function(err, data){ poloApi.getOrderBook(symbolA, symbolB, function(err, data){
if (err){ if (err){
callback(err); callback(err);
return; return;
} }
var depth = new Number(0); var depth = new Number(0);
if (data.hasOwnProperty('bids')){ if (data.hasOwnProperty('bids')){
data['bids'].forEach(function(order){ data['bids'].forEach(function(order){
var price = new Number(order[0]); var price = new Number(order[0]);
var qty = new Number(order[1]); var qty = new Number(order[1]);
// only measure the depth down to configured depth // only measure the depth down to configured depth
if (price >= coinPrice * portalConfig.profitSwitch.depth){ if (price >= coinPrice * portalConfig.profitSwitch.depth){
depth += (qty * price); depth += (qty * price);
} }
}); });
} }
if (!profitStatus[profitSymbols[symbolB]][symbolB].depths.hasOwnProperty('Poloniex')){ if (!profitStatus[profitSymbols[symbolB]][symbolB].depths.hasOwnProperty('Poloniex')){
profitStatus[profitSymbols[symbolB]][symbolB].depths['Poloniex'] = { profitStatus[profitSymbols[symbolB]][symbolB].depths['Poloniex'] = {
BTC: 0, BTC: 0,
LTC: 0 LTC: 0
}; };
} }
profitStatus[profitSymbols[symbolB]][symbolB].depths['Poloniex'][symbolA] = depth; profitStatus[profitSymbols[symbolB]][symbolB].depths['Poloniex'][symbolA] = depth;
callback(); callback();
}); });
}; };
// TODO // TODO
@ -207,20 +205,74 @@ module.exports = function(logger){
callback(null); callback(null);
}; };
this.getCoindDaemonInfo = function(callback){
var daemonTasks = [];
Object.keys(profitStatus).forEach(function(algo){
Object.keys(profitStatus[algo]).forEach(function(symbol){
var coinName = profitStatus[algo][symbol].name;
var poolConfig = poolConfigs[coinName];
var daemonConfig = poolConfig.shareProcessing.internal.daemon;
daemonTasks.push(function(callback){
_this.getDaemonInfoForCoin(symbol, daemonConfig, callback)
});
});
});
if (daemonTasks.length == 0){
callback();
return;
}
async.parallel(daemonTasks, function(err){
if (err){
callback(err);
return;
}
callback(null);
});
};
this.getDaemonInfoForCoin = function(symbol, cfg, callback){
var daemon = new Stratum.daemon.interface([cfg]);
daemon.once('online', function(){
daemon.cmd('getdifficulty', null, function(result){
if (result[0].error != null){
callback(result[0].error);
return;
}
profitStatus[profitSymbols[symbol]][symbol].difficulty = result[0].response;
daemon.cmd('getblocktemplate',
[{"capabilities": [ "coinbasetxn", "workid", "coinbase/append" ]}],
function(result){
if (result[0].error != null){
callback(result[0].error);
return;
}
profitStatus[profitSymbols[symbol]][symbol].reward = new Number(result[0].response.coinbasevalue / 100000000);
});
callback(null)
});
}).once('connectionFailed', function(error){
callback(error);
}).on('error', function(error){
callback(error);
}).init();
};
var checkProfitability = function(){ var checkProfitability = function(){
logger.debug(logSystem, 'Check', 'Running profitability checks.'); logger.debug(logSystem, 'Check', 'Running mining profitability check.');
async.parallel([ async.parallel([
_this.getProfitDataPoloniex, _this.getProfitDataPoloniex,
_this.getProfitDataCryptsy _this.getProfitDataCryptsy,
], function(err){ _this.getCoindDaemonInfo
if (err){ ], function(err){
if (err){
logger.error(logSystem, 'Check', 'Error while checking profitability: ' + err); logger.error(logSystem, 'Check', 'Error while checking profitability: ' + err);
return; return;
} }
logger.debug(logSystem, 'Check', JSON.stringify(profitStatus)); logger.debug(logSystem, 'Check', JSON.stringify(profitStatus));
}); });
}; };
setInterval(checkProfitability, portalConfig.profitSwitch.updateInterval * 1000); setInterval(checkProfitability, portalConfig.profitSwitch.updateInterval * 1000);