Files
plm-lottery/tests/unit/test_deposits.py
T
davideandClaude Sonnet 5 df72367f02 Implement full MVP: auth, HD wallet, Electrum client, deposits, bets, round/draw engine, payout, withdrawals, RBF, admin+audit
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>
2026-07-20 23:52:20 +02:00

55 lines
2.1 KiB
Python

import pytest
from sqlalchemy.ext.asyncio import async_sessionmaker, create_async_engine
from app.db.base import Base
from app.db.models import User
from app.deposits.service import credit_confirmed_utxos
@pytest.fixture
async def session_factory():
engine = create_async_engine("sqlite+aiosqlite:///:memory:")
async with engine.begin() as conn:
await conn.run_sync(Base.metadata.create_all)
yield async_sessionmaker(engine, expire_on_commit=False)
await engine.dispose()
@pytest.fixture
async def user_id(session_factory):
async with session_factory() as session:
user = User(username="alice", password_hash="x", derivation_index=0, address="plm1qxxx")
session.add(user)
await session.commit()
return user.id
async def test_credits_confirmed_utxo_and_updates_balance(session_factory, user_id):
entries = [{"tx_hash": "aa" * 32, "tx_pos": 0, "height": 100, "value": 10_000_000}]
async with session_factory() as session:
credited = await credit_confirmed_utxos(session, user_id, entries)
assert credited == 1
user = await session.get(User, user_id)
assert user.cached_balance_sats == 10_000_000
async def test_unconfirmed_entry_is_ignored(session_factory, user_id):
entries = [{"tx_hash": "bb" * 32, "tx_pos": 0, "height": 0, "value": 5_000_000}]
async with session_factory() as session:
credited = await credit_confirmed_utxos(session, user_id, entries)
assert credited == 0
user = await session.get(User, user_id)
assert user.cached_balance_sats == 0
async def test_idempotent_on_repeated_notification(session_factory, user_id):
entries = [{"tx_hash": "cc" * 32, "tx_pos": 0, "height": 100, "value": 7_000_000}]
async with session_factory() as session:
first = await credit_confirmed_utxos(session, user_id, entries)
async with session_factory() as session:
second = await credit_confirmed_utxos(session, user_id, entries)
user = await session.get(User, user_id)
assert first == 1
assert second == 0
assert user.cached_balance_sats == 7_000_000