data_anchor_client/fees/
priority.rs1use anchor_lang::prelude::Pubkey;
2use clap::ValueEnum;
3use itertools::Itertools;
4use serde::{Deserialize, Serialize};
5use solana_client::nonblocking::rpc_client::RpcClient;
6
7use crate::{DataAnchorClientResult, MicroLamports};
8
9#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Serialize, Deserialize, ValueEnum)]
11pub enum Priority {
12 Min,
14 Low,
16 #[default]
18 Medium,
19 High,
21 VeryHigh,
23}
24
25impl Priority {
26 pub fn percentile(&self) -> f32 {
28 match self {
29 Self::Min => 0.0,
30 Self::Low => 0.25,
31 Self::Medium => 0.5,
32 Self::High => 0.75,
33 Self::VeryHigh => 0.95,
34 }
35 }
36
37 fn calculate_percentile(&self, sorted_fees: &[u64]) -> MicroLamports {
42 if sorted_fees.is_empty() {
43 return MicroLamports::MIN;
44 }
45 let percentile = self.percentile();
46 let index = (percentile * (sorted_fees.len() as f32 - 1.0)) as usize;
47 MicroLamports(sorted_fees[index.min(sorted_fees.len() - 1)].max(MicroLamports::MIN.0))
48 }
49
50 pub async fn get_priority_fee_estimate(
52 &self,
53 client: &RpcClient,
54 mutable_accounts: &[Pubkey],
55 ) -> DataAnchorClientResult<MicroLamports> {
56 self.calculate_compute_unit_price(client, mutable_accounts)
57 .await
58 }
59
60 pub async fn calculate_compute_unit_price(
66 &self,
67 client: &RpcClient,
68 mutable_accounts: &[Pubkey],
69 ) -> DataAnchorClientResult<MicroLamports> {
70 let recent_prioritization_fees = client
71 .get_recent_prioritization_fees(mutable_accounts)
72 .await?;
73 if recent_prioritization_fees.is_empty() {
74 return Ok(MicroLamports::MIN);
75 }
76 let sorted_fees = recent_prioritization_fees
77 .into_iter()
78 .map(|f| f.prioritization_fee)
79 .sorted()
80 .collect::<Vec<_>>();
81 Ok(self.calculate_percentile(&sorted_fees))
82 }
83}
84
85#[cfg(test)]
86mod tests {
87 use super::*;
88
89 #[test]
90 fn medium_is_default() {
91 let default = Priority::default();
93 let medium = Priority::Medium;
94 assert_eq!(medium, default);
95 }
96}