Skip to main content

pragma_common/entries/
open_interest.rs

1#[cfg(feature = "proto")]
2use prost::Message;
3
4use crate::{instrument_type::InstrumentType, Pair};
5#[cfg(feature = "proto")]
6use crate::{ProtoDeserialize, ProtoSerialize};
7
8#[derive(Debug, Clone, PartialEq)]
9#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
10#[cfg_attr(
11    feature = "borsh",
12    derive(borsh::BorshSerialize, borsh::BorshDeserialize)
13)]
14#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
15pub struct OpenInterestEntry {
16    pub source: String,
17    pub pair: Pair,
18    pub open_interest: f64,
19    pub timestamp_ms: i64,
20    pub instrument_type: InstrumentType,
21    pub received_timestamp_ms: i64,
22}
23
24#[cfg(feature = "proto")]
25impl OpenInterestEntry {
26    fn to_proto(&self) -> crate::schema::OpenInterestEntry {
27        crate::schema::OpenInterestEntry {
28            source: self.source.clone(),
29            pair: Some(crate::schema::Pair {
30                base: self.pair.base.clone(),
31                quote: self.pair.quote.clone(),
32            }),
33            open_interest: self.open_interest,
34            timestamp_ms: self.timestamp_ms,
35            instrument_type: match self.instrument_type {
36                InstrumentType::Spot => crate::schema::InstrumentType::Spot as i32,
37                InstrumentType::Perp => crate::schema::InstrumentType::Perp as i32,
38            },
39            received_timestamp_ms: self.received_timestamp_ms,
40        }
41    }
42
43    fn from_proto(proto: crate::schema::OpenInterestEntry) -> Result<Self, prost::DecodeError> {
44        let pair = proto
45            .pair
46            .ok_or_else(|| prost::DecodeError::new("Missing pair field in OpenInterestEntry"))?;
47        let instrument_type = match proto.instrument_type {
48            x if x == crate::schema::InstrumentType::Spot as i32 => InstrumentType::Spot,
49            x if x == crate::schema::InstrumentType::Perp as i32 => InstrumentType::Perp,
50            _ => InstrumentType::Perp, // Default to Perp for OI (backwards compat)
51        };
52
53        Ok(OpenInterestEntry {
54            source: proto.source,
55            pair: Pair {
56                base: pair.base,
57                quote: pair.quote,
58            },
59            open_interest: proto.open_interest,
60            timestamp_ms: proto.timestamp_ms,
61            instrument_type,
62            received_timestamp_ms: proto.received_timestamp_ms,
63        })
64    }
65}
66
67#[cfg(feature = "proto")]
68impl ProtoSerialize for OpenInterestEntry {
69    fn to_proto_bytes(&self) -> Vec<u8> {
70        let proto = self.to_proto();
71        let mut buf = Vec::new();
72        proto
73            .encode(&mut buf)
74            .expect("Failed to encode OpenInterestEntry to protobuf");
75        buf
76    }
77}
78
79#[cfg(feature = "proto")]
80impl ProtoDeserialize for OpenInterestEntry {
81    fn from_proto_bytes(bytes: &[u8]) -> Result<Self, prost::DecodeError> {
82        let proto = crate::schema::OpenInterestEntry::decode(bytes)?;
83        Self::from_proto(proto)
84    }
85}