Files
plm-lottery/app/main.py
T
davideandClaude Sonnet 5 c45bf543c0 Wire up the FastAPI app and master-key bootstrap script
app/main.py assembles the lifespan-managed background tasks (Electrum
listener, round scheduler, confirmation poller, RBF bumper) and mounts
all routers behind a /health check. generate_master_key.py is the
one-time ops script that creates and Fernet-encrypts the server's
master xprv before first launch.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-21 10:26:42 +02:00

64 lines
2.2 KiB
Python

import asyncio
from contextlib import asynccontextmanager
from fastapi import FastAPI
import app.bets.confirmation # noqa: F401 (registers the "bet" confirmation handler)
import app.rounds.confirmation # noqa: F401 (registers the "payout" confirmation handler)
import app.withdrawals.confirmation # noqa: F401 (registers the "withdrawal" confirmation handler)
from app.api.routes.admin import router as admin_router
from app.api.routes.bets import router as bets_router
from app.api.routes.users import router as users_router
from app.api.routes.withdrawals import router as withdrawals_router
from app.auth.routes import router as auth_router
from app.config import settings
from app.db.base import AsyncSessionLocal
from app.electrum.client import ElectrumClient
from app.electrum.listener import ElectrumListener
from app.rounds.scheduler import RoundScheduler
from app.tx.broadcast import RbfBumper
from app.tx.confirmation import ConfirmationPoller
from app.tx.locks import UserLocks
def _make_electrum_client() -> ElectrumClient:
return ElectrumClient(settings.electrum_host, settings.electrum_port, settings.electrum_use_ssl)
@asynccontextmanager
async def lifespan(app: FastAPI):
listener = ElectrumListener(_make_electrum_client, AsyncSessionLocal)
app.state.electrum_listener = listener
app.state.user_locks = UserLocks()
scheduler = RoundScheduler(AsyncSessionLocal, listener)
poller = ConfirmationPoller(AsyncSessionLocal, lambda: listener.client)
bumper = RbfBumper(AsyncSessionLocal, lambda: listener.client)
tasks = [
asyncio.create_task(listener.run()),
asyncio.create_task(scheduler.run()),
asyncio.create_task(poller.run()),
asyncio.create_task(bumper.run()),
]
try:
yield
finally:
for task in tasks:
task.cancel()
if listener.client is not None:
await listener.client.close()
app = FastAPI(title="PLM Lottery", lifespan=lifespan)
app.include_router(auth_router)
app.include_router(users_router)
app.include_router(bets_router)
app.include_router(withdrawals_router)
app.include_router(admin_router)
@app.get("/health")
async def health() -> dict[str, str]:
return {"status": "ok"}