df_hyperliquid_core/deploy/outcomes/actions/
bounded.rs1use std::{fmt, str::FromStr};
5
6use crate::deploy::outcomes::actions::error::DeployError;
7use crate::utils::Dec;
8
9fn bounded(text: &str, most: Dec) -> Option<Dec> {
12 let text = text.trim();
13 if text.starts_with(['+', '-']) {
14 return None;
15 }
16 let value = Dec::parse(text).ok()?;
17 (!value.is_negative() && value <= most).then_some(value)
18}
19
20#[derive(Debug, Clone, Copy, PartialEq, Eq)]
25pub struct FeeScale(Dec);
26
27impl FeeScale {
28 pub const ZERO: FeeScale = FeeScale(Dec::ZERO);
29 pub const ONE: FeeScale = FeeScale(Dec::ONE);
30
31 #[must_use]
32 pub const fn value(self) -> Dec {
33 self.0
34 }
35
36 #[must_use]
38 pub fn to_wire(self) -> String {
39 self.0.to_wire()
40 }
41}
42
43impl FromStr for FeeScale {
44 type Err = DeployError;
45
46 fn from_str(text: &str) -> Result<Self, Self::Err> {
49 bounded(text, Dec::from_int(10)).map(FeeScale).ok_or_else(|| DeployError::FeeScale(text.trim().to_owned()))
50 }
51}
52
53impl fmt::Display for FeeScale {
54 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
55 write!(f, "{}", self.0)
56 }
57}
58
59#[derive(Debug, Clone, Copy, PartialEq, Eq)]
63pub struct Fraction(Dec);
64
65impl Fraction {
66 pub const ZERO: Fraction = Fraction(Dec::ZERO);
67 pub const ONE: Fraction = Fraction(Dec::ONE);
68
69 #[must_use]
70 pub const fn value(self) -> Dec {
71 self.0
72 }
73
74 #[must_use]
75 pub fn to_wire(self) -> String {
76 self.0.to_wire()
77 }
78
79 #[must_use]
81 pub fn is_whole(self) -> bool {
82 self == Fraction::ZERO || self == Fraction::ONE
83 }
84}
85
86impl FromStr for Fraction {
87 type Err = DeployError;
88
89 fn from_str(text: &str) -> Result<Self, Self::Err> {
91 bounded(text, Dec::ONE).map(Fraction).ok_or_else(|| DeployError::Fraction(text.trim().to_owned()))
92 }
93}
94
95impl fmt::Display for Fraction {
96 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
97 write!(f, "{}", self.0)
98 }
99}
100
101#[cfg(test)]
102#[path = "tests/bounded.rs"]
103mod tests;