A full-stack banking application built with Rust (Axum) and React, featuring real-time transactions, admin panel, and double-entry bookkeeping principles used by real banks.
- π Secure Authentication - JWT-based login/registration
- π° Real-time Balance - Instant balance updates with SSE streaming
- πΈ Peer-to-Peer Transfers - Send money to any account instantly
- π Transaction History - Complete payment history with search & filters
- π± Mobile-Responsive - Beautiful UI that works on all devices
- π Transaction Notifications - Real-time toast notifications
- π PDF Export - Download transaction statements as PDF
- π₯ User Management - View all users and their wallets
- π΅ Manual Credits - Credit user accounts (simulates bank deposits)
- βοΈ Freeze/Unfreeze - Control wallet access
- π Audit Trail - Complete log of all admin actions
- π¦ Double-Entry Bookkeeping - Real banking accounting principles
- Rust - Systems programming language for performance & safety
- Axum 0.8 - Ergonomic web framework
- PostgreSQL - Primary database via SQLX
- Redis - Rate limiting & session management
- JWT - Secure authentication
- utoipa - OpenAPI/Swagger documentation
- React 18 - UI library
- TypeScript - Type-safe development
- Vite - Fast build tool
- Tailwind CSS - Utility-first styling
- shadcn/ui - Beautiful components
- React Query - Data fetching & caching
- Zustand - State management
- Sonner - Toast notifications
cd backend
# Copy environment template
cp .env.example .env
# Edit .env with your configuration
# DATABASE_URL=postgresql://user:pass@localhost/payvault
# REDIS_URL=redis://localhost:6379
# JWT_SECRET=your-secret-key
# Run database migrations
sqlx migrate run
# Start development server
cargo runBackend will start on http://localhost:8000
API docs available at http://localhost:8000/docs
cd frontend
# Install dependencies
npm install
# Copy environment template
cp .env.example .env
# Set API URL
# VITE_API_URL=http://localhost:8000
# Start development server
npm run devFrontend will start on http://localhost:5174
POST /auth/register- Create new accountPOST /auth/login- User loginPOST /auth/refresh- Refresh JWT tokenPOST /auth/verify-email- Verify email with OTPPOST /auth/forgot-password- Request password resetPOST /auth/reset-password- Reset password
GET /wallet/balance- Get wallet balanceGET /wallet/balance-stream- SSE balance updatesGET /wallet/lookup/{account_number}- Lookup account holderPOST /wallet/transfer- Transfer moneyGET /transactions- List transactionsGET /transactions/{id}- Transaction details
GET /admin/users- List all usersGET /admin/users/{id}- Get user detailsPOST /admin/wallets/{id}/credit- Credit user walletPOST /admin/wallets/{id}/freeze- Freeze/unfreeze walletGET /admin/audit-logs- View audit trail
-- Users table
CREATE TABLE users (
id UUID PRIMARY KEY,
email VARCHAR UNIQUE NOT NULL,
password_hash VARCHAR NOT NULL,
role VARCHAR NOT NULL DEFAULT 'user',
is_verified BOOLEAN DEFAULT FALSE,
created_at TIMESTAMP
);
-- Wallets table
CREATE TABLE wallets (
id UUID PRIMARY KEY,
user_id UUID REFERENCES users(id),
balance_kobo BIGINT NOT NULL CHECK (balance_kobo >= 0),
account_number VARCHAR(10) UNIQUE NOT NULL,
is_frozen BOOLEAN DEFAULT FALSE,
created_at TIMESTAMP
);
-- Transactions table
CREATE TABLE transactions (
id UUID PRIMARY KEY,
reference VARCHAR UNIQUE NOT NULL,
sender_id UUID REFERENCES users(id),
receiver_id UUID REFERENCES users(id),
amount_kobo BIGINT NOT NULL,
type VARCHAR NOT NULL,
status VARCHAR NOT NULL,
metadata JSONB,
created_at TIMESTAMP
);
-- Audit log table
CREATE TABLE audit_log (
id UUID PRIMARY KEY,
actor_id UUID REFERENCES users(id),
action VARCHAR NOT NULL,
target_type VARCHAR NOT NULL,
target_id UUID,
details JSONB,
created_at TIMESTAMP
);Access at: http://localhost:5174/admin/login
Email: admin@payvault.com
Password: Admin123!
Register new accounts at: http://localhost:5174/auth/register
Or use demo accounts (if pre-created):
- demo1@payvault.com / Demo123!
- demo2@payvault.com / Demo123!
cd backend
cargo testcd frontend
npm testRust_Bank/
βββ backend/
β βββ src/
β β βββ middleware/ # Auth, rate limiting, idempotency
β β βββ modules/ # Feature modules (auth, wallet, etc.)
β β βββ utils/ # Helper functions
β β βββ config.rs # Configuration
β β βββ error.rs # Error handling
β β βββ router.rs # Route definitions
β β βββ main.rs # Entry point
β βββ tests/
β βββ db/migrations/ # SQL migrations
β βββ Cargo.toml
β
βββ frontend/
β βββ src/
β β βββ components/ # React components
β β βββ hooks/ # Custom hooks
β β βββ lib/ # Utilities & API client
β β βββ pages/ # Page components
β β βββ store/ # Zustand stores
β β βββ types/ # TypeScript types
β β βββ App.tsx
β βββ public/
β βββ package.json
β
βββ README.md
- β JWT authentication with refresh tokens
- β Password hashing with bcrypt
- β Rate limiting on sensitive endpoints
- β Idempotency keys for transfers
- β Input validation with validator crate
- β SQL injection prevention via SQLX
- β XSS protection via React escaping
- β CORS configuration
- β Audit logging for admin actions
This isn't just another demo app - it implements real banking principles:
Every transaction affects at least 2 accounts:
User A sends β¦5,000 to User B:
DEBIT: User A Wallet (β¦5,000)
CREDIT: User B Wallet (β¦5,000)
- Assets: Bank's reserves (operations account)
- Liabilities: Customer deposits (user wallets)
- Equity: Bank's capital
Every admin action is logged:
- Who performed the action
- What action was taken
- Which entity was affected
- Details of the change
All money movements use database transactions:
- Atomicity: All or nothing
- Consistency: Database stays valid
- Isolation: Concurrent operations don't interfere
- Durability: Committed data persists
See DEPLOYMENT.md for production deployment guides:
- VPS deployment (DigitalOcean, Linode)
- PaaS deployment (Railway, Render)
- Docker deployment
- Frontend deployment (Vercel, Netlify)
Contributions are welcome! Please read our contributing guidelines first.
MIT License - See LICENSE file for details
Built with β€οΈ using Rust and React
PayVault - Banking infrastructure for the modern web.