1use serde::{Deserialize, Serialize};
2use steel::*;
3
4use crate::state::{miner_pda, OreAccountV4, Treasury, TreasuryV1, TreasuryV4};
5
6use super::OreAccountV1;
7
8#[repr(C)]
9#[derive(Clone, Copy, Debug, PartialEq, Pod, Zeroable, Serialize, Deserialize)]
10pub struct MinerV1 {
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 MinerV1 {
113 pub fn pda(&self) -> (Pubkey, u8) {
114 miner_pda(self.authority)
115 }
116
117 pub fn claim_ore_v1(&mut self, clock: &Clock, treasury: &mut TreasuryV1) -> u64 {
118 self.update_rewards_v1(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_ore_v4(&mut self, clock: &Clock, treasury: &mut TreasuryV4) -> u64 {
141 self.update_rewards_v4(treasury);
142 let refined_ore = self.refined_ore;
143 let rewards_ore = self.rewards_ore;
144 let mut amount = refined_ore + rewards_ore;
145 self.refined_ore = 0;
146 self.rewards_ore = 0;
147 treasury.total_unrefined -= rewards_ore;
148 treasury.total_refined -= refined_ore;
149 self.last_claim_ore_at = clock.unix_timestamp;
150
151 if treasury.total_unrefined > 0 {
153 let fee = rewards_ore / 10;
154 amount -= fee;
155 treasury.rewards_factor += Numeric::from_fraction(fee, treasury.total_unrefined);
156 treasury.total_refined += fee;
157 self.lifetime_rewards_ore -= fee;
158 }
159
160 amount
161 }
162
163 pub fn claim_sol(&mut self, clock: &Clock) -> u64 {
164 let amount = self.rewards_sol;
165 self.rewards_sol = 0;
166 self.last_claim_sol_at = clock.unix_timestamp;
167 amount
168 }
169
170 pub fn update_rewards_v1(&mut self, treasury: &TreasuryV1) {
171 if treasury.miner_rewards_factor > self.rewards_factor {
173 let accumulated_rewards = treasury.miner_rewards_factor - self.rewards_factor;
174 if accumulated_rewards < Numeric::ZERO {
175 panic!("Accumulated rewards is negative");
176 }
177 let personal_rewards = accumulated_rewards * Numeric::from_u64(self.rewards_ore);
178 self.refined_ore += personal_rewards.to_u64();
179 self.lifetime_rewards_ore += personal_rewards.to_u64();
180 }
181
182 self.rewards_factor = treasury.miner_rewards_factor;
184 }
185
186 pub fn update_rewards_v4(&mut self, treasury: &TreasuryV4) {
187 if treasury.rewards_factor > self.rewards_factor {
189 let accumulated_rewards = treasury.rewards_factor - self.rewards_factor;
190 if accumulated_rewards < Numeric::ZERO {
191 panic!("Accumulated rewards is negative");
192 }
193 let personal_rewards = accumulated_rewards * Numeric::from_u64(self.rewards_ore);
194 self.refined_ore += personal_rewards.to_u64();
195 self.lifetime_rewards_ore += personal_rewards.to_u64();
196 }
197
198 self.rewards_factor = treasury.rewards_factor;
200 }
201}
202
203impl MinerV4 {
204 pub fn pda(&self) -> (Pubkey, u8) {
205 miner_pda(self.authority)
206 }
207
208 pub fn claim_ore_v1(&mut self, clock: &Clock, treasury: &mut TreasuryV1) -> u64 {
209 self.update_rewards_v1(treasury);
210 let refined_ore = self.ore_refined;
211 let rewards_ore = self.ore_unrefined;
212 let mut amount = refined_ore + rewards_ore;
213 self.ore_refined = 0;
214 self.ore_unrefined = 0;
215 treasury.total_unclaimed -= rewards_ore;
216 treasury.total_refined -= refined_ore;
217 self.last_claim_ore_at = clock.unix_timestamp;
218
219 if treasury.total_unclaimed > 0 {
221 let fee = rewards_ore / 10;
222 amount -= fee;
223 treasury.miner_rewards_factor += Numeric::from_fraction(fee, treasury.total_unclaimed);
224 treasury.total_refined += fee;
225 self.lifetime_rewards -= fee;
226 }
227
228 amount
229 }
230
231 pub fn claim_ore_v4(&mut self, clock: &Clock, treasury: &mut TreasuryV4) -> u64 {
232 self.update_rewards_v4(treasury);
233 let refined_ore = self.ore_refined;
234 let rewards_ore = self.ore_unrefined;
235 let mut amount = refined_ore + rewards_ore;
236 self.ore_refined = 0;
237 self.ore_unrefined = 0;
238 treasury.total_unrefined -= rewards_ore;
239 treasury.total_refined -= refined_ore;
240 self.last_claim_ore_at = clock.unix_timestamp;
241
242 if treasury.total_unrefined > 0 {
244 let fee = rewards_ore / 10;
245 amount -= fee;
246 treasury.rewards_factor += Numeric::from_fraction(fee, treasury.total_unrefined);
247 treasury.total_refined += fee;
248 self.lifetime_rewards -= fee;
249 }
250
251 amount
252 }
253
254 pub fn claim_sol(&mut self, clock: &Clock) -> u64 {
255 let amount = self.sol_returned;
256 self.sol_returned = 0;
257 self.last_claim_sol_at = clock.unix_timestamp;
258 amount
259 }
260
261 pub fn update_rewards_v4(&mut self, treasury: &TreasuryV4) {
262 if treasury.rewards_factor > self.rewards_factor {
264 let accumulated_rewards = treasury.rewards_factor - self.rewards_factor;
265 if accumulated_rewards < Numeric::ZERO {
266 panic!("Accumulated rewards is negative");
267 }
268 let personal_rewards = accumulated_rewards * Numeric::from_u64(self.ore_unrefined);
269 self.ore_refined += personal_rewards.to_u64();
270 self.lifetime_rewards += personal_rewards.to_u64();
271 }
272
273 self.rewards_factor = treasury.rewards_factor;
275 }
276
277 pub fn update_rewards_v1(&mut self, treasury: &TreasuryV1) {
278 if treasury.miner_rewards_factor > self.rewards_factor {
280 let accumulated_rewards = treasury.miner_rewards_factor - self.rewards_factor;
281 if accumulated_rewards < Numeric::ZERO {
282 panic!("Accumulated rewards is negative");
283 }
284 let personal_rewards = accumulated_rewards * Numeric::from_u64(self.ore_unrefined);
285 self.ore_refined += personal_rewards.to_u64();
286 self.lifetime_rewards += personal_rewards.to_u64();
287 }
288
289 self.rewards_factor = treasury.miner_rewards_factor;
291 }
292}
293
294account!(OreAccountV1, MinerV1);
295account!(OreAccountV4, MinerV4);
296
297#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)]
298pub enum Miner {
299 V1(MinerV1),
300 V4(MinerV4),
301}
302
303impl Miner {
304 pub fn authority(&self) -> Pubkey {
305 match self {
306 Miner::V1(miner) => miner.authority,
307 Miner::V4(miner) => miner.authority,
308 }
309 }
310
311 pub fn deployed(&self) -> [u64; 25] {
312 match self {
313 Miner::V1(miner) => miner.deployed,
314 Miner::V4(miner) => miner.sol,
315 }
316 }
317
318 pub fn cumulative(&self) -> [u64; 25] {
319 match self {
320 Miner::V1(miner) => miner.cumulative,
321 Miner::V4(miner) => miner.mass_cumulative,
322 }
323 }
324
325 pub fn checkpoint_fee(&self) -> u64 {
326 match self {
327 Miner::V1(miner) => miner.checkpoint_fee,
328 Miner::V4(miner) => miner.checkpoint_fee,
329 }
330 }
331
332 pub fn checkpoint_id(&self) -> u64 {
333 match self {
334 Miner::V1(miner) => miner.checkpoint_id,
335 Miner::V4(miner) => miner.checkpoint_id,
336 }
337 }
338
339 pub fn last_claim_ore_at(&self) -> i64 {
340 match self {
341 Miner::V1(miner) => miner.last_claim_ore_at,
342 Miner::V4(miner) => miner.last_claim_ore_at,
343 }
344 }
345
346 pub fn last_claim_sol_at(&self) -> i64 {
347 match self {
348 Miner::V1(miner) => miner.last_claim_sol_at,
349 Miner::V4(miner) => miner.last_claim_sol_at,
350 }
351 }
352 pub fn rewards_factor(&self) -> Numeric {
353 match self {
354 Miner::V1(miner) => miner.rewards_factor,
355 Miner::V4(miner) => miner.rewards_factor,
356 }
357 }
358
359 pub fn rewards_sol(&self) -> u64 {
360 match self {
361 Miner::V1(miner) => miner.rewards_sol,
362 Miner::V4(miner) => miner.sol_returned,
363 }
364 }
365
366 pub fn rewards_ore(&self) -> u64 {
367 match self {
368 Miner::V1(miner) => miner.rewards_ore,
369 Miner::V4(miner) => miner.ore_unrefined,
370 }
371 }
372
373 pub fn refined_ore(&self) -> u64 {
374 match self {
375 Miner::V1(miner) => miner.refined_ore,
376 Miner::V4(miner) => miner.ore_refined,
377 }
378 }
379
380 pub fn round_id(&self) -> u64 {
381 match self {
382 Miner::V1(miner) => miner.round_id,
383 Miner::V4(miner) => miner.round_id,
384 }
385 }
386
387 pub fn lifetime_rewards_sol(&self) -> u64 {
388 match self {
389 Miner::V1(miner) => miner.lifetime_rewards_sol,
390 Miner::V4(miner) => miner.lifetime_returned_sol,
391 }
392 }
393
394 pub fn lifetime_rewards_ore(&self) -> u64 {
395 match self {
396 Miner::V1(miner) => miner.lifetime_rewards_ore,
397 Miner::V4(miner) => miner.lifetime_rewards,
398 }
399 }
400
401 pub fn lifetime_deployed(&self) -> u64 {
402 match self {
403 Miner::V1(miner) => miner.lifetime_deployed,
404 Miner::V4(miner) => miner.lifetime_deployed,
405 }
406 }
407
408 pub fn pda(&self) -> (Pubkey, u8) {
409 match self {
410 Miner::V1(miner) => miner.pda(),
411 Miner::V4(miner) => miner.pda(),
412 }
413 }
414
415 pub fn claim_ore(&mut self, clock: &Clock, treasury: &mut Treasury) -> u64 {
416 match self {
417 Miner::V1(miner) => match treasury {
418 Treasury::V1(treasury) => miner.claim_ore_v1(clock, treasury),
419 Treasury::V4(treasury) => miner.claim_ore_v4(clock, treasury),
420 },
421 Miner::V4(miner) => match treasury {
422 Treasury::V1(treasury) => miner.claim_ore_v1(clock, treasury),
423 Treasury::V4(treasury) => miner.claim_ore_v4(clock, treasury),
424 },
425 }
426 }
427
428 pub fn claim_sol(&mut self, clock: &Clock) -> u64 {
429 match self {
430 Miner::V1(miner) => miner.claim_sol(clock),
431 Miner::V4(miner) => miner.claim_sol(clock),
432 }
433 }
434
435 pub fn update_rewards(&mut self, treasury: &Treasury) {
436 match self {
437 Miner::V1(miner) => match treasury {
438 Treasury::V1(treasury) => miner.update_rewards_v1(treasury),
439 Treasury::V4(treasury) => miner.update_rewards_v4(treasury),
440 },
441 Miner::V4(miner) => match treasury {
442 Treasury::V1(treasury) => miner.update_rewards_v1(treasury),
443 Treasury::V4(treasury) => miner.update_rewards_v4(treasury),
444 },
445 }
446 }
447}