1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
mod okx_v3;
mod okx_v5;

use crypto_message::{BboMsg, CandlestickMsg};
use simple_error::SimpleError;
use std::collections::HashMap;

use crate::{FundingRateMsg, OrderBookMsg, TradeMsg};
use crypto_market_type::MarketType;
use crypto_msg_type::MessageType;
use serde_json::Value;

pub(super) const EXCHANGE_NAME: &str = "okx";

pub(crate) fn extract_symbol(_market_type: MarketType, msg: &str) -> Result<String, SimpleError> {
    let obj = serde_json::from_str::<HashMap<String, Value>>(msg).map_err(SimpleError::from)?;
    if obj.contains_key("arg") && obj.contains_key("data") {
        okx_v5::extract_symbol(msg)
    } else if obj.contains_key("table") && obj.contains_key("data") {
        okx_v3::extract_symbol(msg)
    } else if obj.contains_key("code") && obj.contains_key("msg") && obj.contains_key("data") {
        // restful v5
        okx_v5::extract_symbol(msg)
    } else {
        // restful v3
        okx_v3::extract_symbol(msg)
    }
}

pub(crate) fn extract_timestamp(
    _market_type: MarketType,
    msg: &str,
) -> Result<Option<i64>, SimpleError> {
    let obj = serde_json::from_str::<HashMap<String, Value>>(msg).map_err(SimpleError::from)?;
    if obj.contains_key("arg") && obj.contains_key("data") {
        // websocket v5
        okx_v5::extract_timestamp(msg)
    } else if obj.contains_key("table") && obj.contains_key("data") {
        // websocket v3
        okx_v3::extract_timestamp(msg)
    } else if obj.contains_key("code") && obj.contains_key("msg") && obj.contains_key("data") {
        // restful v5
        okx_v5::extract_timestamp(msg)
    } else {
        // restful v3
        okx_v3::extract_timestamp(msg)
    }
}

pub(crate) fn get_msg_type(msg: &str) -> MessageType {
    let obj =
        serde_json::from_str::<HashMap<String, Value>>(msg).map_err(SimpleError::from).unwrap();
    if obj.contains_key("arg") && obj.contains_key("data") {
        // websocket v5
        okx_v5::get_msg_type(msg)
    } else if obj.contains_key("table") && obj.contains_key("data") {
        // websocket v3
        okx_v3::get_msg_type(msg)
    } else if obj.contains_key("code") && obj.contains_key("msg") && obj.contains_key("data") {
        // restful v5
        okx_v5::get_msg_type(msg)
    } else {
        // restful v3
        okx_v3::get_msg_type(msg)
    }
}

pub(crate) fn parse_trade(
    market_type: MarketType,
    msg: &str,
) -> Result<Vec<TradeMsg>, SimpleError> {
    let obj =
        serde_json::from_str::<HashMap<String, Value>>(msg).map_err(SimpleError::from).unwrap();
    if obj.contains_key("arg") && obj.contains_key("data") {
        okx_v5::parse_trade(market_type, msg)
    } else if obj.contains_key("table") && obj.contains_key("data") {
        okx_v3::parse_trade(market_type, msg)
    } else {
        panic!("Unknown msg format {msg}")
    }
}

pub(crate) fn parse_l2(
    market_type: MarketType,
    msg: &str,
) -> Result<Vec<OrderBookMsg>, SimpleError> {
    let obj =
        serde_json::from_str::<HashMap<String, Value>>(msg).map_err(SimpleError::from).unwrap();
    if obj.contains_key("arg") && obj.contains_key("data") {
        okx_v5::parse_l2(market_type, msg)
    } else if obj.contains_key("table") && obj.contains_key("data") {
        okx_v3::parse_l2(market_type, msg)
    } else {
        panic!("Unknown msg format {msg}")
    }
}

pub(crate) fn parse_l2_topk(
    market_type: MarketType,
    msg: &str,
) -> Result<Vec<OrderBookMsg>, SimpleError> {
    parse_l2(market_type, msg)
}

pub(crate) fn parse_funding_rate(
    market_type: MarketType,
    msg: &str,
    received_at: i64,
) -> Result<Vec<FundingRateMsg>, SimpleError> {
    let obj = serde_json::from_str::<HashMap<String, Value>>(msg).map_err(SimpleError::from)?;
    if obj.contains_key("arg") && obj.contains_key("data") {
        okx_v5::parse_funding_rate(market_type, msg, received_at)
    } else if obj.contains_key("table") && obj.contains_key("data") {
        okx_v3::parse_funding_rate(market_type, msg, received_at)
    } else {
        panic!("Unknown msg format {msg}")
    }
}

pub(crate) fn parse_bbo(market_type: MarketType, msg: &str) -> Result<Vec<BboMsg>, SimpleError> {
    let obj = serde_json::from_str::<HashMap<String, Value>>(msg).map_err(SimpleError::from)?;
    if obj.contains_key("arg") && obj.contains_key("data") {
        okx_v5::parse_bbo(market_type, msg)
    } else if obj.contains_key("table") && obj.contains_key("data") {
        okx_v3::parse_bbo(market_type, msg)
    } else {
        panic!("Unknown msg format {msg}")
    }
}

pub(crate) fn parse_candlestick(
    market_type: MarketType,
    msg: &str,
    received_at: i64,
) -> Result<Vec<CandlestickMsg>, SimpleError> {
    let obj = serde_json::from_str::<HashMap<String, Value>>(msg).map_err(SimpleError::from)?;
    if obj.contains_key("arg") && obj.contains_key("data") {
        okx_v5::parse_candlestick(market_type, msg, received_at)
    } else if obj.contains_key("table") && obj.contains_key("data") {
        okx_v3::parse_candlestick(market_type, msg)
    } else {
        panic!("Unknown msg format {msg}")
    }
}