Skip to main content

percli_chain/commands/
deploy.rs

1use anyhow::{bail, Result};
2use solana_sdk::pubkey::Pubkey;
3use solana_sdk::system_instruction;
4
5use crate::config::ChainConfig;
6use crate::ix::{self, InitializeMarketArgs, RiskParamsInput};
7use crate::rpc::ChainRpc;
8
9/// Market account size: 8 (discriminator) + 136 (header) + size_of::<RiskEngine>().
10/// Must match MARKET_ACCOUNT_SIZE in the on-chain program.
11const MARKET_ACCOUNT_SIZE: usize = 8 + 136 + std::mem::size_of::<percli_core::RiskEngine>();
12
13pub fn run(
14    config: &ChainConfig,
15    mint: &Pubkey,
16    oracle: &Pubkey,
17    matcher: &Pubkey,
18    init_oracle_price: u64,
19) -> Result<()> {
20    let rpc = ChainRpc::new(&config.rpc_url);
21    let (market_pda, _bump) = config.market_pda();
22    let (vault_pda, _) = config.vault_pda();
23
24    if rpc.account_exists(&market_pda)? {
25        bail!("Market already exists at {market_pda}");
26    }
27
28    let slot = rpc.get_slot()?;
29
30    // Default risk params for devnet testing
31    let params = RiskParamsInput {
32        warmup_period_slots: 0,
33        maintenance_margin_bps: 500,
34        initial_margin_bps: 1000,
35        trading_fee_bps: 10,
36        max_accounts: 4096,
37        new_account_fee: 0,
38        maintenance_fee_per_slot: 0,
39        max_crank_staleness_slots: 100,
40        liquidation_fee_bps: 50,
41        liquidation_fee_cap: 1_000_000,
42        min_liquidation_abs: 100,
43        min_initial_deposit: 1000,
44        min_nonzero_mm_req: 100,
45        min_nonzero_im_req: 200,
46        insurance_floor: 0,
47    };
48
49    let args = InitializeMarketArgs {
50        init_slot: slot,
51        init_oracle_price,
52        params,
53    };
54
55    // Step 1: Create the market PDA account (large accounts can't be created via CPI)
56    let rent = rpc.get_minimum_balance(MARKET_ACCOUNT_SIZE)?;
57    let create_ix = system_instruction::create_account(
58        &config.authority(),
59        &market_pda,
60        rent,
61        MARKET_ACCOUNT_SIZE as u64,
62        &config.program_id,
63    );
64
65    // Step 2: Initialize the market
66    let init_ix = ix::initialize_market_ix(
67        &config.program_id,
68        &market_pda,
69        &config.authority(),
70        mint,
71        &vault_pda,
72        oracle,
73        matcher,
74        &spl_token::id(),
75        args,
76    );
77
78    println!("Deploying market...");
79    println!("  Authority: {}", config.authority());
80    println!("  Market PDA: {market_pda}");
81    println!("  Vault PDA:  {vault_pda}");
82    println!("  Mint:       {mint}");
83    println!("  Oracle:     {oracle}");
84    println!("  Matcher:    {matcher}");
85    println!("  RPC: {}", config.rpc_url);
86
87    let sig = rpc.send_tx(&[create_ix, init_ix], &config.keypair)?;
88    println!("  Tx: {sig}");
89    println!("Market deployed.");
90
91    Ok(())
92}