| from __future__ import annotations |
|
|
| from fastapi import FastAPI |
| from fastapi.responses import HTMLResponse |
|
|
| from .ledger import Ledger |
| from .models import EventIn, WindsurfPacketRequest |
| from .loop import LiquidityLoop |
| from .windsurf_bridge import WindsurfBridge |
|
|
|
|
| def create_app(db_path: str = "membra_liquidity_agg.db") -> FastAPI: |
| ledger = Ledger(db_path) |
| ledger.init() |
| loop = LiquidityLoop(ledger) |
| bridge = WindsurfBridge(ledger) |
|
|
| app = FastAPI(title="Membra Liquidity Automation Aggregator", version="0.1.0") |
|
|
| @app.get("/", response_class=HTMLResponse) |
| def root(): |
| return """ |
| <!DOCTYPE html> |
| <html> |
| <head> |
| <title>Membra Liquidity Automation</title> |
| <style> |
| body { font-family: Arial, sans-serif; max-width: 800px; margin: 50px auto; padding: 20px; } |
| h1 { color: #2563eb; } |
| .endpoint { background: #f3f4f6; padding: 10px; margin: 10px 0; border-radius: 5px; } |
| code { background: #e5e7eb; padding: 2px 5px; border-radius: 3px; } |
| </style> |
| </head> |
| <body> |
| <h1>💧 Membra Liquidity Automation Aggregator</h1> |
| <p>Local-first automation/control plane for 24/7 liquidity loop with Windsurf bridge.</p> |
| <h2>API Endpoints</h2> |
| <div class="endpoint"><code>GET /health</code> - Health check</div> |
| <div class="endpoint"><code>POST /events</code> - Ingest events</div> |
| <div class="endpoint"><code>GET /events</code> - List events</div> |
| <div class="endpoint"><code>POST /loop/step</code> - Execute loop step</div> |
| <div class="endpoint"><code>GET /loop/state</code> - Get loop state</div> |
| <div class="endpoint"><code>POST /windsurf/packet</code> - Build Windsurf packet</div> |
| <div class="endpoint"><code>GET /receipts</code> - Get receipts</div> |
| <div class="endpoint"><code>POST /halt</code> - Emergency halt</div> |
| <div class="endpoint"><code>POST /resume</code> - Resume operation</div> |
| <p><strong>Status:</strong> Control plane only (no live trading)</p> |
| </body> |
| </html> |
| """ |
|
|
| @app.get("/health") |
| def health(): |
| return {"ok": True, "product": "Membra Liquidity Automation Aggregator", "mode": "control_plane_only"} |
|
|
| @app.post("/events") |
| def add_event(event: EventIn): |
| return ledger.add_event(event) |
|
|
| @app.get("/events") |
| def events(limit: int = 100): |
| return ledger.list_events(limit=limit) |
|
|
| @app.post("/loop/step") |
| def loop_step(): |
| return loop.step() |
|
|
| @app.get("/loop/state") |
| def loop_state(): |
| return ledger.get_loop_state() |
|
|
| @app.post("/windsurf/packet") |
| def windsurf_packet(req: WindsurfPacketRequest): |
| return bridge.build_packet( |
| goal=req.goal, |
| repo_path=req.repo_path, |
| include_recent_events=req.include_recent_events, |
| strict_dry_run=req.strict_dry_run, |
| liquidity_loop=req.liquidity_loop, |
| ) |
|
|
| @app.get("/receipts") |
| def receipts(limit: int = 100): |
| return ledger.receipts(limit=limit) |
|
|
| @app.post("/halt") |
| def halt(reason: str = "manual halt"): |
| from .models import LoopState |
| ledger.set_loop_state(LoopState.HALTED, halted=True, reason=reason) |
| return ledger.get_loop_state() |
|
|
| @app.post("/resume") |
| def resume(): |
| from .models import LoopState |
| ledger.set_loop_state(LoopState.OBSERVE, halted=False, reason=None) |
| return ledger.get_loop_state() |
|
|
| return app |
|
|
|
|
| app = create_app() |
|
|