1use super::error::{assert_with_msg, PhoenixError};
2use super::MarketSizeParams;
3use crate::state::markets::{
4 FIFOMarket, FIFOOrderId, FIFORestingOrder, Market, MarketWrapper, MarketWrapperMut,
5 WritableMarket,
6};
7use crate::state::OrderPacket;
8use sokoban::node_allocator::ZeroCopy;
9use solana_program::{program_error::ProgramError, pubkey::Pubkey};
10
11macro_rules! fifo_market_mut {
12 ($num_bids:literal, $num_asks:literal, $num_seats:literal, $bytes:expr) => {
13 FIFOMarket::<Pubkey, $num_bids, $num_asks, $num_seats>::load_mut_bytes($bytes)
14 .ok_or(PhoenixError::FailedToLoadMarketFromAccount)?
15 as &mut dyn WritableMarket<Pubkey, FIFOOrderId, FIFORestingOrder, OrderPacket>
16 };
17}
18
19macro_rules! fifo_market {
20 ($num_bids:literal, $num_asks:literal, $num_seats:literal, $bytes:expr) => {
21 FIFOMarket::<Pubkey, $num_bids, $num_asks, $num_seats>::load_bytes($bytes)
22 .ok_or(PhoenixError::FailedToLoadMarketFromAccount)?
23 as &dyn Market<Pubkey, FIFOOrderId, FIFORestingOrder, OrderPacket>
24 };
25}
26
27macro_rules! fifo_market_size {
28 ($num_bids:literal, $num_asks:literal, $num_seats:literal) => {
29 std::mem::size_of::<FIFOMarket<Pubkey, $num_bids, $num_asks, $num_seats>>()
30 };
31}
32
33pub(crate) fn load_with_dispatch_mut<'a>(
34 market_size_params: &'a MarketSizeParams,
35 bytes: &'a mut [u8],
36) -> Result<MarketWrapperMut<'a, Pubkey, FIFOOrderId, FIFORestingOrder, OrderPacket>, ProgramError>
37{
38 dispatch_market_mut(market_size_params, bytes, false)
39}
40
41pub(crate) fn load_with_dispatch_init<'a>(
42 market_size_params: &'a MarketSizeParams,
43 bytes: &'a mut [u8],
44) -> Result<MarketWrapperMut<'a, Pubkey, FIFOOrderId, FIFORestingOrder, OrderPacket>, ProgramError>
45{
46 dispatch_market_mut(market_size_params, bytes, true)
47}
48
49pub(crate) fn dispatch_market_mut<'a>(
50 market_size_params: &'a MarketSizeParams,
51 bytes: &'a mut [u8],
52 is_initial: bool,
53) -> Result<MarketWrapperMut<'a, Pubkey, FIFOOrderId, FIFORestingOrder, OrderPacket>, ProgramError>
54{
55 let MarketSizeParams {
56 bids_size,
57 asks_size,
58 num_seats,
59 } = market_size_params;
60 let market = match (bids_size, asks_size, num_seats) {
61 (512, 512, 128) => fifo_market_mut!(512, 512, 128, bytes),
62 (512, 512, 1025) => fifo_market_mut!(512, 512, 1025, bytes),
63 (512, 512, 1153) => fifo_market_mut!(512, 512, 1153, bytes),
64 (1024, 1024, 128) => fifo_market_mut!(1024, 1024, 128, bytes),
65 (1024, 1024, 2049) => fifo_market_mut!(1024, 1024, 2049, bytes),
66 (1024, 1024, 2177) => fifo_market_mut!(1024, 1024, 2177, bytes),
67 (2048, 2048, 128) => fifo_market_mut!(2048, 2048, 128, bytes),
68 (2048, 2048, 4097) => fifo_market_mut!(2048, 2048, 4097, bytes),
69 (2048, 2048, 4225) => fifo_market_mut!(2048, 2048, 4225, bytes),
70 (4096, 4096, 128) => fifo_market_mut!(4096, 4096, 128, bytes),
71 (4096, 4096, 8193) => fifo_market_mut!(4096, 4096, 8193, bytes),
72 (4096, 4096, 8321) => fifo_market_mut!(4096, 4096, 8321, bytes),
73 _ => {
74 phoenix_log!("Invalid parameters for market");
75 return Err(PhoenixError::InvalidMarketParameters.into());
76 }
77 };
78 if !is_initial {
79 assert_with_msg(
80 market.get_sequence_number() > 0,
81 PhoenixError::MarketUninitialized,
82 "Market is not initialized",
83 )?;
84 }
85 Ok(MarketWrapperMut::<
86 Pubkey,
87 FIFOOrderId,
88 FIFORestingOrder,
89 OrderPacket,
90 >::new(market))
91}
92
93pub fn load_with_dispatch<'a>(
95 market_size_params: &'a MarketSizeParams,
96 bytes: &'a [u8],
97) -> Result<MarketWrapper<'a, Pubkey, FIFOOrderId, FIFORestingOrder, OrderPacket>, ProgramError> {
98 dispatch_market(market_size_params, bytes)
99}
100
101fn dispatch_market<'a>(
102 market_size_params: &'a MarketSizeParams,
103 bytes: &'a [u8],
104) -> Result<MarketWrapper<'a, Pubkey, FIFOOrderId, FIFORestingOrder, OrderPacket>, ProgramError> {
105 let market = match (
106 market_size_params.bids_size,
107 market_size_params.asks_size,
108 market_size_params.num_seats,
109 ) {
110 (512, 512, 128) => fifo_market!(512, 512, 128, bytes),
111 (512, 512, 1025) => fifo_market!(512, 512, 1025, bytes),
112 (512, 512, 1153) => fifo_market!(512, 512, 1153, bytes),
113 (1024, 1024, 128) => fifo_market!(1024, 1024, 128, bytes),
114 (1024, 1024, 2049) => fifo_market!(1024, 1024, 2049, bytes),
115 (1024, 1024, 2177) => fifo_market!(1024, 1024, 2177, bytes),
116 (2048, 2048, 128) => fifo_market!(2048, 2048, 128, bytes),
117 (2048, 2048, 4097) => fifo_market!(2048, 2048, 4097, bytes),
118 (2048, 2048, 4225) => fifo_market!(2048, 2048, 4225, bytes),
119 (4096, 4096, 128) => fifo_market!(4096, 4096, 128, bytes),
120 (4096, 4096, 8193) => fifo_market!(4096, 4096, 8193, bytes),
121 (4096, 4096, 8321) => fifo_market!(4096, 4096, 8321, bytes),
122 _ => {
123 phoenix_log!("Invalid parameters for market");
124 return Err(PhoenixError::InvalidMarketParameters.into());
125 }
126 };
127 Ok(MarketWrapper::<
128 Pubkey,
129 FIFOOrderId,
130 FIFORestingOrder,
131 OrderPacket,
132 >::new(market))
133}
134
135pub fn get_market_size(market_size_params: &MarketSizeParams) -> Result<usize, ProgramError> {
136 let MarketSizeParams {
137 bids_size,
138 asks_size,
139 num_seats,
140 } = market_size_params;
141 let size = match (bids_size, asks_size, num_seats) {
142 (512, 512, 128) => fifo_market_size!(512, 512, 128),
143 (512, 512, 1025) => fifo_market_size!(512, 512, 1025),
144 (512, 512, 1153) => fifo_market_size!(512, 512, 1153),
145 (1024, 1024, 128) => fifo_market_size!(1024, 1024, 128),
146 (1024, 1024, 2049) => fifo_market_size!(1024, 1024, 2049),
147 (1024, 1024, 2177) => fifo_market_size!(1024, 1024, 2177),
148 (2048, 2048, 128) => fifo_market_size!(2048, 2048, 128),
149 (2048, 2048, 4097) => fifo_market_size!(2048, 2048, 4097),
150 (2048, 2048, 4225) => fifo_market_size!(2048, 2048, 4225),
151 (4096, 4096, 128) => fifo_market_size!(4096, 4096, 128),
152 (4096, 4096, 8193) => fifo_market_size!(4096, 4096, 8193),
153 (4096, 4096, 8321) => fifo_market_size!(4096, 4096, 8321),
154 _ => {
155 phoenix_log!("Invalid parameters for market");
156 return Err(PhoenixError::InvalidMarketParameters.into());
157 }
158 };
159 Ok(size)
160}
161
162#[test]
163fn test_market_size() {
164 use solana_program::rent::Rent;
165 let valid_configs = [
166 (512, 512, 128),
167 (512, 512, 1025),
168 (512, 512, 1153),
169 (1024, 1024, 128),
170 (1024, 1024, 2049),
171 (1024, 1024, 2177),
172 (2048, 2048, 128),
173 (2048, 2048, 4097),
174 (2048, 2048, 4225),
175 (4096, 4096, 128),
176 (4096, 4096, 8193),
177 (4096, 4096, 8321),
178 ];
179 for (bids_size, asks_size, num_seats) in valid_configs.into_iter() {
180 let market_size_params = MarketSizeParams {
181 bids_size,
182 asks_size,
183 num_seats,
184 };
185 if let Ok(size) = get_market_size(&market_size_params) {
186 println!(
187 "({} {} {}) {} bytes, {} rent (SOL)",
188 bids_size,
189 asks_size,
190 num_seats,
191 size,
192 Rent::default().minimum_balance(size) as f64 / 1e9
193 );
194 } else {
195 panic!("Invalid market size params")
196 }
197 }
198 assert!(get_market_size(&MarketSizeParams {
199 bids_size: 1234,
200 asks_size: 89345,
201 num_seats: 2134
202 })
203 .is_err());
204}