Skip to main content

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​

PiecePath
Featuresrc/modules/finance/wallet
Listenerwallet.listener.ts
Schema52-wallet.prisma
Razorpay packagesrc/integrations/payments

Entities: Wallet, WalletLedgerEntry, PaymentIntent, PaymentEvent.

HTTP: /finance/wallets, /finance/admin.

Business rules​

Implementation behavior

order.confirmed is handled by WalletListener, which calls WalletService.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 throw is 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.