Skip to content

zugobite/wallet

Repository files navigation

Wallet Transaction API

A secure, production-ready wallet transaction API with user authentication, two-phase debit authorization, HMAC request signing, and comprehensive admin controls.

Node.js Express Prisma MySQL License: MIT

Features

  • User Registration & Authentication - Complete auth flow with JWT tokens
  • Role-Based Access Control (RBAC) - Customer and Admin roles
  • Customer Wallet APIs - Deposit, withdraw, view balance and transactions
  • Admin Controls - Freeze wallets, reverse transactions, platform oversight
  • Two-Phase Debit Authorization - Authorize → Debit/Reverse pattern for safe fund holds
  • Rate Limiting - Comprehensive rate limiting to protect against abuse
  • Batch Transactions - Atomic processing of multiple transactions
  • Transaction History - Advanced filtering and sorting capabilities
  • Webhook Notifications - Real-time event notifications for transactions
  • Multi-Currency Support - 10 major currencies with automatic conversion
  • HMAC-SHA256 Request Signing - Cryptographic request integrity verification
  • Replay Protection - Nonce-based protection against duplicate requests
  • Idempotent Operations - Safe retry handling with referenceId tracking
  • Precision Math - Financial calculations using monetra v2.3.0 for accuracy
  • Full Audit Trail - Complete ledger with balance snapshots
  • Serverless Ready - AWS Lambda compatible via serverless-http

Table of Contents

Terminology

Understanding the transaction terminology used in this API:

Term Alias Description
Authorize Reserve Places a hold on funds without transferring them. The amount is reserved but still belongs to the wallet.
Debit Capture Completes a previously authorized transaction, actually transferring the reserved funds.
Credit Add Adds funds directly to a wallet balance.
Reverse Release/Undo Cancels a pending authorization, releasing the held funds back to available balance.
Deposit - Customer-initiated credit to their own wallet.
Withdraw - Customer-initiated debit from their own wallet.
Freeze Lock Admin action to prevent all transactions on a wallet.
Unfreeze Unlock Admin action to restore normal wallet operations.

Transaction States

State Description
pending Authorization created, funds reserved but not captured
completed Transaction finalized, funds transferred
reversed Authorization cancelled, funds released

Quick Start

Prerequisites

  • Node.js 20.x or higher
  • MySQL 8.x or MariaDB 10.x
  • Redis 7.x

Installation by OS

macOS

# Install Homebrew if not already installed
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

# Install dependencies
brew install node@20 mysql redis

# Start services
brew services start mysql
brew services start redis

# Clone and setup project
git clone https://github.com/zugobite/wallet.git
cd wallet
npm install
cp .env.example .env
npm run prisma:generate
npm run prisma:migrate
npm run dev

Ubuntu/Debian

# Install Node.js 20.x
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
sudo apt-get install -y nodejs

# Install MySQL
sudo apt-get install -y mysql-server
sudo systemctl start mysql

# Install Redis
sudo apt-get install -y redis-server
sudo systemctl start redis

# Clone and setup project
git clone https://github.com/zugobite/wallet.git
cd wallet
npm install
cp .env.example .env
npm run prisma:generate
npm run prisma:migrate
npm run dev

Windows

