From 6db69e01de611d86d45ac3e7103333f7c93d7805 Mon Sep 17 00:00:00 2001 From: Eshan Vaid Date: Sun, 11 Jun 2023 01:52:13 +0530 Subject: [PATCH 1/6] refactor: add types to library crate --- src/lib.rs | 2 ++ src/main.rs | 8 ++------ src/types.rs | 5 +++++ 3 files changed, 9 insertions(+), 6 deletions(-) create mode 100644 src/types.rs diff --git a/src/lib.rs b/src/lib.rs index 610f485..1b404bf 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -4,3 +4,5 @@ mod client; pub use client::*; + +pub mod types; diff --git a/src/main.rs b/src/main.rs index 1e1b49d..c6b1d0c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -15,6 +15,8 @@ use std::fs::{self}; mod constants; mod token; +use galoy_cli::types::*; + #[derive(Parser)] #[clap(author, version, about, long_about = None)] struct Cli { @@ -82,12 +84,6 @@ enum Commands { Batch { filename: String, price: Decimal }, } -#[derive(Debug, Clone, clap::ValueEnum, PartialEq, Eq)] -enum Wallet { - Btc, - Usd, -} - fn main() -> anyhow::Result<()> { log::set_max_level(LevelFilter::Warn); diff --git a/src/types.rs b/src/types.rs new file mode 100644 index 0000000..7ecec72 --- /dev/null +++ b/src/types.rs @@ -0,0 +1,5 @@ +#[derive(Debug, Clone, clap::ValueEnum, PartialEq, Eq)] +pub enum Wallet { + Btc, + Usd, +} From c4a575de2e758cc16dc70415aa11fdb922892332 Mon Sep 17 00:00:00 2001 From: Eshan Vaid Date: Sun, 11 Jun 2023 02:15:32 +0530 Subject: [PATCH 2/6] feat(balance): add balance command --- src/client/mod.rs | 53 +++++++++++++++++++++++++++++++++++++++++++++++ src/main.rs | 19 +++++++++++++++++ 2 files changed, 72 insertions(+) diff --git a/src/client/mod.rs b/src/client/mod.rs index 51f5297..b0c3d1a 100644 --- a/src/client/mod.rs +++ b/src/client/mod.rs @@ -17,6 +17,8 @@ pub use batch::Batch; use self::query_me::WalletCurrency; +use crate::types::Wallet; + pub mod server; pub struct GaloyClient { @@ -97,6 +99,57 @@ impl GaloyClient { Ok(me) } + pub fn fetch_balance(&self, wallet: Option) -> anyhow::Result { + let me = self.me()?; + + let default_wallet_id = me.default_account.default_wallet_id; + + let wallets = &me.default_account.wallets; + let mut wallet_balances = String::new(); + + for wallet_info in wallets { + match &wallet { + Some(Wallet::Usd) if wallet_info.wallet_currency == WalletCurrency::USD => { + return Ok(format!("USD wallet: {} cents", wallet_info.balance)); + } + Some(Wallet::Btc) if wallet_info.wallet_currency == WalletCurrency::BTC => { + return Ok(format!("BTC wallet: {} sats", wallet_info.balance)); + } + None => { + if wallet_info.wallet_currency == WalletCurrency::USD { + wallet_balances += &format!( + "USD wallet{}: {} cents\n", + if wallet_info.id == default_wallet_id { + " (default)" + } else { + "" + }, + wallet_info.balance + ); + } + if wallet_info.wallet_currency == WalletCurrency::BTC { + wallet_balances += &format!( + "BTC wallet{}: {} sats\n", + if wallet_info.id == default_wallet_id { + " (default)" + } else { + "" + }, + wallet_info.balance + ); + } + } + _ => {} + } + } + + if wallet_balances.is_empty() { + Err(anyhow::anyhow!("No matching wallet found")) + } else { + Ok(wallet_balances) + } + } + pub fn request_phone_code(&self, phone: String, nocaptcha: bool) -> std::io::Result<()> { match nocaptcha { false => { diff --git a/src/main.rs b/src/main.rs index c6b1d0c..0a103ae 100644 --- a/src/main.rs +++ b/src/main.rs @@ -67,6 +67,13 @@ enum Commands { }, /// Execute Me query Me, + /// Fetch the balance of a wallet + Balance { + #[clap(long)] + btc: bool, + #[clap(long)] + usd: bool, + }, /// Execute a Payment Pay { #[clap(short, long)] @@ -124,6 +131,18 @@ fn main() -> anyhow::Result<()> { serde_json::to_string_pretty(&result).expect("Can't serialize json") ); } + Commands::Balance { btc, usd } => { + let wallet_type = match (btc, usd) { + (true, true) | (false, false) => None, + (true, false) => Some(Wallet::Btc), + (false, true) => Some(Wallet::Usd), + }; + + let balance = galoy_cli + .fetch_balance(wallet_type) + .context("can't fetch balance")?; + println!("{}", balance); + } Commands::Pay { username, wallet, From 4a65bd3f0ae2fc4c7f87850be882f835bfe012a4 Mon Sep 17 00:00:00 2001 From: Eshan Vaid Date: Mon, 12 Jun 2023 00:27:44 +0530 Subject: [PATCH 3/6] feat: allow input of wallet-ids --- src/client/mod.rs | 73 +++++++++++++++++++++++-------------------- src/client/queries.rs | 2 +- src/lib.rs | 1 + src/main.rs | 10 ++++-- src/utils.rs | 9 ++++++ 5 files changed, 58 insertions(+), 37 deletions(-) create mode 100644 src/utils.rs diff --git a/src/client/mod.rs b/src/client/mod.rs index b0c3d1a..89e5225 100644 --- a/src/client/mod.rs +++ b/src/client/mod.rs @@ -17,7 +17,8 @@ pub use batch::Batch; use self::query_me::WalletCurrency; -use crate::types::Wallet; +use crate::types::*; +use crate::utils::*; pub mod server; @@ -99,54 +100,58 @@ impl GaloyClient { Ok(me) } - pub fn fetch_balance(&self, wallet: Option) -> anyhow::Result { + pub fn fetch_balance( + &self, + wallet: Option, + wallet_ids: Vec, + ) -> anyhow::Result { let me = self.me()?; let default_wallet_id = me.default_account.default_wallet_id; - let wallets = &me.default_account.wallets; + + let wallet_ids_set: std::collections::HashSet<_> = wallet_ids.iter().collect(); + let mut wallet_balances = String::new(); for wallet_info in wallets { - match &wallet { - Some(Wallet::Usd) if wallet_info.wallet_currency == WalletCurrency::USD => { - return Ok(format!("USD wallet: {} cents", wallet_info.balance)); - } - Some(Wallet::Btc) if wallet_info.wallet_currency == WalletCurrency::BTC => { - return Ok(format!("BTC wallet: {} sats", wallet_info.balance)); + if wallet_ids_set.contains(&wallet_info.id) + || match (&wallet, &wallet_info.wallet_currency) { + (Some(w), wc) if wallet_to_currency(w) == *wc => true, + (None, _) if wallet_ids_set.is_empty() => true, + _ => false, } - None => { + { + let currency = match wallet_info.wallet_currency { + WalletCurrency::USD => "cents", + WalletCurrency::BTC => "sats", + _ => "unknown", + }; + + wallet_balances += &format!( + "{}{}: {} {}\n", if wallet_info.wallet_currency == WalletCurrency::USD { - wallet_balances += &format!( - "USD wallet{}: {} cents\n", - if wallet_info.id == default_wallet_id { - " (default)" - } else { - "" - }, - wallet_info.balance - ); - } - if wallet_info.wallet_currency == WalletCurrency::BTC { - wallet_balances += &format!( - "BTC wallet{}: {} sats\n", - if wallet_info.id == default_wallet_id { - " (default)" - } else { - "" - }, - wallet_info.balance - ); - } - } - _ => {} + "USD wallet" + } else if wallet_info.wallet_currency == WalletCurrency::BTC { + "BTC wallet" + } else { + &wallet_info.id + }, + if wallet_info.id == default_wallet_id { + " (default)" + } else { + "" + }, + wallet_info.balance, + currency, + ); } } if wallet_balances.is_empty() { Err(anyhow::anyhow!("No matching wallet found")) } else { - Ok(wallet_balances) + Ok(wallet_balances.trim().to_string()) } } diff --git a/src/client/queries.rs b/src/client/queries.rs index 0400205..a3463be 100644 --- a/src/client/queries.rs +++ b/src/client/queries.rs @@ -41,7 +41,7 @@ pub use self::query_globals::QueryGlobalsGlobals; query_path = "src/client/graphql/queries/me.graphql", response_derives = "Debug, Serialize, PartialEq" )] -pub(super) struct QueryMe; +pub struct QueryMe; pub use self::query_me::QueryMeMe; // mutations diff --git a/src/lib.rs b/src/lib.rs index 1b404bf..17af812 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -6,3 +6,4 @@ mod client; pub use client::*; pub mod types; +pub mod utils; diff --git a/src/main.rs b/src/main.rs index 0a103ae..ade4213 100644 --- a/src/main.rs +++ b/src/main.rs @@ -73,6 +73,8 @@ enum Commands { btc: bool, #[clap(long)] usd: bool, + #[clap(long, use_value_delimiter = true)] + wallet_ids: Vec, }, /// Execute a Payment Pay { @@ -131,7 +133,11 @@ fn main() -> anyhow::Result<()> { serde_json::to_string_pretty(&result).expect("Can't serialize json") ); } - Commands::Balance { btc, usd } => { + Commands::Balance { + btc, + usd, + wallet_ids, + } => { let wallet_type = match (btc, usd) { (true, true) | (false, false) => None, (true, false) => Some(Wallet::Btc), @@ -139,7 +145,7 @@ fn main() -> anyhow::Result<()> { }; let balance = galoy_cli - .fetch_balance(wallet_type) + .fetch_balance(wallet_type, wallet_ids) .context("can't fetch balance")?; println!("{}", balance); } diff --git a/src/utils.rs b/src/utils.rs new file mode 100644 index 0000000..93e3618 --- /dev/null +++ b/src/utils.rs @@ -0,0 +1,9 @@ +use crate::client::queries::query_me::WalletCurrency; +use crate::types::Wallet; + +pub fn wallet_to_currency(wallet: &Wallet) -> WalletCurrency { + match wallet { + Wallet::Usd => WalletCurrency::USD, + Wallet::Btc => WalletCurrency::BTC, + } +} From 3292bb9e8fcc3418cb86e6f308298920aea41861 Mon Sep 17 00:00:00 2001 From: Eshan Vaid Date: Tue, 13 Jun 2023 22:59:45 +0530 Subject: [PATCH 4/6] refactor: implement From for Wallet conversion --- src/client/mod.rs | 15 ++++++++++++--- src/lib.rs | 1 - src/utils.rs | 9 --------- 3 files changed, 12 insertions(+), 13 deletions(-) delete mode 100644 src/utils.rs diff --git a/src/client/mod.rs b/src/client/mod.rs index 89e5225..89e000f 100644 --- a/src/client/mod.rs +++ b/src/client/mod.rs @@ -15,13 +15,22 @@ pub use error::*; pub mod batch; pub use batch::Batch; -use self::query_me::WalletCurrency; +pub use self::query_me::WalletCurrency; use crate::types::*; -use crate::utils::*; pub mod server; +impl From<&WalletCurrency> for Wallet { + fn from(currency: &WalletCurrency) -> Self { + match currency { + WalletCurrency::USD => Wallet::Usd, + WalletCurrency::BTC => Wallet::Btc, + _ => panic!("Unsupported currency"), + } + } +} + pub struct GaloyClient { graphql_client: Client, api: String, @@ -117,7 +126,7 @@ impl GaloyClient { for wallet_info in wallets { if wallet_ids_set.contains(&wallet_info.id) || match (&wallet, &wallet_info.wallet_currency) { - (Some(w), wc) if wallet_to_currency(w) == *wc => true, + (Some(w), wc) if *w == Wallet::from(wc) => true, (None, _) if wallet_ids_set.is_empty() => true, _ => false, } diff --git a/src/lib.rs b/src/lib.rs index 17af812..1b404bf 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -6,4 +6,3 @@ mod client; pub use client::*; pub mod types; -pub mod utils; diff --git a/src/utils.rs b/src/utils.rs deleted file mode 100644 index 93e3618..0000000 --- a/src/utils.rs +++ /dev/null @@ -1,9 +0,0 @@ -use crate::client::queries::query_me::WalletCurrency; -use crate::types::Wallet; - -pub fn wallet_to_currency(wallet: &Wallet) -> WalletCurrency { - match wallet { - Wallet::Usd => WalletCurrency::USD, - Wallet::Btc => WalletCurrency::BTC, - } -} From 626873f802763ef53fbef0cf9b53c8a89a3fe5c5 Mon Sep 17 00:00:00 2001 From: Eshan Vaid Date: Tue, 13 Jun 2023 23:01:00 +0530 Subject: [PATCH 5/6] refactor: rename wallet to wallet_type --- src/client/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/client/mod.rs b/src/client/mod.rs index 89e000f..ae57960 100644 --- a/src/client/mod.rs +++ b/src/client/mod.rs @@ -111,7 +111,7 @@ impl GaloyClient { pub fn fetch_balance( &self, - wallet: Option, + wallet_type: Option, wallet_ids: Vec, ) -> anyhow::Result { let me = self.me()?; @@ -125,7 +125,7 @@ impl GaloyClient { for wallet_info in wallets { if wallet_ids_set.contains(&wallet_info.id) - || match (&wallet, &wallet_info.wallet_currency) { + || match (&wallet_type, &wallet_info.wallet_currency) { (Some(w), wc) if *w == Wallet::from(wc) => true, (None, _) if wallet_ids_set.is_empty() => true, _ => false, From b9a2227aabddad86e3691ec389637689c8d1ffa2 Mon Sep 17 00:00:00 2001 From: Eshan Vaid Date: Tue, 13 Jun 2023 23:20:29 +0530 Subject: [PATCH 6/6] refactor(fetch_balance): return type to json --- src/client/mod.rs | 69 +++++++++++++++++++---------------------------- src/main.rs | 6 +++-- src/types.rs | 11 ++++++++ 3 files changed, 42 insertions(+), 44 deletions(-) diff --git a/src/client/mod.rs b/src/client/mod.rs index ae57960..7d97d7d 100644 --- a/src/client/mod.rs +++ b/src/client/mod.rs @@ -4,7 +4,7 @@ use reqwest::blocking::Client; use log::info; use rust_decimal::Decimal; -use std::net::TcpListener; +use std::{collections::HashSet, net::TcpListener}; pub mod queries; pub use queries::*; @@ -113,54 +113,39 @@ impl GaloyClient { &self, wallet_type: Option, wallet_ids: Vec, - ) -> anyhow::Result { + ) -> anyhow::Result> { let me = self.me()?; - let default_wallet_id = me.default_account.default_wallet_id; let wallets = &me.default_account.wallets; - let wallet_ids_set: std::collections::HashSet<_> = wallet_ids.iter().collect(); - - let mut wallet_balances = String::new(); - - for wallet_info in wallets { - if wallet_ids_set.contains(&wallet_info.id) - || match (&wallet_type, &wallet_info.wallet_currency) { - (Some(w), wc) if *w == Wallet::from(wc) => true, - (None, _) if wallet_ids_set.is_empty() => true, - _ => false, - } - { - let currency = match wallet_info.wallet_currency { - WalletCurrency::USD => "cents", - WalletCurrency::BTC => "sats", - _ => "unknown", - }; - - wallet_balances += &format!( - "{}{}: {} {}\n", - if wallet_info.wallet_currency == WalletCurrency::USD { - "USD wallet" - } else if wallet_info.wallet_currency == WalletCurrency::BTC { - "BTC wallet" - } else { - &wallet_info.id - }, - if wallet_info.id == default_wallet_id { - " (default)" - } else { - "" - }, - wallet_info.balance, - currency, - ); - } - } + let wallet_ids_set: HashSet<_> = wallet_ids.into_iter().collect(); - if wallet_balances.is_empty() { + let balances: Vec<_> = wallets + .iter() + .filter(|wallet_info| { + wallet_ids_set.contains(&wallet_info.id) + || wallet_type.as_ref().map_or(wallet_ids_set.is_empty(), |w| { + *w == Wallet::from(&wallet_info.wallet_currency) + }) + }) + .map(|wallet_info| WalletBalance { + currency: format!("{:?}", Wallet::from(&wallet_info.wallet_currency)), + balance: wallet_info.balance, + id: if wallet_info.wallet_currency == WalletCurrency::USD + || wallet_info.wallet_currency == WalletCurrency::BTC + { + None + } else { + Some(wallet_info.id.clone()) + }, + default: wallet_info.id == default_wallet_id, + }) + .collect(); + + if balances.is_empty() { Err(anyhow::anyhow!("No matching wallet found")) } else { - Ok(wallet_balances.trim().to_string()) + Ok(balances) } } diff --git a/src/main.rs b/src/main.rs index ade4213..f0ab6ca 100644 --- a/src/main.rs +++ b/src/main.rs @@ -144,10 +144,12 @@ fn main() -> anyhow::Result<()> { (false, true) => Some(Wallet::Usd), }; - let balance = galoy_cli + let balances = galoy_cli .fetch_balance(wallet_type, wallet_ids) .context("can't fetch balance")?; - println!("{}", balance); + let balances_json = + serde_json::to_string_pretty(&balances).context("Can't serialize json")?; + println!("{}", balances_json); } Commands::Pay { username, diff --git a/src/types.rs b/src/types.rs index 7ecec72..065d01d 100644 --- a/src/types.rs +++ b/src/types.rs @@ -1,5 +1,16 @@ +use rust_decimal::Decimal; +use serde::Serialize; + #[derive(Debug, Clone, clap::ValueEnum, PartialEq, Eq)] pub enum Wallet { Btc, Usd, } + +#[derive(Debug, Serialize)] +pub struct WalletBalance { + pub currency: String, + pub balance: Decimal, + pub id: Option, + pub default: bool, +}