use crate::{
clients::wss::WssDecoder,
errors::ExchangeError,
sources::kraken::{
events::KrakenWssEvent,
responses::{
orderbooks::KrakenBookResponse,
trades::KrakenTradeResponse,
},
},
};
use serde_json::Value;
pub struct KrakenDecoder;
impl WssDecoder for KrakenDecoder {
type Event = KrakenWssEvent;
fn decode(text: &str) -> Result<Option<Self::Event>, Box<ExchangeError>> {
let json: Value =
serde_json::from_str(text).map_err(|e| Box::new(ExchangeError::from(e)))?;
if let Some(method) = json.get("method").and_then(|v| v.as_str()) {
let success = json
.get("success")
.and_then(|v| v.as_bool())
.unwrap_or(true);
let channel = json
.get("result")
.and_then(|r| r.get("channel"))
.and_then(|c| c.as_str())
.unwrap_or("unknown");
if success {
tracing::info!(
method = method,
channel = channel,
"kraken.subscription_confirmed"
);
} else {
let error = json
.get("error")
.and_then(|v| v.as_str())
.unwrap_or("unknown error");
tracing::error!(
method = method,
channel = channel,
error = error,
raw = text,
"kraken.subscription_failed"
);
}
return Ok(None);
}
let channel = json
.get("channel")
.and_then(|c| c.as_str())
.unwrap_or("");
match channel {
"book" => {
match serde_json::from_str::<KrakenBookResponse>(text) {
Ok(resp) => Ok(Some(KrakenWssEvent::OrderbookData(resp))),
Err(e) => {
tracing::warn!("Failed to parse Kraken book data: {}", e);
Ok(None)
}
}
}
"trade" => {
match serde_json::from_str::<KrakenTradeResponse>(text) {
Ok(resp) => {
if let Some(trade) = resp.data.into_iter().next() {
return Ok(Some(KrakenWssEvent::TradeData(trade)));
}
Ok(None)
}
Err(e) => {
tracing::warn!("Failed to parse Kraken trade data: {}", e);
Ok(None)
}
}
}
_ => {
tracing::debug!("Kraken: ignoring channel={}", channel);
Ok(None)
}
}
}
}