Wallet
Overview
A tenant wallet and ledger. Confirming an order enqueues a token debit. Razorpay is the payment dependency for intents. Stripe appears as a WhatsApp checkout adapter, not as the wallet’s primary client.
Code map
| Piece | Path |
|---|---|
| Feature | src/modules/finance/wallet |
| Listener | wallet.listener.ts |
| Schema | 52-wallet.prisma |
| Razorpay package | src/integrations/payments |
Entities: Wallet, WalletLedgerEntry, PaymentIntent, PaymentEvent.
HTTP: /finance/wallets, /finance/admin.
Business rules
Implementation behavior
order.confirmedis handled byWalletListener, which callsWalletService.deductToken. The order HTTP response does not wait for the debit.Status
Listener is loaded for the worker because it consumes an outbox event.
Implementation behavior
On failure the listener logs
Failed to deduct token…and then throws. The comment in the same catch says not to rethrow.Status
The
throwis what runs. The outbox will retry. See Wallet debit.
Unknown: what a token costs, when it is refunded, and whether the ledger unique key makes deductToken idempotent per order.
Events
Only order.confirmed was found as the wallet trigger. Label failure does not, by itself, enqueue a reversing outbox event in the producer list that was scanned.
Integrations
Razorpay env keys and webhook secret. Setting the key id makes the secret and webhook secret mandatory at boot. WhatsApp payment webhooks accept Stripe and Razorpay signatures. See Payments.