1use serde::{Deserialize, Serialize};
2use steel::*;
3
4use crate::state::{miner_pda, OreAccount, Treasury, DENOMINATOR_BPS};
5
6#[repr(C)]
7#[derive(Clone, Copy, Debug, PartialEq, Pod, Zeroable, Serialize, Deserialize)]
8pub struct Miner {
9 pub authority: Pubkey,
11
12 pub auto_return: u64,
14
15 pub checkpoint_id: u64,
17
18 pub checkpoint_fee: u64,
20
21 pub deployed: [u64; 25],
24
25 pub mass: [u64; 25],
27
28 pub cumulative: [u64; 25],
31
32 pub round_id: u64,
34
35 pub rewards_factor: Numeric,
37
38 pub rewards_sol: u64,
41
42 pub refined_ore: u64,
45
46 pub rewards_ore: u64,
49
50 pub last_claim_ore_at: i64,
52
53 pub last_claim_sol_at: i64,
55
56 pub lifetime_rewards_ore: u64,
59
60 pub lifetime_deployed: u64,
62
63 pub lifetime_rewards_sol: u64,
66}
67
68impl Miner {
69 pub fn pda(&self) -> (Pubkey, u8) {
70 miner_pda(self.authority)
71 }
72
73 pub fn claim_ore(&mut self, clock: &Clock, treasury: &mut Treasury, bps: u64) -> (u64, u64) {
74 self.update_rewards(treasury);
75
76 let bps = bps.min(DENOMINATOR_BPS);
79 let claim_refined = (self.refined_ore * bps) / DENOMINATOR_BPS;
80 let claim_rewards = (self.rewards_ore * bps) / DENOMINATOR_BPS;
81
82 self.refined_ore -= claim_refined;
84 self.rewards_ore -= claim_rewards;
85 treasury.total_refined -= claim_refined;
86 treasury.total_unclaimed -= claim_rewards;
87 self.last_claim_ore_at = clock.unix_timestamp;
88
89 let mut fee = 0;
91 let mut amount = claim_refined + claim_rewards;
92 if claim_rewards > 0 && treasury.total_unclaimed > 0 {
93 fee = 1.max(claim_rewards / 10);
94 amount -= fee;
95 treasury.miner_rewards_factor += Numeric::from_fraction(fee, treasury.total_unclaimed);
97 treasury.total_refined += fee;
98 self.lifetime_rewards_ore -= fee;
99 }
100
101 (amount, fee)
102 }
103
104 pub fn claim_sol(&mut self, clock: &Clock) -> u64 {
105 let amount = self.rewards_sol;
106 self.rewards_sol = 0;
107 self.last_claim_sol_at = clock.unix_timestamp;
108 amount
109 }
110
111 pub fn update_rewards(&mut self, treasury: &Treasury) {
112 if treasury.miner_rewards_factor > self.rewards_factor {
114 let accumulated_rewards = treasury.miner_rewards_factor - self.rewards_factor;
115 if accumulated_rewards < Numeric::ZERO {
116 panic!("Accumulated rewards is negative");
117 }
118 let personal_rewards = accumulated_rewards * Numeric::from_u64(self.rewards_ore);
119 self.refined_ore += personal_rewards.to_u64();
120 self.lifetime_rewards_ore += personal_rewards.to_u64();
121 }
122
123 self.rewards_factor = treasury.miner_rewards_factor;
125 }
126}
127
128account!(OreAccount, Miner);