Skip to main content

oil_api/state/
rig.rs

1use serde::{Deserialize, Serialize};
2use steel::*;
3
4use crate::state::rig_pda;
5
6use super::OilAccount;
7
8/// Rig account (one per NFT mint, links NFT to on-chain stats)
9#[repr(C)]
10#[derive(Clone, Copy, Debug, PartialEq, Pod, Zeroable, Serialize, Deserialize)]
11pub struct Rig {
12    /// The authority (owner) of this rig (matches NFT owner)
13    pub authority: Pubkey,
14
15    /// NFT mint address (used for PDA derivation)
16    pub mint: Pubkey,
17
18    /// Rig type ID (0-14)
19    pub rig_type: u64,
20
21    /// Unique rig ID (can be NFT edition number)
22    pub rig_id: u64,
23
24    /// Mining power (snapshotted at mint, immutable)
25    pub mining_power: u64,
26
27    /// Fuel requirement for placement (snapshotted at mint, immutable)
28    pub fuel_requirement: u64,
29
30    /// Fuel consumption rate per block (snapshotted at mint, immutable, in atomic units with 11 decimals)
31    pub fuel_consumption_rate: u64,
32
33    /// Purchase price in OIL (minting cost)
34    pub purchase_price: u64,
35
36    /// Timestamp when rig was purchased/minted
37    pub purchased_at: i64,
38
39    /// Plot slot (0 = not placed, 1-5 = slot number)
40    pub plot_slot: u64,
41
42    /// Buffer field (for future extensions)
43    pub buffer_a: u64,
44
45    /// Buffer field (for future extensions)
46    pub buffer_b: u64,
47
48    /// Buffer field (for future extensions)
49    pub buffer_c: u64,
50}
51
52impl Rig {
53    pub fn pda(&self) -> (Pubkey, u8) {
54        rig_pda(self.mint)
55    }
56
57    /// Get rig purchase cost in atomic units (11 decimals)
58    /// Returns None for rig_type 0 (Basic Rig - special starter pack)
59    pub fn get_purchase_cost(rig_type: u64) -> Option<u64> {
60        use crate::consts::ONE_OIL;
61        
62        // Costs in OIL (multiply by 10^11 for atomic units)
63        const RIG_COSTS: [Option<u64>; 15] = [
64            None, // 0: Basic Rig (SOL + OIL starter pack, special handling)
65            Some(21 * ONE_OIL), // 1: Small Rig (21 OIL - placeholder, needs confirmation)
66            Some(42 * ONE_OIL), // 2: Sensor Rig
67            Some(84 * ONE_OIL), // 3: Compressor Rig
68            Some(168 * ONE_OIL), // 4: Medium Rig
69            Some(336 * ONE_OIL), // 5: Large Rig
70            Some(672 * ONE_OIL), // 6: Advanced Sensor Rig
71            Some(1_344 * ONE_OIL), // 7: Turbo Compressor Rig
72            Some(2_688 * ONE_OIL), // 8: Deep Rig
73            Some(5_376 * ONE_OIL), // 9: Mega Rig
74            Some(10_752 * ONE_OIL), // 10: Epic Sensor Rig
75            Some(21_504 * ONE_OIL), // 11: Ultra Compressor Rig
76            Some(43_008 * ONE_OIL), // 12: Legendary Rig
77            Some(86_016 * ONE_OIL), // 13: Master Rig
78            Some(172_032 * ONE_OIL), // 14: Ultimate Rig
79        ];
80        
81        if rig_type >= 15 {
82            return None;
83        }
84        RIG_COSTS[rig_type as usize]
85    }
86
87    /// Display name for metadata; model rig_1..rig_15 plus edition e.g. "rig_2 #47"
88    pub fn get_rig_name(rig_type: u64, rig_id: u64) -> String {
89        if rig_type >= 15 {
90            return format!("rig_unknown #{}", rig_id + 1);
91        }
92        format!("rig_{} #{}", rig_type + 1, rig_id + 1)
93    }
94
95    /// Metadata URI by type (rig_1.json .. rig_15.json)
96    pub fn get_rig_metadata_uri(rig_type: u64) -> String {
97        if rig_type >= 15 {
98            return String::new();
99        }
100        format!(
101            "https://raw.githubusercontent.com/oil-protocol/token-metadata/main/metadata/rigs/rig_{}.json",
102            rig_type + 1
103        )
104    }
105
106    /// Model slug for display/traits (rig_1 .. rig_15). Use for UI or off-chain metadata attributes.
107    pub fn model_name(rig_type: u64) -> &'static str {
108        const MODELS: [&str; 15] = [
109            "rig_1", "rig_2", "rig_3", "rig_4", "rig_5", "rig_6", "rig_7", "rig_8",
110            "rig_9", "rig_10", "rig_11", "rig_12", "rig_13", "rig_14", "rig_15",
111        ];
112        if rig_type >= 15 {
113            "rig_unknown"
114        } else {
115            MODELS[rig_type as usize]
116        }
117    }
118
119    pub fn initialize(
120        &mut self,
121        authority: Pubkey,
122        mint: Pubkey,
123        rig_type: u64,
124        rig_id: u64,
125        mining_power: u64,
126        fuel_requirement: u64,
127        fuel_consumption_rate: u64,
128        purchase_price: u64,
129        clock: &Clock,
130    ) {
131        self.authority = authority;
132        self.mint = mint;
133        self.rig_type = rig_type;
134        self.rig_id = rig_id;
135        self.mining_power = mining_power;
136        self.fuel_requirement = fuel_requirement;
137        self.fuel_consumption_rate = fuel_consumption_rate;
138        self.purchase_price = purchase_price;
139        self.purchased_at = clock.unix_timestamp;
140        self.plot_slot = 0; // Not placed initially
141        self.buffer_a = 0;
142        self.buffer_b = 0;
143        self.buffer_c = 0;
144    }
145
146    /// Check if rig is staked (placed on plot)
147    pub fn is_staked(&self) -> bool {
148        self.plot_slot > 0
149    }
150
151    /// Place rig on plot (stake)
152    pub fn place(&mut self, slot: u64) {
153        self.plot_slot = slot;
154    }
155
156    /// Remove rig from plot (unstake)
157    pub fn remove(&mut self) {
158        self.plot_slot = 0;
159    }
160}
161
162account!(OilAccount, Rig);