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
9pub 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
47pub 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
81pub 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
114pub 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
147pub 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
180pub 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
208pub 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
241pub 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
255pub 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}