use std::sync::Arc;
use gmsol_model::PositionState;
use gmsol_programs::{gmsol_store::accounts::Position, model::PositionModel};
use wasm_bindgen::prelude::*;
use crate::{
js::events::JsTradeEvent,
position::{status::PositionStatus, CalculatePositionStatusOptions, PositionCalculations},
utils::zero_copy::{
try_deserialize_zero_copy, try_deserialize_zero_copy_from_base64_with_options,
},
};
use super::{market::JsMarketModel, price::Prices};
#[wasm_bindgen(js_name = Position)]
#[derive(Clone)]
pub struct JsPosition {
pub(crate) position: Arc<Position>,
}
#[wasm_bindgen(js_class = Position)]
impl JsPosition {
pub fn decode_from_base64_with_options(
data: &str,
no_discriminator: Option<bool>,
) -> crate::Result<Self> {
let position = try_deserialize_zero_copy_from_base64_with_options(
data,
no_discriminator.unwrap_or(false),
)?;
Ok(Self {
position: Arc::new(position.0),
})
}
pub fn decode_from_base64(data: &str) -> crate::Result<Self> {
Self::decode_from_base64_with_options(data, None)
}
pub fn decode(data: &[u8]) -> crate::Result<Self> {
let position = try_deserialize_zero_copy(data)?;
Ok(Self {
position: Arc::new(position.0),
})
}
pub fn to_model(&self, market: &JsMarketModel) -> crate::Result<JsPositionModel> {
let mut market_model = market.model.clone();
Ok(JsPositionModel {
model: market_model.with_vis_disabled(|market| {
PositionModel::new(market.clone(), self.position.clone())
})?,
})
}
#[wasm_bindgen(js_name = clone)]
pub fn js_clone(&self) -> Self {
self.clone()
}
}
#[wasm_bindgen(js_name = PositionModel)]
#[derive(Clone)]
pub struct JsPositionModel {
model: PositionModel,
}
#[wasm_bindgen(js_class = PositionModel)]
impl JsPositionModel {
pub fn status(&self, prices: Prices) -> crate::Result<PositionStatus> {
self.status_with_options(prices, None)
}
pub fn status_with_options(
&self,
prices: Prices,
include_virtual_inventory_impact: Option<bool>,
) -> crate::Result<PositionStatus> {
let prices = prices.into();
self.model.status_with_options(
&prices,
CalculatePositionStatusOptions {
include_virtual_inventory_impact: include_virtual_inventory_impact
.unwrap_or_default(),
},
)
}
pub fn size(&self) -> u128 {
*self.model.size_in_usd()
}
pub fn size_in_tokens(&self) -> u128 {
*self.model.size_in_tokens()
}
pub fn collateral_amount(&self) -> u128 {
*self.model.collateral_amount()
}
pub fn position(&self) -> JsPosition {
JsPosition {
position: self.model.position_arc().clone(),
}
}
pub fn update_with_trade_event(
&mut self,
event: &JsTradeEvent,
force_update: Option<bool>,
) -> crate::Result<bool> {
let updated = self
.model
.update(&event.event.after.into(), force_update.unwrap_or_default());
Ok(updated)
}
#[wasm_bindgen(js_name = clone)]
pub fn js_clone(&self) -> Self {
self.clone()
}
}
impl From<PositionModel> for JsPositionModel {
fn from(model: PositionModel) -> Self {
Self { model }
}
}