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}