@@ -34,6 +34,7 @@ impl From<BdkScriptBuf> for Script {
3434 }
3535}
3636
37+ #[ derive( PartialEq , Debug ) ]
3738pub enum Network {
3839 Bitcoin ,
3940 Testnet ,
@@ -121,6 +122,15 @@ impl Address {
121122 pub fn as_string ( & self ) -> String {
122123 self . inner . to_string ( )
123124 }
125+
126+ pub fn is_valid_for_network ( & self , network : Network ) -> bool {
127+ let address_str = self . inner . to_string ( ) ;
128+ if let Ok ( unchecked_address) = address_str. parse :: < BdkAddress < NetworkUnchecked > > ( ) {
129+ unchecked_address. is_valid_for_network ( network. into ( ) )
130+ } else {
131+ false
132+ }
133+ }
124134}
125135
126136impl From < Address > for BdkAddress {
@@ -314,3 +324,354 @@ impl From<&BdkTxOut> for TxOut {
314324 }
315325 }
316326}
327+
328+ #[ cfg( test) ]
329+ mod tests {
330+ use crate :: bitcoin:: Address ;
331+ use crate :: bitcoin:: Network ;
332+
333+ #[ test]
334+ fn test_is_valid_for_network ( ) {
335+ // ====Docs tests====
336+ // https://docs.rs/bitcoin/0.29.2/src/bitcoin/util/address.rs.html#798-802
337+
338+ let docs_address_testnet_str = "2N83imGV3gPwBzKJQvWJ7cRUY2SpUyU6A5e" ;
339+ let docs_address_testnet =
340+ Address :: new ( docs_address_testnet_str. to_string ( ) , Network :: Testnet ) . unwrap ( ) ;
341+ assert ! (
342+ docs_address_testnet. is_valid_for_network( Network :: Testnet ) ,
343+ "Address should be valid for Testnet"
344+ ) ;
345+ assert ! (
346+ docs_address_testnet. is_valid_for_network( Network :: Signet ) ,
347+ "Address should be valid for Signet"
348+ ) ;
349+ assert ! (
350+ docs_address_testnet. is_valid_for_network( Network :: Regtest ) ,
351+ "Address should be valid for Regtest"
352+ ) ;
353+ assert_ne ! (
354+ docs_address_testnet. network( ) ,
355+ Network :: Bitcoin ,
356+ "Address should not be parsed as Bitcoin"
357+ ) ;
358+
359+ let docs_address_mainnet_str = "32iVBEu4dxkUQk9dJbZUiBiQdmypcEyJRf" ;
360+ let docs_address_mainnet =
361+ Address :: new ( docs_address_mainnet_str. to_string ( ) , Network :: Bitcoin ) . unwrap ( ) ;
362+ assert ! (
363+ docs_address_mainnet. is_valid_for_network( Network :: Bitcoin ) ,
364+ "Address should be valid for Bitcoin"
365+ ) ;
366+ assert_ne ! (
367+ docs_address_mainnet. network( ) ,
368+ Network :: Testnet ,
369+ "Address should not be valid for Testnet"
370+ ) ;
371+ assert_ne ! (
372+ docs_address_mainnet. network( ) ,
373+ Network :: Signet ,
374+ "Address should not be valid for Signet"
375+ ) ;
376+ assert_ne ! (
377+ docs_address_mainnet. network( ) ,
378+ Network :: Regtest ,
379+ "Address should not be valid for Regtest"
380+ ) ;
381+
382+ // ====Bech32====
383+
384+ // | Network | Prefix | Address Type |
385+ // |-----------------|---------|--------------|
386+ // | Bitcoin Mainnet | `bc1` | Bech32 |
387+ // | Bitcoin Testnet | `tb1` | Bech32 |
388+ // | Bitcoin Signet | `tb1` | Bech32 |
389+ // | Bitcoin Regtest | `bcrt1` | Bech32 |
390+
391+ // Bech32 - Bitcoin
392+ // Valid for:
393+ // - Bitcoin
394+ // Not valid for:
395+ // - Testnet
396+ // - Signet
397+ // - Regtest
398+ let bitcoin_mainnet_bech32_address_str = "bc1qxhmdufsvnuaaaer4ynz88fspdsxq2h9e9cetdj" ;
399+ let bitcoin_mainnet_bech32_address = Address :: new (
400+ bitcoin_mainnet_bech32_address_str. to_string ( ) ,
401+ Network :: Bitcoin ,
402+ )
403+ . unwrap ( ) ;
404+ assert ! (
405+ bitcoin_mainnet_bech32_address. is_valid_for_network( Network :: Bitcoin ) ,
406+ "Address should be valid for Bitcoin"
407+ ) ;
408+ assert ! (
409+ !bitcoin_mainnet_bech32_address. is_valid_for_network( Network :: Testnet ) ,
410+ "Address should not be valid for Testnet"
411+ ) ;
412+ assert ! (
413+ !bitcoin_mainnet_bech32_address. is_valid_for_network( Network :: Signet ) ,
414+ "Address should not be valid for Signet"
415+ ) ;
416+ assert ! (
417+ !bitcoin_mainnet_bech32_address. is_valid_for_network( Network :: Regtest ) ,
418+ "Address should not be valid for Regtest"
419+ ) ;
420+
421+ // Bech32 - Testnet
422+ // Valid for:
423+ // - Testnet
424+ // - Regtest
425+ // Not valid for:
426+ // - Bitcoin
427+ // - Regtest
428+ let bitcoin_testnet_bech32_address_str =
429+ "tb1p4nel7wkc34raczk8c4jwk5cf9d47u2284rxn98rsjrs4w3p2sheqvjmfdh" ;
430+ let bitcoin_testnet_bech32_address = Address :: new (
431+ bitcoin_testnet_bech32_address_str. to_string ( ) ,
432+ Network :: Testnet ,
433+ )
434+ . unwrap ( ) ;
435+ assert ! (
436+ !bitcoin_testnet_bech32_address. is_valid_for_network( Network :: Bitcoin ) ,
437+ "Address should not be valid for Bitcoin"
438+ ) ;
439+ assert ! (
440+ bitcoin_testnet_bech32_address. is_valid_for_network( Network :: Testnet ) ,
441+ "Address should be valid for Testnet"
442+ ) ;
443+ assert ! (
444+ bitcoin_testnet_bech32_address. is_valid_for_network( Network :: Signet ) ,
445+ "Address should be valid for Signet"
446+ ) ;
447+ assert ! (
448+ !bitcoin_testnet_bech32_address. is_valid_for_network( Network :: Regtest ) ,
449+ "Address should not not be valid for Regtest"
450+ ) ;
451+
452+ // Bech32 - Signet
453+ // Valid for:
454+ // - Signet
455+ // - Testnet
456+ // Not valid for:
457+ // - Bitcoin
458+ // - Regtest
459+ let bitcoin_signet_bech32_address_str =
460+ "tb1pwzv7fv35yl7ypwj8w7al2t8apd6yf4568cs772qjwper74xqc99sk8x7tk" ;
461+ let bitcoin_signet_bech32_address = Address :: new (
462+ bitcoin_signet_bech32_address_str. to_string ( ) ,
463+ Network :: Signet ,
464+ )
465+ . unwrap ( ) ;
466+ assert ! (
467+ !bitcoin_signet_bech32_address. is_valid_for_network( Network :: Bitcoin ) ,
468+ "Address should not be valid for Bitcoin"
469+ ) ;
470+ assert ! (
471+ bitcoin_signet_bech32_address. is_valid_for_network( Network :: Testnet ) ,
472+ "Address should be valid for Testnet"
473+ ) ;
474+ assert ! (
475+ bitcoin_signet_bech32_address. is_valid_for_network( Network :: Signet ) ,
476+ "Address should be valid for Signet"
477+ ) ;
478+ assert ! (
479+ !bitcoin_signet_bech32_address. is_valid_for_network( Network :: Regtest ) ,
480+ "Address should not not be valid for Regtest"
481+ ) ;
482+
483+ // Bech32 - Regtest
484+ // Valid for:
485+ // - Regtest
486+ // Not valid for:
487+ // - Bitcoin
488+ // - Testnet
489+ // - Signet
490+ let bitcoin_regtest_bech32_address_str = "bcrt1q39c0vrwpgfjkhasu5mfke9wnym45nydfwaeems" ;
491+ let bitcoin_regtest_bech32_address = Address :: new (
492+ bitcoin_regtest_bech32_address_str. to_string ( ) ,
493+ Network :: Regtest ,
494+ )
495+ . unwrap ( ) ;
496+ assert ! (
497+ !bitcoin_regtest_bech32_address. is_valid_for_network( Network :: Bitcoin ) ,
498+ "Address should not be valid for Bitcoin"
499+ ) ;
500+ assert ! (
501+ !bitcoin_regtest_bech32_address. is_valid_for_network( Network :: Testnet ) ,
502+ "Address should not be valid for Testnet"
503+ ) ;
504+ assert ! (
505+ !bitcoin_regtest_bech32_address. is_valid_for_network( Network :: Signet ) ,
506+ "Address should not be valid for Signet"
507+ ) ;
508+ assert ! (
509+ bitcoin_regtest_bech32_address. is_valid_for_network( Network :: Regtest ) ,
510+ "Address should be valid for Regtest"
511+ ) ;
512+
513+ // ====P2PKH====
514+
515+ // | Network | Prefix for P2PKH | Prefix for P2SH |
516+ // |------------------------------------|------------------|-----------------|
517+ // | Bitcoin Mainnet | `1` | `3` |
518+ // | Bitcoin Testnet, Regtest, Signet | `m` or `n` | `2` |
519+
520+ // P2PKH - Bitcoin
521+ // Valid for:
522+ // - Bitcoin
523+ // Not valid for:
524+ // - Testnet
525+ // - Regtest
526+ let bitcoin_mainnet_p2pkh_address_str = "1FfmbHfnpaZjKFvyi1okTjJJusN455paPH" ;
527+ let bitcoin_mainnet_p2pkh_address = Address :: new (
528+ bitcoin_mainnet_p2pkh_address_str. to_string ( ) ,
529+ Network :: Bitcoin ,
530+ )
531+ . unwrap ( ) ;
532+ assert ! (
533+ bitcoin_mainnet_p2pkh_address. is_valid_for_network( Network :: Bitcoin ) ,
534+ "Address should be valid for Bitcoin"
535+ ) ;
536+ assert ! (
537+ !bitcoin_mainnet_p2pkh_address. is_valid_for_network( Network :: Testnet ) ,
538+ "Address should not be valid for Testnet"
539+ ) ;
540+ assert ! (
541+ !bitcoin_mainnet_p2pkh_address. is_valid_for_network( Network :: Regtest ) ,
542+ "Address should not be valid for Regtest"
543+ ) ;
544+
545+ // P2PKH - Testnet
546+ // Valid for:
547+ // - Testnet
548+ // - Regtest
549+ // Not valid for:
550+ // - Bitcoin
551+ let bitcoin_testnet_p2pkh_address_str = "mucFNhKMYoBQYUAEsrFVscQ1YaFQPekBpg" ;
552+ let bitcoin_testnet_p2pkh_address = Address :: new (
553+ bitcoin_testnet_p2pkh_address_str. to_string ( ) ,
554+ Network :: Testnet ,
555+ )
556+ . unwrap ( ) ;
557+ assert ! (
558+ !bitcoin_testnet_p2pkh_address. is_valid_for_network( Network :: Bitcoin ) ,
559+ "Address should not be valid for Bitcoin"
560+ ) ;
561+ assert ! (
562+ bitcoin_testnet_p2pkh_address. is_valid_for_network( Network :: Testnet ) ,
563+ "Address should be valid for Testnet"
564+ ) ;
565+ assert ! (
566+ bitcoin_testnet_p2pkh_address. is_valid_for_network( Network :: Regtest ) ,
567+ "Address should be valid for Regtest"
568+ ) ;
569+
570+ // P2PKH - Regtest
571+ // Valid for:
572+ // - Testnet
573+ // - Regtest
574+ // Not valid for:
575+ // - Bitcoin
576+ let bitcoin_regtest_p2pkh_address_str = "msiGFK1PjCk8E6FXeoGkQPTscmcpyBdkgS" ;
577+ let bitcoin_regtest_p2pkh_address = Address :: new (
578+ bitcoin_regtest_p2pkh_address_str. to_string ( ) ,
579+ Network :: Regtest ,
580+ )
581+ . unwrap ( ) ;
582+ assert ! (
583+ !bitcoin_regtest_p2pkh_address. is_valid_for_network( Network :: Bitcoin ) ,
584+ "Address should not be valid for Bitcoin"
585+ ) ;
586+ assert ! (
587+ bitcoin_regtest_p2pkh_address. is_valid_for_network( Network :: Testnet ) ,
588+ "Address should be valid for Testnet"
589+ ) ;
590+ assert ! (
591+ bitcoin_regtest_p2pkh_address. is_valid_for_network( Network :: Regtest ) ,
592+ "Address should be valid for Regtest"
593+ ) ;
594+
595+ // ====P2SH====
596+
597+ // | Network | Prefix for P2PKH | Prefix for P2SH |
598+ // |------------------------------------|------------------|-----------------|
599+ // | Bitcoin Mainnet | `1` | `3` |
600+ // | Bitcoin Testnet, Regtest, Signet | `m` or `n` | `2` |
601+
602+ // P2SH - Bitcoin
603+ // Valid for:
604+ // - Bitcoin
605+ // Not valid for:
606+ // - Testnet
607+ // - Regtest
608+ let bitcoin_mainnet_p2sh_address_str = "3J98t1WpEZ73CNmQviecrnyiWrnqRhWNLy" ;
609+ let bitcoin_mainnet_p2sh_address = Address :: new (
610+ bitcoin_mainnet_p2sh_address_str. to_string ( ) ,
611+ Network :: Bitcoin ,
612+ )
613+ . unwrap ( ) ;
614+ assert ! (
615+ bitcoin_mainnet_p2sh_address. is_valid_for_network( Network :: Bitcoin ) ,
616+ "Address should be valid for Bitcoin"
617+ ) ;
618+ assert ! (
619+ !bitcoin_mainnet_p2sh_address. is_valid_for_network( Network :: Testnet ) ,
620+ "Address should not be valid for Testnet"
621+ ) ;
622+ assert ! (
623+ !bitcoin_mainnet_p2sh_address. is_valid_for_network( Network :: Regtest ) ,
624+ "Address should not be valid for Regtest"
625+ ) ;
626+
627+ // P2SH - Testnet
628+ // Valid for:
629+ // - Testnet
630+ // - Regtest
631+ // Not valid for:
632+ // - Bitcoin
633+ let bitcoin_testnet_p2sh_address_str = "2NFUBBRcTJbYc1D4HSCbJhKZp6YCV4PQFpQ" ;
634+ let bitcoin_testnet_p2sh_address = Address :: new (
635+ bitcoin_testnet_p2sh_address_str. to_string ( ) ,
636+ Network :: Testnet ,
637+ )
638+ . unwrap ( ) ;
639+ assert ! (
640+ !bitcoin_testnet_p2sh_address. is_valid_for_network( Network :: Bitcoin ) ,
641+ "Address should not be valid for Bitcoin"
642+ ) ;
643+ assert ! (
644+ bitcoin_testnet_p2sh_address. is_valid_for_network( Network :: Testnet ) ,
645+ "Address should be valid for Testnet"
646+ ) ;
647+ assert ! (
648+ bitcoin_testnet_p2sh_address. is_valid_for_network( Network :: Regtest ) ,
649+ "Address should be valid for Regtest"
650+ ) ;
651+
652+ // P2SH - Regtest
653+ // Valid for:
654+ // - Testnet
655+ // - Regtest
656+ // Not valid for:
657+ // - Bitcoin
658+ let bitcoin_regtest_p2sh_address_str = "2NEb8N5B9jhPUCBchz16BB7bkJk8VCZQjf3" ;
659+ let bitcoin_regtest_p2sh_address = Address :: new (
660+ bitcoin_regtest_p2sh_address_str. to_string ( ) ,
661+ Network :: Regtest ,
662+ )
663+ . unwrap ( ) ;
664+ assert ! (
665+ !bitcoin_regtest_p2sh_address. is_valid_for_network( Network :: Bitcoin ) ,
666+ "Address should not be valid for Bitcoin"
667+ ) ;
668+ assert ! (
669+ bitcoin_regtest_p2sh_address. is_valid_for_network( Network :: Testnet ) ,
670+ "Address should be valid for Testnet"
671+ ) ;
672+ assert ! (
673+ bitcoin_regtest_p2sh_address. is_valid_for_network( Network :: Regtest ) ,
674+ "Address should be valid for Regtest"
675+ ) ;
676+ }
677+ }
0 commit comments