use super::*; #[derive(Debug, PartialEq, Clone, Copy)] pub struct FeeRate(f64); impl FromStr for FeeRate { type Err = Error; fn from_str(s: &str) -> Result { Self::try_from(f64::from_str(s)?) } } impl TryFrom for FeeRate { type Error = Error; fn try_from(rate: f64) -> Result { if rate.is_sign_negative() | rate.is_nan() | rate.is_infinite() { bail!("invalid fee rate: {rate}") } Ok(Self(rate)) } } impl FeeRate { pub fn fee(&self, vsize: usize) -> Amount { #[allow(clippy::cast_possible_truncation)] #[allow(clippy::cast_sign_loss)] Amount::from_sat((self.0 * vsize as f64).round() as u64) } pub(crate) fn n(&self) -> f64 { self.0 } } #[cfg(test)] mod tests { use super::*; #[test] fn parse() { assert_eq!("1.1".parse::().unwrap().0, 1.1); assert_eq!("11.19".parse::().unwrap().0, 11.19); assert_eq!("11.1111".parse::().unwrap().0, 11.1111); assert!("-4.2".parse::().is_err());