Files
explorer-monorepo/docs/specs/banking/account-ledger.md

4.4 KiB

Account & Ledger Specification

Overview

This document specifies the customer ledger system using double-entry bookkeeping principles for banking operations.

Double-Entry Ledger Schema

Ledger Entry

CREATE TABLE ledger_entries (
    id UUID PRIMARY KEY,
    customer_id UUID NOT NULL,
    transaction_id UUID NOT NULL,
    entry_type VARCHAR(20) NOT NULL, -- 'debit', 'credit'
    account_type VARCHAR(50) NOT NULL, -- 'cash', 'crypto', 'fiat', etc.
    amount NUMERIC(78, 0) NOT NULL,
    currency VARCHAR(10) NOT NULL,
    description TEXT,
    reference_id VARCHAR(255), -- External transaction reference
    created_at TIMESTAMP DEFAULT NOW(),
    FOREIGN KEY (customer_id) REFERENCES customers(id),
    FOREIGN KEY (transaction_id) REFERENCES transactions(id)
);

Transaction Table

CREATE TABLE transactions (
    id UUID PRIMARY KEY,
    customer_id UUID NOT NULL,
    transaction_type VARCHAR(50) NOT NULL, -- 'deposit', 'withdrawal', 'transfer', etc.
    status VARCHAR(20) NOT NULL, -- 'pending', 'completed', 'failed'
    amount NUMERIC(78, 0) NOT NULL,
    currency VARCHAR(10) NOT NULL,
    from_account UUID,
    to_account UUID,
    blockchain_tx_hash VARCHAR(66), -- If blockchain transaction
    created_at TIMESTAMP DEFAULT NOW(),
    completed_at TIMESTAMP,
    FOREIGN KEY (customer_id) REFERENCES customers(id)
);

Double-Entry Rule

Constraint: Sum of debits = Sum of credits for each transaction

Implementation: Two entries per transaction (debit and credit)

Wallet Mapping

Customer-Wallet Mapping

CREATE TABLE customer_wallets (
    id UUID PRIMARY KEY,
    customer_id UUID NOT NULL,
    chain_id INTEGER NOT NULL,
    address VARCHAR(42) NOT NULL,
    wallet_type VARCHAR(20) NOT NULL, -- 'external', 'custodial'
    verified BOOLEAN DEFAULT false,
    verified_at TIMESTAMP,
    created_at TIMESTAMP DEFAULT NOW(),
    UNIQUE (customer_id, chain_id, address),
    FOREIGN KEY (customer_id) REFERENCES customers(id)
);

Wallet Verification

Process:

  1. Customer provides address
  2. Request signature verification
  3. Verify signature matches address
  4. Link address to customer account
  5. Mark as verified

Reconciliation Jobs

Reconciliation Process

Purpose: Ensure ledger matches actual blockchain/custodial balances

Frequency: Daily or real-time (depending on account type)

Steps:

  1. Query actual balances (blockchain or custodial wallet)
  2. Calculate expected balance from ledger
  3. Compare and identify discrepancies
  4. Create reconciliation entries if needed
  5. Alert on discrepancies

Reconciliation Schema

CREATE TABLE reconciliations (
    id UUID PRIMARY KEY,
    customer_id UUID NOT NULL,
    account_type VARCHAR(50) NOT NULL,
    currency VARCHAR(10) NOT NULL,
    expected_balance NUMERIC(78, 0) NOT NULL,
    actual_balance NUMERIC(78, 0) NOT NULL,
    discrepancy NUMERIC(78, 0) NOT NULL,
    status VARCHAR(20) NOT NULL, -- 'matched', 'discrepancy', 'resolved'
    reconciled_at TIMESTAMP DEFAULT NOW(),
    resolved_at TIMESTAMP,
    FOREIGN KEY (customer_id) REFERENCES customers(id)
);

Audit Trails

Audit Log Schema

CREATE TABLE audit_logs (
    id UUID PRIMARY KEY,
    customer_id UUID,
    action VARCHAR(100) NOT NULL,
    resource_type VARCHAR(50) NOT NULL,
    resource_id VARCHAR(255),
    old_value JSONB,
    new_value JSONB,
    actor_id UUID NOT NULL, -- User/system that performed action
    ip_address VARCHAR(45),
    user_agent TEXT,
    created_at TIMESTAMP DEFAULT NOW()
);

Immutable Log Storage

Storage: Append-only log (immutable) Retention: Per regulatory requirements (typically 7 years) Access: Audit team only Integrity: Cryptographic hashing for tamper detection

Balance Calculations

Account Balance

Formula: Sum of credits - Sum of debits for account

Implementation:

SELECT 
    SUM(CASE WHEN entry_type = 'credit' THEN amount ELSE 0 END) -
    SUM(CASE WHEN entry_type = 'debit' THEN amount ELSE 0 END) AS balance
FROM ledger_entries
WHERE customer_id = ? AND account_type = ? AND currency = ?;

Real-Time Balance

Caching: Cache balances with TTL Updates: Invalidate on new ledger entries Accuracy: Reconcile with actual balances periodically

References

  • Identity & Compliance: See identity-compliance.md
  • Payment Rails: See payment-rails.md
  • Database Schema: See ../database/postgres-schema.md