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