@@ -4,8 +4,9 @@ use std::str::FromStr;
44use std:: sync:: Arc ;
55
66use key_wallet:: {
7- self as kw, address as kw_address, derivation:: HDWallet as KwHDWallet , mnemonic as kw_mnemonic,
8- DerivationPath as KwDerivationPath , ExtendedPrivKey , ExtendedPubKey , Network as KwNetwork ,
7+ self as kw, derivation:: HDWallet as KwHDWallet , mnemonic as kw_mnemonic, Address as KwAddress ,
8+ AddressType as KwAddressType , DerivationPath as KwDerivationPath , ExtendedPrivKey ,
9+ ExtendedPubKey , Network as KwNetwork ,
910} ;
1011use secp256k1:: { PublicKey , Secp256k1 } ;
1112
@@ -75,20 +76,21 @@ pub enum AddressType {
7576 P2SH ,
7677}
7778
78- impl From < kw_address :: AddressType > for AddressType {
79- fn from ( t : kw_address :: AddressType ) -> Self {
79+ impl From < KwAddressType > for AddressType {
80+ fn from ( t : KwAddressType ) -> Self {
8081 match t {
81- kw_address:: AddressType :: P2PKH => AddressType :: P2PKH ,
82- kw_address:: AddressType :: P2SH => AddressType :: P2SH ,
82+ KwAddressType :: P2pkh => AddressType :: P2PKH ,
83+ KwAddressType :: P2sh => AddressType :: P2SH ,
84+ _ => AddressType :: P2PKH , // Default to P2PKH for unknown types
8385 }
8486 }
8587}
8688
87- impl From < AddressType > for kw_address :: AddressType {
89+ impl From < AddressType > for KwAddressType {
8890 fn from ( t : AddressType ) -> Self {
8991 match t {
90- AddressType :: P2PKH => kw_address :: AddressType :: P2PKH ,
91- AddressType :: P2SH => kw_address :: AddressType :: P2SH ,
92+ AddressType :: P2PKH => KwAddressType :: P2pkh ,
93+ AddressType :: P2SH => KwAddressType :: P2sh ,
9294 }
9395 }
9496}
@@ -189,6 +191,15 @@ impl From<kw::Error> for KeyWalletError {
189191 kw:: Error :: KeyError ( msg) => KeyWalletError :: KeyError {
190192 message : msg,
191193 } ,
194+ kw:: Error :: CoinJoinNotEnabled => KeyWalletError :: KeyError {
195+ message : "CoinJoin not enabled" . into ( ) ,
196+ } ,
197+ kw:: Error :: Serialization ( msg) => KeyWalletError :: KeyError {
198+ message : format ! ( "Serialization error: {}" , msg) ,
199+ } ,
200+ kw:: Error :: InvalidParameter ( msg) => KeyWalletError :: KeyError {
201+ message : format ! ( "Invalid parameter: {}" , msg) ,
202+ } ,
192203 }
193204 }
194205}
@@ -201,6 +212,14 @@ impl From<kw::bip32::Error> for KeyWalletError {
201212 }
202213}
203214
215+ impl From < kw:: dashcore:: address:: Error > for KeyWalletError {
216+ fn from ( e : kw:: dashcore:: address:: Error ) -> Self {
217+ KeyWalletError :: AddressError {
218+ message : e. to_string ( ) ,
219+ }
220+ }
221+ }
222+
204223// Validate mnemonic function
205224pub fn validate_mnemonic ( phrase : String , language : Language ) -> Result < bool , KeyWalletError > {
206225 Ok ( kw:: Mnemonic :: validate ( & phrase, language. into ( ) ) )
@@ -439,53 +458,33 @@ impl ExtPubKey {
439458
440459// Address wrapper
441460pub struct Address {
442- inner : kw_address :: Address ,
461+ inner : KwAddress ,
443462}
444463
445464impl Address {
446465 pub fn from_string ( address : String , network : Network ) -> Result < Self , KeyWalletError > {
447- let inner = kw_address :: Address :: from_str ( & address) . map_err ( |e| KeyWalletError :: from ( e) ) ?;
466+ let unchecked_addr = KwAddress :: from_str ( & address) . map_err ( |e| KeyWalletError :: from ( e) ) ?;
448467
449- // Validate that the parsed network matches the expected network
450- // Note: Testnet, Devnet, and Regtest all share the same address prefixes (140/19)
451- // so we need to be flexible when comparing these networks
452- let parsed_network: KwNetwork = inner. network ;
468+ // Convert to expected network and require it
453469 let expected_network: KwNetwork = network. into ( ) ;
454-
455- let networks_compatible = match ( parsed_network, expected_network) {
456- // Exact matches are always OK
457- ( n1, n2) if n1 == n2 => true ,
458- // Testnet addresses can be used on devnet/regtest and vice versa
459- ( KwNetwork :: Testnet , KwNetwork :: Devnet )
460- | ( KwNetwork :: Testnet , KwNetwork :: Regtest )
461- | ( KwNetwork :: Devnet , KwNetwork :: Testnet )
462- | ( KwNetwork :: Devnet , KwNetwork :: Regtest )
463- | ( KwNetwork :: Regtest , KwNetwork :: Testnet )
464- | ( KwNetwork :: Regtest , KwNetwork :: Devnet ) => true ,
465- // All other combinations are incompatible
466- _ => false ,
467- } ;
468-
469- if !networks_compatible {
470- return Err ( KeyWalletError :: AddressError {
471- message : format ! (
472- "Address is for network {:?}, expected {:?}" ,
473- inner. network, network
474- ) ,
475- } ) ;
476- }
470+ let inner = unchecked_addr. require_network ( expected_network) . map_err ( |e| {
471+ KeyWalletError :: AddressError {
472+ message : format ! ( "Address network validation failed: {}" , e) ,
473+ }
474+ } ) ?;
477475
478476 Ok ( Self {
479477 inner,
480478 } )
481479 }
482480
483481 pub fn from_public_key ( public_key : Vec < u8 > , network : Network ) -> Result < Self , KeyWalletError > {
484- let pubkey =
482+ let secp_pubkey =
485483 PublicKey :: from_slice ( & public_key) . map_err ( |e| KeyWalletError :: Secp256k1Error {
486484 message : e. to_string ( ) ,
487485 } ) ?;
488- let inner = kw_address:: Address :: p2pkh ( & pubkey, network. into ( ) ) ;
486+ let dashcore_pubkey = kw:: dashcore:: PublicKey :: new ( secp_pubkey) ;
487+ let inner = KwAddress :: p2pkh ( & dashcore_pubkey, network. into ( ) ) ;
489488 Ok ( Self {
490489 inner,
491490 } )
@@ -496,11 +495,11 @@ impl Address {
496495 }
497496
498497 pub fn get_type ( & self ) -> AddressType {
499- self . inner . address_type . into ( )
498+ self . inner . address_type ( ) . unwrap_or ( KwAddressType :: P2pkh ) . into ( )
500499 }
501500
502501 pub fn get_network ( & self ) -> Network {
503- match self . inner . network {
502+ match * self . inner . network ( ) {
504503 KwNetwork :: Dash => Network :: Dash ,
505504 KwNetwork :: Testnet => Network :: Testnet ,
506505 KwNetwork :: Regtest => Network :: Regtest ,
@@ -510,19 +509,19 @@ impl Address {
510509 }
511510
512511 pub fn get_script_pubkey ( & self ) -> Vec < u8 > {
513- self . inner . script_pubkey ( )
512+ self . inner . script_pubkey ( ) . into ( )
514513 }
515514}
516515
517516// Address generator wrapper
518517pub struct AddressGenerator {
519- inner : kw_address :: AddressGenerator ,
518+ network : Network ,
520519}
521520
522521impl AddressGenerator {
523522 pub fn new ( network : Network ) -> Self {
524523 Self {
525- inner : kw_address :: AddressGenerator :: new ( network. into ( ) ) ,
524+ network,
526525 }
527526 }
528527
@@ -538,15 +537,44 @@ impl AddressGenerator {
538537 message : e. to_string ( ) ,
539538 } ) ?;
540539
541- // Generate addresses for a single index
542- let addrs = self
543- . inner
544- . generate_range ( & xpub, external, index, 1 )
545- . map_err ( |e| KeyWalletError :: from ( e) ) ?;
540+ let secp = Secp256k1 :: new ( ) ;
546541
547- let addr = addrs. into_iter ( ) . next ( ) . ok_or_else ( || KeyWalletError :: KeyError {
548- message : "Failed to generate address" . into ( ) ,
549- } ) ?;
542+ // Derive child key: 0 for external (receiving), 1 for internal (change)
543+ let chain_code = if external {
544+ 0
545+ } else {
546+ 1
547+ } ;
548+ let child_chain = xpub
549+ . ckd_pub (
550+ & secp,
551+ kw:: ChildNumber :: from_normal_idx ( chain_code) . map_err ( |e| {
552+ KeyWalletError :: InvalidDerivationPath {
553+ message : e. to_string ( ) ,
554+ }
555+ } ) ?,
556+ )
557+ . map_err ( |e| KeyWalletError :: KeyError {
558+ message : e. to_string ( ) ,
559+ } ) ?;
560+
561+ // Derive specific index
562+ let child = child_chain
563+ . ckd_pub (
564+ & secp,
565+ kw:: ChildNumber :: from_normal_idx ( index) . map_err ( |e| {
566+ KeyWalletError :: InvalidDerivationPath {
567+ message : e. to_string ( ) ,
568+ }
569+ } ) ?,
570+ )
571+ . map_err ( |e| KeyWalletError :: KeyError {
572+ message : e. to_string ( ) ,
573+ } ) ?;
574+
575+ // Generate P2PKH address from the public key
576+ let dashcore_pubkey = kw:: dashcore:: PublicKey :: new ( child. public_key ) ;
577+ let addr = KwAddress :: p2pkh ( & dashcore_pubkey, self . network . into ( ) ) ;
550578
551579 Ok ( Arc :: new ( Address {
552580 inner : addr,
@@ -560,25 +588,14 @@ impl AddressGenerator {
560588 start : u32 ,
561589 count : u32 ,
562590 ) -> Result < Vec < Arc < Address > > , KeyWalletError > {
563- // Parse the extended public key from string
564- let xpub =
565- ExtendedPubKey :: from_str ( & account_xpub. xpub ) . map_err ( |e| KeyWalletError :: KeyError {
566- message : e. to_string ( ) ,
567- } ) ?;
591+ let mut addresses = Vec :: new ( ) ;
568592
569- let addrs = self
570- . inner
571- . generate_range ( & xpub , external , start , count )
572- . map_err ( |e| KeyWalletError :: from ( e ) ) ? ;
593+ for i in 0 ..count {
594+ let addr = self . generate ( account_xpub . clone ( ) , external , start + i ) ? ;
595+ addresses . push ( addr ) ;
596+ }
573597
574- Ok ( addrs
575- . into_iter ( )
576- . map ( |addr| {
577- Arc :: new ( Address {
578- inner : addr,
579- } )
580- } )
581- . collect ( ) )
598+ Ok ( addresses)
582599 }
583600}
584601
0 commit comments