gmsol_programs/model/
position.rs

1use std::sync::Arc;
2
3use gmsol_model::action::{decrease_position::DecreasePositionSwapType, swap::SwapReport};
4
5use crate::{
6    constants,
7    gmsol_store::{accounts::Position, types::PositionState},
8};
9
10use super::MarketModel;
11
12/// Position Model.
13#[derive(Debug, Clone)]
14pub struct PositionModel {
15    market: MarketModel,
16    position: Arc<Position>,
17    is_long: bool,
18    is_collateral_token_long: bool,
19}
20
21#[repr(u8)]
22enum PositionKind {
23    #[allow(dead_code)]
24    Uninitialized,
25    Long,
26    Short,
27}
28
29impl Position {
30    /// Return whether the side of the position is long.
31    pub fn try_is_long(&self) -> gmsol_model::Result<bool> {
32        if self.kind == PositionKind::Long as u8 {
33            Ok(true)
34        } else if self.kind == PositionKind::Short as u8 {
35            Ok(false)
36        } else {
37            Err(gmsol_model::Error::InvalidPosition(
38                "uninitialized position",
39            ))
40        }
41    }
42}
43
44impl PositionModel {
45    /// Create from [`MarketModel`] and [`Position`].
46    pub fn new(market: MarketModel, position: Arc<Position>) -> gmsol_model::Result<Self> {
47        let is_long = position.try_is_long()?;
48        let is_collateral_token_long = market.meta.token_side(&position.collateral_token)?;
49        Ok(Self {
50            market,
51            position,
52            is_long,
53            is_collateral_token_long,
54        })
55    }
56
57    fn make_position_mut(&mut self) -> &mut Position {
58        Arc::make_mut(&mut self.position)
59    }
60
61    /// Get position.
62    pub fn position(&self) -> &Position {
63        &self.position
64    }
65}
66
67impl gmsol_model::PositionState<{ constants::MARKET_DECIMALS }> for PositionState {
68    type Num = u128;
69
70    type Signed = i128;
71
72    fn collateral_amount(&self) -> &Self::Num {
73        &self.collateral_amount
74    }
75
76    fn size_in_usd(&self) -> &Self::Num {
77        &self.size_in_usd
78    }
79
80    fn size_in_tokens(&self) -> &Self::Num {
81        &self.size_in_tokens
82    }
83
84    fn borrowing_factor(&self) -> &Self::Num {
85        &self.borrowing_factor
86    }
87
88    fn funding_fee_amount_per_size(&self) -> &Self::Num {
89        &self.funding_fee_amount_per_size
90    }
91
92    fn claimable_funding_fee_amount_per_size(&self, is_long_collateral: bool) -> &Self::Num {
93        if is_long_collateral {
94            &self.long_token_claimable_funding_amount_per_size
95        } else {
96            &self.short_token_claimable_funding_amount_per_size
97        }
98    }
99}
100
101impl gmsol_model::PositionState<{ constants::MARKET_DECIMALS }> for PositionModel {
102    type Num = u128;
103
104    type Signed = i128;
105
106    fn collateral_amount(&self) -> &Self::Num {
107        self.position.state.collateral_amount()
108    }
109
110    fn size_in_usd(&self) -> &Self::Num {
111        self.position.state.size_in_usd()
112    }
113
114    fn size_in_tokens(&self) -> &Self::Num {
115        self.position.state.size_in_tokens()
116    }
117
118    fn borrowing_factor(&self) -> &Self::Num {
119        self.position.state.borrowing_factor()
120    }
121
122    fn funding_fee_amount_per_size(&self) -> &Self::Num {
123        self.position.state.funding_fee_amount_per_size()
124    }
125
126    fn claimable_funding_fee_amount_per_size(&self, is_long_collateral: bool) -> &Self::Num {
127        self.position
128            .state
129            .claimable_funding_fee_amount_per_size(is_long_collateral)
130    }
131}
132
133impl gmsol_model::PositionStateMut<{ constants::MARKET_DECIMALS }> for PositionModel {
134    fn collateral_amount_mut(&mut self) -> &mut Self::Num {
135        &mut self.make_position_mut().state.collateral_amount
136    }
137
138    fn size_in_usd_mut(&mut self) -> &mut Self::Num {
139        &mut self.make_position_mut().state.size_in_usd
140    }
141
142    fn size_in_tokens_mut(&mut self) -> &mut Self::Num {
143        &mut self.make_position_mut().state.size_in_tokens
144    }
145
146    fn borrowing_factor_mut(&mut self) -> &mut Self::Num {
147        &mut self.make_position_mut().state.borrowing_factor
148    }
149
150    fn funding_fee_amount_per_size_mut(&mut self) -> &mut Self::Num {
151        &mut self.make_position_mut().state.funding_fee_amount_per_size
152    }
153
154    fn claimable_funding_fee_amount_per_size_mut(
155        &mut self,
156        is_long_collateral: bool,
157    ) -> &mut Self::Num {
158        if is_long_collateral {
159            &mut self
160                .make_position_mut()
161                .state
162                .long_token_claimable_funding_amount_per_size
163        } else {
164            &mut self
165                .make_position_mut()
166                .state
167                .short_token_claimable_funding_amount_per_size
168        }
169    }
170}
171
172impl gmsol_model::Position<{ constants::MARKET_DECIMALS }> for PositionModel {
173    type Market = MarketModel;
174
175    fn market(&self) -> &Self::Market {
176        &self.market
177    }
178
179    fn is_long(&self) -> bool {
180        self.is_long
181    }
182
183    fn is_collateral_token_long(&self) -> bool {
184        self.is_collateral_token_long
185    }
186
187    fn are_pnl_and_collateral_tokens_the_same(&self) -> bool {
188        self.is_long == self.is_collateral_token_long || self.market.is_pure()
189    }
190
191    fn on_validate(&self) -> gmsol_model::Result<()> {
192        Ok(())
193    }
194}
195
196impl gmsol_model::PositionMut<{ constants::MARKET_DECIMALS }> for PositionModel {
197    fn market_mut(&mut self) -> &mut Self::Market {
198        &mut self.market
199    }
200
201    fn on_increased(&mut self) -> gmsol_model::Result<()> {
202        Ok(())
203    }
204
205    fn on_decreased(&mut self) -> gmsol_model::Result<()> {
206        Ok(())
207    }
208
209    fn on_swapped(
210        &mut self,
211        _ty: DecreasePositionSwapType,
212        _report: &SwapReport<Self::Num, <Self::Num as gmsol_model::num::Unsigned>::Signed>,
213    ) -> gmsol_model::Result<()> {
214        Ok(())
215    }
216
217    fn on_swap_error(
218        &mut self,
219        _ty: DecreasePositionSwapType,
220        _error: gmsol_model::Error,
221    ) -> gmsol_model::Result<()> {
222        Ok(())
223    }
224}