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