diff --git a/README.md b/README.md index 9492e53..bc2e9bf 100644 --- a/README.md +++ b/README.md @@ -14,11 +14,14 @@ Simple, reference implementation Cashu wallet, in Rust, with UI, based on CDK. ## TODO +Minor: +- No mint list, selected mint if only one mint + Proto: - UI: Show Mints in dialog -- Add mint! MVP: +- mint onboarding: guide to adding mint, propose mints, links to pink - Wallet init, seed verify - cmd line args - arg for DB file @@ -28,10 +31,13 @@ Non-MVP: - pending operations, show, check - app: collect logs, provide - claim pending +- mint list, with recommendations, etc. +- Parse and show info from entered LN invoice & cashu tokens - list proofs - re-mint, change denoms - burn spent tokens - send LN from multiple mints (MPP) +- read QR codes CDK: - melt_quote_status vs. mint_quote_state diff --git a/parakesh-common/Cargo.toml b/parakesh-common/Cargo.toml index 73a07cd..09dd9a0 100644 --- a/parakesh-common/Cargo.toml +++ b/parakesh-common/Cargo.toml @@ -1,8 +1,11 @@ [package] name = "parakesh-common" version = "0.1.1" +description = "Common parts for ParaKesh Cashu wallet" +license = "MIT" edition = "2021" + [dependencies] cdk = "0.8.1" cdk-common = "0.8.1" diff --git a/parakesh-console-sync/Cargo.toml b/parakesh-console-sync/Cargo.toml index c415311..ebf0223 100644 --- a/parakesh-console-sync/Cargo.toml +++ b/parakesh-console-sync/Cargo.toml @@ -1,6 +1,8 @@ [package] name = "parakesh-console-sync" version = "0.1.1" +description = "Simple Cashu wallet, console UI, built on CDK, simple async/await invocations" +license = "MIT" edition = "2021" [dependencies] diff --git a/parakesh-ui/Cargo.toml b/parakesh-ui/Cargo.toml index 9c51338..51f2e5b 100644 --- a/parakesh-ui/Cargo.toml +++ b/parakesh-ui/Cargo.toml @@ -1,6 +1,8 @@ [package] name = "parakesh-ui" version = "0.1.1" +description = "Simple Cashu wallet with UI (iced-based), built on CDK" +license = "MIT" edition = "2021" [dependencies] diff --git a/parakesh-ui/src/common.rs b/parakesh-ui/src/common.rs index 2b3f499..1988d21 100644 --- a/parakesh-ui/src/common.rs +++ b/parakesh-ui/src/common.rs @@ -31,6 +31,7 @@ pub(crate) enum Message { AmountInput(String), InvoiceInput(String), TokenInput(String), + AddMintInput(String), ReceiveLN(u64), ReceiveLNOK, ReceiveEC(String), @@ -40,6 +41,7 @@ pub(crate) enum Message { SendEC(u64), SendECOK, SelectMint(String), + AddMint(String), WidgetMessage((String, WidgetMessage)), CopyToClipboard(String), } diff --git a/parakesh-ui/src/ui.rs b/parakesh-ui/src/ui.rs index 16fe6cd..c7cd4ad 100644 --- a/parakesh-ui/src/ui.rs +++ b/parakesh-ui/src/ui.rs @@ -9,6 +9,14 @@ use iced::futures::{SinkExt, StreamExt}; use iced::widget::{button, column, mouse_area, row, scrollable, text, text_input, Column}; use iced::{Element, Renderer, Task, Theme}; +#[derive(Default)] +enum AddMintState { + #[default] + NotRequested, + Requested, + Completed(Result<(), String>), +} + #[derive(Default)] enum RecLNState { #[default] @@ -53,7 +61,9 @@ pub(crate) struct IcedApp { amount_input: String, invoice_input: String, token_input: String, + add_mint_input: String, + add_mint_state: AddMintState, rec_ln_state: RecLNState, rec_ec_state: RecECState, send_ln_state: SendLNState, @@ -250,6 +260,7 @@ impl IcedApp { .as_ref() .map(|wi| wi.selected_mint_url.to_string()) .unwrap_or("?".to_owned()); + let mints_ui: Column<'_, Message, Theme, Renderer> = Column::with_children(self.mints_info.iter().map(|mi| { mouse_area(row![ @@ -266,11 +277,25 @@ impl IcedApp { })); column![ row![text("Mints:").size(20)], - row![ - text("Selected mint: ").size(15), - text(selected_mint).size(15), - ], + row![text("Selected: ").size(15), text(selected_mint).size(15),], + row![text("List (click to select)").size(15),], mints_ui, + row![ + button("Add Mint:").on_press(Message::AddMint(self.add_mint_input.clone())), + text_input("(mint url)", &self.add_mint_input) + .on_input(Message::AddMintInput) + .size(20) + .width(200), + ] + .spacing(10), + row![text(match &self.add_mint_state { + AddMintState::NotRequested => "-".to_owned(), + AddMintState::Requested => "Add in progress...".to_owned(), + AddMintState::Completed(Ok(_)) => "Mint added".to_owned(), + AddMintState::Completed(Err(e)) => format!("Error adding mint, {}", e), + }) + .size(15),] + .spacing(10), ] .spacing(10) .into() @@ -323,14 +348,14 @@ impl IcedApp { let header = self.view_header(); let tab_header: Element = row![ + button("Mints").on_press(Message::Tab(UiMainTab::Mints)), button("Receive LN").on_press(Message::Tab(UiMainTab::RecLN)), button("Receive EC").on_press(Message::Tab(UiMainTab::RecEC)), button("Send LN").on_press(Message::Tab(UiMainTab::SendLN)), button("Send EC").on_press(Message::Tab(UiMainTab::SendEC)), - button("Mints").on_press(Message::Tab(UiMainTab::Mints)), button("Settings").on_press(Message::Tab(UiMainTab::Settings)), text("|").size(20), - button("Refresh").on_press(Message::RefreshInfo), + button("(Refresh)").on_press(Message::RefreshInfo), ] .spacing(10) .into(); @@ -362,7 +387,9 @@ impl IcedApp { amount_input: "0".to_owned(), invoice_input: "".to_owned(), token_input: "".to_owned(), + add_mint_input: "".to_owned(), + add_mint_state: AddMintState::NotRequested, rec_ln_state: RecLNState::NotRequested, rec_ec_state: RecECState::NotRequested, send_ln_state: SendLNState::NotRequested, @@ -432,7 +459,8 @@ impl IcedApp { self.wallet_info = Some(wallet_info.clone()); } } - AppEvent::MintAdded(_res) => { + AppEvent::MintAdded(res) => { + self.add_mint_state = AddMintState::Completed(res); self.refresh_info(); } AppEvent::MintSelectedByUrl(_res) => { @@ -480,6 +508,10 @@ impl IcedApp { Message::SelectMint(url) => { let _res = self.app.select_mint(url); } + Message::AddMint(url) => { + self.add_mint_state = AddMintState::Requested; + let _res = self.app.add_mint(url); + } Message::AmountInput(amount_str) => { if let Ok(amnt) = amount_str.parse::() { self.amount_input = (amnt as u64).to_string(); @@ -491,6 +523,9 @@ impl IcedApp { Message::TokenInput(token) => { self.token_input = token; } + Message::AddMintInput(mint_url) => { + self.add_mint_input = mint_url; + } Message::ReceiveLN(amount) => { self.rec_ln_state = RecLNState::Requested(amount); let _res = self.app.mint_from_ln(amount); diff --git a/parakesh/Cargo.toml b/parakesh/Cargo.toml index 16a3ff7..0fb0fca 100644 --- a/parakesh/Cargo.toml +++ b/parakesh/Cargo.toml @@ -1,6 +1,8 @@ [package] name = "parakesh" version = "0.1.1" +description = "Simple Cashu wallet, console UI, based on CDK, event-based invocations" +license = "MIT" edition = "2021" [dependencies]