phoenix/program/
dispatch_market.rs

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
93/// Loads a market from a given buffer and known market params.
94pub 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}