contract ended
This commit is contained in:
parent
52caa8066d
commit
18757ce70f
4 changed files with 163 additions and 1 deletions
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
/target
|
8
Cargo.toml
Normal file
8
Cargo.toml
Normal 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]
|
14
README.md
14
README.md
|
@ -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
141
src/main.rs
Normal 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);
|
||||||
|
}
|
Loading…
Reference in a new issue