crypto_pair/exchanges/
bitget.rs

1use crypto_market_type::MarketType;
2
3pub(crate) fn normalize_pair(symbol: &str) -> Option<String> {
4    if symbol.ends_with("_SPBL")
5        || symbol.contains("_UMCBL")
6        || symbol.contains("_CMCBL")
7        || symbol.contains("_DMCBL")
8    {
9        let pos = symbol.find('_').unwrap();
10        let pair = &symbol[..pos];
11        if symbol == "SBTCSUSDT_SPBL" {
12            Some("SBTC/SUSDT".to_string())
13        } else if symbol.ends_with("PERP_CMCBL") {
14            Some(format!("{}/USDC", symbol.strip_suffix("PERP_CMCBL").unwrap()))
15        } else if pair.ends_with("USDT") {
16            Some(format!("{}/USDT", pair.strip_suffix("USDT").unwrap()))
17        } else if pair.ends_with("USD") {
18            Some(format!("{}/USD", pair.strip_suffix("USD").unwrap()))
19        } else if pair.ends_with("ETH") {
20            Some(format!("{}/ETH", pair.strip_suffix("ETH").unwrap()))
21        } else if pair.ends_with("BTC") {
22            Some(format!("{}/BTC", pair.strip_suffix("BTC").unwrap()))
23        } else {
24            panic!("Failed to parse {symbol}");
25        }
26    } else {
27        #[allow(clippy::collapsible_else_if)]
28        if symbol.starts_with("cmt_") {
29            // linear swap
30            assert!(symbol.ends_with("usdt"));
31            let base = &symbol[4..symbol.len() - 4];
32            Some(format!("{base}/usdt").to_uppercase())
33        } else if symbol.contains('_') {
34            // spot
35            Some(symbol.replace('_', "/").to_uppercase())
36        } else if symbol.ends_with("usd") {
37            // inverse swap
38            let base = symbol.strip_suffix("usd").unwrap();
39            Some(format!("{base}/usd").to_uppercase())
40        } else {
41            None
42        }
43    }
44}
45
46pub(crate) fn get_market_type(symbol: &str) -> MarketType {
47    if symbol.ends_with("_SPBL")
48        || symbol.contains("_UMCBL")
49        || symbol.contains("_CMCBL")
50        || symbol.contains("_DMCBL")
51    {
52        // bitget v3 API
53        if symbol.ends_with("_SPBL") {
54            MarketType::Spot
55        } else if symbol.ends_with("_UMCBL") || symbol.ends_with("_CMCBL") {
56            MarketType::LinearSwap
57        } else if symbol.ends_with("_DMCBL") {
58            MarketType::InverseSwap
59        } else if symbol.contains("_UMCBL_") | symbol.contains("_CMCBL_") {
60            MarketType::LinearFuture
61        } else if symbol.contains("_DMCBL_") {
62            MarketType::InverseFuture
63        } else {
64            MarketType::Unknown
65        }
66    } else {
67        // deprecated bitget v1 API
68        if symbol.starts_with("cmt_") {
69            MarketType::LinearSwap
70        } else if symbol.contains('_') {
71            MarketType::Spot
72        } else if symbol.ends_with("usd") {
73            MarketType::InverseSwap
74        } else {
75            MarketType::Unknown
76        }
77    }
78}
79
80#[cfg(test)]
81mod tests {
82    use crypto_market_type::MarketType;
83
84    #[test]
85    fn test_get_market_type() {
86        assert_eq!(MarketType::InverseFuture, super::get_market_type("BTCUSD_DMCBL_221230"));
87        assert_eq!(MarketType::LinearSwap, super::get_market_type("BTCPERP_CMCBL"));
88    }
89
90    #[test]
91    fn test_normalize_pair() {
92        assert_eq!("SBTC/SUSDT", super::normalize_pair("SBTCSUSDT_SPBL").unwrap());
93        assert_eq!("EOS/USDT", super::normalize_pair("EOSUSDT_SPBL").unwrap());
94        assert_eq!("BTC/USD", super::normalize_pair("BTCUSD_DMCBL_221230").unwrap());
95        assert_eq!("BTC/USDC", super::normalize_pair("BTCPERP_CMCBL").unwrap());
96    }
97}