lnm_sdk/api_v3/rest/models/
cross_leverage.rs1use std::{convert::TryFrom, fmt};
2
3use serde::{Deserialize, Serialize, de};
4
5use crate::shared::models::{
6 SATS_PER_BTC, leverage::Leverage, margin::Margin, price::Price, quantity::Quantity,
7};
8
9use super::error::CrossLeverageValidationError;
10
11#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
37pub struct CrossLeverage(u64);
38
39impl CrossLeverage {
40 pub const MIN: Self = Self(1);
42
43 pub const MAX: Self = Self(100);
45
46 pub fn bounded<T>(value: T) -> Self
73 where
74 T: Into<f64>,
75 {
76 let as_f64: f64 = value.into();
77 let rounded = as_f64.round().max(0.0) as u64;
78 let clamped = rounded.clamp(Self::MIN.0, Self::MAX.0);
79
80 Self(clamped)
81 }
82
83 pub fn as_u64(&self) -> u64 {
94 self.0
95 }
96
97 pub fn try_calculate_rounded(
115 quantity: Quantity,
116 margin: Margin,
117 price: Price,
118 ) -> Result<Self, CrossLeverageValidationError> {
119 let leverage_value = quantity.as_f64() * SATS_PER_BTC / (margin.as_f64() * price.as_f64());
120
121 Self::try_from(leverage_value.round())
122 }
123}
124
125impl From<CrossLeverage> for u64 {
126 fn from(value: CrossLeverage) -> u64 {
127 value.0
128 }
129}
130
131impl From<CrossLeverage> for Leverage {
132 fn from(value: CrossLeverage) -> Leverage {
133 Leverage::try_from(value.0 as f64).expect("Must be a valid `Leverage`")
134 }
135}
136
137impl TryFrom<u64> for CrossLeverage {
138 type Error = CrossLeverageValidationError;
139
140 fn try_from(value: u64) -> Result<Self, Self::Error> {
141 if value < Self::MIN.0 {
142 return Err(CrossLeverageValidationError::TooLow { value });
143 }
144
145 if value > Self::MAX.0 {
146 return Err(CrossLeverageValidationError::TooHigh { value });
147 }
148
149 Ok(CrossLeverage(value))
150 }
151}
152
153impl TryFrom<u8> for CrossLeverage {
154 type Error = CrossLeverageValidationError;
155
156 fn try_from(value: u8) -> Result<Self, Self::Error> {
157 Self::try_from(value as u64)
158 }
159}
160
161impl TryFrom<u16> for CrossLeverage {
162 type Error = CrossLeverageValidationError;
163
164 fn try_from(value: u16) -> Result<Self, Self::Error> {
165 Self::try_from(value as u64)
166 }
167}
168
169impl TryFrom<u32> for CrossLeverage {
170 type Error = CrossLeverageValidationError;
171
172 fn try_from(value: u32) -> Result<Self, Self::Error> {
173 Self::try_from(value as u64)
174 }
175}
176
177impl TryFrom<i8> for CrossLeverage {
178 type Error = CrossLeverageValidationError;
179
180 fn try_from(value: i8) -> Result<Self, Self::Error> {
181 Self::try_from(value.max(0) as u64)
182 }
183}
184
185impl TryFrom<i16> for CrossLeverage {
186 type Error = CrossLeverageValidationError;
187
188 fn try_from(value: i16) -> Result<Self, Self::Error> {
189 Self::try_from(value.max(0) as u64)
190 }
191}
192
193impl TryFrom<i32> for CrossLeverage {
194 type Error = CrossLeverageValidationError;
195
196 fn try_from(value: i32) -> Result<Self, Self::Error> {
197 Self::try_from(value.max(0) as u64)
198 }
199}
200
201impl TryFrom<i64> for CrossLeverage {
202 type Error = CrossLeverageValidationError;
203
204 fn try_from(value: i64) -> Result<Self, Self::Error> {
205 Self::try_from(value.max(0) as u64)
206 }
207}
208
209impl TryFrom<usize> for CrossLeverage {
210 type Error = CrossLeverageValidationError;
211
212 fn try_from(value: usize) -> Result<Self, Self::Error> {
213 Self::try_from(value as u64)
214 }
215}
216
217impl TryFrom<isize> for CrossLeverage {
218 type Error = CrossLeverageValidationError;
219
220 fn try_from(value: isize) -> Result<Self, Self::Error> {
221 Self::try_from(value.max(0) as u64)
222 }
223}
224
225impl TryFrom<f32> for CrossLeverage {
226 type Error = CrossLeverageValidationError;
227
228 fn try_from(value: f32) -> Result<Self, Self::Error> {
229 Self::try_from(value as f64)
230 }
231}
232
233impl TryFrom<f64> for CrossLeverage {
234 type Error = CrossLeverageValidationError;
235
236 fn try_from(value: f64) -> Result<Self, Self::Error> {
237 if value.fract() != 0.0 {
238 return Err(CrossLeverageValidationError::NotAnInteger { value });
239 }
240
241 Self::try_from(value.max(0.) as u64)
242 }
243}
244
245impl fmt::Display for CrossLeverage {
246 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
247 self.0.fmt(f)
248 }
249}
250
251impl Serialize for CrossLeverage {
252 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
253 where
254 S: serde::Serializer,
255 {
256 serializer.serialize_u64(self.0)
257 }
258}
259
260impl<'de> Deserialize<'de> for CrossLeverage {
261 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
262 where
263 D: serde::Deserializer<'de>,
264 {
265 let leverage_u64 = u64::deserialize(deserializer)?;
266 CrossLeverage::try_from(leverage_u64).map_err(|e| de::Error::custom(e.to_string()))
267 }
268}