airmicrodrip / app.py
josephrw's picture
Upload folder using huggingface_hub
e9d4f6a verified
Raw
History Blame Contribute Delete
80.1 kB
#!/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
@app.route('/health', methods=['GET'])
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",
}
})
@app.route('/api/config', methods=['GET'])
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
@app.route('/api/token-launch/status', methods=['GET'])
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
@app.route('/api/token-launch/prepare', methods=['POST'])
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
@app.route('/api/token-launch/pool-setup', methods=['GET'])
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) ──
@app.route('/api/token/create', methods=['POST'])
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
@app.route('/api/token/status', methods=['GET'])
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
@app.route('/api/token/backup', methods=['GET'])
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
@app.route('/api/collateral/status', methods=['GET'])
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
@app.route('/api/collateral/scan', methods=['POST'])
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 {}
@app.route('/api/slippage/stats', methods=['GET'])
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
@app.route('/api/holders/stats', methods=['GET'])
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
@app.route('/api/holders/eligible', methods=['GET'])
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
@app.route('/api/liquidity/stats', methods=['GET'])
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
@app.route('/api/liquidity/providers', methods=['GET'])
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
@app.route('/api/trading/stats', methods=['GET'])
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
@app.route('/api/trading/markets', methods=['GET'])
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])
@app.route('/api/funding/stats', methods=['GET'])
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 {}
@app.route('/api/liquidation/stats', methods=['GET'])
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
@app.route('/api/liquidation/at-risk', methods=['GET'])
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
@app.route('/api/mining/stats', methods=['GET'])
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
@app.route('/api/mining/leaderboard', methods=['GET'])
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
@app.route('/api/overview', methods=['GET'])
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
@app.route('/')
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)