@@ -22,9 +22,22 @@ use bdk_wallet::bitcoin::consensus::encode::serialize_hex;
2222use bdk_wallet:: bitcoin:: script:: PushBytesBuf ;
2323use bdk_wallet:: bitcoin:: Network ;
2424use bdk_wallet:: bitcoin:: { secp256k1:: Secp256k1 , Txid } ;
25- use bdk_wallet:: bitcoin:: { Amount , FeeRate , Psbt , Sequence } ;
2625use bdk_wallet:: descriptor:: Segwitv0 ;
2726use bdk_wallet:: keys:: bip39:: WordCount ;
27+ use bdk_wallet:: keys:: { GeneratableKey , GeneratedKey } ;
28+ use bdk_wallet:: serde:: ser:: Error as SerdeErrorTrait ;
29+ use serde_json:: json;
30+ use serde_json:: Error as SerdeError ;
31+ use serde_json:: Value ;
32+
33+ #[ cfg( any(
34+ feature = "electrum" ,
35+ feature = "esplora" ,
36+ feature = "cbf" ,
37+ feature = "rpc"
38+ ) ) ]
39+ use bdk_wallet:: bitcoin:: Transaction ;
40+ use bdk_wallet:: bitcoin:: { Amount , FeeRate , Psbt , Sequence } ;
2841#[ cfg( feature = "sqlite" ) ]
2942use bdk_wallet:: rusqlite:: Connection ;
3043#[ cfg( feature = "compiler" ) ]
@@ -33,18 +46,18 @@ use bdk_wallet::{
3346 miniscript:: policy:: Concrete ,
3447} ;
3548use bdk_wallet:: { KeychainKind , SignOptions , Wallet } ;
49+ use std:: fmt;
50+ use std:: str:: FromStr ;
3651
3752use bdk_wallet:: keys:: DescriptorKey :: Secret ;
38- use bdk_wallet:: keys:: { DerivableKey , DescriptorKey , ExtendedKey , GeneratableKey , GeneratedKey } ;
53+ use bdk_wallet:: keys:: { DerivableKey , DescriptorKey , ExtendedKey } ;
3954use bdk_wallet:: miniscript:: miniscript;
40- use serde_json:: json;
4155use std:: collections:: BTreeMap ;
4256#[ cfg( any( feature = "electrum" , feature = "esplora" ) ) ]
4357use std:: collections:: HashSet ;
4458use std:: convert:: TryFrom ;
4559#[ cfg( any( feature = "repl" , feature = "electrum" , feature = "esplora" ) ) ]
4660use std:: io:: Write ;
47- use std:: str:: FromStr ;
4861
4962#[ cfg( feature = "electrum" ) ]
5063use crate :: utils:: BlockchainClient :: Electrum ;
@@ -61,7 +74,7 @@ use tokio::select;
6174) ) ]
6275use {
6376 crate :: commands:: OnlineWalletSubCommand :: * ,
64- bdk_wallet:: bitcoin:: { consensus:: Decodable , hex:: FromHex , Transaction } ,
77+ bdk_wallet:: bitcoin:: { consensus:: Decodable , hex:: FromHex } ,
6578} ;
6679#[ cfg( feature = "esplora" ) ]
6780use { crate :: utils:: BlockchainClient :: Esplora , bdk_esplora:: EsploraAsyncExt } ;
@@ -909,6 +922,13 @@ pub(crate) async fn handle_command(cli_opts: CliOpts) -> Result<String, Error> {
909922 }
910923 Ok ( "" . to_string ( ) )
911924 }
925+ CliSubCommand :: Descriptor ( args) => {
926+ let network = cli_opts. network ;
927+ let descriptor = generate_descriptor_from_args ( args. clone ( ) , network)
928+ . map_err ( |e| SerdeError :: custom ( e. to_string ( ) ) ) ?;
929+ let json = serde_json:: to_string_pretty ( & descriptor) ?;
930+ Ok ( json)
931+ }
912932 } ;
913933 result. map_err ( |e| e. into ( ) )
914934}
@@ -980,6 +1000,57 @@ fn readline() -> Result<String, Error> {
9801000 Ok ( buffer)
9811001}
9821002
1003+ pub fn generate_descriptor_from_args (
1004+ args : GenerateDescriptorArgs ,
1005+ network : Network ,
1006+ ) -> Result < serde_json:: Value , Error > {
1007+ match ( args. multipath , args. key . as_ref ( ) ) {
1008+ ( true , Some ( key) ) => generate_multipath_descriptor ( & network, args. r#type , key) ,
1009+ ( false , Some ( key) ) => generate_standard_descriptor ( & network, args. r#type , key) ,
1010+ ( false , None ) => {
1011+ // New default: generate descriptor from fresh mnemonic (for script_type 84 only)
1012+ if args. r#type == 84 {
1013+ generate_new_bip84_descriptor_with_mnemonic ( network)
1014+ } else {
1015+ Err ( Error :: Generic (
1016+ "Only script type 84 is supported for mnemonic-based generation" . to_string ( ) ,
1017+ ) )
1018+ }
1019+ }
1020+ _ => Err ( Error :: InvalidArguments (
1021+ "Invalid arguments: please provide a key or a weak string" . to_string ( ) ,
1022+ ) ) ,
1023+ }
1024+ }
1025+
1026+ pub fn generate_standard_descriptor (
1027+ network : & Network ,
1028+ script_type : u8 ,
1029+ key : & str ,
1030+ ) -> Result < Value , Error > {
1031+ let descriptor_type = match script_type {
1032+ 44 => DescriptorType :: Bip44 ,
1033+ 49 => DescriptorType :: Bip49 ,
1034+ 84 => DescriptorType :: Bip84 ,
1035+ 86 => DescriptorType :: Bip86 ,
1036+ _ => return Err ( Error :: UnsupportedScriptType ( script_type) ) ,
1037+ } ;
1038+
1039+ generate_descriptor_from_key_by_type ( network, key, descriptor_type)
1040+ }
1041+
1042+ impl fmt:: Display for DescriptorType {
1043+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
1044+ let s = match self {
1045+ DescriptorType :: Bip44 => "bip44" ,
1046+ DescriptorType :: Bip49 => "bip49" ,
1047+ DescriptorType :: Bip84 => "bip84" ,
1048+ DescriptorType :: Bip86 => "bip86" ,
1049+ } ;
1050+ write ! ( f, "{}" , s)
1051+ }
1052+ }
1053+
9831054#[ cfg( any(
9841055 feature = "electrum" ,
9851056 feature = "esplora" ,
0 commit comments