gmsol_model/action/
update_borrowing_state.rs1use crate::{
2 market::{BaseMarket, BorrowingFeeMarketExt, BorrowingFeeMarketMut},
3 num::Unsigned,
4 price::Prices,
5 PoolExt,
6};
7
8use super::MarketAction;
9
10#[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 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#[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 pub fn duration_in_seconds(&self) -> u64 {
81 self.duration_in_seconds
82 }
83
84 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}