oil_api/state/
refinery.rs1use serde::{Deserialize, Serialize};
2use steel::*;
3
4use crate::state::refinery_pda;
5
6use super::OilAccount;
7
8#[repr(C)]
10#[derive(Clone, Copy, Debug, PartialEq, Pod, Zeroable, Serialize, Deserialize)]
11pub struct RigConfig {
12 pub mining_power: u64,
14
15 pub fuel_requirement: u64,
17
18 pub fuel_consumption_rate: u64,
20}
21
22#[repr(C)]
24#[derive(Clone, Copy, Debug, PartialEq, Pod, Zeroable, Serialize, Deserialize)]
25pub struct Refinery {
26 pub total_network_mining_power: u64,
28
29 pub emission_per_block: u64,
31
32 pub last_emission_update_block: u64,
34
35 pub rig_supplies: [u64; 15],
37
38 pub rig_current: [u64; 15],
40
41 pub rig_configs: [RigConfig; 15],
43
44 pub admin: Pubkey,
46
47 pub refinery_rewards_factor: Numeric,
49
50 pub last_rewards_factor_block: u64,
52
53 pub buffer_a: u64,
55
56 pub buffer_b: u64,
58}
59
60impl Refinery {
61 pub fn pda() -> (Pubkey, u8) {
62 refinery_pda()
63 }
64
65 pub fn initialize(&mut self, admin: Pubkey, clock: &Clock, initial_emission: u64) {
66 self.total_network_mining_power = 0;
67 self.emission_per_block = initial_emission; self.last_emission_update_block = clock.slot;
69 self.rig_supplies = [u64::MAX; 15]; self.rig_current = [0; 15];
71 self.admin = admin;
73 self.refinery_rewards_factor = Numeric::ZERO;
74 self.last_rewards_factor_block = clock.slot;
75 self.buffer_a = 0;
76 self.buffer_b = 0;
77 }
78
79 pub fn update_emission_rate(&mut self, clock: &Clock, blocks_per_day: u64) {
81 let initialization_block = self.last_emission_update_block;
82 let blocks_elapsed = clock.slot.saturating_sub(initialization_block);
83 let days_elapsed = blocks_elapsed / blocks_per_day;
84
85 if days_elapsed <= 7 {
87 let start_emission = 7_100_000_000u64; let peak_emission = 17_900_000_000u64; if days_elapsed == 0 {
91 self.emission_per_block = start_emission;
92 } else if days_elapsed >= 7 {
93 self.emission_per_block = peak_emission;
94 } else {
95 let days_progress = (days_elapsed - 1) as u128;
97 let emission_range = (peak_emission - start_emission) as u128;
98 let interpolated = start_emission as u128
99 + (emission_range * days_progress) / 6;
100 self.emission_per_block = interpolated as u64;
101 }
102 self.last_emission_update_block = clock.slot;
103 return;
104 }
105
106 if days_elapsed <= 14 {
108 self.emission_per_block = 17_900_000_000u64; self.last_emission_update_block = clock.slot;
110 return;
111 }
112
113 let blocks_since_update = clock.slot.saturating_sub(self.last_emission_update_block);
116 let blocks_per_day = blocks_per_day;
117
118 if blocks_since_update >= blocks_per_day {
119 let min_emission = 3_600_000_000u64; let new_emission = (self.emission_per_block as u128 * 98) / 100; self.emission_per_block = new_emission.max(min_emission as u128) as u64;
123 self.last_emission_update_block = clock.slot;
124 }
125 }
126
127 pub fn can_mint_rig(&self, rig_type: u64) -> bool {
129 let idx = rig_type as usize;
130 if idx >= 15 {
131 return false;
132 }
133
134 let max_supply = self.rig_supplies[idx];
135 if max_supply == u64::MAX {
136 true } else {
138 self.rig_current[idx] < max_supply
139 }
140 }
141
142 pub fn increment_rig_supply(&mut self, rig_type: u64) {
144 let idx = rig_type as usize;
145 if idx < 15 {
146 self.rig_current[idx] = self.rig_current[idx].saturating_add(1);
147 }
148 }
149
150 pub fn update_mining_power(&mut self, mining_power_change: i64) {
152 if mining_power_change > 0 {
153 self.total_network_mining_power = self.total_network_mining_power
154 .saturating_add(mining_power_change as u64);
155 } else {
156 self.total_network_mining_power = self.total_network_mining_power
157 .saturating_sub((-mining_power_change) as u64);
158 }
159 }
160
161 pub fn advance_rewards_factor(&mut self, clock: &Clock) {
164 let blocks = clock.slot.saturating_sub(self.last_rewards_factor_block);
165 if self.total_network_mining_power > 0 && blocks > 0 {
166 let total_emission = self.emission_per_block.saturating_mul(blocks);
167 self.refinery_rewards_factor +=
168 Numeric::from_fraction(total_emission, self.total_network_mining_power);
169 }
170 self.last_rewards_factor_block = clock.slot;
171 }
172}
173
174account!(OilAccount, Refinery);