Skip to content

Commit 30fa3a0

Browse files
committed
feat(wallet-init): add list command
1 parent 7e4d0e0 commit 30fa3a0

File tree

6 files changed

+167
-189
lines changed

6 files changed

+167
-189
lines changed

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ Changelog info is also documented on the [GitHub releases](https://github.com/bi
44
page. See [DEVELOPMENT_CYCLE.md](DEVELOPMENT_CYCLE.md) for more details.
55

66
## [Unreleased]
7-
- Add wallet configs initialization for initialiazing and saving wallet configs
87
- Add wallet subcommand `config` to save wallet configs
8+
- Add wallet subcommand `list` to display saved configs
99

1010
## [2.0.0]
1111

src/commands.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -108,9 +108,6 @@ pub enum CliSubCommand {
108108
/// Wallet name for this REPL session
109109
#[arg(env = "WALLET_NAME", short = 'w', long = "wallet", required = true)]
110110
wallet: String,
111-
112-
#[command(flatten)]
113-
wallet_opts: WalletOpts,
114111
},
115112
}
116113

@@ -136,6 +133,8 @@ pub enum WalletSubCommand {
136133
OnlineWalletSubCommand(OnlineWalletSubCommand),
137134
#[command(flatten)]
138135
OfflineWalletSubCommand(OfflineWalletSubCommand),
136+
/// List all saved wallet configurations.
137+
List,
139138
}
140139

141140
#[derive(Clone, ValueEnum, Debug, Eq, PartialEq)]

src/config.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,6 @@ impl WalletConfig {
105105
return Err(Error::Generic("Invalid database type".to_string()));
106106
}
107107
};
108-
109108
#[cfg(any(
110109
feature = "electrum",
111110
feature = "esplora",
@@ -144,9 +143,9 @@ impl WalletConfig {
144143
.clone()
145144
.ok_or_else(|| Error::Generic(format!("Server url not found")))?,
146145
#[cfg(feature = "electrum")]
147-
batch_size: 10,
146+
batch_size: wallet_config.batch_size.unwrap_or(10),
148147
#[cfg(feature = "esplora")]
149-
parallel_requests: 5,
148+
parallel_requests: wallet_config.parallel_requests.unwrap_or(5),
150149
#[cfg(feature = "rpc")]
151150
basic_auth: (
152151
wallet_config

src/handlers.rs

Lines changed: 152 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -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.
11641297
pub(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

Comments
 (0)