gmsol_model/pool/
balance.rs1use crate::num::{Num, Unsigned};
2use num_traits::CheckedMul;
3
4use super::PoolDelta;
5
6pub trait Balance {
8 type Num: Num + Unsigned<Signed = Self::Signed>;
10
11 type Signed;
13
14 fn long_amount(&self) -> crate::Result<Self::Num>;
16
17 fn short_amount(&self) -> crate::Result<Self::Num>;
19}
20
21pub trait BalanceExt: Balance {
23 fn long_usd_value(&self, price: &Self::Num) -> crate::Result<Self::Num> {
25 self.long_amount()?
26 .checked_mul(price)
27 .ok_or(crate::Error::Overflow)
28 }
29
30 fn short_usd_value(&self, price: &Self::Num) -> crate::Result<Self::Num> {
32 self.short_amount()?
33 .checked_mul(price)
34 .ok_or(crate::Error::Overflow)
35 }
36
37 fn pool_delta_with_amounts(
39 &self,
40 long_token_delta_amount: &Self::Signed,
41 short_token_delta_amount: &Self::Signed,
42 long_token_price: &Self::Num,
43 short_token_price: &Self::Num,
44 ) -> crate::Result<PoolDelta<Self::Num>> {
45 PoolDelta::try_from_delta_amounts(
46 self,
47 long_token_delta_amount,
48 short_token_delta_amount,
49 long_token_price,
50 short_token_price,
51 )
52 }
53
54 fn pool_delta_with_values(
56 &self,
57 delta_long_token_usd_value: Self::Signed,
58 delta_short_token_usd_value: Self::Signed,
59 long_token_price: &Self::Num,
60 short_token_price: &Self::Num,
61 ) -> crate::Result<PoolDelta<Self::Num>> {
62 PoolDelta::try_new(
63 self,
64 delta_long_token_usd_value,
65 delta_short_token_usd_value,
66 long_token_price,
67 short_token_price,
68 )
69 }
70
71 fn merge<B: Balance>(&self, short: B) -> Merged<&Self, B> {
76 Merged(self, short)
77 }
78
79 #[inline]
81 fn amount(&self, is_long: bool) -> crate::Result<Self::Num> {
82 if is_long {
83 self.long_amount()
84 } else {
85 self.short_amount()
86 }
87 }
88}
89
90impl<P: Balance + ?Sized> BalanceExt for P {}
91
92impl<P: Balance> Balance for &P {
93 type Num = P::Num;
94
95 type Signed = P::Signed;
96
97 fn long_amount(&self) -> crate::Result<Self::Num> {
98 (**self).long_amount()
99 }
100
101 fn short_amount(&self) -> crate::Result<Self::Num> {
102 (**self).short_amount()
103 }
104}
105
106#[derive(Debug, Clone, Copy)]
109pub struct Merged<A, B>(A, B);
110
111impl<A, B, Num, Signed> Balance for Merged<A, B>
112where
113 Num: crate::num::Num + Unsigned<Signed = Signed>,
114 A: Balance<Num = Num, Signed = Signed>,
115 B: Balance<Num = Num, Signed = Signed>,
116{
117 type Num = Num;
118
119 type Signed = Signed;
120
121 fn long_amount(&self) -> crate::Result<Self::Num> {
122 self.0
123 .long_amount()?
124 .checked_add(&self.0.short_amount()?)
125 .ok_or(crate::Error::Overflow)
126 }
127
128 fn short_amount(&self) -> crate::Result<Self::Num> {
129 self.1
130 .long_amount()?
131 .checked_add(&self.1.short_amount()?)
132 .ok_or(crate::Error::Overflow)
133 }
134}
135
136#[cfg(test)]
137mod tests {
138 use super::*;
139 use crate::{test::TestPool, Pool};
140
141 #[test]
142 fn test_merge_balances() -> crate::Result<()> {
143 let mut open_interest_for_long = TestPool::<u64>::default();
144 let mut open_interest_for_short = TestPool::<u64>::default();
145
146 open_interest_for_long.apply_delta_to_long_amount(&1000)?;
147 open_interest_for_long.apply_delta_to_short_amount(&2000)?;
148 open_interest_for_short.apply_delta_to_long_amount(&3000)?;
149 open_interest_for_short.apply_delta_to_short_amount(&4000)?;
150
151 let open_interest = open_interest_for_long.merge(&open_interest_for_short);
152
153 assert_eq!(open_interest.long_amount()?, 3000);
154 assert_eq!(open_interest.short_amount()?, 7000);
155
156 Ok(())
157 }
158}