diff --git a/client/src/bin/space-cli.rs b/client/src/bin/space-cli.rs index c49a22e..5322df5 100644 --- a/client/src/bin/space-cli.rs +++ b/client/src/bin/space-cli.rs @@ -25,7 +25,8 @@ use spaces_client::{ format::{ print_error_rpc_response, print_list_bidouts, print_list_spaces_response, print_list_transactions, print_list_unspent, print_server_info, - print_wallet_balance_response, print_wallet_info, print_wallet_response, Format, + print_list_wallets, print_wallet_balance_response, print_wallet_info, print_wallet_response, + Format, }, rpc::{ BidParams, ExecuteParams, OpenParams, RegisterParams, RpcClient, RpcWalletRequest, @@ -71,6 +72,9 @@ pub struct Args { #[derive(Subcommand, Debug, Clone)] enum Commands { + /// List existing wallets + #[command(name = "listwallets")] + ListWallets, /// Generate a new wallet #[command(name = "createwallet")] CreateWallet, @@ -573,6 +577,10 @@ async fn handle_commands(cli: &SpaceCli, command: Commands) -> Result<(), Client let response = cli.client.get_spaceout(outpoint).await?; println!("{}", serde_json::to_string_pretty(&response)?); } + Commands::ListWallets => { + let result = cli.client.list_wallets().await?; + print_list_wallets(result, cli.format); + } Commands::CreateWallet => { cli.client.wallet_create(&cli.wallet).await?; } diff --git a/client/src/format.rs b/client/src/format.rs index 1ddaa5c..e936bd7 100644 --- a/client/src/format.rs +++ b/client/src/format.rs @@ -149,6 +149,17 @@ pub fn print_list_unspent(utxos: Vec, format: Format) { } } +pub fn print_list_wallets(wallets: Vec, format: Format) { + match format { + Format::Text => { + println!("{}", wallets.join("\n")); + } + Format::Json => { + println!("{}", serde_json::to_string_pretty(&wallets).unwrap()); + } + } +} + pub fn print_server_info(info: ServerInfo, format: Format) { match format { Format::Text => { diff --git a/client/src/rpc.rs b/client/src/rpc.rs index dcfc133..baa8826 100644 --- a/client/src/rpc.rs +++ b/client/src/rpc.rs @@ -74,8 +74,8 @@ pub struct ServerInfo { #[derive(Debug, Clone, Serialize, Deserialize)] pub struct ChainInfo { - blocks: u32, - headers: u32, + pub blocks: u32, + pub headers: u32, } #[derive(Debug, Clone, Serialize, Deserialize)] @@ -207,6 +207,9 @@ pub trait Rpc { #[method(name = "gettxmeta")] async fn get_tx_meta(&self, txid: Txid) -> Result, ErrorObjectOwned>; + #[method(name = "listwallets")] + async fn list_wallets(&self) -> Result, ErrorObjectOwned>; + #[method(name = "walletload")] async fn wallet_load(&self, name: &str) -> Result<(), ErrorObjectOwned>; @@ -583,6 +586,21 @@ impl WalletManager { (network, genesis_hash) } + pub async fn list_wallets(&self) -> anyhow::Result> { + let wallets = std::fs::read_dir(&self.data_dir)? + .filter_map(Result::ok) + .filter(|entry| entry.path().is_dir()) + .filter_map(|entry| { + entry.path() + .file_name() + .and_then(|name| name.to_str()) + .map(String::from) + }) + .collect(); + + Ok(wallets) + } + pub async fn load_wallet(&self, name: &str) -> anyhow::Result<()> { if self.wallets.read().await.contains_key(name) { return Ok(()); @@ -828,6 +846,15 @@ impl RpcServer for RpcServerImpl { Ok(data) } + async fn list_wallets(&self) -> Result, ErrorObjectOwned> { + self.wallet_manager + .list_wallets() + .await + .map_err(|error| { + ErrorObjectOwned::owned(-1, error.to_string(), None::) + }) + } + async fn wallet_load(&self, name: &str) -> Result<(), ErrorObjectOwned> { self.wallet_manager .load_wallet(name) @@ -1597,4 +1624,4 @@ async fn get_server_info(client: &reqwest::Client, rpc: &BitcoinRpc, tip: ChainA 0.0 }, }) -} \ No newline at end of file +}