Skip to content

Latest commit

 

History

17 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Ledger Vault

A minimal banking-style backend built with Express and Mongoose. This project provides a simple REST API for user authentication, account management, ledger-based balance tracking, and money transfers.

Purpose

This project is designed to demonstrate a basic banking workflow where each financial movement is recorded in an immutable ledger. Instead of storing only a mutable balance field, the application calculates balances from debit and credit entries, making the system more transparent and auditable.

Prerequisites

  • Node.js 18 or newer
  • npm
  • A MongoDB connection string (local MongoDB or MongoDB Atlas)
  • A Gmail account or SMTP-compatible email service for sending emails

Setup

  1. Create a .env file in the project root and set the required environment variables.
  2. Install dependencies:
npm install
  1. Run the server:
npm run dev

You can also start it in production mode with:

npm start

Environment Variables

Create a .env file with the following variables:

PORT=3000
MONGO_URI=mongodb://127.0.0.1:27017/banking-backend
JWT_SECRET=your_secret_key_here
EMAIL_USER=your_email@gmail.com
CLIENT_ID=your_google_client_id
CLIENT_SECRET=your_google_client_secret
REFRESH_TOKEN=your_google_refresh_token

Folder Structure

Important files and folders:

  • server.js - application entry point, connects to MongoDB and starts the server
  • src/app.js - Express app setup and route mounting
  • src/config/db.js - MongoDB connection helper
  • src/routes/auth.routes.js - authentication routes
  • src/routes/account.routes.js - account routes
  • src/routes/transaction.routes.js - transaction routes
  • src/controllers/auth.controllers.js - register, login, and logout logic
  • src/controllers/account.controllers.js - account creation and balance logic
  • src/controllers/transaction.controllers.js - transfer and initial funds transaction logic
  • src/model/user.models.js - user schema and model
  • src/model/account.models.js - account schema and model
  • src/model/transaction.models.js - transaction schema and model
  • src/model/ledger.models.js - ledger schema and model
  • src/middleware/auth.middleware.js - JWT authentication and authorization middleware
  • src/services/email.service.js - email notification service

Features

  • User registration, login, and logout
  • JWT authentication with cookie support
  • Account creation and balance lookup
  • Fund transfer and initial-funds transactions
  • Ledger-based balance tracking
  • Idempotency protection using idempotency keys
  • Email notifications for registration and transactions

API Routes

All routes are mounted under the /api base path.

Route Summary

Method Path Purpose Auth Required
POST /api/auth/register Register a new user No
POST /api/auth/login Login an existing user No
POST /api/auth/logout Logout the current user and blacklist the token Yes
POST /api/accounts/create Create a new bank account for the authenticated user Yes
GET /api/accounts/ Get all accounts belonging to the authenticated user Yes
GET /api/accounts/balance/:accountId Get the balance of a specific account Yes
POST /api/transactions/ Create a money transfer transaction between two accounts Yes
POST /api/transactions/system/initial-funds Create an initial funds transaction for a system user Yes

Authentication Routes

Register a user

  • Method: POST
  • Path: /api/auth/register
  • Body:
{
  "name": "John Doe",
  "email": "john@example.com",
  "password": "123456"
}

Success response:

{
  "user": {
    "_id": "user_id",
    "email": "john@example.com",
    "name": "John Doe"
  },
  "token": "jwt_token",
  "message": "User Created Successfully"
}

Login a user

  • Method: POST
  • Path: /api/auth/login
  • Body:
{
  "email": "john@example.com",
  "password": "123456"
}

Success response:

{
  "user": {
    "_id": "user_id",
    "email": "john@example.com",
    "name": "John Doe"
  },
  "token": "jwt_token",
  "message": "User LoggedIn Successfully"
}

Logout a user

  • Method: POST
  • Path: /api/auth/logout
  • Requires authentication

Account Routes

Create an account

  • Method: POST
  • Path: /api/accounts/create
  • Requires authentication

Get all accounts for the logged-in user

  • Method: GET
  • Path: /api/accounts/
  • Requires authentication

Get account balance

  • Method: GET
  • Path: /api/accounts/balance/:accountId
  • Requires authentication

Transaction Routes

Create a transfer transaction

  • Method: POST
  • Path: /api/transactions/
  • Requires authentication
  • Body:
{
  "fromAccount": "account_id_here",
  "toAccount": "account_id_here",
  "amount": 500,
  "idempotencyKey": "txn-001"
}

Success response:

{
  "status": "success",
  "message": "Transaction completed successfully",
  "transaction": {
    "_id": "transaction_id",
    "status": "COMPLETED"
  }
}

Create initial funds transaction

  • Method: POST
  • Path: /api/transactions/system/initial-funds
  • Body:
{
  "toAccount": "account_id_here",
  "amount": 1000,
  "idempotencyKey": "initial-funds-001"
}

Data Models

  • User: stores login credentials, profile data, and system-user flag
  • Account: links a user to a bank account with status and currency
  • Transaction: stores transfer details and status
  • Ledger: stores immutable debit/credit entries for each transaction
  • TokenBlacklist: stores invalidated JWT tokens after logout

Transaction Flow

The transfer flow works as follows:

  1. Validate the request body.
  2. Check that both accounts exist.
  3. Check whether a transaction already exists for the provided idempotency key.
  4. Validate that both accounts are active.
  5. Calculate the sender balance from the ledger.
  6. Create a transaction in PENDING state.
  7. Create a DEBIT ledger entry for the sender.
  8. Create a CREDIT ledger entry for the receiver.
  9. Mark the transaction as COMPLETED.
  10. Commit the MongoDB session.
  11. Send an email notification.

Error Handling

The API returns JSON errors for invalid input, missing authentication, invalid accounts, insufficient funds, and server issues.

Common status codes:

  • 400 Bad Request: missing or invalid request data
  • 401 Unauthorized: missing or invalid token
  • 403 Forbidden: user is not authorized for the requested action
  • 404 Not Found: account or user not found
  • 422 Unprocessable Entity: duplicate user email
  • 500 Internal Server Error: unexpected server issue

Notes and Troubleshooting

  • Make sure MONGO_URI is valid and includes the correct database name.
  • Ensure the MongoDB server is running before starting the app.
  • Check the terminal logs for MongoDB connection status and server start messages.
  • Use Postman, Insomnia, or curl to test the endpoints.
  • If email sending fails, verify the Gmail OAuth2 credentials in the environment variables.

Releases

Packages

Contributors

Languages