ADR 0005: Conversion rate captured per transaction¶
- Status:
Accepted
Context¶
A wallet’s conversionRate (points per coin) can change over time. A past
conversion must remain explainable against the rate that was actually
applied, not whatever the wallet’s rate happens to be now.
Decision¶
Each ConvertPointsToCoins ledger row stamps
appliedConversionRate = wallet.conversionRate at conversion time
(app/services/user_service.py); the column lives on the ledger model
(app/model/wallet_transactions.py). The field is only meaningful for
conversions; AssignPoints rows on the engine scoring path leave it at
0 (app/services/user_points/persistence.py), since no conversion
happens on award.
Consequences¶
Historical conversions stay auditable and replayable even after the wallet rate is changed: the rate travels with the row.
Cost: a denormalized rate snapshot per conversion row.
A conversion can only be traced to its rate if the ledger row was written - see the conversion-atomicity caveat in Known limitations.
See also¶
Domain Model - the
WalletTransactionsfields.Integrating with GAME - “Wallets & the economy”.
ADR 0002: Append-only, immutable wallet ledger - the ledger this rate lives in.