zebra_rpc/methods/types/
zec.rs1use std::{
7 fmt,
8 hash::{Hash, Hasher},
9 ops,
10 str::FromStr,
11};
12
13use zebra_chain::amount::{self, Amount, Constraint, COIN};
14
15use zebra_node_services::BoxError;
16
17#[allow(unused_imports)]
19use zebra_chain::amount::MAX_MONEY;
20
21pub const MAX_ZEC_FORMAT_PRECISION: usize = 8;
27
28#[derive(Clone, Copy, serde::Serialize, serde::Deserialize, Default)]
41#[serde(try_from = "f64")]
42#[serde(into = "f64")]
43#[serde(bound = "C: Constraint + Clone")]
44pub struct Zec<C: Constraint>(Amount<C>);
45
46impl<C: Constraint> Zec<C> {
47 pub fn lossy_zec(&self) -> f64 {
52 let zats = self.zatoshis();
53 let zats = zats as f64;
56 let coin = COIN as f64;
57
58 zats / coin
61 }
62
63 pub fn from_lossy_zec(lossy_zec: f64) -> Result<Self, BoxError> {
67 let coin = COIN as f64;
69
70 let zats = lossy_zec * coin;
72
73 if zats != zats.trunc() {
74 return Err(
75 "loss of precision parsing ZEC value: floating point had fractional zatoshis"
76 .into(),
77 );
78 }
79
80 let zats = zats as i64;
82 let zats = Amount::try_from(zats)?;
83
84 Ok(Self(zats))
85 }
86}
87
88impl<C: Constraint> From<Zec<C>> for f64 {
90 fn from(zec: Zec<C>) -> f64 {
91 zec.lossy_zec()
92 }
93}
94
95impl<C: Constraint> TryFrom<f64> for Zec<C> {
96 type Error = BoxError;
97
98 fn try_from(value: f64) -> Result<Self, Self::Error> {
99 Self::from_lossy_zec(value)
100 }
101}
102
103impl<C: Constraint> fmt::Display for Zec<C> {
105 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
106 let zec = self.lossy_zec();
107
108 let decimals = f.precision().unwrap_or(MAX_ZEC_FORMAT_PRECISION);
110 let string = format!("{zec:.decimals$}");
111 f.pad_integral(zec >= 0.0, "", &string)
112 }
113}
114
115impl<C: Constraint> FromStr for Zec<C> {
117 type Err = BoxError;
118
119 fn from_str(s: &str) -> Result<Self, Self::Err> {
120 let lossy_zec: f64 = s.parse()?;
121
122 Self::from_lossy_zec(lossy_zec)
123 }
124}
125
126impl<C: Constraint> std::fmt::Debug for Zec<C> {
127 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
128 f.debug_struct(&format!("Zec<{}>", std::any::type_name::<C>()))
129 .field("ZEC", &self.to_string())
130 .field("zat", &self.0)
131 .finish()
132 }
133}
134
135impl<C: Constraint> ops::Deref for Zec<C> {
136 type Target = Amount<C>;
137
138 fn deref(&self) -> &Self::Target {
139 &self.0
140 }
141}
142
143impl<C: Constraint> ops::DerefMut for Zec<C> {
144 fn deref_mut(&mut self) -> &mut Self::Target {
145 &mut self.0
146 }
147}
148
149impl<C: Constraint> From<Amount<C>> for Zec<C> {
150 fn from(amount: Amount<C>) -> Self {
151 Self(amount)
152 }
153}
154
155impl<C: Constraint> From<Zec<C>> for Amount<C> {
156 fn from(zec: Zec<C>) -> Amount<C> {
157 zec.0
158 }
159}
160
161impl<C: Constraint> From<Zec<C>> for i64 {
162 fn from(zec: Zec<C>) -> i64 {
163 zec.0.into()
164 }
165}
166
167impl<C: Constraint> TryFrom<i64> for Zec<C> {
168 type Error = amount::Error;
169
170 fn try_from(value: i64) -> Result<Self, Self::Error> {
171 Ok(Self(Amount::try_from(value)?))
172 }
173}
174
175impl<C: Constraint> Hash for Zec<C> {
176 fn hash<H: Hasher>(&self, state: &mut H) {
178 self.0.hash(state);
179 }
180}
181
182impl<C1: Constraint, C2: Constraint> PartialEq<Zec<C2>> for Zec<C1> {
183 fn eq(&self, other: &Zec<C2>) -> bool {
184 self.0.eq(&other.0)
185 }
186}
187
188impl<C: Constraint> PartialEq<i64> for Zec<C> {
189 fn eq(&self, other: &i64) -> bool {
190 self.0.eq(other)
191 }
192}
193
194impl<C: Constraint> PartialEq<Zec<C>> for i64 {
195 fn eq(&self, other: &Zec<C>) -> bool {
196 self.eq(&other.0)
197 }
198}
199
200impl<C1: Constraint, C2: Constraint> PartialEq<Amount<C2>> for Zec<C1> {
201 fn eq(&self, other: &Amount<C2>) -> bool {
202 self.0.eq(other)
203 }
204}
205
206impl<C1: Constraint, C2: Constraint> PartialEq<Zec<C2>> for Amount<C1> {
207 fn eq(&self, other: &Zec<C2>) -> bool {
208 self.eq(&other.0)
209 }
210}
211
212impl<C: Constraint> Eq for Zec<C> {}