Phoenix Wallet

Ledger

Immutable transaction record using double-entry accounting

The ledger is the immutable record of all financial transactions in Phoenix Wallet. Built on double-entry accounting principles, it provides a complete audit trail and ensures that every operation is traceable and balanced.

Double-Entry Accounting

Every transaction in Phoenix Wallet creates balanced ledger entries. For every debit, there's a corresponding credit, ensuring the books always balance:

Transaction: User deposits $100

┌─────────────────────────────────────────────────────────────┐
│                      Ledger Entries                         │
├─────────────────────────────────────────────────────────────┤
│  Entry #1: DEBIT   System Liability Account    $100.00     │
│  Entry #2: CREDIT  User Wallet (lot_abc)       $100.00     │
├─────────────────────────────────────────────────────────────┤
│  Balance: $0.00 (debits = credits)              ✓          │
└─────────────────────────────────────────────────────────────┘

This ensures:

  • Accuracy - Mathematical verification that all transactions balance
  • Auditability - Complete trail of every fund movement
  • Integrity - No funds can be created or destroyed accidentally

Entry Structure

FieldTypeDescription
idstringUnique entry identifier
transaction_idstringParent transaction grouping
wallet_idstringAffected wallet
lot_idstringAffected lot (if applicable)
asset_codestringAsset type
amountstringEntry amount (always positive)
directionenumCREDIT or DEBIT
entry_typeenumType of entry (see below)
balance_afterstringLot balance after this entry
metadataobjectCustom key-value pairs
created_attimestampEntry timestamp

Entry Types

TypeDescriptionEffect on Wallet
CREDITFunds added to lotIncreases available balance
DEBITFunds removed from lotDecreases available balance
RESERVEFunds moved to reservedDecreases available, increases reserved
RELEASEReserved funds returnedIncreases available, decreases reserved
COMMITReserved funds finalizedDecreases reserved, removes from wallet
EXPIRELot expirationDecreases available (funds forfeited)

Transaction Examples

Simple Credit (Deposit)

{
  "transaction_id": "txn_01HV8X9Y2KPQRS3T4UV5WX6YZ7",
  "entries": [
    {
      "id": "ent_01HV8X9Y2KPQRS3T4UV5WX6YZ7",
      "wallet_id": "wal_01HV8X9Y2KPQRS3T4UV5WX6YZ7",
      "lot_id": "lot_01HV8X9Y2KPQRS3T4UV5WX6YZ7",
      "asset_code": "USD",
      "amount": "10000",
      "direction": "CREDIT",
      "entry_type": "CREDIT",
      "balance_after": "10000",
      "metadata": {
        "source": "bank_transfer",
        "reference": "dep_12345"
      },
      "created_at": "2024-01-15T10:30:00Z"
    }
  ]
}

Reservation Flow

Creating a reservation generates a RESERVE entry:

{
  "transaction_id": "txn_02HV8X9Y2KPQRS3T4UV5WX6YZ8",
  "entries": [
    {
      "id": "ent_02HV8X9Y2KPQRS3T4UV5WX6YZ8",
      "wallet_id": "wal_01HV8X9Y2KPQRS3T4UV5WX6YZ7",
      "lot_id": "lot_01HV8X9Y2KPQRS3T4UV5WX6YZ7",
      "asset_code": "USD",
      "amount": "2500",
      "direction": "DEBIT",
      "entry_type": "RESERVE",
      "balance_after": "7500",
      "metadata": {
        "reservation_id": "rsv_01HV8X9Y2KPQRS3T4UV5WX6YZ7",
        "intent": "purchase"
      },
      "created_at": "2024-01-15T11:00:00Z"
    }
  ]
}

Committing the reservation generates a COMMIT entry:

