Spaces:
Paused
Paused
| // Configuration | |
| const API_BASE_URL = '/api'; // Use relative URL | |
| const UPDATE_INTERVAL = 1000; // 1 second | |
| const DEBUG = true; // Enable debug logging | |
| // Debug logger | |
| function debug(message, data = null) { | |
| if (DEBUG) { | |
| if (data) { | |
| console.log(`[Debug] ${message}`, data); | |
| } else { | |
| console.log(`[Debug] ${message}`); | |
| } | |
| } | |
| } | |
| // Chart configuration | |
| const chartConfig = { | |
| hashrate: { | |
| data: { | |
| labels: [], | |
| datasets: [{ | |
| label: 'Hashrate (KH/s)', | |
| data: [], | |
| borderColor: '#2ecc71', | |
| tension: 0.4, | |
| fill: false | |
| }] | |
| }, | |
| options: { | |
| responsive: true, | |
| maintainAspectRatio: false, | |
| scales: { | |
| y: { | |
| beginAtZero: true, | |
| grid: { | |
| color: 'rgba(255, 255, 255, 0.1)' | |
| } | |
| }, | |
| x: { | |
| grid: { | |
| color: 'rgba(255, 255, 255, 0.1)' | |
| } | |
| } | |
| }, | |
| plugins: { | |
| legend: { | |
| display: false | |
| } | |
| } | |
| } | |
| }, | |
| totalHashes: { | |
| data: { | |
| labels: [], | |
| datasets: [{ | |
| label: 'Total Hashes', | |
| data: [], | |
| borderColor: '#3498db', | |
| tension: 0.4, | |
| fill: false | |
| }] | |
| }, | |
| options: { | |
| responsive: true, | |
| maintainAspectRatio: false, | |
| scales: { | |
| y: { | |
| beginAtZero: true, | |
| grid: { | |
| color: 'rgba(255, 255, 255, 0.1)' | |
| } | |
| }, | |
| x: { | |
| grid: { | |
| color: 'rgba(255, 255, 255, 0.1)' | |
| } | |
| } | |
| }, | |
| plugins: { | |
| legend: { | |
| display: false | |
| } | |
| } | |
| } | |
| } | |
| }; | |
| // DOM Elements | |
| const elements = { | |
| startButton: document.getElementById('startButton'), | |
| stopButton: document.getElementById('stopButton'), | |
| statusText: document.getElementById('statusText'), | |
| statusDot: document.querySelector('.status-dot'), | |
| lastUpdate: document.getElementById('lastUpdate'), | |
| hashrateValue: document.getElementById('hashrateValue'), | |
| totalHashesValue: document.getElementById('totalHashesValue'), | |
| blocksFoundValue: document.getElementById('blocksFoundValue'), | |
| difficultyValue: document.getElementById('difficultyValue'), | |
| bestHashValue: document.getElementById('bestHashValue'), | |
| hashrateChart: document.getElementById('hashrateChart').getContext('2d'), | |
| totalHashesChart: document.getElementById('totalHashesChart').getContext('2d') | |
| }; | |
| // Initialize charts | |
| const charts = { | |
| hashrate: new Chart(elements.hashrateChart, chartConfig.hashrate), | |
| totalHashes: new Chart(elements.totalHashesChart, chartConfig.totalHashes) | |
| }; | |
| // Helper functions | |
| function formatNumber(num) { | |
| return num.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ","); | |
| } | |
| function updateLastUpdateTime() { | |
| const now = new Date(); | |
| elements.lastUpdate.textContent = now.toLocaleTimeString(); | |
| } | |
| function updateStatusIndicator(status) { | |
| elements.statusText.textContent = status; | |
| elements.statusDot.classList.toggle('active', status === 'Running'); | |
| } | |
| function updateCharts(hashrate, totalHashes) { | |
| const timestamp = new Date().toLocaleTimeString(); | |
| // Update hashrate chart | |
| if (chartConfig.hashrate.data.labels.length > 20) { | |
| chartConfig.hashrate.data.labels.shift(); | |
| chartConfig.hashrate.data.datasets[0].data.shift(); | |
| } | |
| chartConfig.hashrate.data.labels.push(timestamp); | |
| chartConfig.hashrate.data.datasets[0].data.push(hashrate); | |
| charts.hashrate.update(); | |
| // Update total hashes chart | |
| if (chartConfig.totalHashes.data.labels.length > 20) { | |
| chartConfig.totalHashes.data.labels.shift(); | |
| chartConfig.totalHashes.data.datasets[0].data.shift(); | |
| } | |
| chartConfig.totalHashes.data.labels.push(timestamp); | |
| chartConfig.totalHashes.data.datasets[0].data.push(totalHashes); | |
| charts.totalHashes.update(); | |
| } | |
| // API functions | |
| async function fetchStatus() { | |
| try { | |
| debug('Fetching status...'); | |
| const response = await fetch(`${API_BASE_URL}/status`); | |
| if (!response.ok) { | |
| throw new Error(`HTTP error! status: ${response.status}`); | |
| } | |
| const data = await response.json(); | |
| debug('Received status data:', data); | |
| // Update UI | |
| elements.hashrateValue.textContent = data.hashrate.toFixed(2); | |
| elements.totalHashesValue.textContent = formatNumber(data.total_hashes); | |
| elements.blocksFoundValue.textContent = data.blocks_found; | |
| elements.difficultyValue.textContent = formatNumber(data.difficulty); | |
| elements.bestHashValue.textContent = data.best_hash || 'None'; | |
| updateStatusIndicator(data.status); | |
| updateLastUpdateTime(); | |
| updateCharts(data.hashrate, data.total_hashes); | |
| debug('UI updated successfully'); | |
| } catch (error) { | |
| console.error('Error fetching status:', error); | |
| updateStatusIndicator('Error'); | |
| // Show error in UI | |
| elements.hashrateValue.textContent = 'ERR'; | |
| elements.totalHashesValue.textContent = 'ERR'; | |
| elements.blocksFoundValue.textContent = 'ERR'; | |
| elements.difficultyValue.textContent = 'ERR'; | |
| elements.bestHashValue.textContent = 'Error fetching data'; | |
| } | |
| } | |
| async function startMining() { | |
| try { | |
| debug('Starting mining...'); | |
| elements.startButton.disabled = true; | |
| const response = await fetch(`${API_BASE_URL}/start`, { | |
| method: 'POST', | |
| headers: { | |
| 'Content-Type': 'application/json' | |
| } | |
| }); | |
| if (!response.ok) { | |
| throw new Error(`HTTP error! status: ${response.status}`); | |
| } | |
| const data = await response.json(); | |
| debug('Mining started:', data); | |
| alert(data.message); | |
| } catch (error) { | |
| console.error('Error starting mining:', error); | |
| alert('Failed to start mining: ' + error.message); | |
| } finally { | |
| elements.startButton.disabled = false; | |
| } | |
| } | |
| async function stopMining() { | |
| try { | |
| debug('Stopping mining...'); | |
| elements.stopButton.disabled = true; | |
| const response = await fetch(`${API_BASE_URL}/stop`, { | |
| method: 'POST', | |
| headers: { | |
| 'Content-Type': 'application/json' | |
| } | |
| }); | |
| if (!response.ok) { | |
| throw new Error(`HTTP error! status: ${response.status}`); | |
| } | |
| const data = await response.json(); | |
| debug('Mining stopped:', data); | |
| alert(data.message); | |
| } catch (error) { | |
| console.error('Error stopping mining:', error); | |
| alert('Failed to stop mining: ' + error.message); | |
| } finally { | |
| elements.stopButton.disabled = false; | |
| } | |
| } | |
| // Event listeners | |
| elements.startButton.addEventListener('click', startMining); | |
| elements.stopButton.addEventListener('click', stopMining); | |
| // Start periodic updates | |
| setInterval(fetchStatus, UPDATE_INTERVAL); | |
| // Initial status fetch | |
| fetchStatus(); |