use std::fmt;
use crate::live::market::Side;
use crate::utils::{Address, Dec};
use serde::{Deserialize, Deserializer, de};
use serde_json::value::RawValue;
pub use crate::account::fill::{Fill, FillLiquidation, TwapSliceFill};
#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct UserFills {
pub user: Address,
#[serde(default)]
pub is_snapshot: bool,
pub fills: Vec<Fill>,
}
pub use crate::account::order::OpenOrder as Order;
#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct OrderUpdate {
pub order: Order,
pub status: String,
pub status_timestamp: u64,
}
pub use crate::account::order::FrontendOrder as OpenOrder;
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum UserEvent {
Fills(Vec<Fill>),
Funding(Funding),
Liquidation(Liquidation),
NonUserCancel(Vec<Cancel>),
TwapHistory(Vec<TwapEvent>),
TwapSliceFills(Vec<TwapSliceFill>),
Other {
key: String,
data: String,
},
}
impl<'de> Deserialize<'de> for UserEvent {
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
struct Event;
impl<'de> de::Visitor<'de> for Event {
type Value = UserEvent;
fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("an object with one event in it")
}
fn visit_map<A: de::MapAccess<'de>>(self, mut map: A) -> Result<UserEvent, A::Error> {
let key: String = map.next_key()?.ok_or_else(|| de::Error::custom("an event with nothing in it"))?;
let event = match key.as_str() {
"fills" => UserEvent::Fills(map.next_value()?),
"funding" => UserEvent::Funding(map.next_value()?),
"liquidation" => UserEvent::Liquidation(map.next_value()?),
"nonUserCancel" => UserEvent::NonUserCancel(map.next_value()?),
"twapHistory" => UserEvent::TwapHistory(map.next_value()?),
"twapSliceFills" => UserEvent::TwapSliceFills(map.next_value()?),
_ => {
let data: Box<RawValue> = map.next_value()?;
UserEvent::Other { key, data: data.get().to_owned() }
}
};
if map.next_key::<de::IgnoredAny>()?.is_some() {
return Err(de::Error::custom("more than one event in a frame"));
}
Ok(event)
}
}
deserializer.deserialize_map(Event)
}
}
#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Funding {
pub time: u64,
pub coin: String,
pub usdc: Dec,
pub szi: Dec,
pub funding_rate: Dec,
#[serde(default)]
pub n_samples: Option<u64>,
}
#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
pub struct Liquidation {
pub lid: u64,
pub liquidator: Address,
pub liquidated_user: Address,
pub liquidated_ntl_pos: Dec,
pub liquidated_account_value: Dec,
}
#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
pub struct Cancel {
pub coin: String,
pub oid: u64,
}
#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct UserFundings {
pub user: Address,
#[serde(default)]
pub is_snapshot: bool,
pub fundings: Vec<Funding>,
}
#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Ledger {
pub user: Address,
#[serde(default)]
pub is_snapshot: bool,
#[serde(rename = "nonFundingLedgerUpdates")]
pub updates: Vec<LedgerUpdate>,
}
pub use crate::account::ledger::{Delta, LedgerUpdate};
pub use crate::account::clearinghouse::{
AssetPosition, Clearinghouse, CumFunding, Leverage, MarginMode as Margin, MarginSummary, Position,
};
#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct DexState {
pub dex: String,
pub user: Address,
#[serde(rename = "clearinghouseState")]
pub state: Clearinghouse,
}
#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct AllDexsState {
pub user: Address,
#[serde(rename = "clearinghouseStates")]
pub states: Vec<(String, Clearinghouse)>,
}
#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
pub struct OpenOrders {
pub dex: String,
pub user: Address,
pub orders: Vec<OpenOrder>,
}
#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct SpotState {
pub user: Address,
#[serde(rename = "spotState")]
pub state: crate::account::clearinghouse::SpotState,
}
pub use crate::account::clearinghouse::SpotBalance as Balance;
#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
pub struct TwapStates {
pub dex: String,
pub user: Address,
pub states: Vec<(u64, TwapState)>,
}
#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct TwapState {
pub coin: String,
pub user: Address,
pub side: Side,
pub sz: Dec,
pub executed_sz: Dec,
pub executed_ntl: Dec,
pub minutes: u32,
pub reduce_only: bool,
pub randomize: bool,
pub timestamp: u64,
}
#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct TwapSliceFills {
pub user: Address,
#[serde(default)]
pub is_snapshot: bool,
#[serde(rename = "twapSliceFills")]
pub fills: Vec<TwapSliceFill>,
}
#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct TwapEvent {
pub time: u64,
pub state: TwapState,
pub status: TwapStatus,
#[serde(default)]
pub twap_id: Option<u64>,
}
#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
pub struct TwapStatus {
pub status: String,
#[serde(default)]
pub description: Option<String>,
}
#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct TwapHistory {
pub user: Address,
#[serde(default)]
pub is_snapshot: bool,
pub history: Vec<TwapEvent>,
}
#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct WebData3 {
pub user_state: UserState,
pub perp_dex_states: Vec<PerpDexState>,
}
#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct UserState {
pub user: Address,
#[serde(default)]
pub agent_address: Option<Address>,
#[serde(default)]
pub agent_valid_until: Option<u64>,
pub server_time: u64,
pub cum_ledger: Dec,
pub is_vault: bool,
#[serde(default)]
pub abstraction: Option<String>,
#[serde(default)]
pub dex_abstraction_enabled: bool,
#[serde(default)]
pub opt_out_of_spot_dusting: bool,
}
#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct PerpDexState {
pub total_vault_equity: Dec,
#[serde(default)]
pub perps_at_open_interest_cap: Vec<String>,
#[serde(default)]
pub leading_vaults: Vec<LeadingVault>,
}
#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
pub struct LeadingVault {
pub address: Address,
pub name: String,
}
pub use crate::account::clearinghouse::ActiveAssetData as AssetData;
#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct HistoricalOrders {
pub user: Address,
#[serde(default)]
pub is_snapshot: bool,
#[serde(rename = "orderHistory")]
pub orders: Vec<HistoricalOrder>,
}
pub use crate::account::order::OrderRecord as HistoricalOrder;