This is a command line tool that reads a CSV file containing a series of transactions and generates an accounts balance output file also in CSV.
-
Update client accounts
-
Handle disputes
-
Handle chargebacks
-
Output the state of clients accounts
-
Learn to spell withdrawal (p.s. It’s not withdrawl)
Default run via cargo that creates an accounts.csv
file
cargo run -- transactions.csv > accounts.csv
The default log level is Info. The debug level can be changed by setting the
RUST_LOG
environment variable used by the env_logger
crate.
RUST_LOG=debug cargo run -- transactions.csv
The input is a CSV formatted file similar to the following 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
withdrawal, 2, 5, 3.0
ℹ️
|
ASSUMPTION — There is a header line in the CSV file. |
ℹ️
|
ASSUMPTION — One can dispute a withdrawal which can cause a negative total which would mean that the bank owes the client for funds withdrawn fraudulently. |
-
Deposit
-
Withdrawal
-
Dispute
-
Resolve
-
Chargeback
The output from running the program on a given set of input data is an account balance summary like this.
client, available, held, total, locked
1, 1.5, 0.0, 1.5, false
2, 2.0, 0.0, 2.0, false
The output is also valid CSV, but is written to stdout instead of to a file.
Most errors are silently handled so they don’t stop the processing of the transaction data. Logging is used to note any errors in the transactions file like referencing tx values that haven’t been seen yet. Logging messages all go to stderr so stdio redirected to a file will not get contaminated.
As software is never done, here are some of the things left to do.
-
❏ Move the
Client
into a file to make it a module. -
❏ Find a more concise way to build unit tests. They are currently a jumble. Figuring out how to parameterize unit tests in Rust is a priority.
-
❏ Figure out how to use csv Writer instead of writing CSV output manually. It’s really easy to write it manually at the moment, but would likely get problematic as the program grows
-
❏ Generate or gather more test data input files. I am woefully lacking valid test data. One alternative would be to model the logic in something like Alloy to help find the edge cases that need special care.
-
❏ Figure out how to handle CSV files both with and without header lines.
-
❏
read_csv
works on anything that isimpl io::Read
, so reading from streams of data wouldn’t be too much extra work. -
❏ Converting things to async/await would facilitate multiple concurrent producers of CSV data.