]> Untitled Git - bdk-cli/commitdiff
ref(handlers): add types for desc, key & wallets
authorVihiga Tyonum <withtvpeter@gmail.com>
Wed, 29 Apr 2026 08:09:01 +0000 (09:09 +0100)
committerVihiga Tyonum <withtvpeter@gmail.com>
Fri, 5 Jun 2026 16:12:21 +0000 (17:12 +0100)
- add types for descriptor, key and wallets mods

src/handlers/descriptor.rs
src/handlers/key.rs
src/handlers/offline.rs
src/handlers/wallets.rs

index c76c0781e91937eeaa0e0e88a5b99e4893bcaeef..44f1954a8fb03f34fefc7d0e5a9b091775b6924a 100644 (file)
@@ -11,14 +11,14 @@ use crate::{
 
 #[cfg(feature = "compiler")]
 use {
+    crate::handlers::types::DescriptorResult,
+    crate::utils::output::FormatOutput,
     bdk_wallet::{
         bitcoin::XOnlyPublicKey,
         miniscript::{
             Descriptor, Legacy, Miniscript, Segwitv0, Tap, descriptor::TapTree, policy::Concrete,
         },
     },
-    cli_table::{Cell, Style, Table},
-    serde_json::json,
     std::{str::FromStr, sync::Arc},
 };
 
@@ -93,18 +93,12 @@ pub(crate) fn handle_compile_subcommand(
             ));
         }
     }?;
-    if pretty {
-        let table = vec![vec![
-            "Descriptor".cell().bold(true),
-            descriptor.to_string().cell(),
-        ]]
-        .table()
-        .display()
-        .map_err(|e| Error::Generic(e.to_string()))?;
-        Ok(format!("{table}"))
-    } else {
-        Ok(serde_json::to_string_pretty(
-            &json!({"descriptor": descriptor.to_string()}),
-        )?)
-    }
+    let result = DescriptorResult {
+        descriptor: Some(descriptor.to_string()),
+        multipath_descriptor: None,
+        public_descriptors: None,
+        private_descriptors: None,
+        mnemonic: None,
+    };
+    result.format(pretty)
 }
index 40c050c43cbc80aac791d2ff6d93d30d58f896be..abf3833b4922918ec3769b610c612dc7a0a513b7 100644 (file)
@@ -1,5 +1,7 @@
 use crate::commands::KeySubCommand;
 use crate::error::BDKCliError as Error;
+use crate::handlers::types::KeyResult;
+use crate::utils::output::FormatOutput;
 use bdk_wallet::bip39::{Language, Mnemonic};
 use bdk_wallet::bitcoin::bip32::KeySource;
 use bdk_wallet::bitcoin::key::Secp256k1;
@@ -8,8 +10,6 @@ use bdk_wallet::keys::bip39::WordCount;
 use bdk_wallet::keys::{DerivableKey, GeneratableKey};
 use bdk_wallet::keys::{DescriptorKey, DescriptorKey::Secret, ExtendedKey, GeneratedKey};
 use bdk_wallet::miniscript::{self, Segwitv0};
-use cli_table::{Cell, Style, Table};
-use serde_json::json;
 
 /// Handle a key sub-command
 ///
@@ -44,24 +44,15 @@ pub(crate) fn handle_key_subcommand(
                 .fold("".to_string(), |phrase, w| phrase + w + " ")
                 .trim()
                 .to_string();
-            if pretty {
-                let table = vec![
-                    vec![
-                        "Fingerprint".cell().bold(true),
-                        fingerprint.to_string().cell(),
-                    ],
-                    vec!["Mnemonic".cell().bold(true), mnemonic.to_string().cell()],
-                    vec!["Xprv".cell().bold(true), xprv.to_string().cell()],
-                ]
-                .table()
-                .display()
-                .map_err(|e| Error::Generic(e.to_string()))?;
-                Ok(format!("{table}"))
-            } else {
-                Ok(serde_json::to_string_pretty(
-                    &json!({ "mnemonic": phrase, "xprv": xprv.to_string(), "fingerprint": fingerprint.to_string() }),
-                )?)
-            }
+
+            let result = KeyResult {
+                xprv: xprv.to_string(),
+                mnemonic: Some(phrase),
+                fingerprint: Some(fingerprint.to_string()),
+                xpub: None,
+            };
+
+            result.format(pretty)
         }
         KeySubCommand::Restore { mnemonic, password } => {
             let mnemonic = Mnemonic::parse_in(Language::English, mnemonic)?;
@@ -70,24 +61,14 @@ pub(crate) fn handle_key_subcommand(
                 Error::Generic("Privatekey info not found (should not happen)".to_string())
             })?;
             let fingerprint = xprv.fingerprint(&secp);
