https://github.com/bwind/payments-engine
A simple payments engine written in Rust 🦀
https://github.com/bwind/payments-engine
Last synced: 9 days ago
JSON representation
A simple payments engine written in Rust 🦀
- Host: GitHub
- URL: https://github.com/bwind/payments-engine
- Owner: bwind
- Created: 2025-06-26T09:30:40.000Z (11 months ago)
- Default Branch: main
- Last Pushed: 2025-06-26T09:59:37.000Z (11 months ago)
- Last Synced: 2025-06-26T10:46:25.997Z (11 months ago)
- Language: Rust
- Size: 25.4 KB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# Payments Engine 🦀
A simple, streaming payments engine written in Rust. It reads a CSV file of transactions and outputs the final balances per client.
## Usage
Run the engine like this:
```
cargo run -- transactions.csv
```
The engine reads the CSV line by line and prints final balances to stdout.
## Design
The core logic is modeled as a **state machine** for transactions. Each `StoredTransaction` tracks its state via an enum (`Normal`, `Disputed`, `Resolved`, `ChargedBack`), and transitions are enforced via explicit methods like `dispute()`, `resolve()`, and `chargeback()`.
All accounts are stored in memory, indexed by client ID, and updated incrementally as transactions are processed.
## Potential Improvements
With more time, the following improvements could be explored:
* **Command pattern**: Extract transaction logic (`deposit`, `withdrawal`, etc.) into separate commands to improve modularity.
* **Stronger state transitions**: Use types to represent transaction states (e.g. `Deposit`, `DisputedDeposit`, etc.), making invalid transitions unrepresentable at compile time.
* **Memory optimization**: Accounts could be flushed from memory immediately after a `chargeback` if their state is final.
* **Better error reporting**: Include CSV line numbers and raw content in error messages for failed rows.
* **Benchmarking**: Use the `criterion` crate to test performance on large datasets.
* **Concurrency**: Process transactions in parallel, for instance by wrapping Engine in `Arc>` to allow multiple threads to handle transactions concurrently.
* **Total funds calculation**: Use a calculated field for `Account.total` instead of using `update_total()` after every transaction.
* **Money struct instead of Decimal**: Use a custom `Money(u64)` struct with a 10_000 factor for performance and precision, avoiding floating-point arithmetic.
## Testing
This project includes:
* **Unit tests** for transaction state transitions and edge cases.
* **Integration tests** that verify full engine output from real CSV input files (see `tests/data`).
Run all tests with:
```
cargo test
```