1pub mod models {
6 #![allow(warnings)]
7 include!(concat!(env!("OUT_DIR"), "/hyperflow.core.v1.rs"));
9}
10
11#[cfg(test)]
12mod tests {
13 use super::models::{EnrichedTrade, HyperliquidTrade, MarketType, Position, RawTrade};
14 use prost::Message;
15
16 macro_rules! generate_model_tests {
31 (
32 $test_module_name:ident,
33 $model_type:ty,
34 $sample_data_fn:expr,
35 $default_checks:expr
36 ) => {
37 mod $test_module_name {
38 use super::*; #[test]
41 fn test_creation_with_sample_data() {
42 let instance = $sample_data_fn;
43 let expected_instance = $sample_data_fn;
44 assert_eq!(instance, expected_instance);
46 }
47
48 #[test]
49 fn test_default_values_are_correct() {
50 let instance = <$model_type>::default();
51 $default_checks(&instance);
53 }
54
55 #[test]
56 fn test_serialization_and_deserialization() {
57 let original = $sample_data_fn;
58 let mut buf = Vec::new();
59 original.encode(&mut buf).unwrap();
60 let deserialized = <$model_type>::decode(&buf[..]).unwrap();
61 assert_eq!(original, deserialized);
62 }
63 }
64 };
65 }
66
67 fn sample_hyperliquid_trade() -> HyperliquidTrade {
69 HyperliquidTrade {
70 coin: "ETH".to_string(),
71 side: "buy".to_string(),
72 px: "123.45".to_string(),
73 sz: "1.0".to_string(),
74 hash: "0xabc123".to_string(),
75 time: 1678886400,
76 tid: 1,
77 users: vec!["buyer_address".to_string(), "seller_address".to_string()],
78 }
79 }
80
81 generate_model_tests!(
82 hyperliquid_trade_tests,
83 HyperliquidTrade,
84 sample_hyperliquid_trade(),
85 |trade: &HyperliquidTrade| {
86 assert_eq!(trade.coin, "");
87 assert_eq!(trade.side, "");
88 assert_eq!(trade.px, "");
89 assert_eq!(trade.sz, "");
90 assert_eq!(trade.hash, "");
91 assert_eq!(trade.time, 0);
92 assert_eq!(trade.tid, 0);
93 assert!(trade.users.is_empty());
94 }
95 );
96
97 #[test]
98 fn test_create_hyperliquid_trade_with_overrides() {
99 let trade = HyperliquidTrade {
100 px: "0.0".to_string(),
101 sz: "0.0".to_string(),
102 users: vec!["buyer_address".to_string()],
103 ..Default::default()
104 };
105 assert_eq!(trade.px, "0.0");
106 assert_eq!(trade.sz, "0.0");
107 assert_eq!(trade.users, vec!["buyer_address"]);
108 }
109
110
111 fn sample_raw_trade() -> RawTrade {
113 RawTrade {
114 symbol: "BTC/USD".to_string(),
115 is_buy: true,
116 is_taker: false,
117 price: "50000.0".to_string(),
118 amount: "0.1".to_string(),
119 quote_amount: "5000.0".to_string(),
120 hash: "abc-123".to_string(),
121 event_at: 1678887000,
122 transaction_id: "ext-xyz".to_string(),
123 wallet_address: "0x12345".to_string(),
124 market_type: MarketType::Perp as i32,
125 extra_data: None, }
127 }
128
129 generate_model_tests!(
130 raw_trade_tests,
131 RawTrade,
132 sample_raw_trade(),
133 |trade: &RawTrade| {
134 assert_eq!(trade.symbol, "");
135 assert!(!trade.is_buy);
136 assert!(!trade.is_taker);
137 assert_eq!(trade.price, "");
138 assert_eq!(trade.amount, "");
139 assert_eq!(trade.quote_amount, "");
140 assert_eq!(trade.hash, "");
141 assert_eq!(trade.event_at, 0);
142 assert_eq!(trade.transaction_id, "");
143 assert_eq!(trade.wallet_address, "");
144 assert_eq!(trade.market_type, MarketType::Perp as i32);
145 }
146 );
147
148 mod raw_trade_specific_tests {
150 use super::*;
151
152 #[test]
153 fn test_serialization_all_market_types() {
154 for mt in [MarketType::Perp, MarketType::Spot] {
155 let mut trade = sample_raw_trade();
156 trade.market_type = mt as i32;
157
158 let mut buf = Vec::new();
159 trade.encode(&mut buf).unwrap();
160 let deserialized = RawTrade::decode(&buf[..]).unwrap();
161 assert_eq!(deserialized.market_type, mt as i32);
162 }
163 }
164
165 #[test]
166 fn test_market_type_enum_values() {
167 assert_eq!(MarketType::Perp as i32, 0);
168 assert_eq!(MarketType::Spot as i32, 1);
169 }
170 }
171
172
173 fn sample_enriched_trade() -> EnrichedTrade {
175 EnrichedTrade {
176 symbol: "BTC/USD".to_string(),
177 is_buy: true,
178 is_taker: false,
179 price: "50000.0".to_string(),
180 amount: "0.1".to_string(),
181 quote_amount: "5000.0".to_string(),
182 hash: "abc-123".to_string(),
183 event_at: 1678887000,
184 transaction_id: "ext-xyz".to_string(),
185 wallet_address: "0x12345".to_string(),
186 market_type: MarketType::Perp as i32,
187 pnl: "100.0".to_string(),
188 pnl_usd: "100.0".to_string(),
189 holding_duration: 3600,
190 extra_data: None,
191 }
192 }
193
194 generate_model_tests!(
195 enriched_trade_tests,
196 EnrichedTrade,
197 sample_enriched_trade(),
198 |trade: &EnrichedTrade| {
199 assert_eq!(trade.symbol, "");
200 assert_eq!(trade.pnl, "");
201 assert_eq!(trade.pnl_usd, "");
202 assert_eq!(trade.holding_duration, 0);
203 }
204 );
205
206 fn sample_position() -> Position {
208 Position {
209 symbol: "BTC/USD".to_string(),
210 is_buy: true,
211 average_price: "50000.0".to_string(),
212 amount: "0.1".to_string(),
213 quote_amount: "5000.0".to_string(),
214 wallet_address: "0x12345".to_string(),
215 market_type: MarketType::Perp as i32,
216 }
217 }
218
219 generate_model_tests!(
220 position_tests,
221 Position,
222 sample_position(),
223 |pos: &Position| {
224 assert_eq!(pos.symbol, "");
225 assert!(!pos.is_buy);
226 assert_eq!(pos.average_price, "");
227 assert_eq!(pos.amount, "");
228 assert_eq!(pos.quote_amount, "");
229 assert_eq!(pos.wallet_address, "");
230 assert_eq!(pos.market_type, MarketType::Perp as i32);
231 }
232 );
233}