-            if pretty {
-                let table = vec![
-                    vec![
-                        "Fingerprint".cell().bold(true),
-                        fingerprint.to_string().cell(),
-                    ],
-                    vec!["Mnemonic".cell().bold(true), mnemonic.to_string().cell()],
-                    vec!["Xprv".cell().bold(true), xprv.to_string().cell()],
-                ]
-                .table()
-                .display()
-                .map_err(|e| Error::Generic(e.to_string()))?;
-                Ok(format!("{table}"))
-            } else {
-                Ok(serde_json::to_string_pretty(
-                    &json!({ "xprv": xprv.to_string(), "fingerprint": fingerprint.to_string() }),
-                )?)
-            }
+
+            let result = KeyResult {
+                xprv: xprv.to_string(),
+                mnemonic: Some(mnemonic.to_string()),
+                fingerprint: Some(fingerprint.to_string()),
+                xpub: None,
+            };
+            result.format(pretty)
         }
         KeySubCommand::Derive { xprv, path } => {
             if xprv.network != network.into() {
@@ -102,22 +83,18 @@ pub(crate) fn handle_key_subcommand(
 
             if let Secret(desc_seckey, _, _) = derived_xprv_desc_key {
                 let desc_pubkey = desc_seckey.to_public(&secp)?;
-                if pretty {
-                    let table = vec![
-                        vec!["Xpub".cell().bold(true), desc_pubkey.to_string().cell()],
-                        vec!["Xprv".cell().bold(true), xprv.to_string().cell()],
-                    ]
-                    .table()
-                    .display()
-                    .map_err(|e| Error::Generic(e.to_string()))?;
-                    Ok(format!("{table}"))
-                } else {
-                    Ok(serde_json::to_string_pretty(
-                        &json!({"xpub": desc_pubkey.to_string(), "xprv": desc_seckey.to_string()}),
-                    )?)
-                }
+
+                let result = KeyResult {
+                    xprv: desc_seckey.to_string(),
+                    xpub: Some(desc_pubkey.to_string()),
+                    mnemonic: None,
+                    fingerprint: None,
+                };
+                result.format(pretty)
             } else {
-                Err(Error::Generic("Invalid key variant".to_string()))
+                Err(Error::Generic(
+                    "Derived key is not a secret key".to_string(),
+                ))
             }
         }
     }
index 63994139bc13bd054f1bcd376ffb5a7a40fa9e8d..8ce056b1dd480142f8dfca2e779ce9c059c084a2 100644 (file)
@@ -2,13 +2,12 @@ use crate::commands::OfflineWalletSubCommand::*;
 use crate::commands::{CliOpts, OfflineWalletSubCommand, WalletOpts};
 use crate::error::BDKCliError as Error;
 use crate::handlers::types::{
-    AddressResult, BalanceResult, PoliciesResult, PsbtResult, PublicDescriptorResult, RawPsbt,
-    TransactionDetails, TransactionListResult, UnspentDetails, UnspentListResult,
+    AddressResult, BalanceResult, KeychainPair, PsbtResult, RawPsbt, TransactionDetails,
+    TransactionListResult, UnspentDetails, UnspentListResult,
 };
 use crate::utils::output::FormatOutput;
 use bdk_wallet::bitcoin::base64::Engine;
 use bdk_wallet::bitcoin::base64::prelude::BASE64_STANDARD;
-use bdk_wallet::bitcoin::consensus::encode::serialize_hex;
 use bdk_wallet::bitcoin::script::PushBytesBuf;
 use bdk_wallet::bitcoin::{Amount, FeeRate, Psbt, Sequence, Txid};
 use bdk_wallet::{KeychainKind, SignOptions, Wallet};
@@ -150,7 +149,7 @@ pub fn handle_offline_wallet_subcommand(
 
             let psbt = tx_builder.finish()?;
 
-            let result = PsbtResult::with_details(&psbt, wallet_opts.verbose);
+            let result = PsbtResult::new(&psbt, wallet_opts.verbose, None);
             result.format(pretty)
         }
         BumpFee {
@@ -187,24 +186,24 @@ pub fn handle_offline_wallet_subcommand(
 
             let psbt = tx_builder.finish()?;
 
-            let result = PsbtResult::with_details(&psbt, wallet_opts.verbose);
+            let result = PsbtResult::new(&psbt, wallet_opts.verbose, None);
             result.format(pretty)
         }
         Policies => {
             let external_policy = wallet.policies(KeychainKind::External)?;
             let internal_policy = wallet.policies(KeychainKind::Internal)?;
-            let result = PoliciesResult {
+            let result = KeychainPair::<serde_json::Value> {
                 external: serde_json::to_value(&external_policy).unwrap_or(json!(null)),
                 internal: serde_json::to_value(&internal_policy).unwrap_or(json!(null)),
             };
-            result.format(pretty)
+            result.format(cli_opts.pretty)
         }
         PublicDescriptor => {
-            let result = PublicDescriptorResult {
+            let result = KeychainPair::<String> {
                 external: wallet.public_descriptor(KeychainKind::External).to_string(),
                 internal: wallet.public_descriptor(KeychainKind::Internal).to_string(),
             };
-            result.format(pretty)
+            result.format(cli_opts.pretty)
         }
         Sign {
             psbt,
@@ -220,7 +219,7 @@ pub fn handle_offline_wallet_subcommand(
             };
             let finalized = wallet.sign(&mut psbt, signopt)?;
 
-            let result = PsbtResult::with_status_and_details(&psbt, finalized, wallet_opts.verbose);
+            let result = PsbtResult::new(&psbt, wallet_opts.verbose, Some(finalized));
             result.format(pretty)
         }
         ExtractPsbt { psbt } => {
@@ -245,7 +244,7 @@ pub fn handle_offline_wallet_subcommand(
             };
             let finalized = wallet.finalize_psbt(&mut psbt, signopt)?;
 
-            let result = PsbtResult::with_status_and_details(&psbt, finalized, wallet_opts.verbose);
+            let result = PsbtResult::new(&psbt, wallet_opts.verbose, Some(finalized));
             result.format(pretty)
         }
         CombinePsbt { psbt } => {
@@ -267,7 +266,7 @@ pub fn handle_offline_wallet_subcommand(
                     Ok(acc)
                 },
             )?;
-            let result = PsbtResult::new(&final_psbt);
+            let result = PsbtResult::new(&final_psbt, wallet_opts.verbose, None);
             result.format(pretty)
         }
     }
index 17c25c780f73509a1b499b5cd808bee502d92327..9f2b32175300ae9a47bdc7929c4bf0cdbceb5d5f 100644 (file)
@@ -1,6 +1,6 @@
-use crate::config::WalletConfig;
+use crate::utils::output::FormatOutput;
+use crate::{config::WalletConfig, handlers::types::WalletsListResult};
 use crate::error::BDKCliError as Error;
-use cli_table::{Cell, CellStruct, Style, Table};
 use std::path::Path;
 
 /// Handle the top-level `wallets` command (lists all saved wallets)
@@ -10,28 +10,6 @@ pub fn handle_wallets_subcommand(home_dir: &Path, pretty: bool) -> Result<String
         None => return Ok("No wallets configured yet.".to_string()),
     };
 
-    if pretty {
-        let mut rows: Vec<Vec<CellStruct>> = vec![];
-        for (name, inner) in &config.wallets {
-            rows.push(vec![
-                name.cell(),
-                inner.network.clone().cell(),
-                inner.ext_descriptor[..30].to_string().cell(),
-            ]);
-        }
-
-        let table = rows
-            .table()
-            .title(vec![
-                "Wallet Name".cell().bold(true),
-                "Network".cell().bold(true),
-                "External Descriptor (truncated)".cell().bold(true),
-            ])
-            .display()
-            .map_err(|e| Error::Generic(e.to_string()))?;
-
-        Ok(format!("{table}"))
-    } else {
-        Ok(serde_json::to_string_pretty(&config.wallets)?)
-    }
+    let result = WalletsListResult(config.wallets);
+    result.format(pretty)
 }