Ledger-DB Service
Система операционного учета и двойной записи
Ledger-DB Service (В разработке)
Статус: В активной разработке (Sprint 1). Проектируется как проекция DLT-данных для быстрого доступа.
Ledger-DB — это критический компонент платформы, отвечающий за операционный учет денежных средств и ЦФА. Он реализует модель двойной записи (Double-Entry Bookkeeping).
Архитектура учета
Система учета построена на следующих сущностях:
- Account: Глобальный счет пользователя или системы.
- SubAccount: Субсчет для конкретного актива (RUB, CFA-EQ, и т.д.).
- Operation: Группировка проводок, представляющая собой одну бизнес-операцию (например, "Торговля").
- Posting: Атомарная запись о движении средств между двумя субсчетами.
- Hold: Временная блокировка средств (например, под открытый ордер).
Технологический стек
- Фреймворк: NestJS
- База данных: PostgreSQL
- ORM: Drizzle ORM
- Связь: gRPC (для синхронных проверок) + Kafka (для асинхронного обновления).
Принципы работы
- Атомарность: Все проводки внутри одной
Operationвыполняются в одной транзакции БД. - Неизменяемость: Существующие проводки нельзя удалять или изменять. Для исправления ошибок используются сторнирующие (reversing) записи.
- Double Contour: Ledger-DB является проекцией данных из DLT (Besu), но также хранит промежуточные состояния (Hold), которых нет в блокчейне.
Модель данных (Entity-Relationship)
Loading diagram...
Модель данных (Protobuf)
message Account {
string account_id = 1;
string user_id = 2;
AccountType type = 3; // MAIN / INVEST / BLOCKED
}
message SubAccount {
string subaccount_id = 1;
string account_id = 2;
string instrument_id = 3; // CFA-RUB / CFA-EQ-001 / ...
Decimal balance = 4;
SubAccountStatus status = 5;
}
message Operation {
string operation_id = 1;
OperationType type = 2;
OperationStatus status = 3;
string user_id = 4;
string idempotency_key = 5;
string external_ref = 6;
string onchain_tx_hash = 7;
}
message Posting {
string posting_id = 1;
string operation_id = 2;
string debit_subaccount_id = 3;
string credit_subaccount_id = 4;
MonetaryAmount amount = 5;
}
message Hold {
string hold_id = 1;
string subaccount_id = 2;
MonetaryAmount amount = 3;
HoldStatus status = 4; // ACTIVE / RELEASED / CONSUMED / EXPIRED
string reason = 5;
}Пример проводок
Пополнение (Deposit):
Debit: System.Reserve.CFA-RUB +1000
Credit: User123.Main.CFA-RUB +1000Покупка инвест-ЦФА:
Debit: User123.Main.CFA-RUB -5000
Credit: System.Reserve.CFA-RUB +5000
Debit: System.Reserve.CFA-EQ-001 -10 shares
Credit: User123.Invest.CFA-EQ-001 +10 shares