gmsol_model/action/
update_borrowing_state.rs

1use crate::{
2    market::{BaseMarket, BorrowingFeeMarketExt, BorrowingFeeMarketMut},
3    num::Unsigned,
4    price::Prices,
5    PoolExt,
6};
7
8use super::MarketAction;
9
10/// Update Borrowing State Action.
11#[must_use = "actions do nothing unless you `execute` them"]
12pub struct UpdateBorrowingState<M: BaseMarket<DECIMALS>, const DECIMALS: u8> {
13    market: M,
14    prices: Prices<M::Num>,
15}
16
17impl<M: BorrowingFeeMarketMut<DECIMALS>, const DECIMALS: u8> UpdateBorrowingState<M, DECIMALS> {
18    /// Create a new [`UpdateBorrowingState`] action.
19    pub fn try_new(market: M, prices: &Prices<M::Num>) -> crate::Result<Self> {
20        prices.validate()?;
21        Ok(Self {
22            market,
23            prices: prices.clone(),
24        })
25    }
26
27    fn execute_one_side(
28        &mut self,
29        is_long: bool,
30        duration_in_seconds: u64,
31    ) -> crate::Result<M::Num> {
32        let (next_cumulative_borrowing_factor, delta) = self
33            .market
34            .next_cumulative_borrowing_factor(is_long, &self.prices, duration_in_seconds)?;
35        self.market
36            .borrowing_factor_pool_mut()?
37            .apply_delta_amount(is_long, &delta.to_signed()?)?;
38        Ok(next_cumulative_borrowing_factor)
39    }
40}
41
42impl<M: BorrowingFeeMarketMut<DECIMALS>, const DECIMALS: u8> MarketAction
43    for UpdateBorrowingState<M, DECIMALS>
44{
45    type Report = UpdateBorrowingReport<M::Num>;
46
47    fn execute(mut self) -> crate::Result<Self::Report> {
48        let duration_in_seconds = self.market.just_passed_in_seconds_for_borrowing()?;
49        let next_cumulative_borrowing_factor_for_long =
50            self.execute_one_side(true, duration_in_seconds)?;
51        let next_cumulative_borrowing_factor_for_short =
52            self.execute_one_side(false, duration_in_seconds)?;
53        Ok(UpdateBorrowingReport {
54            duration_in_seconds,
55            next_cumulative_borrowing_factor_for_long,
56            next_cumulative_borrowing_factor_for_short,
57        })
58    }
59}
60
61/// Update Borrowing Report.
62#[derive(Debug)]
63#[cfg_attr(
64    feature = "anchor-lang",
65    derive(anchor_lang::AnchorDeserialize, anchor_lang::AnchorSerialize)
66)]
67pub struct UpdateBorrowingReport<T> {
68    duration_in_seconds: u64,
69    next_cumulative_borrowing_factor_for_long: T,
70    next_cumulative_borrowing_factor_for_short: T,
71}
72
73#[cfg(feature = "gmsol-utils")]
74impl<T: gmsol_utils::InitSpace> gmsol_utils::InitSpace for UpdateBorrowingReport<T> {
75    const INIT_SPACE: usize = u64::INIT_SPACE + 2 * T::INIT_SPACE;
76}
77
78impl<T> UpdateBorrowingReport<T> {
79    /// Get considered duration in seconds.
80    pub fn duration_in_seconds(&self) -> u64 {
81        self.duration_in_seconds
82    }
83
84    /// Get next cumulative borrowing factor
85    pub fn next_cumulative_borrowing_factor(&self, is_long: bool) -> &T {
86        if is_long {
87            &self.next_cumulative_borrowing_factor_for_long
88        } else {
89            &self.next_cumulative_borrowing_factor_for_short
90        }
91    }
92}
93
94#[cfg(test)]
95mod tests {
96    use std::{thread::sleep, time::Duration};
97
98    use crate::{
99        market::LiquidityMarketMutExt,
100        test::{TestMarket, TestPosition},
101        MarketAction, PositionMutExt,
102    };
103
104    use super::*;
105
106    #[test]
107    fn test_update_borrowing_state() -> crate::Result<()> {
108        let mut market = TestMarket::<u64, 9>::default();
109        let prices = Prices::new_for_test(120, 120, 1);
110        market
111            .deposit(1_000_000_000_000, 100_000_000_000_000, prices)?
112            .execute()?;
113        println!("{market:#?}");
114        let mut position = TestPosition::long(true);
115        let prices = Prices::new_for_test(123, 123, 1);
116        let report = position
117            .ops(&mut market)
118            .increase(prices, 1_000_000_000_000, 50_000_000_000_000, None)?
119            .execute()?;
120        println!("{report:#?}");
121        println!("{market:#?}");
122        sleep(Duration::from_secs(2));
123        let report = position
124            .ops(&mut market)
125            .decrease(prices, 50_000_000_000_000, None, 0, Default::default())?
126            .execute()?;
127        println!("{report:#?}");
128        println!("{market:#?}");
129        Ok(())
130    }
131}