use std::collections::HashMap;
use crate::MessageType;
fn msg_type_symbol_to_command(
msg_type: MessageType,
symbol: &str,
subscribe: bool,
configs: Option<&HashMap<String, String>>,
) -> String {
let sub_or_unsub = if subscribe { "subscribe" } else { "unsubscribe" };
match msg_type {
MessageType::Trade | MessageType::Ticker => {
let channel = if msg_type == MessageType::Trade { "trades" } else { "ticker" };
format!(r#"{{"event":"{sub_or_unsub}", "channel":"{channel}", "symbol":"{symbol}"}}"#)
}
MessageType::L2Event => format!(
r#"{{"event":"{sub_or_unsub}", "channel":"book", "symbol":"{symbol}", "prec":"P0", "frec":"F0", "len":25}}"#
),
MessageType::L3Event | MessageType::BBO => format!(
r#"{{"event":"{}", "channel":"book", "symbol": "{}", "prec":"R0", "len": {}}}"#,
sub_or_unsub,
symbol,
if msg_type == MessageType::L3Event { 25 } else { 1 }
),
MessageType::Candlestick => format!(
r#"{{"event":"{}", "channel":"candles", "key":"trade:{}:{}"}}"#,
sub_or_unsub,
configs.unwrap().get("interval").unwrap(),
symbol
),
_ => panic!("Unknown message type {msg_type}"),
}
}
pub(crate) fn get_ws_commands(
msg_types: &[MessageType],
symbols: &[String],
subscribe: bool,
configs: Option<&HashMap<String, String>>,
) -> Vec<String> {
msg_types
.iter()
.flat_map(|msg_type| {
symbols
.iter()
.map(|symbol| msg_type_symbol_to_command(*msg_type, symbol, subscribe, configs))
})
.collect::<Vec<String>>()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn single_msg_type_multiple_symbols() {
let commands = get_ws_commands(
&[MessageType::Trade],
&["tBTCUST".to_string(), "tETHUST".to_string()],
true,
None,
);
assert_eq!(commands.len(), 2);
assert_eq!(r#"{"event":"subscribe", "channel":"trades", "symbol":"tBTCUST"}"#, commands[0]);
assert_eq!(r#"{"event":"subscribe", "channel":"trades", "symbol":"tETHUST"}"#, commands[1]);
}
#[test]
fn multiple_msg_types_single_symbol() {
let commands = get_ws_commands(
&[MessageType::Trade, MessageType::L2Event],
&["tBTCUST".to_string()],
true,
None,
);
assert_eq!(commands.len(), 2);
assert_eq!(r#"{"event":"subscribe", "channel":"trades", "symbol":"tBTCUST"}"#, commands[0]);
assert_eq!(
r#"{"event":"subscribe", "channel":"book", "symbol":"tBTCUST", "prec":"P0", "frec":"F0", "len":25}"#,
commands[1]
);
}
#[test]
fn candlestick() {
let mut configs = HashMap::new();
configs.insert("interval".to_string(), "1m".to_string());
let commands = get_ws_commands(
&[MessageType::Candlestick],
&["tBTCUST".to_string(), "tETHUST".to_string()],
true,
Some(&configs),
);
assert_eq!(commands.len(), 2);
assert_eq!(
r#"{"event":"subscribe", "channel":"candles", "key":"trade:1m:tBTCUST"}"#,
commands[0]
);
assert_eq!(
r#"{"event":"subscribe", "channel":"candles", "key":"trade:1m:tETHUST"}"#,
commands[1]
);
}
}