More development for payment processing. so close...
This commit is contained in:
parent
191d81bd18
commit
5acaaa5686
@ -128,15 +128,16 @@ Description of options:
|
|||||||
payments less frequently (they dislike). Opposite for a lower minimum payment. */
|
payments less frequently (they dislike). Opposite for a lower minimum payment. */
|
||||||
"minimumPayment": 0.001,
|
"minimumPayment": 0.001,
|
||||||
|
|
||||||
|
/* Minimum number of coins to keep in pool wallet. It is recommended to deposit at
|
||||||
|
at least this many coins into the pool wallet when first starting the pool. */
|
||||||
|
"minimumReserve": 10,
|
||||||
|
|
||||||
/* (2% default) What percent fee your pool takes from the block reward. */
|
/* (2% default) What percent fee your pool takes from the block reward. */
|
||||||
"feePercent": 0.02,
|
"feePercent": 0.02,
|
||||||
|
|
||||||
/* Your address that receives pool revenue from fees */
|
/* Your address that receives pool revenue from fees */
|
||||||
"feeReceiveAddress": "LZz44iyF4zLCXJTU8RxztyyJZBntdS6fvv",
|
"feeReceiveAddress": "LZz44iyF4zLCXJTU8RxztyyJZBntdS6fvv",
|
||||||
|
|
||||||
/* Minimum number of coins to keep in pool wallet */
|
|
||||||
"minimumReserve": 10,
|
|
||||||
|
|
||||||
/* How many coins from fee revenue must accumulate on top of the minimum reserve amount
|
/* How many coins from fee revenue must accumulate on top of the minimum reserve amount
|
||||||
in order to trigger withdrawal to fee address. The higher this threshold, the less of
|
in order to trigger withdrawal to fee address. The higher this threshold, the less of
|
||||||
your profit goes to transactions fees. */
|
your profit goes to transactions fees. */
|
||||||
|
|||||||
@ -100,11 +100,11 @@ function SetupForPool(logger, poolOptions){
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var rounds = [];
|
var rounds = results.map(function(r){
|
||||||
results.forEach(function(item){
|
var details = r.split(':');
|
||||||
var details = item.split(':');
|
return {txHash: details[0], height: details[1], reward: details[2]};
|
||||||
rounds.push({txHash: details[0], height: details[1], reward: details[2]});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
callback(null, rounds);
|
callback(null, rounds);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
@ -114,11 +114,10 @@ function SetupForPool(logger, poolOptions){
|
|||||||
It also adds the block reward amount to the round object - which the daemon gives also gives us. */
|
It also adds the block reward amount to the round object - which the daemon gives also gives us. */
|
||||||
function(rounds, callback){
|
function(rounds, callback){
|
||||||
|
|
||||||
var batchRPCcommand = [];
|
var batchRPCcommand = rounds.map(function(r){
|
||||||
|
return ['gettransaction', [r.txHash]];
|
||||||
|
});
|
||||||
|
|
||||||
for (var i = 0; i < rounds.length; i++){
|
|
||||||
batchRPCcommand.push(['gettransaction', [rounds[i].txHash]]);
|
|
||||||
}
|
|
||||||
daemon.batchCmd(batchRPCcommand, function(error, txDetails){
|
daemon.batchCmd(batchRPCcommand, function(error, txDetails){
|
||||||
|
|
||||||
if (error || !txDetails){
|
if (error || !txDetails){
|
||||||
@ -128,18 +127,14 @@ function SetupForPool(logger, poolOptions){
|
|||||||
|
|
||||||
//Rounds that are not confirmed yet are removed from the round array
|
//Rounds that are not confirmed yet are removed from the round array
|
||||||
//We also get reward amount for each block from daemon reply
|
//We also get reward amount for each block from daemon reply
|
||||||
txDetails.forEach(function(tx){
|
rounds = rounds.filter(function(r){
|
||||||
var txResult = tx.result;
|
var tx = txDetails.filter(function(t){ return t.result.txid === r.txHash; })[0];
|
||||||
var txDetails = tx.result.details[0];
|
if (tx.result.details[0].category !== 'generate') return false;
|
||||||
for (var i = 0; i < rounds.length; i++){
|
r.amount = tx.result.amount;
|
||||||
if (rounds[i].txHash === txResult.txid){
|
r.magnitude = r.reward / r.amount;
|
||||||
rounds[i].amount = txResult.amount;
|
return true;
|
||||||
rounds[i].magnitude = rounds[i].reward / txResult.amount;
|
|
||||||
if (txDetails.category !== 'generate')
|
|
||||||
rounds.splice(i, 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
if (rounds.length === 0){
|
if (rounds.length === 0){
|
||||||
callback('done - no confirmed transactions yet');
|
callback('done - no confirmed transactions yet');
|
||||||
return;
|
return;
|
||||||
@ -154,14 +149,12 @@ function SetupForPool(logger, poolOptions){
|
|||||||
amount owned to each miner for each round. */
|
amount owned to each miner for each round. */
|
||||||
function(rounds, callback){
|
function(rounds, callback){
|
||||||
|
|
||||||
var shareLooksup = [];
|
|
||||||
for (var i = 0; i < rounds.length; i++){
|
|
||||||
shareLooksup.push(['hgetall', coin + '_shares:round' + rounds[i].height]);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
var shareLookups = rounds.map(function(r){
|
||||||
|
return ['hgetall', coin + '_shares:round' + r.height]
|
||||||
|
});
|
||||||
|
|
||||||
|
redisClient.multi(shareLookups).exec(function(error, allWorkerShares){
|
||||||
redisClient.multi(shareLooksup).exec(function(error, allWorkerShares){
|
|
||||||
if (error){
|
if (error){
|
||||||
callback('done - redis error with multi get rounds share')
|
callback('done - redis error with multi get rounds share')
|
||||||
return;
|
return;
|
||||||
@ -169,58 +162,68 @@ function SetupForPool(logger, poolOptions){
|
|||||||
|
|
||||||
var workerRewards = {};
|
var workerRewards = {};
|
||||||
|
|
||||||
|
|
||||||
for (var i = 0; i < rounds.length; i++){
|
for (var i = 0; i < rounds.length; i++){
|
||||||
var round = rounds[i];
|
var round = rounds[i];
|
||||||
var workerShares = allWorkerShares[i];
|
var workerShares = allWorkerShares[i];
|
||||||
|
|
||||||
var reward = round.reward * (1 - processingConfig.feePercent);
|
var reward = round.reward * (1 - processingConfig.feePercent);
|
||||||
|
|
||||||
var totalShares = 0;
|
var totalShares = Object.keys(workerShares).reduce(function(p, c){
|
||||||
for (var worker in workerShares){
|
return p + parseInt(workerShares[c])
|
||||||
totalShares += parseInt(workerShares[worker]);
|
}, 0);
|
||||||
}
|
|
||||||
|
|
||||||
for (var worker in workerShares){
|
for (var worker in workerShares){
|
||||||
var singleWorkerShares = parseInt(workerShares[worker]);
|
var percent = parseInt(workerShares[worker]) / totalShares;
|
||||||
var percent = singleWorkerShares / totalShares;
|
var workerRewardTotal = Math.floor(reward * percent);
|
||||||
var workerRewardTotal = (reward * percent) / round.magnitude;
|
if (!(worker in workerRewards)) workerRewards[worker] = 0;
|
||||||
workerRewardTotal = Math.floor(workerRewardTotal * round.magnitude) / round.magnitude;
|
workerRewards[worker] += workerRewardTotal;
|
||||||
if (worker in workerRewards)
|
|
||||||
workerRewards[worker] += workerRewardTotal;
|
|
||||||
else
|
|
||||||
workerRewards[worker] = workerRewardTotal;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//this calculates profit if you wanna see it
|
||||||
|
/*
|
||||||
|
var workerTotalRewards = Object.keys(workerRewards).reduce(function(p, c){
|
||||||
|
return p + workerRewards[c];
|
||||||
|
}, 0);
|
||||||
|
|
||||||
console.dir(workerRewards);
|
var poolTotalRewards = rounds.reduce(function(p, c){
|
||||||
|
return p + c.amount;
|
||||||
|
}, 0);
|
||||||
|
|
||||||
callback(null, rounds);
|
console.log(workerRewards);
|
||||||
|
console.log('pool profit percent' + ((poolTotalRewards - workerTotalRewards) / poolTotalRewards));
|
||||||
|
*/
|
||||||
|
|
||||||
|
callback(null, rounds, workerRewards);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
/* Does a batch call to redis to get worker existing balances from coin_balances*/
|
/* Does a batch call to redis to get worker existing balances from coin_balances*/
|
||||||
function(rounds, callback){
|
function(rounds, workerRewards, callback){
|
||||||
/*
|
|
||||||
var workerAddress = Object.keys(balancesForRounds);
|
|
||||||
|
|
||||||
redisClient.hmget([coin + '_balances'].concat(workerAddress), function(error, results){
|
var workers = Object.keys(workerRewards);
|
||||||
|
|
||||||
|
redisClient.hmget([coin + '_balances'].concat(workers), function(error, results){
|
||||||
if (error){
|
if (error){
|
||||||
callback('done - redis error with multi get rounds share')
|
callback('done - redis error with multi get rounds share')
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
console.dir(workerRewards);
|
||||||
|
|
||||||
for (var i = 0; i < results.length; i++){
|
var workerBalances = {};
|
||||||
var shareInt = parseInt(results[i]);
|
|
||||||
if (shareInt)
|
|
||||||
balancesForRounds[workerAddress[i]] += shareInt;
|
|
||||||
|
|
||||||
|
for (var i = 0; i < workers.length; i++){
|
||||||
|
workerBalances[workers[i]] = parseInt(results[i]) || 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
callback(null, rounds, balancesForRounds)
|
console.dir(workerBalances);
|
||||||
|
|
||||||
|
callback(null, rounds, workerRewards, workerBalances)
|
||||||
});
|
});
|
||||||
*/
|
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
@ -230,13 +233,20 @@ function SetupForPool(logger, poolOptions){
|
|||||||
when deciding the sent balance, it the difference should be -1*amount they had in db,
|
when deciding the sent balance, it the difference should be -1*amount they had in db,
|
||||||
if not sending the balance, the differnce should be +(the amount they earned this round)
|
if not sending the balance, the differnce should be +(the amount they earned this round)
|
||||||
*/
|
*/
|
||||||
function(fullBalance, rounds, callback){
|
function(rounds, workerRewards, workerBalances, callback){
|
||||||
|
|
||||||
/* if payments dont succeed (likely because daemon isnt responding to rpc), then cancel here
|
/* if payments dont succeed (likely because daemon isnt responding to rpc), then cancel here
|
||||||
so that all of this can be tried again when the daemon is working. otherwise we will consider
|
so that all of this can be tried again when the daemon is working. otherwise we will consider
|
||||||
payment sent after we cleaned up the db.
|
payment sent after we cleaned up the db.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* In here do daemon.getbalance, figure out how many payments should be sent, see if the
|
||||||
|
remaining balance after payments-to-be sent is greater than the min reserver, otherwise
|
||||||
|
put everything in worker balances to be paid next time.
|
||||||
|
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -8,9 +8,9 @@
|
|||||||
"validateWorkerAddress": true,
|
"validateWorkerAddress": true,
|
||||||
"paymentInterval": 10,
|
"paymentInterval": 10,
|
||||||
"minimumPayment": 0.001,
|
"minimumPayment": 0.001,
|
||||||
|
"minimumReserve": 10,
|
||||||
"feePercent": 0.02,
|
"feePercent": 0.02,
|
||||||
"feeReceiveAddress": "LZz44iyF4zLCXJTU8RxztyyJZBntdS6fvv",
|
"feeReceiveAddress": "LZz44iyF4zLCXJTU8RxztyyJZBntdS6fvv",
|
||||||
"minimumReserve": 10,
|
|
||||||
"feeWithdrawalThreshold": 5,
|
"feeWithdrawalThreshold": 5,
|
||||||
"daemon": {
|
"daemon": {
|
||||||
"host": "localhost",
|
"host": "localhost",
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user