crypto_markets/exchanges/gate/
gate_swap.rs1use std::collections::HashMap;
2
3use super::super::utils::http_get;
4use crate::{error::Result, Fees, Market, Precision, QuantityLimit};
5
6use crypto_market_type::MarketType;
7use serde::{Deserialize, Serialize};
8use serde_json::Value;
9
10#[derive(Clone, Serialize, Deserialize)]
12#[allow(non_snake_case)]
13struct SwapMarket {
14 name: String,
15 #[serde(rename = "type")]
16 type_: String, quanto_multiplier: String,
18 leverage_min: String,
19 leverage_max: String,
20 maintenance_rate: String,
21 mark_type: String, maker_fee_rate: String,
23 taker_fee_rate: String,
24 order_price_round: String,
25 mark_price_round: String,
26 funding_rate: String,
27 order_size_min: f64,
28 order_size_max: f64,
29 in_delisting: bool,
30 #[serde(flatten)]
31 extra: HashMap<String, Value>,
32}
33
34fn fetch_swap_markets_raw(settle: &str) -> Result<Vec<SwapMarket>> {
36 let txt = http_get(
37 format!("https://api.gateio.ws/api/v4/futures/{settle}/contracts").as_str(),
38 None,
39 )?;
40 let markets = serde_json::from_str::<Vec<SwapMarket>>(&txt)?;
41 Ok(markets.into_iter().filter(|x| !x.in_delisting).collect::<Vec<SwapMarket>>())
42}
43
44pub(super) fn fetch_inverse_swap_symbols() -> Result<Vec<String>> {
45 let symbols =
46 fetch_swap_markets_raw("btc")?.into_iter().map(|m| m.name).collect::<Vec<String>>();
47 Ok(symbols)
48}
49
50pub(super) fn fetch_linear_swap_symbols() -> Result<Vec<String>> {
51 let symbols =
52 fetch_swap_markets_raw("usdt")?.into_iter().map(|m| m.name).collect::<Vec<String>>();
53 Ok(symbols)
54}
55
56fn to_market(raw_market: &SwapMarket) -> Market {
57 let pair = crypto_pair::normalize_pair(&raw_market.name, "gate").unwrap();
58 let (base, quote) = {
59 let v: Vec<&str> = pair.split('/').collect();
60 (v[0].to_string(), v[1].to_string())
61 };
62 let (base_id, quote_id) = {
63 let v: Vec<&str> = raw_market.name.split('_').collect();
64 (v[0].to_string(), v[1].to_string())
65 };
66 let market_type = if raw_market.name.ends_with("_USD") {
67 MarketType::InverseSwap
68 } else if raw_market.name.ends_with("_USDT") {
69 MarketType::LinearSwap
70 } else {
71 panic!("Failed to detect market type for {}", raw_market.name);
72 };
73 let mut quanto_multiplier = raw_market.quanto_multiplier.parse::<f64>().unwrap();
74 if raw_market.name == "BTC_USD" {
75 assert_eq!(quanto_multiplier, 0.0);
76 quanto_multiplier = 1.0;
77 }
78 assert!(quanto_multiplier > 0.0);
79
80 Market {
81 exchange: "gate".to_string(),
82 market_type,
83 symbol: raw_market.name.to_string(),
84 base_id: base_id.clone(),
85 quote_id: quote_id.clone(),
86 settle_id: if market_type == MarketType::InverseSwap {
87 Some(base_id)
88 } else {
89 Some(quote_id)
90 },
91 base: base.clone(),
92 quote: quote.clone(),
93 settle: if market_type == MarketType::InverseSwap { Some(base) } else { Some(quote) },
94 active: !raw_market.in_delisting,
95 margin: true,
96 fees: Fees {
97 maker: raw_market.maker_fee_rate.parse::<f64>().unwrap(),
98 taker: raw_market.taker_fee_rate.parse::<f64>().unwrap(),
99 },
100 precision: Precision {
101 tick_size: raw_market.order_price_round.parse::<f64>().unwrap(),
102 lot_size: quanto_multiplier,
103 },
104 quantity_limit: Some(QuantityLimit {
105 min: Some(raw_market.order_size_min),
106 max: Some(raw_market.order_size_max),
107 notional_min: None,
108 notional_max: None,
109 }),
110 contract_value: Some(quanto_multiplier),
111 delivery_date: None,
112 info: serde_json::to_value(raw_market).unwrap().as_object().unwrap().clone(),
113 }
114}
115
116pub(super) fn fetch_inverse_swap_markets() -> Result<Vec<Market>> {
117 let markets =
118 fetch_swap_markets_raw("btc")?.into_iter().map(|m| to_market(&m)).collect::<Vec<Market>>();
119 Ok(markets)
120}
121
122pub(super) fn fetch_linear_swap_markets() -> Result<Vec<Market>> {
123 let markets =
124 fetch_swap_markets_raw("usdt")?.into_iter().map(|m| to_market(&m)).collect::<Vec<Market>>();
125 Ok(markets)
126}