Advertise the jackpot that will actually be paid (B-65)
participant_count and jackpot_sats were computed over every round_participants row, while the draw only picks from confirmed participants and the payout only spends their sats. So the advertised jackpot could exceed the one paid out, and a player whose bet was later abandoned appeared in the count and then vanished again. Counting only confirmed rows would have fixed the arithmetic and broken something else: the player who just bet would see neither themselves nor their money for a whole block. So this is the same confirmed/in-flight split the balance already exposes (balance_sats vs pending_balance_sats): participant_count and jackpot_sats are now the confirmed, authoritative figures, and pending_participant_count/pending_jackpot_sats/has_pending_bets report what is in flight — inclusive figures, not deltas, matching the balance pair's convention. /'s round card shows the confirmed numbers big and the difference as an amber "+N in attesa" suffix, reusing .balance-pending's colour for the same "not settled yet" meaning. The two new spans render from server data through t(), so they carry no data-i18n and onLanguageChange() repaints them from the last response — the one-mechanism-per-element rule. Both strings are in all 7 languages. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -134,6 +134,64 @@ async def test_jackpot_comes_from_the_participants_actual_bets(client):
|
||||
assert body["jackpot_sats"] == (999_800_000 * 2) * 70 // 100
|
||||
|
||||
|
||||
async def test_advertised_jackpot_covers_only_the_bets_that_will_be_paid(client): # B-65
|
||||
"""The draw picks from confirmed participants and the payout spends only their
|
||||
sats, so counting every participant row advertised a jackpot bigger than the one
|
||||
that would actually be paid — and let a player appear in the count and then
|
||||
vanish again if their bet was abandoned. The confirmed figures are the headline
|
||||
ones; what's in flight is reported alongside, never folded in."""
|
||||
from app.db.models import Round, RoundConfig, RoundParticipant
|
||||
|
||||
ac, session_factory = client
|
||||
|
||||
async with session_factory() as session:
|
||||
session.add(RoundConfig(fee_address="", bet_amount_sats=1_000_000_000))
|
||||
session.add(Round(id=60, status="open"))
|
||||
await session.flush()
|
||||
session.add(
|
||||
RoundParticipant(round_id=60, user_id=1, bet_amount_sats=999_800_000, bet_txid="a", status="confirmed")
|
||||
)
|
||||
# One mid-broadcast and one written but not yet broadcast: both in flight,
|
||||
# neither drawn from nor spent by the payout as things stand.
|
||||
session.add(
|
||||
RoundParticipant(round_id=60, user_id=2, bet_amount_sats=999_800_000, bet_txid="b", status="broadcast")
|
||||
)
|
||||
session.add(
|
||||
RoundParticipant(round_id=60, user_id=3, bet_amount_sats=999_800_000, bet_txid="c", status="building")
|
||||
)
|
||||
await session.commit()
|
||||
|
||||
body = (await ac.get("/rounds/current")).json()
|
||||
|
||||
assert body["participant_count"] == 1
|
||||
assert body["jackpot_sats"] == 999_800_000 * 70 // 100
|
||||
# Inclusive, like pending_balance_sats — not a delta.
|
||||
assert body["pending_participant_count"] == 3
|
||||
assert body["pending_jackpot_sats"] == (999_800_000 * 3) * 70 // 100
|
||||
assert body["has_pending_bets"] is True
|
||||
|
||||
|
||||
async def test_no_pending_bets_reported_once_every_bet_has_confirmed(client): # B-65
|
||||
from app.db.models import Round, RoundConfig, RoundParticipant
|
||||
|
||||
ac, session_factory = client
|
||||
|
||||
async with session_factory() as session:
|
||||
session.add(RoundConfig(fee_address="", bet_amount_sats=1_000_000_000))
|
||||
session.add(Round(id=61, status="open"))
|
||||
await session.flush()
|
||||
session.add(
|
||||
RoundParticipant(round_id=61, user_id=1, bet_amount_sats=999_800_000, bet_txid="a", status="confirmed")
|
||||
)
|
||||
await session.commit()
|
||||
|
||||
body = (await ac.get("/rounds/current")).json()
|
||||
|
||||
assert body["has_pending_bets"] is False
|
||||
assert body["pending_participant_count"] == body["participant_count"] == 1
|
||||
assert body["pending_jackpot_sats"] == body["jackpot_sats"]
|
||||
|
||||
|
||||
async def test_draw_waiting_since_is_exposed_only_while_drawing(client):
|
||||
"""B-36: the "drawing" wait on a future block has no timeout, so the frontend
|
||||
needs draw_waiting_since to show "still waiting" instead of implying a bounded
|
||||
|
||||
Reference in New Issue
Block a user