Skip to main content

tengu_api/state/
forge.rs

1use super::DojosAccount;
2use steel::*;
3
4#[repr(C)]
5#[derive(Clone, Copy, Debug, PartialEq, bytemuck::Pod, bytemuck::Zeroable)]
6pub struct Forge {
7    pub dojo: Pubkey,
8    pub level: u64,
9    pub ore_queued: u64,
10    pub last_refine_slot: u64,
11    pub upgrade_cooldown_slot: u64,
12    pub buffer1: u64,
13    pub buffer2: u64,
14}
15
16account!(DojosAccount, Forge);
17
18impl Forge {
19    /// Ore per second throughput.
20    pub fn throughput(level: u64) -> f64 {
21        match level {
22            1 => 1.0 / 8.0,
23            2 => 1.0 / 6.0,
24            3 => 1.0 / 5.0,
25            4 => 1.0 / 4.0,
26            5 => 1.0 / 3.0,
27            6 => 1.0 / 2.0,
28            7 => 1.0,       // Lv.7 max: 1.0 ore/s = 1.0 $DOJO/s
29            _ => 1.0 / 8.0,
30        }
31    }
32
33    /// Raw $DOJO (6 decimals) per ore. 1:1 (matches Hyper Ninja: throughput only, no separate refine rate).
34    pub fn refine_rate(_level: u64) -> u64 {
35        crate::consts::ONE_DOJO // 1 ore = 1 $DOJO
36    }
37
38    pub fn upgrade_cost(from_level: u64) -> u64 {
39        match from_level {
40            1 => crate::consts::FORGE_COST_1_2,
41            2 => crate::consts::FORGE_COST_2_3,
42            3 => crate::consts::FORGE_COST_3_4,
43            4 => crate::consts::FORGE_COST_4_5,
44            5 => crate::consts::FORGE_COST_5_6,
45            6 => crate::consts::FORGE_COST_6_7,
46            _ => u64::MAX,
47        }
48    }
49
50    /// Forge upgrades always pay SOL.
51    pub fn upgrade_pays_sol(_from_level: u64) -> bool {
52        true
53    }
54
55    pub fn upgrade_cooldown(from_level: u64) -> u64 {
56        match from_level {
57            1 => crate::consts::FORGE_COOLDOWN_1_2,
58            2 => crate::consts::FORGE_COOLDOWN_2_3,
59            3 => crate::consts::FORGE_COOLDOWN_3_4,
60            4 => crate::consts::FORGE_COOLDOWN_4_5,
61            5 => crate::consts::FORGE_COOLDOWN_5_6,
62            6 => crate::consts::FORGE_COOLDOWN_6_7,
63            _ => 0,
64        }
65    }
66
67    /// Remaining seconds until cooldown ends. 0 when no cooldown or timer has ended.
68    /// `now` is current Solana slot.
69    pub fn cooldown_remaining_seconds(&self, now: u64) -> u64 {
70        if self.upgrade_cooldown_slot == 0 || now >= self.upgrade_cooldown_slot {
71            return 0;
72        }
73        let remaining_slots = self.upgrade_cooldown_slot - now;
74        (remaining_slots as f64 * crate::consts::SECONDS_PER_SLOT) as u64
75    }
76
77    /// Remaining minutes (floor). For display: 0 when in last minute (e.g. 30 sec left → 0 mins).
78    pub fn cooldown_remaining_minutes(&self, now: u64) -> u64 {
79        self.cooldown_remaining_seconds(now) / 60
80    }
81}