[IMPROVED] Payout logics
* [ADDED] More methods to our transaction class * `createDebitAPRecord` and `createDebitMPRecord`, will handle the * entire debit process * Adds Debit transaction * Adds TXFee transaction * mark transactions as archived * validate user is fully paid out * send notification to user * `getMPQueue` was added to unify the process of getting payout queues * [MOVED] Only one mail template for both payout methods * [ADDED] Some minor calls to user class * [ADDED] Full address validation to bitcoin class * [SQL] New SQL upgrade and Version Increment * Adding UNIQUE index to coin_address in accounts table * preperation for `sendmany` implementation
This commit is contained in:
parent
a9b56433cb
commit
c00b6d6757
@ -34,169 +34,77 @@ if ($bitcoin->can_connect() !== true) {
|
||||
$log->logFatal(" unable to connect to RPC server, exiting");
|
||||
$monitoring->endCronjob($cron_name, 'E0006', 1, true);
|
||||
}
|
||||
if ($setting->getValue('disable_manual_payouts') != 1) {
|
||||
// Fetch outstanding payout requests
|
||||
if ($aPayouts = $oPayout->getUnprocessedPayouts()) {
|
||||
if (count($aPayouts) > 0) {
|
||||
$log->logInfo("\tStarting Manual Payments...");
|
||||
$log->logInfo("\tAccount ID\tUsername\tBalance\t\tCoin Address");
|
||||
foreach ($aPayouts as $aData) {
|
||||
$transaction_id = NULL;
|
||||
$rpc_txid = NULL;
|
||||
$aBalance = $transaction->getBalance($aData['account_id']);
|
||||
$dBalance = $aBalance['confirmed'];
|
||||
$aData['coin_address'] = $user->getCoinAddress($aData['account_id']);
|
||||
$aData['username'] = $user->getUserName($aData['account_id']);
|
||||
// Validate address against RPC
|
||||
try {
|
||||
$aStatus = $bitcoin->validateaddress($aData['coin_address']);
|
||||
if (!$aStatus['isvalid']) {
|
||||
$log->logError('User: ' . $aData['username'] . ' - Failed to verify this users coin address, skipping payout');
|
||||
continue;
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
$log->logError('User: ' . $aData['username'] . ' - Failed to verify this users coin address, skipping payout');
|
||||
continue;
|
||||
}
|
||||
if ($dBalance > $config['txfee_manual']) {
|
||||
// To ensure we don't run this transaction again, lets mark it completed
|
||||
if (!$oPayout->setProcessed($aData['id'])) {
|
||||
$log->logFatal('unable to mark transactions ' . $aData['id'] . ' as processed. ERROR: ' . $oPayout->getCronError());
|
||||
$monitoring->endCronjob($cron_name, 'E0010', 1, true);
|
||||
}
|
||||
$log->logInfo("\t" . $aData['account_id'] . "\t\t" . $aData['username'] . "\t" . $dBalance . "\t\t" . $aData['coin_address']);
|
||||
if ($transaction->addTransaction($aData['account_id'], $dBalance - $config['txfee_manual'], 'Debit_MP', NULL, $aData['coin_address'], NULL)) {
|
||||
// Store debit transaction ID for later update
|
||||
$transaction_id = $transaction->insert_id;
|
||||
if (!$transaction->addTransaction($aData['account_id'], $config['txfee_manual'], 'TXFee', NULL, $aData['coin_address']))
|
||||
$log->logError('Failed to add TXFee record: ' . $transaction->getCronError());
|
||||
// Mark all older transactions as archived
|
||||
if (!$transaction->setArchived($aData['account_id'], $transaction->insert_id))
|
||||
$log->logError('Failed to mark transactions for #' . $aData['account_id'] . ' prior to #' . $transaction->insert_id . ' as archived. ERROR: ' . $transaction->getCronError());
|
||||
// Run the payouts from RPC now that the user is fully debited
|
||||
try {
|
||||
$rpc_txid = $bitcoin->sendtoaddress($aData['coin_address'], $dBalance - $config['txfee_manual']);
|
||||
} catch (Exception $e) {
|
||||
$log->logError('E0078: RPC method did not return 200 OK: Address: ' . $aData['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);
|
||||
}
|
||||
// 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());
|
||||
// Notify user via mail
|
||||
$aMailData['email'] = $user->getUserEmail($user->getUserName($aData['account_id']));
|
||||
$aMailData['subject'] = 'Manual Payout Completed';
|
||||
$aMailData['amount'] = $dBalance - $config['txfee_manual'];
|
||||
$aMailData['payout_id'] = $aData['id'];
|
||||
if (!$notification->sendNotification($aData['account_id'], 'manual_payout', $aMailData))
|
||||
$log->logError('Failed to send notification email to users address: ' . $aMailData['email'] . 'ERROR: ' . $notification->getCronError());
|
||||
// Recheck the users balance to make sure it is now 0
|
||||
if (!$aBalance = $transaction->getBalance($aData['account_id'])) {
|
||||
$log->logFatal('Failed to fetch balance for account ' . $aData['account_id'] . '. ERROR: ' . $transaction->getCronError());
|
||||
$monitoring->endCronjob($cron_name, 'E0065', 1, true);
|
||||
}
|
||||
if ($aBalance['confirmed'] > 0) {
|
||||
$log->logFatal('User has a remaining balance of ' . $aBalance['confirmed'] . ' after a successful payout!');
|
||||
$monitoring->endCronjob($cron_name, 'E0065', 1, true);
|
||||
}
|
||||
} else {
|
||||
$log->logFatal('Failed to add new Debit_MP transaction in database for user ' . $user->getUserName($aData['account_id']) . ' ERROR: ' . $transaction->getCronError());
|
||||
$monitoring->endCronjob($cron_name, 'E0064', 1, true);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
// Fetch our manual payouts, process them
|
||||
if ($setting->getValue('disable_manual_payouts') != 1 && $aManualPayouts = $transaction->getMPQueue()) {
|
||||
$log->logInfo(' found ' . count($aManualPayouts) . ' queued manual payouts');
|
||||
$mask = ' | %-10.10s | %-25.25s | %-20.20s | %-40.40s | %-20.20s |';
|
||||
$log->logInfo(sprintf($mask, 'UserID', 'Username', 'Balance', 'Address', 'Payout ID'));
|
||||
foreach ($aManualPayouts as $aUserData) {
|
||||
$transaction_id = NULL;
|
||||
$rpc_txid = NULL;
|
||||
$log->logInfo(sprintf($mask, $aUserData['id'], $aUserData['username'], $aUserData['confirmed'], $aUserData['coin_address'], $aUserData['payout_id']));
|
||||
if (!$oPayout->setProcessed($aUserData['payout_id'])) {
|
||||
$log->logFatal(' unable to mark transactions ' . $aData['id'] . ' as processed. ERROR: ' . $oPayout->getCronError());
|
||||
$monitoring->endCronjob($cron_name, 'E0010', 1, true);
|
||||
}
|
||||
} else if (empty($aPayouts)) {
|
||||
$log->logInfo("\tStopping Payments. No Payout Requests Found.");
|
||||
} else {
|
||||
$log->logFatal("\tFailed Processing Manual Payment Queue...Aborting...");
|
||||
$monitoring->endCronjob($cron_name, 'E0050', 1, true);
|
||||
}
|
||||
if (count($aPayouts > 0)) $log->logDebug(" found " . count($aPayouts) . " queued manual payout requests");
|
||||
} else {
|
||||
$log->logDebug("Manual payouts are disabled via admin panel");
|
||||
}
|
||||
if ($setting->getValue('disable_auto_payouts') != 1) {
|
||||
// Fetch all users balances
|
||||
if ($users = $transaction->getAPQueue()) {
|
||||
if (!empty($users)) {
|
||||
if (count($users) > 0) $log->logDebug(" found " . count($users) . " queued payout(s)");
|
||||
// Go through users and run transactions
|
||||
$log->logInfo("Starting Payments...");
|
||||
$log->logInfo("\tUserID\tUsername\tBalance\tThreshold\tAddress");
|
||||
foreach ($users as $aUserData) {
|
||||
$transaction_id = NULL;
|
||||
$rpc_txid = NULL;
|
||||
$dBalance = $aUserData['confirmed'];
|
||||
// Validate address against RPC
|
||||
if ($bitcoin->validateaddress($aUserData['coin_address'])) {
|
||||
if (!$transaction_id = $transaction->createDebitAPRecord($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 {
|
||||
// Run the payouts from RPC now that the user is fully debited
|
||||
try {
|
||||
$aStatus = $bitcoin->validateaddress($aUserData['coin_address']);
|
||||
if (!$aStatus['isvalid']) {
|
||||
$log->logError('User: ' . $aUserData['username'] . ' - Failed to verify this users coin address, skipping payout');
|
||||
continue;
|
||||
}
|
||||
$rpc_txid = $bitcoin->sendtoaddress($aUserData['coin_address'], $aUserData['confirmed'] - $config['txfee_manual']);
|
||||
} catch (Exception $e) {
|
||||
$log->logError('User: ' . $aUserData['username'] . ' - Failed to verify this users coin address, skipping payout');
|
||||
continue;
|
||||
}
|
||||
$log->logInfo("\t" . $aUserData['id'] . "\t" . $aUserData['username'] . "\t" . $dBalance . "\t" . $aUserData['ap_threshold'] . "\t\t" . $aUserData['coin_address']);
|
||||
// Only run if balance meets threshold and can pay the potential transaction fee
|
||||
if ($dBalance > $aUserData['ap_threshold'] && $dBalance > $config['txfee_auto']) {
|
||||
// Create transaction record
|
||||
if ($transaction->addTransaction($aUserData['id'], $dBalance - $config['txfee_auto'], 'Debit_AP', NULL, $aUserData['coin_address'], NULL)) {
|
||||
// Store debit ID for later update
|
||||
$transaction_id = $transaction->insert_id;
|
||||
if (!$transaction->addTransaction($aUserData['id'], $config['txfee_auto'], 'TXFee', NULL, $aUserData['coin_address']))
|
||||
$log->logError('Failed to add TXFee record: ' . $transaction->getCronError());
|
||||
// Mark all older transactions as archived
|
||||
if (!$transaction->setArchived($aUserData['id'], $transaction->insert_id))
|
||||
$log->logError('Failed to mark transactions for user #' . $aUserData['id'] . ' prior to #' . $transaction->insert_id . ' as archived. ERROR: ' . $transaction->getCronError());
|
||||
// Run the payouts from RPC now that the user is fully debited
|
||||
try {
|
||||
$rpc_txid = $bitcoin->sendtoaddress($aUserData['coin_address'], $dBalance - $config['txfee_auto']);
|
||||
} catch (Exception $e) {
|
||||
$log->logError('E0078: RPC method 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);
|
||||
}
|
||||
// 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());
|
||||
// Notify user via mail
|
||||
$aMailData['email'] = $user->getUserEmail($user->getUserName($aUserData['id']));
|
||||
$aMailData['subject'] = 'Auto Payout Completed';
|
||||
$aMailData['amount'] = $dBalance - $config['txfee_auto'];
|
||||
if (!$notification->sendNotification($aUserData['id'], 'auto_payout', $aMailData))
|
||||
$log->logError('Failed to send notification email to users address: ' . $aMailData['email'] . ' ERROR: ' . $notification->getCronError());
|
||||
// Recheck the users balance to make sure it is now 0
|
||||
$aBalance = $transaction->getBalance($aUserData['id']);
|
||||
if ($aBalance['confirmed'] > 0) {
|
||||
$log->logFatal('User has a remaining balance of ' . $aBalance['confirmed'] . ' after a successful payout!');
|
||||
$monitoring->endCronjob($cron_name, 'E0065', 1, true);
|
||||
}
|
||||
} else {
|
||||
$log->logFatal('Failed to add new Debit_AP transaction in database for user ' . $user->getUserName($aUserData['id']) . ' ERROR: ' . $transaction->getCronError());
|
||||
$monitoring->endCronjob($cron_name, 'E0064', 1, true);
|
||||
}
|
||||
$log->logError('E0078: RPC method 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);
|
||||
}
|
||||
// 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 {
|
||||
$log->logInfo(' failed to validate address for user: ' . $aUserData['username']);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Fetch our auto payouts, process them
|
||||
if ($setting->getValue('disable_auto_payouts') != 1 && $aAutoPayouts = $transaction->getAPQueue()) {
|
||||
$log->logInfo(' found ' . count($aAutoPayouts) . ' queued auto payouts');
|
||||
$mask = ' | %-10.10s | %-25.25s | %-20.20s | %-40.40s | %-20.20s |';
|
||||
$log->logInfo(sprintf($mask, 'UserID', 'Username', 'Balance', 'Address', 'Threshold'));
|
||||
foreach ($aAutoPayouts as $aUserData) {
|
||||
$transaction_id = NULL;
|
||||
$rpc_txid = NULL;
|
||||
$log->logInfo(sprintf($mask, $aUserData['id'], $aUserData['username'], $aUserData['confirmed'], $aUserData['coin_address'], $aUserData['ap_threshold']));
|
||||
if ($bitcoin->validateaddress($aUserData['coin_address'])) {
|
||||
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 {
|
||||
// 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']);
|
||||
} catch (Exception $e) {
|
||||
$log->logError('E0078: RPC method 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);
|
||||
}
|
||||
// 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 {
|
||||
$log->logInfo(' failed to validate address for user: ' . $aUserData['username']);
|
||||
continue;
|
||||
}
|
||||
} else if(empty($users)) {
|
||||
$log->logInfo("\tSkipping payments. No Auto Payments Eligible.");
|
||||
$log->logDebug("Users have not configured their AP > 0");
|
||||
} else{
|
||||
$log->logFatal("\tFailed Processing Auto Payment Payment Queue. ERROR: " . $transaction->getCronError());
|
||||
$monitoring->endCronjob($cron_name, 'E0050', 1, true);
|
||||
}
|
||||
} else {
|
||||
$log->logDebug("Auto payouts disabled via admin panel");
|
||||
}
|
||||
|
||||
$log->logInfo("Completed Payouts");
|
||||
// Cron cleanup and monitoring
|
||||
require_once('cron_end.inc.php');
|
||||
?>
|
||||
|
||||
@ -52,6 +52,12 @@ class Base {
|
||||
public function setBlock($block) {
|
||||
$this->block = $block;
|
||||
}
|
||||
public function setPayout($payout) {
|
||||
$this->payout = $payout;
|
||||
}
|
||||
public function setNotification($notification) {
|
||||
$this->notification = $notification;
|
||||
}
|
||||
public function setTransaction($transaction) {
|
||||
$this->transaction = $transaction;
|
||||
}
|
||||
|
||||
@ -296,4 +296,16 @@ class BitcoinClient extends jsonRPCClient {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public function validateaddress($coin_address) {
|
||||
try {
|
||||
$aStatus = parent::validateaddress($coin_address);
|
||||
if (!$aStatus['isvalid']) {
|
||||
return false;
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -16,18 +16,6 @@ class Payout Extends Base {
|
||||
return $this->sqlError('E0048');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all new, unprocessed payout requests
|
||||
* @param none
|
||||
* @return data Associative array with DB Fields
|
||||
**/
|
||||
public function getUnprocessedPayouts() {
|
||||
$stmt = $this->mysqli->prepare("SELECT * FROM $this->table WHERE completed = 0");
|
||||
if ($this->checkStmt($stmt) && $stmt->execute() && $result = $stmt->get_result())
|
||||
return $result->fetch_all(MYSQLI_ASSOC);
|
||||
return $this->sqlError('E0050');
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert a new payout request
|
||||
* @param account_id int Account ID
|
||||
|
||||
@ -312,21 +312,110 @@ class Transaction extends Base {
|
||||
ON t.account_id = a.id
|
||||
WHERE t.archived = 0 AND a.ap_threshold > 0 AND a.coin_address IS NOT NULL AND a.coin_address != ''
|
||||
GROUP BY t.account_id
|
||||
HAVING confirmed > a.ap_threshold
|
||||
");
|
||||
HAVING confirmed > a.ap_threshold AND confirmed > " . $this->config['txfee_auto']);
|
||||
if ($this->checkStmt($stmt) && $stmt->execute() && $result = $stmt->get_result())
|
||||
return $result->fetch_all(MYSQLI_ASSOC);
|
||||
return $this->sqlError();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Debit a user account
|
||||
* @param account_id int Account ID
|
||||
* @param coin_address string Coin Address
|
||||
* @param amount float Balance to record
|
||||
* @return int Debit transaction ID or false
|
||||
**/
|
||||
public function createDebitMPRecord($account_id, $coin_address, $amount) {
|
||||
return $this->createDebitRecord($account_id, $coin_address, $amount, 'Debit_MP');
|
||||
}
|
||||
public function createDebitAPRecord($account_id, $coin_address, $amount) {
|
||||
return $this->createDebitRecord($account_id, $coin_address, $amount, 'Debit_AP');
|
||||
}
|
||||
private function createDebitRecord($account_id, $coin_address, $amount, $type) {
|
||||
$type == 'Debit_MP' ? $txfee = $this->config['txfee_manual'] : $txfee = $this->config['txfee_auto'];
|
||||
// Add Debit record
|
||||
if (!$this->addTransaction($account_id, $amount, $type, NULL, $coin_address, NULL)) {
|
||||
$this->setErrorMessage('Failed to create ' . $type . ' transaction record in database');
|
||||
return false;
|
||||
}
|
||||
// Fetch the inserted record ID so we can return this at the end
|
||||
$transaction_id = $this->insert_id;
|
||||
// Add TXFee record
|
||||
if (!$this->addTransaction($account_id, $txfee, 'TXFee', NULL, $coin_address)) {
|
||||
$this->setErrorMessage('Failed to create TXFee transaction record in database: ' . $this->getError());
|
||||
return false;
|
||||
}
|
||||
// Mark transactions archived
|
||||
if (!$this->setArchived($account_id, $this->insert_id)) {
|
||||
$this->setErrorMessage('Failed to mark transactions <= #' . $this->insert_id . ' as archived. ERROR: ' . $this->getError());
|
||||
return false;
|
||||
}
|
||||
// Recheck the users balance to make sure it is now 0
|
||||
if (!$aBalance = $this->getBalance($account_id)) {
|
||||
$this->setErrorMessage('Failed to fetch balance for account ' . $account_id . '. ERROR: ' . $this->getCronError());
|
||||
return false;
|
||||
}
|
||||
if ($aBalance['confirmed'] > 0) {
|
||||
$this->setErrorMessage('User has a remaining balance of ' . $aBalance['confirmed'] . ' after a successful payout!');
|
||||
return false;
|
||||
}
|
||||
// Notify user via mail
|
||||
$aMailData['email'] = $this->user->getUserEmailById($account_id);
|
||||
$aMailData['subject'] = $type . ' Completed';
|
||||
$aMailData['amount'] = $amount - $txfee;
|
||||
if (!$this->notification->sendNotification($account_id, 'payout', $aMailData)) {
|
||||
$this->setErrorMessage('Failed to send notification email to users address: ' . $aMailData['email'] . 'ERROR: ' . $this->notification->getCronError());
|
||||
}
|
||||
return $transaction_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all new, unprocessed manual payout requests
|
||||
* @param none
|
||||
* @return data Associative array with DB Fields
|
||||
**/
|
||||
public function getMPQueue() {
|
||||
$stmt = $this->mysqli->prepare("
|
||||
SELECT
|
||||
a.id,
|
||||
a.username,
|
||||
a.ap_threshold,
|
||||
a.coin_address,
|
||||
p.id AS payout_id,
|
||||
IFNULL(
|
||||
ROUND(
|
||||
(
|
||||
SUM( IF( ( t.type IN ('Credit','Bonus') AND b.confirmations >= " . $this->config['confirmations'] . ") OR t.type = 'Credit_PPS', t.amount, 0 ) ) -
|
||||
SUM( IF( t.type IN ('Debit_MP', 'Debit_AP'), t.amount, 0 ) ) -
|
||||
SUM( IF( ( t.type IN ('Donation','Fee') AND b.confirmations >= " . $this->config['confirmations'] . ") OR ( t.type IN ('Donation_PPS', 'Fee_PPS', 'TXFee') ), t.amount, 0 ) )
|
||||
), 8
|
||||
), 0
|
||||
) AS confirmed
|
||||
FROM " . $this->payout->getTableName() . " AS p
|
||||
JOIN " . $this->user->getTableName() . " AS a
|
||||
ON p.account_id = a.id
|
||||
JOIN " . $this->getTableName() . " AS t
|
||||
ON t.account_id = p.account_id
|
||||
JOIN " . $this->block->getTableName() . " AS b
|
||||
ON t.block_id = b.id
|
||||
WHERE p.completed = 0 AND t.archived = 0 AND a.coin_address IS NOT NULL AND a.coin_address != ''
|
||||
GROUP BY t.account_id
|
||||
HAVING confirmed > " . $this->config['txfee_manual']);
|
||||
if ($this->checkStmt($stmt) && $stmt->execute() && $result = $stmt->get_result())
|
||||
return $result->fetch_all(MYSQLI_ASSOC);
|
||||
return $this->sqlError('E0050');
|
||||
}
|
||||
}
|
||||
|
||||
$transaction = new Transaction();
|
||||
$transaction->setMemcache($memcache);
|
||||
$transaction->setNotification($notification);
|
||||
$transaction->setDebug($debug);
|
||||
$transaction->setMysql($mysqli);
|
||||
$transaction->setConfig($config);
|
||||
$transaction->setBlock($block);
|
||||
$transaction->setUser($user);
|
||||
$transaction->setPayout($oPayout);
|
||||
$transaction->setErrorCodes($aErrorCodes);
|
||||
|
||||
?>
|
||||
|
||||
@ -25,8 +25,8 @@ class User extends Base {
|
||||
public function getUserEmail($username, $lower=false) {
|
||||
return $this->getSingle($username, 'email', 'username', 's', $lower);
|
||||
}
|
||||
public function getUserNotifyEmail($username, $lower=false) {
|
||||
return $this->getSingle($username, 'notify_email', 'username', 's', $lower);
|
||||
public function getUserEmailById($id) {
|
||||
return $this->getSingle($id, 'email', 'id', 'i');
|
||||
}
|
||||
public function getUserNoFee($id) {
|
||||
return $this->getSingle($id, 'no_fees', 'id');
|
||||
@ -280,6 +280,16 @@ class User extends Base {
|
||||
return $this->getSingle($userID, 'coin_address', 'id');
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a coin address exists already
|
||||
* @param address string Coin Address
|
||||
* @return bool True of false
|
||||
**/
|
||||
public function existsCoinAddress($address) {
|
||||
$this->debug->append("STA " . __METHOD__, 4);
|
||||
return $this->getSingle($address, 'coin_address', 'coin_address') === $address;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch users donation value
|
||||
* @param userID int UserID
|
||||
@ -413,6 +423,10 @@ class User extends Base {
|
||||
return false;
|
||||
}
|
||||
if (!empty($address)) {
|
||||
if ($this->existsCoinAddress($address)) {
|
||||
$this->setErrorMessage('Address is already in use');
|
||||
return false;
|
||||
}
|
||||
if ($this->bitcoin->can_connect() === true) {
|
||||
try {
|
||||
$aStatus = $this->bitcoin->validateaddress($address);
|
||||
@ -428,6 +442,8 @@ class User extends Base {
|
||||
$this->setErrorMessage('Unable to connect to RPC server for coin address validation');
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
$address = NULL;
|
||||
}
|
||||
|
||||
// Number sanitizer, just in case we fall through above
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
$defflip = (!cfip()) ? exit(header('HTTP/1.1 401 Unauthorized')) : 1;
|
||||
|
||||
define('MPOS_VERSION', '0.0.3');
|
||||
define('DB_VERSION', '0.0.4');
|
||||
define('DB_VERSION', '0.0.5');
|
||||
define('CONFIG_VERSION', '0.0.7');
|
||||
|
||||
// Fetch installed database version
|
||||
|
||||
@ -1,8 +0,0 @@
|
||||
<html>
|
||||
<body>
|
||||
<p>An manual payout request completed.</p>
|
||||
<p>Amount: {nocache}{$DATA.amount}{/nocache}</p>
|
||||
<br/>
|
||||
<br/>
|
||||
</body>
|
||||
</html>
|
||||
@ -1,6 +1,6 @@
|
||||
<html>
|
||||
<body>
|
||||
<p>An automated payout completed.</p>
|
||||
<p>You account has been debited and the coins have been sent to your wallet.</p>
|
||||
<p>Amount: {nocache}{$DATA.amount}{/nocache}</p>
|
||||
<br/>
|
||||
<br/>
|
||||
2
sql/015_accounts_update.sql
Normal file
2
sql/015_accounts_update.sql
Normal file
@ -0,0 +1,2 @@
|
||||
ALTER TABLE `accounts` ADD UNIQUE INDEX ( `coin_address` ) ;
|
||||
INSERT INTO `settings` (`name`, `value`) VALUES ('DB_VERSION', '0.0.5') ON DUPLICATE KEY UPDATE `value` = '0.0.5';
|
||||
Loading…
Reference in New Issue
Block a user