-
Notifications
You must be signed in to change notification settings - Fork 101
feat: add SOCKS5/HTTP proxy support #21
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
d3d1f23
5acf9f7
e690e5f
27cb3e4
489d83e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -6,17 +6,21 @@ use serde::{Deserialize, Serialize}; | |
|
|
||
| const ENV_VAR: &str = "POLYMARKET_PRIVATE_KEY"; | ||
| const SIG_TYPE_ENV_VAR: &str = "POLYMARKET_SIGNATURE_TYPE"; | ||
| const PROXY_ENV_VAR: &str = "POLYMARKET_PROXY"; | ||
| pub const DEFAULT_SIGNATURE_TYPE: &str = "proxy"; | ||
|
|
||
| pub const NO_WALLET_MSG: &str = | ||
| "No wallet configured. Run `polymarket wallet create` or `polymarket wallet import <key>`"; | ||
|
|
||
| #[derive(Serialize, Deserialize)] | ||
| pub struct Config { | ||
| #[serde(default)] | ||
cursor[bot] marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| pub private_key: String, | ||
| pub chain_id: u64, | ||
| #[serde(default = "default_signature_type")] | ||
| pub signature_type: String, | ||
| #[serde(default, skip_serializing_if = "Option::is_none")] | ||
| pub proxy: Option<String>, | ||
| } | ||
|
|
||
| fn default_signature_type() -> String { | ||
|
|
@@ -94,10 +98,14 @@ pub fn save_wallet(key: &str, chain_id: u64, signature_type: &str) -> Result<()> | |
| fs::set_permissions(&dir, fs::Permissions::from_mode(0o700))?; | ||
| } | ||
|
|
||
| // Preserve existing proxy setting from config file | ||
| let existing_proxy = load_config().and_then(|c| c.proxy); | ||
|
|
||
| let config = Config { | ||
| private_key: key.to_string(), | ||
| chain_id, | ||
| signature_type: signature_type.to_string(), | ||
| proxy: existing_proxy, | ||
| }; | ||
| let json = serde_json::to_string_pretty(&config)?; | ||
| let path = config_path()?; | ||
|
|
@@ -125,6 +133,22 @@ pub fn save_wallet(key: &str, chain_id: u64, signature_type: &str) -> Result<()> | |
| Ok(()) | ||
| } | ||
|
|
||
|
|
||
| /// Priority: CLI flag > env var > config file. | ||
| pub fn resolve_proxy(cli_flag: Option<&str>) -> Option<String> { | ||
| if let Some(url) = cli_flag { | ||
| return Some(url.to_string()); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Empty proxy string not filtered from CLI flagLow Severity
|
||
| } | ||
| if let Ok(url) = std::env::var(PROXY_ENV_VAR) | ||
| && !url.is_empty() | ||
| { | ||
| return Some(url); | ||
| } | ||
| if let Some(config) = load_config() { | ||
| return config.proxy; | ||
| } | ||
| None | ||
| } | ||
| /// Priority: CLI flag > env var > config file. | ||
| pub fn resolve_key(cli_flag: Option<&str>) -> (Option<String>, KeySource) { | ||
| if let Some(key) = cli_flag { | ||
|
|
@@ -136,7 +160,9 @@ pub fn resolve_key(cli_flag: Option<&str>) -> (Option<String>, KeySource) { | |
| return (Some(key), KeySource::EnvVar); | ||
| } | ||
| if let Some(config) = load_config() { | ||
| return (Some(config.private_key), KeySource::ConfigFile); | ||
| if !config.private_key.is_empty() { | ||
| return (Some(config.private_key), KeySource::ConfigFile); | ||
| } | ||
| } | ||
| (None, KeySource::None) | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -26,6 +26,10 @@ pub(crate) struct Cli { | |
| /// Signature type: eoa, proxy, or gnosis-safe | ||
| #[arg(long, global = true)] | ||
| signature_type: Option<String>, | ||
|
|
||
| /// SOCKS5 or HTTP proxy URL (e.g., socks5://127.0.0.1:1080) | ||
| #[arg(long, global = true)] | ||
| proxy: Option<String>, | ||
| } | ||
|
|
||
| #[derive(Subcommand)] | ||
|
|
@@ -66,12 +70,32 @@ enum Commands { | |
| Upgrade, | ||
| } | ||
|
|
||
| #[tokio::main] | ||
| async fn main() -> ExitCode { | ||
| fn main() -> ExitCode { | ||
| // Resolve proxy BEFORE tokio spawns worker threads. | ||
| // Parse CLI args early (sync) to get --proxy flag. | ||
| let cli = Cli::parse(); | ||
|
|
||
| // Apply proxy: --proxy flag > POLYMARKET_PROXY env > config file proxy field. | ||
| // Only set HTTP(S)_PROXY for CLOB/Gamma API calls. | ||
| // Exclude the Polygon RPC so alloy (which uses reqwest 0.12 without socks | ||
| // support) can still reach the RPC directly. | ||
| if let Some(ref url) = config::resolve_proxy(cli.proxy.as_deref()) { | ||
| // SAFETY: no threads exist yet — called before tokio runtime is built. | ||
| unsafe { | ||
| std::env::set_var("HTTPS_PROXY", url); | ||
| std::env::set_var("HTTP_PROXY", url); | ||
| std::env::set_var("NO_PROXY", "polygon.drpc.org,drpc.org"); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. NO_PROXY overwrites existing user environment variable valuesMedium Severity Setting |
||
| } | ||
| } | ||
cursor[bot] marked this conversation as resolved.
Show resolved
Hide resolved
cursor[bot] marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| let output = cli.output; | ||
|
|
||
| if let Err(e) = run(cli).await { | ||
| let runtime = tokio::runtime::Builder::new_multi_thread() | ||
| .enable_all() | ||
| .build() | ||
| .expect("Failed to build tokio runtime"); | ||
|
|
||
| if let Err(e) = runtime.block_on(run(cli)) { | ||
| match output { | ||
| OutputFormat::Json => { | ||
| println!("{}", serde_json::json!({"error": e.to_string()})); | ||
|
|
||


There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cargo.lock missing
tokio-socksbreaks SOCKS5 proxy supportHigh Severity
The
Cargo.tomladdsreqwestwithfeatures = ["socks"], but the committedCargo.lockdoes not containtokio-socksanywhere — the required transitive dependency for SOCKS5 support. Thereqwest 0.13.2entry in the lockfile lists no socks-related dependencies. This means builds usingcargo install --lockedor CI with--lockedwill compilereqwestwithout actual SOCKS5 support, silently making the PR's core feature non-functional at runtime.Additional Locations (1)
Cargo.lock#L3464-L3503