gmsol_model/params/
fee.rs

1use num_traits::{CheckedAdd, CheckedSub, Zero};
2use typed_builder::TypedBuilder;
3
4use crate::{fixed::FixedPointOps, num::Unsigned, pool::delta::BalanceChange, price::Price, utils};
5
6/// Fee Parameters.
7#[derive(Debug, Clone, Copy, TypedBuilder)]
8pub struct FeeParams<T> {
9    positive_impact_fee_factor: T,
10    negative_impact_fee_factor: T,
11    fee_receiver_factor: T,
12    #[builder(default = None, setter(strip_option))]
13    discount_factor: Option<T>,
14}
15
16impl<T> FeeParams<T> {
17    /// Set discount factor.
18    pub fn with_discount_factor(self, factor: T) -> Self {
19        Self {
20            discount_factor: Some(factor),
21            ..self
22        }
23    }
24
25    /// Get receiver factor.
26    pub fn receiver_factor(&self) -> &T {
27        &self.fee_receiver_factor
28    }
29
30    #[inline]
31    fn factor(&self, balance_change: BalanceChange) -> &T {
32        match balance_change {
33            BalanceChange::Improved => &self.positive_impact_fee_factor,
34            BalanceChange::Unchanged | BalanceChange::Worsened => &self.negative_impact_fee_factor,
35        }
36    }
37
38    fn discount_factor(&self) -> T
39    where
40        T: Zero + Clone,
41    {
42        self.discount_factor
43            .as_ref()
44            .cloned()
45            .unwrap_or(Zero::zero())
46    }
47
48    /// Get basic fee.
49    #[inline]
50    pub fn fee<const DECIMALS: u8>(&self, balance_change: BalanceChange, amount: &T) -> Option<T>
51    where
52        T: FixedPointOps<DECIMALS>,
53    {
54        let factor = self.factor(balance_change);
55        let fee = utils::apply_factor(amount, factor)?;
56        let discount = utils::apply_factor(&fee, &self.discount_factor())?;
57        fee.checked_sub(&discount)
58    }
59
60    /// Get receiver fee.
61    #[inline]
62    pub fn receiver_fee<const DECIMALS: u8>(&self, fee_amount: &T) -> Option<T>
63    where
64        T: FixedPointOps<DECIMALS>,
65    {
66        utils::apply_factor(fee_amount, &self.fee_receiver_factor)
67    }
68
69    /// Apply fees to `amount`.
70    /// - `DECIMALS` is the decimals of the parameters.
71    ///
72    /// Returns `None` if the computation fails, otherwise `amount` after fees and the fees are returned.
73    pub fn apply_fees<const DECIMALS: u8>(
74        &self,
75        balance_change: BalanceChange,
76        amount: &T,
77    ) -> Option<(T, Fees<T>)>
78    where
79        T: FixedPointOps<DECIMALS>,
80    {
81        let fee_amount = self.fee(balance_change, amount)?;
82        let fee_receiver_amount = self.receiver_fee(&fee_amount)?;
83        let fees = Fees {
84            fee_amount_for_pool: fee_amount.checked_sub(&fee_receiver_amount)?,
85            fee_amount_for_receiver: fee_receiver_amount,
86        };
87        Some((amount.checked_sub(&fee_amount)?, fees))
88    }
89
90    /// Get order fees.
91    fn order_fees<const DECIMALS: u8>(
92        &self,
93        collateral_token_price: &Price<T>,
94        size_delta_usd: &T,
95        balance_change: BalanceChange,
96    ) -> crate::Result<OrderFees<T>>
97    where
98        T: FixedPointOps<DECIMALS>,
99    {
100        if collateral_token_price.has_zero() {
101            return Err(crate::Error::InvalidPrices);
102        }
103
104        let fee_value = self
105            .fee(balance_change, size_delta_usd)
106            .ok_or(crate::Error::Computation("calculating order fee value"))?;
107        let fee_amount = fee_value
108            .checked_div(collateral_token_price.pick_price(false))
109            .ok_or(crate::Error::Computation("calculating order fee amount"))?;
110
111        let receiver_fee_amount = self
112            .receiver_fee(&fee_amount)
113            .ok_or(crate::Error::Computation("calculating order receiver fee"))?;
114        Ok(OrderFees {
115            base: Fees::new(
116                fee_amount
117                    .checked_sub(&receiver_fee_amount)
118                    .ok_or(crate::Error::Computation("calculating order fee for pool"))?,
119                receiver_fee_amount,
120            ),
121            fee_value,
122        })
123    }
124
125    /// Get position fees with only order fees considered.
126    pub fn base_position_fees<const DECIMALS: u8>(
127        &self,
128        collateral_token_price: &Price<T>,
129        size_delta_usd: &T,
130        balance_change: BalanceChange,
131    ) -> crate::Result<PositionFees<T>>
132    where
133        T: FixedPointOps<DECIMALS>,
134    {
135        let order_fees = self.order_fees(collateral_token_price, size_delta_usd, balance_change)?;
136        Ok(PositionFees {
137            paid_order_and_borrowing_fee_value: order_fees.fee_value.clone(),
138            order: order_fees,
139            borrowing: Default::default(),
140            funding: Default::default(),
141            liquidation: Default::default(),
142        })
143    }
144}
145
146/// Borrowing Fee Parameters.
147#[derive(Debug, Clone, Copy, TypedBuilder)]
148pub struct BorrowingFeeParams<T> {
149    receiver_factor: T,
150    exponent_for_long: T,
151    exponent_for_short: T,
152    factor_for_long: T,
153    factor_for_short: T,
154    #[builder(default = true)]
155    skip_borrowing_fee_for_smaller_side: bool,
156}
157
158impl<T> BorrowingFeeParams<T> {
159    /// Get borrowing exponent factor.
160    pub fn exponent(&self, is_long: bool) -> &T {
161        if is_long {
162            &self.exponent_for_long
163        } else {
164            &self.exponent_for_short
165        }
166    }
167
168    /// Get borrowing factor.
169    pub fn factor(&self, is_long: bool) -> &T {
170        if is_long {
171            &self.factor_for_long
172        } else {
173            &self.factor_for_short
174        }
175    }
176
177    /// Get whether to skip borrowing fee for smaller side.
178    pub fn skip_borrowing_fee_for_smaller_side(&self) -> bool {
179        self.skip_borrowing_fee_for_smaller_side
180    }
181
182    /// Get borrowing fee receiver factor.
183    pub fn receiver_factor(&self) -> &T {
184        &self.receiver_factor
185    }
186}
187
188/// Borrowing Fee Kink Model Parameters.
189#[derive(Debug, Clone, Copy, TypedBuilder)]
190pub struct BorrowingFeeKinkModelParams<T> {
191    long: BorrowingFeeKinkModelParamsForOneSide<T>,
192    short: BorrowingFeeKinkModelParamsForOneSide<T>,
193}
194
195impl<T> BorrowingFeeKinkModelParams<T> {
196    fn params_for_one_side(&self, is_long: bool) -> &BorrowingFeeKinkModelParamsForOneSide<T> {
197        if is_long {
198            &self.long
199        } else {
200            &self.short
201        }
202    }
203
204    /// Get optimal usage factor.
205    pub fn optimal_usage_factor(&self, is_long: bool) -> &T {
206        &self.params_for_one_side(is_long).optimal_usage_factor
207    }
208
209    /// Get base borrowing factor.
210    pub fn base_borrowing_factor(&self, is_long: bool) -> &T {
211        &self.params_for_one_side(is_long).base_borrowing_factor
212    }
213
214    /// Get above optimal usage borrowing factor.
215    pub fn above_optimal_usage_borrowing_factor(&self, is_long: bool) -> &T {
216        &self
217            .params_for_one_side(is_long)
218            .above_optimal_usage_borrowing_factor
219    }
220
221    /// Calculate borrowing factor per second.
222    pub fn borrowing_factor_per_second<const DECIMALS: u8, M>(
223        &self,
224        market: &M,
225        is_long: bool,
226        reserved_value: &T,
227        pool_value: &T,
228    ) -> crate::Result<Option<T>>
229    where
230        M: crate::BaseMarket<DECIMALS, Num = T> + ?Sized,
231        T: FixedPointOps<DECIMALS>,
232    {
233        use crate::market::utils::MarketUtils;
234
235        let optimal_usage_factor = self.optimal_usage_factor(is_long);
236
237        if optimal_usage_factor.is_zero() {
238            return Ok(None);
239        }
240
241        let usage_factor = market.usage_factor(is_long, reserved_value, pool_value)?;
242
243        let base_borrowing_factor = self.base_borrowing_factor(is_long);
244
245        let borrowing_factor_per_second = utils::apply_factor(&usage_factor, base_borrowing_factor)
246            .ok_or(crate::Error::Computation(
247                "borrowing fee kink model: calculating borrowing factor per second",
248            ))?;
249
250        if usage_factor > *optimal_usage_factor && T::UNIT > *optimal_usage_factor {
251            let diff =
252                usage_factor
253                    .checked_sub(optimal_usage_factor)
254                    .ok_or(crate::Error::Computation(
255                        "borrowing fee kink model: calculating diff",
256                    ))?;
257
258            let above_optimal_usage_borrowing_factor =
259                self.above_optimal_usage_borrowing_factor(is_long);
260
261            let additional_borrowing_factor_per_second =
262                if above_optimal_usage_borrowing_factor > base_borrowing_factor {
263                    above_optimal_usage_borrowing_factor
264                        .checked_sub(base_borrowing_factor)
265                        .ok_or(crate::Error::Computation(
266                            "borrowing fee kink model: calculating additional factor",
267                        ))?
268                } else {
269                    T::zero()
270                };
271
272            let divisor =
273                T::UNIT
274                    .checked_sub(optimal_usage_factor)
275                    .ok_or(crate::Error::Computation(
276                        "borrowing fee kink model: calculating divisor",
277                    ))?;
278
279            let borrowing_factor_per_second = additional_borrowing_factor_per_second
280                .checked_mul_div(&diff, &divisor)
281                .and_then(|a| borrowing_factor_per_second.checked_add(&a))
282                .ok_or(crate::Error::Computation(
283                    "borrowing fee kink model: increasing borrowing factor per second",
284                ))?;
285
286            Ok(Some(borrowing_factor_per_second))
287        } else {
288            Ok(Some(borrowing_factor_per_second))
289        }
290    }
291}
292
293/// Borrowing Fee Kink Model Parameters for one side.
294#[derive(Debug, Clone, Copy, TypedBuilder)]
295pub struct BorrowingFeeKinkModelParamsForOneSide<T> {
296    optimal_usage_factor: T,
297    base_borrowing_factor: T,
298    above_optimal_usage_borrowing_factor: T,
299}
300
301/// Funding Fee Parameters.
302#[derive(Debug, Clone, Copy, TypedBuilder)]
303pub struct FundingFeeParams<T> {
304    exponent: T,
305    funding_factor: T,
306    increase_factor_per_second: T,
307    decrease_factor_per_second: T,
308    max_factor_per_second: T,
309    min_factor_per_second: T,
310    threshold_for_stable_funding: T,
311    threshold_for_decrease_funding: T,
312}
313
314impl<T> FundingFeeParams<T> {
315    /// Get funding exponent factor.
316    pub fn exponent(&self) -> &T {
317        &self.exponent
318    }
319
320    /// Get funding increase factor per second.
321    pub fn increase_factor_per_second(&self) -> &T {
322        &self.increase_factor_per_second
323    }
324
325    /// Get funding decrease factor per second.
326    pub fn decrease_factor_per_second(&self) -> &T {
327        &self.decrease_factor_per_second
328    }
329
330    /// Get max funding factor per second.
331    pub fn max_factor_per_second(&self) -> &T {
332        &self.max_factor_per_second
333    }
334
335    /// Get min funding factor per second.
336    pub fn min_factor_per_second(&self) -> &T {
337        &self.min_factor_per_second
338    }
339
340    /// Fallback funding factor.
341    pub fn factor(&self) -> &T {
342        &self.funding_factor
343    }
344
345    /// Threshold for stable funding.
346    pub fn threshold_for_stable_funding(&self) -> &T {
347        &self.threshold_for_stable_funding
348    }
349
350    /// Threshold for decrease funding.
351    pub fn threshold_for_decrease_funding(&self) -> &T {
352        &self.threshold_for_decrease_funding
353    }
354
355    /// Get change type for next funding rate.
356    pub fn change(
357        &self,
358        funding_factor_per_second: &T::Signed,
359        long_open_interest: &T,
360        short_open_interest: &T,
361        diff_factor: &T,
362    ) -> FundingRateChangeType
363    where
364        T: Ord + Unsigned,
365    {
366        use num_traits::Signed;
367
368        let is_skew_the_same_direction_as_funding = (funding_factor_per_second.is_positive()
369            && *long_open_interest > *short_open_interest)
370            || (funding_factor_per_second.is_negative()
371                && *long_open_interest < *short_open_interest);
372
373        if is_skew_the_same_direction_as_funding {
374            if *diff_factor > self.threshold_for_stable_funding {
375                FundingRateChangeType::Increase
376            } else if *diff_factor < self.threshold_for_decrease_funding {
377                FundingRateChangeType::Decrease
378            } else {
379                FundingRateChangeType::NoChange
380            }
381        } else {
382            FundingRateChangeType::Increase
383        }
384    }
385}
386
387/// Funding Rate Change Type.
388#[derive(Default, Debug)]
389pub enum FundingRateChangeType {
390    /// No Change.
391    #[default]
392    NoChange,
393    /// Increase.
394    Increase,
395    /// Decrease.
396    Decrease,
397}
398
399/// Liquidation Fee Parameters.
400#[derive(Debug, Clone, Copy, TypedBuilder)]
401pub struct LiquidationFeeParams<T> {
402    factor: T,
403    receiver_factor: T,
404}
405
406impl<T> LiquidationFeeParams<T> {
407    pub(crate) fn fee<const DECIMALS: u8>(
408        &self,
409        size_delta_usd: &T,
410        collateral_token_price: &Price<T>,
411    ) -> crate::Result<LiquidationFees<T>>
412    where
413        T: FixedPointOps<DECIMALS>,
414    {
415        if self.factor.is_zero() {
416            return Ok(Default::default());
417        }
418
419        let fee_value = utils::apply_factor(size_delta_usd, &self.factor).ok_or(
420            crate::Error::Computation("liquidation fee: calculating fee value"),
421        )?;
422        let fee_amount = fee_value
423            .checked_round_up_div(collateral_token_price.pick_price(false))
424            .ok_or(crate::Error::Computation(
425                "liquidation fee: calculating fee amount",
426            ))?;
427        let fee_amount_for_receiver = utils::apply_factor(&fee_amount, &self.receiver_factor)
428            .ok_or(crate::Error::Computation(
429                "liquidation fee: calculating fee amount for receiver",
430            ))?;
431
432        Ok(LiquidationFees {
433            fee_value,
434            fee_amount,
435            fee_amount_for_receiver,
436        })
437    }
438}
439
440/// Fees.
441#[derive(Debug, Clone, Copy)]
442#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
443#[cfg_attr(
444    feature = "anchor-lang",
445    derive(anchor_lang::AnchorDeserialize, anchor_lang::AnchorSerialize)
446)]
447pub struct Fees<T> {
448    fee_amount_for_receiver: T,
449    fee_amount_for_pool: T,
450}
451
452#[cfg(feature = "gmsol-utils")]
453impl<T: gmsol_utils::InitSpace> gmsol_utils::InitSpace for Fees<T> {
454    const INIT_SPACE: usize = 2 * T::INIT_SPACE;
455}
456
457impl<T: Zero> Default for Fees<T> {
458    fn default() -> Self {
459        Self {
460            fee_amount_for_receiver: Zero::zero(),
461            fee_amount_for_pool: Zero::zero(),
462        }
463    }
464}
465
466impl<T> Fees<T> {
467    /// Create a new [`Fees`].
468    pub fn new(pool: T, receiver: T) -> Self {
469        Self {
470            fee_amount_for_pool: pool,
471            fee_amount_for_receiver: receiver,
472        }
473    }
474
475    /// Get fee amount for receiver
476    pub fn fee_amount_for_receiver(&self) -> &T {
477        &self.fee_amount_for_receiver
478    }
479
480    /// Get fee amount for pool.
481    pub fn fee_amount_for_pool(&self) -> &T {
482        &self.fee_amount_for_pool
483    }
484}
485
486/// Order Fees.
487#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
488#[cfg_attr(
489    feature = "anchor-lang",
490    derive(anchor_lang::AnchorDeserialize, anchor_lang::AnchorSerialize)
491)]
492#[derive(Debug, Clone, Copy)]
493pub struct OrderFees<T> {
494    base: Fees<T>,
495    fee_value: T,
496}
497
498#[cfg(feature = "gmsol-utils")]
499impl<T: gmsol_utils::InitSpace> gmsol_utils::InitSpace for OrderFees<T> {
500    const INIT_SPACE: usize = Fees::<T>::INIT_SPACE + T::INIT_SPACE;
501}
502
503impl<T> OrderFees<T> {
504    /// Get fee amounts.
505    pub fn fee_amounts(&self) -> &Fees<T> {
506        &self.base
507    }
508
509    /// Get order fee value.
510    pub fn fee_value(&self) -> &T {
511        &self.fee_value
512    }
513}
514
515impl<T: Zero> Default for OrderFees<T> {
516    fn default() -> Self {
517        Self {
518            base: Default::default(),
519            fee_value: Zero::zero(),
520        }
521    }
522}
523
524/// Borrowing Fee.
525#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
526#[cfg_attr(
527    feature = "anchor-lang",
528    derive(anchor_lang::AnchorDeserialize, anchor_lang::AnchorSerialize)
529)]
530#[derive(Debug, Clone, Copy)]
531pub struct BorrowingFees<T> {
532    fee_amount: T,
533    fee_amount_for_receiver: T,
534}
535
536#[cfg(feature = "gmsol-utils")]
537impl<T: gmsol_utils::InitSpace> gmsol_utils::InitSpace for BorrowingFees<T> {
538    const INIT_SPACE: usize = 2 * T::INIT_SPACE;
539}
540
541impl<T> BorrowingFees<T> {
542    /// Get total borrowing fee amount.
543    pub fn fee_amount(&self) -> &T {
544        &self.fee_amount
545    }
546
547    /// Get borrowing fee amount for receiver.
548    pub fn fee_amount_for_receiver(&self) -> &T {
549        &self.fee_amount_for_receiver
550    }
551
552    /// Get borrowing fee amount for pool.
553    pub fn fee_amount_for_pool(&self) -> crate::Result<T>
554    where
555        T: CheckedSub,
556    {
557        self.fee_amount
558            .checked_sub(&self.fee_amount_for_receiver)
559            .ok_or(crate::Error::Computation(
560                "borrowing fee: calculating fee for pool",
561            ))
562    }
563}
564
565impl<T: Zero> Default for BorrowingFees<T> {
566    fn default() -> Self {
567        Self {
568            fee_amount: Zero::zero(),
569            fee_amount_for_receiver: Zero::zero(),
570        }
571    }
572}
573
574/// Funding Fees.
575#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
576#[cfg_attr(
577    feature = "anchor-lang",
578    derive(anchor_lang::AnchorDeserialize, anchor_lang::AnchorSerialize)
579)]
580#[derive(Debug, Clone, Copy, TypedBuilder)]
581pub struct FundingFees<T> {
582    amount: T,
583    claimable_long_token_amount: T,
584    claimable_short_token_amount: T,
585}
586
587#[cfg(feature = "gmsol-utils")]
588impl<T: gmsol_utils::InitSpace> gmsol_utils::InitSpace for FundingFees<T> {
589    const INIT_SPACE: usize = 3 * T::INIT_SPACE;
590}
591
592impl<T> FundingFees<T> {
593    /// Get funding fee amount.
594    pub fn amount(&self) -> &T {
595        &self.amount
596    }
597
598    /// Get claimable long token funding fee amount.
599    pub fn claimable_long_token_amount(&self) -> &T {
600        &self.claimable_long_token_amount
601    }
602
603    /// Get claimable short token funding fee amount.
604    pub fn claimable_short_token_amount(&self) -> &T {
605        &self.claimable_short_token_amount
606    }
607}
608
609impl<T: Zero> Default for FundingFees<T> {
610    fn default() -> Self {
611        Self {
612            amount: Zero::zero(),
613            claimable_long_token_amount: Zero::zero(),
614            claimable_short_token_amount: Zero::zero(),
615        }
616    }
617}
618
619/// Liquidation Fees.
620#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
621#[cfg_attr(
622    feature = "anchor-lang",
623    derive(anchor_lang::AnchorDeserialize, anchor_lang::AnchorSerialize)
624)]
625#[derive(Debug, Clone, Copy)]
626pub struct LiquidationFees<T> {
627    fee_value: T,
628    fee_amount: T,
629    fee_amount_for_receiver: T,
630}
631
632#[cfg(feature = "gmsol-utils")]
633impl<T: gmsol_utils::InitSpace> gmsol_utils::InitSpace for LiquidationFees<T> {
634    const INIT_SPACE: usize = 3 * T::INIT_SPACE;
635}
636
637impl<T: Zero> Default for LiquidationFees<T> {
638    fn default() -> Self {
639        Self {
640            fee_value: Zero::zero(),
641            fee_amount: Zero::zero(),
642            fee_amount_for_receiver: Zero::zero(),
643        }
644    }
645}
646
647impl<T> LiquidationFees<T> {
648    /// Get total liquidation fee amount.
649    pub fn fee_amount(&self) -> &T {
650        &self.fee_amount
651    }
652
653    /// Get liquidation fee amount for receiver.
654    pub fn fee_amount_for_receiver(&self) -> &T {
655        &self.fee_amount_for_receiver
656    }
657
658    /// Get liquidation fee amount for pool.
659    pub fn fee_amount_for_pool(&self) -> crate::Result<T>
660    where
661        T: CheckedSub,
662    {
663        self.fee_amount
664            .checked_sub(&self.fee_amount_for_receiver)
665            .ok_or(crate::Error::Computation(
666                "liquidation fee: calculating fee for pool",
667            ))
668    }
669
670    /// Get total liquidation fee value.
671    pub fn fee_value(&self) -> &T {
672        &self.fee_value
673    }
674}
675
676/// Position Fees.
677#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
678#[cfg_attr(
679    feature = "anchor-lang",
680    derive(anchor_lang::AnchorDeserialize, anchor_lang::AnchorSerialize)
681)]
682#[derive(Debug, Clone, Copy)]
683pub struct PositionFees<T> {
684    paid_order_and_borrowing_fee_value: T,
685    order: OrderFees<T>,
686    borrowing: BorrowingFees<T>,
687    funding: FundingFees<T>,
688    liquidation: Option<LiquidationFees<T>>,
689}
690
691#[cfg(feature = "gmsol-utils")]
692impl<T: gmsol_utils::InitSpace> gmsol_utils::InitSpace for PositionFees<T> {
693    const INIT_SPACE: usize = T::INIT_SPACE
694        + OrderFees::<T>::INIT_SPACE
695        + BorrowingFees::<T>::INIT_SPACE
696        + FundingFees::<T>::INIT_SPACE
697        + 1
698        + LiquidationFees::<T>::INIT_SPACE;
699}
700
701impl<T> PositionFees<T> {
702    /// Get fee for receiver.
703    pub fn for_receiver(&self) -> crate::Result<T>
704    where
705        T: CheckedAdd,
706    {
707        self.order
708            .fee_amounts()
709            .fee_amount_for_receiver()
710            .checked_add(self.borrowing.fee_amount_for_receiver())
711            .and_then(|total| {
712                if let Some(fees) = self.liquidation_fees() {
713                    total.checked_add(fees.fee_amount_for_receiver())
714                } else {
715                    Some(total)
716                }
717            })
718            .ok_or(crate::Error::Computation("calculating fee for receiver"))
719    }
720
721    /// Get fee for pool.
722    pub fn for_pool<const DECIMALS: u8>(&self) -> crate::Result<T>
723    where
724        T: FixedPointOps<DECIMALS>,
725    {
726        let amount = self
727            .order
728            .fee_amounts()
729            .fee_amount_for_pool()
730            .checked_add(&self.borrowing.fee_amount_for_pool()?)
731            .ok_or(crate::Error::Computation("adding borrowing fee for pool"))
732            .and_then(|total| {
733                if let Some(fees) = self.liquidation_fees() {
734                    total
735                        .checked_add(&fees.fee_amount_for_pool()?)
736                        .ok_or(crate::Error::Computation("adding liquidation fee for pool"))
737                } else {
738                    Ok(total)
739                }
740            })?;
741        Ok(amount)
742    }
743
744    /// Get paid order and borrowing fee value.
745    pub fn paid_order_and_borrowing_fee_value(&self) -> &T {
746        &self.paid_order_and_borrowing_fee_value
747    }
748
749    /// Get order fees.
750    pub fn order_fees(&self) -> &OrderFees<T> {
751        &self.order
752    }
753
754    /// Get borrowing fees.
755    pub fn borrowing_fees(&self) -> &BorrowingFees<T> {
756        &self.borrowing
757    }
758
759    /// Get funding fees.
760    pub fn funding_fees(&self) -> &FundingFees<T> {
761        &self.funding
762    }
763
764    /// Get liquidation fees.
765    pub fn liquidation_fees(&self) -> Option<&LiquidationFees<T>> {
766        self.liquidation.as_ref()
767    }
768
769    /// Get total cost amount in collateral tokens.
770    pub fn total_cost_amount(&self) -> crate::Result<T>
771    where
772        T: CheckedAdd,
773    {
774        self.total_cost_excluding_funding()?
775            .checked_add(&self.funding.amount)
776            .ok_or(crate::Error::Overflow)
777    }
778
779    /// Get total cost excluding funding fee.
780    pub fn total_cost_excluding_funding(&self) -> crate::Result<T>
781    where
782        T: CheckedAdd,
783    {
784        self.order
785            .fee_amounts()
786            .fee_amount_for_pool()
787            .checked_add(self.order.fee_amounts().fee_amount_for_receiver())
788            .and_then(|acc| acc.checked_add(self.borrowing.fee_amount()))
789            .and_then(|acc| {
790                if let Some(fees) = self.liquidation_fees() {
791                    acc.checked_add(fees.fee_amount())
792                } else {
793                    Some(acc)
794                }
795            })
796            .ok_or(crate::Error::Computation(
797                "overflow while calculating total cost excluding funding",
798            ))
799    }
800
801    /// Set paid order and borrwing fee value.
802    pub(crate) fn set_paid_order_and_borrowing_fee_value(
803        &mut self,
804        paid_order_and_borrowing_fee_value: T,
805    ) {
806        self.paid_order_and_borrowing_fee_value = paid_order_and_borrowing_fee_value;
807    }
808
809    /// Clear fees excluding funding fee.
810    pub fn clear_fees_excluding_funding(&mut self)
811    where
812        T: Zero,
813    {
814        self.order = Default::default();
815        self.borrowing = BorrowingFees::default();
816        self.liquidation = None;
817    }
818
819    /// Set borrowing fees.
820    pub fn set_borrowing_fees<const DECIMALS: u8>(
821        mut self,
822        receiver_factor: &T,
823        price: &Price<T>,
824        value: T,
825    ) -> crate::Result<Self>
826    where
827        T: FixedPointOps<DECIMALS>,
828    {
829        let price = price.pick_price(false);
830        debug_assert!(!price.is_zero(), "must be non-zero");
831        let amount = value
832            .checked_div(price)
833            .ok_or(crate::Error::Computation("calculating borrowing amount"))?;
834        let paid_fee_value = self
835            .paid_order_and_borrowing_fee_value
836            .checked_add(&value)
837            .ok_or(crate::Error::Computation("adding borrowing fee value"))?;
838        self.borrowing.fee_amount_for_receiver =
839            crate::utils::apply_factor(&amount, receiver_factor).ok_or(
840                crate::Error::Computation("calculating borrowing fee amount for receiver"),
841            )?;
842        self.borrowing.fee_amount = amount;
843        self.paid_order_and_borrowing_fee_value = paid_fee_value;
844        Ok(self)
845    }
846
847    /// Set funding fees.
848    pub fn set_funding_fees(mut self, fees: FundingFees<T>) -> Self {
849        self.funding = fees;
850        self
851    }
852
853    /// Set liquidation fees.
854    pub fn set_liquidation_fees(mut self, fees: Option<LiquidationFees<T>>) -> Self {
855        self.liquidation = fees;
856        self
857    }
858}
859
860impl<T: Zero> Default for PositionFees<T> {
861    fn default() -> Self {
862        Self {
863            paid_order_and_borrowing_fee_value: Zero::zero(),
864            order: Default::default(),
865            borrowing: Default::default(),
866            funding: Default::default(),
867            liquidation: None,
868        }
869    }
870}