solana_trader_client_rust/common/
mod.rs

1pub mod constants;
2pub mod signing;
3
4use std::{env, str::FromStr};
5
6use anyhow::{anyhow, Result};
7use constants::{
8    LOCAL, MAINNET_AMSTERDAM, MAINNET_FRANKFURT, MAINNET_LA, MAINNET_NY, MAINNET_PUMP_NY,
9    MAINNET_PUMP_UK, MAINNET_TOKYO, MAINNET_UK, TESTNET,
10};
11use dotenv::dotenv;
12use solana_sdk::{bs58::decode, pubkey::Pubkey, signature::Keypair};
13
14pub fn http_endpoint(base_url: &str, secure: bool) -> String {
15    let prefix = if secure { "https" } else { "http" };
16    format!("{}://{}", prefix, base_url)
17}
18
19pub fn ws_endpoint(base_url: &str, secure: bool) -> String {
20    let prefix = if secure { "wss" } else { "ws" };
21    format!("{}://{}/ws", prefix, base_url)
22}
23
24pub fn grpc_endpoint(base_url: &str, secure: bool) -> String {
25    let prefix = if secure { "https" } else { "http" };
26    let port = if secure { ":443" } else { "" };
27    format!("{}://{}{}", prefix, base_url, port)
28}
29
30pub fn is_submit_only_endpoint(endpoint: &str) -> bool {
31    matches!(
32        endpoint,
33        MAINNET_FRANKFURT | MAINNET_LA | MAINNET_AMSTERDAM | MAINNET_TOKYO
34    ) && {
35        println!("\x1b[93m⚠️  WARNING\x1b[0m: Endpoint \x1b[96m{}\x1b[0m only supports transaction submission. Quotes, streams and other services are \x1b[91mnot available\x1b[0m.", endpoint);
36        true
37    }
38}
39
40pub fn get_base_url_from_env() -> (String, bool) {
41    let network = std::env::var("NETWORK").unwrap_or_else(|_| "mainnet".to_string());
42    let region = std::env::var("REGION").unwrap_or_else(|_| "NY".to_string());
43    println!("network {}", network);
44    println!("region {}", region);
45
46    let (base_url, secure) = match (network.as_str(), region.as_str()) {
47        ("LOCAL", _) => (LOCAL.to_string(), false),
48        ("TESTNET", _) => (TESTNET.to_string(), true),
49        ("MAINNET", "UK") => (MAINNET_UK.to_string(), true),
50        ("MAINNET", "NY") => (MAINNET_NY.to_string(), true),
51        ("MAINNET", "FRANKFURT") => (MAINNET_FRANKFURT.to_string(), true),
52        ("MAINNET", "LA") => (MAINNET_LA.to_string(), true),
53        ("MAINNET", "AMSTERDAM") => (MAINNET_AMSTERDAM.to_string(), true),
54        ("MAINNET", "TOKYO") => (MAINNET_TOKYO.to_string(), true),
55        ("MAINNET_PUMP", "NY") => (MAINNET_PUMP_NY.to_string(), true),
56        ("MAINNET_PUMP", "UK") => (MAINNET_PUMP_UK.to_string(), true),
57        _ => (MAINNET_NY.to_string(), false),
58    };
59
60    (base_url, secure)
61}
62
63pub struct BaseConfig {
64    pub auth_header: String,
65    pub keypair: Option<Keypair>,
66    pub public_key: Option<Pubkey>,
67}
68
69impl BaseConfig {
70    pub fn try_from_env() -> Result<Self> {
71        dotenv().ok();
72
73        let auth_header = env::var("AUTH_HEADER")
74            .map_err(|_| anyhow!("AUTH_HEADER environment variable not set"))?;
75
76        let public_key = env::var("PUBLIC_KEY").ok().and_then(|pk_str| {
77            Pubkey::from_str(&pk_str)
78                .map_err(|e| {
79                    println!("Warning: Failed to parse public key: {}", e);
80                    e
81                })
82                .ok()
83        });
84
85        let keypair = if let Ok(private_key) = env::var("PRIVATE_KEY") {
86            let mut output = [0; 64];
87            match decode(private_key).onto(&mut output) {
88                Ok(_) => match Keypair::from_bytes(&output) {
89                    Ok(kp) => Some(kp),
90                    Err(e) => {
91                        println!("Warning: Failed to create keypair: {}", e);
92                        None
93                    }
94                },
95                Err(e) => {
96                    println!("Warning: Failed to decode private key: {}", e);
97                    None
98                }
99            }
100        } else {
101            None
102        };
103
104        Ok(Self {
105            keypair,
106            auth_header,
107            public_key,
108        })
109    }
110}