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!(" Conservation: {}", if conservation { "PASS" } else { "FAIL" });
42 println!(" Oracle price: {}", engine.last_oracle_price);
43 println!(" Last slot: {}", engine.last_crank_slot);
44
45 let mut active = 0u32;
47 for i in 0..engine.accounts.len() {
48 if engine.is_used(i) {
49 active += 1;
50 }
51 }
52 println!(" Accounts: {active}/{}", engine.accounts.len());
53
54 Ok(())
55}
56
57fn print_account(engine: &percli_core::RiskEngine, idx: u16) -> Result<()> {
58 let i = idx as usize;
59 if i >= engine.accounts.len() {
60 bail!("Account index {idx} out of range (max {})", engine.accounts.len() - 1);
61 }
62 if !engine.is_used(i) {
63 bail!("Account slot {idx} is empty");
64 }
65
66 let acct = &engine.accounts[i];
67 let eff_pos = engine.effective_pos_q(i);
68 let equity_maint = engine.account_equity_maint_raw(acct);
69 let equity_init = engine.account_equity_init_raw(acct, i);
70 let above_mm = engine.is_above_maintenance_margin(acct, i, engine.last_oracle_price);
71 let above_im = engine.is_above_initial_margin(acct, i, engine.last_oracle_price);
72 let notional = engine.notional(i, engine.last_oracle_price);
73
74 println!("Account #{idx}");
75 println!(" Capital: {}", acct.capital.get());
76 println!(" PnL: {}", acct.pnl);
77 println!(" Reserved: {}", acct.reserved_pnl);
78 println!(" Position: {eff_pos}");
79 println!(" Notional: {notional}");
80 println!(" Equity(M): {equity_maint}");
81 println!(" Equity(I): {equity_init}");
82 println!(" Above MM: {above_mm}");
83 println!(" Above IM: {above_im}");
84
85 Ok(())
86}