1use std::{cell::Ref, slice::Iter};
2
3use hypertree::{get_helper, trace};
4use solana_program::{
5 account_info::{next_account_info, AccountInfo},
6 program_error::ProgramError,
7 pubkey::Pubkey,
8 system_program,
9};
10
11use crate::{
12 program::ManifestError,
13 require,
14 state::{GlobalFixed, MarketFixed},
15 validation::{EmptyAccount, MintAccountInfo, Program, Signer, TokenAccountInfo},
16};
17
18use super::{get_vault_address, ManifestAccountInfo, TokenProgram};
19
20#[cfg(feature = "certora")]
21use early_panic::early_panic;
22
23pub(crate) struct CreateMarketContext<'a, 'info> {
25 pub payer: Signer<'a, 'info>,
26 pub market: ManifestAccountInfo<'a, 'info, MarketFixed>,
27 pub base_mint: MintAccountInfo<'a, 'info>,
28 pub quote_mint: MintAccountInfo<'a, 'info>,
29 pub base_vault: EmptyAccount<'a, 'info>,
30 pub quote_vault: EmptyAccount<'a, 'info>,
31 pub system_program: Program<'a, 'info>,
32 pub token_program: TokenProgram<'a, 'info>,
33 pub token_program_22: TokenProgram<'a, 'info>,
34}
35
36impl<'a, 'info> CreateMarketContext<'a, 'info> {
37 pub fn load(accounts: &'a [AccountInfo<'info>]) -> Result<Self, ProgramError> {
38 let account_iter: &mut Iter<AccountInfo<'info>> = &mut accounts.iter();
39
40 let payer: Signer = Signer::new_payer(next_account_info(account_iter)?)?;
41 let market: ManifestAccountInfo<MarketFixed> =
42 ManifestAccountInfo::<MarketFixed>::new_init(next_account_info(account_iter)?)?;
43 let system_program: Program =
44 Program::new(next_account_info(account_iter)?, &system_program::id())?;
45 let base_mint: MintAccountInfo = MintAccountInfo::new(next_account_info(account_iter)?)?;
46 let quote_mint: MintAccountInfo = MintAccountInfo::new(next_account_info(account_iter)?)?;
47 let base_vault: EmptyAccount = EmptyAccount::new(next_account_info(account_iter)?)?;
48 let quote_vault: EmptyAccount = EmptyAccount::new(next_account_info(account_iter)?)?;
49
50 let (expected_base_vault, _base_vault_bump) =
51 get_vault_address(market.key, base_mint.info.key);
52 let (expected_quote_vault, _quote_vault_bump) =
53 get_vault_address(market.key, quote_mint.info.key);
54
55 require!(
56 expected_base_vault == *base_vault.info.key,
57 ManifestError::IncorrectAccount,
58 "Incorrect base vault account",
59 )?;
60 require!(
61 expected_quote_vault == *quote_vault.info.key,
62 ManifestError::IncorrectAccount,
63 "Incorrect quote vault account",
64 )?;
65 let token_program: TokenProgram = TokenProgram::new(next_account_info(account_iter)?)?;
66 let token_program_22: TokenProgram = TokenProgram::new(next_account_info(account_iter)?)?;
67
68 Ok(Self {
69 payer,
70 market,
71 base_vault,
72 quote_vault,
73 base_mint,
74 quote_mint,
75 token_program,
76 token_program_22,
77 system_program,
78 })
79 }
80}
81
82pub(crate) struct ClaimSeatContext<'a, 'info> {
84 pub payer: Signer<'a, 'info>,
85 pub market: ManifestAccountInfo<'a, 'info, MarketFixed>,
86 pub _system_program: Program<'a, 'info>,
87}
88
89impl<'a, 'info> ClaimSeatContext<'a, 'info> {
90 #[cfg_attr(all(feature = "certora", not(feature = "certora-test")), early_panic)]
91 pub fn load(accounts: &'a [AccountInfo<'info>]) -> Result<Self, ProgramError> {
92 let account_iter: &mut Iter<AccountInfo<'info>> = &mut accounts.iter();
93
94 let payer: Signer = Signer::new(next_account_info(account_iter)?)?;
95 let market: ManifestAccountInfo<MarketFixed> =
96 ManifestAccountInfo::<MarketFixed>::new(next_account_info(account_iter)?)?;
97 let _system_program: Program =
98 Program::new(next_account_info(account_iter)?, &system_program::id())?;
99 Ok(Self {
100 payer,
101 market,
102 _system_program,
103 })
104 }
105}
106
107pub(crate) struct ExpandMarketContext<'a, 'info> {
109 pub payer: Signer<'a, 'info>,
110 pub market: ManifestAccountInfo<'a, 'info, MarketFixed>,
111 pub _system_program: Program<'a, 'info>,
112}
113
114impl<'a, 'info> ExpandMarketContext<'a, 'info> {
115 pub fn load(accounts: &'a [AccountInfo<'info>]) -> Result<Self, ProgramError> {
116 let account_iter: &mut Iter<AccountInfo<'info>> = &mut accounts.iter();
117
118 let payer: Signer = Signer::new_payer(next_account_info(account_iter)?)?;
119 let market: ManifestAccountInfo<MarketFixed> =
120 ManifestAccountInfo::<MarketFixed>::new(next_account_info(account_iter)?)?;
121 let _system_program: Program =
122 Program::new(next_account_info(account_iter)?, &system_program::id())?;
123 Ok(Self {
124 payer,
125 market,
126 _system_program,
127 })
128 }
129}
130
131pub(crate) struct DepositContext<'a, 'info> {
133 pub payer: Signer<'a, 'info>,
134 pub market: ManifestAccountInfo<'a, 'info, MarketFixed>,
135 pub trader_token: TokenAccountInfo<'a, 'info>,
136 pub vault: TokenAccountInfo<'a, 'info>,
137 pub token_program: TokenProgram<'a, 'info>,
138 pub mint: MintAccountInfo<'a, 'info>,
139}
140
141impl<'a, 'info> DepositContext<'a, 'info> {
142 #[cfg_attr(all(feature = "certora", not(feature = "certora-test")), early_panic)]
143 pub fn load(accounts: &'a [AccountInfo<'info>]) -> Result<Self, ProgramError> {
144 let account_iter: &mut Iter<AccountInfo<'info>> = &mut accounts.iter();
145
146 let payer: Signer = Signer::new(next_account_info(account_iter)?)?;
147 let market: ManifestAccountInfo<MarketFixed> =
148 ManifestAccountInfo::<MarketFixed>::new(next_account_info(account_iter)?)?;
149
150 let market_fixed: Ref<MarketFixed> = market.get_fixed()?;
151 let base_mint: &Pubkey = market_fixed.get_base_mint();
152 let quote_mint: &Pubkey = market_fixed.get_quote_mint();
153
154 let token_account_info: &AccountInfo<'info> = next_account_info(account_iter)?;
155
156 let (mint, expected_vault_address) =
158 if &token_account_info.try_borrow_data()?[0..32] == base_mint.as_ref() {
159 (base_mint, market_fixed.get_base_vault())
160 } else if &token_account_info.try_borrow_data()?[0..32] == quote_mint.as_ref() {
161 (quote_mint, market_fixed.get_quote_vault())
162 } else {
163 return Err(ManifestError::InvalidWithdrawAccounts.into());
164 };
165
166 trace!("trader token account {:?}", token_account_info.key);
167 let trader_token: TokenAccountInfo =
168 TokenAccountInfo::new_with_owner(token_account_info, mint, payer.key)?;
169
170 trace!("vault token account {:?}", expected_vault_address);
171 let vault: TokenAccountInfo = TokenAccountInfo::new_with_owner_and_key(
172 next_account_info(account_iter)?,
173 mint,
174 &expected_vault_address,
175 &expected_vault_address,
176 )?;
177
178 let token_program: TokenProgram = TokenProgram::new(next_account_info(account_iter)?)?;
179 let mint: MintAccountInfo = MintAccountInfo::new(next_account_info(account_iter)?)?;
180
181 drop(market_fixed);
183 Ok(Self {
184 payer,
185 market,
186 trader_token,
187 vault,
188 token_program,
189 mint,
190 })
191 }
192}
193
194pub(crate) struct WithdrawContext<'a, 'info> {
196 pub payer: Signer<'a, 'info>,
197 pub market: ManifestAccountInfo<'a, 'info, MarketFixed>,
198 pub trader_token: TokenAccountInfo<'a, 'info>,
199 pub vault: TokenAccountInfo<'a, 'info>,
200 pub token_program: TokenProgram<'a, 'info>,
201 pub mint: MintAccountInfo<'a, 'info>,
202}
203
204impl<'a, 'info> WithdrawContext<'a, 'info> {
205 pub fn load(accounts: &'a [AccountInfo<'info>]) -> Result<Self, ProgramError> {
206 let account_iter: &mut Iter<AccountInfo<'info>> = &mut accounts.iter();
207
208 let payer: Signer = Signer::new(next_account_info(account_iter)?)?;
209 let market: ManifestAccountInfo<MarketFixed> =
210 ManifestAccountInfo::<MarketFixed>::new(next_account_info(account_iter)?)?;
211
212 let market_fixed: Ref<MarketFixed> = market.get_fixed()?;
213 let base_mint: &Pubkey = market_fixed.get_base_mint();
214 let quote_mint: &Pubkey = market_fixed.get_quote_mint();
215
216 let token_account_info: &AccountInfo<'info> = next_account_info(account_iter)?;
217
218 let (mint, expected_vault_address) =
219 if &token_account_info.try_borrow_data()?[0..32] == base_mint.as_ref() {
220 (base_mint, market_fixed.get_base_vault())
221 } else if &token_account_info.try_borrow_data()?[0..32] == quote_mint.as_ref() {
222 (quote_mint, market_fixed.get_quote_vault())
223 } else {
224 return Err(ManifestError::InvalidWithdrawAccounts.into());
225 };
226
227 let trader_token: TokenAccountInfo =
228 TokenAccountInfo::new_with_owner(token_account_info, mint, payer.key)?;
229 let vault: TokenAccountInfo = TokenAccountInfo::new_with_owner_and_key(
230 next_account_info(account_iter)?,
231 mint,
232 &expected_vault_address,
233 &expected_vault_address,
234 )?;
235
236 let token_program: TokenProgram = TokenProgram::new(next_account_info(account_iter)?)?;
237 let mint: MintAccountInfo = MintAccountInfo::new(next_account_info(account_iter)?)?;
238
239 drop(market_fixed);
241 Ok(Self {
242 payer,
243 market,
244 trader_token,
245 vault,
246 token_program,
247 mint,
248 })
249 }
250}
251
252pub(crate) struct SwapContext<'a, 'info> {
254 pub payer: Signer<'a, 'info>,
255 pub owner: Signer<'a, 'info>,
256 pub market: ManifestAccountInfo<'a, 'info, MarketFixed>,
257 pub trader_base: TokenAccountInfo<'a, 'info>,
258 pub trader_quote: TokenAccountInfo<'a, 'info>,
259 pub base_vault: TokenAccountInfo<'a, 'info>,
260 pub quote_vault: TokenAccountInfo<'a, 'info>,
261 pub token_program_base: TokenProgram<'a, 'info>,
262 pub token_program_quote: TokenProgram<'a, 'info>,
263 pub base_mint: Option<MintAccountInfo<'a, 'info>>,
264 pub quote_mint: Option<MintAccountInfo<'a, 'info>>,
265
266 pub global_trade_accounts_opts: [Option<GlobalTradeAccounts<'a, 'info>>; 2],
268}
269
270impl<'a, 'info> SwapContext<'a, 'info> {
271 #[cfg_attr(all(feature = "certora", not(feature = "certora-test")), early_panic)]
272 pub fn load(accounts: &'a [AccountInfo<'info>]) -> Result<Self, ProgramError> {
273 let account_iter: &mut Iter<AccountInfo<'info>> = &mut accounts.iter();
274
275 let payer: Signer = Signer::new(next_account_info(account_iter)?)?;
276
277 let owner_or_market: &'a AccountInfo<'info> = next_account_info(account_iter)?;
278 let (owner, market): (Signer, ManifestAccountInfo<MarketFixed>) =
279 if *owner_or_market.owner == crate::ID {
280 (
284 payer.clone(),
285 ManifestAccountInfo::<MarketFixed>::new(owner_or_market)?,
286 )
287 } else {
288 (
290 Signer::new(owner_or_market)?,
291 ManifestAccountInfo::<MarketFixed>::new(next_account_info(account_iter)?)?,
292 )
293 };
294
295 let _system_program: Program =
297 Program::new(next_account_info(account_iter)?, &system_program::id())?;
298
299 let market_fixed: Ref<MarketFixed> = market.get_fixed()?;
300 let base_mint_key: Pubkey = *market_fixed.get_base_mint();
301 let quote_mint_key: Pubkey = *market_fixed.get_quote_mint();
302
303 let trader_base: TokenAccountInfo = TokenAccountInfo::new_with_owner(
304 next_account_info(account_iter)?,
305 &base_mint_key,
306 owner.key,
307 )?;
308 let trader_quote: TokenAccountInfo = TokenAccountInfo::new_with_owner(
309 next_account_info(account_iter)?,
310 "e_mint_key,
311 owner.key,
312 )?;
313 let base_vault_address: &Pubkey = market_fixed.get_base_vault();
314 let quote_vault_address: &Pubkey = market_fixed.get_quote_vault();
315
316 let base_vault: TokenAccountInfo = TokenAccountInfo::new_with_owner_and_key(
317 next_account_info(account_iter)?,
318 &base_mint_key,
319 &base_vault_address,
320 &base_vault_address,
321 )?;
322 let quote_vault: TokenAccountInfo = TokenAccountInfo::new_with_owner_and_key(
323 next_account_info(account_iter)?,
324 "e_mint_key,
325 "e_vault_address,
326 "e_vault_address,
327 )?;
328 drop(market_fixed);
329
330 let token_program_base: TokenProgram = TokenProgram::new(next_account_info(account_iter)?)?;
331 let mut base_mint: Option<MintAccountInfo> = None;
332
333 let mut current_account_info_or: Result<&AccountInfo<'info>, ProgramError> =
334 next_account_info(account_iter);
335
336 if current_account_info_or
338 .as_ref()
339 .is_ok_and(|f| *f.owner == spl_token::id() || *f.owner == spl_token_2022::id())
340 {
341 let current_account_info: &AccountInfo<'info> = current_account_info_or?;
342 base_mint = Some(MintAccountInfo::new(current_account_info)?);
343 current_account_info_or = next_account_info(account_iter);
344 }
345
346 let mut token_program_quote: TokenProgram = token_program_base.clone();
349 let mut quote_mint: Option<MintAccountInfo> = None;
350 let mut global_trade_accounts_opts: [Option<GlobalTradeAccounts<'a, 'info>>; 2] =
351 [None, None];
352
353 if current_account_info_or
355 .as_ref()
356 .is_ok_and(|f| *f.key == spl_token::id() || *f.key == spl_token_2022::id())
357 {
358 let current_account_info: &AccountInfo<'info> = current_account_info_or?;
359 token_program_quote = TokenProgram::new(current_account_info)?;
360 current_account_info_or = next_account_info(account_iter);
361 }
362 if current_account_info_or
364 .as_ref()
365 .is_ok_and(|f| *f.owner == spl_token::id() || *f.owner == spl_token_2022::id())
366 {
367 let current_account_info: &AccountInfo<'info> = current_account_info_or?;
368 quote_mint = Some(MintAccountInfo::new(current_account_info)?);
369 current_account_info_or = next_account_info(account_iter);
370 }
371
372 if current_account_info_or.is_ok() {
373 let current_account_info: &AccountInfo<'info> = current_account_info_or?;
374
375 if !current_account_info.data_is_empty() {
379 let global: ManifestAccountInfo<'a, 'info, GlobalFixed> =
380 ManifestAccountInfo::<GlobalFixed>::new(current_account_info)?;
381 let global_data: Ref<&mut [u8]> = global.data.borrow();
382 let global_fixed: &GlobalFixed = get_helper::<GlobalFixed>(&global_data, 0_u32);
383 let global_mint_key: &Pubkey = global_fixed.get_mint();
384 let expected_global_vault_address: &Pubkey = global_fixed.get_vault();
385
386 let global_vault: TokenAccountInfo<'a, 'info> =
387 TokenAccountInfo::new_with_owner_and_key(
388 next_account_info(account_iter)?,
389 global_mint_key,
390 &expected_global_vault_address,
391 &expected_global_vault_address,
392 )?;
393
394 let index: usize = if *global_mint_key == base_mint_key {
395 0
396 } else {
397 require!(
398 quote_mint_key == *global_mint_key,
399 ManifestError::MissingGlobal,
400 "Unexpected global accounts",
401 )?;
402 1
403 };
404
405 drop(global_data);
406 global_trade_accounts_opts[index] = Some(GlobalTradeAccounts {
407 mint_opt: if index == 0 {
408 base_mint.clone()
409 } else {
410 quote_mint.clone()
411 },
412 global,
413 global_vault_opt: Some(global_vault),
414 market_vault_opt: if index == 0 {
415 Some(base_vault.clone())
416 } else {
417 Some(quote_vault.clone())
418 },
419 token_program_opt: if index == 0 {
420 Some(token_program_base.clone())
421 } else {
422 Some(token_program_quote.clone())
423 },
424 gas_payer_opt: None,
425 gas_receiver_opt: Some(payer.clone()),
426 market: *market.info.key,
427 system_program: None,
428 });
429 }
430 }
431
432 Ok(Self {
433 payer,
434 owner,
435 market,
436 trader_base,
437 trader_quote,
438 base_vault,
439 quote_vault,
440 token_program_base,
441 token_program_quote,
442 base_mint,
443 quote_mint,
444 global_trade_accounts_opts,
445 })
446 }
447}
448
449pub struct GlobalTradeAccounts<'a, 'info> {
452 pub mint_opt: Option<MintAccountInfo<'a, 'info>>,
454 pub global: ManifestAccountInfo<'a, 'info, GlobalFixed>,
455
456 pub global_vault_opt: Option<TokenAccountInfo<'a, 'info>>,
459 pub market_vault_opt: Option<TokenAccountInfo<'a, 'info>>,
460 pub token_program_opt: Option<TokenProgram<'a, 'info>>,
461
462 pub system_program: Option<Program<'a, 'info>>,
463
464 pub gas_payer_opt: Option<Signer<'a, 'info>>,
467 pub gas_receiver_opt: Option<Signer<'a, 'info>>,
468 pub market: Pubkey,
469}
470
471pub(crate) struct BatchUpdateContext<'a, 'info> {
473 pub payer: Signer<'a, 'info>,
474 pub market: ManifestAccountInfo<'a, 'info, MarketFixed>,
475 pub _system_program: Program<'a, 'info>,
476
477 pub global_trade_accounts_opts: [Option<GlobalTradeAccounts<'a, 'info>>; 2],
479}
480
481impl<'a, 'info> BatchUpdateContext<'a, 'info> {
482 pub fn load(accounts: &'a [AccountInfo<'info>]) -> Result<Self, ProgramError> {
483 let account_iter: &mut Iter<AccountInfo<'info>> = &mut accounts.iter();
484
485 let payer: Signer = Signer::new(next_account_info(account_iter)?)?;
488 let market: ManifestAccountInfo<MarketFixed> =
489 ManifestAccountInfo::<MarketFixed>::new(next_account_info(account_iter)?)?;
490 let system_program: Program =
491 Program::new(next_account_info(account_iter)?, &system_program::id())?;
492 #[cfg(feature = "certora")]
494 let global_trade_accounts_opts: [Option<GlobalTradeAccounts<'a, 'info>>; 2] = [None, None];
495 #[cfg(not(feature = "certora"))]
496 let mut global_trade_accounts_opts: [Option<GlobalTradeAccounts<'a, 'info>>; 2] =
497 [None, None];
498
499 #[cfg(not(feature = "certora"))]
500 {
501 let market_fixed: Ref<MarketFixed> = market.get_fixed()?;
502 let base_mint: Pubkey = *market_fixed.get_base_mint();
503 let quote_mint: Pubkey = *market_fixed.get_quote_mint();
504 let base_vault: Pubkey = *market_fixed.get_base_vault();
505 let quote_vault: Pubkey = *market_fixed.get_quote_vault();
506 drop(market_fixed);
507
508 for _ in 0..2 {
509 let next_account_info_or: Result<&AccountInfo<'info>, ProgramError> =
510 next_account_info(account_iter);
511 if next_account_info_or.is_ok() {
512 let mint: MintAccountInfo<'a, 'info> =
513 MintAccountInfo::new(next_account_info_or?)?;
514 let (index, expected_market_vault_address) = if base_mint == *mint.info.key {
515 (0, &base_vault)
516 } else {
517 require!(
518 quote_mint == *mint.info.key,
519 ManifestError::MissingGlobal,
520 "Unexpected global mint",
521 )?;
522 (1, "e_vault)
523 };
524
525 let global_or: Result<
526 ManifestAccountInfo<'a, 'info, GlobalFixed>,
527 ProgramError,
528 > = ManifestAccountInfo::<GlobalFixed>::new(next_account_info(account_iter)?);
529
530 if global_or.is_err() {
534 let _global_vault: Result<&AccountInfo<'info>, ProgramError> =
535 next_account_info(account_iter);
536 let _market_vault: Result<&AccountInfo<'info>, ProgramError> =
537 next_account_info(account_iter);
538 let _token_program: Result<&AccountInfo<'info>, ProgramError> =
539 next_account_info(account_iter);
540 continue;
541 }
542 let global: ManifestAccountInfo<'a, 'info, GlobalFixed> = global_or.unwrap();
543 let global_data: Ref<&mut [u8]> = global.data.borrow();
544 let global_fixed: &GlobalFixed = get_helper::<GlobalFixed>(&global_data, 0_u32);
545 let expected_global_vault_address: &Pubkey = global_fixed.get_vault();
546
547 let global_vault: TokenAccountInfo<'a, 'info> =
548 TokenAccountInfo::new_with_owner_and_key(
549 next_account_info(account_iter)?,
550 mint.info.key,
551 &expected_global_vault_address,
552 &expected_global_vault_address,
553 )?;
554 drop(global_data);
555
556 let market_vault: TokenAccountInfo<'a, 'info> =
557 TokenAccountInfo::new_with_owner_and_key(
558 next_account_info(account_iter)?,
559 mint.info.key,
560 &expected_market_vault_address,
561 &expected_market_vault_address,
562 )?;
563 let token_program: TokenProgram<'a, 'info> =
564 TokenProgram::new(next_account_info(account_iter)?)?;
565
566 global_trade_accounts_opts[index] = Some(GlobalTradeAccounts {
567 mint_opt: Some(mint),
568 global,
569 global_vault_opt: Some(global_vault),
570 market_vault_opt: Some(market_vault),
571 token_program_opt: Some(token_program),
572 system_program: Some(system_program.clone()),
573 gas_payer_opt: Some(payer.clone()),
574 gas_receiver_opt: Some(payer.clone()),
575 market: *market.info.key,
576 })
577 };
578 }
579 }
580
581 Ok(Self {
582 payer,
583 market,
584 _system_program: system_program,
585 global_trade_accounts_opts,
586 })
587 }
588}
589
590pub(crate) struct GlobalCreateContext<'a, 'info> {
592 pub payer: Signer<'a, 'info>,
593 pub global: EmptyAccount<'a, 'info>,
594 pub system_program: Program<'a, 'info>,
595 pub global_mint: MintAccountInfo<'a, 'info>,
596 pub global_vault: EmptyAccount<'a, 'info>,
597 pub token_program: TokenProgram<'a, 'info>,
598}
599
600impl<'a, 'info> GlobalCreateContext<'a, 'info> {
601 pub fn load(accounts: &'a [AccountInfo<'info>]) -> Result<Self, ProgramError> {
602 let account_iter: &mut Iter<AccountInfo<'info>> = &mut accounts.iter();
603
604 let payer: Signer = Signer::new_payer(next_account_info(account_iter)?)?;
605 let global: EmptyAccount = EmptyAccount::new(next_account_info(account_iter)?)?;
606 let system_program: Program =
607 Program::new(next_account_info(account_iter)?, &system_program::id())?;
608 let global_mint: MintAccountInfo = MintAccountInfo::new(next_account_info(account_iter)?)?;
609 let global_vault: EmptyAccount = EmptyAccount::new(next_account_info(account_iter)?)?;
612 let token_program: TokenProgram = TokenProgram::new(next_account_info(account_iter)?)?;
613 Ok(Self {
614 payer,
615 global,
616 system_program,
617 global_mint,
618 global_vault,
619 token_program,
620 })
621 }
622}
623
624pub(crate) struct GlobalAddTraderContext<'a, 'info> {
626 pub payer: Signer<'a, 'info>,
627 pub global: ManifestAccountInfo<'a, 'info, GlobalFixed>,
628 pub _system_program: Program<'a, 'info>,
629}
630
631impl<'a, 'info> GlobalAddTraderContext<'a, 'info> {
632 pub fn load(accounts: &'a [AccountInfo<'info>]) -> Result<Self, ProgramError> {
633 let account_iter: &mut Iter<AccountInfo<'info>> = &mut accounts.iter();
634
635 let payer: Signer = Signer::new_payer(next_account_info(account_iter)?)?;
636 let global: ManifestAccountInfo<GlobalFixed> =
637 ManifestAccountInfo::<GlobalFixed>::new(next_account_info(account_iter)?)?;
638 let _system_program: Program =
639 Program::new(next_account_info(account_iter)?, &system_program::id())?;
640 Ok(Self {
641 payer,
642 global,
643 _system_program,
644 })
645 }
646}
647
648pub(crate) struct GlobalDepositContext<'a, 'info> {
650 pub payer: Signer<'a, 'info>,
651 pub global: ManifestAccountInfo<'a, 'info, GlobalFixed>,
652 pub mint: MintAccountInfo<'a, 'info>,
653 pub global_vault: TokenAccountInfo<'a, 'info>,
654 pub trader_token: TokenAccountInfo<'a, 'info>,
655 pub token_program: TokenProgram<'a, 'info>,
656}
657
658impl<'a, 'info> GlobalDepositContext<'a, 'info> {
659 pub fn load(accounts: &'a [AccountInfo<'info>]) -> Result<Self, ProgramError> {
660 let account_iter: &mut Iter<AccountInfo<'info>> = &mut accounts.iter();
661
662 let payer: Signer = Signer::new(next_account_info(account_iter)?)?;
663 let global: ManifestAccountInfo<GlobalFixed> =
664 ManifestAccountInfo::<GlobalFixed>::new(next_account_info(account_iter)?)?;
665
666 let mint: MintAccountInfo = MintAccountInfo::new(next_account_info(account_iter)?)?;
667
668 let global_data: Ref<&mut [u8]> = global.data.borrow();
669 let global_fixed: &GlobalFixed = get_helper::<GlobalFixed>(&global_data, 0_u32);
670 let expected_global_vault_address: &Pubkey = global_fixed.get_vault();
671
672 let global_vault: TokenAccountInfo = TokenAccountInfo::new_with_owner_and_key(
673 next_account_info(account_iter)?,
674 mint.info.key,
675 &expected_global_vault_address,
676 &expected_global_vault_address,
677 )?;
678 drop(global_data);
679
680 let token_account_info: &AccountInfo<'info> = next_account_info(account_iter)?;
681 let trader_token: TokenAccountInfo =
682 TokenAccountInfo::new_with_owner(token_account_info, mint.info.key, payer.key)?;
683 let token_program: TokenProgram = TokenProgram::new(next_account_info(account_iter)?)?;
684 Ok(Self {
685 payer,
686 global,
687 mint,
688 global_vault,
689 trader_token,
690 token_program,
691 })
692 }
693}
694
695pub(crate) struct GlobalWithdrawContext<'a, 'info> {
697 pub payer: Signer<'a, 'info>,
698 pub global: ManifestAccountInfo<'a, 'info, GlobalFixed>,
699 pub mint: MintAccountInfo<'a, 'info>,
700 pub global_vault: TokenAccountInfo<'a, 'info>,
701 pub trader_token: TokenAccountInfo<'a, 'info>,
702 pub token_program: TokenProgram<'a, 'info>,
703}
704
705impl<'a, 'info> GlobalWithdrawContext<'a, 'info> {
706 pub fn load(accounts: &'a [AccountInfo<'info>]) -> Result<Self, ProgramError> {
707 let account_iter: &mut Iter<AccountInfo<'info>> = &mut accounts.iter();
708
709 let payer: Signer = Signer::new(next_account_info(account_iter)?)?;
710 let global: ManifestAccountInfo<GlobalFixed> =
711 ManifestAccountInfo::<GlobalFixed>::new(next_account_info(account_iter)?)?;
712
713 let mint: MintAccountInfo = MintAccountInfo::new(next_account_info(account_iter)?)?;
714
715 let global_data: Ref<&mut [u8]> = global.data.borrow();
716 let global_fixed: &GlobalFixed = get_helper::<GlobalFixed>(&global_data, 0_u32);
717 let expected_global_vault_address: &Pubkey = global_fixed.get_vault();
718
719 let global_vault: TokenAccountInfo = TokenAccountInfo::new_with_owner_and_key(
720 next_account_info(account_iter)?,
721 mint.info.key,
722 &expected_global_vault_address,
723 &expected_global_vault_address,
724 )?;
725 drop(global_data);
726
727 let token_account_info: &AccountInfo<'info> = next_account_info(account_iter)?;
728 let trader_token: TokenAccountInfo =
729 TokenAccountInfo::new_with_owner(token_account_info, mint.info.key, payer.key)?;
730 let token_program: TokenProgram = TokenProgram::new(next_account_info(account_iter)?)?;
731 Ok(Self {
732 payer,
733 global,
734 mint,
735 global_vault,
736 trader_token,
737 token_program,
738 })
739 }
740}
741
742pub(crate) struct GlobalEvictContext<'a, 'info> {
744 pub payer: Signer<'a, 'info>,
745 pub global: ManifestAccountInfo<'a, 'info, GlobalFixed>,
746 pub mint: MintAccountInfo<'a, 'info>,
747 pub global_vault: TokenAccountInfo<'a, 'info>,
748 pub trader_token: TokenAccountInfo<'a, 'info>,
749 pub evictee_token: TokenAccountInfo<'a, 'info>,
750 pub token_program: TokenProgram<'a, 'info>,
751}
752
753impl<'a, 'info> GlobalEvictContext<'a, 'info> {
754 pub fn load(accounts: &'a [AccountInfo<'info>]) -> Result<Self, ProgramError> {
755 let account_iter: &mut Iter<AccountInfo<'info>> = &mut accounts.iter();
756
757 let payer: Signer = Signer::new_payer(next_account_info(account_iter)?)?;
758 let global: ManifestAccountInfo<GlobalFixed> =
759 ManifestAccountInfo::<GlobalFixed>::new(next_account_info(account_iter)?)?;
760
761 let mint: MintAccountInfo = MintAccountInfo::new(next_account_info(account_iter)?)?;
762
763 let global_data: Ref<&mut [u8]> = global.data.borrow();
764 let global_fixed: &GlobalFixed = get_helper::<GlobalFixed>(&global_data, 0_u32);
765 let expected_global_vault_address: &Pubkey = global_fixed.get_vault();
766
767 let global_vault: TokenAccountInfo = TokenAccountInfo::new_with_owner_and_key(
768 next_account_info(account_iter)?,
769 mint.info.key,
770 &expected_global_vault_address,
771 &expected_global_vault_address,
772 )?;
773 drop(global_data);
774
775 let token_account_info: &AccountInfo<'info> = next_account_info(account_iter)?;
776 let trader_token: TokenAccountInfo =
777 TokenAccountInfo::new_with_owner(token_account_info, mint.info.key, payer.key)?;
778 let token_account_info: &AccountInfo<'info> = next_account_info(account_iter)?;
779 let evictee_token: TokenAccountInfo =
780 TokenAccountInfo::new(token_account_info, mint.info.key)?;
781 let token_program: TokenProgram = TokenProgram::new(next_account_info(account_iter)?)?;
782 Ok(Self {
783 payer,
784 global,
785 mint,
786 global_vault,
787 trader_token,
788 evictee_token,
789 token_program,
790 })
791 }
792}
793
794pub(crate) struct GlobalCleanContext<'a, 'info> {
796 pub payer: Signer<'a, 'info>,
797 pub market: ManifestAccountInfo<'a, 'info, MarketFixed>,
798 pub system_program: Program<'a, 'info>,
799 pub global: ManifestAccountInfo<'a, 'info, GlobalFixed>,
800}
801
802impl<'a, 'info> GlobalCleanContext<'a, 'info> {
803 pub fn load(accounts: &'a [AccountInfo<'info>]) -> Result<Self, ProgramError> {
804 let account_iter: &mut Iter<AccountInfo<'info>> = &mut accounts.iter();
805
806 let payer: Signer = Signer::new_payer(next_account_info(account_iter)?)?;
807 let market: ManifestAccountInfo<MarketFixed> =
808 ManifestAccountInfo::<MarketFixed>::new(next_account_info(account_iter)?)?;
809 let system_program: Program =
810 Program::new(next_account_info(account_iter)?, &system_program::id())?;
811 let global: ManifestAccountInfo<GlobalFixed> =
812 ManifestAccountInfo::<GlobalFixed>::new(next_account_info(account_iter)?)?;
813
814 Ok(Self {
815 payer,
816 market,
817 system_program,
818 global,
819 })
820 }
821}