A Rust-based financial transactions processing engine that handles deposits, withdrawals, disputes, resolutions, and chargebacks with precise decimal arithmetic.
- Transaction Types: deposit, withdrawal, dispute, resolve, chargeback
- Account Management: Tracks available, held, total balances and locked status
- Precise Arithmetic: Uses rust_decimalfor exact financial calculations (4 decimal places)
- CSV Input/Output: Reads transactions from a CSV file, outputs account balances to stdoutin a CSV format
- Error Handling: Fails completely on invalid CSV file, ignores invalid transactions
cargo run -- <input.csv>The input CSV must have the following columns:
- type: Transaction type (deposit, withdrawal, dispute, resolve, chargeback)
- client: Client ID (u16)
- tx: Transaction ID (u32)
- amount: Transaction amount (only for deposit/withdrawal)
Example:
type,client,tx,amount
deposit,1,1,1.0
deposit,2,2,2.0
deposit,1,3,2.0
withdrawal,1,4,1.5
Outputs account balances with columns:
- client: Client ID
- available: Available balance
- held: Held balance (disputed funds)
- total: Total balance (available + held)
- locked: Account locked status
Example:
client,available,held,total,locked
1,1.5,0,1.5,false
2,2,0,2,false
- Increase available and total balance
- Must have positive amount
- Cannot process if account is locked
- Decrease available and total balance
- Must have sufficient available funds
- Must have positive amount
- Cannot process if account is locked
- Move funds from available to held
- Can only dispute deposit transactions
- Client must match original transaction
- Cannot dispute already disputed transactions
- Cannot process if account is locked
- Move funds from held back to available
- Can only resolve disputed transactions
- Client must match original transaction
- Cannot process if account is locked
- Remove disputed funds from total balance
- Lock the account permanently
- Can only chargeback disputed transactions
- Client must match original transaction
cargo buildcargo test- serde: Serialization/deserialization
- csv: CSV file processing
- rust_decimal: Precise decimal arithmetic for financial calculations
Run with the provided test file:
cargo run -- example.csvYou can generate a file with random transactions using the generate_rand_tx.sh script:
./generate_rand_tx.sh 50 > random.csv
cargo run -- random.csvThe engine fails completely on an invalid CSV file or if a transaction row doesn't have the required information, such as:
- Invalid transaction types
- Missing amounts for deposits/withdrawals
- Amounts provided for dispute-related transactions
- Negative amounts
The engine will ignore correctly formed transactions that are invalid, such as:
- Insufficient funds for withdrawals
- Duplicate transaction IDs (for deposits/withdrawals)
- Operations on locked accounts (except chargebacks)
- Invalid dispute operations (wrong client, non-existent transactions, etc.)
If a dispute is made when the amount available is not enough to cover for the original transaction amount, then we put on hold the maximum available amount possible.
When resolving that transaction, the amount previously held will be credited back to the account (not the original transaction amount).
When charging back that transaction, the amount previously held will be debited from the account. Even if at that point the available amount (or held amount) is enough to cover the original transaction amount, we still only debit the amount that was put on hold at the time of the dispute of the transaction.
See tests/data/dispute_after_withdrawal.csv for an example of such a case.
- main.rs: CLI entry point
- lib.rs: Library interface that will call the engine
- transaction.rs: Transaction type
- account.rs: Account management and balance operations
- engine.rs: Main transaction processing engine
- engine_error.rs: Engine error type