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
107#[derive(BorshSerialize)]
108pub struct ReclaimAccountArgs {
109 pub account_idx: u16,
110}
111
112#[derive(BorshSerialize)]
113pub struct WithdrawInsuranceArgs {
114 pub amount: u64,
115}
116
117#[derive(BorshSerialize)]
118pub struct TopUpInsuranceArgs {
119 pub amount: u64,
120}
121
122#[derive(BorshSerialize)]
123pub struct DepositFeeCreditsArgs {
124 pub account_idx: u16,
125 pub amount: u64,
126}
127
128#[derive(BorshSerialize)]
129pub struct ConvertReleasedPnlArgs {
130 pub account_idx: u16,
131 pub x_req: u64,
132 pub funding_rate: i64,
133}
134
135#[derive(BorshSerialize)]
136pub struct UpdateMatcherArgs {
137 pub new_matcher: Pubkey,
138}
139
140pub fn initialize_market_ix(
143 program_id: &Pubkey,
144 market: &Pubkey,
145 authority: &Pubkey,
146 mint: &Pubkey,
147 vault: &Pubkey,
148 oracle: &Pubkey,
149 matcher: &Pubkey,
150 token_program: &Pubkey,
151 args: InitializeMarketArgs,
152) -> Instruction {
153 build_ix(
154 program_id,
155 "initialize_market",
156 args,
157 vec![
158 AccountMeta::new(*authority, true),
159 AccountMeta::new(*market, false),
160 AccountMeta::new_readonly(*mint, false),
161 AccountMeta::new(*vault, false),
162 AccountMeta::new_readonly(*oracle, false),
163 AccountMeta::new_readonly(*matcher, false),
164 AccountMeta::new_readonly(*token_program, false),
165 AccountMeta::new_readonly(system_program::id(), false),
166 ],
167 )
168}
169
170pub fn deposit_ix(
171 program_id: &Pubkey,
172 market: &Pubkey,
173 user: &Pubkey,
174 mint: &Pubkey,
175 user_token_account: &Pubkey,
176 vault: &Pubkey,
177 token_program: &Pubkey,
178 args: DepositArgs,
179) -> Instruction {
180 build_ix(
181 program_id,
182 "deposit",
183 args,
184 vec![
185 AccountMeta::new(*user, true),
186 AccountMeta::new(*market, false),
187 AccountMeta::new_readonly(*mint, false),
188 AccountMeta::new(*user_token_account, false),
189 AccountMeta::new(*vault, false),
190 AccountMeta::new_readonly(*token_program, false),
191 ],
192 )
193}
194
195pub fn withdraw_ix(
196 program_id: &Pubkey,
197 market: &Pubkey,
198 user: &Pubkey,
199 mint: &Pubkey,
200 user_token_account: &Pubkey,
201 vault: &Pubkey,
202 token_program: &Pubkey,
203 args: WithdrawArgs,
204) -> Instruction {
205 build_ix(
206 program_id,
207 "withdraw",
208 args,
209 vec![
210 AccountMeta::new(*user, true),
211 AccountMeta::new(*market, false),
212 AccountMeta::new_readonly(*mint, false),
213 AccountMeta::new(*user_token_account, false),
214 AccountMeta::new(*vault, false),
215 AccountMeta::new_readonly(*token_program, false),
216 ],
217 )
218}
219
220pub fn trade_ix(
221 program_id: &Pubkey,
222 market: &Pubkey,
223 authority: &Pubkey,
224 args: TradeArgs,
225) -> Instruction {
226 build_ix(
227 program_id,
228 "trade",
229 args,
230 vec![
231 AccountMeta::new_readonly(*authority, true),
232 AccountMeta::new(*market, false),
233 ],
234 )
235}
236
237pub fn crank_ix(
238 program_id: &Pubkey,
239 market: &Pubkey,
240 cranker: &Pubkey,
241 oracle: &Pubkey,
242 args: CrankArgs,
243) -> Instruction {
244 build_ix(
245 program_id,
246 "crank",
247 args,
248 vec![
249 AccountMeta::new_readonly(*cranker, true),
250 AccountMeta::new(*market, false),
251 AccountMeta::new_readonly(*oracle, false),
252 ],
253 )
254}
255
256pub fn liquidate_ix(
257 program_id: &Pubkey,
258 market: &Pubkey,
259 liquidator: &Pubkey,
260 args: LiquidateArgs,
261) -> Instruction {
262 build_ix(
263 program_id,
264 "liquidate",
265 args,
266 vec![
267 AccountMeta::new_readonly(*liquidator, true),
268 AccountMeta::new(*market, false),
269 ],
270 )
271}
272
273pub fn settle_ix(
274 program_id: &Pubkey,
275 market: &Pubkey,
276 user: &Pubkey,
277 args: SettleArgs,
278) -> Instruction {
279 build_ix(
280 program_id,
281 "settle",
282 args,
283 vec![
284 AccountMeta::new_readonly(*user, true),
285 AccountMeta::new(*market, false),
286 ],
287 )
288}
289
290pub fn close_account_ix(
291 program_id: &Pubkey,
292 market: &Pubkey,
293 user: &Pubkey,
294 args: CloseAccountArgs,
295) -> Instruction {
296 build_ix(
297 program_id,
298 "close_account",
299 args,
300 vec![
301 AccountMeta::new_readonly(*user, true),
302 AccountMeta::new(*market, false),
303 ],
304 )
305}
306
307pub fn reclaim_account_ix(
308 program_id: &Pubkey,
309 market: &Pubkey,
310 reclaimer: &Pubkey,
311 args: ReclaimAccountArgs,
312) -> Instruction {
313 build_ix(
314 program_id,
315 "reclaim_account",
316 args,
317 vec![
318 AccountMeta::new_readonly(*reclaimer, true),
319 AccountMeta::new(*market, false),
320 ],
321 )
322}
323
324pub fn withdraw_insurance_ix(
325 program_id: &Pubkey,
326 market: &Pubkey,
327 authority: &Pubkey,
328 mint: &Pubkey,
329 authority_token_account: &Pubkey,
330 vault: &Pubkey,
331 token_program: &Pubkey,
332 args: WithdrawInsuranceArgs,
333) -> Instruction {
334 build_ix(
335 program_id,
336 "withdraw_insurance",
337 args,
338 vec![
339 AccountMeta::new(*authority, true),
340 AccountMeta::new(*market, false),
341 AccountMeta::new_readonly(*mint, false),
342 AccountMeta::new(*authority_token_account, false),
343 AccountMeta::new(*vault, false),
344 AccountMeta::new_readonly(*token_program, false),
345 ],
346 )
347}
348
349pub fn top_up_insurance_ix(
350 program_id: &Pubkey,
351 market: &Pubkey,
352 depositor: &Pubkey,
353 mint: &Pubkey,
354 depositor_token_account: &Pubkey,
355 vault: &Pubkey,
356 token_program: &Pubkey,
357 args: TopUpInsuranceArgs,
358) -> Instruction {
359 build_ix(
360 program_id,
361 "top_up_insurance",
362 args,
363 vec![
364 AccountMeta::new(*depositor, true),
365 AccountMeta::new(*market, false),
366 AccountMeta::new_readonly(*mint, false),
367 AccountMeta::new(*depositor_token_account, false),
368 AccountMeta::new(*vault, false),
369 AccountMeta::new_readonly(*token_program, false),
370 ],
371 )
372}
373
374pub fn deposit_fee_credits_ix(
375 program_id: &Pubkey,
376 market: &Pubkey,
377 user: &Pubkey,
378 mint: &Pubkey,
379 user_token_account: &Pubkey,
380 vault: &Pubkey,
381 token_program: &Pubkey,
382 args: DepositFeeCreditsArgs,
383) -> Instruction {
384 build_ix(
385 program_id,
386 "deposit_fee_credits",
387 args,
388 vec![
389 AccountMeta::new(*user, true),
390 AccountMeta::new(*market, false),
391 AccountMeta::new_readonly(*mint, false),
392 AccountMeta::new(*user_token_account, false),
393 AccountMeta::new(*vault, false),
394 AccountMeta::new_readonly(*token_program, false),
395 ],
396 )
397}
398
399pub fn convert_released_pnl_ix(
400 program_id: &Pubkey,
401 market: &Pubkey,
402 user: &Pubkey,
403 oracle: &Pubkey,
404 args: ConvertReleasedPnlArgs,
405) -> Instruction {
406 build_ix(
407 program_id,
408 "convert_released_pnl",
409 args,
410 vec![
411 AccountMeta::new_readonly(*user, true),
412 AccountMeta::new(*market, false),
413 AccountMeta::new_readonly(*oracle, false),
414 ],
415 )
416}
417
418pub fn accrue_market_ix(
419 program_id: &Pubkey,
420 market: &Pubkey,
421 signer: &Pubkey,
422 oracle: &Pubkey,
423) -> Instruction {
424 build_ix(
425 program_id,
426 "accrue_market",
427 (),
428 vec![
429 AccountMeta::new_readonly(*signer, true),
430 AccountMeta::new(*market, false),
431 AccountMeta::new_readonly(*oracle, false),
432 ],
433 )
434}
435
436pub fn update_matcher_ix(
437 program_id: &Pubkey,
438 market: &Pubkey,
439 authority: &Pubkey,
440 args: UpdateMatcherArgs,
441) -> Instruction {
442 build_ix(
443 program_id,
444 "update_matcher",
445 args,
446 vec![
447 AccountMeta::new_readonly(*authority, true),
448 AccountMeta::new(*market, false),
449 ],
450 )
451}
452
453pub fn update_oracle_ix(
454 program_id: &Pubkey,
455 market: &Pubkey,
456 authority: &Pubkey,
457 new_oracle: &Pubkey,
458) -> Instruction {
459 build_ix(
460 program_id,
461 "update_oracle",
462 (),
463 vec![
464 AccountMeta::new_readonly(*authority, true),
465 AccountMeta::new(*market, false),
466 AccountMeta::new_readonly(*new_oracle, false),
467 ],
468 )
469}