import { useEffect, useState } from 'react'; import { Hammer, Play, Pause, Square, Cpu, Blocks, TrendingUp, Clock, Zap, } from 'lucide-react'; import { useMiningStore, formatHashrate } from '../../store/mining'; import { useNodeStore } from '../../store/node'; import { useWalletStore } from '../../store/wallet'; export default function MiningDashboard() { const { status, recentBlocks, hashrateHistory, defaultThreads, defaultCoinbaseAddress, startMining, stopMining, pauseMining, resumeMining, setThreads, refreshStatus, refreshStats, setupEventListeners, cleanupEventListeners, } = useMiningStore(); const nodeStatus = useNodeStore((state) => state.status); const addresses = useWalletStore((state) => state.addresses); const [threads, setThreadsLocal] = useState(defaultThreads); const [coinbaseAddress, setCoinbaseAddress] = useState( defaultCoinbaseAddress || addresses[0]?.address || '' ); const [isStarting, setIsStarting] = useState(false); const [error, setError] = useState(null); // Max threads available const maxThreads = navigator.hardwareConcurrency || 8; // Setup event listeners on mount useEffect(() => { setupEventListeners(); return () => cleanupEventListeners(); }, [setupEventListeners, cleanupEventListeners]); // Refresh stats periodically when mining useEffect(() => { if (!status.isMining) return; const interval = setInterval(() => { refreshStatus(); refreshStats(); }, 1000); return () => clearInterval(interval); }, [status.isMining, refreshStatus, refreshStats]); // Update coinbase address when addresses change useEffect(() => { if (!coinbaseAddress && addresses.length > 0) { setCoinbaseAddress(addresses[0].address); } }, [addresses, coinbaseAddress]); const handleStart = async () => { if (!nodeStatus.isConnected) { setError('Please connect to a node first'); return; } if (!coinbaseAddress) { setError('Please select a coinbase address for rewards'); return; } setIsStarting(true); setError(null); try { await startMining(coinbaseAddress, threads); } catch (err) { setError(err instanceof Error ? err.message : 'Failed to start mining'); } finally { setIsStarting(false); } }; const handleStop = async () => { try { await stopMining(); } catch (err) { setError(err instanceof Error ? err.message : 'Failed to stop mining'); } }; const handlePauseResume = async () => { try { if (status.isPaused) { await resumeMining(); } else { await pauseMining(); } } catch (err) { setError(err instanceof Error ? err.message : 'Action failed'); } }; const handleThreadsChange = async (newThreads: number) => { setThreadsLocal(newThreads); if (status.isMining) { try { await setThreads(newThreads); } catch (err) { setError(err instanceof Error ? err.message : 'Failed to update threads'); } } }; return (
{/* Header */}

Mining

Mine SYN coins using your computer's CPU

{/* Control buttons */}
{status.isMining ? ( <> ) : ( )}
{/* Error display */} {error && (
{error}
)} {/* Warning if not connected */} {!nodeStatus.isConnected && (
Please connect to a node before starting mining
)} {/* Stats Grid */}
} label="Hashrate" value={formatHashrate(status.hashrate)} highlight={status.isMining && !status.isPaused} /> } label="Blocks Found" value={status.blocksFound.toString()} /> } label="Threads" value={`${status.threads || threads}/${maxThreads}`} /> } label="Status" value={ status.isMining ? status.isPaused ? 'Paused' : 'Mining' : 'Idle' } highlight={status.isMining && !status.isPaused} />
{/* Configuration (when not mining) */} {!status.isMining && (

Mining Configuration

{/* Coinbase address */}

Mining rewards will be sent to this address

{/* Thread slider */}
handleThreadsChange(parseInt(e.target.value))} className="w-full h-2 bg-gray-700 rounded-lg appearance-none cursor-pointer accent-synor-500" />
1 (Low Power) {maxThreads} (Max Performance)
)} {/* Hashrate Chart (simplified) */} {status.isMining && hashrateHistory.length > 0 && (

Hashrate History

{hashrateHistory.slice(-60).map((point, i) => { const maxHash = Math.max(...hashrateHistory.map((h) => h.hashrate)); const height = maxHash > 0 ? (point.hashrate / maxHash) * 100 : 0; return (
); })}
60s ago Now
)} {/* Recent Blocks */} {recentBlocks.length > 0 && (

Blocks Found

{recentBlocks.slice(0, 5).map((block, i) => (

Block #{block.height.toLocaleString()}

{block.hash.slice(0, 24)}...

+{(block.reward / 100_000_000).toFixed(2)} SYN

{new Date(block.timestamp).toLocaleTimeString()}

))}
)} {/* Mining Tips */}

Mining Tips

  • • Use fewer threads to keep your computer responsive
  • • Mining profitability depends on network difficulty
  • • Ensure adequate cooling for sustained mining
  • • For best results, use an embedded node for lower latency
); } // Stat card component function StatCard({ icon, label, value, highlight = false, }: { icon: React.ReactNode; label: string; value: string; highlight?: boolean; }) { return (
{icon} {label}

{value}

); }