Skip to main content

solana_validator_optimizer/
priority_fee.rs

1use serde::Serialize;
2
3const MICRO_LAMPORTS_PER_LAMPORT: u64 = 1_000_000;
4
5#[derive(Debug, Clone, Serialize)]
6pub struct PriorityFeeAdvice {
7    pub compute_units: u64,
8    pub micro_lamports_per_compute_unit: u64,
9    pub estimated_priority_fee_lamports: u64,
10    pub estimated_priority_fee_sol: f64,
11    pub risk_level: String,
12    pub recommendation: String,
13}
14
15pub fn advise_priority_fee(
16    compute_units: u64,
17    micro_lamports_per_compute_unit: u64,
18) -> PriorityFeeAdvice {
19    let estimated_priority_fee_lamports =
20        compute_units.saturating_mul(micro_lamports_per_compute_unit) / MICRO_LAMPORTS_PER_LAMPORT;
21
22    let estimated_priority_fee_sol = estimated_priority_fee_lamports as f64 / 1_000_000_000_f64;
23
24    let (risk_level, recommendation) = classify_fee(
25        compute_units,
26        micro_lamports_per_compute_unit,
27        estimated_priority_fee_lamports,
28    );
29
30    PriorityFeeAdvice {
31        compute_units,
32        micro_lamports_per_compute_unit,
33        estimated_priority_fee_lamports,
34        estimated_priority_fee_sol,
35        risk_level,
36        recommendation,
37    }
38}
39
40fn classify_fee(
41    compute_units: u64,
42    micro_lamports_per_compute_unit: u64,
43    estimated_priority_fee_lamports: u64,
44) -> (String, String) {
45    if compute_units == 0 {
46        return (
47            "Invalid".to_string(),
48            "Compute units must be greater than zero.".to_string(),
49        );
50    }
51
52    if micro_lamports_per_compute_unit == 0 {
53        return (
54            "Low".to_string(),
55            "No priority fee is configured. This may be acceptable during low network activity but can reduce transaction landing reliability during congestion.".to_string(),
56        );
57    }
58
59    if estimated_priority_fee_lamports < 100 {
60        return (
61            "Low".to_string(),
62            "Priority fee is very low. Consider increasing compute unit price for production marketplace, reward, or high-frequency transaction flows.".to_string(),
63        );
64    }
65
66    if estimated_priority_fee_lamports <= 5_000 {
67        return (
68            "Normal".to_string(),
69            "Priority fee appears reasonable for moderate load. Monitor transaction landing rate and RPC latency in production.".to_string(),
70        );
71    }
72
73    if estimated_priority_fee_lamports <= 50_000 {
74        return (
75            "Elevated".to_string(),
76            "Priority fee is elevated. This may improve landing probability during congestion but should be monitored for cost impact.".to_string(),
77        );
78    }
79
80    (
81        "High".to_string(),
82        "Priority fee is high. Verify that this is intentional and justified by congestion, latency-sensitive flows, or high-value transactions.".to_string(),
83    )
84}
85
86#[cfg(test)]
87mod tests {
88    use super::*;
89
90    #[test]
91    fn calculates_priority_fee_in_lamports() {
92        let advice = advise_priority_fee(250_000, 1_000);
93        assert_eq!(advice.estimated_priority_fee_lamports, 250);
94    }
95
96    #[test]
97    fn detects_zero_compute_units() {
98        let advice = advise_priority_fee(0, 1_000);
99        assert_eq!(advice.risk_level, "Invalid");
100    }
101
102    #[test]
103    fn detects_zero_priority_fee() {
104        let advice = advise_priority_fee(250_000, 0);
105        assert_eq!(advice.risk_level, "Low");
106    }
107}