use crate::utils::dec::{Dec, Round};
pub const USDC_DECIMALS: u32 = 6;
pub const HYPE_DECIMALS: u32 = 8;
#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
pub enum BadUnits {
#[error("{0} is not a positive amount")]
NotPositive(Dec),
#[error("{value} has more than {places} decimal places")]
TooFine { value: Dec, places: u32 },
#[error("{0} is too large")]
TooLarge(Dec),
}
pub fn exact_units(value: Dec, places: u32) -> Result<u64, BadUnits> {
if value.places() > places {
return Err(BadUnits::TooFine { value, places });
}
cut_units(value, places)
}
pub fn cut_units(value: Dec, places: u32) -> Result<u64, BadUnits> {
if !value.is_positive() {
return Err(BadUnits::NotPositive(value));
}
let units = value.units_at(places, Round::Down).ok_or(BadUnits::TooLarge(value))?;
match u64::try_from(units) {
Ok(0) => Err(BadUnits::NotPositive(value)),
Ok(units) => Ok(units),
Err(_) => Err(BadUnits::TooLarge(value)),
}
}
#[cfg(test)]
#[path = "tests/units.rs"]
mod tests;