diff --git a/api/balance.php b/api/balance.php new file mode 100644 index 0000000..7c11dcd --- /dev/null +++ b/api/balance.php @@ -0,0 +1,21 @@ + false, 'error' => 'Unauthorized']); + exit; +} + +$symbol = $_GET['symbol'] ?? 'USDT'; +$symbol = strtoupper($symbol); + +$stmt = db()->prepare("SELECT available FROM user_balances WHERE user_id = ? AND symbol = ?"); +$stmt->execute([$_SESSION['user_id'], $symbol]); +$balance = $stmt->fetch(); + +echo json_encode([ + 'success' => true, + 'available' => $balance ? (float)$balance['available'] : 0.00 +]); diff --git a/api/mining.php b/api/mining.php new file mode 100644 index 0000000..edfdedc --- /dev/null +++ b/api/mining.php @@ -0,0 +1,68 @@ + false, 'error' => __('unauthorized')]); + exit; +} + +$input = json_decode(file_get_contents('php://input'), true); + +if (!$input || empty($input['symbol']) || empty($input['amount'])) { + echo json_encode(['success' => false, 'error' => __('fill_all_fields')]); + exit; +} + +$userId = $_SESSION['user_id']; +$symbol = strtoupper($input['symbol']); +$poolName = $input['pool_name']; +$amount = (float)$input['amount']; +$apy = (float)str_replace('%', '', $input['apy']); +$periodStr = $input['period']; +$dailyProfit = $apy / 365; + +// Check balance +$stmt = db()->prepare("SELECT available FROM user_balances WHERE user_id = ? AND symbol = ?"); +$stmt->execute([$userId, $symbol]); +$balance = $stmt->fetch(); + +if (!$balance || $balance['available'] < $amount) { + echo json_encode(['success' => false, 'error' => __('insufficient_balance')]); + exit; +} + +try { + $db = db(); + $db->beginTransaction(); + + // Deduct balance + $stmt = $db->prepare("UPDATE user_balances SET available = available - ?, frozen = frozen + ? WHERE user_id = ? AND symbol = ?"); + $stmt->execute([$amount, $amount, $userId, $symbol]); + + // Create staking record + $period = 0; + if (preg_match('/(\d+)/', $periodStr, $matches)) { + $period = (int)$matches[1]; + } else { + $period = 0; // flexible + } + + $startDate = date('Y-m-d'); + $endDate = date('Y-m-d', strtotime("+$period days")); + if ($period == 0) $endDate = '2099-12-31'; + + $stmt = $db->prepare("INSERT INTO staking_records (user_id, plan_name, amount, symbol, daily_profit, period, status, start_date, end_date) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)"); + $stmt->execute([$userId, $poolName, $amount, $symbol, $dailyProfit, $period, 'running', $startDate, $endDate]); + + // Add transaction record + $stmt = $db->prepare("INSERT INTO transactions (user_id, symbol, type, amount, status) VALUES (?, ?, ?, ?, ?)"); + $stmt->execute([$userId, $symbol, 'mining', $amount, 'completed']); + + $db->commit(); + echo json_encode(['success' => true]); +} catch (Exception $e) { + $db->rollBack(); + echo json_encode(['success' => false, 'error' => $e->getMessage()]); +} diff --git a/app.php b/app.php index 26332db..2d2fd23 100644 --- a/app.php +++ b/app.php @@ -28,87 +28,100 @@ if (isset($_GET['action']) && $_GET['action'] === 'download') { ?>
-
-
+
+ +
+
+
+ +
-

- +

+

-

+

-
-
+
+
- QR + QR
-
-
-

+
+
+