# Install Chocolatey if not already installed (run as Administrator)
Set-ExecutionPolicy Bypass -Scope Process -Force
[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072
iex ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1'))

# Install dependencies
choco install nodejs-lts mysql redis-64

# Start services (run as Administrator)
net start mysql
net start redis

# Clone and setup project
git clone https://github.com/zugobite/wallet.git
cd wallet
npm install
copy .env.example .env
npm run prisma:generate
npm run prisma:migrate
npm run dev

Quick Start (All Platforms)

# Clone the repository
git clone https://github.com/zugobite/wallet.git
cd wallet

# Install dependencies
npm install

# Copy environment template
cp .env.example .env
# Edit .env with your configuration

# Generate Prisma client
npm run prisma:generate

# Run database migrations
npm run prisma:migrate

# Start the server
npm run dev

The server will start at http://localhost:3000.

Health Check

curl http://localhost:3000/health

Troubleshooting

Redis Connection Issues

# macOS - Check if Redis is running
brew services list | grep redis

# Start Redis if not running
brew services start redis

# Ubuntu/Debian
sudo systemctl status redis
sudo systemctl start redis

MySQL Connection Issues

# Check MySQL status
# macOS
brew services list | grep mysql

# Ubuntu/Debian
sudo systemctl status mysql

# Verify connection
mysql -u root -p -e "SELECT 1;"

Common Errors

Error Solution
ECONNREFUSED 127.0.0.1:6379 Redis is not running. Start with brew services start redis or sudo systemctl start redis
ECONNREFUSED 127.0.0.1:3306 MySQL is not running. Start with brew services start mysql or sudo systemctl start mysql
P1001: Can't reach database Check DATABASE_URL in .env, ensure MySQL is running
assertNonNegative is not exported Update monetra to v2.1.0: npm install monetra@^2.1.0

Documentation

Interactive API documentation is available via Swagger UI.

Accessing the Docs

Start the server and visit:

http://localhost:3000/api-docs

This provides:

  • Interactive Testing - Execute requests directly from the browser
  • Schema Definitions - detailed models of inputs and outputs
  • Authentication - visual interface for Bearer token authorization

API Endpoints

Public Endpoints

Method Endpoint Description
GET /health Health check (no auth)
GET /health/live Liveness probe (Kubernetes)
GET /health/ready Readiness probe (Kubernetes)
GET /api/v1 API information (no auth)

Authentication Endpoints

Method Endpoint Description
POST /api/v1/auth/register Register new user
POST /api/v1/auth/login Login and get token
GET /api/v1/auth/me Get current user

Customer Wallet Endpoints

Method Endpoint Description
GET /api/v1/wallets/:id Get wallet details
GET /api/v1/wallets/:id/balance Get wallet balance
GET /api/v1/wallets/:id/transactions Get transaction history
POST /api/v1/wallets/:id/deposit Deposit funds
POST /api/v1/wallets/:id/withdraw Withdraw funds

Transaction Endpoints

Method Endpoint Description
POST /api/v1/transactions/authorize Create pending authorization
POST /api/v1/transactions/debit Complete debit transaction
POST /api/v1/transactions/credit Direct credit to wallet
POST /api/v1/transactions/reverse Reverse pending authorization

Admin Endpoints (ADMIN role required)

Method Endpoint Description
GET /api/v1/admin/users List all users
GET /api/v1/admin/wallets List all wallets
GET /api/v1/admin/transactions List all transactions
POST /api/v1/admin/wallets/:id/freeze Freeze a wallet
POST /api/v1/admin/wallets/:id/unfreeze Unfreeze a wallet
POST /api/v1/admin/transactions/:id/reverse Admin reverse transaction

Testing

Unit Tests

Run the Jest unit test suite:

npm test

End-to-End (E2E) Tests

Run the comprehensive cURL-based E2E test suite to verify all flows against a running server:

# 1. Start the server
npm run dev

# 2. Run the test script (in a separate terminal)
./tests/e2e/run_curl_flows.sh

The E2E script tests:

  • User Registration & Login
  • Wallet Details & Balance Checks
  • Deposits & Withdrawals
  • Two-Phase Transactions (Authorize & Debit)
  • Transaction Reversal
  • Transaction History

cURL Examples

Register a New Account

curl -X POST http://localhost:3000/api/v1/auth/register \
  -H "Content-Type: application/json" \
  -d '{
    "email": "demo@example.com",
    "password": "SecurePassword123!"
  }'

Login

curl -X POST http://localhost:3000/api/v1/auth/login \
  -H "Content-Type: application/json" \
  -d '{
    "email": "demo@example.com",
    "password": "SecurePassword123!"
  }'

Check Wallet Balance

curl -X GET "http://localhost:3000/api/v1/wallets/YOUR_WALLET_ID/balance" \
  -H "Authorization: Bearer YOUR_JWT_TOKEN"

Deposit Funds

