Skip to content

Commit 811d02f

Browse files
smypmsaclaude
andcommitted
refactor: use alloy built-in keystore methods, drop eth-keystore and hex deps
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 211b45e commit 811d02f

File tree

3 files changed

+50
-29
lines changed

3 files changed

+50
-29
lines changed

Cargo.lock

Lines changed: 1 addition & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ path = "src/main.rs"
1515

1616
[dependencies]
1717
polymarket-client-sdk = { version = "0.4", features = ["gamma", "data", "bridge", "clob", "ctf"] }
18-
alloy = { version = "1.6.3", default-features = false, features = ["providers", "sol-types", "contract", "reqwest", "reqwest-rustls-tls", "signer-local", "signers"] }
18+
alloy = { version = "1.6.3", default-features = false, features = ["providers", "sol-types", "contract", "reqwest", "reqwest-rustls-tls", "signer-local", "signers", "signer-keystore"] }
1919
clap = { version = "4", features = ["derive"] }
2020
tokio = { version = "1", features = ["rt-multi-thread", "macros"] }
2121
serde_json = "1"
@@ -26,9 +26,7 @@ anyhow = "1"
2626
chrono = "0.4"
2727
dirs = "6"
2828
rustyline = "15"
29-
eth-keystore = "0.5"
3029
rpassword = "7"
31-
hex = "0.4"
3230
rand = "0.8"
3331

3432
[dev-dependencies]

src/config.rs

