1const MICRO_LAMPORTS_PER_LAMPORT: u64 = 1_000_000;
3
4type MicroLamports = u128;
5
6pub enum PrioritizationFeeType {
7 ComputeUnitPrice(u64),
8 Deprecated(u64),
10}
11
12#[derive(Default, Debug, PartialEq, Eq)]
13pub struct PrioritizationFeeDetails {
14 fee: u64,
15 priority: u64,
16}
17
18impl PrioritizationFeeDetails {
19 pub fn new(fee_type: PrioritizationFeeType, compute_unit_limit: u64) -> Self {
20 match fee_type {
21 PrioritizationFeeType::Deprecated(fee) => {
23 let priority = if compute_unit_limit == 0 {
24 0
25 } else {
26 let micro_lamport_fee: MicroLamports =
27 (fee as u128).saturating_mul(MICRO_LAMPORTS_PER_LAMPORT as u128);
28 let priority = micro_lamport_fee.saturating_div(compute_unit_limit as u128);
29 u64::try_from(priority).unwrap_or(u64::MAX)
30 };
31
32 Self { fee, priority }
33 }
34 PrioritizationFeeType::ComputeUnitPrice(cu_price) => {
35 let fee = {
36 let micro_lamport_fee: MicroLamports =
37 (cu_price as u128).saturating_mul(compute_unit_limit as u128);
38 let fee = micro_lamport_fee
39 .saturating_add(MICRO_LAMPORTS_PER_LAMPORT.saturating_sub(1) as u128)
40 .saturating_div(MICRO_LAMPORTS_PER_LAMPORT as u128);
41 u64::try_from(fee).unwrap_or(u64::MAX)
42 };
43
44 Self {
45 fee,
46 priority: cu_price,
47 }
48 }
49 }
50 }
51
52 pub fn get_fee(&self) -> u64 {
53 self.fee
54 }
55
56 pub fn get_priority(&self) -> u64 {
57 self.priority
58 }
59}
60
61#[cfg(test)]
62mod test {
63 use super::{PrioritizationFeeDetails as FeeDetails, PrioritizationFeeType as FeeType, *};
64
65 #[test]
66 fn test_new_with_no_fee() {
67 for compute_units in [0, 1, MICRO_LAMPORTS_PER_LAMPORT, u64::MAX] {
68 assert_eq!(
69 FeeDetails::new(FeeType::ComputeUnitPrice(0), compute_units),
70 FeeDetails::default(),
71 );
72 assert_eq!(
73 FeeDetails::new(FeeType::Deprecated(0), compute_units),
74 FeeDetails::default(),
75 );
76 }
77 }
78
79 #[test]
80 fn test_new_with_compute_unit_price() {
81 assert_eq!(
82 FeeDetails::new(FeeType::ComputeUnitPrice(MICRO_LAMPORTS_PER_LAMPORT - 1), 1),
83 FeeDetails {
84 fee: 1,
85 priority: MICRO_LAMPORTS_PER_LAMPORT - 1,
86 },
87 "should round up (<1.0) lamport fee to 1 lamport"
88 );
89
90 assert_eq!(
91 FeeDetails::new(FeeType::ComputeUnitPrice(MICRO_LAMPORTS_PER_LAMPORT), 1),
92 FeeDetails {
93 fee: 1,
94 priority: MICRO_LAMPORTS_PER_LAMPORT,
95 },
96 );
97
98 assert_eq!(
99 FeeDetails::new(FeeType::ComputeUnitPrice(MICRO_LAMPORTS_PER_LAMPORT + 1), 1),
100 FeeDetails {
101 fee: 2,
102 priority: MICRO_LAMPORTS_PER_LAMPORT + 1,
103 },
104 "should round up (>1.0) lamport fee to 2 lamports"
105 );
106
107 assert_eq!(
108 FeeDetails::new(FeeType::ComputeUnitPrice(200), 100_000),
109 FeeDetails {
110 fee: 20,
111 priority: 200,
112 },
113 );
114
115 assert_eq!(
116 FeeDetails::new(
117 FeeType::ComputeUnitPrice(MICRO_LAMPORTS_PER_LAMPORT),
118 u64::MAX
119 ),
120 FeeDetails {
121 fee: u64::MAX,
122 priority: MICRO_LAMPORTS_PER_LAMPORT,
123 },
124 );
125
126 assert_eq!(
127 FeeDetails::new(FeeType::ComputeUnitPrice(u64::MAX), u64::MAX),
128 FeeDetails {
129 fee: u64::MAX,
130 priority: u64::MAX,
131 },
132 );
133 }
134
135 #[test]
136 fn test_new_with_deprecated_fee() {
137 assert_eq!(
138 FeeDetails::new(FeeType::Deprecated(1), MICRO_LAMPORTS_PER_LAMPORT / 2 - 1),
139 FeeDetails {
140 fee: 1,
141 priority: 2,
142 },
143 "should round down fee rate of (>2.0) to priority value 1"
144 );
145
146 assert_eq!(
147 FeeDetails::new(FeeType::Deprecated(1), MICRO_LAMPORTS_PER_LAMPORT / 2),
148 FeeDetails {
149 fee: 1,
150 priority: 2,
151 },
152 );
153
154 assert_eq!(
155 FeeDetails::new(FeeType::Deprecated(1), MICRO_LAMPORTS_PER_LAMPORT / 2 + 1),
156 FeeDetails {
157 fee: 1,
158 priority: 1,
159 },
160 "should round down fee rate of (<2.0) to priority value 1"
161 );
162
163 assert_eq!(
164 FeeDetails::new(FeeType::Deprecated(1), MICRO_LAMPORTS_PER_LAMPORT),
165 FeeDetails {
166 fee: 1,
167 priority: 1,
168 },
169 );
170
171 assert_eq!(
172 FeeDetails::new(FeeType::Deprecated(42), 42 * MICRO_LAMPORTS_PER_LAMPORT),
173 FeeDetails {
174 fee: 42,
175 priority: 1,
176 },
177 );
178
179 assert_eq!(
180 FeeDetails::new(FeeType::Deprecated(420), 42 * MICRO_LAMPORTS_PER_LAMPORT),
181 FeeDetails {
182 fee: 420,
183 priority: 10,
184 },
185 );
186
187 assert_eq!(
188 FeeDetails::new(
189 FeeType::Deprecated(u64::MAX),
190 2 * MICRO_LAMPORTS_PER_LAMPORT
191 ),
192 FeeDetails {
193 fee: u64::MAX,
194 priority: u64::MAX / 2,
195 },
196 );
197
198 assert_eq!(
199 FeeDetails::new(FeeType::Deprecated(u64::MAX), u64::MAX),
200 FeeDetails {
201 fee: u64::MAX,
202 priority: MICRO_LAMPORTS_PER_LAMPORT,
203 },
204 );
205 }
206}