Skip to main content

percli_chain/
config.rs

1use anyhow::{Context, Result};
2use solana_sdk::{pubkey::Pubkey, signature::Keypair, signer::Signer};
3use std::str::FromStr;
4
5const DEFAULT_PROGRAM_ID: &str = "PercQhVBxXnVCaAhfrPZFc2dVZcQANnwEYroogLJFwm";
6const DEFAULT_RPC_URL: &str = "https://api.devnet.solana.com";
7
8pub struct ChainConfig {
9    pub rpc_url: String,
10    pub keypair: Keypair,
11    pub program_id: Pubkey,
12}
13
14impl ChainConfig {
15    pub fn new(
16        rpc_url: Option<&str>,
17        keypair_path: Option<&str>,
18        program_id: Option<&str>,
19    ) -> Result<Self> {
20        let rpc_url = match rpc_url {
21            Some("devnet") => DEFAULT_RPC_URL.to_string(),
22            Some("mainnet") => "https://api.mainnet-beta.solana.com".to_string(),
23            Some("localhost" | "local") => "http://127.0.0.1:8899".to_string(),
24            Some(url) => url.to_string(),
25            None => DEFAULT_RPC_URL.to_string(),
26        };
27
28        let keypair_path = keypair_path.map(|s| s.to_string()).unwrap_or_else(|| {
29            let home = std::env::var("HOME").unwrap_or_default();
30            format!("{home}/.config/solana/id.json")
31        });
32
33        let keypair_bytes = std::fs::read(&keypair_path)
34            .with_context(|| format!("Failed to read keypair from {keypair_path}"))?;
35        let keypair_json: Vec<u8> = serde_json::from_slice(&keypair_bytes)
36            .with_context(|| "Invalid keypair JSON format")?;
37        let keypair = Keypair::try_from(keypair_json.as_slice())
38            .map_err(|e| anyhow::anyhow!("Invalid keypair bytes: {e}"))?;
39
40        let program_id = match program_id {
41            Some(id) => {
42                Pubkey::from_str(id).with_context(|| format!("Invalid program ID: {id}"))?
43            }
44            None => Pubkey::from_str(DEFAULT_PROGRAM_ID).unwrap(),
45        };
46
47        Ok(Self {
48            rpc_url,
49            keypair,
50            program_id,
51        })
52    }
53
54    pub fn authority(&self) -> Pubkey {
55        self.keypair.pubkey()
56    }
57
58    pub fn market_pda(&self) -> (Pubkey, u8) {
59        Pubkey::find_program_address(&[b"market", self.authority().as_ref()], &self.program_id)
60    }
61
62    pub fn vault_pda(&self) -> (Pubkey, u8) {
63        let (market, _) = self.market_pda();
64        Pubkey::find_program_address(&[b"vault", market.as_ref()], &self.program_id)
65    }
66}