{
  "transaction_id": "txn_03HV8X9Y2KPQRS3T4UV5WX6YZ9",
  "entries": [
    {
      "id": "ent_03HV8X9Y2KPQRS3T4UV5WX6YZ9",
      "wallet_id": "wal_01HV8X9Y2KPQRS3T4UV5WX6YZ7",
      "lot_id": "lot_01HV8X9Y2KPQRS3T4UV5WX6YZ7",
      "asset_code": "USD",
      "amount": "2500",
      "direction": "DEBIT",
      "entry_type": "COMMIT",
      "balance_after": "7500",
      "metadata": {
        "reservation_id": "rsv_01HV8X9Y2KPQRS3T4UV5WX6YZ7",
        "order_id": "ord_12345"
      },
      "created_at": "2024-01-15T12:00:00Z"
    }
  ]
}

Wallet-to-Wallet Transfer

Transfers create paired entries across two wallets:

{
  "transaction_id": "txn_04HV8X9Y2KPQRS3T4UV5WX6YZA",
  "entries": [
    {
      "id": "ent_04HV8X9Y2KPQRS3T4UV5WX6YZA",
      "wallet_id": "wal_sender",
      "lot_id": "lot_sender_01",
      "asset_code": "USD",
      "amount": "5000",
      "direction": "DEBIT",
      "entry_type": "DEBIT",
      "balance_after": "2500",
      "metadata": {
        "transfer_to": "wal_recipient",
        "reason": "P2P transfer"
      }
    },
    {
      "id": "ent_05HV8X9Y2KPQRS3T4UV5WX6YZB",
      "wallet_id": "wal_recipient",
      "lot_id": "lot_recipient_01",
      "asset_code": "USD",
      "amount": "5000",
      "direction": "CREDIT",
      "entry_type": "CREDIT",
      "balance_after": "5000",
      "metadata": {
        "transfer_from": "wal_sender",
        "reason": "P2P transfer"
      }
    }
  ]
}

Immutability

Ledger entries are immutable. Once created, they cannot be modified or deleted. This is fundamental to maintaining audit integrity.

To correct errors, you must create new compensating entries:

Original (incorrect):  CREDIT $100 to user
Correction:           DEBIT $100 from user (reversal)
                      CREDIT $75 to user (correct amount)

This approach ensures:

  • Complete audit trail of all changes
  • Regulatory compliance
  • Forensic analysis capability

Querying the Ledger

Get Transaction History for a Wallet

curl "https://api.phoenixwallet.io/v1/wallets/wal_01HV8X.../ledger" \
  -H "Authorization: Bearer $API_KEY"

Filter by Date Range

curl "https://api.phoenixwallet.io/v1/wallets/wal_01HV8X.../ledger?from=2024-01-01&to=2024-01-31" \
  -H "Authorization: Bearer $API_KEY"

Filter by Entry Type

curl "https://api.phoenixwallet.io/v1/wallets/wal_01HV8X.../ledger?entry_type=CREDIT" \
  -H "Authorization: Bearer $API_KEY"

Get Specific Transaction

curl "https://api.phoenixwallet.io/v1/transactions/txn_01HV8X..." \
  -H "Authorization: Bearer $API_KEY"

Ledger Response Example

{
  "data": [
    {
      "id": "ent_01HV8X9Y2KPQRS3T4UV5WX6YZ7",
      "transaction_id": "txn_01HV8X9Y2KPQRS3T4UV5WX6YZ7",
      "wallet_id": "wal_01HV8X9Y2KPQRS3T4UV5WX6YZ7",
      "lot_id": "lot_01HV8X9Y2KPQRS3T4UV5WX6YZ7",
      "asset_code": "USD",
      "amount": "10000",
      "direction": "CREDIT",
      "entry_type": "CREDIT",
      "balance_after": "10000",
      "metadata": {
        "source": "deposit"
      },
      "created_at": "2024-01-15T10:30:00Z"
    }
  ],
  "pagination": {
    "has_more": true,
    "next_cursor": "cur_abc123"
  }
}

Balance Reconciliation

You can verify wallet balances by summing ledger entries:

Wallet Balance = SUM(CREDIT entries) - SUM(DEBIT entries)

This provides an independent verification mechanism for balance accuracy.

  • Wallets - Balances derived from ledger entries
  • Lots - Individual lot balances tracked in ledger
  • Reservations - Reserve/release/commit entries
  • Multi-Tenancy - Ledger isolation per tenant