use barter_integration::model::instrument::symbol::Symbol;
use serde::{Deserialize, Serialize};
#[derive(Clone, PartialEq, PartialOrd, Debug, Deserialize, Serialize)]
pub struct SymbolBalance {
pub symbol: Symbol,
pub balance: Balance,
}
impl SymbolBalance {
pub fn new<S>(symbol: S, balance: Balance) -> Self
where
S: Into<Symbol>,
{
Self {
symbol: symbol.into(),
balance,
}
}
}
#[derive(Copy, Clone, PartialEq, PartialOrd, Debug, Deserialize, Serialize)]
pub struct Balance {
pub total: f64,
pub available: f64,
}
impl Balance {
pub fn new(total: f64, available: f64) -> Self {
Self { total, available }
}
pub fn used(&self) -> f64 {
self.total - self.available
}
pub fn apply(&mut self, delta: BalanceDelta) {
self.total += delta.total;
self.available += delta.available;
}
}
#[derive(Copy, Clone, PartialEq, PartialOrd, Debug, Deserialize, Serialize)]
pub struct BalanceDelta {
pub total: f64,
pub available: f64,
}
impl BalanceDelta {
pub fn new(total: f64, available: f64) -> Self {
Self { total, available }
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_balance_used() {
let balance = Balance::new(10.0, 10.0);
assert_eq!(balance.used(), 0.0);
let balance = Balance::new(10.0, 0.0);
assert_eq!(balance.used(), balance.total);
let balance = Balance::new(10.0, 5.0);
assert_eq!(balance.used(), balance.available);
}
#[test]
fn test_balance_apply_balance_delta() {
struct TestCase {
balance: Balance,
input_delta: BalanceDelta,
expected: Balance,
}
let tests = vec![
TestCase {
balance: Balance::new(10.0, 0.0),
input_delta: BalanceDelta::new(-10.0, 0.0),
expected: Balance::new(0.0, 0.0),
},
TestCase {
balance: Balance::new(10.0, 10.0),
input_delta: BalanceDelta::new(0.0, -10.0),
expected: Balance::new(10.0, 0.0),
},
TestCase {
balance: Balance::new(10.0, 10.0),
input_delta: BalanceDelta::new(0.0, 10.0),
expected: Balance::new(10.0, 20.0),
},
TestCase {
balance: Balance::new(10.0, 10.0),
input_delta: BalanceDelta::new(0.0, 10.0),
expected: Balance::new(10.0, 20.0),
},
TestCase {
balance: Balance::new(10.0, 10.0),
input_delta: BalanceDelta::new(10.0, 10.0),
expected: Balance::new(20.0, 20.0),
},
TestCase {
balance: Balance::new(10.0, 10.0),
input_delta: BalanceDelta::new(-10.0, -10.0),
expected: Balance::new(0.0, 0.0),
},
];
for (index, mut test) in tests.into_iter().enumerate() {
test.balance.apply(test.input_delta);
assert_eq!(test.balance, test.expected, "TC{} failed", index);
}
}
}