gmsol_sdk/js/
position.rs

1use std::sync::Arc;
2
3use gmsol_model::PositionState;
4use gmsol_programs::{gmsol_store::accounts::Position, model::PositionModel};
5use wasm_bindgen::prelude::*;
6
7use crate::{
8    js::events::JsTradeEvent,
9    position::{status::PositionStatus, PositionCalculations},
10    utils::zero_copy::{
11        try_deserialize_zero_copy, try_deserialize_zero_copy_from_base64_with_options,
12    },
13};
14
15use super::{market::JsMarketModel, price::Prices};
16
17/// JS version of [`Position`].
18#[wasm_bindgen(js_name = Position)]
19#[derive(Clone)]
20pub struct JsPosition {
21    pub(crate) position: Arc<Position>,
22}
23
24#[wasm_bindgen(js_class = Position)]
25impl JsPosition {
26    /// Create from base64 encoded account data with options.
27    pub fn decode_from_base64_with_options(
28        data: &str,
29        no_discriminator: Option<bool>,
30    ) -> crate::Result<Self> {
31        let position = try_deserialize_zero_copy_from_base64_with_options(
32            data,
33            no_discriminator.unwrap_or(false),
34        )?;
35
36        Ok(Self {
37            position: Arc::new(position.0),
38        })
39    }
40
41    /// Create from base64 encoded account data.
42    pub fn decode_from_base64(data: &str) -> crate::Result<Self> {
43        Self::decode_from_base64_with_options(data, None)
44    }
45
46    /// Create from account data.
47    pub fn decode(data: &[u8]) -> crate::Result<Self> {
48        let position = try_deserialize_zero_copy(data)?;
49
50        Ok(Self {
51            position: Arc::new(position.0),
52        })
53    }
54
55    /// Convert to a [`JsPositionModel`].
56    pub fn to_model(&self, market: &JsMarketModel) -> crate::Result<JsPositionModel> {
57        Ok(JsPositionModel {
58            model: PositionModel::new(market.model.clone(), self.position.clone())?,
59        })
60    }
61
62    /// Create a clone of this position.
63    #[wasm_bindgen(js_name = clone)]
64    pub fn js_clone(&self) -> Self {
65        self.clone()
66    }
67}
68
69/// JS version of [`PositionModel`].
70#[wasm_bindgen(js_name = PositionModel)]
71#[derive(Clone)]
72pub struct JsPositionModel {
73    model: PositionModel,
74}
75
76#[wasm_bindgen(js_class = PositionModel)]
77impl JsPositionModel {
78    /// Get position status.
79    pub fn status(&self, prices: Prices) -> crate::Result<PositionStatus> {
80        let prices = prices.into();
81        self.model.status(&prices)
82    }
83
84    /// Get position size.
85    pub fn size(&self) -> u128 {
86        *self.model.size_in_usd()
87    }
88
89    /// Get position size in tokens.
90    pub fn size_in_tokens(&self) -> u128 {
91        *self.model.size_in_tokens()
92    }
93
94    /// Get collateral amount.
95    pub fn collateral_amount(&self) -> u128 {
96        *self.model.collateral_amount()
97    }
98
99    /// Returns the inner [`JsPosition`].
100    pub fn position(&self) -> JsPosition {
101        JsPosition {
102            position: self.model.position_arc().clone(),
103        }
104    }
105
106    /// Update with trade event.
107    pub fn update_with_trade_event(
108        &mut self,
109        event: &JsTradeEvent,
110        force_update: Option<bool>,
111    ) -> crate::Result<bool> {
112        let updated = self
113            .model
114            .update(&event.event.after.into(), force_update.unwrap_or_default());
115
116        Ok(updated)
117    }
118
119    /// Create a clone of this position model.
120    #[wasm_bindgen(js_name = clone)]
121    pub fn js_clone(&self) -> Self {
122        self.clone()
123    }
124}
125
126impl From<PositionModel> for JsPositionModel {
127    fn from(model: PositionModel) -> Self {
128        Self { model }
129    }
130}