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#[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 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 pub fn decode_from_base64(data: &str) -> crate::Result<Self> {
43 Self::decode_from_base64_with_options(data, None)
44 }
45
46 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 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 #[wasm_bindgen(js_name = clone)]
64 pub fn js_clone(&self) -> Self {
65 self.clone()
66 }
67}
68
69#[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 pub fn status(&self, prices: Prices) -> crate::Result<PositionStatus> {
80 let prices = prices.into();
81 self.model.status(&prices)
82 }
83
84 pub fn size(&self) -> u128 {
86 *self.model.size_in_usd()
87 }
88
89 pub fn size_in_tokens(&self) -> u128 {
91 *self.model.size_in_tokens()
92 }
93
94 pub fn collateral_amount(&self) -> u128 {
96 *self.model.collateral_amount()
97 }
98
99 pub fn position(&self) -> JsPosition {
101 JsPosition {
102 position: self.model.position_arc().clone(),
103 }
104 }
105
106 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 #[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}