from fastapi import FastAPI, HTTPException from fastapi.middleware.cors import CORSMiddleware from fastapi.responses import JSONResponse from parallel_miner_v3 import ParallelMiner import threading from typing import Dict, Optional import uvicorn import logging # Configure logging logging.basicConfig(level=logging.INFO) logger = logging.getLogger(__name__) app = FastAPI(title="Mining Dashboard API") # Enable CORS app.add_middleware( CORSMiddleware, allow_origins=["*"], # In production, replace with your frontend URL allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) # Global variables for mining state miner_instance: Optional[ParallelMiner] = None mining_thread: Optional[threading.Thread] = None is_mining = False @app.get("/status") # Remove /api prefix since we're mounting at /api async def get_status() -> Dict: """Get current mining status and statistics""" global miner_instance, is_mining logger.info("Status endpoint called") try: if not miner_instance: logger.info("No miner instance found, returning default values") return { "status": "Stopped", "hashrate": 0, "total_hashes": 0, "blocks_found": 0, "best_hash": None, "difficulty": 0 } stats = { "status": "Running" if is_mining else "Stopped", "hashrate": round(miner_instance.current_hashrate / 1000, 2), # KH/s "total_hashes": miner_instance.total_hashes, "blocks_found": miner_instance.blocks_found, "best_hash": miner_instance.best_hash.hex() if miner_instance.best_hash else None, "difficulty": miner_instance.best_hash_difficulty } logger.info(f"Returning stats: {stats}") return stats except Exception as e: logger.error(f"Error getting status: {str(e)}") raise HTTPException(status_code=500, detail=str(e)) @app.post("/start") # Remove /api prefix since we're mounting at /api async def start_mining() -> Dict: """Start the mining process""" global miner_instance, mining_thread, is_mining logger.info("Start mining endpoint called") if is_mining: logger.warning("Mining is already running") raise HTTPException(status_code=400, detail="Mining is already running") try: logger.info("Initializing miner...") miner_instance = ParallelMiner(num_cores=5) miner_instance.mining = True is_mining = True # Start mining in background thread logger.info("Starting mining thread...") mining_thread = threading.Thread( target=miner_instance.start_mining, kwargs={"duration": None} ) mining_thread.daemon = True mining_thread.start() logger.info("Mining started successfully") return {"message": "Mining started successfully"} except Exception as e: logger.error(f"Error starting mining: {str(e)}") raise HTTPException(status_code=500, detail=str(e)) @app.post("/api/stop") async def stop_mining() -> Dict: """Stop the mining process""" global miner_instance, is_mining if not is_mining: raise HTTPException(status_code=400, detail="Mining is not running") try: if miner_instance: miner_instance.mining = False is_mining = False return {"message": "Mining stopped successfully"} raise HTTPException(status_code=400, detail="No active mining instance found") except Exception as e: raise HTTPException(status_code=500, detail=str(e)) if __name__ == "__main__": uvicorn.run(app, host="0.0.0.0", port=8000)