# 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

```sql
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

```sql
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

```sql
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

```sql
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

```sql
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**:
```sql
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`

