use std::collections::HashMap; use serde::{Serialize, Deserialize}; use rust_util::XResult; use crate::tx::Transaction; #[derive(Debug, Serialize, Deserialize)] pub struct CreditContract { pub name: String, pub credit_limit: u32, pub issue_amount: u32, pub admin: String, pub credit: HashMap, } impl CreditContract { pub fn new(tx: &Transaction, name: &str, credit_limit: u32) -> XResult { let c = Self { name: name.into(), credit_limit, issue_amount: 0, admin: tx.sender.clone(), credit: HashMap::new(), }; Ok(c) } pub fn issue(&mut self, tx: &Transaction, receiver: &str, credit: u32) -> XResult<()> { if &self.admin != &tx.sender { return simple_error!("Current user is not admin, {} vs {:?}", self.admin, tx.sender); } if credit == 0 { return simple_error!("Cannot issue 0 credit!"); } if self.issue_amount + credit > self.credit_limit { return simple_error!( "Issue too much credit, current: {}, issue: {}, limit: {}, left: {}", self.issue_amount, credit, self.credit_limit, self.credit_limit - self.issue_amount ); } match self.credit.get_mut(receiver) { None => { self.credit.insert(receiver.to_owned(), credit); }, Some(cr) => *cr += credit, } self.issue_amount += credit; Ok(()) } pub fn transfer(&mut self, tx: &Transaction, receiver: &str, credit: u32) -> XResult<()> { if credit == 0 { return simple_error!("Cannot transfer 0 credit!"); } match self.credit.get_mut(&tx.sender) { None => return simple_error!("Have not enough credit: {:?}", tx.sender), Some(cr) => { if *cr >= credit { *cr -= credit; match self.credit.get_mut(receiver) { None => { self.credit.insert(receiver.to_owned(), credit); }, Some(receiver_credit) => *receiver_credit += credit, } } else { return simple_error!("Have not enough credit: {:?}", tx.sender); } }, } Ok(()) } pub fn query(&self, _tx: &Transaction, account: &str) -> u32 { match self.credit.get(account) { None => 0, Some(receiver_credit) => *receiver_credit, } } pub fn query_all(&self, _tx: &Transaction) -> &HashMap { &self.credit } }