percli_program/instructions/
initialize_market.rs1use anchor_lang::prelude::*;
2use anchor_spl::token::{Mint, Token, TokenAccount};
3use percli_core::RiskParams;
4
5use crate::error::PercolatorError;
6use crate::state::{engine_from_account_data, write_header, MarketHeader, MARKET_ACCOUNT_SIZE};
7
8#[derive(Accounts)]
9pub struct InitializeMarket<'info> {
10 #[account(mut)]
11 pub authority: Signer<'info>,
12
13 #[account(
15 init,
16 payer = authority,
17 space = MARKET_ACCOUNT_SIZE,
18 seeds = [b"market", authority.key().as_ref()],
19 bump,
20 )]
21 pub market: UncheckedAccount<'info>,
22
23 pub mint: Account<'info, Mint>,
25
26 #[account(
28 init,
29 payer = authority,
30 token::mint = mint,
31 token::authority = market,
32 seeds = [b"vault", market.key().as_ref()],
33 bump,
34 )]
35 pub vault: Account<'info, TokenAccount>,
36
37 pub token_program: Program<'info, Token>,
38 pub system_program: Program<'info, System>,
39}
40
41pub fn handler(
42 ctx: Context<InitializeMarket>,
43 init_slot: u64,
44 init_oracle_price: u64,
45 params: RiskParamsInput,
46) -> Result<()> {
47 let market = &ctx.accounts.market;
48 let mut data = market.try_borrow_mut_data()?;
49
50 data[0..8].copy_from_slice(b"percmrkt");
52
53 let header = MarketHeader {
54 authority: ctx.accounts.authority.key(),
55 mint: ctx.accounts.mint.key(),
56 bump: ctx.bumps.market,
57 vault_bump: ctx.bumps.vault,
58 _padding: [0; 6],
59 };
60 write_header(&mut data, &header);
61
62 require!(init_oracle_price > 0, PercolatorError::InvalidOraclePriceValue);
63
64 let engine = engine_from_account_data(&mut data);
65 let risk_params = params.to_risk_params();
66 engine.init_in_place(risk_params, init_slot, init_oracle_price);
67
68 Ok(())
69}
70
71#[derive(AnchorSerialize, AnchorDeserialize, Clone)]
73pub struct RiskParamsInput {
74 pub warmup_period_slots: u64,
75 pub maintenance_margin_bps: u64,
76 pub initial_margin_bps: u64,
77 pub trading_fee_bps: u64,
78 pub max_accounts: u64,
79 pub new_account_fee: u64,
80 pub maintenance_fee_per_slot: u64,
81 pub max_crank_staleness_slots: u64,
82 pub liquidation_fee_bps: u64,
83 pub liquidation_fee_cap: u64,
84 pub min_liquidation_abs: u64,
85 pub min_initial_deposit: u64,
86 pub min_nonzero_mm_req: u64,
87 pub min_nonzero_im_req: u64,
88 pub insurance_floor: u64,
89}
90
91impl RiskParamsInput {
92 pub fn to_risk_params(&self) -> RiskParams {
93 use percli_core::U128;
94 RiskParams {
95 warmup_period_slots: self.warmup_period_slots,
96 maintenance_margin_bps: self.maintenance_margin_bps,
97 initial_margin_bps: self.initial_margin_bps,
98 trading_fee_bps: self.trading_fee_bps,
99 max_accounts: self.max_accounts,
100 new_account_fee: U128::new(self.new_account_fee as u128),
101 maintenance_fee_per_slot: U128::new(self.maintenance_fee_per_slot as u128),
102 max_crank_staleness_slots: self.max_crank_staleness_slots,
103 liquidation_fee_bps: self.liquidation_fee_bps,
104 liquidation_fee_cap: U128::new(self.liquidation_fee_cap as u128),
105 min_liquidation_abs: U128::new(self.min_liquidation_abs as u128),
106 min_initial_deposit: U128::new(self.min_initial_deposit as u128),
107 min_nonzero_mm_req: self.min_nonzero_mm_req as u128,
108 min_nonzero_im_req: self.min_nonzero_im_req as u128,
109 insurance_floor: U128::new(self.insurance_floor as u128),
110 }
111 }
112}