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
297pub enum Miner {
298 V1(MinerV1),
299 V4(MinerV4),
300}
301
302impl Miner {
303 pub fn authority(&self) -> Pubkey {
304 match self {
305 Miner::V1(miner) => miner.authority,
306 Miner::V4(miner) => miner.authority,
307 }
308 }
309
310 pub fn deployed(&self) -> [u64; 25] {
311 match self {
312 Miner::V1(miner) => miner.deployed,
313 Miner::V4(miner) => miner.sol,
314 }
315 }
316
317 pub fn cumulative(&self) -> [u64; 25] {
318 match self {
319 Miner::V1(miner) => miner.cumulative,
320 Miner::V4(miner) => miner.mass_cumulative,
321 }
322 }
323
324 pub fn checkpoint_fee(&self) -> u64 {
325 match self {
326 Miner::V1(miner) => miner.checkpoint_fee,
327 Miner::V4(miner) => miner.checkpoint_fee,
328 }
329 }
330
331 pub fn checkpoint_id(&self) -> u64 {
332 match self {
333 Miner::V1(miner) => miner.checkpoint_id,
334 Miner::V4(miner) => miner.checkpoint_id,
335 }
336 }
337
338 pub fn last_claim_ore_at(&self) -> i64 {
339 match self {
340 Miner::V1(miner) => miner.last_claim_ore_at,
341 Miner::V4(miner) => miner.last_claim_ore_at,
342 }
343 }
344
345 pub fn last_claim_sol_at(&self) -> i64 {
346 match self {
347 Miner::V1(miner) => miner.last_claim_sol_at,
348 Miner::V4(miner) => miner.last_claim_sol_at,
349 }
350 }
351 pub fn rewards_factor(&self) -> Numeric {
352 match self {
353 Miner::V1(miner) => miner.rewards_factor,
354 Miner::V4(miner) => miner.rewards_factor,
355 }
356 }
357
358 pub fn rewards_sol(&self) -> u64 {
359 match self {
360 Miner::V1(miner) => miner.rewards_sol,
361 Miner::V4(miner) => miner.sol_returned,
362 }
363 }
364
365 pub fn rewards_ore(&self) -> u64 {
366 match self {
367 Miner::V1(miner) => miner.rewards_ore,
368 Miner::V4(miner) => miner.ore_unrefined,
369 }
370 }
371
372 pub fn refined_ore(&self) -> u64 {
373 match self {
374 Miner::V1(miner) => miner.refined_ore,
375 Miner::V4(miner) => miner.ore_refined,
376 }
377 }
378
379 pub fn round_id(&self) -> u64 {
380 match self {
381 Miner::V1(miner) => miner.round_id,
382 Miner::V4(miner) => miner.round_id,
383 }
384 }
385
386 pub fn lifetime_rewards_sol(&self) -> u64 {
387 match self {
388 Miner::V1(miner) => miner.lifetime_rewards_sol,
389 Miner::V4(miner) => miner.lifetime_returned_sol,
390 }
391 }
392
393 pub fn lifetime_rewards_ore(&self) -> u64 {
394 match self {
395 Miner::V1(miner) => miner.lifetime_rewards_ore,
396 Miner::V4(miner) => miner.lifetime_rewards,
397 }
398 }
399
400 pub fn lifetime_deployed(&self) -> u64 {
401 match self {
402 Miner::V1(miner) => miner.lifetime_deployed,
403 Miner::V4(miner) => miner.lifetime_deployed,
404 }
405 }
406
407 pub fn pda(&self) -> (Pubkey, u8) {
408 match self {
409 Miner::V1(miner) => miner.pda(),
410 Miner::V4(miner) => miner.pda(),
411 }
412 }
413
414 pub fn claim_ore(&mut self, clock: &Clock, treasury: &mut Treasury) -> u64 {
415 match self {
416 Miner::V1(miner) => match treasury {
417 Treasury::V1(treasury) => miner.claim_ore_v1(clock, treasury),
418 Treasury::V4(treasury) => miner.claim_ore_v4(clock, treasury),
419 },
420 Miner::V4(miner) => match treasury {
421 Treasury::V1(treasury) => miner.claim_ore_v1(clock, treasury),
422 Treasury::V4(treasury) => miner.claim_ore_v4(clock, treasury),
423 },
424 }
425 }
426
427 pub fn claim_sol(&mut self, clock: &Clock) -> u64 {
428 match self {
429 Miner::V1(miner) => miner.claim_sol(clock),
430 Miner::V4(miner) => miner.claim_sol(clock),
431 }
432 }
433
434 pub fn update_rewards(&mut self, treasury: &Treasury) {
435 match self {
436 Miner::V1(miner) => match treasury {
437 Treasury::V1(treasury) => miner.update_rewards_v1(treasury),
438 Treasury::V4(treasury) => miner.update_rewards_v4(treasury),
439 },
440 Miner::V4(miner) => match treasury {
441 Treasury::V1(treasury) => miner.update_rewards_v1(treasury),
442 Treasury::V4(treasury) => miner.update_rewards_v4(treasury),
443 },
444 }
445 }
446}