Skip to main content

oil_api/state/
miner.rs

1use serde::{Deserialize, Serialize};
2use steel::*;
3
4use crate::state::{miner_pda, Treasury};
5
6use super::OilAccount;
7
8
9#[repr(C)]
10#[derive(Clone, Copy, Debug, PartialEq, Pod, Zeroable, Serialize, Deserialize)]
11pub struct Miner {
12    /// The authority of this miner account.
13    pub authority: Pubkey,
14
15    /// The miner's prospects in the current round.
16    pub deployed: [u64; 25],
17
18    /// The cumulative amount of SOL deployed on each square prior to this miner's move.
19    pub cumulative: [u64; 25],
20
21    /// SOL witheld in reserve to pay for checkpointing.
22    pub checkpoint_fee: u64,
23
24    /// The last round that this miner checkpointed.
25    pub checkpoint_id: u64,
26
27    /// The last time this miner claimed OIL rewards.
28    pub last_claim_block_oil_at: i64,
29
30    /// The last time this miner claimed SOL rewards.
31    pub last_claim_block_sol_at: i64,
32
33    /// The rewards factor last time rewards were updated on this miner account.
34    pub block_rewards_factor: Numeric,
35
36    /// The amount of SOL this miner can claim.
37    pub block_rewards_sol: u64,
38
39    /// The amount of OIL this miner can claim.
40    pub block_rewards_oil: u64,
41
42    /// The amount of OIL this miner has earned from claim fees.
43    pub block_refined_oil: u64,
44
45    /// The ID of the round this miner last played in.
46    pub round_id: u64,
47
48    /// The pooled deployed amount of this miner.
49    pub pooled_deployed: u64,
50
51    /// OIL rewards from auction wells (not yet claimed)
52    pub auction_rewards_oil: u64,
53
54    /// SOL rewards from auction wells (not yet claimed)
55    pub auction_rewards_sol: u64,
56
57    /// The rewards factor last time auction rewards were updated on this miner account.
58    pub auction_rewards_factor: Numeric,
59
60    /// The amount of OIL this miner has earned from auction claim fees (refined OIL).
61    pub auction_refined_oil: u64,
62
63    /// The last time this miner claimed OIL rewards.
64    pub last_claim_auction_oil_at: i64,
65
66    /// The last time this miner claimed SOL rewards.
67    pub last_claim_auction_sol_at: i64,
68
69    /// The total amount of SOL this miner has mined across all blocks.
70    pub lifetime_rewards_sol: u64,
71
72    /// The total amount of OIL this miner has mined across all blocks.
73    pub lifetime_rewards_oil: u64,
74
75    /// The total amount of OIL this miner has deployed across all rounds.
76    pub lifetime_deployed: u64,
77
78    pub lifetime_bid: u64,
79
80    /// The pubkey of the referrer who referred this miner.
81    pub referrer: Pubkey,
82
83    /// Total stake score across all stake accounts for this miner.
84    pub total_stake_score: u64,
85
86    pub is_seeker: u64,
87    /// XP system (future development)
88    pub buffer_a: u64,
89    
90    /// Last epoch participated in per well (index = well_id, 0-3)
91    /// Moved from Rig to Miner to free Rig for progression/Refinery mode
92    pub current_epoch_id: [u64; 4],
93    
94    /// Last epoch checkpointed per well (index = well_id, 0-3)
95    /// Moved from Rig to Miner to free Rig for progression/Refinery mode
96    pub checkpointed_epoch_id: [u64; 4],
97}
98
99impl Miner {
100    pub fn pda(&self) -> (Pubkey, u8) {
101        miner_pda(self.authority)
102    }
103
104    pub fn initialize(&mut self, authority: Pubkey) {
105        self.authority = authority;
106        self.deployed = [0; 25];
107        self.cumulative = [0; 25];
108        self.checkpoint_fee = 0;
109        self.checkpoint_id = 0;
110        self.last_claim_block_oil_at = 0;
111        self.last_claim_block_sol_at = 0;
112        self.block_rewards_factor = Numeric::ZERO;
113        self.block_rewards_sol = 0;
114        self.block_rewards_oil = 0;
115        self.block_refined_oil = 0;
116        self.round_id = 0;
117        self.pooled_deployed = 0;
118        self.is_seeker = 0;
119        self.buffer_a = 0;
120        self.auction_rewards_oil = 0;
121        self.auction_rewards_sol = 0;
122        self.auction_rewards_factor = Numeric::ZERO;
123        self.auction_refined_oil = 0;
124        self.last_claim_auction_oil_at = 0;
125        self.last_claim_auction_sol_at = 0;
126        self.lifetime_rewards_sol = 0;
127        self.lifetime_rewards_oil = 0;
128        self.lifetime_deployed = 0;
129        self.lifetime_bid = 0;
130        self.referrer = Pubkey::default();
131        self.total_stake_score = 0;
132        self.current_epoch_id = [0; 4];
133        self.checkpointed_epoch_id = [0; 4];
134    }
135
136    pub fn claim_oil(&mut self, clock: &Clock, treasury: &mut Treasury) -> u64 {
137        self.update_rewards(treasury);
138        let refined_oil = self.block_refined_oil;
139        let rewards_oil = self.block_rewards_oil;
140        let mut amount = refined_oil + rewards_oil;
141        self.block_refined_oil = 0;
142        self.block_rewards_oil = 0;
143
144        // Charge a 10% fee and share with miners who haven't claimed yet.
145        // Check block_total_unclaimed BEFORE subtracting this miner's rewards_oil
146        // to ensure fee is charged even if this is the only miner with unclaimed oil.
147        if treasury.block_total_unclaimed > 0 {
148            let fee = rewards_oil / 10;
149            amount -= fee;
150            treasury.block_rewards_factor += Numeric::from_fraction(fee, treasury.block_total_unclaimed);
151            treasury.block_total_refined += fee;
152            self.lifetime_rewards_oil -= fee;
153        }
154        
155        treasury.block_total_unclaimed -= rewards_oil;
156        treasury.block_total_refined -= refined_oil;
157        self.last_claim_block_oil_at = clock.unix_timestamp;
158
159        amount
160    }
161
162    pub fn claim_sol(&mut self, clock: &Clock) -> u64 {
163        let amount = self.block_rewards_sol;
164        self.block_rewards_sol = 0;
165        self.last_claim_block_sol_at = clock.unix_timestamp;
166        amount
167    }
168
169    pub fn update_rewards(&mut self, treasury: &Treasury) {
170        // Accumulate rewards, weighted by stake balance.
171        if treasury.block_rewards_factor > self.block_rewards_factor {
172            let accumulated_rewards = treasury.block_rewards_factor - self.block_rewards_factor;
173            if accumulated_rewards < Numeric::ZERO {
174                panic!("Accumulated rewards is negative");
175            }
176            let personal_rewards = accumulated_rewards * Numeric::from_u64(self.block_rewards_oil);
177            self.block_refined_oil += personal_rewards.to_u64();
178            self.lifetime_rewards_oil += personal_rewards.to_u64();
179        }
180
181        // Update this miner account's last seen rewards factor.
182        self.block_rewards_factor = treasury.block_rewards_factor;
183    }
184
185    pub fn update_auction_rewards(&mut self, treasury: &Treasury) {
186        // Accumulate auction rewards, weighted by unclaimed auction OIL.
187        if treasury.auction_rewards_factor > self.auction_rewards_factor {
188            let accumulated_rewards = treasury.auction_rewards_factor - self.auction_rewards_factor;
189            if accumulated_rewards < Numeric::ZERO {
190                panic!("Accumulated auction rewards is negative");
191            }
192            let personal_rewards = accumulated_rewards * Numeric::from_u64(self.auction_rewards_oil);
193            self.auction_refined_oil += personal_rewards.to_u64();
194        }
195
196        // Update this miner account's last seen auction rewards factor.
197        self.auction_rewards_factor = treasury.auction_rewards_factor;
198    }
199}
200
201account!(OilAccount, Miner);