Lines changed: 48 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,8 @@ pub fn needs_migration() -> bool {
101101

102102
/// Encrypt a private key and save as keystore.json.
103103
pub fn save_key_encrypted(key_hex: &str, password: &str) -> Result<()> {
104+
use std::str::FromStr;
105+
104106
let dir = config_dir()?;
105107
fs::create_dir_all(&dir).context("Failed to create config directory")?;
106108

@@ -110,16 +112,15 @@ pub fn save_key_encrypted(key_hex: &str, password: &str) -> Result<()> {
110112
fs::set_permissions(&dir, fs::Permissions::from_mode(0o700))?;
111113
}
112114

113-
// Strip 0x prefix for raw bytes
114-
let hex_str = key_hex.strip_prefix("0x")
115-
.or_else(|| key_hex.strip_prefix("0X"))
116-
.unwrap_or(key_hex);
117-
let key_bytes = hex::decode(hex_str)
118-
.context("Invalid hex in private key")?;
115+
let signer = alloy::signers::local::LocalSigner::from_str(key_hex)
116+
.map_err(|e| anyhow::anyhow!("Invalid private key: {e}"))?;
117+
let key_bytes = signer.credential().to_bytes();
119118

120119
let mut rng = rand::thread_rng();
121-
let _uuid = eth_keystore::encrypt_key(&dir, &mut rng, &key_bytes, password, Some("keystore"))
122-
.map_err(|e| anyhow::anyhow!("Failed to encrypt keystore: {e}"))?;
120+
alloy::signers::local::LocalSigner::encrypt_keystore(
121+
&dir, &mut rng, key_bytes, password, Some("keystore"),
122+
)
123+
.map_err(|e| anyhow::anyhow!("Failed to encrypt keystore: {e}"))?;
123124

124125
// eth-keystore writes to dir/keystore — rename to keystore.json
125126
let written = dir.join("keystore");
@@ -141,16 +142,26 @@ pub fn save_key_encrypted(key_hex: &str, password: &str) -> Result<()> {
141142

142143
/// Decrypt keystore.json and return the private key as 0x-prefixed hex.
143144
pub fn load_key_encrypted(password: &str) -> Result<String> {
145+
use std::fmt::Write as _;
146+
144147
let path = keystore_path()?;
145-
let key_bytes = eth_keystore::decrypt_key(&path, password)
146-
.map_err(|e| match e {
147-
eth_keystore::KeystoreError::MacMismatch => {
148+
let signer = alloy::signers::local::LocalSigner::decrypt_keystore(&path, password)
149+
.map_err(|e| {
150+
let msg = e.to_string();
151+
if msg.contains("Mac Mismatch") {
148152
anyhow::anyhow!("Wrong password")
153+
} else {
154+
anyhow::anyhow!("Failed to decrypt keystore: {e}")
149155
}
150-
_ => anyhow::anyhow!("Failed to decrypt keystore: {e}"),
151156
})?;
152-
let hex_str: String = key_bytes.iter().map(|b| format!("{b:02x}")).collect();
153-
Ok(format!("0x{hex_str}"))
157+
158+
let bytes = signer.credential().to_bytes();
159+
let mut hex = String::with_capacity(2 + bytes.len() * 2);
160+
hex.push_str("0x");
161+
for b in &bytes {
162+
write!(hex, "{b:02x}").unwrap();
163+
}
164+
Ok(hex)
154165
}
155166

156167
/// Migrate old plaintext config to encrypted keystore.
@@ -291,38 +302,51 @@ mod tests {
291302

292303
#[test]
293304
fn keystore_encrypt_decrypt_round_trip() {
305+
use std::str::FromStr;
306+
294307
let temp = std::env::temp_dir().join("polymarket_test_keystore");
295308
let _ = fs::remove_dir_all(&temp);
296309
fs::create_dir_all(&temp).unwrap();
297310

298311
let key_hex = "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80";
299312
let password = "test_password_123";
300313

301-
let hex_str = key_hex.strip_prefix("0x").unwrap();
302-
let key_bytes = hex::decode(hex_str).unwrap();
314+
let original = alloy::signers::local::LocalSigner::from_str(key_hex).unwrap();
303315

304316
let mut rng = rand::thread_rng();
305-
eth_keystore::encrypt_key(&temp, &mut rng, &key_bytes, password, Some("test_ks"))
306-
.unwrap();
317+
alloy::signers::local::LocalSigner::encrypt_keystore(
318+
&temp, &mut rng, original.credential().to_bytes(), password, Some("test_ks"),
319+
)
320+
.unwrap();
307321

308-
let decrypted = eth_keystore::decrypt_key(temp.join("test_ks"), password).unwrap();
309-
assert_eq!(decrypted, key_bytes);
322+
let recovered =
323+
alloy::signers::local::LocalSigner::decrypt_keystore(temp.join("test_ks"), password)
324+
.unwrap();
325+
assert_eq!(original.address(), recovered.address());
310326

311327
let _ = fs::remove_dir_all(&temp);
312328
}
313329

314330
#[test]
315331
fn keystore_wrong_password_fails() {
332+
use std::str::FromStr;
333+
316334
let temp = std::env::temp_dir().join("polymarket_test_keystore_fail");
317335
let _ = fs::remove_dir_all(&temp);
318336
fs::create_dir_all(&temp).unwrap();
319337

320-
let key_bytes = [0u8; 32];
338+
let signer = alloy::signers::local::LocalSigner::from_str(
339+
"0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80",
340+
)
341+
.unwrap();
321342
let mut rng = rand::thread_rng();
322-
eth_keystore::encrypt_key(&temp, &mut rng, &key_bytes, "correct", Some("test_ks2"))
323-
.unwrap();
343+
alloy::signers::local::LocalSigner::encrypt_keystore(
344+
&temp, &mut rng, signer.credential().to_bytes(), "correct", Some("test_ks2"),
345+
)
346+
.unwrap();
324347

325-
let result = eth_keystore::decrypt_key(temp.join("test_ks2"), "wrong");
348+
let result =
349+
alloy::signers::local::LocalSigner::decrypt_keystore(temp.join("test_ks2"), "wrong");
326350
assert!(result.is_err());
327351

328352
let _ = fs::remove_dir_all(&temp);

0 commit comments

Comments
 (0)