from fastapi import FastAPI, HTTPException, WebSocket, WebSocketDisconnect from fastapi.middleware.cors import CORSMiddleware from sqlalchemy import create_engine, Column, Integer, String, Float, Boolean, DateTime, Text from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.orm import sessionmaker, Session from pydantic import BaseModel from datetime import datetime from typing import List, Optional import json import asyncio import random # Database setup SQLALCHEMY_DATABASE_URL = "sqlite:///./flameborn_testnet.db" engine = create_engine(SQLALCHEMY_DATABASE_URL, connect_args={"check_same_thread": False}) SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine) Base = declarative_base() # Database Models class User(Base): __tablename__ = "users" id = Column(Integer, primary_key=True, index=True) wallet_address = Column(String, unique=True, index=True) role = Column(String) # "healer", "guardian", "community" name = Column(String) location = Column(String) verified = Column(Boolean, default=False) flb_balance = Column(Float, default=0.0) created_at = Column(DateTime, default=datetime.utcnow) class Validator(Base): __tablename__ = "validators" id = Column(Integer, primary_key=True, index=True) wallet_address = Column(String, unique=True, index=True) name = Column(String) stake_amount = Column(Float) active = Column(Boolean, default=True) last_heartbeat = Column(DateTime, default=datetime.utcnow) blocks_validated = Column(Integer, default=0) uptime_percentage = Column(Float, default=100.0) class Transaction(Base): __tablename__ = "transactions" id = Column(Integer, primary_key=True, index=True) from_address = Column(String) to_address = Column(String) amount = Column(Float) transaction_type = Column(String) # "birth_verification", "health_action", "donation" description = Column(Text) timestamp = Column(DateTime, default=datetime.utcnow) block_number = Column(Integer) class HealthAction(Base): __tablename__ = "health_actions" id = Column(Integer, primary_key=True, index=True) user_id = Column(Integer) action_type = Column(String) # "birth_registration", "health_check", "community_support" description = Column(Text) impact_score = Column(Float) flb_reward = Column(Float) timestamp = Column(DateTime, default=datetime.utcnow) # Create tables Base.metadata.create_all(bind=engine) # Pydantic models class UserCreate(BaseModel): wallet_address: str role: str name: str location: str class UserResponse(BaseModel): id: int wallet_address: str role: str name: str location: str verified: bool flb_balance: float created_at: datetime class ValidatorCreate(BaseModel): wallet_address: str name: str stake_amount: float class ValidatorResponse(BaseModel): id: int wallet_address: str name: str stake_amount: float active: bool last_heartbeat: datetime blocks_validated: int uptime_percentage: float class HealthActionCreate(BaseModel): user_id: int action_type: str description: str impact_score: float class NetworkStats(BaseModel): total_users: int total_validators: int total_transactions: int total_flb_supply: float active_validators: int network_uptime: float # FastAPI app app = FastAPI(title="FlameBorn Testnet", version="0.0.1-alpha") # CORS middleware app.add_middleware( CORSMiddleware, allow_origins=["*"], allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) # WebSocket connections class ConnectionManager: def __init__(self): self.active_connections: List[WebSocket] = [] async def connect(self, websocket: WebSocket): await websocket.accept() self.active_connections.append(websocket) def disconnect(self, websocket: WebSocket): self.active_connections.remove(websocket) async def broadcast(self, message: str): for connection in self.active_connections: try: await connection.send_text(message) except: pass manager = ConnectionManager() # Database dependency def get_db(): db = SessionLocal() try: yield db finally: db.close() # Routes @app.get("/ping") def ping(): return { "status": "alive", "network": "FlameBorn-Testnet", "version": "0.0.1-alpha", "timestamp": datetime.utcnow().isoformat(), "ubuntu_message": "I am because we are" } @app.get("/.well-known/manifest.json") def manifest(): return { "network": "FlameBorn-Testnet", "version": "0.0.1-alpha", "consensus": "Ubuntu-PoS", "ubuntu_principle": "I am because we are", "oracle": True, "validator": True, "features": [ "birth_verification", "health_action_rewards", "community_governance", "ubuntu_consensus", "cultural_anchoring", "real_time_updates" ], "endpoints": { "users": "/users", "validators": "/validators", "stats": "/stats", "oracle": "/oracle/price", "consensus": "/consensus/status", "websocket": "/ws" } } @app.get("/users", response_model=List[UserResponse]) def get_users(db: Session = next(get_db())): users = db.query(User).all() return users @app.post("/users", response_model=UserResponse) def create_user(user: UserCreate, db: Session = next(get_db())): # Check if user already exists existing_user = db.query(User).filter(User.wallet_address == user.wallet_address).first() if existing_user: raise HTTPException(status_code=400, detail="User already exists") # Create new user with initial FLB balance db_user = User( wallet_address=user.wallet_address, role=user.role, name=user.name, location=user.location, verified=True, # Auto-verify for testnet flb_balance=1000.0 # Initial testnet tokens ) db.add(db_user) db.commit() db.refresh(db_user) # Broadcast new user event asyncio.create_task(manager.broadcast(json.dumps({ "type": "new_user", "data": { "name": db_user.name, "role": db_user.role, "location": db_user.location } }))) return db_user @app.get("/users/{wallet_address}", response_model=UserResponse) def get_user(wallet_address: str, db: Session = next(get_db())): user = db.query(User).filter(User.wallet_address == wallet_address).first() if not user: raise HTTPException(status_code=404, detail="User not found") return user @app.get("/validators", response_model=List[ValidatorResponse]) def get_validators(db: Session = next(get_db())): validators = db.query(Validator).all() return validators @app.post("/validators", response_model=ValidatorResponse) def create_validator(validator: ValidatorCreate, db: Session = next(get_db())): # Check if validator already exists existing_validator = db.query(Validator).filter(Validator.wallet_address == validator.wallet_address).first() if existing_validator: raise HTTPException(status_code=400, detail="Validator already exists") db_validator = Validator( wallet_address=validator.wallet_address, name=validator.name, stake_amount=validator.stake_amount, active=True, last_heartbeat=datetime.utcnow(), blocks_validated=0, uptime_percentage=100.0 ) db.add(db_validator) db.commit() db.refresh(db_validator) # Broadcast new validator event asyncio.create_task(manager.broadcast(json.dumps({ "type": "new_validator", "data": { "name": db_validator.name, "stake_amount": db_validator.stake_amount } }))) return db_validator @app.post("/validators/{wallet_address}/heartbeat") def validator_heartbeat(wallet_address: str, db: Session = next(get_db())): validator = db.query(Validator).filter(Validator.wallet_address == wallet_address).first() if not validator: raise HTTPException(status_code=404, detail="Validator not found") validator.last_heartbeat = datetime.utcnow() validator.blocks_validated += 1 db.commit() return {"status": "heartbeat_recorded", "timestamp": validator.last_heartbeat} @app.get("/stats", response_model=NetworkStats) def get_network_stats(db: Session = next(get_db())): total_users = db.query(User).count() total_validators = db.query(Validator).count() active_validators = db.query(Validator).filter(Validator.active == True).count() total_transactions = db.query(Transaction).count() # Calculate total FLB supply total_flb_supply = db.query(User).with_entities(User.flb_balance).all() total_supply = sum([balance[0] for balance in total_flb_supply]) return NetworkStats( total_users=total_users, total_validators=total_validators, total_transactions=total_transactions, total_flb_supply=total_supply, active_validators=active_validators, network_uptime=99.8 # Simulated uptime ) @app.get("/oracle/price") def get_flb_price(): # Simulate FLB price with some volatility base_price = 0.00125 volatility = random.uniform(-0.0002, 0.0002) current_price = base_price + volatility return { "symbol": "FLB", "price_usd": current_price, "price_change_24h": random.uniform(-15, 15), "volume_24h": random.uniform(10000, 50000), "market_cap": current_price * 750000000, "last_updated": datetime.utcnow().isoformat() } @app.get("/consensus/status") def get_consensus_status(db: Session = next(get_db())): active_validators = db.query(Validator).filter(Validator.active == True).count() total_validators = db.query(Validator).count() return { "consensus_type": "Ubuntu-PoS", "active_validators": active_validators, "total_validators": total_validators, "consensus_participation": (active_validators / max(total_validators, 1)) * 100, "last_block_time": datetime.utcnow().isoformat(), "ubuntu_principle": "Collective validation through community consensus", "network_health": "healthy" if active_validators >= 3 else "warning" } @app.post("/health-actions") def record_health_action(action: HealthActionCreate, db: Session = next(get_db())): # Calculate FLB reward based on impact score flb_reward = action.impact_score * 10.0 # 10 FLB per impact point db_action = HealthAction( user_id=action.user_id, action_type=action.action_type, description=action.description, impact_score=action.impact_score, flb_reward=flb_reward, timestamp=datetime.utcnow() ) db.add(db_action) # Update user's FLB balance user = db.query(User).filter(User.id == action.user_id).first() if user: user.flb_balance += flb_reward db.commit() db.refresh(db_action) # Broadcast health action event asyncio.create_task(manager.broadcast(json.dumps({ "type": "health_action", "data": { "action_type": db_action.action_type, "impact_score": db_action.impact_score, "flb_reward": db_action.flb_reward, "user_name": user.name if user else "Unknown" } }))) return db_action @app.websocket("/ws") async def websocket_endpoint(websocket: WebSocket): await manager.connect(websocket) try: while True: # Send periodic network updates await asyncio.sleep(10) await websocket.send_text(json.dumps({ "type": "network_pulse", "timestamp": datetime.utcnow().isoformat(), "message": "Ubuntu network heartbeat - I am because we are" })) except WebSocketDisconnect: manager.disconnect(websocket) if __name__ == "__main__": import uvicorn uvicorn.run(app, host="0.0.0.0", port=8000)