contract ended

This commit is contained in:
Claus Matzinger 2022-05-06 11:34:51 +02:00
parent 52caa8066d
commit 18757ce70f
No known key found for this signature in database
GPG key ID: 7B183BCF2DBEC988
4 changed files with 163 additions and 1 deletions

1
.gitignore vendored Normal file
View file

@ -0,0 +1 @@
/target

8
Cargo.toml Normal file
View file

@ -0,0 +1,8 @@
[package]
name = "accounting-with-fundamental-rust-1"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]

View file

@ -1,2 +1,14 @@
# accounting-with-fundamental-rust-lp-author # Accounting Prototype
This prototype was created for Salmon Finance Inc. A brief summary of the requirements:
- Selecting names for types to represent errors, transactions, and the accounting structure
- Implement a `deposit()` function and a constructor
- Provide function signatures for `withdraw()` and `send()`
- Set up a scenario to run as a binary
Please refer to the [original contract](https://liveproject.manning.com/module/1167_3_1/accounting-with-fundamental-rust) for details.
Made by Trout Consulting
Repository for liveProject: Accounting with Fundamental Rust Repository for liveProject: Accounting with Fundamental Rust

141
src/main.rs Normal file
View file

@ -0,0 +1,141 @@
use std::collections::HashMap;
/// An application-specific error type
#[derive(Debug)]
enum AccountingError {
// Add variants here for account not found, account underfunded and account overfunded
}
/// A transaction type. Transactions should be able to rebuild a ledger's state
/// when they are applied in the same sequence to an empty state.
#[derive(Debug)]
pub enum Tx {
// Add variants for storing withdraw/deposit transactions
}
/// A type for managing accounts and their current currency balance
#[derive(Debug)]
struct Accounts {
// Add a property `accounts` here
}
impl Accounts {
/// Returns an empty instance of the [`Accounts`] type
pub fn new() -> Self {
Accounts {
accounts: Default::default()
}
}
/// Either deposits the `amount` provided into the `signer` account or adds the amount to the existing account.
/// # Errors
/// Attempted overflow
pub fn deposit(&mut self, signer: &str, amount: u64) -> Result<Tx, AccountingError> {
if let Some(account) = self.accounts.get_mut(signer) {
(*account)
.checked_add(amount)
.and_then(|r| {
*account = r;
Some(r)
})
.ok_or(AccountingError::AccountOverFunded(
signer.to_string(),
amount,
))
// Using map() here is an easy way to only manipulate the non-error result
.map(|_| Tx::Deposit {
account: signer.to_string(),
amount,
})
} else {
self.accounts.insert(signer.to_string(), amount);
Ok(Tx::Deposit {
account: signer.to_string(),
amount,
})
}
}
/// Withdraws the `amount` from the `signer` account.
/// # Errors
/// Attempted overflow
pub fn withdraw(&mut self, signer: &str, amount: u64) -> Result<Tx, AccountingError> {
todo!();
}
/// Withdraws the amount from the sender account and deposits it in the recipient account.
///
/// # Errors
/// The account doesn't exist
pub fn send(
&mut self,
sender: &str,
recipient: &str,
amount: u64,
) -> Result<(Tx, Tx), AccountingError> {
todo!();
}
}
fn main() {
println!("Hello, accounting world!");
// We are using simple &str instances as keys
// for more sophisticated keys (e.g. hashes)
// the data type could remain the same
let bob = "bob";
let alice = "alice";
let charlie = "charlie";
let initial_amount = 100;
// Creates the basic ledger and a tx log container
let mut ledger = Accounts::new();
let mut tx_log = vec![];
// Deposit an amount to each account
for signer in &[bob, alice, charlie] {
let status = ledger.deposit(*signer, initial_amount);
println!("Depositing {} for {}: {:?}", signer, initial_amount, status);
// Add the resulting transaction to a list of transactions
// .unwrap() will crash the program if the status is an error.
tx_log.push(status.unwrap());
}
// Send currency from one account (bob) to the other (alice)
let send_amount = 10_u64;
let status = ledger.send(bob, alice, send_amount);
println!(
"Sent {} from {} to {}: {:?}",
send_amount, bob, alice, status
);
// Add both transactions to the transaction log
let (tx1, tx2) = status.unwrap();
tx_log.push(tx1);
tx_log.push(tx2);
// Withdraw everything from the accounts
let tx = ledger.withdraw(charlie, initial_amount).unwrap();
tx_log.push(tx);
let tx = ledger
.withdraw(alice, initial_amount + send_amount)
.unwrap();
tx_log.push(tx);
// Here we are withdrawing too much and there won't be a transaction
println!(
"Withdrawing {} from {}: {:?}",
initial_amount,
bob,
ledger.withdraw(bob, initial_amount)
);
// Withdrawing the expected amount results in a transaction
let tx = ledger.withdraw(bob, initial_amount - send_amount).unwrap();
tx_log.push(tx);
// {:?} prints the Debug implementation, {:#?} pretty-prints it
println!("Ledger empty: {:?}", ledger);
println!("The TX log: {:#?}", tx_log);
}