diff --git a/cronjobs/payouts.php b/cronjobs/payouts.php index cd16c68d..c96af16c 100755 --- a/cronjobs/payouts.php +++ b/cronjobs/payouts.php @@ -29,18 +29,29 @@ if ($setting->getValue('disable_payouts') == 1) { $log->logInfo(" payouts disabled via admin panel"); $monitoring->endCronjob($cron_name, 'E0009', 0, true, false); } -$log->logInfo("Starting Payout..."); +$log->logDebug("Starting Payout..."); if ($bitcoin->can_connect() !== true) { $log->logFatal(" unable to connect to RPC server, exiting"); $monitoring->endCronjob($cron_name, 'E0006', 1, true); } + +// Check and see if the sendmany RPC method is available +// This does not test if it actually works too! +$sendmanyAvailable = ((strpos($bitcoin->help('sendmany'), 'unknown') === FALSE) ? true : false); +if ($sendmanyAvailable) + $log->logDebug(' sendmany available in coind help command'); + if (!$dWalletBalance = $bitcoin->getbalance()) $dWalletBalance = 0; +// Fetch outstanding manual-payouts +$aManualPayouts = $transaction->getMPQueue(); + // Fetch our manual payouts, process them -if ($setting->getValue('disable_manual_payouts') != 1 && $aManualPayouts = $transaction->getMPQueue()) { +if ($setting->getValue('disable_manual_payouts') != 1 && $aManualPayouts) { // Calculate our sum first $dMPTotalAmount = 0; + $aSendMany = NULL; foreach ($aManualPayouts as $aUserData) $dMPTotalAmount += $aUserData['confirmed']; if ($dMPTotalAmount > $dWalletBalance) { $log->logError(" Wallet does not cover MP payouts"); @@ -62,7 +73,7 @@ if ($setting->getValue('disable_manual_payouts') != 1 && $aManualPayouts = $tran if (!$transaction_id = $transaction->createDebitMPRecord($aUserData['id'], $aUserData['coin_address'], $aUserData['confirmed'] - $config['txfee_manual'])) { $log->logFatal(' failed to fullt debit user ' . $aUserData['username'] . ': ' . $transaction->getCronError()); $monitoring->endCronjob($cron_name, 'E0064', 1, true); - } else { + } else if (!$config['sendmany']['enabled'] || !$sendmanyAvailable) { // Run the payouts from RPC now that the user is fully debited try { $rpc_txid = $bitcoin->sendtoaddress($aUserData['coin_address'], $aUserData['confirmed'] - $config['txfee_manual']); @@ -75,18 +86,42 @@ if ($setting->getValue('disable_manual_payouts') != 1 && $aManualPayouts = $tran // Update our transaction and add the RPC Transaction ID if (empty($rpc_txid) || !$transaction->setRPCTxId($transaction_id, $rpc_txid)) $log->logError('Unable to add RPC transaction ID ' . $rpc_txid . ' to transaction record ' . $transaction_id . ': ' . $transaction->getCronError()); + } else { + // We don't run sendtoaddress but run sendmany later + $aSendMany[$aUserData['coin_address']] = $aUserData['confirmed'] - $config['txfee_manual']; + $aTransactions[] = $transaction_id; } } else { $log->logInfo(' failed to validate address for user: ' . $aUserData['username']); continue; } } + if ($config['sendmany']['enabled'] && $sendmanyAvailable && is_array($aSendMany)) { + try { + $rpc_txid = $bitcoin->sendmany('', $aSendMany); + } catch (Exception $e) { + $log->logError('E0078: RPC method sendmany did not return 200 OK: Address: ' . $aUserData['coin_address'] . ' ERROR: ' . $e->getMessage()); + // Remove this line below if RPC calls are failing but transactions are still added to it + // Don't blame MPOS if you run into issues after commenting this out! + $monitoring->endCronjob($cron_name, 'E0078', 1, true); + } + $log->logInfo(' payout succeeded with RPC TXID: ' . $rpc_txid); + foreach ($aTransactions as $iTransactionID) { + if (empty($rpc_txid) || !$transaction->setRPCTxId($iTransactionID, $rpc_txid)) + $log->logError('Unable to add RPC transaction ID ' . $rpc_txid . ' to transaction record ' . $iTransactionID . ': ' . $transaction->getCronError()); + } + } } if (!$dWalletBalance = $bitcoin->getbalance()) $dWalletBalance = 0; + +// Fetch outstanding auto-payouts +$aAutoPayouts = $transaction->getAPQueue(); + // Fetch our auto payouts, process them -if ($setting->getValue('disable_auto_payouts') != 1 && $aAutoPayouts = $transaction->getAPQueue()) { +if ($setting->getValue('disable_auto_payouts') != 1 && $aAutoPayouts) { + $aSendMany = NULL; // Calculate our sum first $dAPTotalAmount = 0; foreach ($aAutoPayouts as $aUserData) $dAPTotalAmount += $aUserData['confirmed']; @@ -106,7 +141,7 @@ if ($setting->getValue('disable_auto_payouts') != 1 && $aAutoPayouts = $transact if (!$transaction_id = $transaction->createDebitAPRecord($aUserData['id'], $aUserData['coin_address'], $aUserData['confirmed'] - $config['txfee_manual'])) { $log->logFatal(' failed to fully debit user ' . $aUserData['username'] . ': ' . $transaction->getCronError()); $monitoring->endCronjob($cron_name, 'E0064', 1, true); - } else { + } else if (!$config['sendmany']['enabled'] || !$sendmanyAvailable) { // Run the payouts from RPC now that the user is fully debited try { $rpc_txid = $bitcoin->sendtoaddress($aUserData['coin_address'], $aUserData['confirmed'] - $config['txfee_manual']); @@ -119,12 +154,31 @@ if ($setting->getValue('disable_auto_payouts') != 1 && $aAutoPayouts = $transact // Update our transaction and add the RPC Transaction ID if (empty($rpc_txid) || !$transaction->setRPCTxId($transaction_id, $rpc_txid)) $log->logError('Unable to add RPC transaction ID ' . $rpc_txid . ' to transaction record ' . $transaction_id . ': ' . $transaction->getCronError()); + } else { + // We don't run sendtoaddress but run sendmany later + $aSendMany[$aUserData['coin_address']] = $aUserData['confirmed'] - $config['txfee_auto']; + $aTransactions[] = $transaction_id; } } else { $log->logInfo(' failed to validate address for user: ' . $aUserData['username']); continue; } } + if ($config['sendmany']['enabled'] && $sendmanyAvailable && is_array($aSendMany)) { + try { + $rpc_txid = $bitcoin->sendmany('', $aSendMany); + } catch (Exception $e) { + $log->logError('E0078: RPC method sendmany did not return 200 OK: Address: ' . $aUserData['coin_address'] . ' ERROR: ' . $e->getMessage()); + // Remove this line below if RPC calls are failing but transactions are still added to it + // Don't blame MPOS if you run into issues after commenting this out! + $monitoring->endCronjob($cron_name, 'E0078', 1, true); + } + $log->logInfo(' payout succeeded with RPC TXID: ' . $rpc_txid); + foreach ($aTransactions as $iTransactionID) { + if (empty($rpc_txid) || !$transaction->setRPCTxId($iTransactionID, $rpc_txid)) + $log->logError('Unable to add RPC transaction ID ' . $rpc_txid . ' to transaction record ' . $iTransactionID . ': ' . $transaction->getCronError()); + } + } } require_once('cron_end.inc.php'); diff --git a/public/include/classes/bitcoinwrapper.class.php b/public/include/classes/bitcoinwrapper.class.php index ccab6b41..ebe1c470 100644 --- a/public/include/classes/bitcoinwrapper.class.php +++ b/public/include/classes/bitcoinwrapper.class.php @@ -31,6 +31,12 @@ class BitcoinWrapper extends BitcoinClient { if ($data = $this->memcache->get(__FUNCTION__)) return $data; return $this->memcache->setCache(__FUNCTION__, parent::getmininginfo(), 30); } + // Wrapper to check our wallet balance from the DEFAULT account only + public function getbalance() { + $this->oDebug->append("STA " . __METHOD__, 4); + $aAccounts = parent::listaccounts(); + return $aAccounts['']; + } public function getblockcount() { $this->oDebug->append("STA " . __METHOD__, 4); if ($data = $this->memcache->get(__FUNCTION__)) return $data; diff --git a/public/include/config/global.inc.dist.php b/public/include/config/global.inc.dist.php index 66ea0e51..fb7e22e2 100644 --- a/public/include/config/global.inc.dist.php +++ b/public/include/config/global.inc.dist.php @@ -144,6 +144,13 @@ $config['block_bonus'] = 0; **/ $config['payout_system'] = 'prop'; +/** + * Sendmany Support + * Enable/Disable Sendmany RPC method + * https://github.com/MPOS/php-mpos/wiki/Config-Setup#wiki-sendmany-support + **/ +$config['sendmany']['enabled'] = false; + /** * Round Purging * Round share purging configuration