use std::{fmt::Display, str::FromStr};
use postgres_types::{FromSql, ToSql};
use serde::{Deserialize, Serialize};
use thiserror::Error;
use utoipa::ToSchema;
#[derive(Serialize, Deserialize, Debug, Clone, Copy, Hash, PartialEq, Eq, ToSchema)]
#[serde(rename_all = "kebab-case")]
pub enum Amm {
UniswapV3,
AlgebraIntegral,
Croc,
Curve,
Carbon,
Nuri,
Velodrome,
}
#[derive(Error, Debug)]
pub enum AmmFromStringError {
#[error("String {0} cannot be converted to a valid AMM")]
Invalid(String),
}
impl FromStr for Amm {
type Err = AmmFromStringError;
fn from_str(value: &str) -> Result<Self, Self::Err> {
match value {
"uniswap-v3" => Ok(Self::UniswapV3),
"algebra-integral" => Ok(Self::AlgebraIntegral),
"croc" => Ok(Self::Croc),
"curve" => Ok(Self::Curve),
"carbon" => Ok(Self::Carbon),
"nuri" => Ok(Self::Nuri),
"velodrome" => Ok(Self::Velodrome),
_ => Err(AmmFromStringError::Invalid(value.to_string())),
}
}
}
impl Display for Amm {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Amm::UniswapV3 => write!(f, "uniswap-v3"),
Amm::AlgebraIntegral => write!(f, "algebra-integral"),
Amm::Croc => write!(f, "croc"),
Amm::Curve => write!(f, "curve"),
Amm::Carbon => write!(f, "carbon"),
Amm::Nuri => write!(f, "nuri"),
Amm::Velodrome => write!(f, "velodrome"),
}
}
}
impl<'a> FromSql<'a> for Amm {
fn from_sql(
ty: &postgres_types::Type,
raw: &'a [u8],
) -> Result<Self, Box<dyn std::error::Error + Sync + Send>> {
Ok(<String as FromSql>::from_sql(ty, raw)?.parse()?)
}
postgres_types::accepts!(VARCHAR);
}
impl ToSql for Amm {
fn to_sql(
&self,
ty: &postgres_types::Type,
out: &mut alloy::primitives::bytes::BytesMut,
) -> Result<postgres_types::IsNull, Box<dyn std::error::Error + Sync + Send>>
where
Self: Sized,
{
self.to_string().to_sql(ty, out)
}
postgres_types::accepts!(VARCHAR);
postgres_types::to_sql_checked!();
}