curl -X POST "http://localhost:3000/api/v1/wallets/YOUR_WALLET_ID/deposit" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_JWT_TOKEN" \
  -d '{
    "amount": 10000,
    "referenceId": "deposit-001"
  }'

Withdraw Funds

curl -X POST "http://localhost:3000/api/v1/wallets/YOUR_WALLET_ID/withdraw" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_JWT_TOKEN" \
  -d '{
    "amount": 2500,
    "referenceId": "withdraw-001"
  }'

View Transaction History

curl -X GET "http://localhost:3000/api/v1/wallets/YOUR_WALLET_ID/transactions" \
  -H "Authorization: Bearer YOUR_JWT_TOKEN"

Complete Customer Flow

# 1. Register
curl -X POST http://localhost:3000/api/v1/auth/register \
  -H "Content-Type: application/json" \
  -d '{"email": "user@example.com", "password": "SecurePass123!"}'

# Save from response:
export TOKEN="your-jwt-token"
export WALLET_ID="your-wallet-id"

# 2. Deposit funds
curl -X POST "http://localhost:3000/api/v1/wallets/$WALLET_ID/deposit" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $TOKEN" \
  -d '{"amount": 10000, "referenceId": "deposit-001"}'

# 3. Check balance
curl -X GET "http://localhost:3000/api/v1/wallets/$WALLET_ID/balance" \
  -H "Authorization: Bearer $TOKEN"

# 4. Withdraw
curl -X POST "http://localhost:3000/api/v1/wallets/$WALLET_ID/withdraw" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $TOKEN" \
  -d '{"amount": 2500, "referenceId": "withdraw-001"}'

# 5. View history
curl -X GET "http://localhost:3000/api/v1/wallets/$WALLET_ID/transactions" \
  -H "Authorization: Bearer $TOKEN"

Admin Operations

# Login as admin
curl -X POST http://localhost:3000/api/v1/auth/login \
  -H "Content-Type: application/json" \
  -d '{"email": "admin@example.com", "password": "AdminPass123!"}'

export ADMIN_TOKEN="admin-jwt-token"

# List all users
curl -X GET "http://localhost:3000/api/v1/admin/users" \
  -H "Authorization: Bearer $ADMIN_TOKEN"

# List all wallets
curl -X GET "http://localhost:3000/api/v1/admin/wallets" \
  -H "Authorization: Bearer $ADMIN_TOKEN"

# Freeze a suspicious wallet
curl -X POST "http://localhost:3000/api/v1/admin/wallets/WALLET_ID/freeze" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $ADMIN_TOKEN" \
  -d '{"reason": "Suspicious activity"}'

# Reverse a fraudulent transaction
curl -X POST "http://localhost:3000/api/v1/admin/transactions/TXN_ID/reverse" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $ADMIN_TOKEN" \
  -d '{"reason": "Customer refund"}'

Authentication

JWT Token

The API uses JWT (JSON Web Token) authentication. Include the token in the Authorization header:

Authorization: Bearer eyJhbGciOiJIUzI1NiIs...

User Roles

Role Description Access
CUSTOMER Regular user Own wallets and transactions only
ADMIN Platform administrator All users, wallets, and transactions

Request Signing (Optional)

For high-security environments, requests can be signed using HMAC-SHA256. See Authentication docs for details.

Transaction Flow

Two-Phase Debit

┌─────────┐     ┌───────────┐     ┌─────────┐
│ Client  │────▶│ Authorize │────▶│ PENDING │
└─────────┘     └───────────┘     └────┬────┘
                                       │
                    ┌──────────────────┴──────────────────┐
                    ▼                                     ▼
              ┌───────────┐                         ┌───────────┐
              │   Debit   │                         │  Reverse  │
              └─────┬─────┘                         └─────┬─────┘
                    ▼                                     ▼
              ┌───────────┐                         ┌───────────┐
              │ COMPLETED │                         │ REVERSED  │
              └───────────┘                         └───────────┘
  1. Authorize - Create a pending hold on funds
  2. Debit - Complete the transaction and deduct funds
  3. Reverse - Cancel the authorization and release hold

Direct Operations

  • Deposit - Credits are applied immediately
  • Withdraw - Debits are applied immediately

