use serde::Deserialize;
use std::collections::HashMap;
#[derive(Debug, Clone, Deserialize)]
#[serde(bound(deserialize = "T: serde::Deserialize<'de>"))]
pub(crate) struct KrakenEnvelope<T> {
#[serde(default)]
pub error: Vec<String>,
#[serde(default)]
pub result: Option<T>,
}
pub(crate) type TickerResult = HashMap<String, KrakenTicker>;
#[derive(Debug, Clone, Deserialize)]
pub(crate) struct KrakenTicker {
pub c: Vec<String>,
pub v: Vec<String>,
pub l: Vec<String>,
pub h: Vec<String>,
pub o: String,
}
impl KrakenTicker {
pub(crate) fn at(field: &[String], index: usize) -> Option<f64> {
field.get(index)?.parse().ok()
}
}
#[derive(Debug, Clone, PartialEq)]
pub(crate) struct KrakenCandle {
pub time: i64,
pub open: f64,
pub high: f64,
pub low: f64,
pub close: f64,
pub volume: f64,
}
impl<'de> Deserialize<'de> for KrakenCandle {
fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
use serde::de::{self, SeqAccess, Visitor};
struct CandleVisitor;
impl<'de> Visitor<'de> for CandleVisitor {
type Value = KrakenCandle;
fn expecting(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str("a Kraken OHLC array")
}
fn visit_seq<A: SeqAccess<'de>>(self, mut seq: A) -> Result<KrakenCandle, A::Error> {
fn next_num<'de, A: SeqAccess<'de>>(
seq: &mut A,
field: &'static str,
) -> Result<f64, A::Error> {
let raw: String = seq
.next_element()?
.ok_or_else(|| de::Error::missing_field(field))?;
raw.parse().map_err(|_| {
de::Error::invalid_value(de::Unexpected::Str(&raw), &"a decimal string")
})
}
let time: i64 = seq
.next_element()?
.ok_or_else(|| de::Error::missing_field("time"))?;
let open = next_num(&mut seq, "open")?;
let high = next_num(&mut seq, "high")?;
let low = next_num(&mut seq, "low")?;
let close = next_num(&mut seq, "close")?;
let _vwap = next_num(&mut seq, "vwap")?;
let volume = next_num(&mut seq, "volume")?;
while seq.next_element::<de::IgnoredAny>()?.is_some() {}
Ok(KrakenCandle {
time,
open,
high,
low,
close,
volume,
})
}
}
deserializer.deserialize_seq(CandleVisitor)
}
}
#[derive(Debug, Clone, Deserialize)]
#[serde(untagged)]
pub(crate) enum OhlcEntry {
Candles(Vec<KrakenCandle>),
Cursor(serde::de::IgnoredAny),
}
pub(crate) type OhlcResult = HashMap<String, OhlcEntry>;