use crate::config_handler::Config;
use safe_nd::{AppPermissions, Coins, Error, PublicKey};
use serde::{Deserialize, Serialize};
use std::collections::{BTreeMap, VecDeque};
pub const DEFAULT_MAX_CREDITS: usize = 100;
#[derive(Deserialize, Serialize)]
pub struct CoinBalance {
owner: PublicKey,
value: Coins,
credits: VecDeque<Credit>,
}
impl CoinBalance {
pub fn new(value: Coins, owner: PublicKey) -> Self {
Self {
owner,
value,
credits: VecDeque::new(),
}
}
pub fn credit_balance(&mut self, amount: Coins, transaction_id: u64) -> Result<(), Error> {
if let Some(new_balance) = self.value.checked_add(amount) {
self.value = new_balance;
self.add_transaction(amount, transaction_id);
Ok(())
} else {
Err(Error::ExcessiveValue)
}
}
pub fn debit_balance(&mut self, amount: Coins) -> Result<(), Error> {
if let Some(new_balance) = self.value.checked_sub(amount) {
self.value = new_balance;
Ok(())
} else {
Err(Error::InsufficientBalance)
}
}
pub fn balance(&self) -> Coins {
self.value
}
fn add_transaction(&mut self, amount: Coins, transaction_id: u64) {
if self.credits.len() == DEFAULT_MAX_CREDITS {
let _ = self.credits.pop_back();
}
let credit = Credit {
amount,
transaction_id,
};
self.credits.push_front(credit);
}
}
#[derive(Deserialize, Serialize)]
pub struct Credit {
amount: Coins,
transaction_id: u64, }
#[derive(Deserialize, Serialize)]
pub struct Account {
auth_keys: BTreeMap<PublicKey, AppPermissions>,
version: u64,
config: Config,
}
impl Account {
pub fn new(config: Config) -> Self {
Account {
auth_keys: Default::default(),
version: 0,
config,
}
}
pub fn version(&self) -> u64 {
self.version
}
pub fn ins_auth_key(
&mut self,
key: PublicKey,
permissions: AppPermissions,
version: u64,
) -> Result<(), Error> {
self.validate_version(version)?;
let _ = self.auth_keys.insert(key, permissions);
self.version = version;
Ok(())
}
pub fn del_auth_key(&mut self, key: &PublicKey, version: u64) -> Result<(), Error> {
self.validate_version(version)?;
if self.auth_keys.remove(key).is_some() {
self.version = version;
Ok(())
} else {
Err(Error::NoSuchKey)
}
}
pub fn auth_keys(&self) -> &BTreeMap<PublicKey, AppPermissions> {
&self.auth_keys
}
fn validate_version(&self, version: u64) -> Result<(), Error> {
if version == self.version + 1 {
Ok(())
} else {
Err(Error::InvalidSuccessor(self.version))
}
}
}