From 7f77544101cc9fb675dda880e1f04f7ca8c4d011 Mon Sep 17 00:00:00 2001 From: Tommy Volk Date: Wed, 3 Sep 2025 15:17:47 -0500 Subject: [PATCH] refactor: add strong typing to AddMint and PeekMint UI messages --- harbor-client/src/lib.rs | 20 +++++++ harbor-ui/src/main.rs | 100 ++++++++++++++-------------------- harbor-ui/src/routes/mints.rs | 9 ++- 3 files changed, 69 insertions(+), 60 deletions(-) diff --git a/harbor-client/src/lib.rs b/harbor-client/src/lib.rs index 8e99dc7c..ce102d90 100644 --- a/harbor-client/src/lib.rs +++ b/harbor-client/src/lib.rs @@ -127,6 +127,26 @@ impl MintIdentifier { } } +#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)] +pub enum MintConnectionInfo { + Cashu(MintUrl), + Fedimint(InviteCode), +} + +impl FromStr for MintConnectionInfo { + type Err = anyhow::Error; + + fn from_str(s: &str) -> Result { + if let Ok(url) = MintUrl::from_str(s) { + Ok(Self::Cashu(url)) + } else if let Ok(invite_code) = InviteCode::from_str(s) { + Ok(Self::Fedimint(invite_code)) + } else { + Err(anyhow::anyhow!("Invalid mint connection info: {}", s)) + } + } +} + #[derive(Debug, Clone)] pub struct UICoreMsgPacket { pub id: Uuid, diff --git a/harbor-ui/src/main.rs b/harbor-ui/src/main.rs index 0addd90d..75f1746d 100644 --- a/harbor-ui/src/main.rs +++ b/harbor-ui/src/main.rs @@ -37,16 +37,14 @@ use components::{MUTINY_GREEN, MUTINY_RED}; use harbor_client::Bolt11Invoice; use harbor_client::bip39::Mnemonic; use harbor_client::bitcoin::{Address, Network}; -use harbor_client::cdk::mint_url::MintUrl; use harbor_client::db_models::MintItem; use harbor_client::db_models::transaction_item::TransactionItem; use harbor_client::fedimint_core::Amount; use harbor_client::fedimint_core::core::ModuleKind; -use harbor_client::fedimint_core::invite_code::InviteCode; use harbor_client::lightning_address::parse_lnurl; use harbor_client::{ - CoreUIMsg, CoreUIMsgPacket, MintIdentifier, ReceiveSuccessMsg, SendSuccessMsg, UICoreMsg, - data_dir, + CoreUIMsg, CoreUIMsgPacket, MintConnectionInfo, MintIdentifier, ReceiveSuccessMsg, + SendSuccessMsg, UICoreMsg, data_dir, }; use iced::Font; use iced::Subscription; @@ -212,9 +210,9 @@ pub enum Message { password: String, seed: Option, }, - AddMint(String), + AddMint(MintConnectionInfo), RejoinMint(MintIdentifier), - PeekMint(String), + PeekMint(MintConnectionInfo), RemoveMint(MintIdentifier), ChangeMint(MintIdentifier), Donate, @@ -876,53 +874,43 @@ impl HarborWallet { } } }, - Message::AddMint(string) => match InviteCode::from_str(&string) { - Ok(invite) => { - self.add_federation_status = AddFederationStatus::Adding; - let (id, task) = self.send_from_ui(UICoreMsg::AddFederation(invite)); - self.current_add_id = Some(id); - task - } - Err(_) => match MintUrl::from_str(&string) { - Ok(mint_url) => { - self.add_federation_status = AddFederationStatus::Adding; - let (id, task) = self.send_from_ui(UICoreMsg::AddCashuMint(mint_url)); - self.current_add_id = Some(id); - task + Message::AddMint(connection_info) => { + self.add_federation_status = AddFederationStatus::Adding; + + let (id, task) = match connection_info { + MintConnectionInfo::Fedimint(invite_code) => { + self.send_from_ui(UICoreMsg::AddFederation(invite_code)) } - Err(_) => Task::done(Message::AddToast(Toast { - title: "Can't add mint".to_string(), - body: Some("Invalid invite code".to_string()), - status: ToastStatus::Bad, - })), - }, - }, - Message::PeekMint(string) => match InviteCode::from_str(&string) { - Ok(invite) => { - if self.mint_list.iter().any(|m| { - m.active - && m.id - .federation_id() - .is_some_and(|f| f == invite.federation_id()) - }) { - return Task::done(Message::AddToast(Toast { - title: "Mint already added".to_string(), - body: None, - status: ToastStatus::Bad, - })); + MintConnectionInfo::Cashu(mint_url) => { + self.send_from_ui(UICoreMsg::AddCashuMint(mint_url)) } + }; - self.peek_status = PeekStatus::Peeking; - let (id, task) = self.send_from_ui(UICoreMsg::GetFederationInfo(invite)); - self.current_peek_id = Some(id); - task - } - Err(_) => match MintUrl::from_str(&string) { - Ok(mint) => { + self.current_add_id = Some(id); + task + } + Message::PeekMint(connection_info) => { + let (id, task) = match connection_info { + MintConnectionInfo::Fedimint(invite_code) => { + if self.mint_list.iter().any(|m| { + m.active + && m.id + .federation_id() + .is_some_and(|f| f == invite_code.federation_id()) + }) { + return Task::done(Message::AddToast(Toast { + title: "Mint already added".to_string(), + body: None, + status: ToastStatus::Bad, + })); + } + self.send_from_ui(UICoreMsg::GetFederationInfo(invite_code)) + } + MintConnectionInfo::Cashu(mint_url) => { if self .mint_list .iter() - .any(|m| m.active && m.id.mint_url().is_some_and(|u| u == mint)) + .any(|m| m.active && m.id.mint_url().is_some_and(|u| u == mint_url)) { return Task::done(Message::AddToast(Toast { title: "Mint already added".to_string(), @@ -930,18 +918,14 @@ impl HarborWallet { status: ToastStatus::Bad, })); } - self.peek_status = PeekStatus::Peeking; - let (id, task) = self.send_from_ui(UICoreMsg::GetCashuMintInfo(mint)); - self.current_peek_id = Some(id); - task + self.send_from_ui(UICoreMsg::GetCashuMintInfo(mint_url)) } - Err(_) => Task::done(Message::AddToast(Toast { - title: "Can't preview mint".to_string(), - body: Some("Invalid invite code".to_string()), - status: ToastStatus::Bad, - })), - }, - }, + }; + + self.peek_status = PeekStatus::Peeking; + self.current_peek_id = Some(id); + task + } Message::RemoveMint(mint) => { // Check if the federation still exists before trying to remove it if !self.mint_list.iter().any(|f| f.id == mint) { diff --git a/harbor-ui/src/routes/mints.rs b/harbor-ui/src/routes/mints.rs index 71da23be..a422b805 100644 --- a/harbor-ui/src/routes/mints.rs +++ b/harbor-ui/src/routes/mints.rs @@ -1,3 +1,6 @@ +use std::str::FromStr; + +use harbor_client::MintConnectionInfo; use iced::Element; use iced::widget::{column, row}; @@ -56,6 +59,8 @@ fn mints_list(harbor: &HarborWallet) -> Element { fn mints_add(harbor: &HarborWallet) -> Element { let header = h_header("Add Mint", "Add a new mint to your wallet."); + let mint_connection_info = MintConnectionInfo::from_str(&harbor.mint_invite_code_str).ok(); + let column = match &harbor.peek_federation_item { None => { let mint_input = h_input(InputArgs { @@ -71,7 +76,7 @@ fn mints_add(harbor: &HarborWallet) -> Element { SvgIcon::Eye, harbor.peek_status == PeekStatus::Peeking, ) - .on_press(Message::PeekMint(harbor.mint_invite_code_str.clone())); + .on_press_maybe(mint_connection_info.map(Message::PeekMint)); let mut peek_column = column![mint_input, peek_mint_button].spacing(16); @@ -91,7 +96,7 @@ fn mints_add(harbor: &HarborWallet) -> Element { let is_joining = harbor.add_federation_status == AddFederationStatus::Adding; let add_mint_button = h_button("Join Mint", SvgIcon::Plus, is_joining) - .on_press(Message::AddMint(harbor.mint_invite_code_str.clone())); + .on_press_maybe(mint_connection_info.map(Message::AddMint)); let start_over_button = h_button("Start Over", SvgIcon::Restart, false) .on_press(Message::CancelAddFederation);