Skip to main content

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, CalculatePositionStatusOptions, 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        let mut market_model = market.model.clone();
58        Ok(JsPositionModel {
59            model: market_model.with_vis_disabled(|market| {
60                PositionModel::new(market.clone(), self.position.clone())
61            })?,
62        })
63    }
64
65    /// Create a clone of this position.
66    #[wasm_bindgen(js_name = clone)]
67    pub fn js_clone(&self) -> Self {
68        self.clone()
69    }
70}
71
72/// JS version of [`PositionModel`].
73#[wasm_bindgen(js_name = PositionModel)]
74#[derive(Clone)]
75pub struct JsPositionModel {
76    model: PositionModel,
77}
78
79#[wasm_bindgen(js_class = PositionModel)]
80impl JsPositionModel {
81    /// Get position status.
82    pub fn status(&self, prices: Prices) -> crate::Result<PositionStatus> {
83        self.status_with_options(prices, None)
84    }
85
86    /// Get position status with options.
87    pub fn status_with_options(
88        &self,
89        prices: Prices,
90        include_virtual_inventory_impact: Option<bool>,
91    ) -> crate::Result<PositionStatus> {
92        let prices = prices.into();
93        self.model.status_with_options(
94            &prices,
95            CalculatePositionStatusOptions {
96                include_virtual_inventory_impact: include_virtual_inventory_impact
97                    .unwrap_or_default(),
98            },
99        )
100    }
101
102    /// Get position size.
103    pub fn size(&self) -> u128 {
104        *self.model.size_in_usd()
105    }
106
107    /// Get position size in tokens.
108    pub fn size_in_tokens(&self) -> u128 {
109        *self.model.size_in_tokens()
110    }
111
112    /// Get collateral amount.
113    pub fn collateral_amount(&self) -> u128 {
114        *self.model.collateral_amount()
115    }
116
117    /// Returns the inner [`JsPosition`].
118    pub fn position(&self) -> JsPosition {
119        JsPosition {
120            position: self.model.position_arc().clone(),
121        }
122    }
123
124    /// Update with trade event.
125    pub fn update_with_trade_event(
126        &mut self,
127        event: &JsTradeEvent,
128        force_update: Option<bool>,
129    ) -> crate::Result<bool> {
130        let updated = self
131            .model
132            .update(&event.event.after.into(), force_update.unwrap_or_default());
133
134        Ok(updated)
135    }
136
137    /// Create a clone of this position model.
138    #[wasm_bindgen(js_name = clone)]
139    pub fn js_clone(&self) -> Self {
140        self.clone()
141    }
142}
143
144impl From<PositionModel> for JsPositionModel {
145    fn from(model: PositionModel) -> Self {
146        Self { model }
147    }
148}