@@ -3,7 +3,10 @@ use alloy_chains::Chain;
3
3
use alloy_dyn_abi:: TypedData ;
4
4
use alloy_primitives:: { hex, Address , PrimitiveSignature as Signature , B256 , U256 } ;
5
5
use alloy_provider:: Provider ;
6
- use alloy_signer:: Signer ;
6
+ use alloy_signer:: {
7
+ k256:: { elliptic_curve:: sec1:: ToEncodedPoint , SecretKey } ,
8
+ Signer ,
9
+ } ;
7
10
use alloy_signer_local:: {
8
11
coins_bip39:: { English , Entropy , Mnemonic } ,
9
12
MnemonicBuilder , PrivateKeySigner ,
@@ -210,7 +213,16 @@ pub enum WalletSubcommands {
210
213
#[ command( flatten) ]
211
214
wallet : WalletOpts ,
212
215
} ,
216
+ /// Get the public key for the given private key.
217
+ #[ command( visible_aliases = & [ "pubkey" ] ) ]
218
+ PublicKey {
219
+ /// If provided, the public key will be derived from the specified private key.
220
+ #[ arg( long = "raw-private-key" , value_name = "PRIVATE_KEY" ) ]
221
+ private_key_override : Option < String > ,
213
222
223
+ #[ command( flatten) ]
224
+ wallet : WalletOpts ,
225
+ } ,
214
226
/// Decrypt a keystore file to get the private key
215
227
#[ command( name = "decrypt-keystore" , visible_alias = "dk" ) ]
216
228
DecryptKeystore {
@@ -398,6 +410,34 @@ impl WalletSubcommands {
398
410
let addr = wallet. address ( ) ;
399
411
sh_println ! ( "{}" , addr. to_checksum( None ) ) ?;
400
412
}
413
+ Self :: PublicKey { wallet, private_key_override } => {
414
+ let wallet = private_key_override
415
+ . map ( |pk| WalletOpts {
416
+ raw : RawWalletOpts { private_key : Some ( pk) , ..Default :: default ( ) } ,
417
+ ..Default :: default ( )
418
+ } )
419
+ . unwrap_or ( wallet)
420
+ . signer ( )
421
+ . await ?;
422
+
423
+ let private_key_bytes = match wallet {
424
+ WalletSigner :: Local ( wallet) => wallet. credential ( ) . to_bytes ( ) ,
425
+ _ => eyre:: bail!( "Only local wallets are supported by this command" ) ,
426
+ } ;
427
+
428
+ let secret_key = SecretKey :: from_slice ( & private_key_bytes)
429
+ . map_err ( |e| eyre:: eyre!( "Invalid private key: {}" , e) ) ?;
430
+
431
+ // Get the public key from the private key
432
+ let public_key = secret_key. public_key ( ) ;
433
+
434
+ // Serialize it as uncompressed (65 bytes: 0x04 || X (32 bytes) || Y (32 bytes))
435
+ let pubkey_bytes = public_key. to_encoded_point ( false ) ;
436
+ // Strip the 1-byte prefix (0x04) to get 64 bytes for Ethereum use
437
+ let ethereum_pubkey = & pubkey_bytes. as_bytes ( ) [ 1 ..] ;
438
+
439
+ sh_println ! ( "0x{}" , hex:: encode( ethereum_pubkey) ) ?;
440
+ }
401
441
Self :: Sign { message, data, from_file, no_hash, wallet } => {
402
442
let wallet = wallet. signer ( ) . await ?;
403
443
let sig = if data {
0 commit comments