V1.11
This commit is contained in:
parent
98db9c4cf7
commit
e44c880941
68
api/ticker.php
Normal file
68
api/ticker.php
Normal file
@ -0,0 +1,68 @@
|
||||
<?php
|
||||
header('Content-Type: application/json');
|
||||
|
||||
// --- Configuration ---
|
||||
$symbol = 'BTCUSDT_SPBL'; // Bitget symbol for BTC/USDT spot market
|
||||
$api_url = "https://api.bitget.com/api/v2/spot/market/tickers?symbol=" . $symbol;
|
||||
|
||||
// --- cURL Execution ---
|
||||
$ch = curl_init();
|
||||
curl_setopt_array($ch, [
|
||||
CURLOPT_URL => $api_url,
|
||||
CURLOPT_RETURNTRANSFER => true,
|
||||
CURLOPT_TIMEOUT => 10,
|
||||
CURLOPT_HTTPHEADER => [
|
||||
'Accept: application/json'
|
||||
],
|
||||
// It's good practice to set a user-agent
|
||||
CURLOPT_USERAGENT => 'FlatlogicMarketDetector/1.0'
|
||||
]);
|
||||
|
||||
$response = curl_exec($ch);
|
||||
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||
$error = curl_error($ch);
|
||||
curl_close($ch);
|
||||
|
||||
// --- Response Handling ---
|
||||
if ($error) {
|
||||
http_response_code(500);
|
||||
echo json_encode(['error' => 'cURL Error: ' . $error]);
|
||||
exit;
|
||||
}
|
||||
|
||||
if ($http_code !== 200) {
|
||||
http_response_code($http_code);
|
||||
echo json_encode(['error' => 'Bitget API returned non-200 status', 'details' => json_decode($response)]);
|
||||
exit;
|
||||
}
|
||||
|
||||
$data = json_decode($response, true);
|
||||
|
||||
// --- Data Validation & Output ---
|
||||
if (json_last_error() !== JSON_ERROR_NONE || empty($data['data'])) {
|
||||
http_response_code(500);
|
||||
echo json_encode(['error' => 'Failed to parse JSON response or data is empty']);
|
||||
exit;
|
||||
}
|
||||
|
||||
// Extract the first ticker object from the response data array
|
||||
$ticker_data = $data['data'][0] ?? null;
|
||||
|
||||
if (!$ticker_data) {
|
||||
http_response_code(404);
|
||||
echo json_encode(['error' => 'Ticker data for symbol not found in API response']);
|
||||
exit;
|
||||
}
|
||||
|
||||
// --- Sanitize and Structure Output ---
|
||||
// We select and sanitize the fields we want to send to the frontend.
|
||||
$output = [
|
||||
'exchange' => 'Bitget',
|
||||
'symbol' => $ticker_data['symbol'] ?? 'N/A',
|
||||
'price' => $ticker_data['lastPr'] ?? '0.00',
|
||||
// Bitget provides the 24h change as a decimal, e.g., 0.025 for +2.5%
|
||||
'change_24h_percent' => isset($ticker_data['priceChangePercent']) ? (float)$ticker_data['priceChangePercent'] * 100 : 0,
|
||||
'signal' => '-' // Placeholder for future signal detection
|
||||
];
|
||||
|
||||
echo json_encode($output);
|
||||
@ -1,4 +1,3 @@
|
||||
|
||||
/* Import Google Fonts */
|
||||
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap');
|
||||
|
||||
@ -45,3 +44,22 @@ body {
|
||||
.badge {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
/* Price flash animations */
|
||||
@keyframes flash-success-anim {
|
||||
from { background-color: rgba(25, 135, 84, 0.2); }
|
||||
to { background-color: transparent; }
|
||||
}
|
||||
|
||||
.flash-success {
|
||||
animation: flash-success-anim 0.75s ease-out;
|
||||
}
|
||||
|
||||
@keyframes flash-danger-anim {
|
||||
from { background-color: rgba(220, 53, 69, 0.2); }
|
||||
to { background-color: transparent; }
|
||||
}
|
||||
|
||||
.flash-danger {
|
||||
animation: flash-danger-anim 0.75s ease-out;
|
||||
}
|
||||
@ -1,3 +1,68 @@
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
const POLLING_INTERVAL = 3000; // 3 seconds
|
||||
|
||||
// No custom JavaScript needed for the initial static dashboard.
|
||||
// This file is ready for future interactivity.
|
||||
const liveRow = document.getElementById('live-crypto-row');
|
||||
if (!liveRow) {
|
||||
console.error('Live crypto row with ID #live-crypto-row not found.');
|
||||
return;
|
||||
}
|
||||
|
||||
// Select cells to update
|
||||
const priceCell = liveRow.querySelector('.price');
|
||||
const changeCell = liveRow.querySelector('.change');
|
||||
const symbolCell = liveRow.querySelector('.symbol');
|
||||
const exchangeCell = liveRow.querySelector('.exchange');
|
||||
|
||||
let lastPrice = 0;
|
||||
|
||||
async function fetchLivePrice() {
|
||||
try {
|
||||
const response = await fetch('api/ticker.php');
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! Status: ${response.status}`);
|
||||
}
|
||||
const data = await response.json();
|
||||
|
||||
if (data.error) {
|
||||
throw new Error(`API Error: ${data.error}`);
|
||||
}
|
||||
|
||||
updateRow(data);
|
||||
|
||||
} catch (error) {
|
||||
console.error('Failed to fetch live price:', error);
|
||||
// Optionally, display an error state in the UI
|
||||
priceCell.textContent = 'Error';
|
||||
changeCell.textContent = '--';
|
||||
}
|
||||
}
|
||||
|
||||
function updateRow(data) {
|
||||
const currentPrice = parseFloat(data.price);
|
||||
const priceChange = currentPrice - lastPrice;
|
||||
|
||||
// Update text content
|
||||
priceCell.textContent = `$${currentPrice.toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 })}`;
|
||||
symbolCell.textContent = data.symbol.replace('_SPBL', ''); // Clean up symbol name
|
||||
exchangeCell.textContent = data.exchange;
|
||||
|
||||
// Update 24h change
|
||||
const changePercent = parseFloat(data.change_24h_percent);
|
||||
changeCell.textContent = `${changePercent.toFixed(2)}%`;
|
||||
changeCell.classList.toggle('text-success', changePercent >= 0);
|
||||
changeCell.classList.toggle('text-danger', changePercent < 0);
|
||||
|
||||
// Visual flash on price change
|
||||
if (lastPrice !== 0 && priceChange !== 0) {
|
||||
const flashClass = priceChange > 0 ? 'flash-success' : 'flash-danger';
|
||||
priceCell.classList.add(flashClass);
|
||||
setTimeout(() => priceCell.classList.remove(flashClass), 750);
|
||||
}
|
||||
|
||||
lastPrice = currentPrice;
|
||||
}
|
||||
|
||||
// Initial fetch and start polling
|
||||
fetchLivePrice();
|
||||
setInterval(fetchLivePrice, POLLING_INTERVAL);
|
||||
});
|
||||
20
index.php
20
index.php
@ -54,9 +54,27 @@
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<!-- Live Row (Updated by JavaScript) -->
|
||||
<tr id="live-crypto-row">
|
||||
<td class="fw-medium text-muted exchange">Bitget</td>
|
||||
<td>
|
||||
<div class="d-flex align-items-center">
|
||||
<img src="https://via.placeholder.com/24/0d6efd/FFFFFF?Text=B" class="symbol-logo rounded-circle" alt="">
|
||||
<span class="fw-bold symbol">BTC/USDT</span>
|
||||
</div>
|
||||
</td>
|
||||
<td class="fw-bold fs-5 price">$0.00</td>
|
||||
<td class="text-center">
|
||||
<span class="fw-bold change">
|
||||
--%
|
||||
</span>
|
||||
</td>
|
||||
<td class="text-end signal">-</td>
|
||||
</tr>
|
||||
|
||||
<?php
|
||||
// Static mock data for UI variety
|
||||
$mock_data = [
|
||||
['exchange' => 'KCEX', 'symbol' => 'BTC/USDT', 'price' => '68,123.45', 'change' => 2.5, 'signal' => null],
|
||||
['exchange' => 'Bitget', 'symbol' => 'ETH/USDT', 'price' => '3,789.12', 'change' => -21.8, 'signal' => 'Crash Alert'],
|
||||
['exchange' => 'WEEX', 'symbol' => 'PEPE/USDT', 'price' => '0.00001234', 'change' => 255.1, 'signal' => 'Pump Alert'],
|
||||
['exchange' => 'KuCoin', 'symbol' => 'SOL/USDT', 'price' => '165.80', 'change' => -1.2, 'signal' => 'Bearish Reversal'],
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user