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 maintenance_margin_bps: u64,
46 pub initial_margin_bps: u64,
47 pub liquidation_fee_bps: u64,
48 pub insurance_fee_bps: u64,
49 pub adl_threshold_bps: u64,
50 pub max_leverage_q: u64,
51 pub min_order_size_q: u64,
52 pub tick_size: u64,
53 pub max_oi_imbalance_q: u64,
54 pub haircut_start_bps: u64,
55 pub haircut_end_bps: u64,
56 pub haircut_maturity_slots: u64,
57 pub matured_haircut_bps: u64,
58 pub max_accounts: u64,
59 pub min_nonzero_mm_req: u128,
60 pub min_nonzero_im_req: u128,
61}
62
63#[derive(BorshSerialize)]
64pub struct DepositArgs {
65 pub account_idx: u16,
66 pub amount: u64,
67}
68
69#[derive(BorshSerialize)]
70pub struct WithdrawArgs {
71 pub account_idx: u16,
72 pub amount: u64,
73 pub funding_rate: i64,
74}
75
76#[derive(BorshSerialize)]
77pub struct TradeArgs {
78 pub account_a: u16,
79 pub account_b: u16,
80 pub size_q: i128,
81 pub exec_price: u64,
82 pub funding_rate: i64,
83}
84
85#[derive(BorshSerialize)]
86pub struct CrankArgs {
87 pub funding_rate: i64,
88}
89
90#[derive(BorshSerialize)]
91pub struct LiquidateArgs {
92 pub account_idx: u16,
93 pub funding_rate: i64,
94}
95
96#[derive(BorshSerialize)]
97pub struct SettleArgs {
98 pub account_idx: u16,
99 pub funding_rate: i64,
100}
101
102#[derive(BorshSerialize)]
103pub struct CloseAccountArgs {
104 pub account_idx: u16,
105 pub funding_rate: i64,
106}
107
108pub fn initialize_market_ix(
111 program_id: &Pubkey,
112 market: &Pubkey,
113 authority: &Pubkey,
114 args: InitializeMarketArgs,
115) -> Instruction {
116 build_ix(
117 program_id,
118 "initialize_market",
119 args,
120 vec![
121 AccountMeta::new(*market, false),
122 AccountMeta::new(*authority, true),
123 AccountMeta::new_readonly(system_program::id(), false),
124 ],
125 )
126}
127
128pub fn deposit_ix(
129 program_id: &Pubkey,
130 market: &Pubkey,
131 user: &Pubkey,
132 mint: &Pubkey,
133 user_token_account: &Pubkey,
134 vault: &Pubkey,
135 token_program: &Pubkey,
136 args: DepositArgs,
137) -> Instruction {
138 build_ix(
139 program_id,
140 "deposit",
141 args,
142 vec![
143 AccountMeta::new(*user, true),
144 AccountMeta::new(*market, false),
145 AccountMeta::new_readonly(*mint, false),
146 AccountMeta::new(*user_token_account, false),
147 AccountMeta::new(*vault, false),
148 AccountMeta::new_readonly(*token_program, false),
149 ],
150 )
151}
152
153pub fn withdraw_ix(
154 program_id: &Pubkey,
155 market: &Pubkey,
156 user: &Pubkey,
157 mint: &Pubkey,
158 user_token_account: &Pubkey,
159 vault: &Pubkey,
160 token_program: &Pubkey,
161 args: WithdrawArgs,
162) -> Instruction {
163 build_ix(
164 program_id,
165 "withdraw",
166 args,
167 vec![
168 AccountMeta::new(*user, true),
169 AccountMeta::new(*market, false),
170 AccountMeta::new_readonly(*mint, false),
171 AccountMeta::new(*user_token_account, false),
172 AccountMeta::new(*vault, false),
173 AccountMeta::new_readonly(*token_program, false),
174 ],
175 )
176}
177
178pub fn trade_ix(
179 program_id: &Pubkey,
180 market: &Pubkey,
181 authority: &Pubkey,
182 args: TradeArgs,
183) -> Instruction {
184 build_ix(
185 program_id,
186 "trade",
187 args,
188 vec![
189 AccountMeta::new(*market, false),
190 AccountMeta::new_readonly(*authority, true),
191 ],
192 )
193}
194
195pub fn crank_ix(
196 program_id: &Pubkey,
197 market: &Pubkey,
198 cranker: &Pubkey,
199 oracle: &Pubkey,
200 args: CrankArgs,
201) -> Instruction {
202 build_ix(
203 program_id,
204 "crank",
205 args,
206 vec![
207 AccountMeta::new_readonly(*cranker, true),
208 AccountMeta::new(*market, false),
209 AccountMeta::new_readonly(*oracle, false),
210 ],
211 )
212}
213
214pub fn liquidate_ix(
215 program_id: &Pubkey,
216 market: &Pubkey,
217 liquidator: &Pubkey,
218 args: LiquidateArgs,
219) -> Instruction {
220 build_ix(
221 program_id,
222 "liquidate",
223 args,
224 vec![
225 AccountMeta::new(*market, false),
226 AccountMeta::new_readonly(*liquidator, true),
227 ],
228 )
229}
230
231pub fn settle_ix(
232 program_id: &Pubkey,
233 market: &Pubkey,
234 user: &Pubkey,
235 args: SettleArgs,
236) -> Instruction {
237 build_ix(
238 program_id,
239 "settle",
240 args,
241 vec![
242 AccountMeta::new(*market, false),
243 AccountMeta::new_readonly(*user, true),
244 ],
245 )
246}
247
248pub fn close_account_ix(
249 program_id: &Pubkey,
250 market: &Pubkey,
251 user: &Pubkey,
252 args: CloseAccountArgs,
253) -> Instruction {
254 build_ix(
255 program_id,
256 "close_account",
257 args,
258 vec![
259 AccountMeta::new(*market, false),
260 AccountMeta::new_readonly(*user, true),
261 ],
262 )
263}