gmsol_solana_utils/
compute_budget.rs1use std::ops::AddAssign;
2
3use solana_sdk::{compute_budget::ComputeBudgetInstruction, instruction::Instruction};
4
5#[derive(Debug, Clone, Copy)]
7pub struct ComputeBudget {
8 min_priority_lamports: Option<u64>,
9 limit_units: u32,
10 price_micro_lamports: u64,
11}
12
13impl Default for ComputeBudget {
14 fn default() -> Self {
15 Self {
16 min_priority_lamports: Some(Self::DEFAULT_MIN_PRIORITY_LAMPORTS),
17 limit_units: 200_000,
18 price_micro_lamports: 50_000,
19 }
20 }
21}
22
23impl ComputeBudget {
24 const MICRO_LAMPORTS: u64 = 10u64.pow(6);
25
26 pub const DEFAULT_MIN_PRIORITY_LAMPORTS: u64 = 10000;
28
29 pub const MAX_COMPUTE_UNIT: u32 = 1_400_000;
31
32 #[inline]
34 pub fn with_limit(mut self, units: u32) -> Self {
35 self.set_limit(units);
36 self
37 }
38
39 #[inline]
41 pub fn with_price(mut self, micro_lamports: u64) -> Self {
42 self.set_price(micro_lamports);
43 self
44 }
45
46 #[inline]
48 pub fn with_min_priority_lamports(mut self, lamports: Option<u64>) -> Self {
49 self.set_min_priority_lamports(lamports);
50 self
51 }
52
53 #[inline]
55 pub fn set_min_priority_lamports(&mut self, lamports: Option<u64>) -> &mut Self {
56 self.min_priority_lamports = lamports;
57 self
58 }
59
60 pub fn set_price(&mut self, micro_lamports: u64) -> &mut Self {
62 self.price_micro_lamports = micro_lamports;
63 self
64 }
65
66 pub fn set_limit(&mut self, units: u32) -> &mut Self {
68 self.limit_units = units;
69 self
70 }
71
72 fn budget_price(&self, compute_unit_price_micro_lamports: Option<u64>) -> u64 {
73 let mut price = compute_unit_price_micro_lamports.unwrap_or(self.price_micro_lamports);
74 if let Some(min_price) = self.min_priority_lamports.and_then(|min_lamports| {
75 min_lamports
76 .checked_mul(Self::MICRO_LAMPORTS)?
77 .checked_div(self.budget_units() as u64)
78 }) {
79 price = price.max(min_price)
80 }
81 price
82 }
83
84 fn budget_units(&self) -> u32 {
85 self.limit_units.min(Self::MAX_COMPUTE_UNIT)
86 }
87
88 pub fn compute_budget_instructions(
90 &self,
91 compute_unit_price_micro_lamports: Option<u64>,
92 ) -> Vec<Instruction> {
93 let price = self.budget_price(compute_unit_price_micro_lamports);
94 vec![
95 ComputeBudgetInstruction::set_compute_unit_limit(self.budget_units()),
96 ComputeBudgetInstruction::set_compute_unit_price(price),
97 ]
98 }
99
100 pub fn limit(&self) -> u32 {
102 self.limit_units
103 }
104
105 pub fn price(&self) -> u64 {
107 self.price_micro_lamports
108 }
109
110 pub fn fee(&self, compute_unit_price_micro_lamports: Option<u64>) -> u64 {
112 self.budget_units() as u64 * self.budget_price(compute_unit_price_micro_lamports)
113 / Self::MICRO_LAMPORTS
114 }
115}
116
117impl AddAssign for ComputeBudget {
118 fn add_assign(&mut self, rhs: Self) {
119 self.limit_units += rhs.limit_units;
120 self.price_micro_lamports = self.price_micro_lamports.max(rhs.price_micro_lamports);
121 let min_lamports = match (self.min_priority_lamports, rhs.min_priority_lamports) {
122 (Some(lamports), None) => Some(lamports),
123 (None, Some(lamports)) => Some(lamports),
124 (Some(lhs), Some(rhs)) => Some(lhs.max(rhs)),
125 (None, None) => None,
126 };
127 self.min_priority_lamports = min_lamports;
128 }
129}