1use borsh::BorshSerialize;
2use sha2::{Digest, Sha256};
3#[allow(deprecated)]
4use solana_sdk::{
5 instruction::{AccountMeta, Instruction},
6 pubkey::Pubkey,
7 system_program,
8};
9
10pub fn anchor_discriminator(name: &str) -> [u8; 8] {
12 let hash = Sha256::digest(format!("global:{name}").as_bytes());
13 let mut disc = [0u8; 8];
14 disc.copy_from_slice(&hash[..8]);
15 disc
16}
17
18pub fn build_ix(
20 program_id: &Pubkey,
21 name: &str,
22 args: impl BorshSerialize,
23 accounts: Vec<AccountMeta>,
24) -> Instruction {
25 let mut data = anchor_discriminator(name).to_vec();
26 args.serialize(&mut data).expect("borsh serialize");
27 Instruction {
28 program_id: *program_id,
29 accounts,
30 data,
31 }
32}
33
34#[derive(BorshSerialize)]
37pub struct InitializeMarketArgs {
38 pub init_slot: u64,
39 pub init_oracle_price: u64,
40 pub params: RiskParamsInput,
41}
42
43#[derive(BorshSerialize)]
44pub struct RiskParamsInput {
45 pub warmup_period_slots: u64,
46 pub maintenance_margin_bps: u64,
47 pub initial_margin_bps: u64,
48 pub trading_fee_bps: u64,
49 pub max_accounts: u64,
50 pub new_account_fee: u64,
51 pub maintenance_fee_per_slot: u64,
52 pub max_crank_staleness_slots: u64,
53 pub liquidation_fee_bps: u64,
54 pub liquidation_fee_cap: u64,
55 pub min_liquidation_abs: u64,
56 pub min_initial_deposit: u64,
57 pub min_nonzero_mm_req: u64,
58 pub min_nonzero_im_req: u64,
59 pub insurance_floor: u64,
60}
61
62#[derive(BorshSerialize)]
63pub struct DepositArgs {
64 pub account_idx: u16,
65 pub amount: u64,
66}
67
68#[derive(BorshSerialize)]
69pub struct WithdrawArgs {
70 pub account_idx: u16,
71 pub amount: u64,
72 pub funding_rate: i64,
73}
74
75#[derive(BorshSerialize)]
76pub struct TradeArgs {
77 pub account_a: u16,
78 pub account_b: u16,
79 pub size_q: i128,
80 pub exec_price: u64,
81 pub funding_rate: i64,
82}
83
84#[derive(BorshSerialize)]
85pub struct CrankArgs {
86 pub funding_rate: i64,
87}
88
89#[derive(BorshSerialize)]
90pub struct LiquidateArgs {
91 pub account_idx: u16,
92 pub funding_rate: i64,
93}
94
95#[derive(BorshSerialize)]
96pub struct SettleArgs {
97 pub account_idx: u16,
98 pub funding_rate: i64,
99}
100
101#[derive(BorshSerialize)]
102pub struct CloseAccountArgs {
103 pub account_idx: u16,
104 pub funding_rate: i64,
105}
106
107pub fn initialize_market_ix(
110 program_id: &Pubkey,
111 market: &Pubkey,
112 authority: &Pubkey,
113 mint: &Pubkey,
114 vault: &Pubkey,
115 oracle: &Pubkey,
116 matcher: &Pubkey,
117 token_program: &Pubkey,
118 args: InitializeMarketArgs,
119) -> Instruction {
120 build_ix(
121 program_id,
122 "initialize_market",
123 args,
124 vec![
125 AccountMeta::new(*authority, true),
126 AccountMeta::new(*market, false),
127 AccountMeta::new_readonly(*mint, false),
128 AccountMeta::new(*vault, false),
129 AccountMeta::new_readonly(*oracle, false),
130 AccountMeta::new_readonly(*matcher, false),
131 AccountMeta::new_readonly(*token_program, false),
132 AccountMeta::new_readonly(system_program::id(), false),
133 ],
134 )
135}
136
137pub fn deposit_ix(
138 program_id: &Pubkey,
139 market: &Pubkey,
140 user: &Pubkey,
141 mint: &Pubkey,
142 user_token_account: &Pubkey,
143 vault: &Pubkey,
144 token_program: &Pubkey,
145 args: DepositArgs,
146) -> Instruction {
147 build_ix(
148 program_id,
149 "deposit",
150 args,
151 vec![
152 AccountMeta::new(*user, true),
153 AccountMeta::new(*market, false),
154 AccountMeta::new_readonly(*mint, false),
155 AccountMeta::new(*user_token_account, false),
156 AccountMeta::new(*vault, false),
157 AccountMeta::new_readonly(*token_program, false),
158 ],
159 )
160}
161
162pub fn withdraw_ix(
163 program_id: &Pubkey,
164 market: &Pubkey,
165 user: &Pubkey,
166 mint: &Pubkey,
167 user_token_account: &Pubkey,
168 vault: &Pubkey,
169 token_program: &Pubkey,
170 args: WithdrawArgs,
171) -> Instruction {
172 build_ix(
173 program_id,
174 "withdraw",
175 args,
176 vec![
177 AccountMeta::new(*user, true),
178 AccountMeta::new(*market, false),
179 AccountMeta::new_readonly(*mint, false),
180 AccountMeta::new(*user_token_account, false),
181 AccountMeta::new(*vault, false),
182 AccountMeta::new_readonly(*token_program, false),
183 ],
184 )
185}
186
187pub fn trade_ix(
188 program_id: &Pubkey,
189 market: &Pubkey,
190 authority: &Pubkey,
191 args: TradeArgs,
192) -> Instruction {
193 build_ix(
194 program_id,
195 "trade",
196 args,
197 vec![
198 AccountMeta::new(*market, false),
199 AccountMeta::new_readonly(*authority, true),
200 ],
201 )
202}
203
204pub fn crank_ix(
205 program_id: &Pubkey,
206 market: &Pubkey,
207 cranker: &Pubkey,
208 oracle: &Pubkey,
209 args: CrankArgs,
210) -> Instruction {
211 build_ix(
212 program_id,
213 "crank",
214 args,
215 vec![
216 AccountMeta::new_readonly(*cranker, true),
217 AccountMeta::new(*market, false),
218 AccountMeta::new_readonly(*oracle, false),
219 ],
220 )
221}
222
223pub fn liquidate_ix(
224 program_id: &Pubkey,
225 market: &Pubkey,
226 liquidator: &Pubkey,
227 args: LiquidateArgs,
228) -> Instruction {
229 build_ix(
230 program_id,
231 "liquidate",
232 args,
233 vec![
234 AccountMeta::new(*market, false),
235 AccountMeta::new_readonly(*liquidator, true),
236 ],
237 )
238}
239
240pub fn settle_ix(
241 program_id: &Pubkey,
242 market: &Pubkey,
243 user: &Pubkey,
244 args: SettleArgs,
245) -> Instruction {
246 build_ix(
247 program_id,
248 "settle",
249 args,
250 vec![
251 AccountMeta::new(*market, false),
252 AccountMeta::new_readonly(*user, true),
253 ],
254 )
255}
256
257pub fn close_account_ix(
258 program_id: &Pubkey,
259 market: &Pubkey,
260 user: &Pubkey,
261 args: CloseAccountArgs,
262) -> Instruction {
263 build_ix(
264 program_id,
265 "close_account",
266 args,
267 vec![
268 AccountMeta::new(*market, false),
269 AccountMeta::new_readonly(*user, true),
270 ],
271 )
272}