Project Structure

wallet/
├── src/
│   ├── app.mjs              # Application entry point
│   ├── routes.mjs           # Route definitions
│   ├── domain/              # Business logic
│   │   ├── wallet.mjs
│   │   └── transactions.mjs
│   ├── handlers/            # Request handlers
│   │   ├── auth/            # Register, login, me
│   │   ├── wallets/         # Wallet operations
│   │   ├── admin/           # Admin operations
│   │   ├── authorize.mjs
│   │   ├── debit.mjs
│   │   ├── credit.mjs
│   │   └── reverse.mjs
│   ├── services/            # Service layer
│   │   ├── auth.service.mjs
│   │   ├── wallet.service.mjs
│   │   └── transaction.service.mjs
│   ├── middleware/          # Express middleware
│   │   ├── auth.mjs
│   │   ├── rbac.mjs         # Role-based access control
│   │   ├── idempotency.mjs
│   │   ├── signature.mjs
│   │   ├── requestLogger.mjs
│   │   └── healthCheck.mjs
│   ├── infra/               # Infrastructure
│   │   ├── prisma.mjs
│   │   ├── redis.mjs
│   │   ├── logger.mjs
│   │   ├── metrics.mjs
│   │   ├── alerting.mjs
│   │   └── repositories/
│   └── utils/
│       └── canonicalJson.mjs
├── prisma/
│   └── schema.prisma        # Database schema
├── tests/                   # Test suite (201 tests)
├── docs/                    # Documentation
└── package.json

Documentation

Comprehensive documentation is available in the /docs directory:

Document Description
001-PROJECT_OVERVIEW.md Architecture and design decisions
002-GETTING_STARTED.md Setup, configuration, and quick start
003-API_REFERENCE.md Complete API docs with cURL examples
004-AUTHENTICATION.md Auth, RBAC, and signing details
005-DATABASE_SCHEMA.md Data model documentation
006-TESTING.md Testing guide
007-DEPLOYMENT.md Deployment instructions
008-MONITORING.md Logging, metrics & alerting
009-SCALING.md Scaling to 100M+ transactions

Testing

# Run all tests (201 tests)
npm test

# Run unit tests only
npm run test:unit

# Run E2E tests
npm run test:e2e

# Run tests in watch mode
npm run test:watch

# Generate coverage report
npm run test:coverage

Test Structure

  • Unit Tests - Domain logic, middleware, services, repositories
  • E2E Tests - Health endpoint, API flow verification

Development

# Start development server
npm run dev

# Lint code
npm run lint

# Format code
npm run format

# Open Prisma Studio (database GUI)
npm run prisma:studio

Environment Variables

Variable Description Required
DATABASE_URL MySQL connection string Yes
DATABASE_ADAPTER_URL MariaDB adapter URL Yes
REDIS_URL Redis connection string Yes
JWT_SECRET JWT signing secret (64+ bytes) Yes
REQUEST_SIGNING_SECRET HMAC signing secret (64+ bytes) Yes
SIGNATURE_TTL_MS Request validity window (ms) Yes
PORT Server port (default: 3000) No

See .env.example for a complete template.

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

Guidelines

  • Follow the existing code style
  • Write tests for new features
  • Update documentation as needed
  • Keep commits atomic and well-described

Disclaimer

This project is created purely for educational and portfolio demonstration purposes to showcase my knowledge of financial transaction systems and software architecture.

Important notices:

  • It implements industry-standard patterns documented in publicly available resources including:
    • Stripe's API design guidelines
    • Martin Fowler's enterprise architecture patterns
    • PCI-DSS compliance frameworks
    • RFC standards (JWT, HMAC, etc.)
  • This is not intended for production use without proper security audits, compliance reviews, and regulatory approvals

License

This project is licensed under the MIT License - see the LICENSE file for details.

About

A RESTful wallet transaction API with two-phase authorization, batch processing, webhooks, multi-currency support, and rate limiting.

Topics

Resources

License

Contributing

Security policy

Stars

Watchers

Forks

Packages

 
 
 

Contributors