smelter_api/
loaders.rs

1use solana_program::{account_info::AccountInfo, program_error::ProgramError, pubkey::Pubkey};
2
3use crate::{
4    consts::*,
5    state::{Bus, Config, Proof, Treasury},
6    utils::{loaders::*, AccountDeserialize, Discriminator},
7};
8
9/// Errors if:
10/// - Owner is not Ore program.
11/// - Address does not match the expected bus address.
12/// - Data is empty.
13/// - Data cannot deserialize into a bus account.
14/// - Bus ID does not match the expected ID.
15/// - Expected to be writable, but is not.
16pub fn load_bus<'a, 'info>(
17    info: &'a AccountInfo<'info>,
18    id: u64,
19    is_writable: bool,
20) -> Result<(), ProgramError> {
21    if info.owner.ne(&crate::id()) {
22        return Err(ProgramError::InvalidAccountOwner);
23    }
24
25    if info.key.ne(&BUS_ADDRESSES[id as usize]) {
26        return Err(ProgramError::InvalidSeeds);
27    }
28
29    if info.data_is_empty() {
30        return Err(ProgramError::UninitializedAccount);
31    }
32
33    let bus_data = info.data.borrow();
34    let bus = Bus::try_from_bytes(&bus_data)?;
35
36    if bus.id.ne(&id) {
37        return Err(ProgramError::InvalidAccountData);
38    }
39
40    if is_writable && !info.is_writable {
41        return Err(ProgramError::InvalidAccountData);
42    }
43
44    Ok(())
45}
46
47/// Errors if:
48/// - Owner is not Ore program.
49/// - Data is empty.
50/// - Data cannot deserialize into a bus account.
51/// - Bus ID is not in the expected range.
52/// - Address is not in set of valid bus address.
53/// - Expected to be writable, but is not.
54pub fn load_any_bus<'a, 'info>(
55    info: &'a AccountInfo<'info>,
56    is_writable: bool,
57) -> Result<(), ProgramError> {
58    if info.owner.ne(&crate::id()) {
59        return Err(ProgramError::InvalidAccountOwner);
60    }
61
62    if info.data_is_empty() {
63        return Err(ProgramError::UninitializedAccount);
64    }
65
66    if info.data.borrow()[0].ne(&(Bus::discriminator() as u8)) {
67        return Err(solana_program::program_error::ProgramError::InvalidAccountData);
68    }
69
70    if !BUS_ADDRESSES.contains(info.key) {
71        return Err(ProgramError::InvalidSeeds);
72    }
73
74    if is_writable && !info.is_writable {
75        return Err(ProgramError::InvalidAccountData);
76    }
77
78    Ok(())
79}
80
81/// Errors if:
82/// - Owner is not Ore program.
83/// - Address does not match the expected address.
84/// - Data is empty.
85/// - Data cannot deserialize into a config account.
86/// - Expected to be writable, but is not.
87pub fn load_config<'a, 'info>(
88    info: &'a AccountInfo<'info>,
89    is_writable: bool,
90) -> Result<(), ProgramError> {
91    if info.owner.ne(&crate::id()) {
92        return Err(ProgramError::InvalidAccountOwner);
93    }
94
95    if info.key.ne(&CONFIG_ADDRESS) {
96        return Err(ProgramError::InvalidSeeds);
97    }
98
99    if info.data_is_empty() {
100        return Err(ProgramError::UninitializedAccount);
101    }
102
103    if info.data.borrow()[0].ne(&(Config::discriminator() as u8)) {
104        return Err(solana_program::program_error::ProgramError::InvalidAccountData);
105    }
106
107    if is_writable && !info.is_writable {
108        return Err(ProgramError::InvalidAccountData);
109    }
110
111    Ok(())
112}
113
114/// Errors if:
115/// - Owner is not Ore program.
116/// - Data is empty.
117/// - Data cannot deserialize into a proof account.
118/// - Proof authority does not match the expected address.
119/// - Expected to be writable, but is not.
120pub fn load_proof<'a, 'info>(
121    info: &'a AccountInfo<'info>,
122    authority: &Pubkey,
123    is_writable: bool,
124) -> Result<(), ProgramError> {
125    if info.owner.ne(&crate::id()) {
126        return Err(ProgramError::InvalidAccountOwner);
127    }
128
129    if info.data_is_empty() {
130        return Err(ProgramError::UninitializedAccount);
131    }
132
133    let proof_data = info.data.borrow();
134    let proof = Proof::try_from_bytes(&proof_data)?;
135
136    if proof.authority.ne(&authority) {
137        return Err(ProgramError::InvalidAccountData);
138    }
139
140    if is_writable && !info.is_writable {
141        return Err(ProgramError::InvalidAccountData);
142    }
143
144    Ok(())
145}
146
147/// Errors if:
148/// - Owner is not Ore program.
149/// - Data is empty.
150/// - Data cannot deserialize into a proof account.
151/// - Proof miner does not match the expected address.
152/// - Expected to be writable, but is not.
153pub fn load_proof_with_miner<'a, 'info>(
154    info: &'a AccountInfo<'info>,
155    miner: &Pubkey,
156    is_writable: bool,
157) -> Result<(), ProgramError> {
158    if info.owner.ne(&crate::id()) {
159        return Err(ProgramError::InvalidAccountOwner);
160    }
161
162    if info.data_is_empty() {
163        return Err(ProgramError::UninitializedAccount);
164    }
165
166    let proof_data = info.data.borrow();
167    let proof = Proof::try_from_bytes(&proof_data)?;
168
169    if proof.miner.ne(&miner) {
170        return Err(ProgramError::InvalidAccountData);
171    }
172
173    if is_writable && !info.is_writable {
174        return Err(ProgramError::InvalidAccountData);
175    }
176
177    Ok(())
178}
179
180/// Errors if:
181/// - Owner is not Ore program.
182/// - Data is empty.
183/// - Data cannot deserialize into a proof account.
184/// - Expected to be writable, but is not.
185pub fn load_any_proof<'a, 'info>(
186    info: &'a AccountInfo<'info>,
187    is_writable: bool,
188) -> Result<(), ProgramError> {
189    if info.owner.ne(&crate::id()) {
190        return Err(ProgramError::InvalidAccountOwner);
191    }
192
193    if info.data_is_empty() {
194        return Err(ProgramError::UninitializedAccount);
195    }
196
197    if info.data.borrow()[0].ne(&(Proof::discriminator() as u8)) {
198        return Err(solana_program::program_error::ProgramError::InvalidAccountData);
199    }
200
201    if is_writable && !info.is_writable {
202        return Err(ProgramError::InvalidAccountData);
203    }
204
205    Ok(())
206}
207
208/// Errors if:
209/// - Owner is not Ore program.
210/// - Address does not match the expected address.
211/// - Data is empty.
212/// - Data cannot deserialize into a treasury account.
213/// - Expected to be writable, but is not.
214pub fn load_treasury<'a, 'info>(
215    info: &'a AccountInfo<'info>,
216    is_writable: bool,
217) -> Result<(), ProgramError> {
218    if info.owner.ne(&crate::id()) {
219        return Err(ProgramError::InvalidAccountOwner);
220    }
221
222    if info.key.ne(&TREASURY_ADDRESS) {
223        return Err(ProgramError::InvalidSeeds);
224    }
225
226    if info.data_is_empty() {
227        return Err(ProgramError::UninitializedAccount);
228    }
229
230    if info.data.borrow()[0].ne(&(Treasury::discriminator() as u8)) {
231        return Err(solana_program::program_error::ProgramError::InvalidAccountData);
232    }
233
234    if is_writable && !info.is_writable {
235        return Err(ProgramError::InvalidAccountData);
236    }
237
238    Ok(())
239}
240
241/// Errors if:
242/// - Address does not match the expected treasury tokens address.
243/// - Cannot load as a token account
244pub fn load_treasury_tokens<'a, 'info>(
245    info: &'a AccountInfo<'info>,
246    is_writable: bool,
247) -> Result<(), ProgramError> {
248    if info.key.ne(&TREASURY_TOKENS_ADDRESS) {
249        return Err(ProgramError::InvalidSeeds);
250    }
251
252    load_token_account(info, Some(&TREASURY_ADDRESS), &MINT_ADDRESS, is_writable)
253}
254
255/// Errors if:
256/// - Address does not match the expected treasury tokens address.
257/// - Cannot load as a token accoun
258pub fn load_treasury_ore_tokens<'a, 'info>(
259    info: &'a AccountInfo<'info>,
260    is_writable: bool,
261) -> Result<(), ProgramError> {
262    if info.key.ne(&TREASURY_ORE_TOKENS_ADDRESS) {
263        return Err(ProgramError::InvalidSeeds);
264    }
265
266    load_token_account(info, Some(&TREASURY_ADDRESS), &ORE_MINT_ADDRESS, is_writable)
267}