Skip to main content

Wallet Architecture Overview

System Components​

Core Services​

Wallet Account Service​

Manages wallet lifecycle and balance operations:

  • Account creation and activation
  • Balance queries
  • Transaction posting
  • Balance reconciliation

Auto Top-Up Worker​

BullMQ worker for scheduled and threshold-based top-ups:

  • Monitors balance thresholds
  • Triggers payment collection
  • Handles failure retry logic
  • Emits outbox events for notifications

Pass Provider Service​

Apple Wallet and Google Wallet integration:

  • Pass template management
  • Pass generation and signing
  • Push updates for balance changes
  • Pass analytics tracking

API Layers​

Portal API​

Member-facing endpoints (/portal/wallet/*):

  • GET /balance - Current balance
  • POST /top-up - Initiate manual top-up
  • GET /transactions - Transaction history
  • POST /auto-top-up - Configure auto top-up
  • GET /pass - Generate digital card

Admin API​

Staff-facing endpoints (/admin/wallet/*):

  • GET /accounts - List all wallets (with filtering)
  • GET /analytics - Cohort analytics
  • POST /credit - Manual credit/debit
  • POST /reconcile - Trigger reconciliation

Webhook API​

External integration endpoints:

  • Payment processor callbacks
  • Pass event webhooks
  • Subscription lifecycle events

Data Model​

Primary Entities​

model WalletAccount {
id String @id @default(uuid())
memberId String
tenantId String
currency String @default("ZAR")
balance Int @default(0) // cents
status WalletStatus
createdAt DateTime
updatedAt DateTime

transactions WalletTransaction[]
autoTopUp AutoTopUpConfig?
passes WalletPass[]
}

model WalletTransaction {
id String @id @default(uuid())
walletId String
type TransactionType
amount Int // cents (positive = credit)
balanceAfter Int
reference String?
description String?
merchantCode String?
postedAt DateTime
}

model AutoTopUpConfig {
id String @id @default(uuid())
walletId String @unique
enabled Boolean @default(false)
type AutoTopUpType // THRESHOLD, SCHEDULED
threshold Int? // cents
amount Int // cents
schedule String? // cron expression
mandateRef String? // stored payment method
}

Event System​

Wallet uses the outbox pattern for reliable event publishing:

Transaction Posted
↓
Insert to wallet_outbox
↓
Outbox Poller claims entry
↓
Process event (notifications, pass updates)
↓
Mark entry complete

Outbox entry types:

  • transaction.posted - New transaction recorded
  • status_changed - Wallet status updated
  • auto_topup.scheduled - Auto top-up scheduled
  • auto_topup.failed - Auto top-up charge failed

Integration Points​

Payment System​

  • Top-up initiation → Checkout session creation
  • Webhook processing → Transaction posting
  • Mandate storage → Auto top-up execution

Notification System​

  • Outbox events → Notification handlers
  • Handler → Channel resolution (email, WhatsApp, SMS, push)
  • Preference gating → Final delivery

Pass Providers​

  • Apple Wallet: PKPass generation, APNS push
  • Google Wallet: Google Pay API integration
  • Balance sync: Periodic and event-driven updates

Security Considerations​

Access Control​

  • Portal endpoints: Member authentication + ownership check
  • Admin endpoints: Staff authentication + permission check
  • Webhook endpoints: Signature verification

Data Protection​

  • All amounts stored in cents (integers)
  • Transaction history immutable
  • Audit trail for admin operations
  • PCI compliance for payment references (no raw card data)

Scaling Considerations​

Performance​

  • Balance queries cached with short TTL
  • Transaction history paginated
  • Analytics queries run on read replicas

Reliability​

  • Outbox pattern ensures at-least-once delivery
  • Idempotent transaction posting
  • Distributed locks for auto top-up execution