Wallet and Billing
Current model
Wallet logic is implemented in app/services/wallet_reservation.py and exposed through app/api/routers/wallet.py.
The branch uses a reserve-then-finalize billing pattern:
- reserve an estimated token amount before generation
- perform chat or quiz generation
- finalize the reservation with actual usage
- refund the difference when actual usage is lower
Tables involved
walletwallet_ledgerreservationstransactionsusage_logs
Chat flow
Chat billing is driven by app/agents/teacher_agent.py:
check_walletreservesBASE_CHAT_COST + TOKEN_BUFFERfinalizecomputes actual cost from answer sizeusage_logsstores the retrieval and answer summary
If the flow enters clarification instead of full answer generation, a lower fixed actual cost is used.
Quiz flow
Quiz generation in app/api/routers/quiz.py reuses the same wallet service:
- estimate
300tokens - reserve before generation
- finalize with actual token usage returned by the quiz generator
- mark and refund expired reservations on failure paths
Admin financial operations
Admin-only endpoints support:
- wallet top-up
- expense logging
- transaction history
- internal reserve/finalize endpoints for operational use
These endpoints require an admin JWT, not a separate billing service.
Operational caveats
- Reservation expiry cleanup is intended to be scheduled, but the current scheduler implementation is not aligned with the wallet service API and should be treated as unverified.
- Billing logic is tightly coupled to Supabase table updates and does not yet use database-side transactions or stored procedures for atomicity.