use gmsol_utils::{
oracle::PriceProviderKind,
token_config::{FeedConfig, TokenConfig},
};
use indexmap::IndexMap;
use strum::IntoEnumIterator;
use crate::utils::Value;
#[derive(Debug, Clone)]
#[cfg_attr(serde, derive(serde::Serialize, serde::Deserialize))]
pub struct SerdeTokenConfig {
pub name: String,
pub is_enabled: bool,
pub is_synthetic: bool,
pub token_decimals: u8,
pub price_precision: u8,
pub expected_provider: PriceProviderKind,
pub feeds: IndexMap<PriceProviderKind, SerdeFeedConfig>,
pub heartbeat_duration: u32,
}
impl<'a> TryFrom<&'a TokenConfig> for SerdeTokenConfig {
type Error = crate::Error;
fn try_from(config: &'a TokenConfig) -> Result<Self, Self::Error> {
let feeds = PriceProviderKind::iter()
.filter_map(|kind| {
config
.get_feed_config(&kind)
.ok()
.map(|config| (kind, SerdeFeedConfig::from_feed_config(kind, config)))
})
.collect();
Ok(Self {
name: config.name().map_err(crate::Error::custom)?.to_string(),
is_enabled: config.is_enabled(),
is_synthetic: config.is_synthetic(),
token_decimals: config.token_decimals(),
price_precision: config.precision(),
expected_provider: config.expected_provider().map_err(crate::Error::custom)?,
feeds,
heartbeat_duration: config.heartbeat_duration(),
})
}
}
#[derive(Debug, Clone, Copy)]
#[cfg_attr(serde, derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(serde, serde(rename_all = "snake_case"))]
pub enum Encoding {
Hex,
Base58,
}
#[derive(Debug, Clone)]
#[cfg_attr(serde, derive(serde::Serialize, serde::Deserialize))]
pub struct SerdeFeedConfig {
pub feed_id: String,
pub feed_id_encoding: Encoding,
pub timestamp_adjustment: u32,
#[cfg_attr(serde, serde(default))]
pub max_deviation_factor: Option<Value>,
}
impl SerdeFeedConfig {
pub fn from_feed_config(kind: PriceProviderKind, config: &FeedConfig) -> Self {
let max_deviation_factor = config.max_deviation_factor().map(Value::from_u128);
match kind {
PriceProviderKind::Pyth | PriceProviderKind::ChainlinkDataStreams => Self {
feed_id_encoding: Encoding::Hex,
feed_id: format!("0x{}", hex::encode(config.feed())),
timestamp_adjustment: config.timestamp_adjustment(),
max_deviation_factor,
},
_ => Self {
feed_id_encoding: Encoding::Base58,
feed_id: config.feed().to_string(),
timestamp_adjustment: config.timestamp_adjustment(),
max_deviation_factor,
},
}
}
pub fn formatted_feed_id(&self) -> String {
match self.feed_id_encoding {
Encoding::Hex => format!("0x{}", self.feed_id),
Encoding::Base58 => self.feed_id.clone(),
}
}
}