1use solana_program::pubkey::Pubkey;
6use spl_associated_token_account::{
7 get_associated_token_address,
8 get_associated_token_address_with_program_id,
9};
10use steel::*;
11
12use crate::{
13 consts::{
14 EXECUTOR_ADDRESS, EXECUTOR_PAY_DAILY_JACKPOT, EXECUTOR_PAY_WEEKLY_JACKPOT, FEE_COLLECTOR,
15 USDC_MAINNET_MINT,
16 },
17 instruction::*,
18 state::{Ledger, Market, Position, Treasury},
19};
20
21#[inline(always)]
22pub fn program_id() -> Pubkey {
23 crate::ID
24}
25
26#[inline(always)]
27fn executor_treasury_ix_bytes(kind: u8, pool: u8, series_id: u16, amount: u64) -> Vec<u8> {
28 ExecutorTreasury {
29 kind,
30 pool,
31 series_id: series_id.to_le_bytes(),
32 _pad_ix: [0; 4],
33 amount: amount.to_le_bytes(),
34 }
35 .to_bytes()
36}
37
38#[inline(always)]
40pub fn treasury_usdc_ata() -> Pubkey {
41 get_associated_token_address(&Treasury::pda().0, &USDC_MAINNET_MINT)
42}
43
44#[inline(always)]
45pub fn treasury_usdc_ata_with_token_program(token_program: &Pubkey) -> Pubkey {
46 get_associated_token_address_with_program_id(&Treasury::pda().0, &USDC_MAINNET_MINT, token_program)
47}
48
49#[inline(always)]
50pub fn associated_usdc_ata(owner: Pubkey, token_program: &Pubkey) -> Pubkey {
51 get_associated_token_address_with_program_id(&owner, &USDC_MAINNET_MINT, token_program)
52}
53
54#[inline(always)]
56pub fn usdc_ata(owner: Pubkey) -> Pubkey {
57 get_associated_token_address(&owner, &USDC_MAINNET_MINT)
58}
59
60#[inline(always)]
62pub fn fee_collector_usdc_ata() -> Pubkey {
63 get_associated_token_address(&FEE_COLLECTOR, &USDC_MAINNET_MINT)
64}
65
66#[inline(always)]
67pub fn fee_collector_usdc_ata_with_token_program(token_program: &Pubkey) -> Pubkey {
68 get_associated_token_address_with_program_id(&FEE_COLLECTOR, &USDC_MAINNET_MINT, token_program)
69}
70
71#[inline(always)]
73pub fn buy_tickets_or_place_bet_previous_accounts(
74 user: Pubkey,
75 series_id: u16,
76 period: u64,
77) -> (Pubkey, Pubkey) {
78 match period.checked_sub(1) {
79 Some(p) => (
80 Market::pda(series_id, p).0,
81 Position::pda(series_id, p, user).0,
82 ),
83 None => (system_program::ID, system_program::ID),
84 }
85}
86
87pub fn initialize(payer: Pubkey, token_program: Pubkey) -> Instruction {
93 let treasury_address = Treasury::pda().0;
94 let mint_address = USDC_MAINNET_MINT;
95 let treasury_ata = treasury_usdc_ata_with_token_program(&token_program);
96 Instruction {
97 program_id: crate::ID,
98 accounts: vec![
99 AccountMeta::new(payer, true),
100 AccountMeta::new(treasury_address, false),
101 AccountMeta::new_readonly(mint_address, false),
102 AccountMeta::new(treasury_ata, false),
103 AccountMeta::new_readonly(system_program::ID, false),
104 AccountMeta::new_readonly(token_program, false),
105 AccountMeta::new_readonly(spl_associated_token_account::ID, false),
106 ],
107 data: Initialize {}.to_bytes(),
108 }
109}
110
111pub fn buy_tickets(
115 user: Pubkey,
116 series_id: u16,
117 period: u64,
118 amount: u64,
119 token_program: Pubkey,
120) -> Instruction {
121 let treasury_address = Treasury::pda().0;
122 let ledger_address = Ledger::pda(user).0;
123 let mint_address = USDC_MAINNET_MINT;
124 let user_ata = associated_usdc_ata(user, &token_program);
125 let treasury_ata_addr = treasury_usdc_ata_with_token_program(&token_program);
126 let team_ata_addr = fee_collector_usdc_ata_with_token_program(&token_program);
127 let (prev_mkt, prev_pos) =
128 buy_tickets_or_place_bet_previous_accounts(user, series_id, period);
129 Instruction {
130 program_id: crate::ID,
131 accounts: vec![
132 AccountMeta::new(user, true),
133 AccountMeta::new(treasury_address, false),
134 AccountMeta::new(ledger_address, false),
135 AccountMeta::new_readonly(mint_address, false),
136 AccountMeta::new(user_ata, false),
137 AccountMeta::new(treasury_ata_addr, false),
138 AccountMeta::new(team_ata_addr, false),
139 AccountMeta::new_readonly(system_program::ID, false),
140 AccountMeta::new_readonly(token_program, false),
141 AccountMeta::new_readonly(spl_associated_token_account::ID, false),
142 AccountMeta::new_readonly(prev_mkt, false),
143 AccountMeta::new_readonly(prev_pos, false),
144 ],
145 data: BuyTickets {
146 series_id: series_id.to_le_bytes(),
147 _pad_ix: [0; 6],
148 period: period.to_le_bytes(),
149 amount: amount.to_le_bytes(),
150 }
151 .to_bytes(),
152 }
153}
154
155pub fn place_bet(
161 user: Pubkey,
162 series_id: u16,
163 period: u64,
164 ticket_units: u64,
165 side: u8,
166) -> Instruction {
167 let ledger_address = Ledger::pda(user).0;
168 let treasury_address = Treasury::pda().0;
169 let market_address = Market::pda(series_id, period).0;
170 let position_address = Position::pda(series_id, period, user).0;
171 let (prev_mkt, prev_pos) =
172 buy_tickets_or_place_bet_previous_accounts(user, series_id, period);
173 Instruction {
174 program_id: crate::ID,
175 accounts: vec![
176 AccountMeta::new(user, true),
177 AccountMeta::new(ledger_address, false),
178 AccountMeta::new_readonly(treasury_address, false),
179 AccountMeta::new(market_address, false),
180 AccountMeta::new(position_address, false),
181 AccountMeta::new_readonly(prev_mkt, false),
182 AccountMeta::new_readonly(prev_pos, false),
183 AccountMeta::new_readonly(system_program::ID, false),
184 ],
185 data: PlaceBet {
186 series_id: series_id.to_le_bytes(),
187 _pad_ix: [0; 6],
188 period: period.to_le_bytes(),
189 ticket_units: ticket_units.to_le_bytes(),
190 side,
191 _pad: [0; 7],
192 }
193 .to_bytes(),
194 }
195}
196
197pub fn executor_treasury_merge_committed(
201 executor: Pubkey,
202 series_id: u16,
203 period: u64,
204 position_owner: Pubkey,
205) -> Instruction {
206 let treasury_address = Treasury::pda().0;
207 let market_address = Market::pda(series_id, period).0;
208 let position_address = Position::pda(series_id, period, position_owner).0;
209 Instruction {
210 program_id: crate::ID,
211 accounts: vec![
212 AccountMeta::new(executor, true),
213 AccountMeta::new_readonly(treasury_address, false),
214 AccountMeta::new(market_address, false),
215 AccountMeta::new(position_address, false),
216 ],
217 data: executor_treasury_ix_bytes(
218 EXECUTOR_KIND_MERGE_COMMITTED_POSITION,
219 0,
220 series_id,
221 0,
222 ),
223 }
224}
225
226pub fn settle_market(
231 authority: Pubkey,
232 series_id: u16,
233 period: u64,
234 price_update_account: Pubkey,
235) -> Instruction {
236 let treasury_address = Treasury::pda().0;
237 let market_address = Market::pda(series_id, period).0;
238 Instruction {
239 program_id: crate::ID,
240 accounts: vec![
241 AccountMeta::new(authority, true),
242 AccountMeta::new(treasury_address, false),
243 AccountMeta::new(market_address, false),
244 AccountMeta::new_readonly(price_update_account, false),
245 ],
246 data: AdminInstantSettlement {
247 series_id: series_id.to_le_bytes(),
248 _pad_ix: [0; 6],
249 period: period.to_le_bytes(),
250 }
251 .to_bytes(),
252 }
253}
254
255pub fn init_market(
264 authority: Pubkey,
265 series_id: u16,
266 period: u64,
267 open_ts: i64,
268 close_ts: i64,
269 feed_id: [u8; 32],
270 price_update_account: Pubkey,
271 rules_hash: [u8; 32],
272) -> Instruction {
273 let market_address = Market::pda(series_id, period).0;
274 let treasury_address = Treasury::pda().0;
275 Instruction {
276 program_id: crate::ID,
277 accounts: vec![
278 AccountMeta::new(authority, true),
279 AccountMeta::new(market_address, false),
280 AccountMeta::new_readonly(treasury_address, false),
281 AccountMeta::new_readonly(system_program::ID, false),
282 AccountMeta::new_readonly(price_update_account, false),
283 ],
284 data: InitMarket {
285 series_id: series_id.to_le_bytes(),
286 _pad_ix: [0; 6],
287 period: period.to_le_bytes(),
288 open_ts: open_ts.to_le_bytes(),
289 close_ts: close_ts.to_le_bytes(),
290 pyth_price_feed: feed_id,
291 rules_hash,
292 }
293 .to_bytes(),
294 }
295}
296
297pub fn void_market(authority: Pubkey, series_id: u16, period: u64) -> Instruction {
303 let treasury_address = Treasury::pda().0;
304 let market_address = Market::pda(series_id, period).0;
305 Instruction {
306 program_id: crate::ID,
307 accounts: vec![
308 AccountMeta::new(authority, true),
309 AccountMeta::new_readonly(treasury_address, false),
310 AccountMeta::new(market_address, false),
311 ],
312 data: AdminVoidMarket {
313 series_id: series_id.to_le_bytes(),
314 _pad_ix: [0; 6],
315 period: period.to_le_bytes(),
316 }
317 .to_bytes(),
318 }
319}
320
321pub fn refund_void_position(
326 authority: Pubkey,
327 series_id: u16,
328 period: u64,
329 position_owner: Pubkey,
330) -> Instruction {
331 let market_address = Market::pda(series_id, period).0;
332 let position_address = Position::pda(series_id, period, position_owner).0;
333 let ledger_address = Ledger::pda(position_owner).0;
334 Instruction {
335 program_id: crate::ID,
336 accounts: vec![
337 AccountMeta::new(authority, true),
338 AccountMeta::new_readonly(market_address, false),
339 AccountMeta::new(position_address, false),
340 AccountMeta::new(ledger_address, false),
341 ],
342 data: AdminRefundVoidPosition {
343 series_id: series_id.to_le_bytes(),
344 _pad_ix: [0; 6],
345 period: period.to_le_bytes(),
346 }
347 .to_bytes(),
348 }
349}
350
351pub fn distribute_market_reward(
355 executor: Pubkey,
356 winning_authority: Pubkey,
357 series_id: u16,
358 market_period: u64,
359 token_program: Pubkey,
360) -> Instruction {
361 let treasury_address = Treasury::pda().0;
362 let treasury_ata_addr = treasury_usdc_ata_with_token_program(&token_program);
363 let recipient_ata = associated_usdc_ata(winning_authority, &token_program);
364 let mint_address = USDC_MAINNET_MINT;
365 let market_address = Market::pda(series_id, market_period).0;
366 let position_address = Position::pda(series_id, market_period, winning_authority).0;
367 let ledger_address = Ledger::pda(winning_authority).0;
368 Instruction {
369 program_id: crate::ID,
370 accounts: vec![
371 AccountMeta::new(executor, true),
372 AccountMeta::new(treasury_address, false),
373 AccountMeta::new(treasury_ata_addr, false),
374 AccountMeta::new(recipient_ata, false),
375 AccountMeta::new_readonly(mint_address, false),
376 AccountMeta::new_readonly(token_program, false),
377 AccountMeta::new_readonly(market_address, false),
378 AccountMeta::new(position_address, false),
379 AccountMeta::new(ledger_address, false),
380 ],
381 data: executor_treasury_ix_bytes(EXECUTOR_KIND_DISTRIBUTE_MARKET_REWARD, 0, series_id, 0),
382 }
383}
384
385pub fn distribute_market_reward_default_executor(
387 winning_authority: Pubkey,
388 series_id: u16,
389 market_period: u64,
390 token_program: Pubkey,
391) -> Instruction {
392 distribute_market_reward(
393 EXECUTOR_ADDRESS,
394 winning_authority,
395 series_id,
396 market_period,
397 token_program,
398 )
399}
400
401pub fn release_market_line(executor: Pubkey, series_id: u16, period: u64) -> Instruction {
405 let treasury_address = Treasury::pda().0;
406 let market_address = Market::pda(series_id, period).0;
407 Instruction {
408 program_id: crate::ID,
409 accounts: vec![
410 AccountMeta::new(executor, true),
411 AccountMeta::new(treasury_address, false),
412 AccountMeta::new_readonly(market_address, false),
413 ],
414 data: executor_treasury_ix_bytes(EXECUTOR_KIND_MARKET_LINE_RELEASE, 0, series_id, period),
415 }
416}
417
418#[inline(always)]
419pub fn release_market_line_default_executor(series_id: u16, period: u64) -> Instruction {
420 release_market_line(EXECUTOR_ADDRESS, series_id, period)
421}
422
423pub fn executor_treasury_pay_recipient_account(
429 executor: Pubkey,
430 recipient_ata: Pubkey,
431 amount: u64,
432 pool: u8,
433 token_program: Pubkey,
434) -> Instruction {
435 let treasury_address = Treasury::pda().0;
436 let treasury_ata_addr = treasury_usdc_ata_with_token_program(&token_program);
437 let mint_address = USDC_MAINNET_MINT;
438 Instruction {
439 program_id: crate::ID,
440 accounts: vec![
441 AccountMeta::new(executor, true),
442 AccountMeta::new(treasury_address, false),
443 AccountMeta::new(treasury_ata_addr, false),
444 AccountMeta::new_readonly(mint_address, false),
445 AccountMeta::new_readonly(token_program, false),
446 AccountMeta::new(recipient_ata, false),
447 ],
448 data: executor_treasury_ix_bytes(EXECUTOR_KIND_JACKPOT_PAY, pool, 0, amount),
449 }
450}
451
452#[inline(always)]
454pub fn executor_treasury_pay(
455 executor: Pubkey,
456 recipient_owner: Pubkey,
457 amount: u64,
458 pool: u8,
459 token_program: Pubkey,
460) -> Instruction {
461 executor_treasury_pay_recipient_account(
462 executor,
463 associated_usdc_ata(recipient_owner, &token_program),
464 amount,
465 pool,
466 token_program,
467 )
468}
469
470#[inline(always)]
472pub fn executor_treasury_pay_daily(
473 executor: Pubkey,
474 recipient_owner: Pubkey,
475 amount: u64,
476 token_program: Pubkey,
477) -> Instruction {
478 executor_treasury_pay_recipient_account(
479 executor,
480 associated_usdc_ata(recipient_owner, &token_program),
481 amount,
482 EXECUTOR_PAY_DAILY_JACKPOT,
483 token_program,
484 )
485}
486
487#[inline(always)]
489pub fn executor_treasury_pay_weekly(
490 executor: Pubkey,
491 recipient_owner: Pubkey,
492 amount: u64,
493 token_program: Pubkey,
494) -> Instruction {
495 executor_treasury_pay_recipient_account(
496 executor,
497 associated_usdc_ata(recipient_owner, &token_program),
498 amount,
499 EXECUTOR_PAY_WEEKLY_JACKPOT,
500 token_program,
501 )
502}
503
504pub fn claim_position_fee_accounts_prefix(
509 owner: Pubkey,
510 owner_usdc_ata: Pubkey,
511 token_program: Pubkey,
512) -> [AccountMeta; 9] {
513 let executor = EXECUTOR_ADDRESS;
514 let treasury_address = Treasury::pda().0;
515 let treasury_ata_addr = treasury_usdc_ata_with_token_program(&token_program);
516 let team_ata_addr = fee_collector_usdc_ata_with_token_program(&token_program);
517 [
518 AccountMeta::new(executor, true),
519 AccountMeta::new(owner, true),
520 AccountMeta::new(treasury_address, false),
521 AccountMeta::new(treasury_ata_addr, false),
522 AccountMeta::new(team_ata_addr, false),
523 AccountMeta::new_readonly(USDC_MAINNET_MINT, false),
524 AccountMeta::new_readonly(system_program::ID, false),
525 AccountMeta::new_readonly(token_program, false),
526 AccountMeta::new(owner_usdc_ata, false),
527 ]
528}
529
530pub fn claim_position_fee(
531 owner: Pubkey,
532 owner_usdc_ata: Pubkey,
533 cp_amm_accounts: &[AccountMeta],
534 token_program: Pubkey,
535) -> Instruction {
536 let prefix = claim_position_fee_accounts_prefix(owner, owner_usdc_ata, token_program);
537 let mut accounts = Vec::with_capacity(9 + cp_amm_accounts.len());
538 accounts.extend_from_slice(&prefix);
539 accounts.extend_from_slice(cp_amm_accounts);
540 Instruction {
541 program_id: crate::ID,
542 accounts,
543 data: ClaimPositionFee {}.to_bytes(),
544 }
545}
546
547pub fn admin_init_week(authority: Pubkey) -> Instruction {
552 let treasury_address = Treasury::pda().0;
553 Instruction {
554 program_id: crate::ID,
555 accounts: vec![
556 AccountMeta::new(authority, true),
557 AccountMeta::new(treasury_address, false),
558 ],
559 data: AdminInitWeek {}.to_bytes(),
560 }
561}