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