diff --git a/cronjobs/auto_payout.php b/cronjobs/auto_payout.php new file mode 100644 index 00000000..fef0d484 --- /dev/null +++ b/cronjobs/auto_payout.php @@ -0,0 +1,69 @@ +#!/usr/bin/php +can_connect() !== true) { + verbose("Unable to connect to RPC server, exiting"); + exit(1); +} + +// Fetch all users with setup AP +$users = $user->getAllAutoPayout(); + +// Go through users and run transactions +if (! empty($users)) { + verbose("UserID\tUsername\tBalance\tThreshold\tAddress\t\t\t\t\tStatus\n\n"); + + foreach ($users as $aUserData) { + $dBalance = $transaction->getBalance($aUserData['id']); + verbose($aUserData['id'] . "\t" . $aUserData['username'] . "\t" . $dBalance . "\t" . $aUserData['ap_threshold'] . "\t\t" . $aUserData['coin_address'] . "\t"); + + // Only run if balance meets threshold and can pay the transaction fee + if ($dBalance > $aUserData['ap_threshold'] && $dBalance > 0.1) { + // Validate address against RPC + try { + $bitcoin->validateaddress($aUserData['coin_address']); + } catch (BitcoinClientException $e) { + verbose("VERIFY FAILED\n"); + continue; + } + + // Send balance - 0.1 Fee to address + try { + $bitcoin->sendtoaddress($aUserData['coin_address'], $dBalance - 0.1); + } catch (BitcoinClientException $e) { + verbose("SEND FAILED\n"); + continue; + } + + // Create transaction record + if ($transaction->addTransaction($aUserData['id'], $dBalance, 'Debit_AP', NULL, $aUserData['coin_address'], 0.1)) { + verbose("OK\n"); + } else { + verbose("FAILED\n"); + } + } + } +} else { + verbose("No user has configured their AP > 0\n"); +} diff --git a/public/include/classes/user.class.php b/public/include/classes/user.class.php index f9b8e5e3..cb7ff1c7 100644 --- a/public/include/classes/user.class.php +++ b/public/include/classes/user.class.php @@ -34,6 +34,12 @@ class User { return $this->getSingle($username, 'id', 'username', 's'); } + /** + * Check user login + * @param username string Username + * @param password string Password + * @return bool + **/ public function checkLogin($username, $password) { $this->debug->append("Checking login for $username with password $password", 2); if ( $this->checkUserPassword($username, $password) ) { @@ -43,6 +49,12 @@ class User { return false; } + /** + * Check the users PIN for confirmation + * @param userID int User ID + * @param pin int PIN to check + * @return bool + **/ public function checkPin($userId, $pin=false) { $this->debug->append("Confirming PIN for $userId and pin $pin", 2); $stmt = $this->mysqli->prepare("SELECT pin FROM $this->table WHERE id=? AND pin=? LIMIT 1"); @@ -55,6 +67,14 @@ class User { return $pin_hash === $row_pin; } + /** + * Get a single row from the table + * @param value string Value to search for + * @param search Return column to search for + * @param field string Search column + * @param type string Type of value + * @return array Return result + **/ private function getSingle($value, $search='id', $field='id', $type="i") { $stmt = $this->mysqli->prepare("SELECT $search FROM $this->table WHERE $field = ? LIMIT 1"); if ($this->checkStmt($stmt)) { @@ -68,12 +88,44 @@ class User { return false; } + /** + * Get all users that have auto payout setup + * @param none + * @return data array All users with payout setup + **/ + public function getAllAutoPayout() { + $stmt = $this->mysqli->prepare(" + SELECT + id, username, coin_address, ap_threshold + FROM " . $this->getTableName() . " + WHERE ap_threshold > 0 + AND coin_address IS NOT NULL + "); + if ( $this->checkStmt($stmt) && $stmt->execute() && $result = $stmt->get_result()) { + return $result->fetch_all(MYSQLI_ASSOC); + } + $this->debug->append("Unable to fetch users with AP set"); + echo $this->mysqli->error; + return false; + } + + /** + * Fetch users coin address + * @param userID int UserID + * @return data string Coin Address + **/ public function getCoinAddress($userID) { return $this->getSingle($userID, 'coin_address', 'id', 's'); } - private function updateSingle($userID, $field, $table) { - $stmt = $this->mysqli->prepare("UPDATE $table SET " . $field['name'] . " = ? WHERE userId = ? LIMIT 1"); + /** + * Update a single row in a table + * @param userID int Account ID + * @param field string Field to update + * @return bool + **/ + private function updateSingle($userID, $field) { + $stmt = $this->mysqli->prepare("UPDATE $this->table SET " . $field['name'] . " = ? WHERE userId = ? LIMIT 1"); if ($this->checkStmt($stmt)) { $stmt->bind_param($field['type'].'i', $field['value'], $userID); $stmt->execute();