Files
plm-lottery/app/api/routes/rounds.py
T
davideandClaude Sonnet 5 80c413ad3d Show the net prize as the jackpot instead of the gross pool
GET /rounds/current's jackpot_sats was the full pool (participant_count *
bet_amount_sats), which overstates what the winner actually receives once
the 30% commission is taken out at payout time. Apply the same 70% split
rounds/scheduler.py uses so the number shown during the round already
matches the real payout, without surfacing the fee itself in the UI/docs.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-22 14:53:09 +02:00

76 lines
2.9 KiB
Python

from datetime import datetime, timedelta, timezone
from fastapi import APIRouter, Depends, Request
from pydantic import BaseModel
from sqlalchemy import func, select
from sqlalchemy.ext.asyncio import AsyncSession
from app.db.models import RoundParticipant
from app.db.session import get_session
from app.rounds.config import get_round_config
from app.rounds.service import get_active_round
router = APIRouter(prefix="/rounds", tags=["rounds"])
class CurrentRoundResponse(BaseModel):
server_time: str
round_id: int | None = None
status: str | None = None
opened_at: str | None = None
closes_at: str | None = None
participant_count: int = 0
bet_amount_sats: int
jackpot_sats: int = 0
draw_animation_seconds: int
winner_user_id: int | None = None
winner_amount_sats: int | None = None
chain_tip_height: int | None = None
lottery_paused: bool = False
@router.get("/current", response_model=CurrentRoundResponse)
async def current_round(request: Request, session: AsyncSession = Depends(get_session)) -> CurrentRoundResponse:
config = await get_round_config(session)
round_ = await get_active_round(session)
listener = request.app.state.electrum_listener
chain_tip_height = listener.tip_height or None
if round_ is None:
await session.commit()
return CurrentRoundResponse(
server_time=datetime.now(timezone.utc).isoformat(),
bet_amount_sats=config.bet_amount_sats,
draw_animation_seconds=config.draw_animation_seconds,
chain_tip_height=chain_tip_height,
lottery_paused=config.paused,
)
participant_count = await session.scalar(
select(func.count()).select_from(RoundParticipant).where(RoundParticipant.round_id == round_.id)
) or 0
opened_at = round_.opened_at.replace(tzinfo=timezone.utc)
closes_at = opened_at + timedelta(seconds=config.round_duration_seconds)
await session.commit()
# Shown to players as "jackpot": the winner's 70% share of the pool (same
# split rounds/scheduler.py applies at payout time), not the full pool —
# what's displayed should match what the winner actually receives.
pool_amount_sats = participant_count * config.bet_amount_sats
jackpot_sats = pool_amount_sats * 70 // 100
return CurrentRoundResponse(
server_time=datetime.now(timezone.utc).isoformat(),
round_id=round_.id,
status=round_.status,
opened_at=opened_at.isoformat(),
closes_at=closes_at.isoformat(),
participant_count=participant_count,
bet_amount_sats=config.bet_amount_sats,
jackpot_sats=jackpot_sats,
draw_animation_seconds=config.draw_animation_seconds,
winner_user_id=round_.winner_user_id,
winner_amount_sats=round_.winner_amount_sats,
chain_tip_height=chain_tip_height,
lottery_paused=config.paused,
)