File size: 3,662 Bytes
64a2a09 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 | 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()
|