From 0c55155fa3783f1d6359babe6375fe4d697c456e Mon Sep 17 00:00:00 2001 From: ssy Date: Thu, 26 Feb 2026 21:52:07 +0800 Subject: [PATCH 1/3] fix: use derive_safe_wallet instead of derive_proxy_wallet for default proxy derivation The CLI used derive_proxy_wallet (EIP-1167 minimal proxy) to derive the proxy wallet address, but Polymarket deploys Gnosis Safe wallets for browser wallet users. This caused the derived address to not match the actual proxy wallet returned by the profiles API. Changes: - Default signature_type from "proxy" to "gnosis-safe" - Replace all derive_proxy_wallet calls with derive_safe_wallet in wallet.rs and setup.rs - Decouple parse_signature_type from DEFAULT_SIGNATURE_TYPE constant to avoid incorrect mapping after the default change Users can still use --signature-type proxy for Magic Link accounts. Fixes #14 --- src/auth.rs | 2 +- src/commands/setup.rs | 4 ++-- src/commands/wallet.rs | 16 ++++++++-------- src/config.rs | 2 +- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/auth.rs b/src/auth.rs index 15ad61e..3958b6c 100644 --- a/src/auth.rs +++ b/src/auth.rs @@ -13,7 +13,7 @@ pub const RPC_URL: &str = "https://polygon.drpc.org"; fn parse_signature_type(s: &str) -> SignatureType { match s { - config::DEFAULT_SIGNATURE_TYPE => SignatureType::Proxy, + "proxy" => SignatureType::Proxy, "gnosis-safe" => SignatureType::GnosisSafe, _ => SignatureType::Eoa, } diff --git a/src/commands/setup.rs b/src/commands/setup.rs index dd04671..e7268f7 100644 --- a/src/commands/setup.rs +++ b/src/commands/setup.rs @@ -5,7 +5,7 @@ use std::str::FromStr; use anyhow::{Context, Result}; use polymarket_client_sdk::auth::{LocalSigner, Signer as _}; use polymarket_client_sdk::types::Address; -use polymarket_client_sdk::{POLYGON, derive_proxy_wallet}; +use polymarket_client_sdk::{POLYGON, derive_safe_wallet}; use super::wallet::normalize_key; use crate::config; @@ -156,7 +156,7 @@ fn finish_setup(address: Address) -> Result<()> { step_header(2, total, "Proxy Wallet"); - let proxy = derive_proxy_wallet(address, POLYGON); + let proxy = derive_safe_wallet(address, POLYGON); match proxy { Some(proxy) => { println!(" ✓ Proxy wallet derived"); diff --git a/src/commands/wallet.rs b/src/commands/wallet.rs index ce7597f..e80e018 100644 --- a/src/commands/wallet.rs +++ b/src/commands/wallet.rs @@ -5,7 +5,7 @@ use anyhow::{Context, Result, bail}; use clap::{Args, Subcommand}; use polymarket_client_sdk::auth::LocalSigner; use polymarket_client_sdk::auth::Signer as _; -use polymarket_client_sdk::{POLYGON, derive_proxy_wallet}; +use polymarket_client_sdk::{POLYGON, derive_safe_wallet}; use crate::config; use crate::output::OutputFormat; @@ -23,8 +23,8 @@ pub enum WalletCommand { /// Overwrite existing wallet #[arg(long)] force: bool, - /// Signature type: eoa, proxy (default), or gnosis-safe - #[arg(long, default_value = "proxy")] + /// Signature type: eoa, proxy, or gnosis-safe (default) + #[arg(long, default_value = "gnosis-safe")] signature_type: String, }, /// Import an existing private key @@ -34,8 +34,8 @@ pub enum WalletCommand { /// Overwrite existing wallet #[arg(long)] force: bool, - /// Signature type: eoa, proxy (default), or gnosis-safe - #[arg(long, default_value = "proxy")] + /// Signature type: eoa, proxy, or gnosis-safe (default) + #[arg(long, default_value = "gnosis-safe")] signature_type: String, }, /// Show the address of the configured wallet @@ -103,7 +103,7 @@ fn cmd_create(output: &OutputFormat, force: bool, signature_type: &str) -> Resul config::save_wallet(&key_hex, POLYGON, signature_type)?; let config_path = config::config_path()?; - let proxy_addr = derive_proxy_wallet(address, POLYGON); + let proxy_addr = derive_safe_wallet(address, POLYGON); match output { OutputFormat::Json => { @@ -144,7 +144,7 @@ fn cmd_import(key: &str, output: &OutputFormat, force: bool, signature_type: &st config::save_wallet(&normalized, POLYGON, signature_type)?; let config_path = config::config_path()?; - let proxy_addr = derive_proxy_wallet(address, POLYGON); + let proxy_addr = derive_safe_wallet(address, POLYGON); match output { OutputFormat::Json => { @@ -195,7 +195,7 @@ fn cmd_show(output: &OutputFormat, private_key_flag: Option<&str>) -> Result<()> let address = signer.as_ref().map(|s| s.address().to_string()); let proxy_addr = signer .as_ref() - .and_then(|s| derive_proxy_wallet(s.address(), POLYGON)) + .and_then(|s| derive_safe_wallet(s.address(), POLYGON)) .map(|a| a.to_string()); let sig_type = config::resolve_signature_type(None); diff --git a/src/config.rs b/src/config.rs index d2f5395..49b3349 100644 --- a/src/config.rs +++ b/src/config.rs @@ -6,7 +6,7 @@ use serde::{Deserialize, Serialize}; const ENV_VAR: &str = "POLYMARKET_PRIVATE_KEY"; const SIG_TYPE_ENV_VAR: &str = "POLYMARKET_SIGNATURE_TYPE"; -pub const DEFAULT_SIGNATURE_TYPE: &str = "proxy"; +pub const DEFAULT_SIGNATURE_TYPE: &str = "gnosis-safe"; pub const NO_WALLET_MSG: &str = "No wallet configured. Run `polymarket wallet create` or `polymarket wallet import `"; From 986c51e09c9fa8ce78fa79560e89dcc63326b642 Mon Sep 17 00:00:00 2001 From: ssy Date: Sat, 28 Feb 2026 13:56:19 +0800 Subject: [PATCH 2/3] fix: derive proxy address dynamically based on signature_type MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The previous commit unconditionally used derive_safe_wallet() for all signature types. When a user specifies --signature-type proxy, the CLI would incorrectly display a Gnosis Safe address instead of the EIP-1167 proxy address. Add derive_wallet_for_type() helper that dispatches to the correct derivation function based on signature_type: - "proxy" → derive_proxy_wallet() (EIP-1167) - "gnosis-safe" → derive_safe_wallet() (Gnosis Safe) - "eoa" / other → None Apply this to wallet create, import, show, and setup finish_setup(). --- src/commands/setup.rs | 14 +++++++++----- src/commands/wallet.rs | 29 +++++++++++++++++++++++------ 2 files changed, 32 insertions(+), 11 deletions(-) diff --git a/src/commands/setup.rs b/src/commands/setup.rs index e7268f7..bf0b622 100644 --- a/src/commands/setup.rs +++ b/src/commands/setup.rs @@ -5,7 +5,7 @@ use std::str::FromStr; use anyhow::{Context, Result}; use polymarket_client_sdk::auth::{LocalSigner, Signer as _}; use polymarket_client_sdk::types::Address; -use polymarket_client_sdk::{POLYGON, derive_safe_wallet}; +use polymarket_client_sdk::{POLYGON, derive_proxy_wallet, derive_safe_wallet}; use super::wallet::normalize_key; use crate::config; @@ -95,7 +95,7 @@ pub fn execute() -> Result<()> { println!(); if !prompt_yn(" Reconfigure wallet?", false)? { - finish_setup(addr)?; + finish_setup(addr, &config::resolve_signature_type(None))?; return Ok(()); } println!(); @@ -107,7 +107,7 @@ pub fn execute() -> Result<()> { println!(); - finish_setup(address) + finish_setup(address, &config::resolve_signature_type(None)) } fn setup_wallet() -> Result
{ @@ -151,12 +151,16 @@ fn setup_wallet() -> Result
{ Ok(address) } -fn finish_setup(address: Address) -> Result<()> { +fn finish_setup(address: Address, signature_type: &str) -> Result<()> { let total = 4; step_header(2, total, "Proxy Wallet"); - let proxy = derive_safe_wallet(address, POLYGON); + let proxy = match signature_type { + "proxy" => derive_proxy_wallet(address, POLYGON), + "gnosis-safe" => derive_safe_wallet(address, POLYGON), + _ => None, + }; match proxy { Some(proxy) => { println!(" ✓ Proxy wallet derived"); diff --git a/src/commands/wallet.rs b/src/commands/wallet.rs index e80e018..8b5ef95 100644 --- a/src/commands/wallet.rs +++ b/src/commands/wallet.rs @@ -5,11 +5,29 @@ use anyhow::{Context, Result, bail}; use clap::{Args, Subcommand}; use polymarket_client_sdk::auth::LocalSigner; use polymarket_client_sdk::auth::Signer as _; -use polymarket_client_sdk::{POLYGON, derive_safe_wallet}; +use polymarket_client_sdk::types::Address; +use polymarket_client_sdk::{POLYGON, derive_proxy_wallet, derive_safe_wallet}; use crate::config; use crate::output::OutputFormat; +/// Derive the appropriate proxy/safe wallet address based on signature type. +/// +/// - `"proxy"` → EIP-1167 proxy wallet +/// - `"gnosis-safe"` → Gnosis Safe wallet +/// - `"eoa"` / other → `None` (no proxy wallet) +fn derive_wallet_for_type( + address: Address, + chain_id: u64, + signature_type: &str, +) -> Option
{ + match signature_type { + "proxy" => derive_proxy_wallet(address, chain_id), + "gnosis-safe" => derive_safe_wallet(address, chain_id), + _ => None, + } +} + #[derive(Args)] pub struct WalletArgs { #[command(subcommand)] @@ -103,7 +121,7 @@ fn cmd_create(output: &OutputFormat, force: bool, signature_type: &str) -> Resul config::save_wallet(&key_hex, POLYGON, signature_type)?; let config_path = config::config_path()?; - let proxy_addr = derive_safe_wallet(address, POLYGON); + let proxy_addr = derive_wallet_for_type(address, POLYGON, signature_type); match output { OutputFormat::Json => { @@ -144,7 +162,7 @@ fn cmd_import(key: &str, output: &OutputFormat, force: bool, signature_type: &st config::save_wallet(&normalized, POLYGON, signature_type)?; let config_path = config::config_path()?; - let proxy_addr = derive_safe_wallet(address, POLYGON); + let proxy_addr = derive_wallet_for_type(address, POLYGON, signature_type); match output { OutputFormat::Json => { @@ -193,12 +211,11 @@ fn cmd_show(output: &OutputFormat, private_key_flag: Option<&str>) -> Result<()> let (key, source) = config::resolve_key(private_key_flag); let signer = key.as_deref().and_then(|k| LocalSigner::from_str(k).ok()); let address = signer.as_ref().map(|s| s.address().to_string()); + let sig_type = config::resolve_signature_type(None); let proxy_addr = signer .as_ref() - .and_then(|s| derive_safe_wallet(s.address(), POLYGON)) + .and_then(|s| derive_wallet_for_type(s.address(), POLYGON, &sig_type)) .map(|a| a.to_string()); - - let sig_type = config::resolve_signature_type(None); let config_path = config::config_path()?; match output { From c9255cad95969b9f4817573ea7e97c0d72bfb6fb Mon Sep 17 00:00:00 2001 From: ssy Date: Sat, 28 Feb 2026 14:20:04 +0800 Subject: [PATCH 3/3] refactor: deduplicate wallet derivation logic via shared helper Move derive_wallet_for_type() to pub(crate) in wallet.rs and reuse it in setup.rs instead of duplicating the signature_type match inline. --- src/commands/setup.rs | 10 +++------- src/commands/wallet.rs | 2 +- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/src/commands/setup.rs b/src/commands/setup.rs index bf0b622..609db36 100644 --- a/src/commands/setup.rs +++ b/src/commands/setup.rs @@ -5,9 +5,9 @@ use std::str::FromStr; use anyhow::{Context, Result}; use polymarket_client_sdk::auth::{LocalSigner, Signer as _}; use polymarket_client_sdk::types::Address; -use polymarket_client_sdk::{POLYGON, derive_proxy_wallet, derive_safe_wallet}; +use polymarket_client_sdk::POLYGON; -use super::wallet::normalize_key; +use super::wallet::{derive_wallet_for_type, normalize_key}; use crate::config; fn print_banner() { @@ -156,11 +156,7 @@ fn finish_setup(address: Address, signature_type: &str) -> Result<()> { step_header(2, total, "Proxy Wallet"); - let proxy = match signature_type { - "proxy" => derive_proxy_wallet(address, POLYGON), - "gnosis-safe" => derive_safe_wallet(address, POLYGON), - _ => None, - }; + let proxy = derive_wallet_for_type(address, POLYGON, signature_type); match proxy { Some(proxy) => { println!(" ✓ Proxy wallet derived"); diff --git a/src/commands/wallet.rs b/src/commands/wallet.rs index 8b5ef95..9717fe4 100644 --- a/src/commands/wallet.rs +++ b/src/commands/wallet.rs @@ -16,7 +16,7 @@ use crate::output::OutputFormat; /// - `"proxy"` → EIP-1167 proxy wallet /// - `"gnosis-safe"` → Gnosis Safe wallet /// - `"eoa"` / other → `None` (no proxy wallet) -fn derive_wallet_for_type( +pub(crate) fn derive_wallet_for_type( address: Address, chain_id: u64, signature_type: &str,