From a00567cadc7223a07cbd654f2a9509fa4b1d26d7 Mon Sep 17 00:00:00 2001 From: Bruno BELANYI Date: Tue, 23 Aug 2022 13:42:57 +0200 Subject: [PATCH] ledger: introduce 'Ledger' type Unfortunately, rust-csv does not support serializing maps [1], so instead of trying to write a `Deserialize` impl, the `dump_csv` method takes care of formatting the output as expected. [1]: https://github.com/BurntSushi/rust-csv/issues/98 --- src/ledger.rs | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 3 +++ 2 files changed, 65 insertions(+) create mode 100644 src/ledger.rs diff --git a/src/ledger.rs b/src/ledger.rs new file mode 100644 index 0000000..b7d0d2c --- /dev/null +++ b/src/ledger.rs @@ -0,0 +1,62 @@ +//! A ledger implementation to track all transactions. + +use crate::{ClientId, TxAmount, TxId}; + +/// A ledger of accounts, which processes transactions one at a time. +#[derive(Clone, Debug, Default, PartialEq, Eq)] +pub struct Ledger { + accounts: std::collections::HashMap, + reversible_transactions: std::collections::HashMap, +} + +#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord)] +pub struct AccountInfo { + available_funds: TxAmount, + held_funds: TxAmount, + locked: bool, +} + +impl Ledger { + pub fn new() -> Self { + Default::default() + } + + /// Serialize a [Ledger] to CSV. + pub fn dump_csv(&self, writer: &mut csv::Writer) -> csv::Result<()> { + // Keep list of accounts ordered for easier diffs + let ordered_accounts: std::collections::BTreeMap<_, _> = self.accounts.iter().collect(); + writer.write_record(&["client", "available", "held", "total", "locked"])?; + for (id, info) in ordered_accounts.into_iter() { + writer.write_record(&[ + id.0.to_string(), + info.available_funds().0.to_string(), + info.held_funds().0.to_string(), + info.total_funds().0.to_string(), + info.is_locked().to_string(), + ])? + } + Ok(()) + } +} + +impl AccountInfo { + /// Whether or not an account has been locked. + pub fn is_locked(&self) -> bool { + self.locked + } + + /// The funds that are usable on this account. + pub fn available_funds(&self) -> TxAmount { + self.available_funds + } + + /// The funds that have been locked pending resolution of dispute. + pub fn held_funds(&self) -> TxAmount { + self.held_funds + } + + /// The totals funds on an account, i.e: available funds and held funds. + pub fn total_funds(&self) -> TxAmount { + self.available_funds + self.held_funds + } +} diff --git a/src/lib.rs b/src/lib.rs index f5d3a10..d51fe77 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -4,5 +4,8 @@ pub use crate::core::*; pub mod error; pub use crate::error::*; +pub mod ledger; +pub use crate::ledger::*; + pub mod transaction; pub use crate::transaction::*;