phoenix/program/processor/
manage_seat.rs1use crate::program::{
2 dispatch_market::load_with_dispatch_mut, error::assert_with_msg, loaders::get_seat_address,
3 status::SeatApprovalStatus, system_utils::create_account, AuthorizedSeatRequestContext,
4 MarketHeader, ModifySeatContext, PhoenixMarketContext, RequestSeatContext, Seat,
5};
6use borsh::BorshDeserialize;
7use sokoban::node_allocator::ZeroCopy;
8use solana_program::{
9 account_info::AccountInfo, entrypoint::ProgramResult, program_error::ProgramError,
10 pubkey::Pubkey, rent::Rent, sysvar::Sysvar,
11};
12use std::mem::size_of;
13
14pub(crate) fn process_request_seat_authorized<'a, 'info>(
16 _program_id: &Pubkey,
17 market_context: &PhoenixMarketContext<'a, 'info>,
18 accounts: &'a [AccountInfo<'info>],
19 _data: &[u8],
20) -> ProgramResult {
21 let AuthorizedSeatRequestContext {
22 payer,
23 trader,
24 seat,
25 system_program,
26 } = AuthorizedSeatRequestContext::load(market_context, accounts)?;
27 _create_seat(
28 payer.as_ref(),
29 trader.key,
30 seat.as_ref(),
31 market_context.market_info.key,
32 system_program.as_ref(),
33 )
34}
35
36pub(crate) fn process_request_seat<'a, 'info>(
38 _program_id: &Pubkey,
39 market_context: &PhoenixMarketContext<'a, 'info>,
40 accounts: &'a [AccountInfo<'info>],
41 _data: &[u8],
42) -> ProgramResult {
43 let RequestSeatContext {
44 seat,
45 system_program,
46 ..
47 } = RequestSeatContext::load(market_context, accounts)?;
48 let PhoenixMarketContext {
49 market_info,
50 signer: trader,
51 } = market_context;
52 _create_seat(
53 trader.as_ref(),
54 trader.key,
55 seat.as_ref(),
56 market_info.key,
57 system_program.as_ref(),
58 )
59}
60
61fn _create_seat<'a, 'info>(
62 payer: &'a AccountInfo<'info>,
63 trader: &'a Pubkey,
64 seat: &'a AccountInfo<'info>,
65 market_key: &Pubkey,
66 system_program: &'a AccountInfo<'info>,
67) -> ProgramResult {
68 let (seat_address, bump) = get_seat_address(market_key, trader);
69 assert_with_msg(
70 &seat_address == seat.key,
71 ProgramError::InvalidAccountData,
72 "Invalid seat address",
73 )?;
74 let space = size_of::<Seat>();
75 let seeds = vec![
76 b"seat".to_vec(),
77 market_key.as_ref().to_vec(),
78 trader.as_ref().to_vec(),
79 vec![bump],
80 ];
81 create_account(
82 payer,
83 seat,
84 system_program,
85 &crate::id(),
86 &Rent::get()?,
87 space as u64,
88 seeds,
89 )?;
90 let mut seat_bytes = seat.try_borrow_mut_data()?;
91 *Seat::load_mut_bytes(&mut seat_bytes).ok_or(ProgramError::InvalidAccountData)? =
92 Seat::new_init(*market_key, *trader)?;
93 Ok(())
94}
95
96pub(crate) fn process_change_seat_status<'a, 'info>(
99 _program_id: &Pubkey,
100 market_context: &PhoenixMarketContext<'a, 'info>,
101 accounts: &'a [AccountInfo<'info>],
102 data: &[u8],
103) -> ProgramResult {
104 let ModifySeatContext { seat: seat_info } = ModifySeatContext::load(market_context, accounts)?;
105 let PhoenixMarketContext {
106 market_info,
107 signer: _,
108 } = market_context;
109 let new_status = SeatApprovalStatus::try_from_slice(data)?;
110 let mut seat = seat_info.load_mut()?;
111 let current_status = SeatApprovalStatus::from(seat.approval_status);
112 if current_status == new_status {
113 phoenix_log!("Seat status is unchanged");
114 return Ok(());
115 }
116 match (current_status, new_status) {
117 (SeatApprovalStatus::NotApproved, SeatApprovalStatus::Approved) => {
118 seat.approval_status = SeatApprovalStatus::Approved as u64;
119 let market_bytes = &mut market_info.try_borrow_mut_data()?[size_of::<MarketHeader>()..];
121 let market = load_with_dispatch_mut(&market_info.size_params, market_bytes)?.inner;
122 assert_with_msg(
123 market.get_or_register_trader(&seat.trader).is_some(),
124 ProgramError::InvalidArgument,
125 "Failed to register trader",
126 )?;
127 }
128 (SeatApprovalStatus::Approved, SeatApprovalStatus::NotApproved) => {
129 seat.approval_status = SeatApprovalStatus::NotApproved as u64;
130 }
131 (SeatApprovalStatus::Approved, SeatApprovalStatus::Retired) => {
132 seat.approval_status = SeatApprovalStatus::Retired as u64;
133 }
134 (SeatApprovalStatus::NotApproved, SeatApprovalStatus::Retired) => {
135 seat.approval_status = SeatApprovalStatus::Retired as u64;
136 }
137 _ => {
138 phoenix_log!(
139 "Invalid seat status transition from {} to {}",
140 current_status,
141 new_status
142 );
143 return Err(ProgramError::InvalidInstructionData);
144 }
145 }
146 Ok(())
147}