All 10 build-order stages complete and unit-tested (49 tests). Verified live on mainnet: registration/address derivation, deposit crediting, a real 10 PLM bet (broadcast + confirmed + change credited). A full round close->draw->payout cycle was triggered live and was in progress at commit time. Withdrawal and RBF bump are unit-tested but not yet exercised against a live broadcast. Known gaps (scheduler doesn't resume mid-flight rounds after restart, payout has no retry, no deployment setup, etc.) are documented in CLAUDE.md. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
45 lines
1.7 KiB
Python
45 lines
1.7 KiB
Python
from fastapi import APIRouter, Depends, Header, HTTPException, status
|
|
from pydantic import BaseModel
|
|
from sqlalchemy.ext.asyncio import AsyncSession
|
|
|
|
from app.config import settings
|
|
from app.db.session import get_session
|
|
from app.rounds.config import get_round_config
|
|
|
|
router = APIRouter(prefix="/admin", tags=["admin"])
|
|
|
|
|
|
async def require_admin(x_admin_token: str = Header(default="")) -> None:
|
|
if not settings.admin_token or x_admin_token != settings.admin_token:
|
|
raise HTTPException(status.HTTP_403_FORBIDDEN, "invalid admin token")
|
|
|
|
|
|
class RoundConfigResponse(BaseModel):
|
|
fee_address: str
|
|
bet_amount_sats: int
|
|
|
|
|
|
class RoundConfigUpdate(BaseModel):
|
|
fee_address: str | None = None
|
|
bet_amount_sats: int | None = None
|
|
|
|
|
|
@router.get("/config", response_model=RoundConfigResponse, dependencies=[Depends(require_admin)])
|
|
async def read_config(session: AsyncSession = Depends(get_session)) -> RoundConfigResponse:
|
|
config = await get_round_config(session)
|
|
await session.commit()
|
|
return RoundConfigResponse(fee_address=config.fee_address, bet_amount_sats=config.bet_amount_sats)
|
|
|
|
|
|
@router.put("/config", response_model=RoundConfigResponse, dependencies=[Depends(require_admin)])
|
|
async def update_config(
|
|
body: RoundConfigUpdate, session: AsyncSession = Depends(get_session)
|
|
) -> RoundConfigResponse:
|
|
config = await get_round_config(session)
|
|
if body.fee_address is not None:
|
|
config.fee_address = body.fee_address
|
|
if body.bet_amount_sats is not None:
|
|
config.bet_amount_sats = body.bet_amount_sats
|
|
await session.commit()
|
|
return RoundConfigResponse(fee_address=config.fee_address, bet_amount_sats=config.bet_amount_sats)
|