A high-performance, production-grade e-wallet core system engineered for financial integrity, concurrency safety, and strict ACID compliance.
VaultCore is an enterprise-level backend engine designed to handle mission-critical financial operations with zero compromise on data integrity. Built from the ground up to solve the hardest challenges in concurrent financial systems—race conditions, deadlocks, and double-spending—this system is architected for banks, fintech platforms, and payment processors that demand absolute correctness.
Unlike typical CRUD applications, VaultCore implements database-level row locking, deterministic resource ordering, and double-entry bookkeeping to ensure that even under extreme concurrent load, every cent is accounted for.
Key Design Decisions:
- Deterministic Lock Ordering: Prevents deadlocks when User A → User B and User B → User A transfer simultaneously.
- Row-Level Locking (
FOR UPDATE): Prevents double-spending in race conditions. - Double-Entry Accounting: Every transfer creates two linked transactions for full audit trails.
- Advanced RBAC System: Custom Role-Based Access Control with weighted hierarchy (Superuser > Admin > Staff > User)
- JWT Token Management: Secure access & refresh tokens stored in
HttpOnlycookies - Token Versioning: Immediate revocation capability via version increment (invalidates all user sessions)
- Token Blacklisting: Revoked tokens stored in database to prevent reuse
- Email Verification: Account activation workflow with templated emails
- Bcrypt Password Hashing: Industry-standard password protection
- Deposit: Add funds to user wallets with automatic balance updates
- Withdrawal: Deduct funds with insufficient balance protection
- P2P Transfers: User-to-user transfers with bi-directional locking
- Multi-Currency Support: Independent wallets per currency (USD, EUR, etc.)
- Transaction History: Complete audit trail with balance snapshots
- ACID Transactions: Atomicity, Consistency, Isolation, Durability on all operations
- Row-Level Locking:
SELECT ... FOR UPDATEprevents concurrent modification conflicts - Deadlock Prevention: Deterministic wallet ordering algorithm eliminates circular wait conditions
- Decimal Precision:
NUMERIC(18,4)data types (NO floating-point errors) - Double-Entry Ledger: Linked debit/credit transaction pairs via
related_transaction_id - Balance Snapshots: Every transaction records
balance_afterfor point-in-time reconciliation
- Service-Repository Pattern: Clear separation of API logic, business logic, and data access
- Modular Design: Routes, Services, Schemas, Models, Utils organized for scalability
- Pydantic Validation: Request/response schema validation with type safety
- SQLAlchemy ORM: Database abstraction with relationship management
- Alembic Migrations: Version-controlled schema evolution
- Dependency Injection: FastAPI's DI system for database sessions and authentication
Schema Highlights:
- Unique Constraint:
(user_id, currency)on Wallet prevents duplicate currency wallets - Self-Referencing FK:
related_transaction_idlinks transfer debit/credit pairs - Cascading Deletes: User deletion cascades to Wallets → Transactions
- Weighted Roles: Integer weights enable hierarchical permission checks
- Python 3.11+
- PostgreSQL 15+
- Git
git clone https://github.com/yourusername/vaultcore.git
cd vaultcorepython -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activatepip install -r requirements.txtCreate a .env file in the project root:
SECRET_KEY=your_secret_key_here
DATABASE_USERNAME=your_database_username
DATABASE_PASSWORD=your_database_password
DATABASE_SERVER_IP=localhost
DATABASE_PORT=5432
DATABASE_NAME=your_database_name
ACCESS_TOKEN_EXPIRE=30 # in minutes
REFRESH_TOKEN_EXPIRE=7200 # in minutes
ALGORITHM=HS256
SUPERUSER_USERNAME=your_superuser_username
SUPERUSER_EMAIL=your_superuser_email
SUPERUSER_FIRST_NAME=your_first_name
SUPERUSER_MIDDLE_NAME=your_middle_name
SUPERUSER_LAST_NAME=your_last_name
SUPERUSER_PASSWORD=your_superuser_password
MAIL_USERNAME=your_email@example.com
MAIL_PASSWORD=your_email_app_password
MAIL_FROM=your_email@example.com
MAIL_PORT=587
MAIL_SERVER=smtp.gmail.com
MAIL_FROM_NAME=Your_App_Name# Initialize Alembic (if not done)
alembic init alembic
# Generate migration
alembic revision --autogenerate -m "Initial schema"
# Apply migrations
alembic upgrade headuvicorn main:app --reload --host 0.0.0.0 --port 8000API will be available at http://localhost:8000
Interactive docs at http://localhost:8000/docs
-
Configure Environment Variables: Ensure your
.envfile is set up as described in Step 4. -
Start Services:
docker-compose up -d --build
This automatically runs migrations and starts the application.
-
Access the Application:
- API:
http://localhost:8000 - Swagger Docs:
http://localhost:8000/docs
- API:
| Method | Endpoint | Description | Auth Required |
|---|---|---|---|
| POST | /api/v1/auth/register/ |
Create new user account | No |
| POST | /api/v1/auth/token |
Login & receive JWT tokens | No |
| GET | /api/v1/auth/refresh |
Refresh access token | Yes (Refresh) |
| POST | /api/v1/auth/logout |
Logout & revoke tokens | Yes |
| PUT | /api/v1/auth/change-password |
Change user password | Yes |
| POST | /api/v1/auth/verify-email/ |
Request email verification | Yes |
| GET | /api/v1/auth/verify-email/ |
Confirm email verification | No (Token) |
| POST | /api/v1/auth/forgot-password |
Request password reset | No |
| POST | /api/v1/auth/reset-password-confirm |
Confirm password reset | No (Token) |
| POST | /api/v1/auth/request-email-change |
Request email change | Yes |
| GET | /api/v1/auth/confirm-email-change |
Confirm email change | No (Token) |
| Method | Endpoint | Description | Auth Required |
|---|---|---|---|
| POST | /api/v1/wallets/ |
Create currency wallet | Yes |
| GET | /api/v1/wallets/ |
List user's wallets | Yes |
| GET | /api/v1/wallets/{currency} |
Get specific wallet | Yes |
| Method | Endpoint | Description | Auth Required |
|---|---|---|---|
| POST | /api/v1/transaction/deposit |
Deposit funds | Yes |
| POST | /api/v1/transaction/withdraw |
Withdraw funds | Yes |
| POST | /api/v1/transaction/transfer |
P2P transfer | Yes |
| Method | Endpoint | Description | Auth Required |
|---|---|---|---|
| GET | /api/v1/users/ |
List all users | Yes (Permission) |
| GET | /api/v1/users/me/ |
Get current user profile | Yes |
| PUT | /api/v1/users/me/ |
Update profile | Yes |
| GET | /api/v1/users/get_user/{username}/ |
Get user by username | Yes (Permission) |
- Import the API collection from
/docs(Swagger JSON export) - Set environment variables for
base_urlandaccess_token - Run requests in sequence: Register → Login → Create Wallet → Deposit → Transfer
- Dockerization: Multi-stage Dockerfile + docker-compose for PostgreSQL
- CI/CD Pipeline: GitHub Actions for automated testing
- Unit & Integration Tests: Pytest test suite
- API Rate Limiting: Redis-based throttling (100 req/min per user)
- Webhook Notifications: Real-time transaction alerts via webhooks
- Transaction Disputes: Dispute filing & resolution workflow
- CSV Export: Transaction history export for accounting
- Scheduled Payments: Cron-based recurring transfers
- Currency Conversion: Real-time FX rates integration
- Read Replicas: Distribute read queries to PostgreSQL replicas
- Event Sourcing: Replace direct DB writes with event log (Kafka/RabbitMQ)
- Horizontal Scaling: Load balancer + multiple FastAPI instances
- Monitoring: Prometheus metrics + Grafana dashboards
- Distributed Tracing: OpenTelemetry for request tracing
# ❌ WITHOUT LOCKING (Race Condition)
# Thread 1: wallet.balance = 100, withdraw 50 → balance = 50
# Thread 2: wallet.balance = 100, withdraw 50 → balance = 50
# Result: 100 withdrawn, balance = 50 (Lost update!)
# ✅ WITH LOCKING
wallet = db.query(Wallet).with_for_update().first() # Blocks Thread 2
# Thread 1: wallet.balance = 100, withdraw 50 → balance = 50, COMMIT
# Thread 2: wallet.balance = 50, withdraw 50 → FAIL (Insufficient funds)# Scenario: User A → User B, User B → User A (simultaneous)
# Without ordering:
# Transaction 1: Lock(Wallet A) → Lock(Wallet B) [WAITING]
# Transaction 2: Lock(Wallet B) → Lock(Wallet A) [WAITING]
# Result: DEADLOCK
# Solution: Always lock in ascending ID order
wallet_ids = sorted([sender_wallet_id, receiver_wallet_id])
wallet_1 = db.query(Wallet).filter(id == wallet_ids[0]).with_for_update()
wallet_2 = db.query(Wallet).filter(id == wallet_ids[1]).with_for_update()
# Result: Both transactions lock in same order → No circular waitMIT License - See LICENSE file for details.
Contributions are welcome! Please follow these steps:
- Fork the repository
- Create a feature branch (
git checkout -b feature/YourFeature) - Commit changes (
git commit -m 'Add YourFeature') - Push to branch (
git push origin feature/YourFeature) - Open a Pull Request
Please ensure:
- Migrations are included for schema changes
For questions or support, reach out via:
- Email: alsaeedhasan@beng.bu.edu.eg
- GitHub Issues: Create an issue
Built for financial integrity
★ Star this repo if you found it useful!

