Skip to content

Commit 9987e3c

Browse files
authored
schema: add PositionEntry proto & rust struct (#26)
1 parent 5781052 commit 9987e3c

File tree

3 files changed

+116
-0
lines changed

3 files changed

+116
-0
lines changed

schema/entries.proto

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,3 +130,13 @@ message TradeEntry {
130130
int64 timestampMs = 10;
131131
int64 receivedTimestampMs = 11;
132132
}
133+
134+
message PositionEntry {
135+
string source = 1;
136+
InstrumentType instrumentType = 2;
137+
Pair pair = 3;
138+
int64 timestampMs = 4;
139+
int64 receivedTimestampMs = 5;
140+
TradeSide side = 6;
141+
double notional_in_usd = 7;
142+
}

src/entries/mod.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,13 @@ pub mod open_interest;
1010
pub mod volume;
1111
// Trade entries
1212
pub mod trade;
13+
// Position entries
14+
pub mod position;
1315

1416
pub use funding_rate::*;
1517
pub use open_interest::*;
1618
pub use orderbook::*;
19+
pub use position::*;
1720
pub use price::*;
1821
pub use trade::*;
1922
pub use volume::*;

src/entries/position.rs

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
use super::trade::TradeSide;
2+
use crate::{instrument_type::InstrumentType, pair::Pair};
3+
#[cfg(feature = "proto")]
4+
use crate::{ProtoDeserialize, ProtoSerialize};
5+
#[cfg(feature = "proto")]
6+
use prost::Message;
7+
#[derive(Debug, Clone, PartialEq)]
8+
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
9+
#[cfg_attr(
10+
feature = "borsh",
11+
derive(borsh::BorshSerialize, borsh::BorshDeserialize)
12+
)]
13+
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
14+
pub struct PositionEntry {
15+
pub source: String,
16+
pub instrument_type: InstrumentType,
17+
pub pair: Pair,
18+
pub timestamp_ms: i64,
19+
pub received_timestamp_ms: i64,
20+
pub side: TradeSide,
21+
pub notional_in_usd: f64,
22+
}
23+
#[cfg(feature = "proto")]
24+
impl PositionEntry {
25+
fn to_proto(&self) -> crate::schema::PositionEntry {
26+
crate::schema::PositionEntry {
27+
source: self.source.clone(),
28+
instrument_type: match self.instrument_type {
29+
InstrumentType::Spot => crate::schema::InstrumentType::Spot as i32,
30+
InstrumentType::Perp => crate::schema::InstrumentType::Perp as i32,
31+
},
32+
pair: Some(crate::schema::Pair {
33+
base: self.pair.base.clone(),
34+
quote: self.pair.quote.clone(),
35+
}),
36+
timestamp_ms: self.timestamp_ms,
37+
received_timestamp_ms: self.received_timestamp_ms,
38+
side: match self.side {
39+
TradeSide::Buy => crate::schema::TradeSide::Buy as i32,
40+
TradeSide::Sell => crate::schema::TradeSide::Sell as i32,
41+
},
42+
notional_in_usd: self.notional_in_usd,
43+
}
44+
}
45+
fn from_proto(proto: crate::schema::PositionEntry) -> Result<Self, prost::DecodeError> {
46+
let pair = proto
47+
.pair
48+
.ok_or_else(|| prost::DecodeError::new("Missing pair field in PositionEntry"))?;
49+
50+
let instrument_type = match proto.instrument_type {
51+
x if x == crate::schema::InstrumentType::Spot as i32 => InstrumentType::Spot,
52+
x if x == crate::schema::InstrumentType::Perp as i32 => InstrumentType::Perp,
53+
_ => {
54+
return Err(prost::DecodeError::new(format!(
55+
"Invalid instrument_type value: {}",
56+
proto.instrument_type,
57+
)))
58+
}
59+
};
60+
61+
let side = match proto.side {
62+
x if x == crate::schema::TradeSide::Buy as i32 => TradeSide::Buy,
63+
x if x == crate::schema::TradeSide::Sell as i32 => TradeSide::Sell,
64+
_ => {
65+
return Err(prost::DecodeError::new(format!(
66+
"Invalid side value: {}",
67+
proto.side,
68+
)))
69+
}
70+
};
71+
72+
Ok(PositionEntry {
73+
source: proto.source,
74+
instrument_type,
75+
pair: Pair {
76+
base: pair.base,
77+
quote: pair.quote,
78+
},
79+
timestamp_ms: proto.timestamp_ms,
80+
received_timestamp_ms: proto.received_timestamp_ms,
81+
side,
82+
notional_in_usd: proto.notional_in_usd,
83+
})
84+
}
85+
}
86+
#[cfg(feature = "proto")]
87+
impl ProtoSerialize for PositionEntry {
88+
fn to_proto_bytes(&self) -> Vec<u8> {
89+
let proto = self.to_proto();
90+
let mut buf = Vec::new();
91+
proto
92+
.encode(&mut buf)
93+
.expect("Failed to encode PositionEntry to protobuf");
94+
buf
95+
}
96+
}
97+
#[cfg(feature = "proto")]
98+
impl ProtoDeserialize for PositionEntry {
99+
fn from_proto_bytes(bytes: &[u8]) -> Result<Self, prost::DecodeError> {
100+
let proto = crate::schema::PositionEntry::decode(bytes)?;
101+
Self::from_proto(proto)
102+
}
103+
}

0 commit comments

Comments
 (0)