/** * Validates amount to ensure it follows the rules of monero * * @param string|float amount * @return bool */ public function valid_amount($amount) { if (!is_numeric($amount)) { return FALSE; } // XMR is limited to 12 decimals if (bc::count_decimals($amount) > 12) { return FALSE; } #// The maximum payment is depended on your system, 32-bit is 10 digits and 64-bit is 19 digits #$max_digits = strlen(PHP_INT_MAX); // PHP 64-bit does not support more than 9223372036854775807 (19-digits) if (bc::is($amount, '>=', '9223372.036854775807')) { return FALSE; } return TRUE; }
/** * Check if user has sufficient balance * * @param object user * @param decimal amount to check * @return bool true if enough balance (equal or more) */ public function available_balance($user, $amount) { return (bool) bc::is($this->get_balance($user), '>=', $amount); }
$payment_ids = $pids->fetch_assoc(); // Credit user his funds (if user has no balance for this asset, we create it, otherwise update) $db->query("INSERT INTO \n users_assets (`user_id`, `asset_id`, `balance`) \n VALUES \n (" . $payment_ids['user_id'] . "," . $asset->get_id() . "," . $row['amount'] . ")\n ON DUPLICATE KEY UPDATE \n `balance` = balance + " . $row['amount'] . ";"); } } $db->query('COMMIT'); // -------------------------------------------------------------------- // // Process pending withdraws // // -------------------------------------------------------------------- $result = $db->query('SELECT * FROM withdraws_pending WHERE status = 1 ORDER BY id ASC LIMIT 1000'); $payments = array(); while ($row = $result->fetch_array(MYSQL_ASSOC)) { // If there is not enough balance, we'll try again later ("break" instead of "continue" so that payment are processed as a queue, most fair) if (bc::is($row['amount'], '>', $wallet->get_unlocked_balance())) { break; } // In rare cases that bulk_transfer sends payment, but script does a rollback, the transfer will not be repeated by setting status to error first (requiring manual approval): $db->query("UPDATE withdraws_pending SET status = -1, error = 'PAYMENT IN PROCESS' WHERE id = " . $row['id']); $tx_id = $wallet->transfer($row['address'], $row['amount'], $row['payment_id'], $row['mixin'], $row['fee'], 0); $db->query('START TRANSACTION'); if (!$tx_id) { $errors = $wallet->get_errors(); $error_message = (isset($errors[0]) and isset($errors[0]['message'])) ? $errors[0]['message'] : 'Unknown error'; $db->query("UPDATE withdraws_pending SET error = " . quote_escape($error_message) . " WHERE id = " . $row['id']); } else { $sql = insert_query('withdraws_complete', array('user_id' => $row['user_id'], 'address' => $row['address'], 'amount' => $row['amount'], 'fee' => $row['fee'], 'date_paid' => array('UTC_TIMESTAMP()'), 'asset_id' => $row['asset_id'], 'mixin' => $row['mixin'], 'txn' => $tx_id)); $db->query($sql); $db->query("DELETE FROM withdraws_pending WHERE id = " . $row['id']); }
/** * Validates withdraw (minimum withdraw) * * @param string|float amount * @param string|float fee * @return bool */ public function valid_withdraw($amount, $fee) { global $config; $amount_after_fee = bc::op($amount, '-', $fee); // Check if amount after fee is negative if (bc::is($amount_after_fee, '=<', '0')) { return FALSE; } // Enforce minimum withdraw return (bool) (bccomp($amount, $config['asset'][$this->id]['min_withdraw']) !== -1); }