Spaces:
Paused
Paused
| #!/usr/bin/env python3 | |
| """ | |
| AirMicroDrip Hugging Face Space | |
| Unified Flask app serving API and static UI | |
| No mocks - real data from all AirMicroDrip systems | |
| """ | |
| from flask import Flask, jsonify, request, render_template_string | |
| from flask_cors import CORS | |
| import sqlite3 | |
| import json | |
| import hashlib | |
| import threading | |
| from datetime import datetime | |
| import sys | |
| import os | |
| import requests | |
| import logging | |
| # Configure logging | |
| logging.basicConfig( | |
| level=logging.INFO, | |
| format='%(asctime)s - %(name)s - %(levelname)s - %(message)s' | |
| ) | |
| logger = logging.getLogger(__name__) | |
| # Import AirMicroDrip modules for real data fetching | |
| from slippage_collector import SlippageCollector, create_collector | |
| from holder_tracker import HolderTracker | |
| from llm_liquidity_provider import InferenceRegistry, LiquidityConverter, PerformanceMonitor | |
| from merkle_token_launch import build_launch_manifest | |
| from hf_account_collateral import scan_hf_account_collateral | |
| from token_launcher import autonomously_create_token, get_launch_status, get_keypair_backup, get_existing_mint | |
| app = Flask(__name__) | |
| CORS(app) | |
| COLLATERAL_SCAN_JOBS = {} | |
| # Database paths | |
| HOLDER_DB = "holder_tracker/holder_registry.db" | |
| INFERENCE_DB = "llm_liquidity_provider/inference_registry.db" | |
| TRADING_DB = "perp_trading_engine/perp_trading.db" | |
| LAUNCH_DB = "token_launch/launch_registry.db" | |
| COLLATERAL_DB = "token_launch/collateral_registry.db" | |
| SPACE_REPO_ID = os.environ.get("SPACE_ID") or os.environ.get("HF_SPACE_ID") or "josephrw/ce" | |
| SPACE_OWNER = SPACE_REPO_ID.split("/")[0] | |
| DEFAULT_TOKEN_MINT = "So11111111111111111111111111111111111111112" | |
| DEFAULT_SOLANA_RPC_URL = "https://api.mainnet-beta.solana.com" | |
| # Create directories | |
| os.makedirs('holder_tracker', exist_ok=True) | |
| os.makedirs('llm_liquidity_provider', exist_ok=True) | |
| os.makedirs('perp_trading_engine', exist_ok=True) | |
| os.makedirs('token_launch', exist_ok=True) | |
| # Initialize databases | |
| def init_databases(): | |
| """Initialize all databases""" | |
| # Holder tracker DB | |
| conn = sqlite3.connect(HOLDER_DB) | |
| cursor = conn.cursor() | |
| cursor.execute(""" | |
| CREATE TABLE IF NOT EXISTS holders ( | |
| address TEXT PRIMARY KEY, | |
| current_balance REAL DEFAULT 0, | |
| first_seen TIMESTAMP, | |
| eligible BOOLEAN DEFAULT FALSE, | |
| eligibility_timestamp TIMESTAMP | |
| ) | |
| """) | |
| cursor.execute(""" | |
| CREATE TABLE IF NOT EXISTS transfers ( | |
| transfer_id TEXT PRIMARY KEY, | |
| from_address TEXT, | |
| to_address TEXT, | |
| amount REAL, | |
| timestamp TIMESTAMP | |
| ) | |
| """) | |
| conn.commit() | |
| conn.close() | |
| # Token launch DB | |
| conn = sqlite3.connect(LAUNCH_DB) | |
| cursor = conn.cursor() | |
| cursor.execute(""" | |
| CREATE TABLE IF NOT EXISTS launch_manifests ( | |
| manifest_hash TEXT PRIMARY KEY, | |
| merkle_root TEXT NOT NULL, | |
| status TEXT NOT NULL, | |
| execution_status TEXT NOT NULL, | |
| manifest_json TEXT NOT NULL, | |
| created_at TIMESTAMP NOT NULL | |
| ) | |
| """) | |
| conn.commit() | |
| conn.close() | |
| # Account collateral DB | |
| conn = sqlite3.connect(COLLATERAL_DB) | |
| cursor = conn.cursor() | |
| cursor.execute(""" | |
| CREATE TABLE IF NOT EXISTS account_collateral ( | |
| owner TEXT PRIMARY KEY, | |
| collateral_root TEXT NOT NULL, | |
| collateral_json TEXT NOT NULL, | |
| scanned_at TIMESTAMP NOT NULL | |
| ) | |
| """) | |
| conn.commit() | |
| conn.close() | |
| # Inference registry DB | |
| conn = sqlite3.connect(INFERENCE_DB) | |
| cursor = conn.cursor() | |
| cursor.execute(""" | |
| CREATE TABLE IF NOT EXISTS providers ( | |
| provider_id TEXT PRIMARY KEY, | |
| wallet_address TEXT, | |
| model_type TEXT, | |
| registered_at TIMESTAMP, | |
| status TEXT DEFAULT 'pending', | |
| reputation_score REAL DEFAULT 0.5, | |
| total_earnings REAL DEFAULT 0.0 | |
| ) | |
| """) | |
| cursor.execute(""" | |
| CREATE TABLE IF NOT EXISTS capacity ( | |
| provider_id TEXT, | |
| tokens_per_second REAL, | |
| latency_ms REAL, | |
| uptime_percentage REAL, | |
| quality_score REAL, | |
| verified_at TIMESTAMP, | |
| FOREIGN KEY (provider_id) REFERENCES providers(provider_id) | |
| ) | |
| """) | |
| cursor.execute(""" | |
| CREATE TABLE IF NOT EXISTS liquidity_allocations ( | |
| provider_id TEXT, | |
| synthetic_liquidity_usd REAL, | |
| liquidity_tokens REAL, | |
| market_allocation TEXT, | |
| allocated_at TIMESTAMP, | |
| FOREIGN KEY (provider_id) REFERENCES providers(provider_id) | |
| ) | |
| """) | |
| cursor.execute(""" | |
| CREATE TABLE IF NOT EXISTS rewards ( | |
| reward_id TEXT PRIMARY KEY, | |
| provider_id TEXT, | |
| amount REAL, | |
| source TEXT, | |
| multiplier REAL, | |
| timestamp TIMESTAMP, | |
| FOREIGN KEY (provider_id) REFERENCES providers(provider_id) | |
| ) | |
| """) | |
| conn.commit() | |
| conn.close() | |
| # Trading engine DB | |
| conn = sqlite3.connect(TRADING_DB) | |
| cursor = conn.cursor() | |
| cursor.execute(""" | |
| CREATE TABLE IF NOT EXISTS orders ( | |
| order_id TEXT PRIMARY KEY, | |
| trader TEXT, | |
| market TEXT, | |
| side TEXT, | |
| order_type TEXT, | |
| size REAL, | |
| price REAL, | |
| stop_price REAL, | |
| leverage INTEGER, | |
| status TEXT, | |
| filled_size REAL, | |
| avg_fill_price REAL, | |
| created_at TIMESTAMP, | |
| updated_at TIMESTAMP | |
| ) | |
| """) | |
| cursor.execute(""" | |
| CREATE TABLE IF NOT EXISTS positions ( | |
| position_id TEXT PRIMARY KEY, | |
| trader TEXT, | |
| market TEXT, | |
| side TEXT, | |
| size REAL, | |
| entry_price REAL, | |
| leverage INTEGER, | |
| margin REAL, | |
| unrealized_pnl REAL, | |
| realized_pnl REAL, | |
| liquidation_price REAL, | |
| opened_at TIMESTAMP, | |
| updated_at TIMESTAMP | |
| ) | |
| """) | |
| cursor.execute(""" | |
| CREATE TABLE IF NOT EXISTS trades ( | |
| trade_id TEXT PRIMARY KEY, | |
| order_id TEXT, | |
| market TEXT, | |
| side TEXT, | |
| size REAL, | |
| price REAL, | |
| fee REAL, | |
| timestamp TIMESTAMP | |
| ) | |
| """) | |
| cursor.execute(""" | |
| CREATE TABLE IF NOT EXISTS funding_rates ( | |
| market TEXT, | |
| rate REAL, | |
| timestamp TIMESTAMP, | |
| PRIMARY KEY (market, timestamp) | |
| ) | |
| """) | |
| conn.commit() | |
| conn.close() | |
| init_databases() | |
| def _token_mint(): | |
| """Use a public no-key default unless a token mint is explicitly configured.""" | |
| return os.environ.get("TOKEN_MINT", DEFAULT_TOKEN_MINT).strip() | |
| def _inference_url(): | |
| """Inference endpoints are optional and never require app-level API keys.""" | |
| return os.environ.get("INFERENCE_API_URL", "").strip() | |
| def _integration_config(): | |
| """Return public-safe integration configuration status.""" | |
| token_mint = _token_mint() | |
| inference_url = _inference_url() | |
| solana_rpc_url = os.environ.get("SOLANA_RPC_URL", DEFAULT_SOLANA_RPC_URL).strip() | |
| return { | |
| "token_mint": { | |
| "configured": True, | |
| "defaulted": token_mint == DEFAULT_TOKEN_MINT, | |
| "label": "Solana token mint", | |
| "env": "optional override", | |
| "value_public": token_mint, | |
| "status": "wired", | |
| }, | |
| "inference_endpoint": { | |
| "configured": bool(inference_url), | |
| "label": "LLM inference endpoint", | |
| "env": "optional local endpoint", | |
| "status": "wired" if inference_url else "local_only", | |
| }, | |
| "solana_rpc": { | |
| "configured": True, | |
| "label": "Solana RPC", | |
| "env": "public default", | |
| "status": "wired", | |
| }, | |
| "gateio_market_data": { | |
| "configured": True, | |
| "label": "Gate.io public market data", | |
| "env": None, | |
| "status": "wired", | |
| }, | |
| "api_keys": { | |
| "configured": True, | |
| "label": "API keys", | |
| "env": None, | |
| "status": "not_required", | |
| }, | |
| } | |
| def _status_meta(status, label=None, detail=None): | |
| """Consistent UI status payload: real backend, no synthetic success.""" | |
| copy = { | |
| "active": ("active", "Real backend route responded with usable data."), | |
| "pending": ("waiting", "Backend is live; the public source has not returned usable data yet."), | |
| "not_wired": ("not wired", "Optional integration is disabled."), | |
| "local_only": ("local only", "No API key is required; live external benchmark is optional."), | |
| "unsigned_ready": ("unsigned ready", "Merkle manifest is verified locally and waiting for a real wallet signature."), | |
| "ready_for_signature": ("ready for signature", "Collateral evidence is scanned and waiting for owner wallet signature."), | |
| "not_scanned": ("not scanned", "Collateral scan has not run yet."), | |
| "error": ("error", "The backend route returned an error."), | |
| } | |
| display, default_detail = copy.get(status, (status, "Unknown status.")) | |
| return { | |
| "status": status, | |
| "display": display, | |
| "label": label or display, | |
| "detail": detail or default_detail, | |
| } | |
| # Attempt to sync real data from external APIs on startup | |
| def _sync_real_data(): | |
| """Sync real data from external APIs into local SQLite DBs""" | |
| token_mint = _token_mint() | |
| # 0. Auto-create token mint if none configured and none exists | |
| if not token_mint: | |
| try: | |
| existing = get_existing_mint() | |
| if existing: | |
| print(f"[startup] Using existing auto-created mint: {existing}") | |
| os.environ["TOKEN_MINT"] = existing | |
| token_mint = existing | |
| else: | |
| print("[startup] No TOKEN_MINT set. Auto-creating devnet token...") | |
| result = autonomously_create_token() | |
| if result["status"] == "ok": | |
| mint = result["mint_address"] | |
| os.environ["TOKEN_MINT"] = mint | |
| token_mint = mint | |
| print(f"[startup] Auto-created token: {mint}") | |
| print(f"[startup] Wallet: {result['wallet_pubkey']}") | |
| print(f"[startup] BACKUP REQUIRED: Visit /api/token/backup to download keypair") | |
| else: | |
| print(f"[startup] Auto-token creation failed: {result.get('message')}") | |
| except Exception as e: | |
| print(f"[startup] Token auto-creation error: {e}") | |
| # 1. Sync slippage data from DexScreener | |
| if token_mint: | |
| try: | |
| collector = create_collector(token_mint, "drippage_pool_placeholder") | |
| count = collector.process_real_trades() | |
| print(f"[startup] Synced {count} slippage collections from DexScreener") | |
| except Exception as e: | |
| print(f"[startup] Slippage sync skipped: {e}") | |
| # 2. Sync holder data from Solana RPC | |
| if token_mint: | |
| try: | |
| tracker = HolderTracker(token_mint, db_path=HOLDER_DB) | |
| count = tracker.sync_holders_from_chain() | |
| print(f"[startup] Synced {count} holders from Solana RPC") | |
| except Exception as e: | |
| print(f"[startup] Holder sync skipped: {e}") | |
| # 3. Benchmark inference endpoint if configured | |
| inference_url = _inference_url() | |
| if inference_url: | |
| try: | |
| registry = InferenceRegistry(db_path=INFERENCE_DB) | |
| converter = LiquidityConverter(registry) | |
| monitor = PerformanceMonitor(registry) | |
| bench = monitor._benchmark_inference_endpoint(inference_url, "llama2") | |
| if bench["status"] == "verified": | |
| # Register a provider with real benchmark results | |
| registry.register_provider("prov_hf_001", "hf_worker", "llama2") | |
| registry.verify_capacity( | |
| "prov_hf_001", | |
| bench["tokens_per_second"], | |
| bench["latency_ms"], | |
| 99.0, | |
| bench["quality_score"], | |
| ) | |
| print(f"[startup] Inference benchmark: {bench['tokens_per_second']:.1f} t/s, {bench['latency_ms']:.1f}ms") | |
| else: | |
| print(f"[startup] Inference endpoint unreachable at {inference_url}") | |
| except Exception as e: | |
| print(f"[startup] Inference benchmark skipped: {e}") | |
| else: | |
| print("[startup] No inference endpoint configured; LLM liquidity stays no-key local-only") | |
| _sync_real_data() | |
| # API Endpoints | |
| def health(): | |
| """Health check endpoint""" | |
| config = _integration_config() | |
| return jsonify({ | |
| "status": "healthy", | |
| "timestamp": datetime.utcnow().isoformat(), | |
| "mode": "no_mock_real_backend", | |
| "configured_integrations": config, | |
| "systems": { | |
| "slippage_collector": "active" if config["token_mint"]["configured"] else "not_wired", | |
| "holder_tracker": "active" if config["token_mint"]["configured"] else "not_wired", | |
| "llm_liquidity": "active" if config["inference_endpoint"]["configured"] else "local_only", | |
| "merkle_token_launch": "unsigned_ready", | |
| "hf_account_collateral": _collateral_summary()["status"], | |
| "trading_engine": "active", | |
| "funding_engine": "active", | |
| "liquidation_system": "active", | |
| "mining_rewards": "active", | |
| } | |
| }) | |
| def config_status(): | |
| """Public-safe integration status. Does not expose secrets.""" | |
| return jsonify({ | |
| "mode": "no_mock_real_backend", | |
| "timestamp": datetime.utcnow().isoformat(), | |
| "integrations": _integration_config(), | |
| "principles": [ | |
| "No fake holders, liquidity, trades, payouts, or inference benchmarks.", | |
| "Optional external sources return local_only, waiting, or error states.", | |
| "Dashboard metrics are derived from local DBs or real public APIs.", | |
| ], | |
| }) | |
| def _launch_source_metrics(): | |
| """Use local persisted state as launch-tree inputs without inventing activity.""" | |
| owner_profile = _hf_owner_profile() | |
| metrics = { | |
| "token_mint_source": _token_mint(), | |
| "space_repo_id": SPACE_REPO_ID, | |
| "space_owner": SPACE_OWNER, | |
| "owner_repository_count": owner_profile["total_repositories"], | |
| "owner_repository_hash": owner_profile["repository_index_hash"], | |
| "generated_from": "airmicrodrip_runtime_ledgers", | |
| "holders": 0, | |
| "eligible_holders": 0, | |
| "active_llm_providers": 0, | |
| "synthetic_liquidity_usd": 0, | |
| "active_positions": 0, | |
| "total_rewards": 0, | |
| } | |
| try: | |
| conn = sqlite3.connect(HOLDER_DB) | |
| cursor = conn.cursor() | |
| cursor.execute("SELECT COUNT(*) FROM holders") | |
| metrics["holders"] = cursor.fetchone()[0] | |
| cursor.execute("SELECT COUNT(*) FROM holders WHERE eligible = TRUE") | |
| metrics["eligible_holders"] = cursor.fetchone()[0] | |
| conn.close() | |
| except Exception as e: | |
| metrics["holder_metric_error"] = str(e) | |
| try: | |
| conn = sqlite3.connect(INFERENCE_DB) | |
| cursor = conn.cursor() | |
| cursor.execute("SELECT COUNT(*) FROM providers WHERE status = 'active'") | |
| metrics["active_llm_providers"] = cursor.fetchone()[0] | |
| cursor.execute("SELECT SUM(synthetic_liquidity_usd) FROM liquidity_allocations") | |
| metrics["synthetic_liquidity_usd"] = cursor.fetchone()[0] or 0 | |
| cursor.execute("SELECT SUM(amount) FROM rewards") | |
| metrics["total_rewards"] = cursor.fetchone()[0] or 0 | |
| conn.close() | |
| except Exception as e: | |
| metrics["liquidity_metric_error"] = str(e) | |
| try: | |
| conn = sqlite3.connect(TRADING_DB) | |
| cursor = conn.cursor() | |
| cursor.execute("SELECT COUNT(*) FROM positions WHERE size > 0") | |
| metrics["active_positions"] = cursor.fetchone()[0] | |
| conn.close() | |
| except Exception as e: | |
| metrics["trading_metric_error"] = str(e) | |
| return metrics | |
| def _owner_token_symbol(owner): | |
| clean = "".join(ch for ch in owner.upper() if ch.isalnum()) | |
| if not clean: | |
| clean = "OWNER" | |
| return f"{clean[:4]}CE" | |
| def _owner_token_spec(owner_profile): | |
| symbol = _owner_token_symbol(owner_profile["owner"]) | |
| return { | |
| "name": f"{owner_profile['owner']} Compute Exchange", | |
| "symbol": symbol, | |
| "decimals": 9, | |
| "network": "solana-mainnet", | |
| "total_supply": 1_000_000_000, | |
| "derived_from_space": SPACE_REPO_ID, | |
| "derived_from_owner": owner_profile["owner"], | |
| "derived_repository_count": owner_profile["total_repositories"], | |
| "repository_index_hash": owner_profile["repository_index_hash"], | |
| } | |
| def _owner_pool_spec(token_spec): | |
| return { | |
| "dex": "meteora-or-raydium", | |
| "pair": f"{token_spec['symbol']}/SOL", | |
| "base_asset": token_spec["symbol"], | |
| "quote_asset": "SOL", | |
| "initial_ce_liquidity": 100_000_000, | |
| "initial_quote_liquidity_required": "external_wallet_signature_required", | |
| "lp_lock": "root_committed", | |
| "derived_from_owner": token_spec["derived_from_owner"], | |
| } | |
| def _hf_api_list(path, owner): | |
| try: | |
| response = requests.get( | |
| f"https://huggingface.co/api/{path}", | |
| params={"author": owner, "limit": 100}, | |
| timeout=10, | |
| ) | |
| if response.status_code == 200: | |
| return response.json() | |
| except Exception as e: | |
| logger.warning("HF %s fetch skipped: %s", path, e) | |
| return [] | |
| def _hf_owner_profile(owner=None): | |
| owner = owner or SPACE_OWNER | |
| repo_records = [] | |
| for repo_type, path in (("model", "models"), ("dataset", "datasets"), ("space", "spaces")): | |
| for item in _hf_api_list(path, owner): | |
| repo_id = item.get("id") or item.get("name") | |
| if not repo_id: | |
| continue | |
| repo_records.append({ | |
| "repo_type": repo_type, | |
| "repo_id": repo_id, | |
| "likes": item.get("likes", 0), | |
| "downloads": item.get("downloads", 0), | |
| "last_modified": item.get("lastModified") or item.get("updatedAt"), | |
| "sdk": item.get("sdk"), | |
| }) | |
| repo_records.sort(key=lambda item: (item["repo_type"], item["repo_id"])) | |
| repo_index_json = json.dumps(repo_records, sort_keys=True, separators=(",", ":")) | |
| return { | |
| "owner": owner, | |
| "space_repo_id": SPACE_REPO_ID, | |
| "total_repositories": len(repo_records), | |
| "repository_index_hash": __import__("hashlib").sha256(repo_index_json.encode("utf-8")).hexdigest(), | |
| "repositories": repo_records, | |
| } | |
| def _persist_collateral(collateral): | |
| conn = sqlite3.connect(COLLATERAL_DB) | |
| cursor = conn.cursor() | |
| cursor.execute(""" | |
| INSERT OR REPLACE INTO account_collateral | |
| (owner, collateral_root, collateral_json, scanned_at) | |
| VALUES (?, ?, ?, ?) | |
| """, ( | |
| collateral["owner"], | |
| collateral["collateral_root"], | |
| json.dumps(collateral, sort_keys=True), | |
| collateral["scanned_at"], | |
| )) | |
| conn.commit() | |
| conn.close() | |
| def _latest_collateral(owner=None): | |
| owner = owner or SPACE_OWNER | |
| conn = sqlite3.connect(COLLATERAL_DB) | |
| cursor = conn.cursor() | |
| cursor.execute(""" | |
| SELECT collateral_json | |
| FROM account_collateral | |
| WHERE owner = ? | |
| """, (owner,)) | |
| row = cursor.fetchone() | |
| conn.close() | |
| return json.loads(row[0]) if row else None | |
| def _collateral_summary(owner=None): | |
| collateral = _latest_collateral(owner) | |
| job = COLLATERAL_SCAN_JOBS.get(owner or SPACE_OWNER) | |
| if collateral: | |
| summary = { | |
| "status": collateral["collateral_status"], | |
| "owner": collateral["owner"], | |
| "collateral_root": collateral["collateral_root"], | |
| "repo_count": collateral["repo_count"], | |
| "space_count": collateral["space_count"], | |
| "total_files": collateral["total_files"], | |
| "total_text_files": collateral["total_text_files"], | |
| "total_loc": collateral["total_loc"], | |
| "collateral_score": collateral["collateral_score"], | |
| "scanned_at": collateral["scanned_at"], | |
| } | |
| if job and job.get("status") == "running": | |
| summary["scan_job_status"] = "running" | |
| return summary | |
| if job: | |
| return { | |
| "status": job.get("status", "running"), | |
| "owner": owner or SPACE_OWNER, | |
| "collateral_root": None, | |
| "repo_count": 0, | |
| "space_count": 0, | |
| "total_files": 0, | |
| "total_text_files": 0, | |
| "total_loc": 0, | |
| "collateral_score": 0, | |
| "started_at": job.get("started_at"), | |
| "message": job.get("message", "Collateral scan is running."), | |
| } | |
| return { | |
| "status": "not_scanned", | |
| "owner": owner or SPACE_OWNER, | |
| "collateral_root": None, | |
| "repo_count": 0, | |
| "space_count": 0, | |
| "total_files": 0, | |
| "total_text_files": 0, | |
| "total_loc": 0, | |
| "collateral_score": 0, | |
| } | |
| def _run_collateral_scan_job(owner): | |
| COLLATERAL_SCAN_JOBS[owner] = { | |
| "status": "running", | |
| "owner": owner, | |
| "started_at": datetime.utcnow().isoformat(), | |
| "message": "Scanning public HF repos, spaces, files, and readable LOC.", | |
| } | |
| try: | |
| collateral = scan_hf_account_collateral(owner) | |
| _persist_collateral(collateral) | |
| manifest = _prepare_launch_manifest({"owner": owner}) | |
| COLLATERAL_SCAN_JOBS[owner] = { | |
| "status": "complete", | |
| "owner": owner, | |
| "started_at": COLLATERAL_SCAN_JOBS[owner]["started_at"], | |
| "completed_at": datetime.utcnow().isoformat(), | |
| "message": "Collateral scan completed and launch manifest rebuilt.", | |
| "collateral_root": collateral["collateral_root"], | |
| "manifest_hash": manifest["manifest_hash"], | |
| "merkle_root": manifest["merkle_root"], | |
| } | |
| except Exception as e: | |
| COLLATERAL_SCAN_JOBS[owner] = { | |
| "status": "error", | |
| "owner": owner, | |
| "started_at": COLLATERAL_SCAN_JOBS.get(owner, {}).get("started_at"), | |
| "completed_at": datetime.utcnow().isoformat(), | |
| "message": str(e), | |
| } | |
| def _owner_repo_leaves(owner_profile): | |
| return [ | |
| { | |
| "kind": f"owner_repo:{repo['repo_type']}:{repo['repo_id']}", | |
| "payload": repo, | |
| } | |
| for repo in owner_profile["repositories"] | |
| ] | |
| def _collateral_leaves(collateral): | |
| if not collateral or collateral.get("status") == "not_scanned": | |
| return [] | |
| leaves = [{ | |
| "kind": f"hf_account_collateral:{collateral['owner']}", | |
| "payload": { | |
| "owner": collateral["owner"], | |
| "collateral_root": collateral["collateral_root"], | |
| "repo_count": collateral["repo_count"], | |
| "space_count": collateral["space_count"], | |
| "total_files": collateral["total_files"], | |
| "total_text_files": collateral["total_text_files"], | |
| "total_loc": collateral["total_loc"], | |
| "collateral_score": collateral["collateral_score"], | |
| }, | |
| }] | |
| for repo in collateral["repositories"]: | |
| leaves.append({ | |
| "kind": f"hf_repo_collateral:{repo['repo_type']}:{repo['repo_id']}", | |
| "payload": { | |
| "repo_type": repo["repo_type"], | |
| "repo_id": repo["repo_id"], | |
| "file_count": repo.get("file_count", 0), | |
| "text_file_count": repo.get("text_file_count", 0), | |
| "loc": repo.get("loc", 0), | |
| "repo_evidence_hash": repo.get("repo_evidence_hash"), | |
| }, | |
| }) | |
| for file_record in repo.get("files", []): | |
| leaves.append({ | |
| "kind": f"hf_file:{repo['repo_type']}:{repo['repo_id']}:{file_record['path']}", | |
| "payload": { | |
| "repo_id": repo["repo_id"], | |
| "repo_type": repo["repo_type"], | |
| "path": file_record["path"], | |
| "text": file_record["text"], | |
| "loc": file_record["loc"], | |
| "sha256": file_record["sha256"], | |
| "read_status": file_record["read_status"], | |
| }, | |
| }) | |
| return leaves | |
| def _persist_launch_manifest(manifest): | |
| conn = sqlite3.connect(LAUNCH_DB) | |
| cursor = conn.cursor() | |
| cursor.execute(""" | |
| INSERT OR REPLACE INTO launch_manifests | |
| (manifest_hash, merkle_root, status, execution_status, manifest_json, created_at) | |
| VALUES (?, ?, ?, ?, ?, ?) | |
| """, ( | |
| manifest["manifest_hash"], | |
| manifest["merkle_root"], | |
| manifest["status"], | |
| manifest["execution_status"], | |
| json.dumps(manifest, sort_keys=True), | |
| manifest["created_at"], | |
| )) | |
| conn.commit() | |
| conn.close() | |
| def _latest_launch_manifest(): | |
| conn = sqlite3.connect(LAUNCH_DB) | |
| cursor = conn.cursor() | |
| cursor.execute(""" | |
| SELECT manifest_json | |
| FROM launch_manifests | |
| ORDER BY created_at DESC | |
| LIMIT 1 | |
| """) | |
| row = cursor.fetchone() | |
| conn.close() | |
| return json.loads(row[0]) if row else None | |
| def _prepare_launch_manifest(payload=None): | |
| payload = payload or {} | |
| owner_profile = _hf_owner_profile(payload.get("owner") or SPACE_OWNER) | |
| collateral = _latest_collateral(owner_profile["owner"]) | |
| token_spec = payload.get("token_spec") or _owner_token_spec(owner_profile) | |
| pool_spec = payload.get("pool_spec") or _owner_pool_spec(token_spec) | |
| manifest = build_launch_manifest( | |
| token_spec=token_spec, | |
| pool_spec=pool_spec, | |
| allocations=payload.get("allocations"), | |
| source_metrics=_launch_source_metrics(), | |
| extra_leaves=_owner_repo_leaves(owner_profile) + _collateral_leaves(collateral), | |
| ) | |
| manifest["owner_profile"] = owner_profile | |
| manifest["account_collateral"] = _collateral_summary(owner_profile["owner"]) | |
| _persist_launch_manifest(manifest) | |
| return manifest | |
| def token_launch_status(): | |
| """Return the latest Merkle token-launch manifest, creating one if needed.""" | |
| try: | |
| manifest = _latest_launch_manifest() or _prepare_launch_manifest() | |
| return jsonify(manifest) | |
| except Exception as e: | |
| return jsonify({"status": "error", "message": str(e)}), 500 | |
| def token_launch_prepare(): | |
| """Prepare a new unsigned Merkle launch manifest from one canonical tree.""" | |
| try: | |
| payload = request.get_json(silent=True) or {} | |
| manifest = _prepare_launch_manifest(payload) | |
| return jsonify(manifest), 201 | |
| except Exception as e: | |
| return jsonify({"status": "error", "message": str(e)}), 500 | |
| def token_launch_pool_setup(): | |
| """Return the unsigned token mint and liquidity-pool setup plan.""" | |
| try: | |
| manifest = _latest_launch_manifest() or _prepare_launch_manifest() | |
| return jsonify({ | |
| "status": manifest["pool_setup_status"]["status"], | |
| "execution_status": manifest["execution_status"], | |
| "pool_setup_status": manifest["pool_setup_status"], | |
| "merkle_root": manifest["merkle_root"], | |
| "manifest_hash": manifest["manifest_hash"], | |
| "token_spec": manifest["token_spec"], | |
| "pool_spec": manifest["pool_spec"], | |
| "unsigned_solana_plan": manifest["unsigned_solana_plan"], | |
| "requires_wallet_signature": True, | |
| "requires_quote_asset_funding": True, | |
| }) | |
| except Exception as e: | |
| return jsonify({"status": "error", "message": str(e)}), 500 | |
| # ── Autonomous Token Creation (real on-chain mint) ── | |
| def token_create(): | |
| """Autonomously create a new Solana devnet token mint.""" | |
| try: | |
| payload = request.get_json(silent=True) or {} | |
| # Check if one already exists | |
| existing = get_existing_mint() | |
| if existing: | |
| return jsonify({ | |
| "status": "already_exists", | |
| "message": "A token mint already exists. Use /api/token/status to view it.", | |
| "mint_address": existing, | |
| }) | |
| result = autonomously_create_token( | |
| token_name=payload.get("token_name", "AirMicroDrip"), | |
| token_symbol=payload.get("token_symbol", "DRIP"), | |
| decimals=payload.get("decimals", 9), | |
| existing_secret_b64=payload.get("existing_secret_b64"), | |
| ) | |
| if result["status"] == "ok": | |
| # Set env for immediate use | |
| os.environ["TOKEN_MINT"] = result["mint_address"] | |
| return jsonify(result) | |
| if result["status"] in ("wallet_created_needs_funding", "wallet_ready"): | |
| # Return 200 with actionable info so caller can fund and retry | |
| return jsonify(result), 200 | |
| return jsonify(result), 400 | |
| except Exception as e: | |
| return jsonify({"status": "error", "message": str(e)}), 500 | |
| def token_status(): | |
| """Get the autonomous token launch status.""" | |
| try: | |
| status = get_launch_status() | |
| if not status: | |
| return jsonify({ | |
| "status": "not_created", | |
| "message": "No token mint found. POST to /api/token/create to create one.", | |
| }) | |
| return jsonify({"status": "ok", "launch": status}) | |
| except Exception as e: | |
| return jsonify({"status": "error", "message": str(e)}), 500 | |
| def token_backup(): | |
| """Download the wallet keypair backup (one-time sensitive operation).""" | |
| try: | |
| backup = get_keypair_backup() | |
| if not backup: | |
| return jsonify({ | |
| "status": "not_found", | |
| "message": "No token launch found. Create one first at /api/token/create", | |
| }), 404 | |
| keypair_json = { | |
| "pubkey": backup["pubkey"], | |
| "secret": backup["secret"], | |
| "mint_address": backup["mint_address"], | |
| "token_symbol": backup["token_symbol"], | |
| "warning": "This is your wallet private key. Store it securely. If lost, this wallet cannot be recovered.", | |
| } | |
| return jsonify(keypair_json) | |
| except Exception as e: | |
| return jsonify({"status": "error", "message": str(e)}), 500 | |
| def collateral_status(): | |
| """Return latest HF account collateral scan summary.""" | |
| try: | |
| owner = request.args.get("owner", SPACE_OWNER) | |
| collateral = _latest_collateral(owner) | |
| if not collateral: | |
| return jsonify(_collateral_summary(owner)) | |
| return jsonify(collateral) | |
| except Exception as e: | |
| return jsonify({"status": "error", "message": str(e)}), 500 | |
| def collateral_scan(): | |
| """Scan owner public HF repos/spaces/files and rebuild launch manifest.""" | |
| try: | |
| payload = request.get_json(silent=True) or {} | |
| owner = payload.get("owner") or SPACE_OWNER | |
| existing = COLLATERAL_SCAN_JOBS.get(owner) | |
| if existing and existing.get("status") == "running": | |
| return jsonify({ | |
| "status": "scan_already_running", | |
| "owner": owner, | |
| "job": existing, | |
| "collateral": _collateral_summary(owner), | |
| }), 202 | |
| thread = threading.Thread(target=_run_collateral_scan_job, args=(owner,), daemon=True) | |
| thread.start() | |
| return jsonify({ | |
| "status": "scan_started", | |
| "owner": owner, | |
| "collateral": _collateral_summary(owner), | |
| "requires_wallet_signature": True, | |
| "message": "Scanning all public HF repos, spaces, files, and readable LOC in the background.", | |
| }), 202 | |
| except Exception as e: | |
| return jsonify({"status": "error", "message": str(e)}), 500 | |
| def _gateio_tickers(): | |
| """Fetch real Gate.io futures tickers""" | |
| try: | |
| r = requests.get('https://api.gateio.ws/api/v4/futures/usdt/tickers', timeout=10) | |
| if r.status_code == 200: | |
| return {t['contract']: t for t in r.json()} | |
| except Exception as e: | |
| logger.warning("Gate.io tickers fetch failed: %s", e) | |
| return {} | |
| def _gateio_funding(): | |
| """Fetch real Gate.io funding rates""" | |
| try: | |
| r = requests.get('https://api.gateio.ws/api/v4/futures/usdt/funding_rate', timeout=10) | |
| if r.status_code == 200: | |
| return {f['contract']: f for f in r.json()} | |
| except Exception as e: | |
| logger.warning("Gate.io funding fetch failed: %s", e) | |
| return {} | |
| def slippage_stats(): | |
| """Get slippage collection statistics from real DexScreener API""" | |
| try: | |
| token_mint = _token_mint() | |
| collector = create_collector(token_mint, "drippage_pool") | |
| collector.process_real_trades() | |
| stats = collector.get_collection_stats() | |
| # Also fetch fresh whale stats | |
| from slippage_collector import _fetch_dexscreener_pairs, WhaleDetector | |
| pairs = _fetch_dexscreener_pairs(token_mint) | |
| detector = WhaleDetector() | |
| detector.detect_from_pairs(pairs) | |
| whale_stats = detector.get_whale_stats() | |
| return jsonify({ | |
| "status": stats.get("status", "pending"), | |
| "last_fetch": stats.get("last_fetch"), | |
| "total_collected_usd": stats.get("total_collected_usd", 0), | |
| "total_collections": stats.get("total_collections", 0), | |
| "avg_slippage_bps": stats.get("avg_slippage_bps", 0), | |
| "recent_collections": stats.get("recent_collections", []), | |
| "whale_trades_today": whale_stats.get("total_whale_trades", 0), | |
| "total_whale_volume_24h": whale_stats.get("total_volume_24h", 0), | |
| }) | |
| except Exception as e: | |
| return jsonify({"status": "error", "message": str(e)}), 500 | |
| def holder_stats(): | |
| """Get holder statistics from real Solana RPC""" | |
| try: | |
| token_mint = _token_mint() | |
| # Attempt to sync fresh holder data from chain | |
| if token_mint: | |
| try: | |
| tracker = HolderTracker(token_mint, db_path=HOLDER_DB) | |
| tracker.sync_holders_from_chain() | |
| except Exception as sync_err: | |
| logger.warning("Holder sync warning: %s", sync_err) | |
| conn = sqlite3.connect(HOLDER_DB) | |
| cursor = conn.cursor() | |
| cursor.execute("SELECT COUNT(*) FROM holders") | |
| total_holders = cursor.fetchone()[0] | |
| cursor.execute("SELECT COUNT(*) FROM holders WHERE eligible = TRUE") | |
| eligible_holders = cursor.fetchone()[0] | |
| today = datetime.utcnow().date() | |
| cursor.execute("SELECT COUNT(*) FROM holders WHERE DATE(first_seen) = ?", (today.isoformat(),)) | |
| new_holders_today = cursor.fetchone()[0] | |
| cursor.execute("SELECT SUM(current_balance) FROM holders") | |
| total_balance = cursor.fetchone()[0] or 0 | |
| conn.close() | |
| return jsonify({ | |
| "status": "active" if token_mint else "pending", | |
| "token_mint": token_mint or None, | |
| "default_token": token_mint == DEFAULT_TOKEN_MINT, | |
| "total_holders": total_holders, | |
| "eligible_holders": eligible_holders, | |
| "new_holders_today": new_holders_today, | |
| "total_balance": total_balance, | |
| "eligibility_rate": eligible_holders / total_holders if total_holders > 0 else 0, | |
| }) | |
| except Exception as e: | |
| return jsonify({"status": "error", "message": str(e)}), 500 | |
| def eligible_holders(): | |
| """Get eligible holders for drippage""" | |
| try: | |
| conn = sqlite3.connect(HOLDER_DB) | |
| cursor = conn.cursor() | |
| cursor.execute(""" | |
| SELECT address, current_balance, first_seen, eligibility_timestamp | |
| FROM holders | |
| WHERE eligible = TRUE | |
| ORDER BY current_balance DESC | |
| LIMIT 100 | |
| """) | |
| holders = cursor.fetchall() | |
| conn.close() | |
| return jsonify([ | |
| { | |
| "address": h[0], | |
| "balance": h[1], | |
| "first_seen": h[2], | |
| "holding_hours": (datetime.utcnow() - datetime.fromisoformat(h[2])).total_seconds() / 3600 if h[2] else 0, | |
| } | |
| for h in holders | |
| ]) | |
| except Exception as e: | |
| return jsonify({"error": str(e)}), 500 | |
| def liquidity_stats(): | |
| """Get LLM liquidity statistics with real inference benchmark""" | |
| try: | |
| inference_url = _inference_url() | |
| # Attempt real benchmark if endpoint configured | |
| if inference_url: | |
| try: | |
| registry = InferenceRegistry(db_path=INFERENCE_DB) | |
| converter = LiquidityConverter(registry) | |
| monitor = PerformanceMonitor(registry) | |
| bench = monitor._benchmark_inference_endpoint(inference_url, "llama2") | |
| if bench["status"] == "verified": | |
| registry.register_provider("prov_api_001", "api_worker", "llama2") | |
| registry.verify_capacity( | |
| "prov_api_001", | |
| bench["tokens_per_second"], | |
| bench["latency_ms"], | |
| 99.0, | |
| bench["quality_score"], | |
| ) | |
| metrics = registry.get_provider_capacity("prov_api_001") | |
| if metrics: | |
| liquidity = converter.calculate_liquidity(metrics) | |
| converter.allocate_liquidity("prov_api_001", liquidity) | |
| except Exception as bench_err: | |
| print(f"Liquidity benchmark warning: {bench_err}") | |
| conn = sqlite3.connect(INFERENCE_DB) | |
| cursor = conn.cursor() | |
| cursor.execute("SELECT COUNT(*) FROM providers WHERE status = 'active'") | |
| total_providers = cursor.fetchone()[0] | |
| cursor.execute("SELECT SUM(total_earnings) FROM providers") | |
| total_earnings = cursor.fetchone()[0] or 0 | |
| cursor.execute(""" | |
| SELECT provider_id, synthetic_liquidity_usd, allocated_at | |
| FROM liquidity_allocations | |
| ORDER BY allocated_at DESC | |
| LIMIT 10 | |
| """) | |
| allocations = cursor.fetchall() | |
| conn.close() | |
| total_liquidity = sum(a[1] for a in allocations) if allocations else 0 | |
| return jsonify({ | |
| "status": "active" if total_providers > 0 else "local_only", | |
| "message": None if total_providers > 0 else "No API key required. Connect a no-key local Ollama/OpenAI-compatible endpoint to benchmark live LLM liquidity.", | |
| "inference_endpoint": inference_url or None, | |
| "total_providers": total_providers, | |
| "total_liquidity_usd": round(total_liquidity, 2), | |
| "total_earnings": round(total_earnings, 2), | |
| "avg_capacity": round(total_liquidity / total_providers, 2) if total_providers > 0 else 0, | |
| "recent_allocations": [ | |
| {"provider_id": a[0], "liquidity_usd": a[1], "allocated_at": a[2]} | |
| for a in allocations | |
| ], | |
| }) | |
| except Exception as e: | |
| return jsonify({"status": "error", "message": str(e)}), 500 | |
| def liquidity_providers(): | |
| """Get all LLM liquidity providers""" | |
| try: | |
| conn = sqlite3.connect(INFERENCE_DB) | |
| cursor = conn.cursor() | |
| cursor.execute(""" | |
| SELECT provider_id, wallet_address, model_type, status, reputation_score, total_earnings | |
| FROM providers | |
| WHERE status = 'active' | |
| ORDER BY total_earnings DESC | |
| """) | |
| providers = cursor.fetchall() | |
| conn.close() | |
| return jsonify([ | |
| { | |
| "provider_id": p[0], | |
| "wallet_address": p[1], | |
| "model_type": p[2], | |
| "status": p[3], | |
| "reputation_score": p[4], | |
| "total_earnings": p[5], | |
| } | |
| for p in providers | |
| ]) | |
| except Exception as e: | |
| return jsonify({"error": str(e)}), 500 | |
| def trading_stats(): | |
| """Get trading statistics""" | |
| try: | |
| conn = sqlite3.connect(TRADING_DB) | |
| cursor = conn.cursor() | |
| cursor.execute("SELECT COUNT(*) FROM positions WHERE size > 0") | |
| active_positions = cursor.fetchone()[0] | |
| cursor.execute("SELECT COUNT(*) FROM trades") | |
| total_trades = cursor.fetchone()[0] | |
| cursor.execute(""" | |
| SELECT SUM(size * price) | |
| FROM trades | |
| WHERE timestamp > datetime('now', '-1 day') | |
| """) | |
| volume_24h = cursor.fetchone()[0] or 0 | |
| cursor.execute("SELECT SUM(size) FROM positions WHERE size > 0") | |
| total_size = cursor.fetchone()[0] or 0 | |
| conn.close() | |
| # Fetch real BTC price from Gate.io for OI calculation | |
| tickers = _gateio_tickers() | |
| btc_price = float(tickers.get('BTC_USDT', {}).get('last', 50000)) | |
| return jsonify({ | |
| "total_volume": volume_24h, | |
| "open_interest": total_size * btc_price, | |
| "active_positions": active_positions, | |
| "total_trades": total_trades, | |
| }) | |
| except Exception as e: | |
| return jsonify({"error": str(e)}), 500 | |
| def trading_markets(): | |
| """Get market overview from Gate.io real data""" | |
| tickers = _gateio_tickers() | |
| funding = _gateio_funding() | |
| markets = [] | |
| for contract, t in tickers.items(): | |
| markets.append({ | |
| "market": contract.replace('_', '/'), | |
| "mark_price": float(t.get('last', 0)), | |
| "index_price": float(t.get('index_price', t.get('last', 0))), | |
| "funding_rate": float(funding.get(contract, {}).get('funding_rate', 0)), | |
| "volume_24h": float(t.get('volume_24h', 0)), | |
| "open_interest": float(t.get('total_size', 0)), | |
| "change_24h": float(t.get('change_percentage', 0)), | |
| }) | |
| if not markets: | |
| return jsonify({"error": "Gate.io API unreachable"}), 503 | |
| return jsonify(markets[:20]) | |
| def funding_stats(): | |
| """Get funding rate statistics from Gate.io""" | |
| try: | |
| funding = _gateio_funding() | |
| rates = list(funding.values()) | |
| if rates: | |
| current_rate = sum(float(r.get('funding_rate', 0)) for r in rates) / len(rates) | |
| avg_rate = current_rate | |
| else: | |
| current_rate = 0 | |
| avg_rate = 0 | |
| return jsonify({ | |
| "current_rate": current_rate, | |
| "current_rate_percent": current_rate * 100, | |
| "avg_rate_24h": avg_rate, | |
| "oi_imbalance": 0, | |
| "recent_rates": [ | |
| {"market": r.get('contract', ''), "rate": float(r.get('funding_rate', 0)), "timestamp": r.get('funding_time', '')} | |
| for r in rates[:24] | |
| ], | |
| }) | |
| except Exception as e: | |
| return jsonify({"error": str(e)}), 500 | |
| def _safe_json(response): | |
| """Extract JSON from a Flask Response or (Response, status) tuple.""" | |
| if isinstance(response, tuple): | |
| response = response[0] | |
| if hasattr(response, 'get_json'): | |
| return response.get_json() or {} | |
| return {} | |
| def liquidation_stats(): | |
| """Get liquidation statistics from real DB""" | |
| try: | |
| conn = sqlite3.connect(TRADING_DB) | |
| cursor = conn.cursor() | |
| cursor.execute("SELECT COUNT(*) FROM positions WHERE size = 0") | |
| total_liquidations = cursor.fetchone()[0] | |
| cursor.execute("SELECT SUM(margin) FROM positions WHERE size > 0") | |
| insurance_fund = cursor.fetchone()[0] or 0 | |
| # Count at-risk positions using real mark prices | |
| tickers = _gateio_tickers() | |
| cursor.execute(""" | |
| SELECT position_id, trader, market, side, size, entry_price, margin, liquidation_price | |
| FROM positions | |
| WHERE size > 0 | |
| """) | |
| positions = cursor.fetchall() | |
| at_risk_count = 0 | |
| for pos in positions: | |
| market = pos[2] | |
| contract = market.replace('/', '_').upper() | |
| mark_price = float(tickers.get(contract, {}).get('last', 50000)) | |
| notional = pos[4] * mark_price | |
| margin_ratio = pos[6] / notional if notional > 0 else 1 | |
| if margin_ratio < 0.10: | |
| at_risk_count += 1 | |
| conn.close() | |
| return jsonify({ | |
| "total_liquidations": total_liquidations, | |
| "insurance_fund": insurance_fund, | |
| "at_risk": at_risk_count, | |
| "recent_liquidations": [], | |
| }) | |
| except Exception as e: | |
| return jsonify({"error": str(e)}), 500 | |
| def at_risk_positions(): | |
| """Get at-risk positions""" | |
| try: | |
| conn = sqlite3.connect(TRADING_DB) | |
| cursor = conn.cursor() | |
| cursor.execute(""" | |
| SELECT position_id, trader, market, side, size, entry_price, margin, liquidation_price | |
| FROM positions | |
| WHERE size > 0 | |
| """) | |
| positions = cursor.fetchall() | |
| conn.close() | |
| tickers = _gateio_tickers() | |
| at_risk = [] | |
| for pos in positions: | |
| market = pos[2] | |
| contract = market.replace('/', '_').upper() | |
| mark_price = float(tickers.get(contract, {}).get('last', 50000)) | |
| notional = pos[4] * mark_price | |
| margin_ratio = pos[6] / notional if notional > 0 else 1 | |
| if margin_ratio < 0.10: | |
| at_risk.append({ | |
| "position_id": pos[0], | |
| "trader": pos[1], | |
| "market": pos[2], | |
| "side": pos[3], | |
| "margin_ratio": margin_ratio, | |
| "liquidation_price": pos[7], | |
| }) | |
| return jsonify(at_risk[:10]) | |
| except Exception as e: | |
| return jsonify({"error": str(e)}), 500 | |
| def mining_stats(): | |
| """Get mining rewards statistics""" | |
| try: | |
| conn = sqlite3.connect(INFERENCE_DB) | |
| cursor = conn.cursor() | |
| cursor.execute("SELECT COUNT(*) FROM providers WHERE status = 'active'") | |
| active_providers = cursor.fetchone()[0] | |
| cursor.execute("SELECT SUM(amount) FROM rewards") | |
| total_rewards = cursor.fetchone()[0] or 0 | |
| cursor.execute("SELECT COUNT(*) FROM rewards") | |
| total_reward_count = cursor.fetchone()[0] | |
| conn.close() | |
| return jsonify({ | |
| "active_providers": active_providers, | |
| "total_rewards": total_rewards, | |
| "total_reward_count": total_reward_count, | |
| "avg_reward_per_provider": total_rewards / active_providers if active_providers > 0 else 0, | |
| }) | |
| except Exception as e: | |
| return jsonify({"error": str(e)}), 500 | |
| def mining_leaderboard(): | |
| """Get mining rewards leaderboard""" | |
| try: | |
| conn = sqlite3.connect(INFERENCE_DB) | |
| cursor = conn.cursor() | |
| cursor.execute(""" | |
| SELECT provider_id, wallet_address, model_type, total_earnings, reputation_score | |
| FROM providers | |
| WHERE status = 'active' | |
| ORDER BY total_earnings DESC | |
| LIMIT 10 | |
| """) | |
| providers = cursor.fetchall() | |
| conn.close() | |
| return jsonify([ | |
| { | |
| "rank": i + 1, | |
| "provider_id": p[0], | |
| "wallet_address": p[1], | |
| "model_type": p[2], | |
| "total_earnings": p[3], | |
| "reputation_score": p[4], | |
| } | |
| for i, p in enumerate(providers) | |
| ]) | |
| except Exception as e: | |
| return jsonify({"error": str(e)}), 500 | |
| def overview(): | |
| """Get overview statistics from all systems""" | |
| try: | |
| config = _integration_config() | |
| slippage = _safe_json(slippage_stats()) | |
| holders = _safe_json(holder_stats()) | |
| liquidity = _safe_json(liquidity_stats()) | |
| trading = _safe_json(trading_stats()) | |
| funding = _safe_json(funding_stats()) | |
| liquidation = _safe_json(liquidation_stats()) | |
| mining = _safe_json(mining_stats()) | |
| token_launch = _safe_json(token_launch_status()) | |
| collateral = _collateral_summary() | |
| # Build systems status from actual endpoint statuses | |
| systems = { | |
| "slippage_collector": slippage.get("status", "pending") if config["token_mint"]["configured"] else "not_wired", | |
| "holder_tracker": holders.get("status", "pending") if config["token_mint"]["configured"] else "not_wired", | |
| "llm_liquidity": liquidity.get("status", "pending") if config["inference_endpoint"]["configured"] else "local_only", | |
| "merkle_token_launch": token_launch.get("status", "pending"), | |
| "hf_account_collateral": collateral.get("status", "not_scanned"), | |
| "trading_engine": "active" if trading.get("total_volume") is not None else "pending", | |
| "funding_engine": "active" if funding.get("current_rate") is not None else "pending", | |
| "liquidation_system": "active" if liquidation.get("total_liquidations") is not None else "pending", | |
| "mining_rewards": "active" if mining.get("total_rewards") is not None else "pending", | |
| } | |
| status_meta = { | |
| "slippage_collector": _status_meta(systems["slippage_collector"], "Slippage collector", "Uses a public default Solana token mint unless another token is configured."), | |
| "holder_tracker": _status_meta(systems["holder_tracker"], "Holder tracker", "Uses public Solana RPC with a default token mint. No API key required."), | |
| "llm_liquidity": _status_meta(systems["llm_liquidity"], "LLM liquidity", "Local-only until an optional no-key local inference endpoint is connected."), | |
| "merkle_token_launch": _status_meta(systems["merkle_token_launch"], "Merkle token launch", "One Merkle root commits token spec, pool spec, allocation vector, gates, and live source metrics."), | |
| "hf_account_collateral": _status_meta(systems["hf_account_collateral"], "HF account collateral", "Public HF repos, spaces, files, and readable LOC are scanned into collateral evidence."), | |
| "trading_engine": _status_meta(systems["trading_engine"], "Trading engine", "Local perpetual futures DB plus public Gate.io market data."), | |
| "funding_engine": _status_meta(systems["funding_engine"], "Funding engine", "Public Gate.io funding-rate feed."), | |
| "liquidation_system": _status_meta(systems["liquidation_system"], "Liquidation system", "Local position-risk engine."), | |
| "mining_rewards": _status_meta(systems["mining_rewards"], "Mining rewards", "Local provider rewards ledger."), | |
| } | |
| return jsonify({ | |
| "mode": "no_mock_real_backend", | |
| "timestamp": datetime.utcnow().isoformat(), | |
| "config": config, | |
| "slippage": slippage, | |
| "holders": holders, | |
| "liquidity": liquidity, | |
| "trading": trading, | |
| "funding": funding, | |
| "liquidation": liquidation, | |
| "mining": mining, | |
| "token_launch": token_launch, | |
| "collateral": collateral, | |
| "systems": systems, | |
| "status_meta": status_meta, | |
| }) | |
| except Exception as e: | |
| return jsonify({"error": str(e)}), 500 | |
| # Serve static UI | |
| def index(): | |
| """Serve the dashboard UI""" | |
| return render_template_string(""" | |
| <!DOCTYPE html> | |
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>AirMicroDrip Control Plane</title> | |
| <script src="https://cdn.tailwindcss.com"></script> | |
| <script> | |
| tailwind.config = { | |
| theme: { | |
| extend: { | |
| colors: { | |
| ink: '#08111f', | |
| panel: '#101b2e', | |
| panel2: '#14233a', | |
| line: '#26364f', | |
| cyan: '#67e8f9', | |
| mint: '#7dd3a8', | |
| amber: '#f5c76b' | |
| } | |
| } | |
| } | |
| } | |
| </script> | |
| <style> | |
| body { | |
| background: | |
| radial-gradient(circle at top left, rgba(103,232,249,0.16), transparent 34rem), | |
| radial-gradient(circle at 80% 15%, rgba(125,211,168,0.10), transparent 30rem), | |
| linear-gradient(135deg, #07111f 0%, #0b1322 55%, #060a12 100%); | |
| } | |
| .glass { background: rgba(16, 27, 46, .82); backdrop-filter: blur(18px); } | |
| .grid-bg { | |
| background-image: | |
| linear-gradient(rgba(255,255,255,.035) 1px, transparent 1px), | |
| linear-gradient(90deg, rgba(255,255,255,.035) 1px, transparent 1px); | |
| background-size: 28px 28px; | |
| } | |
| .mono { font-variant-numeric: tabular-nums; } | |
| </style> | |
| </head> | |
| <body class="grid-bg min-h-screen text-slate-100"> | |
| <div class="mx-auto flex min-h-screen w-full max-w-7xl flex-col px-4 py-5 sm:px-6 lg:px-8"> | |
| <header class="mb-5 flex flex-col gap-4 rounded-3xl border border-white/10 bg-white/[0.035] p-5 shadow-2xl shadow-black/30 md:flex-row md:items-center md:justify-between"> | |
| <div> | |
| <div class="mb-3 flex flex-wrap items-center gap-2"> | |
| <span class="rounded-full border border-cyan/30 bg-cyan/10 px-3 py-1 text-xs font-semibold uppercase tracking-[0.24em] text-cyan">No-key backend</span> | |
| <span id="last-updated" class="rounded-full border border-white/10 px-3 py-1 text-xs text-slate-400">syncing</span> | |
| </div> | |
| <h1 class="text-3xl font-black tracking-tight text-white sm:text-5xl">AirMicroDrip Control Plane</h1> | |
| <p class="mt-3 max-w-3xl text-sm leading-6 text-slate-300 sm:text-base"> | |
| Real Flask backend, public market data, local SQLite ledgers, and optional no-key inference wiring. No fabricated holders, liquidity, payouts, or model benchmarks. | |
| </p> | |
| </div> | |
| <div class="grid min-w-[250px] grid-cols-2 gap-2 text-xs"> | |
| <div class="rounded-2xl border border-white/10 bg-black/20 p-3"> | |
| <div class="text-slate-500">Mode</div> | |
| <div id="runtime-mode" class="mt-1 font-semibold text-mint">no_mock_real_backend</div> | |
| </div> | |
| <div class="rounded-2xl border border-white/10 bg-black/20 p-3"> | |
| <div class="text-slate-500">API keys</div> | |
| <div class="mt-1 font-semibold text-cyan">not required</div> | |
| </div> | |
| </div> | |
| </header> | |
| <main class="grid flex-1 gap-5 lg:grid-cols-[1.35fr_.65fr]"> | |
| <section class="space-y-5"> | |
| <div class="grid grid-cols-1 gap-4 sm:grid-cols-2 xl:grid-cols-4"> | |
| <article class="glass rounded-3xl border border-white/10 p-5 shadow-xl shadow-black/20"> | |
| <p class="text-xs uppercase tracking-[0.2em] text-slate-500">Total holders</p> | |
| <p id="total-holders" class="mono mt-3 text-4xl font-black">--</p> | |
| <p id="holder-subtitle" class="mt-2 text-xs text-slate-400">public Solana RPC</p> | |
| </article> | |
| <article class="glass rounded-3xl border border-white/10 p-5 shadow-xl shadow-black/20"> | |
| <p class="text-xs uppercase tracking-[0.2em] text-slate-500">LLM providers</p> | |
| <p id="total-providers" class="mono mt-3 text-4xl font-black">--</p> | |
| <p class="mt-2 text-xs text-slate-400">optional local inference endpoint</p> | |
| </article> | |
| <article class="glass rounded-3xl border border-white/10 p-5 shadow-xl shadow-black/20"> | |
| <p class="text-xs uppercase tracking-[0.2em] text-slate-500">Synthetic liquidity</p> | |
| <p id="total-liquidity" class="mono mt-3 text-4xl font-black">--</p> | |
| <p class="mt-2 text-xs text-slate-400">verified benchmark only</p> | |
| </article> | |
| <article class="glass rounded-3xl border border-white/10 p-5 shadow-xl shadow-black/20"> | |
| <p class="text-xs uppercase tracking-[0.2em] text-slate-500">Active positions</p> | |
| <p id="active-positions" class="mono mt-3 text-4xl font-black">--</p> | |
| <p class="mt-2 text-xs text-slate-400">local perp engine</p> | |
| </article> | |
| </div> | |
| <div class="grid gap-5 xl:grid-cols-[.9fr_1.1fr]"> | |
| <section class="glass rounded-3xl border border-white/10 p-5"> | |
| <div class="mb-4 flex items-center justify-between"> | |
| <h2 class="text-lg font-bold">System fabric</h2> | |
| <span class="rounded-full bg-mint/10 px-3 py-1 text-xs font-semibold text-mint">backend online</span> | |
| </div> | |
| <div id="system-status" class="space-y-3"> | |
| <div class="h-14 animate-pulse rounded-2xl bg-white/5"></div> | |
| <div class="h-14 animate-pulse rounded-2xl bg-white/5"></div> | |
| <div class="h-14 animate-pulse rounded-2xl bg-white/5"></div> | |
| </div> | |
| </section> | |
| <section class="glass rounded-3xl border border-white/10 p-5"> | |
| <div class="mb-4 flex items-center justify-between"> | |
| <h2 class="text-lg font-bold">No-key integration map</h2> | |
| <span class="rounded-full border border-cyan/25 bg-cyan/10 px-3 py-1 text-xs text-cyan">public + local</span> | |
| </div> | |
| <div id="integration-map" class="grid gap-3 sm:grid-cols-2"></div> | |
| </section> | |
| </div> | |
| <section class="glass rounded-3xl border border-white/10 p-5"> | |
| <div class="mb-4 flex items-center justify-between"> | |
| <h2 class="text-lg font-bold">Market and protocol telemetry</h2> | |
| <span class="text-xs text-slate-500">values are persisted or fetched live</span> | |
| </div> | |
| <div class="grid gap-3 md:grid-cols-3"> | |
| <div class="rounded-2xl border border-white/10 bg-black/20 p-4"> | |
| <p class="text-xs uppercase tracking-[0.18em] text-slate-500">24h volume</p> | |
| <p id="volume-24h" class="mono mt-2 text-2xl font-bold">$0</p> | |
| </div> | |
| <div class="rounded-2xl border border-white/10 bg-black/20 p-4"> | |
| <p class="text-xs uppercase tracking-[0.18em] text-slate-500">Funding avg</p> | |
| <p id="funding-rate" class="mono mt-2 text-2xl font-bold">0%</p> | |
| </div> | |
| <div class="rounded-2xl border border-white/10 bg-black/20 p-4"> | |
| <p class="text-xs uppercase tracking-[0.18em] text-slate-500">Insurance fund</p> | |
| <p id="insurance-fund" class="mono mt-2 text-2xl font-bold">$0</p> | |
| </div> | |
| </div> | |
| </section> | |
| <section class="glass rounded-3xl border border-cyan/20 p-5"> | |
| <div class="mb-4 flex items-center justify-between gap-3"> | |
| <div> | |
| <h2 class="text-lg font-bold">One Merkle Tree Token Launch</h2> | |
| <p class="mt-1 text-xs text-slate-400">A single root commits token spec, pool spec, allocation vector, gates, and live source metrics.</p> | |
| </div> | |
| <span id="launch-status" class="rounded-full border border-cyan/30 bg-cyan/10 px-3 py-1 text-xs font-semibold uppercase tracking-[0.18em] text-cyan">loading</span> | |
| </div> | |
| <div class="grid gap-3 md:grid-cols-3"> | |
| <div class="rounded-2xl border border-white/10 bg-black/20 p-4"> | |
| <p class="text-xs uppercase tracking-[0.18em] text-slate-500">Token</p> | |
| <p id="launch-token" class="mt-2 text-2xl font-black">--</p> | |
| <p id="launch-supply" class="mt-1 text-xs text-slate-400">supply pending</p> | |
| </div> | |
| <div class="rounded-2xl border border-white/10 bg-black/20 p-4"> | |
| <p class="text-xs uppercase tracking-[0.18em] text-slate-500">Pool</p> | |
| <p id="launch-pool" class="mt-2 text-2xl font-black">--</p> | |
| <p id="launch-pool-status" class="mt-1 text-xs text-slate-400">quote asset requires signer funding</p> | |
| </div> | |
| <div class="rounded-2xl border border-white/10 bg-black/20 p-4"> | |
| <p class="text-xs uppercase tracking-[0.18em] text-slate-500">Setup plan</p> | |
| <p id="launch-proofs" class="mt-2 text-2xl font-black">--</p> | |
| <p id="launch-leaves" class="mt-1 text-xs text-slate-400">leaves pending</p> | |
| </div> | |
| </div> | |
| <div class="mt-3 grid gap-3 lg:grid-cols-2"> | |
| <div class="rounded-2xl border border-white/10 bg-black/20 p-4"> | |
| <p class="text-xs uppercase tracking-[0.18em] text-slate-500">Merkle root</p> | |
| <p id="launch-root" class="mono mt-2 break-all text-xs text-cyan">--</p> | |
| </div> | |
| <div class="rounded-2xl border border-white/10 bg-black/20 p-4"> | |
| <p class="text-xs uppercase tracking-[0.18em] text-slate-500">Manifest hash</p> | |
| <p id="launch-hash" class="mono mt-2 break-all text-xs text-mint">--</p> | |
| </div> | |
| </div> | |
| <div class="mt-3 rounded-2xl border border-amber/20 bg-amber/10 p-4 text-xs leading-5 text-amber"> | |
| This prepares the launch tree. It does not claim a live SPL mint or live liquidity pool until real wallet-signed transaction signatures are published. | |
| </div> | |
| </section> | |
| <section class="glass rounded-3xl border border-mint/20 p-5"> | |
| <div class="mb-4 flex items-center justify-between gap-3"> | |
| <div> | |
| <h2 class="text-lg font-bold">HF Account Collateral</h2> | |
| <p class="mt-1 text-xs text-slate-400">Owner repos, Spaces, files, and readable LOC become collateral leaves in the same launch tree.</p> | |
| </div> | |
| <div class="flex flex-col items-end gap-2"> | |
| <span id="collateral-status" class="rounded-full border border-mint/30 bg-mint/10 px-3 py-1 text-xs font-semibold uppercase tracking-[0.18em] text-mint">not scanned</span> | |
| <button id="collateral-scan-button" class="rounded-full border border-cyan/30 bg-cyan/10 px-3 py-1 text-xs font-semibold text-cyan hover:bg-cyan/20">scan account</button> | |
| </div> | |
| </div> | |
| <div class="grid gap-3 md:grid-cols-4"> | |
| <div class="rounded-2xl border border-white/10 bg-black/20 p-4"> | |
| <p class="text-xs uppercase tracking-[0.18em] text-slate-500">Owner</p> | |
| <p id="collateral-owner" class="mt-2 text-2xl font-black">--</p> | |
| </div> | |
| <div class="rounded-2xl border border-white/10 bg-black/20 p-4"> | |
| <p class="text-xs uppercase tracking-[0.18em] text-slate-500">Repos</p> | |
| <p id="collateral-repos" class="mono mt-2 text-2xl font-black">0</p> | |
| </div> | |
| <div class="rounded-2xl border border-white/10 bg-black/20 p-4"> | |
| <p class="text-xs uppercase tracking-[0.18em] text-slate-500">Files read</p> | |
| <p id="collateral-files" class="mono mt-2 text-2xl font-black">0</p> | |
| </div> | |
| <div class="rounded-2xl border border-white/10 bg-black/20 p-4"> | |
| <p class="text-xs uppercase tracking-[0.18em] text-slate-500">LOC</p> | |
| <p id="collateral-loc" class="mono mt-2 text-2xl font-black">0</p> | |
| </div> | |
| </div> | |
| <div class="mt-3 rounded-2xl border border-white/10 bg-black/20 p-4"> | |
| <p class="text-xs uppercase tracking-[0.18em] text-slate-500">Collateral root</p> | |
| <p id="collateral-root" class="mono mt-2 break-all text-xs text-mint">scan required</p> | |
| </div> | |
| </section> | |
| </div> | |
| <aside class="space-y-5"> | |
| <section class="glass rounded-3xl border border-white/10 p-5"> | |
| <h2 class="text-lg font-bold">Backend contract</h2> | |
| <div class="mt-4 space-y-3 text-sm text-slate-300"> | |
| <div class="rounded-2xl border border-mint/20 bg-mint/10 p-4"> | |
| <div class="font-semibold text-mint">No API keys required</div> | |
| <p class="mt-1 text-xs text-slate-300">Public feeds and local ledgers are used by default. Optional endpoints are clearly marked local-only until connected.</p> | |
| </div> | |
| <div class="rounded-2xl border border-white/10 bg-black/20 p-4"> | |
| <div class="font-semibold text-white">No mock success states</div> | |
| <p class="mt-1 text-xs text-slate-400">If a source is unavailable, the app reports waiting, local-only, or error states instead of inventing values.</p> | |
| </div> | |
| </div> | |
| </section> | |
| <section class="glass rounded-3xl border border-white/10 p-5"> | |
| <h2 class="text-lg font-bold">Data provenance</h2> | |
| <div class="mt-4 space-y-3 text-sm" id="provenance-list"> | |
| <div class="rounded-2xl border border-white/10 bg-black/20 p-3 text-slate-400">Loading provenance...</div> | |
| </div> | |
| </section> | |
| <section class="glass rounded-3xl border border-white/10 p-5"> | |
| <h2 class="text-lg font-bold">Operator notes</h2> | |
| <ul class="mt-4 space-y-2 text-sm text-slate-300"> | |
| <li>• Holder and slippage routes use a public default token mint.</li> | |
| <li>• LLM liquidity activates only after a real endpoint responds.</li> | |
| <li>• Existing local ledgers remain empty until real events occur.</li> | |
| </ul> | |
| </section> | |
| </aside> | |
| </main> | |
| </div> | |
| <script> | |
| function formatNumber(value, prefix = '') { | |
| if (value === undefined || value === null || Number.isNaN(Number(value))) return prefix + '0'; | |
| return prefix + Number(value).toLocaleString(undefined, { maximumFractionDigits: 2 }); | |
| } | |
| function formatValue(value, prefix = '') { | |
| if (value === undefined || value === null) return prefix + '0'; | |
| if (typeof value === 'number') return formatNumber(value, prefix); | |
| return String(value); | |
| } | |
| function statusClasses(status) { | |
| if (status === 'active') return 'border-mint/30 bg-mint/10 text-mint'; | |
| if (status === 'local_only') return 'border-cyan/30 bg-cyan/10 text-cyan'; | |
| if (status === 'unsigned_ready') return 'border-cyan/30 bg-cyan/10 text-cyan'; | |
| if (status === 'ready_for_signature') return 'border-mint/30 bg-mint/10 text-mint'; | |
| if (status === 'pending' || status === 'not_wired') return 'border-amber/30 bg-amber/10 text-amber'; | |
| if (status === 'not_scanned') return 'border-amber/30 bg-amber/10 text-amber'; | |
| return 'border-red-400/30 bg-red-400/10 text-red-300'; | |
| } | |
| function statusDot(status) { | |
| if (status === 'active') return 'bg-mint'; | |
| if (status === 'local_only') return 'bg-cyan'; | |
| if (status === 'unsigned_ready') return 'bg-cyan'; | |
| if (status === 'ready_for_signature') return 'bg-mint'; | |
| if (status === 'pending' || status === 'not_wired') return 'bg-amber'; | |
| if (status === 'not_scanned') return 'bg-amber'; | |
| return 'bg-red-300'; | |
| } | |
| async function startCollateralScan() { | |
| const button = document.getElementById('collateral-scan-button'); | |
| button.disabled = true; | |
| button.textContent = 'scanning...'; | |
| try { | |
| await fetch('/api/collateral/scan', { | |
| method: 'POST', | |
| headers: { 'Content-Type': 'application/json' }, | |
| body: JSON.stringify({}) | |
| }); | |
| await loadData(); | |
| } catch (error) { | |
| console.error('Failed to start collateral scan:', error); | |
| } finally { | |
| setTimeout(() => { | |
| button.disabled = false; | |
| button.textContent = 'scan account'; | |
| }, 3000); | |
| } | |
| } | |
| async function loadData() { | |
| try { | |
| const response = await fetch('/api/overview'); | |
| if (!response.ok) throw new Error('overview failed: ' + response.status); | |
| const data = await response.json(); | |
| const holders = data.holders || {}; | |
| const liquidity = data.liquidity || {}; | |
| const trading = data.trading || {}; | |
| const funding = data.funding || {}; | |
| const liquidation = data.liquidation || {}; | |
| const tokenLaunch = data.token_launch || {}; | |
| const collateral = data.collateral || {}; | |
| const statusMeta = data.status_meta || {}; | |
| const config = data.config || {}; | |
| const integrations = config || {}; | |
| document.getElementById('total-holders').textContent = formatValue(holders.total_holders); | |
| document.getElementById('total-providers').textContent = formatValue(liquidity.total_providers); | |
| document.getElementById('total-liquidity').textContent = formatNumber(liquidity.total_liquidity_usd, '$'); | |
| document.getElementById('active-positions').textContent = formatValue(trading.active_positions); | |
| document.getElementById('volume-24h').textContent = formatNumber(trading.total_volume, '$'); | |
| document.getElementById('funding-rate').textContent = ((funding.current_rate_percent || 0).toFixed(4)) + '%'; | |
| document.getElementById('insurance-fund').textContent = formatNumber(liquidation.insurance_fund, '$'); | |
| document.getElementById('runtime-mode').textContent = data.mode || 'no_mock_real_backend'; | |
| document.getElementById('last-updated').textContent = data.timestamp ? new Date(data.timestamp).toLocaleTimeString() : 'live'; | |
| document.getElementById('holder-subtitle').textContent = holders.default_token ? 'default public token mint' : 'configured token mint'; | |
| document.getElementById('launch-status').textContent = (tokenLaunch.status || 'waiting').replace('_', ' '); | |
| document.getElementById('launch-token').textContent = `${tokenLaunch.token_spec?.symbol || '--'}`; | |
| document.getElementById('launch-supply').textContent = formatNumber(tokenLaunch.token_spec?.total_supply) + ' committed supply'; | |
| document.getElementById('launch-pool').textContent = tokenLaunch.pool_spec?.pair || '--'; | |
| document.getElementById('launch-pool-status').textContent = tokenLaunch.pool_setup_status?.status?.replaceAll('_', ' ') || 'ready for signature'; | |
| document.getElementById('launch-proofs').textContent = `${tokenLaunch.unsigned_solana_plan?.length || 0} steps`; | |
| document.getElementById('launch-leaves').textContent = `${tokenLaunch.leaf_count || 0} leaves / proofs ${Object.values(tokenLaunch.proof_checks || {}).every(Boolean) ? 'verified' : 'waiting'}`; | |
| document.getElementById('launch-root').textContent = tokenLaunch.merkle_root || '--'; | |
| document.getElementById('launch-hash').textContent = tokenLaunch.manifest_hash || '--'; | |
| document.getElementById('collateral-status').textContent = (collateral.status || 'not_scanned').replaceAll('_', ' '); | |
| document.getElementById('collateral-owner').textContent = collateral.owner || '--'; | |
| document.getElementById('collateral-repos').textContent = formatValue(collateral.repo_count); | |
| document.getElementById('collateral-files').textContent = formatValue(collateral.total_text_files || collateral.total_files); | |
| document.getElementById('collateral-loc').textContent = formatValue(collateral.total_loc); | |
| document.getElementById('collateral-root').textContent = collateral.collateral_root || 'scan required'; | |
| const scanButton = document.getElementById('collateral-scan-button'); | |
| if (collateral.status === 'running') { | |
| scanButton.disabled = true; | |
| scanButton.textContent = 'scanning...'; | |
| } else { | |
| scanButton.disabled = false; | |
| scanButton.textContent = collateral.collateral_root ? 'rescan account' : 'scan account'; | |
| } | |
| const statusHtml = Object.entries(statusMeta).map(([key, meta]) => { | |
| const status = meta.status || 'pending'; | |
| return ` | |
| <div class="rounded-2xl border ${statusClasses(status)} p-4"> | |
| <div class="flex items-start justify-between gap-3"> | |
| <div> | |
| <div class="flex items-center gap-2 font-semibold"> | |
| <span class="h-2 w-2 rounded-full ${statusDot(status)}"></span> | |
| ${meta.label || key} | |
| </div> | |
| <p class="mt-1 text-xs leading-5 text-slate-300">${meta.detail || ''}</p> | |
| </div> | |
| <span class="rounded-full bg-black/30 px-2.5 py-1 text-[10px] uppercase tracking-[0.18em]">${meta.display || status}</span> | |
| </div> | |
| </div>`; | |
| }).join(''); | |
| document.getElementById('system-status').innerHTML = statusHtml || '<p class="text-slate-400">No system status returned.</p>'; | |
| const integrationHtml = Object.entries(integrations).map(([key, item]) => { | |
| const status = item.status || 'pending'; | |
| return ` | |
| <div class="rounded-2xl border ${statusClasses(status)} p-4"> | |
| <div class="text-xs uppercase tracking-[0.18em] opacity-80">${item.label || key}</div> | |
| <div class="mt-2 text-lg font-bold">${(item.status || '').replace('_', ' ')}</div> | |
| <div class="mt-2 text-xs text-slate-300">${item.env || 'no key needed'}</div> | |
| ${item.value_public ? `<div class="mono mt-2 truncate text-[11px] text-slate-400">${item.value_public}</div>` : ''} | |
| </div>`; | |
| }).join(''); | |
| document.getElementById('integration-map').innerHTML = integrationHtml; | |
| document.getElementById('provenance-list').innerHTML = ` | |
| <div class="rounded-2xl border border-white/10 bg-black/20 p-3"> | |
| <div class="font-semibold text-white">Market data</div> | |
| <div class="mt-1 text-xs text-slate-400">Gate.io public futures endpoints; no API key.</div> | |
| </div> | |
| <div class="rounded-2xl border border-white/10 bg-black/20 p-3"> | |
| <div class="font-semibold text-white">Token graph</div> | |
| <div class="mt-1 text-xs text-slate-400">Solana RPC and DexScreener public routes using the displayed token mint.</div> | |
| </div> | |
| <div class="rounded-2xl border border-white/10 bg-black/20 p-3"> | |
| <div class="font-semibold text-white">Local ledgers</div> | |
| <div class="mt-1 text-xs text-slate-400">SQLite stores inside the running Space container.</div> | |
| </div>`; | |
| } catch (error) { | |
| console.error('Failed to load data:', error); | |
| document.getElementById('system-status').innerHTML = '<div class="rounded-2xl border border-red-400/30 bg-red-400/10 p-4 text-red-200">Backend API did not respond. This is a real error, not a simulated state.</div>'; | |
| } | |
| } | |
| loadData(); | |
| setInterval(loadData, 5000); | |
| document.getElementById('collateral-scan-button').addEventListener('click', startCollateralScan); | |
| </script> | |
| </body> | |
| </html> | |
| """) | |
| if __name__ == '__main__': | |
| port = int(os.environ.get("PORT", 7860)) | |
| print(f"Starting AirMicroDrip on port {port}") | |
| app.run(host='0.0.0.0', port=port, debug=False) | |