diff --git a/Cargo.lock b/Cargo.lock index 122c8a9..9a099fd 100755 --- a/Cargo.lock +++ b/Cargo.lock @@ -84,6 +84,15 @@ dependencies = [ "version_check", ] +[[package]] +name = "aho-corasick" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43f6cb1bf222025340178f382c426f13757b2960e89779dfcb319c32542a5a41" +dependencies = [ + "memchr", +] + [[package]] name = "aliasable" version = "0.1.3" @@ -1001,6 +1010,15 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "format_num" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14ac05eb8d2eb4ed1eeff847911deae077b0b53332465de9d6a26b0ea9961bc8" +dependencies = [ + "regex", +] + [[package]] name = "funty" version = "2.0.0" @@ -1421,9 +1439,9 @@ checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" [[package]] name = "itoa" -version = "1.0.1" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35" +checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" [[package]] name = "js-sys" @@ -1584,6 +1602,7 @@ dependencies = [ "chrono", "clap 4.3.0", "colored", + "format_num", "migration", "sea-orm", "sea-orm-migration", @@ -2115,6 +2134,8 @@ version = "1.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "81ca098a9821bd52d6b24fd8b10bd081f47d39c22778cafaa75a2857a62c6390" dependencies = [ + "aho-corasick", + "memchr", "regex-syntax 0.7.2", ] @@ -2498,7 +2519,7 @@ version = "1.0.96" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "057d394a50403bcac12672b2b18fb387ab6d289d957dab67dd201875391e52f1" dependencies = [ - "itoa 1.0.1", + "itoa 1.0.6", "ryu", "serde", ] @@ -2533,7 +2554,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9d684e3ec7de3bf5466b32bd75303ac16f0736426e5a4e0d6e489559ce1249c" dependencies = [ "indexmap", - "itoa 1.0.1", + "itoa 1.0.6", "ryu", "serde", "unsafe-libyaml", @@ -2700,7 +2721,7 @@ dependencies = [ "hashlink", "hex", "indexmap", - "itoa 1.0.1", + "itoa 1.0.6", "libc", "log", "memchr", @@ -2991,7 +3012,7 @@ version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f3403384eaacbca9923fa06940178ac13e4edb725486d70e8e15881d0c836cc" dependencies = [ - "itoa 1.0.1", + "itoa 1.0.6", "serde", "time-core", "time-macros 0.2.9", diff --git a/Cargo.toml b/Cargo.toml index bc3ce24..807b500 100755 --- a/Cargo.toml +++ b/Cargo.toml @@ -32,4 +32,5 @@ anyhow = "1.0.71" sea-orm-migration = "0.11.3" migration = {path = "migration"} colored = "2.0.0" +format_num = "0.1.0" # futures = "0.3.28" \ No newline at end of file diff --git a/src/bin/cli.rs b/src/bin/cli.rs index 6c1ef37..cffa804 100644 --- a/src/bin/cli.rs +++ b/src/bin/cli.rs @@ -77,10 +77,10 @@ async fn main() -> Result<()> { let account_command = sub_matches.subcommand().unwrap(); match account_command { ("list", _) => { - commands::account::list().await; + commands::account::list().await?; } ("balance", _) => { - println!("Accoount balances") + commands::account::balance().await?; } (name, _) => { diff --git a/src/commands/account.rs b/src/commands/account.rs index 717be34..7916fb7 100644 --- a/src/commands/account.rs +++ b/src/commands/account.rs @@ -1,15 +1,24 @@ //! Command Line Interface `Accounts` commands //! -use crate::db; +use crate::{db, starling::client::StarlingApiClient}; use anyhow::Result; pub async fn list() -> Result<()> { - println!("Account list"); - + println!("Account list:"); for account in db::account::list().await? { - println!("{:#?}", account.name); + println!("- {:#?}", account.name); } Ok(()) } + +pub async fn balance() -> Result<()> { + println!("Account balances:"); + for account in db::account::list().await? { + let client = StarlingApiClient::new(&account.token); + let balance = client.balance(&account.uid).await?; + println!("- {}: {}", account.name, balance.effective.as_string()); + } + Ok(()) +} diff --git a/src/starling/account.rs b/src/starling/account.rs index cac4260..2b76393 100644 --- a/src/starling/account.rs +++ b/src/starling/account.rs @@ -1,10 +1,11 @@ //! Structures and methods for processing `/api/v2/accounts/` endpoints +use super::client::StarlingApiClient; +use anyhow::Result; use chrono::{DateTime, Utc}; +use format_num::NumberFormat; use serde::Deserialize; -use super::client::StarlingApiClient; - /// Represents a list of Starling accounts #[derive(Deserialize, Debug)] pub struct Accounts { @@ -26,30 +27,42 @@ pub struct Account { #[derive(Deserialize, Debug)] pub struct Balance { #[serde(rename = "clearedBalance")] - cleared: SignedCurrencyAndAmount, + pub cleared: SignedCurrencyAndAmount, #[serde(rename = "effectiveBalance")] - effective: SignedCurrencyAndAmount, + pub effective: SignedCurrencyAndAmount, #[serde(rename = "pendingTransactions")] - pending: SignedCurrencyAndAmount, + pub pending: SignedCurrencyAndAmount, #[serde(rename = "totalClearedBalance")] - total_cleared: SignedCurrencyAndAmount, + pub total_cleared: SignedCurrencyAndAmount, #[serde(rename = "acceptedOverdraft")] - overdraft: SignedCurrencyAndAmount, + pub overdraft: SignedCurrencyAndAmount, #[serde(rename = "totalEffectiveBalance")] - total_effective: SignedCurrencyAndAmount, + pub total_effective: SignedCurrencyAndAmount, } #[derive(Deserialize, Debug)] -struct SignedCurrencyAndAmount { +pub struct SignedCurrencyAndAmount { currency: String, - #[serde(rename = "minurUnits")] + #[serde(rename = "minorUnits")] minor_units: i64, } +impl SignedCurrencyAndAmount { + pub fn as_float(&self) -> f32 { + self.minor_units as f32 / 100.0 + } + + pub fn as_string(&self) -> String { + let num = NumberFormat::new(); + let amount = num.format(" >10,.2f", self.as_float()); + format!("{} {}", self.currency, amount) + } +} + // Implement `/api/v2/accounts/{accountUid}/balance` // impl StarlingApiClient { - async fn balance(&self, account_uid: &String) -> Balance { + pub async fn balance(&self, account_uid: &String) -> Result { let mut resp = surf::get(format!( "{}/accounts/{}/balance", &self.base_url, &account_uid @@ -59,6 +72,6 @@ impl StarlingApiClient { .await .unwrap(); - resp.body_json::().await.unwrap() + Ok(resp.body_json::().await.unwrap()) } }