1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
use borsh::{BorshDeserialize, BorshSerialize};
use solana_program::{
account_info::{next_account_info, AccountInfo},
entrypoint::ProgramResult,
msg,
program_error::ProgramError,
pubkey::Pubkey,
};
use crate::{
critbit::Slab,
state::{AccountTag, EventQueueHeader, MarketState},
utils::check_unitialized,
};
#[derive(BorshDeserialize, BorshSerialize)]
pub struct Params {
pub caller_authority: Pubkey,
pub callback_info_len: u64,
pub callback_id_len: u64,
pub min_base_order_size: u64,
}
struct Accounts<'a, 'b: 'a> {
market: &'a AccountInfo<'b>,
event_queue: &'a AccountInfo<'b>,
bids: &'a AccountInfo<'b>,
asks: &'a AccountInfo<'b>,
}
impl<'a, 'b: 'a> Accounts<'a, 'b> {
pub fn parse(
_program_id: &Pubkey,
accounts: &'a [AccountInfo<'b>],
) -> Result<Self, ProgramError> {
let accounts_iter = &mut accounts.iter();
Ok(Self {
market: next_account_info(accounts_iter)?,
event_queue: next_account_info(accounts_iter)?,
bids: next_account_info(accounts_iter)?,
asks: next_account_info(accounts_iter)?,
})
}
}
pub(crate) fn process(
program_id: &Pubkey,
accounts: &[AccountInfo],
params: Params,
) -> ProgramResult {
let accounts = Accounts::parse(program_id, accounts)?;
let Params {
caller_authority,
callback_info_len,
callback_id_len,
min_base_order_size,
} = params;
if accounts.event_queue.owner != program_id {
msg!("The event queue should be owned by the AO program");
return Err(ProgramError::InvalidArgument);
}
if accounts.bids.owner != program_id {
msg!("The bids account should be owned by the AO program");
return Err(ProgramError::InvalidArgument);
}
if accounts.asks.owner != program_id {
msg!("The asks account should be owned by the AO program");
return Err(ProgramError::InvalidArgument);
}
check_unitialized(accounts.event_queue)?;
check_unitialized(accounts.bids)?;
check_unitialized(accounts.asks)?;
check_unitialized(accounts.market)?;
let market_state = MarketState {
tag: AccountTag::Market,
caller_authority,
event_queue: *accounts.event_queue.key,
bids: *accounts.bids.key,
asks: *accounts.asks.key,
callback_info_len,
callback_id_len,
fee_budget: 0,
initial_lamports: accounts.market.lamports(),
min_base_order_size,
};
let event_queue_header = EventQueueHeader::initialize(params.callback_info_len as usize);
event_queue_header
.serialize(&mut (&mut accounts.event_queue.data.borrow_mut() as &mut [u8]))
.unwrap();
Slab::initialize(accounts.bids, accounts.asks, *accounts.market.key);
let mut market_data: &mut [u8] = &mut accounts.market.data.borrow_mut();
market_state.serialize(&mut market_data).unwrap();
Ok(())
}