@@ -101,6 +101,8 @@ pub fn needs_migration() -> bool {
101101
102102/// Encrypt a private key and save as keystore.json.
103103pub 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.
143144pub 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