|
2 | 2 |
|
3 | 3 | ## Project Overview |
4 | 4 |
|
5 | | -LedgerFlow is a blockchain-based payment gateway built on stablecoins (USDC) to provide low-barrier, non-custodial payment solutions. The system uses a **decoupled architecture** where a single smart contract serves as the vault, and multiple off-chain services handle business logic, event monitoring, and user interfaces. |
| 5 | +LedgerFlow is a blockchain-based payment gateway built on stablecoins (USDC) providing low-barrier, non-custodial payment solutions. The system uses a **decoupled architecture** where smart contracts serve as vaults, and multiple off-chain services handle business logic, event monitoring, and user interfaces. |
6 | 6 |
|
7 | 7 | ## Architecture & Service Boundaries |
8 | 8 |
|
9 | 9 | ### Core Components |
10 | | -- **ledgerflow-vault-evm/**: EVM smart contracts (Solidity/Foundry) - single PaymentVault contract that receives all USDC deposits |
| 10 | +- **ledgerflow-vault-evm/**: EVM smart contracts (Solidity/Foundry) - PaymentVault UUPS upgradeable contract for USDC deposits |
11 | 11 | - **ledgerflow-vault-aptos/**: Aptos smart contracts (Move) - alternative blockchain implementation |
12 | 12 | - **ledgerflow-balancer/**: Backend API service (Rust/Axum) - business logic core, order management, account system |
13 | | -- **ledgerflow-indexer/**: Event monitoring service (Rust/Alloy) - listens for DepositReceived events, updates order status |
14 | | -- **ledgerflow-bot/**: Telegram bot frontend (Rust/Teloxide) - user interface for payment requests and notifications |
| 13 | +- **ledgerflow-indexer-evm/**: EVM event monitoring (Rust/Alloy) - listens for DepositReceived events |
| 14 | +- **ledgerflow-indexer-aptos/**: Aptos event monitoring (Rust) - monitors Move-based deposits |
| 15 | +- **ledgerflow-bot/**: Telegram bot frontend (Rust/Teloxide) - user interface for payment requests |
15 | 16 | - **ledgerflow-cli/**: Command-line tools (Rust/Clap) - developer utilities |
16 | | -- **ledgerflow-migrations/**: Database schema management (SQL) - unified PostgreSQL schema for all services |
| 17 | +- **ledgerflow-migrations/**: Database schema management (SQL) - unified PostgreSQL schema |
17 | 18 |
|
18 | | -### Data Flow Pattern |
| 19 | +### Critical Data Flow |
19 | 20 | 1. **Order Creation**: Bot → Balancer API → Database (status: pending) |
20 | | -2. **Payment**: User → PaymentVault contract (with orderId) |
21 | | -3. **Event Detection**: Indexer → DepositReceived event → Database (status: completed) |
| 21 | +2. **Payment**: User → PaymentVault.deposit(orderId) → DepositReceived event |
| 22 | +3. **Event Detection**: Indexer → processes event → Database (status: completed) |
22 | 23 | 4. **Notification**: Indexer → Bot → User notification |
23 | 24 |
|
24 | 25 | ## Critical Implementation Details |
25 | 26 |
|
26 | 27 | ### Order ID Generation Algorithm |
27 | | -All components use the same keccak256-based order ID generation: |
| 28 | +**MUST** be consistent across all components: |
28 | 29 | ```rust |
29 | | -// From ledgerflow-balancer/src/utils.rs |
| 30 | +// From ledgerflow-balancer/src/utils.rs:generate_order_id() |
30 | 31 | order_id = keccak256(abi.encodePacked(broker_id, account_id, order_id_num)) |
31 | 32 | ``` |
32 | | -- This pattern appears in `ledgerflow-balancer/src/utils.rs:generate_order_id()` and must be consistent across all components |
33 | | -- Uses big-endian encoding for numeric values to match Solidity's abi.encodePacked |
34 | | - |
35 | | -### Database Schema Patterns |
36 | | -- Use `VARCHAR(255)` for amounts (arbitrary precision handling, no floating point) |
37 | | -- All timestamps are `TIMESTAMP WITH TIME ZONE` |
38 | | -- Order status uses PostgreSQL ENUM: `pending`, `deposited`, `completed`, `failed`, `cancelled` |
39 | | -- Chain ID support built into all tables for multi-chain deployments |
40 | | -- See `ledgerflow-migrations/migrations/001_initial_schema.sql` for complete schema |
41 | | - |
42 | | -### Error Handling Convention |
43 | | -- Use `eyre::Result` for error propagation in all Rust components |
44 | | -- Custom `AppError` types per service (see `*/src/error.rs`) |
45 | | -- Database errors wrapped with context about the failing operation |
| 33 | +- Uses big-endian encoding (`to_be_bytes()`) to match Solidity's `abi.encodePacked` |
| 34 | +- Pattern appears in balancer utils and must match smart contract expectations |
| 35 | + |
| 36 | +### Database Schema Critical Patterns |
| 37 | +- **Amounts**: Always `VARCHAR(255)` (never floats - arbitrary precision required) |
| 38 | +- **Timestamps**: `TIMESTAMP WITH TIME ZONE` with auto-update triggers |
| 39 | +- **Order Status**: PostgreSQL ENUM: `pending`, `deposited`, `completed`, `failed`, `cancelled` |
| 40 | +- **Multi-chain**: `chain_id BIGINT` field in all relevant tables |
| 41 | +- **Unique constraints**: Composite keys for chain_id + transaction_hash + log_index |
| 42 | + |
| 43 | +### Smart Contract Architecture |
| 44 | +- **UUPS Upgradeable**: Uses OpenZeppelin's UUPS pattern (`UUPSUpgradeable`) |
| 45 | +- **Event Structure**: `DepositReceived(address indexed payer, bytes32 indexed orderId, uint256 amount)` |
| 46 | +- **Both deposit modes**: Standard `approve/transferFrom` and `permit` for better UX |
| 47 | +- **Deterministic deployment**: CREATE2 for consistent addresses across chains |
46 | 48 |
|
47 | 49 | ## Development Workflows |
48 | 50 |
|
49 | | -### Build & Test Commands |
| 51 | +### Build System (Just + Cargo Workspace) |
50 | 52 | ```bash |
51 | | -# Use Just for common tasks (workspace root) |
52 | | -just format # Format all code (cargo fmt + taplo fmt) |
53 | | -just lint # Full linting pipeline with strict rules including clippy::unwrap_used |
54 | | -just test # Run all tests |
| 53 | +# Root workspace commands |
| 54 | +just format # taplo fmt + cargo +nightly fmt --all |
| 55 | +just lint # strict clippy with -D clippy::unwrap_used |
| 56 | +just test # cargo test workspace-wide |
55 | 57 |
|
56 | | -# Per-component builds |
57 | | -cd ledgerflow-{component} && cargo build --release |
| 58 | +# Component-specific |
| 59 | +cd ledgerflow-{component} && make build |
58 | 60 | ``` |
59 | 61 |
|
60 | | -### Database Management |
| 62 | +### Database Management Pattern |
61 | 63 | ```bash |
62 | | -# Migrations run from ledgerflow-migrations/ |
| 64 | +# Run from ledgerflow-migrations/ only |
63 | 65 | cargo run -- migrate |
64 | | - |
65 | | -# Each service needs DATABASE_URL environment variable |
66 | | -# Schema is shared across all services - modify migrations/ carefully |
| 66 | +# All services share same DATABASE_URL - modify schema carefully |
67 | 67 | ``` |
68 | 68 |
|
69 | | -### Smart Contract Deployment |
| 69 | +### Multi-Chain Deployment |
70 | 70 | ```bash |
71 | | -# EVM contracts from ledgerflow-vault-evm/ |
| 71 | +# EVM: Foundry with deterministic deployment |
72 | 72 | forge script script/DeployDeterministic.s.sol --rpc-url $RPC_URL --broadcast |
73 | | -# Uses CREATE2 for deterministic addresses across chains |
74 | 73 |
|
75 | | -# Move contracts from ledgerflow-vault-aptos/ |
76 | | -# See individual README files for Move-specific deployment |
| 74 | +# Configuration supports multiple chains simultaneously |
| 75 | +# Each indexer instance monitors one chain/contract pair |
77 | 76 | ``` |
78 | 77 |
|
79 | 78 | ## Project-Specific Conventions |
80 | 79 |
|
81 | | -### Configuration Management |
82 | | -- All services use YAML config files with `.example` templates |
83 | | -- Config structs use `serde` with `config` crate pattern |
84 | | -- Environment variables override config file values |
85 | | -- Each service has CLI argument for custom config path: `--config` |
| 80 | +### Configuration Pattern |
| 81 | +- YAML files with `.example` templates in each component |
| 82 | +- Config struct + `serde` + `config` crate pattern |
| 83 | +- CLI `--config` argument overrides default `config.yaml` |
| 84 | +- Environment variables override file values |
86 | 85 |
|
87 | | -### Logging & Observability |
88 | | -- Standardized on `tracing` framework across all Rust components |
89 | | -- Structured logging with consistent field names: `order_id`, `account_id`, `chain_id` |
90 | | -- Database operations always logged with context |
91 | | -- Use info!/warn!/error! macros consistently |
| 86 | +### Error Handling Standard |
| 87 | +- `eyre::Result` for all fallible operations |
| 88 | +- Custom `AppError` per service with context wrapping |
| 89 | +- Database operations always wrapped with operation context |
| 90 | + |
| 91 | +### Logging Conventions |
| 92 | +- `tracing` framework with structured fields |
| 93 | +- Standard field names: `order_id`, `account_id`, `chain_id`, `transaction_hash` |
| 94 | +- Log levels: database ops at info, business logic at info, errors at error |
92 | 95 |
|
93 | 96 | ### Multi-Chain Support Pattern |
94 | | -- Chain ID embedded in all data models and database tables (`chain_id` field) |
95 | | -- Indexer runs separate monitoring loops per chain/contract pair |
96 | | -- Configuration supports multiple chain endpoints and contract addresses |
97 | | -- Both EVM and non-EVM (Aptos) chains supported |
98 | | - |
99 | | -### Security Patterns |
100 | | -- Smart contract uses UUPS upgradeable pattern with OpenZeppelin |
101 | | -- Bot manages encrypted private keys for user wallets (custodial model using XOR encryption) |
102 | | -- Balancer validates business rules (max 2 pending orders per account) |
103 | | -- All services validate order ownership before state changes |
104 | | - |
105 | | -## Integration Points |
106 | | - |
107 | | -### API Contracts |
108 | | -- Balancer exposes REST API consumed by Bot: `/orders`, `/accounts`, `/balances` |
109 | | -- Request/response models in `*/src/models.rs` with consistent field naming |
110 | | -- All APIs return JSON with standardized error format |
111 | | - |
112 | | -### Smart Contract Events |
113 | | -```solidity |
114 | | -event DepositReceived(address indexed payer, bytes32 indexed orderId, uint256 amount); |
115 | | -``` |
116 | | -- Indexer processes this event to complete payment flow using keccak256 signature matching |
117 | | -- Event data maps directly to database order records |
118 | | -- Must handle duplicate events (idempotent processing) |
119 | | - |
120 | | -### Database Constraints |
121 | | -- Foreign key relationships: `orders.account_id` → `accounts.id` |
122 | | -- Unique constraints on `order_id`, `telegram_id`, `username` |
123 | | -- Use transactions for multi-table operations (order creation + balance updates) |
124 | | - |
125 | | -## Key Files for Understanding Patterns |
126 | | - |
127 | | -- `ledgerflow-balancer/src/models.rs` - Core data models shared across services |
128 | | -- `ledgerflow-balancer/src/utils.rs` - Order ID generation and encryption utilities |
129 | | -- `ledgerflow-migrations/migrations/001_initial_schema.sql` - Complete database schema |
130 | | -- `ledgerflow-vault-evm/src/PaymentVault.sol` - EVM smart contract interface |
131 | | -- `ledgerflow-indexer/src/indexer.rs` - Event monitoring patterns and multi-chain handling |
132 | | -- `Cargo.toml` (workspace root) - Shared dependency versions and features |
133 | | - |
134 | | -## Testing Approach |
135 | | - |
136 | | -- Unit tests for business logic (order generation, validation) |
137 | | -- Integration tests require PostgreSQL database |
138 | | -- Smart contract tests use Foundry framework in `ledgerflow-vault-evm/test/` |
139 | | -- Bot testing uses mock HTTP clients for Balancer API calls |
140 | | -- Clippy configured to forbid `.unwrap()` usage - use proper error handling |
| 97 | +- `chain_id` embedded in all data models and database tables |
| 98 | +- Indexer config supports array of chain configurations |
| 99 | +- Each chain has separate state tracking (`chain_states` table) |
| 100 | +- Both EVM and Aptos chains use same database schema |
0 commit comments