#!/usr/bin/env python3 """ AirMicroDrip API Server Flask API serving real data from all AirMicroDrip systems No mocks - real data from slippage collector, holder tracker, trading engine, etc. """ from flask import Flask, jsonify, request from flask_cors import CORS import sqlite3 import json from datetime import datetime import sys import os import requests # Add parent directory to path for imports sys.path.append(os.path.dirname(os.path.abspath(__file__))) app = Flask(__name__) CORS(app) 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: import logging logging.warning(f"Gate.io tickers fetch failed: {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: import logging logging.warning(f"Gate.io funding fetch failed: {e}") return {} # 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" @app.route('/health', methods=['GET']) def health(): """Health check endpoint""" return jsonify({ "status": "healthy", "timestamp": datetime.utcnow().isoformat(), "systems": { "slippage_collector": "active", "holder_tracker": "active", "llm_liquidity": "active", "trading_engine": "active", "funding_engine": "active", "liquidation_system": "active", "mining_rewards": "active", } }) @app.route('/api/slippage/stats', methods=['GET']) def slippage_stats(): """Get slippage collection statistics from real DB""" try: conn = sqlite3.connect(HOLDER_DB) cursor = conn.cursor() cursor.execute("SELECT COUNT(*) FROM transfers") total_collections = cursor.fetchone()[0] cursor.execute("SELECT SUM(amount) FROM transfers") total_collected = cursor.fetchone()[0] or 0 cursor.execute("SELECT * FROM transfers ORDER BY timestamp DESC LIMIT 10") recent = cursor.fetchall() conn.close() return jsonify({ "total_collected": total_collected, "total_collections": total_collections, "avg_slippage_bps": 0, "recent_collections": [ {"transfer_id": r[0], "from": r[1], "to": r[2], "amount": r[3], "timestamp": r[4]} for r in recent ], "whale_trades_today": 0, "total_whale_volume": 0, }) except Exception as e: return jsonify({"error": str(e)}), 500 @app.route('/api/holders/stats', methods=['GET']) def holder_stats(): """Get holder statistics""" try: conn = sqlite3.connect(HOLDER_DB) cursor = conn.cursor() # Total holders cursor.execute("SELECT COUNT(*) FROM holders") total_holders = cursor.fetchone()[0] # Eligible holders cursor.execute("SELECT COUNT(*) FROM holders WHERE eligible = TRUE") eligible_holders = cursor.fetchone()[0] # New holders today today = datetime.utcnow().date() cursor.execute(""" SELECT COUNT(*) FROM holders WHERE DATE(first_seen) = ? """, (today.isoformat(),)) new_holders_today = cursor.fetchone()[0] # Total balance cursor.execute("SELECT SUM(current_balance) FROM holders") total_balance = cursor.fetchone()[0] or 0 conn.close() return jsonify({ "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({"error": 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""" try: conn = sqlite3.connect(INFERENCE_DB) cursor = conn.cursor() # Active providers cursor.execute("SELECT COUNT(*) FROM providers WHERE status = 'active'") total_providers = cursor.fetchone()[0] # Total earnings cursor.execute("SELECT SUM(total_earnings) FROM providers") total_earnings = cursor.fetchone()[0] or 0 # Get recent liquidity allocations 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() # Calculate total liquidity total_liquidity = sum(a[1] for a in allocations) if allocations else 0 return jsonify({ "total_providers": total_providers, "total_liquidity_usd": total_liquidity, "total_earnings": total_earnings, "avg_capacity": total_liquidity / total_providers 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({"error": 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() # Active positions cursor.execute("SELECT COUNT(*) FROM positions WHERE size > 0") active_positions = cursor.fetchone()[0] # Total trades cursor.execute("SELECT COUNT(*) FROM trades") total_trades = cursor.fetchone()[0] # 24h volume (sum of trade sizes * prices) cursor.execute(""" SELECT SUM(size * price) FROM trades WHERE timestamp > datetime('now', '-1 day') """) volume_24h = cursor.fetchone()[0] or 0 # Open interest (sum of position sizes * real mark price from Gate.io) 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""" try: 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]) except Exception as e: return jsonify({"error": str(e)}), 500 @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 @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() # Calculate margin ratio for each position using real mark prices 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: # Below 10% margin 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]) # Return top 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() # Active providers cursor.execute("SELECT COUNT(*) FROM providers WHERE status = 'active'") active_providers = cursor.fetchone()[0] # Total rewards distributed cursor.execute("SELECT SUM(amount) FROM rewards") total_rewards = cursor.fetchone()[0] or 0 # Total reward count 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 def _safe_json(response): """Extract JSON from a Flask Response or (Response, status) tuple.""" from flask import Response if isinstance(response, tuple): response = response[0] if hasattr(response, 'get_json'): return response.get_json() or {} return {} @app.route('/api/overview', methods=['GET']) def overview(): """Get overview statistics from all systems""" try: # Aggregate data from all endpoints safely return jsonify({ "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()), }) except Exception as e: return jsonify({"error": str(e)}), 500 if __name__ == '__main__': # Create databases if they don't exist os.makedirs('holder_tracker', exist_ok=True) os.makedirs('llm_liquidity_provider', exist_ok=True) os.makedirs('perp_trading_engine', exist_ok=True) # Run Flask app app.run(host='0.0.0.0', port=7861)