df_hyperliquid_core/trade/builder/
fee.rs1use crate::utils::dec::{Dec, Round};
5use crate::utils::sign::Map;
6use crate::utils::{Address, AssetKind};
7use serde::Deserialize;
8use std::fmt;
9
10#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default, Deserialize)]
12#[serde(transparent)]
13pub struct BuilderFee(u64);
14
15pub const PERP_BUILDER_CAP: BuilderFee = BuilderFee(100);
17
18pub const SPOT_BUILDER_CAP: BuilderFee = BuilderFee(1_000);
20
21pub const OUTCOME_BUILDER_CAP: BuilderFee = SPOT_BUILDER_CAP;
23
24impl BuilderFee {
25 pub const ZERO: BuilderFee = BuilderFee(0);
26
27 #[must_use]
28 pub const fn from_tenths(tenths: u64) -> BuilderFee {
29 BuilderFee(tenths)
30 }
31
32 #[must_use]
33 pub const fn tenths(self) -> u64 {
34 self.0
35 }
36
37 #[must_use]
40 pub fn percent(self) -> String {
41 let figure = Dec::lit::<3>(i128::from(self.0)).to_wire();
42 format!("{figure}%")
43 }
44
45 #[must_use]
48 pub fn from_percent(text: &str) -> Option<BuilderFee> {
49 let digits = text.trim().strip_suffix('%')?;
50 if !digits.bytes().all(|byte| byte.is_ascii_digit() || byte == b'.') {
51 return None;
52 }
53 let figure = Dec::parse(digits).ok()?;
54 if figure.places() > 3 {
55 return None;
56 }
57 u64::try_from(figure.units_at(3, Round::Down)?).ok().map(BuilderFee)
58 }
59}
60
61impl fmt::Display for BuilderFee {
62 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
63 f.write_str(&self.percent())
64 }
65}
66
67#[derive(Debug, Clone, Copy, PartialEq, Eq)]
70pub struct Builder {
71 address: Address,
72 fee: BuilderFee,
73}
74
75impl Builder {
76 #[must_use]
79 pub const fn new(address: Address, fee: BuilderFee) -> Builder {
80 Builder { address, fee }
81 }
82
83 #[must_use]
84 pub const fn address(&self) -> Address {
85 self.address
86 }
87
88 #[must_use]
89 pub const fn fee(&self) -> BuilderFee {
90 self.fee
91 }
92
93 #[must_use]
94 pub fn wire(&self) -> Map {
95 Map::new().put("b", self.address.to_hex()).put("f", self.fee.tenths())
96 }
97}
98
99#[derive(Debug, Clone, Copy, PartialEq, Eq, thiserror::Error)]
101#[error("the builder fee of {} is over the {} {} order allows ({})", .fee.tenths(), .cap.tenths(), .kind.one(), .cap)]
102pub struct OverCap {
103 pub fee: BuilderFee,
104 pub cap: BuilderFee,
105 pub kind: AssetKind,
106}
107
108#[cfg(test)]
109#[path = "tests/fee.rs"]
110mod tests;