use crate::{
domain::book::MarketId,
fuel_types::Bytes32,
parse::HexDisplayFromStr,
};
use serde::{
Deserialize,
Serialize,
};
use serde_with::{
DisplayFromStr,
serde_as,
};
use std::{
fmt::Display,
str::FromStr,
};
#[derive(
Debug,
Clone,
Copy,
PartialEq,
Eq,
strum_macros::EnumCount,
enum_iterator::Sequence,
serde::Serialize,
Hash,
)]
pub enum BarResolution {
Second,
OneMinute,
TwoMinutes,
ThreeMinutes,
FiveMinutes,
FifteenMinutes,
ThirtyMinutes,
OneHour,
TwoHours,
FourHours,
SixHours,
EightHours,
TwelveHours,
OneDay,
ThreeDays,
OneWeek,
OneMonth,
ThreeMonths,
}
impl Display for BarResolution {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
BarResolution::Second => write!(f, "1s"),
BarResolution::OneMinute => write!(f, "1m"),
BarResolution::TwoMinutes => write!(f, "2m"),
BarResolution::ThreeMinutes => write!(f, "3m"),
BarResolution::FiveMinutes => write!(f, "5m"),
BarResolution::FifteenMinutes => write!(f, "15m"),
BarResolution::ThirtyMinutes => write!(f, "30m"),
BarResolution::OneHour => write!(f, "1h"),
BarResolution::TwoHours => write!(f, "2h"),
BarResolution::FourHours => write!(f, "4h"),
BarResolution::SixHours => write!(f, "6h"),
BarResolution::EightHours => write!(f, "8h"),
BarResolution::TwelveHours => write!(f, "12h"),
BarResolution::OneDay => write!(f, "1d"),
BarResolution::ThreeDays => write!(f, "3d"),
BarResolution::OneWeek => write!(f, "1w"),
BarResolution::OneMonth => write!(f, "1M"),
BarResolution::ThreeMonths => write!(f, "3M"),
}
}
}
impl BarResolution {
pub fn as_millis(&self) -> u128 {
match self {
BarResolution::Second => 1_000,
BarResolution::OneMinute => 60_000,
BarResolution::TwoMinutes => 120_000,
BarResolution::ThreeMinutes => 180_000,
BarResolution::FiveMinutes => 300_000,
BarResolution::FifteenMinutes => 900_000,
BarResolution::ThirtyMinutes => 1_800_000,
BarResolution::OneHour => 3_600_000,
BarResolution::TwoHours => 7_200_000,
BarResolution::FourHours => 14_400_000,
BarResolution::SixHours => 21_600_000,
BarResolution::EightHours => 28_800_000,
BarResolution::TwelveHours => 43_200_000,
BarResolution::OneDay => 86_400_000,
BarResolution::ThreeDays => 259_200_000,
BarResolution::OneWeek => 604_800_000,
BarResolution::OneMonth => 2_629_746_000,
BarResolution::ThreeMonths => 7_889_472_000,
}
}
}
impl FromStr for BarResolution {
type Err = anyhow::Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"1s" => Ok(BarResolution::Second),
"1m" => Ok(BarResolution::OneMinute),
"2m" => Ok(BarResolution::TwoMinutes),
"3m" => Ok(BarResolution::ThreeMinutes),
"5m" => Ok(BarResolution::FiveMinutes),
"15m" => Ok(BarResolution::FifteenMinutes),
"30m" => Ok(BarResolution::ThirtyMinutes),
"1h" => Ok(BarResolution::OneHour),
"2h" => Ok(BarResolution::TwoHours),
"4h" => Ok(BarResolution::FourHours),
"6h" => Ok(BarResolution::SixHours),
"8h" => Ok(BarResolution::EightHours),
"12h" => Ok(BarResolution::TwelveHours),
"1d" => Ok(BarResolution::OneDay),
"3d" => Ok(BarResolution::ThreeDays),
"1w" => Ok(BarResolution::OneWeek),
"1M" => Ok(BarResolution::OneMonth),
"3M" => Ok(BarResolution::ThreeMonths),
s => Err(anyhow::anyhow!("Invalid bar resolution: {s}")),
}
}
}
#[serde_as]
#[derive(Serialize, Deserialize, Debug)]
pub struct GetBarsParams {
#[serde_as(as = "HexDisplayFromStr")]
pub market_id: MarketId,
#[serde_as(as = "DisplayFromStr")]
pub from: u128,
#[serde_as(as = "DisplayFromStr")]
pub to: u128,
pub count_back: Option<usize>,
#[serde_as(as = "DisplayFromStr")]
pub resolution: BarResolution,
}
#[serde_as]
#[derive(serde::Serialize, serde::Deserialize, Copy, Clone, Debug, PartialEq, Eq)]
pub struct BarResponse {
#[serde_as(as = "DisplayFromStr")]
pub open: u64,
#[serde_as(as = "DisplayFromStr")]
pub close: u64,
#[serde_as(as = "DisplayFromStr")]
pub high: u64,
#[serde_as(as = "DisplayFromStr")]
pub low: u64,
#[serde_as(as = "DisplayFromStr")]
pub buy_volume: u128,
#[serde_as(as = "DisplayFromStr")]
pub sell_volume: u128,
pub timestamp: u128,
}
#[serde_as]
#[derive(serde::Serialize, serde::Deserialize, Debug)]
pub struct GetBarsResponse {
pub action: String,
pub bars: Vec<BarResponse>,
#[serde_as(as = "HexDisplayFromStr")]
pub market_id: Bytes32,
}
#[derive(
Clone, Copy, Debug, PartialEq, Eq, strum_macros::EnumCount, enum_iterator::Sequence,
)]
pub enum SubscriptionFrequency {
HundredMillis,
FiveHundredMillis,
OneSecond,
ThreeSecond,
}
impl Display for SubscriptionFrequency {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
SubscriptionFrequency::HundredMillis => write!(f, "100ms"),
SubscriptionFrequency::FiveHundredMillis => write!(f, "500ms"),
SubscriptionFrequency::OneSecond => write!(f, "1s"),
SubscriptionFrequency::ThreeSecond => write!(f, "3s"),
}
}
}
impl FromStr for SubscriptionFrequency {
type Err = anyhow::Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"100ms" => Ok(SubscriptionFrequency::HundredMillis),
"500ms" => Ok(SubscriptionFrequency::FiveHundredMillis),
"1s" => Ok(SubscriptionFrequency::OneSecond),
"3s" => Ok(SubscriptionFrequency::ThreeSecond),
s => Err(anyhow::anyhow!("Invalid subscription frequency: {s}")),
}
}
}