gmsol_model/action/decrease_position/
report.rs1use std::fmt;
2
3#[cfg(feature = "anchor-lang")]
4use anchor_lang::Space;
5
6use crate::{num::Unsigned, params::fee::PositionFees, position::InsolventCloseStep};
7
8use super::{ClaimableCollateral, DecreasePositionParams, ProcessCollateralResult};
9
10#[must_use = "
12 `output_amount`, `secondary_output_amount`, `should_remove`, `withdrawable_collateral_amount`,
13 `claimable_funding_amounts`, `claimable_collateral_for_holding` and `claimable_collateral_for_user`
14 must be used
15"]
16#[derive(Clone)]
17#[cfg_attr(
18 feature = "anchor-lang",
19 derive(anchor_lang::AnchorDeserialize, anchor_lang::AnchorSerialize)
20)]
21pub struct DecreasePositionReport<Unsigned, Signed> {
22 price_impact_value: Signed,
23 price_impact_diff: Unsigned,
24 execution_price: Unsigned,
25 size_delta_in_tokens: Unsigned,
26 withdrawable_collateral_amount: Unsigned,
27 initial_size_delta_usd: Unsigned,
28 size_delta_usd: Unsigned,
29 fees: PositionFees<Unsigned>,
30 pnl: Pnl<Signed>,
31 insolvent_close_step: Option<InsolventCloseStep>,
32 should_remove: bool,
34 is_output_token_long: bool,
35 is_secondary_output_token_long: bool,
36 output_amounts: OutputAmounts<Unsigned>,
37 claimable_funding_long_token_amount: Unsigned,
38 claimable_funding_short_token_amount: Unsigned,
39 for_holding: ClaimableCollateral<Unsigned>,
40 for_user: ClaimableCollateral<Unsigned>,
41}
42
43#[cfg(feature = "gmsol-utils")]
44impl<Unsigned, Signed> gmsol_utils::InitSpace for DecreasePositionReport<Unsigned, Signed>
45where
46 Unsigned: gmsol_utils::InitSpace,
47 Signed: gmsol_utils::InitSpace,
48{
49 const INIT_SPACE: usize = Signed::INIT_SPACE
50 + 6 * Unsigned::INIT_SPACE
51 + PositionFees::<Unsigned>::INIT_SPACE
52 + Pnl::<Signed>::INIT_SPACE
53 + 1
54 + InsolventCloseStep::INIT_SPACE
55 + 3 * bool::INIT_SPACE
56 + OutputAmounts::<Unsigned>::INIT_SPACE
57 + 2 * Unsigned::INIT_SPACE
58 + 2 * ClaimableCollateral::<Unsigned>::INIT_SPACE;
59}
60
61impl<T: Unsigned + fmt::Debug> fmt::Debug for DecreasePositionReport<T, T::Signed>
62where
63 T::Signed: fmt::Debug,
64{
65 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
66 f.debug_struct("DecreasePositionReport")
67 .field("price_impact_value", &self.price_impact_value)
68 .field("price_impact_diff", &self.price_impact_diff)
69 .field("execution_price", &self.execution_price)
70 .field("size_delta_in_tokens", &self.size_delta_in_tokens)
71 .field(
72 "withdrawable_collateral_amount",
73 &self.withdrawable_collateral_amount,
74 )
75 .field("initial_size_delta_usd", &self.initial_size_delta_usd)
76 .field("size_delta_usd", &self.size_delta_usd)
77 .field("fees", &self.fees)
78 .field("pnl", &self.pnl)
79 .field("insolvent_close_step", &self.insolvent_close_step)
80 .field("should_remove", &self.should_remove)
81 .field("is_output_token_long", &self.is_output_token_long)
82 .field(
83 "is_secondary_output_token_long",
84 &self.is_secondary_output_token_long,
85 )
86 .field("output_amounts", &self.output_amounts)
87 .field(
88 "claimable_funding_long_token_amount",
89 &self.claimable_funding_long_token_amount,
90 )
91 .field(
92 "claimable_funding_short_token_amount",
93 &self.claimable_funding_short_token_amount,
94 )
95 .field("for_holding", &self.for_holding)
96 .field("for_user", &self.for_user)
97 .finish()
98 }
99}
100
101impl<T: Unsigned + Clone> DecreasePositionReport<T, T::Signed> {
102 pub(super) fn new(
103 params: &DecreasePositionParams<T>,
104 execution: ProcessCollateralResult<T>,
105 withdrawable_collateral_amount: T,
106 size_delta_usd: T,
107 should_remove: bool,
108 ) -> Self {
109 let claimable_funding_long_token_amount = execution
110 .fees
111 .funding_fees()
112 .claimable_long_token_amount()
113 .clone();
114 let claimable_funding_short_token_amount = execution
115 .fees
116 .funding_fees()
117 .claimable_short_token_amount()
118 .clone();
119 Self {
120 price_impact_value: execution.price_impact_value,
121 price_impact_diff: execution.price_impact_diff,
122 execution_price: execution.execution_price,
123 size_delta_in_tokens: execution.size_delta_in_tokens,
124 withdrawable_collateral_amount,
125 initial_size_delta_usd: params.initial_size_delta_usd.clone(),
126 size_delta_usd,
127 fees: execution.fees,
128 pnl: execution.pnl,
129 insolvent_close_step: execution.collateral.insolvent_close_step,
130 should_remove,
132 is_output_token_long: execution.is_output_token_long,
133 is_secondary_output_token_long: execution.is_secondary_output_token_long,
134 output_amounts: OutputAmounts {
135 output_amount: execution.collateral.output_amount,
136 secondary_output_amount: execution.collateral.secondary_output_amount,
137 },
138 claimable_funding_long_token_amount,
139 claimable_funding_short_token_amount,
140 for_holding: execution.collateral.for_holding,
141 for_user: execution.collateral.for_user,
142 }
143 }
144
145 pub fn size_delta_in_tokens(&self) -> &T {
147 &self.size_delta_in_tokens
148 }
149
150 pub fn initial_size_delta_usd(&self) -> &T {
152 &self.initial_size_delta_usd
153 }
154
155 pub fn size_delta_usd(&self) -> &T {
157 &self.size_delta_usd
158 }
159
160 pub fn execution_price(&self) -> &T {
162 &self.execution_price
163 }
164
165 pub fn price_impact_value(&self) -> &T::Signed {
167 &self.price_impact_value
168 }
169
170 pub fn price_impact_diff(&self) -> &T {
172 &self.price_impact_diff
173 }
174
175 pub fn fees(&self) -> &PositionFees<T> {
177 &self.fees
178 }
179
180 pub fn is_output_token_long(&self) -> bool {
182 self.is_output_token_long
183 }
184
185 pub fn is_secondary_output_token_long(&self) -> bool {
187 self.is_secondary_output_token_long
188 }
189
190 #[must_use = "the returned amount of output tokens should be transferred out from the market vault"]
192 pub fn output_amount(&self) -> &T {
193 &self.output_amounts.output_amount
194 }
195
196 #[must_use = "the returned amount of secondary output tokens should be transferred out from the market vault"]
198 pub fn secondary_output_amount(&self) -> &T {
199 &self.output_amounts.secondary_output_amount
200 }
201
202 pub fn output_amounts(&self) -> &OutputAmounts<T> {
204 &self.output_amounts
205 }
206
207 pub(super) fn output_amounts_mut(&mut self) -> (&mut T, &mut T) {
208 (
209 &mut self.output_amounts.output_amount,
210 &mut self.output_amounts.secondary_output_amount,
211 )
212 }
213
214 #[must_use = "The position should be removed if `true` is returned"]
216 pub fn should_remove(&self) -> bool {
217 self.should_remove
218 }
219
220 #[must_use = "the returned amount of collateral tokens should be transferred out from the market vault"]
222 pub fn withdrawable_collateral_amount(&self) -> &T {
223 &self.withdrawable_collateral_amount
224 }
225
226 #[must_use = "the returned amounts of tokens should be transferred out from the market vault"]
228 pub fn claimable_funding_amounts(&self) -> (&T, &T) {
229 (
230 &self.claimable_funding_long_token_amount,
231 &self.claimable_funding_short_token_amount,
232 )
233 }
234
235 #[must_use = "the returned amount of tokens should be transferred out from the market vault"]
237 pub fn claimable_collateral_for_holding(&self) -> &ClaimableCollateral<T> {
238 &self.for_holding
239 }
240
241 #[must_use = "the returned amount of tokens should be transferred out from the market vault"]
243 pub fn claimable_collateral_for_user(&self) -> &ClaimableCollateral<T> {
244 &self.for_user
245 }
246
247 pub fn pnl(&self) -> &Pnl<T::Signed> {
249 &self.pnl
250 }
251
252 pub fn insolvent_close_step(&self) -> Option<InsolventCloseStep> {
254 self.insolvent_close_step
255 }
256}
257
258#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
260#[cfg_attr(
261 feature = "anchor-lang",
262 derive(anchor_lang::AnchorDeserialize, anchor_lang::AnchorSerialize)
263)]
264#[derive(Debug, Clone, Copy, Default)]
265pub struct Pnl<T> {
266 pnl: T,
268 uncapped_pnl: T,
270}
271
272#[cfg(feature = "gmsol-utils")]
273impl<T: gmsol_utils::InitSpace> gmsol_utils::InitSpace for Pnl<T> {
274 const INIT_SPACE: usize = 2 * T::INIT_SPACE;
275}
276
277impl<T> Pnl<T> {
278 pub fn new(pnl: T, uncapped_pnl: T) -> Self {
280 Self { pnl, uncapped_pnl }
281 }
282
283 pub fn pnl(&self) -> &T {
285 &self.pnl
286 }
287
288 pub fn uncapped_pnl(&self) -> &T {
290 &self.uncapped_pnl
291 }
292}
293
294#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
296#[cfg_attr(
297 feature = "anchor-lang",
298 derive(anchor_lang::AnchorDeserialize, anchor_lang::AnchorSerialize)
299)]
300#[derive(Debug, Clone, Copy, Default)]
301pub struct OutputAmounts<T> {
302 pub(super) output_amount: T,
303 pub(super) secondary_output_amount: T,
304}
305
306#[cfg(feature = "gmsol-utils")]
307impl<T: gmsol_utils::InitSpace> gmsol_utils::InitSpace for OutputAmounts<T> {
308 const INIT_SPACE: usize = 2 * T::INIT_SPACE;
309}
310
311impl<T> OutputAmounts<T> {
312 pub fn output_amount(&self) -> &T {
314 &self.output_amount
315 }
316
317 pub fn secondary_output_amount(&self) -> &T {
319 &self.secondary_output_amount
320 }
321}