use crate::balance::MarginDetails;
use chrono::{DateTime, Utc};
use derive_more::Constructor;
use serde::{Deserialize, Serialize};
use smol_str::SmolStr;
use std::fmt::{Display, Formatter};
#[non_exhaustive]
#[derive(Debug, Clone, PartialEq, Eq, Hash, Deserialize, Serialize, Constructor)]
pub struct MarginDebtUpdate<AssetKey, InstrumentKey> {
pub asset: AssetKey,
pub instrument: Option<InstrumentKey>,
pub debt: MarginDetails,
pub kind: MarginDebtKind,
pub venue_kind: SmolStr,
pub time_exchange: DateTime<Utc>,
}
#[non_exhaustive]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Deserialize, Serialize)]
pub enum MarginDebtKind {
Borrow,
Repay,
Interest,
Other,
}
impl Display for MarginDebtKind {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.write_str(match self {
Self::Borrow => "borrow",
Self::Repay => "repay",
Self::Interest => "interest",
Self::Other => "other",
})
}
}
#[cfg(test)]
#[allow(clippy::unwrap_used)] mod tests {
use super::*;
use chrono::TimeZone;
use rust_decimal_macros::dec;
#[test]
fn an_update_round_trips_through_serde() {
let update = MarginDebtUpdate::new(
SmolStr::new("BTC"),
Some(SmolStr::new("BTCUSDT")),
MarginDetails {
borrowed: dec!(0.00006),
interest: dec!(0.00000002),
},
MarginDebtKind::Interest,
SmolStr::new("INTEREST"),
Utc.timestamp_millis_opt(1_700_000_000_000).unwrap(),
);
let json = serde_json::to_string(&update).unwrap();
assert_eq!(
serde_json::from_str::<MarginDebtUpdate<SmolStr, SmolStr>>(&json).unwrap(),
update
);
}
#[test]
fn a_kind_displays_as_its_lowercase_name() {
let names = [
MarginDebtKind::Borrow,
MarginDebtKind::Repay,
MarginDebtKind::Interest,
MarginDebtKind::Other,
]
.map(|kind| kind.to_string());
assert_eq!(names, ["borrow", "repay", "interest", "other"]);
}
}