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()