@@ -1160,6 +1160,139 @@ pub(crate) fn handle_compile_subcommand(
11601160 }
11611161}
11621162
1163+ /// Handle list subcommand to show all saved wallet configurations
1164+ pub fn handle_list_subcommand ( datadir : & Path , pretty : bool ) -> Result < String , Error > {
1165+ let load_config = WalletConfig :: load ( datadir) ?;
1166+
1167+ let config = match load_config {
1168+ Some ( c) if !c. wallets . is_empty ( ) => c,
1169+ _ => {
1170+ return Ok ( if pretty {
1171+ "No wallet configurations found." . to_string ( )
1172+ } else {
1173+ serde_json:: to_string_pretty ( & json ! ( {
1174+ "wallets" : [ ]
1175+ } ) ) ?
1176+ } ) ;
1177+ }
1178+ } ;
1179+
1180+ if pretty {
1181+ let mut rows: Vec < Vec < CellStruct > > = vec ! [ ] ;
1182+
1183+ for ( name, wallet_config) in config. wallets . iter ( ) {
1184+ let mut row = vec ! [ name. cell( ) , wallet_config. network. clone( ) . cell( ) ] ;
1185+
1186+ #[ cfg( any( feature = "sqlite" , feature = "redb" ) ) ]
1187+ row. push ( wallet_config. database_type . clone ( ) . cell ( ) ) ;
1188+
1189+ #[ cfg( any(
1190+ feature = "electrum" ,
1191+ feature = "esplora" ,
1192+ feature = "rpc" ,
1193+ feature = "cbf"
1194+ ) ) ]
1195+ {
1196+ let client_str = wallet_config. client_type . as_deref ( ) . unwrap_or ( "N/A" ) ;
1197+ row. push ( client_str. cell ( ) ) ;
1198+ }
1199+
1200+ #[ cfg( any( feature = "electrum" , feature = "esplora" , feature = "rpc" ) ) ]
1201+ {
1202+ let url_str = wallet_config. server_url . as_deref ( ) . unwrap_or ( "N/A" ) ;
1203+ let display_url = if url_str. len ( ) > 20 {
1204+ shorten ( url_str, 15 , 10 )
1205+ } else {
1206+ url_str. to_string ( )
1207+ } ;
1208+ row. push ( display_url. cell ( ) ) ;
1209+ }
1210+
1211+ let ext_desc_display = if wallet_config. ext_descriptor . len ( ) > 40 {
1212+ shorten ( & wallet_config. ext_descriptor , 20 , 15 )
1213+ } else {
1214+ wallet_config. ext_descriptor . clone ( )
1215+ } ;
1216+ row. push ( ext_desc_display. cell ( ) ) ;
1217+
1218+ let has_int_desc = if wallet_config. int_descriptor . is_some ( ) {
1219+ "Yes"
1220+ } else {
1221+ "No"
1222+ } ;
1223+ row. push ( has_int_desc. cell ( ) ) ;
1224+
1225+ rows. push ( row) ;
1226+ }
1227+
1228+ let mut title_cells = vec ! [ "Wallet Name" . cell( ) . bold( true ) , "Network" . cell( ) . bold( true ) ] ;
1229+
1230+ #[ cfg( any( feature = "sqlite" , feature = "redb" ) ) ]
1231+ title_cells. push ( "Database" . cell ( ) . bold ( true ) ) ;
1232+
1233+ #[ cfg( any(
1234+ feature = "electrum" ,
1235+ feature = "esplora" ,
1236+ feature = "rpc" ,
1237+ feature = "cbf"
1238+ ) ) ]
1239+ title_cells. push ( "Client" . cell ( ) . bold ( true ) ) ;
1240+
1241+ #[ cfg( any( feature = "electrum" , feature = "esplora" , feature = "rpc" ) ) ]
1242+ title_cells. push ( "Server URL" . cell ( ) . bold ( true ) ) ;
1243+
1244+ title_cells. push ( "External Desc" . cell ( ) . bold ( true ) ) ;
1245+ title_cells. push ( "Internal Desc" . cell ( ) . bold ( true ) ) ;
1246+
1247+ let table = rows
1248+ . table ( )
1249+ . title ( title_cells)
1250+ . display ( )
1251+ . map_err ( |e| Error :: Generic ( e. to_string ( ) ) ) ?;
1252+
1253+ Ok ( format ! ( "{table}" ) )
1254+ } else {
1255+ let wallets_summary: Vec < _ > = config
1256+ . wallets
1257+ . iter ( )
1258+ . map ( |( name, wallet_config) | {
1259+ let mut wallet_json = json ! ( {
1260+ "name" : name,
1261+ "network" : wallet_config. network,
1262+ "ext_descriptor" : wallet_config. ext_descriptor,
1263+ "int_descriptor" : wallet_config. int_descriptor,
1264+ } ) ;
1265+
1266+ #[ cfg( any( feature = "sqlite" , feature = "redb" ) ) ]
1267+ {
1268+ wallet_json[ "database_type" ] = json ! ( wallet_config. database_type. clone( ) ) ;
1269+ }
1270+
1271+ #[ cfg( any(
1272+ feature = "electrum" ,
1273+ feature = "esplora" ,
1274+ feature = "rpc" ,
1275+ feature = "cbf"
1276+ ) ) ]
1277+ {
1278+ wallet_json[ "client_type" ] = json ! ( wallet_config. client_type. clone( ) ) ;
1279+ }
1280+
1281+ #[ cfg( any( feature = "electrum" , feature = "esplora" , feature = "rpc" ) ) ]
1282+ {
1283+ wallet_json[ "server_url" ] = json ! ( wallet_config. server_url. clone( ) ) ;
1284+ }
1285+
1286+ wallet_json
1287+ } )
1288+ . collect ( ) ;
1289+
1290+ Ok ( serde_json:: to_string_pretty ( & json ! ( {
1291+ "wallets" : wallets_summary
1292+ } ) ) ?)
1293+ }
1294+ }
1295+
11631296/// The global top level handler.
11641297pub ( crate ) async fn handle_command ( cli_opts : CliOpts ) -> Result < String , Error > {
11651298 let network = cli_opts. network ;
@@ -1298,6 +1431,14 @@ pub(crate) async fn handle_command(cli_opts: CliOpts) -> Result<String, Error> {
12981431 let result = handle_config_subcommand ( & home_dir, network, wallet, & wallet_opts, force) ?;
12991432 Ok ( result)
13001433 }
1434+ CliSubCommand :: Wallet {
1435+ wallet : _,
1436+ subcommand : WalletSubCommand :: List ,
1437+ } => {
1438+ let home_dir = prepare_home_dir ( cli_opts. datadir ) ?;
1439+ let result = handle_list_subcommand ( & home_dir, pretty) ?;
1440+ Ok ( result)
1441+ }
13011442 CliSubCommand :: Key {
13021443 subcommand : key_subcommand,
13031444 } => {
@@ -1315,21 +1456,19 @@ pub(crate) async fn handle_command(cli_opts: CliOpts) -> Result<String, Error> {
13151456 #[ cfg( feature = "repl" ) ]
13161457 CliSubCommand :: Repl {
13171458 wallet : wallet_name,
1318- mut wallet_opts,
13191459 } => {
13201460 let network = cli_opts. network ;
13211461 let home_dir = prepare_home_dir ( cli_opts. datadir . clone ( ) ) ?;
1322- wallet_opts. wallet = Some ( wallet_name. clone ( ) ) ;
13231462
13241463 let config = WalletConfig :: load ( & home_dir) ?. ok_or ( Error :: Generic ( format ! (
1325- "No config found for wallet {}" ,
1464+ "No config found for wallet {}, please run 'config' command first. " ,
13261465 wallet_name. clone( )
13271466 ) ) ) ?;
1328- let loaded_wallet_opts = config. get_wallet_opts ( & wallet_name) ?;
1467+ let wallet_opts = config. get_wallet_opts ( & wallet_name) ?;
13291468
13301469 #[ cfg( any( feature = "sqlite" , feature = "redb" ) ) ]
13311470 let ( mut wallet, mut persister) = {
1332- let mut persister: Persister = match & loaded_wallet_opts . database_type {
1471+ let mut persister: Persister = match & wallet_opts . database_type {
13331472 #[ cfg( feature = "sqlite" ) ]
13341473 DatabaseType :: Sqlite => {
13351474 let database_path = prepare_wallet_db_dir ( & home_dir, & wallet_name) ?;
@@ -1348,7 +1487,7 @@ pub(crate) async fn handle_command(cli_opts: CliOpts) -> Result<String, Error> {
13481487 Persister :: RedbStore ( store)
13491488 }
13501489 } ;
1351- let wallet = new_persisted_wallet ( network, & mut persister, & loaded_wallet_opts ) ?;
1490+ let wallet = new_persisted_wallet ( network, & mut persister, & wallet_opts ) ?;
13521491 ( wallet, persister)
13531492 } ;
13541493 #[ cfg( not( any( feature = "sqlite" , feature = "redb" ) ) ) ]
@@ -1448,6 +1587,13 @@ async fn respond(
14481587 . map_err ( |e| e. to_string ( ) ) ?;
14491588 Some ( value)
14501589 }
1590+ ReplSubCommand :: Wallet {
1591+ subcommand : WalletSubCommand :: List ,
1592+ } => {
1593+ let value =
1594+ handle_list_subcommand ( & _datadir, cli_opts. pretty ) . map_err ( |e| e. to_string ( ) ) ?;
1595+ Some ( value)
1596+ }
14511597 ReplSubCommand :: Key { subcommand } => {
14521598 let value = handle_key_subcommand ( network, subcommand, cli_opts. pretty )
14531599 . map_err ( |e| e. to_string ( ) ) ?;
0 commit comments