+
+
+
+
+
-
+
-
-
+
+
-
-
+
+
-
-
-
+
BTC/USDT
+
Secure
+
Fast
+ + +
@@ -116,32 +129,32 @@ if (isset($_GET['action']) && $_GET['action'] === 'download') {
-
-
+
+
-

-

+

+

-
-
01
+
+
01

-

+

-
-
02
+
+
02

-

+

-
-
03
+
+
03

-

+

@@ -149,39 +162,40 @@ if (isset($_GET['action']) && $_GET['action'] === 'download') {
-
+
-
-
+
+
-

+

-
-
+
+
-

+

-
-
+
+
-

+

+
diff --git a/assets/pasted-20260219-073456-0e79a370.png b/assets/pasted-20260219-073456-0e79a370.png new file mode 100644 index 0000000..4e22489 Binary files /dev/null and b/assets/pasted-20260219-073456-0e79a370.png differ diff --git a/assets/pasted-20260219-080909-f22812cc.png b/assets/pasted-20260219-080909-f22812cc.png new file mode 100644 index 0000000..fc95ead Binary files /dev/null and b/assets/pasted-20260219-080909-f22812cc.png differ diff --git a/assets/pasted-20260219-081544-37a22a14.png b/assets/pasted-20260219-081544-37a22a14.png new file mode 100644 index 0000000..d0a1762 Binary files /dev/null and b/assets/pasted-20260219-081544-37a22a14.png differ diff --git a/assets/pasted-20260219-082349-d2b06418.png b/assets/pasted-20260219-082349-d2b06418.png new file mode 100644 index 0000000..596e489 Binary files /dev/null and b/assets/pasted-20260219-082349-d2b06418.png differ diff --git a/assets/pasted-20260219-082954-46ef5781.png b/assets/pasted-20260219-082954-46ef5781.png new file mode 100644 index 0000000..9e50f11 Binary files /dev/null and b/assets/pasted-20260219-082954-46ef5781.png differ diff --git a/db/migrations/20260219_create_mining_orders.php b/db/migrations/20260219_create_mining_orders.php new file mode 100644 index 0000000..2fd8283 --- /dev/null +++ b/db/migrations/20260219_create_mining_orders.php @@ -0,0 +1,24 @@ +exec("CREATE TABLE IF NOT EXISTS mining_orders ( + id INT AUTO_INCREMENT PRIMARY KEY, + user_id INT NOT NULL, + symbol VARCHAR(10) NOT NULL, + pool_name VARCHAR(100) NOT NULL, + amount DECIMAL(20, 8) NOT NULL, + apy DECIMAL(10, 4) NOT NULL, + period VARCHAR(20) NOT NULL, + status VARCHAR(20) DEFAULT 'running', + start_time DATETIME DEFAULT CURRENT_TIMESTAMP, + end_time DATETIME, + last_payout DATETIME DEFAULT CURRENT_TIMESTAMP, + total_profit DECIMAL(20, 8) DEFAULT 0 + )"); + echo "Table mining_orders created successfully.\n"; +} catch (Exception $e) { + echo "Error creating table: " . $e->getMessage() . "\n"; +} diff --git a/includes/header.php b/includes/header.php index 6a87a15..8ca2981 100644 --- a/includes/header.php +++ b/includes/header.php @@ -336,10 +336,34 @@ if (isset($_SESSION['user_id'])) { 'ATOM': '1481/small/cosmos.png', 'IMX': '17233/small/immutable-x.png', 'KAS': '26851/small/kaspa.png', + 'DAI': '992/small/dai.png', + 'STX': '2069/small/stacks.png', + 'RNDR': '11634/small/render-token.png', + 'INJ': '12882/small/injective_protocol.png', + 'TIA': '31967/small/tia.png', + 'SUI': '26375/small/sui-ocean-64.png', + 'SEI': '31322/small/sei.png', }; function getCoinIconJs(symbol) { - const id = window.coinIcons[symbol.toUpperCase()] || '1/small/bitcoin.png'; - return "https://assets.coingecko.com/coins/images/" + id; + symbol = symbol.toUpperCase(); + const id = window.coinIcons[symbol]; + if (id) { + return "https://coin-images.coingecko.com/coins/images/" + id; + } + // Fallback to Binance CDN + return "https://bin.bnbstatic.com/static/images/home/market/coin-icon/" + symbol + ".png"; + } + function handleIconError(img, symbol) { + if (!img.triedOKX) { + img.triedOKX = true; + img.src = "https://static.okx.com/cdn/oksupport/asset/currency/icon/" + symbol.toLowerCase() + ".png"; + } else if (!img.triedCrypto) { + img.triedCrypto = true; + img.src = "https://assets.coincap.io/assets/icons/" + symbol.toLowerCase() + "@2x.png"; + } else { + img.src = 'https://coin-images.coingecko.com/coins/images/1/small/bitcoin.png'; + img.onerror = null; + } } diff --git a/includes/lang.php b/includes/lang.php index 40d7394..c60a315 100644 --- a/includes/lang.php +++ b/includes/lang.php @@ -377,6 +377,7 @@ $translations = [ 'limit' => '限价', 'amount' => '数量', 'operation' => '操作', + 'action' => '操作', 'frozen' => '冻结', 'converted_to' => '折合', 'asset_records' => '资产记录', @@ -386,6 +387,9 @@ $translations = [ 'time' => '时间', 'hot' => '热门', 'executing' => '进行中', + 'running' => '运行中', + 'pool_name' => '矿池名称', + 'my_mining_orders' => '我的矿池订单', 'won' => '盈利', 'loss' => '亏损', 'total' => '总计', @@ -886,6 +890,7 @@ $translations = [ 'limit' => 'Limit', 'amount' => 'Amount', 'operation' => 'Operation', + 'action' => 'Action', 'frozen' => 'Frozen', 'converted_to' => 'Converted', 'asset_records' => 'Asset Records', @@ -895,6 +900,9 @@ $translations = [ 'time' => 'Time', 'hot' => 'Hot', 'executing' => 'Executing', + 'running' => 'Running', + 'pool_name' => 'Pool Name', + 'my_mining_orders' => 'My Mining Orders', 'won' => 'Won', 'loss' => 'Loss', 'total' => 'Total', @@ -1020,6 +1028,7 @@ function __($key) { } function getCoinIcon($symbol) { + $symbol = strtoupper($symbol); $icon_ids = [ 'BTC' => '1/small/bitcoin.png', 'ETH' => '279/small/ethereum.png', @@ -1048,7 +1057,20 @@ function getCoinIcon($symbol) { 'ATOM' => '1481/small/cosmos.png', 'IMX' => '17233/small/immutable-x.png', 'KAS' => '26851/small/kaspa.png', + 'DAI' => '992/small/dai.png', + 'STX' => '2069/small/stacks.png', + 'RNDR' => '11634/small/render-token.png', + 'INJ' => '12882/small/injective_protocol.png', + 'TIA' => '31967/small/tia.png', + 'SUI' => '26375/small/sui-ocean-64.png', + 'SEI' => '31322/small/sei.png', ]; - $id = $icon_ids[strtoupper($symbol)] ?? '1/small/bitcoin.png'; - return "https://assets.coingecko.com/coins/images/" . $id; + + if (isset($icon_ids[$symbol])) { + return "https://coin-images.coingecko.com/coins/images/" . $icon_ids[$symbol]; + } + + // Fallback order: Binance -> OKX + // Binance is very reliable for symbols + return "https://bin.bnbstatic.com/static/images/home/market/coin-icon/" . $symbol . ".png"; } diff --git a/includes/terminal_layout.php b/includes/terminal_layout.php index 67a1f7d..00900c3 100644 --- a/includes/terminal_layout.php +++ b/includes/terminal_layout.php @@ -78,7 +78,7 @@ function renderTerminal($activeTab = 'spot') {
- <?= $coin['symbol'] ?> + <?= $coin['symbol'] ?>
@@ -105,19 +105,19 @@ function renderTerminal($activeTab = 'spot') {
- + --
- + --
- + --
- + --
@@ -155,7 +155,7 @@ function renderTerminal($activeTab = 'spot') { tvWidget = new TradingView.widget( { "autosize": true, - "symbol": "BINANCE:USDT", + "symbol": "", "interval": "1", "timezone": "Etc/UTC", "theme": "dark", @@ -859,7 +859,7 @@ function renderTerminal($activeTab = 'spot') { row.innerHTML = `
- ${symbol} + ${symbol}
${symbol}
diff --git a/index.php b/index.php index e1eaed6..28f7d69 100644 --- a/index.php +++ b/index.php @@ -187,7 +187,7 @@ require_once __DIR__ . '/includes/header.php';
- <?php echo $coin['symbol']; ?> + <?php echo $coin['symbol']; ?> /USDT
@@ -348,32 +348,50 @@ function updateUI(symbol, price, change) { badge.className = `change-badge badge ${change >= 0 ? 'bg-success' : 'bg-danger'}`; } -// Sparklines -document.querySelectorAll('.sparkline-canvas').forEach(canvas => { - const ctx = canvas.getContext('2d'); - const isUp = Math.random() > 0.4; - new Chart(ctx, { - type: 'line', - data: { - labels: new Array(10).fill(''), - datasets: [{ - data: new Array(10).fill(0).map(() => Math.random() * 100), - borderColor: isUp ? '#26a69a' : '#ef5350', - borderWidth: 2, - pointRadius: 0, - fill: true, - backgroundColor: isUp ? 'rgba(38, 166, 154, 0.1)' : 'rgba(239, 83, 80, 0.1)', - tension: 0.4 - }] - }, - options: { - plugins: { legend: { display: false } }, - scales: { x: { display: false }, y: { display: false } }, - maintainAspectRatio: false +// Sparklines with real data +async function initSparklines() { + const symbols = ['BTCUSDT', 'ETHUSDT', 'BNBUSDT', 'SOLUSDT', 'XRPUSDT', 'ADAUSDT', 'DOGEUSDT', 'DOTUSDT', 'MATICUSDT', 'LINKUSDT', 'SHIBUSDT']; + + for (const symbol of symbols) { + try { + const response = await fetch(`https://api.binance.com/api/v3/klines?symbol=${symbol}&interval=1h&limit=20`); + const data = await response.json(); + const prices = data.map(d => parseFloat(d[4])); + const s = symbol.replace('USDT', ''); + const canvas = document.getElementById(`spark-${s}`); + if (!canvas) continue; + + const ctx = canvas.getContext('2d'); + const isUp = prices[prices.length - 1] >= prices[0]; + + new Chart(ctx, { + type: 'line', + data: { + labels: new Array(prices.length).fill(''), + datasets: [{ + data: prices, + borderColor: isUp ? '#0ecb81' : '#f6465d', + borderWidth: 2, + pointRadius: 0, + fill: true, + backgroundColor: isUp ? 'rgba(14, 203, 129, 0.1)' : 'rgba(246, 70, 93, 0.1)', + tension: 0.4 + }] + }, + options: { + plugins: { legend: { display: false }, tooltip: { enabled: false } }, + scales: { x: { display: false }, y: { display: false } }, + maintainAspectRatio: false, + responsive: true + } + }); + } catch (err) { + console.error(`Failed to fetch sparkline for ${symbol}:`, err); } - }); -}); + } +} +initSparklines(); initPriceUpdate(); diff --git a/market.php b/market.php index a689b90..48db86e 100644 --- a/market.php +++ b/market.php @@ -12,8 +12,8 @@ require_once __DIR__ . '/includes/header.php'; - - + + @@ -44,7 +44,7 @@ require_once __DIR__ . '/includes/header.php';
- <?= $coin['symbol'] ?> + <?= $coin['symbol'] ?>
@@ -52,11 +52,13 @@ require_once __DIR__ . '/includes/header.php';
- $ - + $ + - + + + @@ -70,23 +72,101 @@ require_once __DIR__ . '/includes/header.php';
- + <?= $coin['symbol'] ?>
-
$
+
$
-
+
+ + diff --git a/mining.php b/mining.php index 971f320..3cbee72 100644 --- a/mining.php +++ b/mining.php @@ -5,7 +5,7 @@ require_once __DIR__ . '/includes/header.php';

-

+

@@ -30,38 +30,224 @@ require_once __DIR__ . '/includes/header.php';
- + <?= $pool['symbol'] ?>
- +
- +
- +
-
+
- +
+ + + + +