percli_chain/commands/
query.rs1use anyhow::{bail, Result};
2
3use crate::config::ChainConfig;
4use crate::read;
5use crate::rpc::ChainRpc;
6
7pub enum QueryTarget {
8 Market,
9 Account(u16),
10}
11
12pub fn run(config: &ChainConfig, target: QueryTarget) -> Result<()> {
13 let rpc = ChainRpc::new(&config.rpc_url);
14 let (market_pda, _) = config.market_pda();
15
16 let data = rpc.get_account_data(&market_pda)?;
17 let engine = read::engine_from_data(&data)?;
18
19 match target {
20 QueryTarget::Market => print_market(engine, &market_pda, config),
21 QueryTarget::Account(idx) => print_account(engine, idx),
22 }
23}
24
25fn print_market(
26 engine: &percli_core::RiskEngine,
27 market_pda: &solana_sdk::pubkey::Pubkey,
28 config: &ChainConfig,
29) -> Result<()> {
30 let vault = engine.vault.get();
31 let insurance = engine.insurance_fund.balance.get();
32 let (h_num, h_den) = engine.haircut_ratio();
33 let conservation = engine.check_conservation();
34
35 println!("Market: {market_pda}");
36 println!(" Program: {}", config.program_id);
37 println!(" Authority: {}", config.authority());
38 println!(" Vault: {vault}");
39 println!(" Insurance: {insurance}");
40 println!(" Haircut: {h_num}/{h_den}");
41 println!(
42 " Conservation: {}",
43 if conservation { "PASS" } else { "FAIL" }
44 );
45 println!(" Oracle price: {}", engine.last_oracle_price);
46 println!(" Last slot: {}", engine.last_crank_slot);
47
48 let mut active = 0u32;
50 for i in 0..engine.accounts.len() {
51 if engine.is_used(i) {
52 active += 1;
53 }
54 }
55 println!(" Accounts: {active}/{}", engine.accounts.len());
56
57 Ok(())
58}
59
60fn print_account(engine: &percli_core::RiskEngine, idx: u16) -> Result<()> {
61 let i = idx as usize;
62 if i >= engine.accounts.len() {
63 bail!(
64 "Account index {idx} out of range (max {})",
65 engine.accounts.len() - 1
66 );
67 }
68 if !engine.is_used(i) {
69 bail!("Account slot {idx} is empty");
70 }
71
72 let acct = &engine.accounts[i];
73 let eff_pos = engine.effective_pos_q(i);
74 let equity_maint = engine.account_equity_maint_raw(acct);
75 let equity_init = engine.account_equity_init_raw(acct, i);
76 let above_mm = engine.is_above_maintenance_margin(acct, i, engine.last_oracle_price);
77 let above_im = engine.is_above_initial_margin(acct, i, engine.last_oracle_price);
78 let notional = engine.notional(i, engine.last_oracle_price);
79
80 println!("Account #{idx}");
81 println!(" Capital: {}", acct.capital.get());
82 println!(" PnL: {}", acct.pnl);
83 println!(" Reserved: {}", acct.reserved_pnl);
84 println!(" Position: {eff_pos}");
85 println!(" Notional: {notional}");
86 println!(" Equity(M): {equity_maint}");
87 println!(" Equity(I): {equity_init}");
88 println!(" Above MM: {above_mm}");
89 println!(" Above IM: {above_im}");
90
91 Ok(())
92}