Skip to content

A robust, scalable backend for a multi-currency FX trading application built with NestJS, TypeORM, and PostgreSQL.

Notifications You must be signed in to change notification settings

ChuloWay/fx_trading_platform

Repository files navigation

FX Trading Assessment API

A robust, scalable backend for a multi-currency FX trading application built with NestJS, TypeORM, and PostgreSQL.

Features

  • User Management: Registration, Login, and Email Verification (OTP).
  • Multi-Currency Wallet: Support for NGN, USD, EUR, GBP, and more.
  • Real-Time FX Rates: Integration with external exchange rate providers (with Redis caching).
  • Trading Engine: Secure currency conversion and trading with slippage protection via time-limited quotes.
  • Transaction History: Comprehensive audit trail of all financial activities.
  • Admin Dashboard: Dedicated module for administrators to view users and transactions.
  • Security: JWT Authentication, Role-Based Access Control (RBAC), and Idempotency.

Tech Stack

  • Framework: NestJS (Node.js)
  • Database: PostgreSQL (via TypeORM)
  • Caching: Redis
  • Testing: Jest (Unit & E2E)
  • Documentation: Swagger (OpenAPI)

Architecture & Design Decisions

1. Modular Architecture

The application is structured into feature-based modules (Auth, User, Wallet, Exchange, Transaction) to ensure separation of concerns and maintainability.

2. Double-Entry Ledger System

To prevent data inconsistency and ensure auditability, all wallet balance changes are recorded in a ledger_entries table.

  • Every financial action (credit/debit) creates a Transaction record and a corresponding LedgerEntry.
  • Wallet balances are calculated/verified by aggregating ledger entries (or updating a snapshot).
  • Pessimistic Locking: SELECT ... FOR UPDATE is used during fund transfers to prevent race conditions and double-spending.

3. Concurrency & Safety

  • Atomic Transactions: All financial operations obey ACID properties using QueryRunner transactions.
  • Idempotency: Critical endpoints (like POST /wallet/trade) support an Idempotency-Key header to safely retry requests without duplicating trades.

4. FX Rate Handling

  • Rates are fetched from an external provider (ExchangeRate-API or similar).
  • Caching: Rates are cached in Redis for 60 seconds to reduce external API calls and improve latency.
  • Quotes: Trades require a 2-step process (Get Quote -> Execute Trade) to lock in a rate for a short window (e.g., 60s), protecting users from price slippage.

System Design

1. High-Level Architecture

Overview of the system's modular structure and external integrations.

High-Level Architecture

2. Trade Execution Flow (Low-Level)

Sequence diagram of the Double-Entry Ledger trade execution with Pessimistic Locking.

Low-Level Trade Execution


API Documentation

Once the application is running, full interactive API documentation is available at: http://localhost:5001/api/v1/docs

Key Endpoints

Module Method Endpoint Description
Auth POST /auth/register Register new user (sends OTP)
POST /auth/login Login and get JWT
POST /auth/verify Verify email with OTP
Wallet GET /wallet Get all currency balances
POST /wallet/fund Fund wallet (e.g., in NGN)
POST /wallet/trade Execute a trade using a quote
FX GET /fx/rates Get live exchange rates
GET /fx/quote Get a guaranteed rate quote
History GET /transactions View transaction history
Admin POST /admin/login Admin login
GET /admin/users (Admin) List all users
GET /admin/transactions (Admin) List all transactions

Setup & Installation

Prerequisites

  • Node.js (v18+)
  • PostgreSQL
  • Redis

1. Clone the repository

git clone https://github.com/ChuloWay/fx_trading_platform`
cd fx_trading_platform

2. Install dependencies

npm install

3. Environment Configuration

Create a .env file in the root directory:

# Server
PORT=5001
NODE_ENV=development

# Database
DATABASE_HOST=localhost
DATABASE_PORT=5432
DATABASE_USERNAME=postgres
DATABASE_PASSWORD=postgres
DATABASE_NAME=fx_trading

# Redis
REDIS_HOST=localhost
REDIS_PORT=6379

# JWT
JWT_SECRET=your_super_secret_key
JWT_EXPIRATION=1d

# Admin Seeding
ADMIN_EMAIL=admin@fxapp.com
ADMIN_PASSWORD=Admin@123

# FX Provider
FX_RATE_API_KEY=your_api_key_here

4. Run the application

# Development
npm run start:dev

# Production
npm run start:prod

5. Run Tests

# Unit tests
npm run test

# E2E tests
npm run test:e2e

Testing Strategy

  • Unit Tests: Cover individual services (AuthService, WalletService, ExchangeService) using mocks.
  • E2E Tests: Validate the entire request flow from Controller to Database using a test database.
    • User flows: Register -> Verify -> Login -> Fund -> Trade.
    • Error handling: Invalid inputs, unauthorized access, insufficient funds.

Assumptions

  1. Base Currency: The system treats NGN as the primary funding currency for this assessment, but the architecture supports any base currency.
  2. Email Delivery: For development, emails are logged to the console (ConsoleEmailProvider). In production, this can be switched to GmailSmtpEmailProvider via env vars.
  3. Authentication: Users must verify their email before they can login or trade.
  4. Transaction Limits: No specific limits (min/max) were enforced for this MVP, but logic exists to prevent negative balances.

Bonus Features Implemented

  • Redis Caching: Implemented for FX rates.
  • Idempotency: Guarded against duplicate trade requests.
  • Role-Based Access: Infrastructure for Admin vs. User roles (RolesGuard).
  • Swagger Docs: Auto-generated API documentation.

About

A robust, scalable backend for a multi-currency FX trading application built with NestJS, TypeORM, and PostgreSQL.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages