I’m somewhat new to JS and working with an existing forked library (which is very complicated and poorly documented) – so please bear with me.
I’m working on a mining pool system, and specifically adding a feature where users can set a custom payout amount instead of the lower pool limit. I’ve already sorted writing that value for a users worker address into redis.
What I’m trying to do now is add logic that will:
- Use the worker Address that did work to see if they set a custom payout value (my external function below)
- If it’s set, some logic to determine if they should be paid immediately or add it to their balance
The existing waterfall script is here: https://github.com/mardock2009/Ravencoin-Pool/blob/master/libs/paymentProcessor.js#L575
Before the waterfall, i’m adding a function similar to this (i’ve tried many iterations):
getCustomPayoutAmount = function(worker, cback) { var logger = loggerFactory.getLogger('PaymentProcessing', 'getCustomPayoutAmount'); var redisClient = redis.createClient(portalConfig.redis.port, portalConfig.redis.host); logger.debug('Getting custom Payout for worker: %s', worker); var payoutAmount = new BigNumber(0); redisClient.hget('ravencoin:workers:customPayoutAmount', worker, function(error, result) { if (error) { logger.error('Error getCustomPayoutAmount: %s', error); payoutAmount = 0; } logger.debug('Got custom payout amount for worker: %s, Payout Amount: %s', worker, result); if (result > 10) { payoutAmount = new BigNumber(result); logger.debug('Parsed Float Amount: %s', payoutAmount); } else { logger.debug('Else lower than: %s', payoutAmount); payoutAmount = new BigNumber(0); } }); cback( new BigNumber(payoutAmount)); };
Then at around line 575, i’m calling it (maybe?):
var customPayoutAmount = new BigNumber(0); getCustomPayoutAmount(worker, function(returnCustomPayoutAmount) { logger.debug('Callback customPayoutAmount = %s', returnCustomPayoutAmount); customPayoutAmount = returnCustomPayoutAmount; }); logger.debug('PP> customPayoutAmount = %s', customPayoutAmount);
And then finally, some if/elseif logic to handle the different cases:
if (toSend.isGreaterThanOrEqualTo(minPayment)) { if (toSend.isGreaterThanOrEqualTo(customPayoutAmount) && !customPayoutAmount.isZero()) { //Amount Sent is higher than the custom amount set for this worker. Pay it out. logger.debug('PP> Worker %s have their custom minimum payout amount: (%s above minimum %s)', w, toSend.toString(10), customPayoutAmount.toString(10)); totalSent = totalSent.plus(toSend); logger.debug('PP> totalSent = %s', totalSent.toString(10)); var address = worker.address = (worker.address || getProperAddress(w)); logger.debug('PP> address = %s', address); worker.sent = addressAmounts[address] = toSend; logger.debug('PP> worker.sent = %s', worker.sent.toString(10)); worker.balanceChange = BigNumber.min(worker.balance, worker.sent).multipliedBy(new BigNumber(-1)); logger.debug('PP> worker.balanceChange = %s', worker.balanceChange.toString(10)); } else if (toSend.isLessThan(customPayoutAmount) && !customPayoutAmount.isZero()){ //Amount is higher than the minimum payment but not higher than the custom amount set for this worker. Add it to their balance. //Did not meet the pool minimum, no custom amount. Add to balance. logger.debug('PP> Worker %s have not reached minimum payout from their custom set payout amount threshold %s', w, customPayoutAmount.toString(10)); worker.balanceChange = BigNumber.max(toSend.minus(worker.balance), new BigNumber(0)); logger.debug('PP> worker.balanceChange = %s', worker.balanceChange.toString(10)); worker.sent = new BigNumber(0); logger.debug('PP> worker.sent = %s', worker.sent.toString(10)); if (worker.balanceChange > 0) { if (balanceAmounts[address] != null && balanceAmounts[address].isGreaterThan(0)) { balanceAmounts[address] = balanceAmounts[address].plus(worker.balanceChange); } else { balanceAmounts[address] = worker.balanceChange; } } } if (toSend.isGreaterThanOrEqualTo(minPayment) && customPayoutAmount.isZero()) { //Meets the pool minimum payment, no custom amount. Pay out based on the pool minimum payment. logger.debug('PP> Worker %s have reached minimum payout threshold (%s above minimum %s)', w, toSend.toString(10), minPayment.toString(10)); totalSent = totalSent.plus(toSend); logger.debug('PP> totalSent = %s', totalSent.toString(10)); var address = worker.address = (worker.address || getProperAddress(w)); logger.debug('PP> address = %s', address); worker.sent = addressAmounts[address] = toSend; logger.debug('PP> worker.sent = %s', worker.sent.toString(10)); worker.balanceChange = BigNumber.min(worker.balance, worker.sent).multipliedBy(new BigNumber(-1)); logger.debug('PP> worker.balanceChange = %s', worker.balanceChange.toString(10)); } } else { //Did not meet the pool minimum, no custom amount. Add to balance. logger.debug('PP> Worker %s have not reached minimum payout threshold %s', w, minPayment.toString(10)); worker.balanceChange = BigNumber.max(toSend.minus(worker.balance), new BigNumber(0)); logger.debug('PP> worker.balanceChange = %s', worker.balanceChange.toString(10)); worker.sent = new BigNumber(0); logger.debug('PP> worker.sent = %s', worker.sent.toString(10)); if (worker.balanceChange > 0) { if (balanceAmounts[address] != null && balanceAmounts[address].isGreaterThan(0)) { balanceAmounts[address] = balanceAmounts[address].plus(worker.balanceChange); } else { balanceAmounts[address] = worker.balanceChange; } } }
The main issue I’m having is I cant get values back from redis calling it inside the waterfall. I’m assuming because it’s async andIi’m not writing async code – which also causes it to not necessarily run in order when I need the values.
Again, I know this is a mess and I’m probably going about this all wrong, so hopefully someone has some insight for this poor noob.
Advertisement
Answer
You can use async.each()
function(workers, rounds, addressAccount, callback) { var trySend = function(withholdPercent) { ... async.each(workers, function(worker, callback) { ... getCustomPayoutAmount(worker, function(customPayoutAmount) { ... if (toSend.isGreaterThanOrEqualTo(minPayment)) { if (toSend.isGreaterThanOrEqualTo(customPayoutAmount) && !customPayoutAmount.isZero()) { ... } ... } callback(); }); }) .then(function() { if (Object.keys(addressAmounts).length === 0) { logger.info('PP> No workers was chosen for paying out'); callback(null, workers, rounds, []); return; } ... daemon.cmd('sendmany', [addressAccount || '', addressAmounts, 1, ""], function(result) { ... } }); }; trySend(new BigNumber(0); }
and In ‘getCustomPayoutAmount’, ‘cback()` should be called within the callback of ‘redisClient.hget()’ like below
getCustomPayoutAmount = function(worker, cback) { ... redisClient.hget('ravencoin:workers:customPayoutAmount', worker, function(error, result) { ... cback(payoutAmount); }); };