Skip to main content

ore_api/state/
automation.rs

1use ore_mint_api::consts::ONE_ORE;
2use serde::{Deserialize, Serialize};
3use steel::*;
4
5use crate::state::{automation_pda, OreAccountV4};
6
7use super::OreAccountV1;
8
9#[repr(C)]
10#[derive(Clone, Copy, Debug, PartialEq, Pod, Zeroable, Serialize, Deserialize)]
11pub struct AutomationV1 {
12    /// The amount of SOL to deploy on each territory per round.
13    pub amount: u64,
14
15    /// The authority of this automation account.
16    pub authority: Pubkey,
17
18    /// The amount of SOL this automation has left.
19    pub balance: u64,
20
21    /// The executor of this automation account.
22    pub executor: Pubkey,
23
24    /// The amount of SOL the executor should receive in fees.
25    pub fee: u64,
26
27    /// The strategy this automation uses.
28    pub strategy: u64,
29
30    /// The mask of squares this automation should deploy to if preferred strategy.
31    /// If strategy is Random, first bit is used to determine how many squares to deploy to.
32    pub mask: u64,
33
34    /// Whether or not to auto-reload SOL winnings into the automation balance.
35    pub reload: u64,
36}
37
38#[repr(C)]
39#[derive(Clone, Copy, Debug, PartialEq, Pod, Zeroable, Serialize, Deserialize)]
40pub struct AutomationV4 {
41    /// The amount of SOL to deploy on each territory per round.
42    pub amount: u64,
43
44    /// The authority of this automation account.
45    pub authority: Pubkey,
46
47    /// The amount of SOL this automation has left.
48    pub balance: u64,
49
50    /// The executor of this automation account.
51    pub executor: Pubkey,
52
53    /// The amount of SOL the executor should receive in fees.
54    pub fee: u64,
55
56    /// The strategy this automation uses.
57    pub strategy: u64,
58
59    /// The mask of squares this automation should deploy to if preferred strategy.
60    /// If strategy is Random, first bit is used to determine how many squares to deploy to.
61    pub mask: u64,
62
63    /// Whether or not to auto-reload SOL winnings into the automation balance.
64    pub reload: u64,
65
66    /// The total SOL spent (lost to fees) by this automation.
67    pub total_sol_spent: u64,
68
69    /// The total ORE earned by this automation.
70    pub total_ore_earned: u64,
71
72    /// Conditions that must be met for the automation to deploy.
73    pub conditions: AutomationConditions,
74}
75
76/// Conditions that gate whether an automation deploys in a given round.
77#[repr(C)]
78#[derive(Clone, Copy, Debug, PartialEq, Pod, Zeroable, Serialize, Deserialize)]
79pub struct AutomationConditions {
80    /// Max production cost EMA (lamports per whole ORE). Deploy blocked if EMA exceeds this.
81    /// Default: u64::MAX (no upper bound).
82    pub max_production_cost: u64,
83
84    /// Min motherlode amount (ORE units). Deploy blocked if motherlode is below this.
85    /// Default: 0 (no lower bound).
86    pub min_motherlode: u64,
87
88    /// Max motherlode amount (ORE units). Deploy blocked if motherlode exceeds this.
89    /// Default: u64::MAX (no upper bound).
90    pub max_motherlode: u64,
91}
92
93#[repr(u8)]
94#[derive(Clone, Copy, Debug, PartialEq, IntoPrimitive, TryFromPrimitive)]
95pub enum AutomationStrategy {
96    Random = 0,
97    Preferred = 1,
98    Discretionary = 2,
99}
100
101impl AutomationStrategy {
102    pub fn from_u64(value: u64) -> Self {
103        Self::try_from(value as u8).unwrap()
104    }
105}
106
107impl Default for AutomationConditions {
108    fn default() -> Self {
109        Self {
110            max_production_cost: u64::MAX,
111            min_motherlode: 0,
112            max_motherlode: u64::MAX,
113        }
114    }
115}
116
117impl AutomationV4 {
118    pub fn pda(&self) -> (Pubkey, u8) {
119        automation_pda(self.authority)
120    }
121
122    pub fn production_cost(&self) -> u64 {
123        if self.total_ore_earned == 0 {
124            return 0;
125        }
126        ((self.total_sol_spent as u128) * (ONE_ORE as u128) / (self.total_ore_earned as u128))
127            as u64
128    }
129}
130
131account!(OreAccountV1, AutomationV1);
132account!(OreAccountV4, AutomationV4);
133
134pub enum Automation {
135    V1(AutomationV1),
136    V4(AutomationV4),
137}
138
139impl Automation {
140    pub fn amount(&self) -> u64 {
141        match self {
142            Automation::V1(a) => a.amount,
143            Automation::V4(a) => a.amount,
144        }
145    }
146
147    pub fn authority(&self) -> Pubkey {
148        match self {
149            Automation::V1(a) => a.authority,
150            Automation::V4(a) => a.authority,
151        }
152    }
153
154    pub fn balance(&self) -> u64 {
155        match self {
156            Automation::V1(a) => a.balance,
157            Automation::V4(a) => a.balance,
158        }
159    }
160
161    pub fn executor(&self) -> Pubkey {
162        match self {
163            Automation::V1(a) => a.executor,
164            Automation::V4(a) => a.executor,
165        }
166    }
167
168    pub fn fee(&self) -> u64 {
169        match self {
170            Automation::V1(a) => a.fee,
171            Automation::V4(a) => a.fee,
172        }
173    }
174
175    pub fn strategy(&self) -> u64 {
176        match self {
177            Automation::V1(a) => a.strategy,
178            Automation::V4(a) => a.strategy,
179        }
180    }
181
182    pub fn mask(&self) -> u64 {
183        match self {
184            Automation::V1(a) => a.mask,
185            Automation::V4(a) => a.mask,
186        }
187    }
188
189    pub fn reload(&self) -> u64 {
190        match self {
191            Automation::V1(a) => a.reload,
192            Automation::V4(a) => a.reload,
193        }
194    }
195}