1- use crate :: utils:: output:: FormatOutput ;
1+ use std:: collections:: HashMap ;
2+
3+ use crate :: config:: WalletConfigInner ;
4+ use crate :: utils:: output:: { FormatOutput , simple_table} ;
25use crate :: { error:: BDKCliError as Error , utils:: shorten} ;
3- use bdk_wallet:: bitcoin:: base64:: Engine ;
4- use bdk_wallet:: bitcoin:: base64:: prelude:: BASE64_STANDARD ;
5- use bdk_wallet:: bitcoin:: consensus:: encode:: serialize_hex;
6- use bdk_wallet:: bitcoin:: { Address , Network , Psbt , Transaction } ;
7- use bdk_wallet:: chain:: ChainPosition ;
8- use bdk_wallet:: { AddressInfo , Balance , LocalOutput } ;
6+ use bdk_wallet:: bitcoin:: {
7+ Address , Network , Psbt , Transaction , base64:: Engine , consensus:: encode:: serialize_hex,
8+ } ;
9+ use bdk_wallet:: { AddressInfo , Balance , LocalOutput , chain:: ChainPosition } ;
910use cli_table:: { Cell , CellStruct , Style , Table , format:: Justify } ;
1011use serde:: Serialize ;
1112use serde_json:: json;
@@ -29,15 +30,16 @@ impl From<AddressInfo> for AddressResult {
2930/// pretty presentation for address
3031impl FormatOutput for AddressResult {
3132 fn to_table ( & self ) -> Result < String , Error > {
32- let table = vec ! [
33- vec![ "Address" . cell( ) . bold( true ) , self . address. clone( ) . cell( ) ] ,
34- vec![ "Index" . cell( ) . bold( true ) , self . index. cell( ) ] ,
35- ]
36- . table ( )
37- . display ( )
38- . map_err ( |e| Error :: Generic ( e. to_string ( ) ) ) ?;
39-
40- Ok ( format ! ( "{table}" ) )
33+ simple_table (
34+ vec ! [
35+ vec![ "Address" . cell( ) . bold( true ) , self . address. clone( ) . cell( ) ] ,
36+ vec![
37+ "Index" . cell( ) . bold( true ) ,
38+ self . index. cell( ) . justify( Justify :: Right ) ,
39+ ] ,
40+ ] ,
41+ None ,
42+ )
4143 }
4244}
4345
@@ -122,37 +124,34 @@ impl From<Balance> for BalanceResult {
122124
123125impl FormatOutput for BalanceResult {
124126 fn to_table ( & self ) -> Result < String , Error > {
125- let table = vec ! [
126- vec![
127- "Total" . cell( ) . bold( true ) ,
128- self . total. cell( ) . justify( Justify :: Right ) ,
129- ] ,
130- vec![
131- "Confirmed" . cell( ) . bold( true ) ,
132- self . confirmed. cell( ) . justify( Justify :: Right ) ,
133- ] ,
134- vec![
135- "Trusted Pending" . cell( ) . bold( true ) ,
136- self . trusted_pending. cell( ) . justify( Justify :: Right ) ,
137- ] ,
138- vec![
139- "Untrusted Pending" . cell( ) . bold( true ) ,
140- self . untrusted_pending. cell( ) . justify( Justify :: Right ) ,
141- ] ,
127+ simple_table (
142128 vec ! [
143- "Immature" . cell( ) . bold( true ) ,
144- self . immature. cell( ) . justify( Justify :: Right ) ,
129+ vec![
130+ "Total" . cell( ) . bold( true ) ,
131+ self . total. cell( ) . justify( Justify :: Right ) ,
132+ ] ,
133+ vec![
134+ "Confirmed" . cell( ) . bold( true ) ,
135+ self . confirmed. cell( ) . justify( Justify :: Right ) ,
136+ ] ,
137+ vec![
138+ "Trusted Pending" . cell( ) . bold( true ) ,
139+ self . trusted_pending. cell( ) . justify( Justify :: Right ) ,
140+ ] ,
141+ vec![
142+ "Untrusted Pending" . cell( ) . bold( true ) ,
143+ self . untrusted_pending. cell( ) . justify( Justify :: Right ) ,
144+ ] ,
145+ vec![
146+ "Immature" . cell( ) . bold( true ) ,
147+ self . immature. cell( ) . justify( Justify :: Right ) ,
148+ ] ,
145149 ] ,
146- ]
147- . table ( )
148- . title ( vec ! [
149- "Status" . cell( ) . bold( true ) ,
150- "Amount (sat)" . cell( ) . bold( true ) ,
151- ] )
152- . display ( )
153- . map_err ( |e| Error :: Generic ( e. to_string ( ) ) ) ?;
154-
155- Ok ( format ! ( "{table}" ) )
150+ Some ( vec ! [
151+ "Status" . cell( ) . bold( true ) ,
152+ "Amount (sat)" . cell( ) . bold( true ) ,
153+ ] ) ,
154+ )
156155 }
157156}
158157
@@ -272,32 +271,12 @@ pub struct PsbtResult {
272271}
273272
274273impl PsbtResult {
275- pub fn new ( psbt : & Psbt ) -> Self {
276- Self {
277- psbt : BASE64_STANDARD . encode ( psbt. serialize ( ) ) ,
278- is_finalized : None ,
279- details : None ,
280- }
281- }
282-
283- pub fn with_details ( psbt : & Psbt , verbose : bool ) -> Self {
284- Self {
285- psbt : BASE64_STANDARD . encode ( psbt. serialize ( ) ) ,
286- is_finalized : None ,
287- details : if verbose {
288- Some ( serde_json:: to_value ( psbt) . unwrap_or ( json ! ( { } ) ) )
289- } else {
290- None
291- } ,
292- }
293- }
294-
295- pub fn with_status_and_details ( psbt : & Psbt , is_finalized : bool , verbose : bool ) -> Self {
274+ pub fn new ( psbt : & Psbt , verbose : bool , finalized : Option < bool > ) -> Self {
296275 Self {
297- psbt : BASE64_STANDARD . encode ( psbt. serialize ( ) ) ,
298- is_finalized : Some ( is_finalized ) ,
276+ psbt : bdk_wallet :: bitcoin :: base64 :: prelude :: BASE64_STANDARD . encode ( psbt. serialize ( ) ) ,
277+ is_finalized : finalized ,
299278 details : if verbose {
300- Some ( serde_json:: to_value ( psbt) . unwrap_or ( json ! ( { } ) ) )
279+ Some ( serde_json:: to_value ( psbt) . unwrap_or_default ( ) )
301280 } else {
302281 None
303282 } ,
@@ -331,24 +310,25 @@ impl FormatOutput for PsbtResult {
331310 }
332311}
333312
334- /// Policies representation
335313#[ derive( Serialize ) ]
336- pub struct PoliciesResult {
337- pub external : serde_json:: Value ,
338- pub internal : serde_json:: Value ,
314+ pub struct RawPsbt {
315+ pub raw_tx : String ,
339316}
340317
341- impl FormatOutput for PoliciesResult {
342- fn to_table ( & self ) -> Result < String , Error > {
343- let ext_str = serde_json:: to_string_pretty ( & self . external )
344- . map_err ( |e| Error :: Generic ( e. to_string ( ) ) ) ?;
345- let int_str = serde_json:: to_string_pretty ( & self . internal )
346- . map_err ( |e| Error :: Generic ( e. to_string ( ) ) ) ?;
318+ impl RawPsbt {
319+ pub fn new ( tx : & Transaction ) -> Self {
320+ Self {
321+ raw_tx : serialize_hex ( tx) ,
322+ }
323+ }
324+ }
347325
348- let table = vec ! [
349- vec![ "External" . cell( ) . bold( true ) , ext_str. cell( ) ] ,
350- vec![ "Internal" . cell( ) . bold( true ) , int_str. cell( ) ] ,
351- ]
326+ impl FormatOutput for RawPsbt {
327+ fn to_table ( & self ) -> Result < String , Error > {
328+ let table = vec ! [ vec![
329+ "Raw Transaction" . cell( ) . bold( true ) ,
330+ self . raw_tx. clone( ) . cell( ) ,
331+ ] ]
352332 . table ( )
353333 . display ( )
354334 . map_err ( |e| Error :: Generic ( e. to_string ( ) ) ) ?;
@@ -358,54 +338,109 @@ impl FormatOutput for PoliciesResult {
358338}
359339
360340#[ derive( Serialize ) ]
361- pub struct PublicDescriptorResult {
362- pub external : String ,
363- pub internal : String ,
341+ pub struct KeychainPair < T > {
342+ pub external : T ,
343+ pub internal : T ,
364344}
365345
366- impl FormatOutput for PublicDescriptorResult {
346+ // Table formatting for string pairs (used by PublicDescriptor)
347+ impl FormatOutput for KeychainPair < String > {
367348 fn to_table ( & self ) -> Result < String , Error > {
368- let table = vec ! [
369- vec![
370- "External Descriptor" . cell( ) . bold( true ) ,
371- self . external. clone( ) . cell( ) ,
372- ] ,
373- vec![
374- "Internal Descriptor" . cell( ) . bold( true ) ,
375- self . internal. clone( ) . cell( ) ,
376- ] ,
377- ]
378- . table ( )
379- . display ( )
380- . map_err ( |e| Error :: Generic ( e. to_string ( ) ) ) ?;
381-
382- Ok ( format ! ( "{table}" ) )
349+ let rows = vec ! [
350+ vec![ "External" . cell( ) . bold( true ) , self . external. clone( ) . cell( ) ] ,
351+ vec![ "Internal" . cell( ) . bold( true ) , self . internal. clone( ) . cell( ) ] ,
352+ ] ;
353+ simple_table ( rows, None )
383354 }
384355}
385356
357+ // Table formatting for JSON value pairs (used by Policies)
358+ impl FormatOutput for KeychainPair < serde_json:: Value > {
359+ fn to_table ( & self ) -> Result < String , Error > {
360+ let ext_str = serde_json:: to_string_pretty ( & self . external )
361+ . map_err ( |e| Error :: Generic ( e. to_string ( ) ) ) ?;
362+ let int_str = serde_json:: to_string_pretty ( & self . internal )
363+ . map_err ( |e| Error :: Generic ( e. to_string ( ) ) ) ?;
364+
365+ let rows = vec ! [
366+ vec![ "External" . cell( ) . bold( true ) , ext_str. cell( ) ] ,
367+ vec![ "Internal" . cell( ) . bold( true ) , int_str. cell( ) ] ,
368+ ] ;
369+ simple_table ( rows, None )
370+ }
371+ }
386372#[ derive( Serialize ) ]
387- pub struct RawPsbt {
388- pub raw_tx : String ,
373+ pub struct KeyResult {
374+ pub xprv : String ,
375+
376+ #[ serde( skip_serializing_if = "Option::is_none" ) ]
377+ pub xpub : Option < String > ,
378+
379+ #[ serde( skip_serializing_if = "Option::is_none" ) ]
380+ pub mnemonic : Option < String > ,
381+
382+ #[ serde( skip_serializing_if = "Option::is_none" ) ]
383+ pub fingerprint : Option < String > ,
389384}
390385
391- impl RawPsbt {
392- pub fn new ( tx : & Transaction ) -> Self {
393- Self {
394- raw_tx : serialize_hex ( tx) ,
386+ impl FormatOutput for KeyResult {
387+ fn to_table ( & self ) -> Result < String , Error > {
388+ let mut rows: Vec < Vec < CellStruct > > = vec ! [ ] ;
389+
390+ if let Some ( mnemonic) = & self . mnemonic {
391+ rows. push ( vec ! [ "Mnemonic" . cell( ) . bold( true ) , mnemonic. clone( ) . cell( ) ] ) ;
395392 }
393+ if let Some ( xpub) = & self . xpub {
394+ rows. push ( vec ! [ "Xpub" . cell( ) . bold( true ) , xpub. clone( ) . cell( ) ] ) ;
395+ }
396+
397+ rows. push ( vec ! [ "Xprv" . cell( ) . bold( true ) , self . xprv. clone( ) . cell( ) ] ) ;
398+
399+ if let Some ( fingerprint) = & self . fingerprint {
400+ rows. push ( vec ! [
401+ "Fingerprint" . cell( ) . bold( true ) ,
402+ fingerprint. clone( ) . cell( ) ,
403+ ] ) ;
404+ }
405+
406+ simple_table ( rows, None )
396407 }
397408}
398409
399- impl FormatOutput for RawPsbt {
410+
411+ #[ derive( Serialize ) ]
412+ #[ serde( transparent) ]
413+ pub struct WalletsListResult ( pub HashMap < String , WalletConfigInner > ) ;
414+
415+ impl FormatOutput for WalletsListResult {
400416 fn to_table ( & self ) -> Result < String , Error > {
401- let table = vec ! [ vec![
402- "Raw Transaction" . cell( ) . bold( true ) ,
403- self . raw_tx. clone( ) . cell( ) ,
404- ] ]
405- . table ( )
406- . display ( )
407- . map_err ( |e| Error :: Generic ( e. to_string ( ) ) ) ?;
417+ if self . 0 . is_empty ( ) {
418+ return Ok ( "No wallets configured yet." . to_string ( ) ) ;
419+ }
408420
409- Ok ( format ! ( "{table}" ) )
421+ let mut rows: Vec < Vec < CellStruct > > = vec ! [ ] ;
422+ for ( name, inner) in & self . 0 {
423+ let desc: String = inner. ext_descriptor . chars ( ) . take ( 30 ) . collect ( ) ;
424+ let desc_display = if inner. ext_descriptor . len ( ) > 30 {
425+ format ! ( "{}..." , desc)
426+ } else {
427+ desc
428+ } ;
429+
430+ rows. push ( vec ! [
431+ name. clone( ) . cell( ) ,
432+ inner. network. clone( ) . cell( ) ,
433+ desc_display. cell( ) ,
434+ ] ) ;
435+ }
436+
437+ simple_table (
438+ rows,
439+ Some ( vec ! [
440+ "Wallet Name" . cell( ) . bold( true ) ,
441+ "Network" . cell( ) . bold( true ) ,
442+ "External Descriptor" . cell( ) . bold( true ) ,
443+ ] ) ,
444+ )
410445 }
411446}
0 commit comments