PHP WebShell
Текущая директория: /var/www/bitcardoApp/models/crypto
Просмотр файла: swap.php
<?php
session_start();
// models/crypto/swap.php
require_once "../../config/db_config.php";
if (!isset($_SESSION['user_id'])) {
header("Location: login.php");
exit();
}
$user_id = (int)$_SESSION['user_id'];
$from = strtoupper(trim($_POST['currencyFrom'] ?? ''));
$to = strtoupper(trim($_POST['currencyTo'] ?? ''));
$amount = (float)($_POST['fromAmount'] ?? 0);
if (!$from || !$to || $amount <= 0 || $from === $to) {
exit("Invalid swap input.");
}
if (!empty($_SESSION['swap_lock'])) {
exit("Please wait, a swap is already in progress.");
}
$_SESSION['swap_lock'] = true;
// -- helpers -------------------------------------------------
function fetchRate(mysqli $conn, string $coin, string $col = 'buy_rate'): float {
$col = in_array($col, ['buy_rate', 'sell_rate'], true) ? $col : 'buy_rate';
$coin = strtoupper($coin);
$stmt = $conn->prepare("SELECT $col FROM coin_rates WHERE UPPER(coin) = ?");
$stmt->bind_param("s", $coin);
$stmt->execute();
$row = $stmt->get_result()->fetch_assoc();
$stmt->close();
return (float)($row[$col] ?? 0);
}
function fetchMinSwap(mysqli $conn, string $coin): float {
$coin = strtoupper($coin);
$stmt = $conn->prepare("SELECT COALESCE(min_swap,0) AS m FROM coin_rates WHERE UPPER(coin) = ?");
$stmt->bind_param("s", $coin);
$stmt->execute();
$row = $stmt->get_result()->fetch_assoc();
$stmt->close();
return (float)($row['m'] ?? 0);
}
// -- load wallets -------------------------------------------
$stmt = $conn->prepare("SELECT wallet_id, balance, wallet_add FROM user_wallets WHERE user_id = ? AND UPPER(coin) = ?");
$stmt->bind_param("is", $user_id, $from);
$stmt->execute();
$fromWallet = $stmt->get_result()->fetch_assoc();
$stmt->close();
if (!$fromWallet || (float)$fromWallet['balance'] < $amount) {
$_SESSION['swap_lock'] = false;
exit("Insufficient balance.");
}
$from_wallet_id = (int)$fromWallet['wallet_id'];
$from_address = $fromWallet['wallet_add'];
$stmt = $conn->prepare("SELECT wallet_id, wallet_add FROM user_wallets WHERE user_id = ? AND UPPER(coin) = ?");
$stmt->bind_param("is", $user_id, $to);
$stmt->execute();
$toWallet = $stmt->get_result()->fetch_assoc();
$stmt->close();
if (!$toWallet) {
$_SESSION['swap_lock'] = false;
exit("Destination wallet not found.");
}
$to_wallet_id = (int)$toWallet['wallet_id'];
$to_address = $toWallet['wallet_add'];
// -- enforce min_swap ---------------------------------------
// NGN min is in Naira; all other coins’ min_swap is in USD.
// Compare NGN directly; for others, convert FROM amount to USDT using FROM.buy_rate.
$min_swap_from = fetchMinSwap($conn, $from);
if ($min_swap_from > 0) {
if ($from === 'NGN') {
if ($amount < $min_swap_from) {
$_SESSION['swap_lock'] = false;
exit("Minimum swap amount for NGN is ₦" . number_format($min_swap_from, 0));
}
} else {
// amount_in_usdt = amount * (USDT per FROM) using buy_rate
$from_buy = fetchRate($conn, $from, 'buy_rate'); // USDT / FROM
$amount_usdt = $amount * $from_buy;
if ($amount_usdt < $min_swap_from) {
$_SESSION['swap_lock'] = false;
exit("Minimum swap amount for $from is $" . number_format($min_swap_from, 2));
}
}
}
// -- rate logic (OLD NGN<->USDT math, extended to NGN<->(BTC|SOL|ETH)) ----
$rate = 0.0;
$to_amount = 0.0;
// Case A: USDT <-> NGN (OLD logic)
if (($from === 'USDT' && $to === 'NGN') || ($from === 'NGN' && $to === 'USDT')) {
if ($from === 'USDT') {
// USDT → NGN: multiply by NGN.sell_rate
$rate = fetchRate($conn, 'NGN', 'sell_rate'); // NGN / 1 USDT
$to_amount = $rate > 0 ? $amount * $rate : 0.0;
} else { // NGN -> USDT
// NGN → USDT: divide by NGN.buy_rate
$rate = fetchRate($conn, 'NGN', 'buy_rate'); // NGN / 1 USDT
$to_amount = $rate > 0 ? $amount / $rate : 0.0;
}
// Case B: NGN -> (BTC|SOL|ETH) via USDT (OLD math extended)
} elseif ($from === 'NGN' && in_array($to, ['BTC','SOL','ETH','USDT'], true)) {
if ($to === 'USDT') {
// Handled above; but if we get here due to logic order, do the same:
$rate = fetchRate($conn, 'NGN', 'buy_rate');
$to_amount = $rate > 0 ? $amount / $rate : 0.0;
} else {
// NGN → USDT (divide by NGN.buy_rate), then USDT → COIN (divide by COIN.sell_rate)
$ngn_buy = fetchRate($conn, 'NGN', 'buy_rate'); // NGN / USDT
$coin_sell = fetchRate($conn, $to, 'sell_rate'); // USDT / COIN
$usdt = $ngn_buy > 0 ? ($amount / $ngn_buy) : 0.0;
$to_amount = ($coin_sell > 0) ? ($usdt / $coin_sell) : 0.0;
// Composite rate (optional, for record): COIN per NGN
$rate = ($ngn_buy > 0 && $coin_sell > 0) ? (1.0 / $ngn_buy) / $coin_sell : 0.0;
}
// Case C: (BTC|SOL|ETH) -> NGN via USDT (OLD math extended)
} elseif (in_array($from, ['BTC','SOL','ETH','USDT'], true) && $to === 'NGN') {
if ($from === 'USDT') {
// USDT → NGN: multiply by NGN.sell_rate
$rate = fetchRate($conn, 'NGN', 'sell_rate'); // NGN / USDT
$to_amount = $rate > 0 ? $amount * $rate : 0.0;
} else {
// COIN → USDT (multiply by COIN.buy_rate), then USDT → NGN (multiply by NGN.sell_rate)
$coin_buy = fetchRate($conn, $from, 'buy_rate'); // USDT / COIN
$ngn_sell = fetchRate($conn, 'NGN', 'sell_rate'); // NGN / USDT
$usdt = $amount * $coin_buy;
$to_amount = $usdt * $ngn_sell;
// Composite rate (optional): NGN per COIN
$rate = $coin_buy * $ngn_sell;
}
// Case D: everything else (existing logic retained)
} else {
if ($to === 'USDT') {
// Coin → USDT: use buy_rate of coin
$rate = fetchRate($conn, $from, 'buy_rate'); // USDT / FROM
$to_amount = $amount * $rate;
} elseif ($from === 'USDT') {
// USDT → Coin: use sell_rate of coin
$rate = fetchRate($conn, $to, 'sell_rate'); // USDT / TO
$to_amount = $rate > 0 ? $amount / $rate : 0.0;
} else {
// Coin → Coin: from → USDT (buy_rate), then USDT → to (sell_rate)
$buy_rate = fetchRate($conn, $from, 'buy_rate'); // USDT / FROM
$sell_rate = fetchRate($conn, $to, 'sell_rate'); // USDT / TO
$usdt_value = $amount * $buy_rate;
$to_amount = $sell_rate > 0 ? $usdt_value / $sell_rate : 0.0;
$rate = ($buy_rate > 0 && $sell_rate > 0) ? ($buy_rate / $sell_rate) : 0.0;
}
}
// Final validation
if ($to_amount <= 0) {
$_SESSION['swap_lock'] = false;
exit("Failed to fetch swap rate.");
}
$swap_id = uniqid("", true);
$conn->begin_transaction();
try {
// Deduct FROM
$stmt = $conn->prepare("UPDATE user_wallets SET balance = balance - ? WHERE wallet_id = ?");
$stmt->bind_param("di", $amount, $from_wallet_id);
$stmt->execute();
$stmt->close();
// Credit TO
$stmt = $conn->prepare("UPDATE user_wallets SET balance = balance + ? WHERE wallet_id = ?");
$stmt->bind_param("di", $to_amount, $to_wallet_id);
$stmt->execute();
$stmt->close();
// Log swap
$stmt = $conn->prepare("INSERT INTO swap_transactions
(swap_id, user_id, from_coin, to_coin, from_amount, to_amount, rate_used, created_at)
VALUES (?, ?, ?, ?, ?, ?, ?, NOW())");
$stmt->bind_param("sissdds", $swap_id, $user_id, $from, $to, $amount, $to_amount, $rate);
$stmt->execute();
$stmt->close();
// Log send
$txid1 = uniqid("txid_", true);
$stmt = $conn->prepare("INSERT INTO transactions
(coin, wallet_id, sender_address, receiver_address, amount, type, txid, confirmation, status, applied, swap_id, note, created_at)
VALUES (?, ?, ?, ?, ?, 'send', ?, 0, 'completed', 1, ?, 'Swap out', NOW())");
$stmt->bind_param("sissdss", $from, $from_wallet_id, $from_address, $to_address, $amount, $txid1, $swap_id);
$stmt->execute();
$stmt->close();
// Log receive
$txid2 = uniqid("txid_", true);
$stmt = $conn->prepare("INSERT INTO transactions
(coin, wallet_id, sender_address, receiver_address, amount, type, txid, confirmation, status, applied, swap_id, note, created_at)
VALUES (?, ?, ?, ?, ?, 'receive', ?, 0, 'completed', 1, ?, 'Swap in', NOW())");
$stmt->bind_param("sissdss", $to, $to_wallet_id, $from_address, $to_address, $to_amount, $txid2, $swap_id);
$stmt->execute();
$stmt->close();
$conn->commit();
$_SESSION['swap_lock'] = false;
$_SESSION['swap_success'] = [
'amount' => $amount,
'from' => $from,
'to_amount' => $to_amount,
'to' => $to,
'rate' => $rate,
'swap_id' => $swap_id,
'from_address' => $from_address,
'to_address' => $to_address,
'timestamp' => date('M j, Y • h:i A'),
];
header("Location: ../../user/wallets/swap_success.php");
exit;
} catch (Exception $e) {
$conn->rollback();
$_SESSION['swap_lock'] = false;
exit("Swap failed: " . $e->getMessage());
}
Выполнить команду
Для локальной разработки. Не используйте в интернете!