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 Google Fonts */
|
||||||
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap');
|
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap');
|
||||||
|
|
||||||
@ -45,3 +44,22 @@ body {
|
|||||||
.badge {
|
.badge {
|
||||||
font-weight: 600;
|
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.
|
const liveRow = document.getElementById('live-crypto-row');
|
||||||
// This file is ready for future interactivity.
|
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>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<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
|
<?php
|
||||||
|
// Static mock data for UI variety
|
||||||
$mock_data = [
|
$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' => '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' => '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'],
|
['exchange' => 'KuCoin', 'symbol' => 'SOL/USDT', 'price' => '165.80', 'change' => -1.2, 'signal' => 'Bearish Reversal'],
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user