1use rust_decimal::{Decimal, serde::str_option::deserialize as option_decimal};
2use serde::{Deserialize, Serialize};
3use serde_aux::prelude::{
4 deserialize_number_from_string as number,
5 deserialize_option_number_from_string as option_number,
6};
7
8use crate::{
9 ContractType, CopyTrading, CurAuctionPhase, Side, Status, Timestamp,
10 enums::{Category, Interval},
11 serde::{empty_string_as_none, string_to_bool},
12};
13
14#[derive(Debug, Serialize)]
15pub struct GetKLinesParams {
16 pub category: Category,
17 pub symbol: String,
18 pub interval: Interval,
19 pub start: Option<Timestamp>,
20 pub end: Option<Timestamp>,
21 pub limit: Option<u64>,
22}
23
24#[derive(Debug, Deserialize, PartialEq)]
25#[serde(tag = "category")]
26pub enum KLine {
27 #[serde(rename = "inverse")]
28 Inverse { symbol: String, list: Vec<KLineRow> },
29 #[serde(rename = "linear")]
30 Linear { symbol: String, list: Vec<KLineRow> },
31 #[serde(rename = "option")]
32 Option { symbol: String, list: Vec<KLineRow> },
33 #[serde(rename = "spot")]
34 Spot { symbol: String, list: Vec<KLineRow> },
35}
36
37#[derive(Debug, Deserialize, PartialEq)]
38pub struct KLineRow {
39 #[serde(rename = "startTime", deserialize_with = "number")]
41 pub start_time: Timestamp,
42 #[serde(rename = "openPrice")]
44 pub open_price: Decimal,
45 #[serde(rename = "highPrice")]
47 pub high_price: Decimal,
48 #[serde(rename = "lowPrice")]
50 pub low_price: Decimal,
51 #[serde(rename = "closePrice")]
53 pub close_price: Decimal,
54 #[serde(rename = "volume")]
56 pub volume: Decimal,
57 #[serde(rename = "turnover")]
59 pub turnover: Decimal,
60}
61
62#[derive(Debug, Serialize)]
63pub struct GetTickersParams {
64 pub category: Category,
65 pub symbol: Option<String>,
66 pub base_coin: Option<String>,
67 pub exp_date: Option<String>,
68}
69
70#[derive(Debug, Deserialize, PartialEq)]
71#[serde(tag = "category")]
72pub enum Ticker {
73 #[serde(rename = "inverse")]
74 Inverse { list: Vec<LinearInverseTicker> },
75 #[serde(rename = "linear")]
76 Linear { list: Vec<LinearInverseTicker> },
77 #[serde(rename = "option")]
78 Option { list: Vec<OptionTicker> },
79 #[serde(rename = "spot")]
80 Spot { list: Vec<SpotTicker> },
81}
82
83#[derive(Debug, Deserialize, PartialEq)]
84#[serde(rename_all = "camelCase")]
85pub struct LinearInverseTicker {
86 pub symbol: String,
88 pub last_price: Decimal,
90 pub mark_price: Decimal,
92 pub index_price: Decimal,
94 pub prev_price24h: Decimal,
96 pub price24h_pcnt: Decimal,
98 pub high_price24h: Decimal,
100 pub low_price24h: Decimal,
102 pub prev_price1h: Decimal,
104 pub open_interest: Decimal,
106 pub open_interest_value: Decimal,
108 pub turnover24h: Decimal,
110 pub volume24h: Decimal,
112 #[serde(default, deserialize_with = "option_decimal")]
114 pub funding_rate: Option<Decimal>,
115 #[serde(deserialize_with = "number")]
117 pub next_funding_time: Timestamp,
118 #[serde(default, deserialize_with = "option_decimal")]
120 pub predicted_delivery_price: Option<Decimal>,
121 #[serde(default, deserialize_with = "option_decimal")]
123 pub basis_rate: Option<Decimal>,
124 #[serde(default, deserialize_with = "option_decimal")]
126 pub basis: Option<Decimal>,
127 #[serde(default, deserialize_with = "option_decimal")]
129 pub delivery_fee_rate: Option<Decimal>,
130 #[serde(deserialize_with = "option_number")]
132 pub delivery_time: Option<Timestamp>,
133 pub bid1_price: Decimal,
135 pub bid1_size: Decimal,
137 pub ask1_price: Decimal,
139 pub ask1_size: Decimal,
141 #[serde(default, deserialize_with = "option_decimal")]
143 pub pre_open_price: Option<Decimal>,
144 #[serde(default, deserialize_with = "option_decimal")]
146 pub pre_qty: Option<Decimal>,
147 #[serde(default, deserialize_with = "empty_string_as_none")]
149 pub cur_pre_listing_phase: Option<CurAuctionPhase>,
150}
151
152#[derive(Debug, Deserialize, PartialEq)]
153#[serde(rename_all = "camelCase")]
154pub struct OptionTicker {
155 pub symbol: String,
157 pub bid1_price: Decimal,
159 pub bid1_size: Decimal,
161 pub bid1_iv: Decimal,
163 pub ask1_price: Decimal,
165 pub ask1_size: Decimal,
167 pub ask1_iv: Decimal,
169 pub last_price: Decimal,
171 pub high_price24h: Decimal,
173 pub low_price24h: Decimal,
175 pub mark_price: Decimal,
177 pub index_price: Decimal,
179 pub mark_iv: Decimal,
181 pub underlying_price: Decimal,
183 pub open_interest: Decimal,
185 pub turnover24h: Decimal,
187 pub volume24h: Decimal,
189 pub total_volume: Decimal,
191 pub total_turnover: Decimal,
193 pub delta: Decimal,
195 pub gamma: Decimal,
197 pub vega: Decimal,
199 pub theta: Decimal,
201 pub predicted_delivery_price: Decimal,
203 pub change24h: Decimal,
205}
206
207#[derive(Debug, Deserialize, PartialEq)]
208#[serde(rename_all = "camelCase")]
209pub struct SpotTicker {
210 pub symbol: String,
212 pub bid1_price: Decimal,
214 pub bid1_size: Decimal,
216 pub ask1_price: Decimal,
218 pub ask1_size: Decimal,
220 pub last_price: Decimal,
222 pub prev_price24h: Decimal,
224 pub price24h_pcnt: Decimal,
226 pub high_price24h: Decimal,
228 pub low_price24h: Decimal,
230 pub turnover24h: Decimal,
232 pub volume24h: Decimal,
234 #[serde(default, deserialize_with = "option_decimal")]
239 pub usd_index_price: Option<Decimal>,
240}
241
242#[derive(Debug, Serialize)]
243#[serde(rename_all = "camelCase")]
244pub struct GetTradesParams {
245 pub category: Category,
246 pub symbol: Option<String>,
249 pub base_coin: Option<String>,
252 pub option_type: Option<u64>,
254 pub limit: Option<u64>,
257}
258
259#[derive(Debug, Deserialize, PartialEq)]
260#[serde(tag = "category")]
261pub enum Trade {
262 #[serde(rename = "inverse")]
263 Inverse { list: Vec<InverseLinearSpotTrade> },
264 #[serde(rename = "linear")]
265 Linear { list: Vec<InverseLinearSpotTrade> },
266 #[serde(rename = "option")]
267 Option { list: Vec<OptionTrade> },
268 #[serde(rename = "spot")]
269 Spot { list: Vec<InverseLinearSpotTrade> },
270}
271
272#[derive(Debug, Deserialize, PartialEq)]
273#[serde(rename_all = "camelCase")]
274pub struct InverseLinearSpotTrade {
275 pub exec_id: String,
277 pub symbol: String,
279 pub price: Decimal,
281 pub size: Decimal,
283 pub side: Side,
285 #[serde(deserialize_with = "number")]
287 pub time: Timestamp,
288 pub is_block_trade: bool,
290 #[serde(rename = "isRPITrade")]
292 pub is_rpi_trade: bool,
293}
294
295#[derive(Debug, Deserialize, PartialEq)]
296#[serde(rename_all = "camelCase")]
297pub struct OptionTrade {
298 pub exec_id: String,
300 pub symbol: String,
302 pub price: Decimal,
304 pub size: Decimal,
306 pub side: Side,
308 #[serde(deserialize_with = "number")]
310 pub time: Timestamp,
311 pub is_block_trade: bool,
313 #[serde(rename = "isRPITrade")]
315 pub is_rpi_trade: bool,
316 #[serde(rename = "mP")]
318 pub mark_price: Decimal,
319 #[serde(rename = "iP")]
321 pub index_price: Decimal,
322 #[serde(rename = "mIv")]
324 pub mark_iv: Decimal,
325 #[serde(rename = "iv")]
327 pub iv: Decimal,
328}
329
330#[derive(Debug, Deserialize, PartialEq)]
331#[serde(rename_all = "camelCase")]
332pub struct ServerTime {
333 #[serde(deserialize_with = "number")]
335 pub time_second: u64,
336 #[serde(deserialize_with = "number")]
338 pub time_nano: u64,
339}
340
341#[derive(Debug, Serialize)]
342pub struct GetInstrumentsInfoParams {
343 pub category: Category,
344 pub symbol: Option<String>,
345 pub status: Option<Status>,
346 pub base_coin: Option<String>,
347 pub limit: Option<i64>,
348 pub cursor: Option<String>,
349}
350
351#[derive(Debug, Deserialize, PartialEq)]
352#[serde(tag = "category")]
353pub enum InstrumentsInfo {
354 #[serde(rename = "inverse", rename_all = "camelCase")]
355 Inverse {
356 next_page_cursor: String,
357 list: Vec<InverseLinearInstrumentsInfo>,
358 },
359 #[serde(rename = "linear", rename_all = "camelCase")]
360 Linear {
361 next_page_cursor: String,
362 list: Vec<InverseLinearInstrumentsInfo>,
363 },
364 #[serde(rename = "option", rename_all = "camelCase")]
365 Option {
366 next_page_cursor: String,
367 list: Vec<OptionInstrumentsInfo>,
368 },
369 #[serde(rename = "spot", rename_all = "camelCase")]
370 Spot {
371 #[serde(default, deserialize_with = "empty_string_as_none")]
372 next_page_cursor: Option<String>,
373 list: Vec<SpotInstrumentsInfo>,
374 },
375}
376
377#[derive(Debug, Deserialize, PartialEq)]
378#[serde(rename_all = "camelCase")]
379pub struct InverseLinearInstrumentsInfo {
380 pub symbol: String,
381 pub contract_type: ContractType,
382 pub status: Status,
383 pub base_coin: String,
384 pub quote_coin: String,
385 #[serde(deserialize_with = "number")]
386 pub launch_time: Timestamp,
387 #[serde(deserialize_with = "number")]
388 pub delivery_time: Timestamp,
389 #[serde(deserialize_with = "option_decimal")]
390 pub delivery_fee_rate: Option<Decimal>,
391 #[serde(deserialize_with = "number")]
392 pub price_scale: i64,
393 pub leverage_filter: LeverageFilter,
394 pub price_filter: PriceFilter,
395 pub lot_size_filter: LotSizeFilter,
396 pub unified_margin_trade: bool,
397 pub funding_interval: i64,
398 pub settle_coin: String,
399 pub copy_trading: CopyTrading,
400 pub upper_funding_rate: Decimal,
401 pub lower_funding_rate: Decimal,
402 pub risk_parameters: RiskParameters,
403 pub is_pre_listing: bool,
404 pub pre_listing_info: Option<PreListingInfo>,
405}
406
407#[derive(Debug, Deserialize, PartialEq)]
408#[serde(rename_all = "camelCase")]
409pub struct OptionInstrumentsInfo {
410 pub symbol: String,
411 pub contract_type: ContractType,
412 pub status: Status,
413 pub base_coin: String,
414 pub quote_coin: String,
415 #[serde(deserialize_with = "number")]
416 pub launch_time: i64,
417 #[serde(deserialize_with = "number")]
418 pub delivery_time: i64,
419 #[serde(deserialize_with = "option_decimal")]
420 pub delivery_fee_rate: Option<Decimal>,
421 #[serde(deserialize_with = "number")]
422 pub price_scale: i64,
423 pub leverage_filter: LeverageFilter,
424 pub price_filter: PriceFilter,
425 pub lot_size_filter: LotSizeFilter,
426 pub unified_margin_trade: bool,
427 pub funding_interval: i64,
428 pub settle_coin: String,
429 pub copy_trading: CopyTrading,
430 pub upper_funding_rate: Decimal,
431 pub lower_funding_rate: Decimal,
432 pub risk_parameters: RiskParameters,
433 pub is_pre_listing: bool,
434 pub pre_listing_info: Option<PreListingInfo>,
435}
436
437#[derive(Debug, Deserialize, PartialEq)]
438#[serde(rename_all = "camelCase")]
439pub struct SpotInstrumentsInfo {
440 pub symbol: String,
442 pub base_coin: String,
444 pub quote_coin: String,
446 #[serde(deserialize_with = "string_to_bool")]
448 pub innovation: bool,
449 pub status: Status,
451 pub margin_trading: String,
455 #[serde(deserialize_with = "string_to_bool")]
457 pub st_tag: bool,
458 pub lot_size_filter: SpotLotSizeFilter,
460 pub price_filter: SpotPriceFilter,
462 pub risk_parameters: RiskParameters,
464}
465
466#[derive(Debug, Deserialize, PartialEq)]
467#[serde(rename_all = "camelCase")]
468pub struct LeverageFilter {
469 pub min_leverage: Decimal,
470 pub max_leverage: Decimal,
471 pub leverage_step: Decimal,
472}
473
474#[derive(Debug, Deserialize, PartialEq)]
475#[serde(rename_all = "camelCase")]
476pub struct PriceFilter {
477 pub min_price: Decimal,
478 pub max_price: Decimal,
479 pub tick_size: Decimal,
480}
481
482#[derive(Debug, Deserialize, PartialEq)]
483#[serde(rename_all = "camelCase")]
484pub struct SpotPriceFilter {
485 pub tick_size: Decimal,
487}
488
489#[derive(Debug, Deserialize, PartialEq)]
490#[serde(rename_all = "camelCase")]
491pub struct LotSizeFilter {
492 pub min_notional_value: Decimal,
493 pub max_order_qty: Decimal,
494 pub max_mkt_order_qty: Decimal,
495 pub min_order_qty: Decimal,
496 pub qty_step: Decimal,
497 pub post_only_max_order_qty: Decimal,
498}
499
500#[derive(Debug, Deserialize, PartialEq)]
501#[serde(rename_all = "camelCase")]
502pub struct SpotLotSizeFilter {
503 pub base_precision: Decimal,
505 pub quote_precision: Decimal,
507 pub min_order_qty: Decimal,
509 pub max_order_qty: Decimal,
511 pub min_order_amt: Decimal,
513 pub max_order_amt: Decimal,
515}
516
517#[derive(Debug, Deserialize, PartialEq)]
518#[serde(rename_all = "camelCase")]
519pub struct RiskParameters {
520 pub price_limit_ratio_x: Decimal,
521 pub price_limit_ratio_y: Decimal,
522}
523
524#[derive(Debug, Deserialize, PartialEq)]
525#[serde(rename_all = "camelCase")]
526pub struct PreListingInfo {
527 pub cur_auction_phase: CurAuctionPhase,
528 pub phases: Vec<Phase>,
529 pub auction_fee_info: AuctionFeeInfo,
530}
531
532#[derive(Debug, Deserialize, PartialEq)]
533#[serde(rename_all = "camelCase")]
534pub struct Phase {
535 pub phase: CurAuctionPhase,
536 #[serde(deserialize_with = "option_number")]
537 pub start_time: Option<Timestamp>,
538 #[serde(deserialize_with = "option_number")]
539 pub end_time: Option<Timestamp>,
540}
541
542#[derive(Debug, Deserialize, PartialEq)]
543#[serde(rename_all = "camelCase")]
544pub struct AuctionFeeInfo {
545 pub auction_fee_rate: Decimal,
546 pub taker_fee_rate: Decimal,
547 pub maker_fee_rate: Decimal,
548}