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    /// Accumulated when ownership changes (pre-minted) or when claiming current ownership (minted on-demand)
53    pub auction_rewards_oil: u64,
54
55    /// SOL rewards from auction wells (not yet claimed)
56    /// Includes: outbid refunds, pool refunds from abandoned pools
57    pub auction_rewards_sol: u64,
58
59    /// The rewards factor last time auction rewards were updated on this rig account.
60    pub auction_rewards_factor: Numeric,
61
62    /// The amount of OIL this rig has earned from auction claim fees (refined OIL).
63    pub auction_refined_oil: u64,
64
65    /// The last time this rig claimed OIL rewards.
66    pub last_claim_auction_oil_at: i64,
67
68    /// The last time this rig claimed SOL rewards.
69    pub last_claim_auction_sol_at: i64,
70
71    /// The total amount of SOL this miner has mined across all blocks.
72    pub lifetime_rewards_sol: u64,
73
74    /// The total amount of OIL this miner has mined across all blocks.
75    pub lifetime_rewards_oil: u64,
76
77    /// The total amount of OIL this miner has deployed across all rounds.
78    pub lifetime_deployed: u64,
79
80    pub lifetime_bid: u64,
81
82    /// The pubkey of the referrer who referred this miner.
83    /// If this is Pubkey::default(), the miner has no referrer (either old account or no referral used).
84    pub referrer: Pubkey,
85
86    /// Total stake score across all stake accounts for this miner.
87    /// Used for governance voting power calculation.
88    /// Updated whenever the miner deposits or withdraws from any stake account.
89    pub total_stake_score: u64,
90}
91
92impl Miner {
93    pub fn pda(&self) -> (Pubkey, u8) {
94        miner_pda(self.authority)
95    }
96
97    pub fn claim_oil(&mut self, clock: &Clock, treasury: &mut Treasury) -> u64 {
98        self.update_rewards(treasury);
99        let refined_oil = self.block_refined_oil;
100        let rewards_oil = self.block_rewards_oil;
101        let mut amount = refined_oil + rewards_oil;
102        self.block_refined_oil = 0;
103        self.block_rewards_oil = 0;
104
105        // Charge a 10% fee and share with miners who haven't claimed yet.
106        // Check block_total_unclaimed BEFORE subtracting this miner's rewards_oil
107        // to ensure fee is charged even if this is the only miner with unclaimed oil.
108        if treasury.block_total_unclaimed > 0 {
109            let fee = rewards_oil / 10;
110            amount -= fee;
111            treasury.block_rewards_factor += Numeric::from_fraction(fee, treasury.block_total_unclaimed);
112            treasury.block_total_refined += fee;
113            self.lifetime_rewards_oil -= fee;
114        }
115        
116        treasury.block_total_unclaimed -= rewards_oil;
117        treasury.block_total_refined -= refined_oil;
118        self.last_claim_block_oil_at = clock.unix_timestamp;
119
120        amount
121    }
122
123    pub fn claim_sol(&mut self, clock: &Clock) -> u64 {
124        let amount = self.block_rewards_sol;
125        self.block_rewards_sol = 0;
126        self.last_claim_block_sol_at = clock.unix_timestamp;
127        amount
128    }
129
130    pub fn update_rewards(&mut self, treasury: &Treasury) {
131        // Accumulate rewards, weighted by stake balance.
132        if treasury.block_rewards_factor > self.block_rewards_factor {
133            let accumulated_rewards = treasury.block_rewards_factor - self.block_rewards_factor;
134            if accumulated_rewards < Numeric::ZERO {
135                panic!("Accumulated rewards is negative");
136            }
137            let personal_rewards = accumulated_rewards * Numeric::from_u64(self.block_rewards_oil);
138            self.block_refined_oil += personal_rewards.to_u64();
139            self.lifetime_rewards_oil += personal_rewards.to_u64();
140        }
141
142        // Update this miner account's last seen rewards factor.
143        self.block_rewards_factor = treasury.block_rewards_factor;
144    }
145
146    pub fn update_auction_rewards(&mut self, treasury: &Treasury) {
147        // Accumulate auction rewards, weighted by unclaimed auction OIL.
148        if treasury.auction_rewards_factor > self.auction_rewards_factor {
149            let accumulated_rewards = treasury.auction_rewards_factor - self.auction_rewards_factor;
150            if accumulated_rewards < Numeric::ZERO {
151                panic!("Accumulated auction rewards is negative");
152            }
153            let personal_rewards = accumulated_rewards * Numeric::from_u64(self.auction_rewards_oil);
154            self.auction_refined_oil += personal_rewards.to_u64();
155        }
156
157        // Update this miner account's last seen auction rewards factor.
158        self.auction_rewards_factor = treasury.auction_rewards_factor;
159    }
160}
161
162account!(OilAccount, Miner);