gmsol_programs/model/
position.rs1use 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#[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 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 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 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}