1use serde::{Deserialize, Serialize};
2use steel::*;
3
4use crate::state::{miner_pda, OreAccountV4, Treasury};
5
6use super::OreAccount;
7
8#[repr(C)]
9#[derive(Clone, Copy, Debug, PartialEq, Pod, Zeroable, Serialize, Deserialize)]
10pub struct Miner {
11 pub authority: Pubkey,
13
14 pub deployed: [u64; 25],
16
17 pub cumulative: [u64; 25],
19
20 pub checkpoint_fee: u64,
22
23 pub checkpoint_id: u64,
25
26 pub last_claim_ore_at: i64,
28
29 pub last_claim_sol_at: i64,
31
32 pub rewards_factor: Numeric,
34
35 pub rewards_sol: u64,
37
38 pub rewards_ore: u64,
40
41 pub refined_ore: u64,
43
44 pub round_id: u64,
46
47 pub lifetime_rewards_sol: u64,
49
50 pub lifetime_rewards_ore: u64,
52
53 pub lifetime_deployed: u64,
55}
56
57#[repr(C)]
58#[derive(Clone, Copy, Debug, PartialEq, Pod, Zeroable, Serialize, Deserialize)]
59pub struct MinerV4 {
60 pub authority: Pubkey,
62
63 pub auto_return: u64,
65
66 pub checkpoint_id: u64,
68
69 pub checkpoint_fee: u64,
71
72 pub sol: [u64; 25],
74
75 pub mass: [u64; 25],
77
78 pub mass_cumulative: [u64; 25],
80
81 pub round_id: u64,
83
84 pub rewards_factor: Numeric,
86
87 pub sol_returned: u64,
89
90 pub ore_refined: u64,
92
93 pub ore_unrefined: u64,
95
96 pub last_claim_ore_at: i64,
98
99 pub last_claim_sol_at: i64,
101
102 pub lifetime_rewards: u64,
104
105 pub lifetime_deployed: u64,
107
108 pub lifetime_returned_sol: u64,
110}
111
112impl Miner {
113 pub fn pda(&self) -> (Pubkey, u8) {
114 miner_pda(self.authority)
115 }
116
117 pub fn claim_ore(&mut self, clock: &Clock, treasury: &mut Treasury) -> u64 {
118 self.update_rewards(treasury);
119 let refined_ore = self.refined_ore;
120 let rewards_ore = self.rewards_ore;
121 let mut amount = refined_ore + rewards_ore;
122 self.refined_ore = 0;
123 self.rewards_ore = 0;
124 treasury.total_unclaimed -= rewards_ore;
125 treasury.total_refined -= refined_ore;
126 self.last_claim_ore_at = clock.unix_timestamp;
127
128 if treasury.total_unclaimed > 0 {
130 let fee = rewards_ore / 10;
131 amount -= fee;
132 treasury.miner_rewards_factor += Numeric::from_fraction(fee, treasury.total_unclaimed);
133 treasury.total_refined += fee;
134 self.lifetime_rewards_ore -= fee;
135 }
136
137 amount
138 }
139
140 pub fn claim_sol(&mut self, clock: &Clock) -> u64 {
141 let amount = self.rewards_sol;
142 self.rewards_sol = 0;
143 self.last_claim_sol_at = clock.unix_timestamp;
144 amount
145 }
146
147 pub fn update_rewards(&mut self, treasury: &Treasury) {
148 if treasury.miner_rewards_factor > self.rewards_factor {
150 let accumulated_rewards = treasury.miner_rewards_factor - self.rewards_factor;
151 if accumulated_rewards < Numeric::ZERO {
152 panic!("Accumulated rewards is negative");
153 }
154 let personal_rewards = accumulated_rewards * Numeric::from_u64(self.rewards_ore);
155 self.refined_ore += personal_rewards.to_u64();
156 self.lifetime_rewards_ore += personal_rewards.to_u64();
157 }
158
159 self.rewards_factor = treasury.miner_rewards_factor;
161 }
162}
163
164impl MinerV4 {
165 pub fn pda(&self) -> (Pubkey, u8) {
166 miner_pda(self.authority)
167 }
168
169 pub fn claim_ore(&mut self, clock: &Clock, treasury: &mut Treasury) -> u64 {
170 self.update_rewards(treasury);
171 let refined_ore = self.ore_refined;
172 let rewards_ore = self.ore_unrefined;
173 let mut amount = refined_ore + rewards_ore;
174 self.ore_refined = 0;
175 self.ore_unrefined = 0;
176 treasury.total_unclaimed -= rewards_ore;
177 treasury.total_refined -= refined_ore;
178 self.last_claim_ore_at = clock.unix_timestamp;
179
180 if treasury.total_unclaimed > 0 {
182 let fee = rewards_ore / 10;
183 amount -= fee;
184 treasury.miner_rewards_factor += Numeric::from_fraction(fee, treasury.total_unclaimed);
185 treasury.total_refined += fee;
186 self.lifetime_rewards -= fee;
187 }
188
189 amount
190 }
191
192 pub fn claim_sol(&mut self, clock: &Clock) -> u64 {
193 let amount = self.sol_returned;
194 self.sol_returned = 0;
195 self.last_claim_sol_at = clock.unix_timestamp;
196 amount
197 }
198
199 pub fn update_rewards(&mut self, treasury: &Treasury) {
200 if treasury.miner_rewards_factor > self.rewards_factor {
202 let accumulated_rewards = treasury.miner_rewards_factor - self.rewards_factor;
203 if accumulated_rewards < Numeric::ZERO {
204 panic!("Accumulated rewards is negative");
205 }
206 let personal_rewards = accumulated_rewards * Numeric::from_u64(self.ore_unrefined);
207 self.ore_refined += personal_rewards.to_u64();
208 self.lifetime_rewards += personal_rewards.to_u64();
209 }
210
211 self.rewards_factor = treasury.miner_rewards_factor;
213 }
214}
215
216account!(OreAccount, Miner);
217account!(OreAccountV4, MinerV4);
218
219pub enum MinerAccount {
220 Miner(Miner),
221 MinerV4(MinerV4),
222}
223
224impl MinerAccount {
225 pub fn authority(&self) -> Pubkey {
226 match self {
227 MinerAccount::Miner(miner) => miner.authority,
228 MinerAccount::MinerV4(miner) => miner.authority,
229 }
230 }
231
232 pub fn deployed(&self) -> [u64; 25] {
233 match self {
234 MinerAccount::Miner(miner) => miner.deployed,
235 MinerAccount::MinerV4(miner) => miner.sol,
236 }
237 }
238
239 pub fn cumulative(&self) -> [u64; 25] {
240 match self {
241 MinerAccount::Miner(miner) => miner.cumulative,
242 MinerAccount::MinerV4(miner) => miner.mass_cumulative,
243 }
244 }
245
246 pub fn checkpoint_fee(&self) -> u64 {
247 match self {
248 MinerAccount::Miner(miner) => miner.checkpoint_fee,
249 MinerAccount::MinerV4(miner) => miner.checkpoint_fee,
250 }
251 }
252
253 pub fn checkpoint_id(&self) -> u64 {
254 match self {
255 MinerAccount::Miner(miner) => miner.checkpoint_id,
256 MinerAccount::MinerV4(miner) => miner.checkpoint_id,
257 }
258 }
259
260 pub fn last_claim_ore_at(&self) -> i64 {
261 match self {
262 MinerAccount::Miner(miner) => miner.last_claim_ore_at,
263 MinerAccount::MinerV4(miner) => miner.last_claim_ore_at,
264 }
265 }
266
267 pub fn last_claim_sol_at(&self) -> i64 {
268 match self {
269 MinerAccount::Miner(miner) => miner.last_claim_sol_at,
270 MinerAccount::MinerV4(miner) => miner.last_claim_sol_at,
271 }
272 }
273 pub fn rewards_factor(&self) -> Numeric {
274 match self {
275 MinerAccount::Miner(miner) => miner.rewards_factor,
276 MinerAccount::MinerV4(miner) => miner.rewards_factor,
277 }
278 }
279
280 pub fn rewards_sol(&self) -> u64 {
281 match self {
282 MinerAccount::Miner(miner) => miner.rewards_sol,
283 MinerAccount::MinerV4(miner) => miner.sol_returned,
284 }
285 }
286
287 pub fn rewards_ore(&self) -> u64 {
288 match self {
289 MinerAccount::Miner(miner) => miner.rewards_ore,
290 MinerAccount::MinerV4(miner) => miner.ore_unrefined,
291 }
292 }
293
294 pub fn refined_ore(&self) -> u64 {
295 match self {
296 MinerAccount::Miner(miner) => miner.refined_ore,
297 MinerAccount::MinerV4(miner) => miner.ore_refined,
298 }
299 }
300
301 pub fn round_id(&self) -> u64 {
302 match self {
303 MinerAccount::Miner(miner) => miner.round_id,
304 MinerAccount::MinerV4(miner) => miner.round_id,
305 }
306 }
307
308 pub fn lifetime_rewards_sol(&self) -> u64 {
309 match self {
310 MinerAccount::Miner(miner) => miner.lifetime_rewards_sol,
311 MinerAccount::MinerV4(miner) => miner.lifetime_returned_sol,
312 }
313 }
314
315 pub fn lifetime_rewards_ore(&self) -> u64 {
316 match self {
317 MinerAccount::Miner(miner) => miner.lifetime_rewards_ore,
318 MinerAccount::MinerV4(miner) => miner.lifetime_rewards,
319 }
320 }
321
322 pub fn lifetime_deployed(&self) -> u64 {
323 match self {
324 MinerAccount::Miner(miner) => miner.lifetime_deployed,
325 MinerAccount::MinerV4(miner) => miner.lifetime_deployed,
326 }
327 }
328
329 pub fn pda(&self) -> (Pubkey, u8) {
330 match self {
331 MinerAccount::Miner(miner) => miner.pda(),
332 MinerAccount::MinerV4(miner) => miner.pda(),
333 }
334 }
335
336 pub fn claim_ore(&mut self, clock: &Clock, treasury: &mut Treasury) -> u64 {
337 match self {
338 MinerAccount::Miner(miner) => miner.claim_ore(clock, treasury),
339 MinerAccount::MinerV4(miner) => miner.claim_ore(clock, treasury),
340 }
341 }
342
343 pub fn claim_sol(&mut self, clock: &Clock) -> u64 {
344 match self {
345 MinerAccount::Miner(miner) => miner.claim_sol(clock),
346 MinerAccount::MinerV4(miner) => miner.claim_sol(clock),
347 }
348 }
349
350 pub fn update_rewards(&mut self, treasury: &Treasury) {
351 match self {
352 MinerAccount::Miner(miner) => miner.update_rewards(treasury),
353 MinerAccount::MinerV4(miner) => miner.update_rewards(treasury),
354 }
355 }
356}