From 34d452db7d093f7878625c76ded10193a9d6e4cd Mon Sep 17 00:00:00 2001 From: benthecarman Date: Fri, 17 May 2024 14:39:03 -0500 Subject: [PATCH] Add unique message id to requests/responses --- src/bridge.rs | 82 +++++++++++++++++++++------- src/core.rs | 107 +++++++++++++++++++++++------------- src/fedimint_client.rs | 120 ++++++++++++++++++++++++++++------------- src/main.rs | 49 +++++++++++------ 4 files changed, 246 insertions(+), 112 deletions(-) diff --git a/src/bridge.rs b/src/bridge.rs index a73aaa3..ebdf9c4 100644 --- a/src/bridge.rs +++ b/src/bridge.rs @@ -6,6 +6,12 @@ use fedimint_core::Amount; use fedimint_ln_common::lightning_invoice::Bolt11Invoice; use tokio::sync::mpsc; +#[derive(Debug, Clone)] +pub struct UICoreMsgPacket { + pub msg: UICoreMsg, + pub id: String, +} + #[derive(Debug, Clone)] pub enum UICoreMsg { SendLightning(Bolt11Invoice), @@ -33,6 +39,12 @@ pub enum ReceiveSuccessMsg { Onchain { txid: Txid }, } +#[derive(Debug, Clone)] +pub struct CoreUIMsgPacket { + pub id: String, + pub msg: CoreUIMsg, +} + #[derive(Debug, Clone)] pub enum CoreUIMsg { Sending, @@ -58,7 +70,7 @@ pub enum CoreUIMsg { #[derive(Debug)] pub struct UIHandle { - ui_to_core_tx: mpsc::Sender, + ui_to_core_tx: mpsc::Sender, } #[derive(Debug, Clone)] @@ -68,61 +80,91 @@ pub enum BridgeError { } impl UIHandle { - pub async fn msg_send(&self, msg: UICoreMsg) { + pub async fn msg_send(&self, msg: UICoreMsgPacket) { self.ui_to_core_tx.send(msg).await.unwrap(); } - pub async fn send_lightning(&self, invoice: Bolt11Invoice) { - self.msg_send(UICoreMsg::SendLightning(invoice)).await; + pub async fn send_lightning(&self, id: String, invoice: Bolt11Invoice) { + self.msg_send(UICoreMsgPacket { + msg: UICoreMsg::SendLightning(invoice), + id, + }) + .await; } - pub async fn send_onchain(&self, address: Address, amount_sats: Option) { - self.msg_send(UICoreMsg::SendOnChain { - address, - amount_sats, + pub async fn send_onchain(&self, id: String, address: Address, amount_sats: Option) { + self.msg_send(UICoreMsgPacket { + msg: UICoreMsg::SendOnChain { + address, + amount_sats, + }, + id, }) .await; } - pub async fn receive(&self, amount: u64) { - self.msg_send(UICoreMsg::ReceiveLightning(Amount::from_sats(amount))) - .await; + pub async fn receive(&self, id: String, amount: u64) { + self.msg_send(UICoreMsgPacket { + msg: UICoreMsg::ReceiveLightning(Amount::from_sats(amount)), + id, + }) + .await; } - pub async fn receive_onchain(&self) { - self.msg_send(UICoreMsg::ReceiveOnChain).await; + pub async fn receive_onchain(&self, id: String) { + self.msg_send(UICoreMsgPacket { + msg: UICoreMsg::ReceiveOnChain, + id, + }) + .await; } pub async fn unlock(&self, password: String) { - self.msg_send(UICoreMsg::Unlock(password)).await; + self.msg_send(UICoreMsgPacket { + msg: UICoreMsg::Unlock(password), + id: "".to_string(), + }) + .await; } pub async fn add_federation(&self, invite: InviteCode) { - self.msg_send(UICoreMsg::AddFederation(invite)).await; + self.msg_send(UICoreMsgPacket { + msg: UICoreMsg::AddFederation(invite), + id: "".to_string(), + }) + .await; } pub async fn peek_federation(&self, invite: InviteCode) { - self.msg_send(UICoreMsg::GetFederationInfo(invite)).await; + self.msg_send(UICoreMsgPacket { + msg: UICoreMsg::GetFederationInfo(invite), + id: "".to_string(), + }) + .await; } pub async fn get_seed_words(&self) { - self.msg_send(UICoreMsg::GetSeedWords).await; + self.msg_send(UICoreMsgPacket { + msg: UICoreMsg::GetSeedWords, + id: "".to_string(), + }) + .await; } } impl CoreHandle { - pub async fn recv(&mut self) -> Option { + pub async fn recv(&mut self) -> Option { self.core_from_ui_rx.recv().await } } #[derive(Debug)] pub struct CoreHandle { - core_from_ui_rx: mpsc::Receiver, + core_from_ui_rx: mpsc::Receiver, } pub fn create_handles() -> (UIHandle, CoreHandle) { - let (ui_to_core_tx, core_from_ui_rx) = mpsc::channel::(50); + let (ui_to_core_tx, core_from_ui_rx) = mpsc::channel::(50); let ui_handle = UIHandle { ui_to_core_tx }; diff --git a/src/core.rs b/src/core.rs index ba88fb0..0bada01 100644 --- a/src/core.rs +++ b/src/core.rs @@ -54,10 +54,10 @@ struct HarborCore { } impl HarborCore { - async fn msg(&self, msg: CoreUIMsg) { + async fn msg(&self, id: String, msg: CoreUIMsg) { self.tx .clone() - .send(Message::CoreMessage(msg)) + .send(Message::core_msg(id, msg)) .await .unwrap(); } @@ -69,14 +69,17 @@ impl HarborCore { balance += client.fedimint_client.get_balance().await; } - self.msg(CoreUIMsg::BalanceUpdated(balance)).await; + let id = "init".to_string(); + + self.msg(id.clone(), CoreUIMsg::BalanceUpdated(balance)) + .await; let history = self.storage.get_transaction_history().unwrap(); - self.msg(CoreUIMsg::TransactionHistoryUpdated(history)) + self.msg(id.clone(), CoreUIMsg::TransactionHistoryUpdated(history)) .await; let federation_items = self.get_federation_items().await; - self.msg(CoreUIMsg::FederationListUpdated(federation_items)) + self.msg(id, CoreUIMsg::FederationListUpdated(federation_items)) .await; } @@ -85,7 +88,7 @@ impl HarborCore { self.clients.read().await.values().next().unwrap().clone() } - async fn send_lightning(&self, invoice: Bolt11Invoice) -> anyhow::Result<()> { + async fn send_lightning(&self, msg_id: String, invoice: Bolt11Invoice) -> anyhow::Result<()> { if invoice.amount_milli_satoshis().is_none() { return Err(anyhow!("Invoice must have an amount")); } @@ -123,6 +126,7 @@ impl HarborCore { client.clone(), self.storage.clone(), op_id, + msg_id, sub, ) .await; @@ -134,6 +138,7 @@ impl HarborCore { client.clone(), self.storage.clone(), op_id, + msg_id, sub, ) .await; @@ -145,7 +150,11 @@ impl HarborCore { Ok(()) } - async fn receive_lightning(&self, amount: Amount) -> anyhow::Result { + async fn receive_lightning( + &self, + msg_id: String, + amount: Amount, + ) -> anyhow::Result { let client = self.get_client().await.fedimint_client; let lightning_module = client.get_first_module::(); @@ -182,6 +191,7 @@ impl HarborCore { client.clone(), self.storage.clone(), op_id, + msg_id, subscription, ) .await; @@ -193,7 +203,12 @@ impl HarborCore { } /// Sends a given amount of sats to a given address, if the amount is None, send all funds - async fn send_onchain(&self, address: Address, sats: Option) -> anyhow::Result<()> { + async fn send_onchain( + &self, + msg_id: String, + address: Address, + sats: Option, + ) -> anyhow::Result<()> { // todo go through all clients and select the first one that has enough balance let client = self.get_client().await.fedimint_client; let onchain = client.get_first_module::(); @@ -248,6 +263,7 @@ impl HarborCore { client.clone(), self.storage.clone(), op_id, + msg_id, sub, ) .await; @@ -255,7 +271,7 @@ impl HarborCore { Ok(()) } - async fn receive_onchain(&self) -> anyhow::Result
{ + async fn receive_onchain(&self, msg_id: String) -> anyhow::Result
{ // todo add federation id selection let client = self.get_client().await.fedimint_client; let onchain = client.get_first_module::(); @@ -275,6 +291,7 @@ impl HarborCore { client.clone(), self.storage.clone(), op_id, + msg_id, sub, ) .await; @@ -364,10 +381,12 @@ pub fn run_core() -> Subscription { loop { let msg = core_handle.recv().await; - match msg { + let id = msg.as_ref().map(|m| m.id.clone()).unwrap_or_default(); + + match msg.map(|m| m.msg) { Some(UICoreMsg::Unlock(password)) => { log::info!("Sending unlock message"); - tx.send(Message::CoreMessage(CoreUIMsg::Unlocking)) + tx.send(Message::core_msg(id.clone(), CoreUIMsg::Unlocking)) .await .expect("should send"); @@ -382,9 +401,10 @@ pub fn run_core() -> Subscription { // probably invalid password error!("error using password: {e}"); - tx.send(Message::CoreMessage(CoreUIMsg::UnlockFailed( - "Invalid Password".to_string(), - ))) + tx.send(Message::core_msg( + id.clone(), + CoreUIMsg::UnlockFailed(e.to_string()), + )) .await .expect("should send"); continue; @@ -425,7 +445,7 @@ pub fn run_core() -> Subscription { stop, }; - tx.send(Message::CoreMessage(CoreUIMsg::UnlockSuccess)) + tx.send(Message::core_msg(id.clone(), CoreUIMsg::UnlockSuccess)) .await .expect("should send"); @@ -450,23 +470,26 @@ async fn process_core(core_handle: &mut bridge::CoreHandle, core: &HarborCore) { let core = core.clone(); tokio::spawn(async move { if let Some(msg) = msg { - match msg { + match msg.msg { UICoreMsg::SendLightning(invoice) => { log::info!("Got UICoreMsg::Send"); - core.msg(CoreUIMsg::Sending).await; - if let Err(e) = core.send_lightning(invoice).await { + core.msg(msg.id.clone(), CoreUIMsg::Sending).await; + if let Err(e) = core.send_lightning(msg.id.clone(), invoice).await { error!("Error sending: {e}"); - core.msg(CoreUIMsg::SendFailure(e.to_string())).await; + core.msg(msg.id, CoreUIMsg::SendFailure(e.to_string())) + .await; } } UICoreMsg::ReceiveLightning(amount) => { - core.msg(CoreUIMsg::ReceiveGenerating).await; - match core.receive_lightning(amount).await { + core.msg(msg.id.clone(), CoreUIMsg::ReceiveGenerating).await; + match core.receive_lightning(msg.id.clone(), amount).await { Err(e) => { - core.msg(CoreUIMsg::ReceiveFailed(e.to_string())).await; + core.msg(msg.id, CoreUIMsg::ReceiveFailed(e.to_string())) + .await; } Ok(invoice) => { - core.msg(CoreUIMsg::ReceiveInvoiceGenerated(invoice)).await; + core.msg(msg.id, CoreUIMsg::ReceiveInvoiceGenerated(invoice)) + .await; } } } @@ -475,20 +498,26 @@ async fn process_core(core_handle: &mut bridge::CoreHandle, core: &HarborCore) { amount_sats, } => { log::info!("Got UICoreMsg::SendOnChain"); - core.msg(CoreUIMsg::Sending).await; - if let Err(e) = core.send_onchain(address, amount_sats).await { + core.msg(msg.id.clone(), CoreUIMsg::Sending).await; + if let Err(e) = core + .send_onchain(msg.id.clone(), address, amount_sats) + .await + { error!("Error sending: {e}"); - core.msg(CoreUIMsg::SendFailure(e.to_string())).await; + core.msg(msg.id, CoreUIMsg::SendFailure(e.to_string())) + .await; } } UICoreMsg::ReceiveOnChain => { - core.msg(CoreUIMsg::ReceiveGenerating).await; - match core.receive_onchain().await { + core.msg(msg.id.clone(), CoreUIMsg::ReceiveGenerating).await; + match core.receive_onchain(msg.id.clone()).await { Err(e) => { - core.msg(CoreUIMsg::ReceiveFailed(e.to_string())).await; + core.msg(msg.id, CoreUIMsg::ReceiveFailed(e.to_string())) + .await; } Ok(address) => { - core.msg(CoreUIMsg::ReceiveAddressGenerated(address)).await; + core.msg(msg.id, CoreUIMsg::ReceiveAddressGenerated(address)) + .await; } } } @@ -496,24 +525,28 @@ async fn process_core(core_handle: &mut bridge::CoreHandle, core: &HarborCore) { match core.get_federation_info(invite_code).await { Err(e) => { error!("Error getting federation info: {e}"); - core.msg(CoreUIMsg::AddFederationFailed(e.to_string())) + core.msg(msg.id, CoreUIMsg::AddFederationFailed(e.to_string())) .await; } Ok(config) => { - core.msg(CoreUIMsg::FederationInfo(config)).await; + core.msg(msg.id, CoreUIMsg::FederationInfo(config)).await; } } } UICoreMsg::AddFederation(invite_code) => { if let Err(e) = core.add_federation(invite_code).await { error!("Error adding federation: {e}"); - core.msg(CoreUIMsg::AddFederationFailed(e.to_string())) + core.msg(msg.id, CoreUIMsg::AddFederationFailed(e.to_string())) .await; } else { - core.msg(CoreUIMsg::AddFederationSuccess).await; - let new_federation_list = core.get_federation_items().await; - core.msg(CoreUIMsg::FederationListUpdated(new_federation_list)) + core.msg(msg.id.clone(), CoreUIMsg::AddFederationSuccess) .await; + let new_federation_list = core.get_federation_items().await; + core.msg( + msg.id, + CoreUIMsg::FederationListUpdated(new_federation_list), + ) + .await; } } UICoreMsg::Unlock(_password) => { @@ -521,7 +554,7 @@ async fn process_core(core_handle: &mut bridge::CoreHandle, core: &HarborCore) { } UICoreMsg::GetSeedWords => { let seed_words = core.get_seed_words().await; - core.msg(CoreUIMsg::SeedWords(seed_words)).await; + core.msg(msg.id, CoreUIMsg::SeedWords(seed_words)).await; } } } diff --git a/src/fedimint_client.rs b/src/fedimint_client.rs index 550dc13..60f0fb9 100644 --- a/src/fedimint_client.rs +++ b/src/fedimint_client.rs @@ -227,13 +227,15 @@ pub(crate) async fn select_gateway(client: &ClientHandleArc) -> Option, + msg_id: String, sender: &mut Sender, ) { if let Ok(history) = storage.get_transaction_history() { sender - .send(Message::CoreMessage(CoreUIMsg::TransactionHistoryUpdated( - history, - ))) + .send(Message::core_msg( + msg_id, + CoreUIMsg::TransactionHistoryUpdated(history), + )) .await .unwrap(); } @@ -244,6 +246,7 @@ pub(crate) async fn spawn_invoice_receive_subscription( client: ClientHandleArc, storage: Arc, operation_id: OperationId, + msg_id: String, subscription: UpdateStreamOrOutcome, ) { spawn(async move { @@ -253,22 +256,25 @@ pub(crate) async fn spawn_invoice_receive_subscription( LnReceiveState::Canceled { reason } => { error!("Payment canceled, reason: {:?}", reason); sender - .send(Message::CoreMessage(CoreUIMsg::ReceiveFailed( - reason.to_string(), - ))) + .send(Message::core_msg( + msg_id, + CoreUIMsg::ReceiveFailed(reason.to_string()), + )) .await .unwrap(); if let Err(e) = storage.mark_ln_receive_as_failed(operation_id) { error!("Could not mark lightning receive as failed: {e}"); } + break; } LnReceiveState::Claimed => { info!("Payment claimed"); sender - .send(Message::CoreMessage(CoreUIMsg::ReceiveSuccess( - ReceiveSuccessMsg::Lightning, - ))) + .send(Message::core_msg( + msg_id.clone(), + CoreUIMsg::ReceiveSuccess(ReceiveSuccessMsg::Lightning), + )) .await .unwrap(); @@ -278,11 +284,14 @@ pub(crate) async fn spawn_invoice_receive_subscription( let new_balance = client.get_balance().await; sender - .send(Message::CoreMessage(CoreUIMsg::BalanceUpdated(new_balance))) + .send(Message::core_msg( + msg_id.clone(), + CoreUIMsg::BalanceUpdated(new_balance), + )) .await .unwrap(); - update_history(storage.clone(), &mut sender).await; + update_history(storage.clone(), msg_id, &mut sender).await; break; } @@ -297,6 +306,7 @@ pub(crate) async fn spawn_invoice_payment_subscription( client: ClientHandleArc, storage: Arc, operation_id: OperationId, + msg_id: String, subscription: UpdateStreamOrOutcome, ) { spawn(async move { @@ -306,9 +316,10 @@ pub(crate) async fn spawn_invoice_payment_subscription( LnPayState::Canceled => { error!("Payment canceled"); sender - .send(Message::CoreMessage(CoreUIMsg::SendFailure( - "Canceled".to_string(), - ))) + .send(Message::core_msg( + msg_id, + CoreUIMsg::SendFailure("Canceled".to_string()), + )) .await .unwrap(); @@ -320,7 +331,10 @@ pub(crate) async fn spawn_invoice_payment_subscription( LnPayState::UnexpectedError { error_message } => { error!("Unexpected payment error: {:?}", error_message); sender - .send(Message::CoreMessage(CoreUIMsg::SendFailure(error_message))) + .send(Message::core_msg( + msg_id, + CoreUIMsg::SendFailure(error_message), + )) .await .unwrap(); @@ -335,7 +349,10 @@ pub(crate) async fn spawn_invoice_payment_subscription( FromHex::from_hex(&preimage).expect("Invalid preimage"); let params = SendSuccessMsg::Lightning { preimage }; sender - .send(Message::CoreMessage(CoreUIMsg::SendSuccess(params))) + .send(Message::core_msg( + msg_id.clone(), + CoreUIMsg::SendSuccess(params), + )) .await .unwrap(); @@ -345,11 +362,14 @@ pub(crate) async fn spawn_invoice_payment_subscription( let new_balance = client.get_balance().await; sender - .send(Message::CoreMessage(CoreUIMsg::BalanceUpdated(new_balance))) + .send(Message::core_msg( + msg_id.clone(), + CoreUIMsg::BalanceUpdated(new_balance), + )) .await .unwrap(); - update_history(storage.clone(), &mut sender).await; + update_history(storage.clone(), msg_id, &mut sender).await; break; } @@ -364,6 +384,7 @@ pub(crate) async fn spawn_internal_payment_subscription( client: ClientHandleArc, storage: Arc, operation_id: OperationId, + msg_id: String, subscription: UpdateStreamOrOutcome, ) { spawn(async move { @@ -373,9 +394,10 @@ pub(crate) async fn spawn_internal_payment_subscription( InternalPayState::FundingFailed { error } => { error!("Funding failed: {error:?}"); sender - .send(Message::CoreMessage(CoreUIMsg::ReceiveFailed( - error.to_string(), - ))) + .send(Message::core_msg( + msg_id, + CoreUIMsg::ReceiveFailed(error.to_string()), + )) .await .unwrap(); if let Err(e) = storage.mark_lightning_payment_as_failed(operation_id) { @@ -386,7 +408,10 @@ pub(crate) async fn spawn_internal_payment_subscription( InternalPayState::UnexpectedError(error_message) => { error!("Unexpected payment error: {error_message:?}"); sender - .send(Message::CoreMessage(CoreUIMsg::SendFailure(error_message))) + .send(Message::core_msg( + msg_id, + CoreUIMsg::SendFailure(error_message), + )) .await .unwrap(); if let Err(e) = storage.mark_lightning_payment_as_failed(operation_id) { @@ -400,7 +425,10 @@ pub(crate) async fn spawn_internal_payment_subscription( preimage: preimage.0, }; sender - .send(Message::CoreMessage(CoreUIMsg::SendSuccess(params))) + .send(Message::core_msg( + msg_id.clone(), + CoreUIMsg::SendSuccess(params), + )) .await .unwrap(); @@ -411,11 +439,14 @@ pub(crate) async fn spawn_internal_payment_subscription( let new_balance = client.get_balance().await; sender - .send(Message::CoreMessage(CoreUIMsg::BalanceUpdated(new_balance))) + .send(Message::core_msg( + msg_id.clone(), + CoreUIMsg::BalanceUpdated(new_balance), + )) .await .unwrap(); - update_history(storage, &mut sender).await; + update_history(storage, msg_id, &mut sender).await; break; } @@ -430,6 +461,7 @@ pub(crate) async fn spawn_onchain_payment_subscription( client: ClientHandleArc, storage: Arc, operation_id: OperationId, + msg_id: String, subscription: UpdateStreamOrOutcome, ) { spawn(async move { @@ -440,9 +472,7 @@ pub(crate) async fn spawn_onchain_payment_subscription( WithdrawState::Failed(error) => { error!("Onchain payment failed: {error:?}"); sender - .send(Message::CoreMessage(CoreUIMsg::SendFailure( - error.to_string(), - ))) + .send(Message::core_msg(msg_id, CoreUIMsg::SendFailure(error))) .await .unwrap(); if let Err(e) = storage.mark_onchain_payment_as_failed(operation_id) { @@ -455,7 +485,10 @@ pub(crate) async fn spawn_onchain_payment_subscription( info!("Onchain payment success: {txid}"); let params = SendSuccessMsg::Onchain { txid }; sender - .send(Message::CoreMessage(CoreUIMsg::SendSuccess(params))) + .send(Message::core_msg( + msg_id.clone(), + CoreUIMsg::SendSuccess(params), + )) .await .unwrap(); @@ -465,11 +498,14 @@ pub(crate) async fn spawn_onchain_payment_subscription( let new_balance = client.get_balance().await; sender - .send(Message::CoreMessage(CoreUIMsg::BalanceUpdated(new_balance))) + .send(Message::core_msg( + msg_id.clone(), + CoreUIMsg::BalanceUpdated(new_balance), + )) .await .unwrap(); - update_history(storage.clone(), &mut sender).await; + update_history(storage.clone(), msg_id, &mut sender).await; break; } @@ -483,6 +519,7 @@ pub(crate) async fn spawn_onchain_receive_subscription( client: ClientHandleArc, storage: Arc, operation_id: OperationId, + msg_id: String, subscription: UpdateStreamOrOutcome, ) { spawn(async move { @@ -493,9 +530,10 @@ pub(crate) async fn spawn_onchain_receive_subscription( DepositState::Failed(error) => { error!("Onchain receive failed: {error:?}"); sender - .send(Message::CoreMessage(CoreUIMsg::ReceiveFailed( - error.to_string(), - ))) + .send(Message::core_msg( + msg_id, + CoreUIMsg::ReceiveFailed(error), + )) .await .unwrap(); @@ -512,7 +550,10 @@ pub(crate) async fn spawn_onchain_receive_subscription( let amount = data.btc_transaction.output[index].value; let params = ReceiveSuccessMsg::Onchain { txid }; sender - .send(Message::CoreMessage(CoreUIMsg::ReceiveSuccess(params))) + .send(Message::core_msg( + msg_id.clone(), + CoreUIMsg::ReceiveSuccess(params), + )) .await .unwrap(); @@ -523,7 +564,7 @@ pub(crate) async fn spawn_onchain_receive_subscription( error!("Could not mark onchain payment txid: {e}"); } - update_history(storage.clone(), &mut sender).await; + update_history(storage.clone(), msg_id.clone(), &mut sender).await; } DepositState::Confirmed(data) => { info!("Onchain receive confirmed: {data:?}"); @@ -532,7 +573,10 @@ pub(crate) async fn spawn_onchain_receive_subscription( info!("Onchain receive claimed: {data:?}"); let new_balance = client.get_balance().await; sender - .send(Message::CoreMessage(CoreUIMsg::BalanceUpdated(new_balance))) + .send(Message::core_msg( + msg_id.clone(), + CoreUIMsg::BalanceUpdated(new_balance), + )) .await .unwrap(); @@ -540,7 +584,7 @@ pub(crate) async fn spawn_onchain_receive_subscription( error!("Could not mark onchain payment txid: {e}"); } - update_history(storage.clone(), &mut sender).await; + update_history(storage.clone(), msg_id, &mut sender).await; break; } diff --git a/src/main.rs b/src/main.rs index 67ca76d..faecea9 100644 --- a/src/main.rs +++ b/src/main.rs @@ -8,7 +8,7 @@ use routes::Route; use std::str::FromStr; use std::sync::Arc; -use bridge::{CoreUIMsg, ReceiveSuccessMsg, SendSuccessMsg}; +use bridge::{CoreUIMsg, CoreUIMsgPacket, ReceiveSuccessMsg, SendSuccessMsg}; use iced::subscription::Subscription; use iced::widget::row; use iced::Element; @@ -104,7 +104,13 @@ pub enum Message { PeekFederation(String), Donate, // Core messages we get from core - CoreMessage(CoreUIMsg), + CoreMessage(CoreUIMsgPacket), +} + +impl Message { + pub fn core_msg(id: String, msg: CoreUIMsg) -> Self { + Self::CoreMessage(CoreUIMsgPacket { id, msg }) + } } // This is the UI state. It should only contain data that is directly rendered by the UI @@ -156,10 +162,11 @@ impl HarborWallet { async fn async_send_lightning( ui_handle: Option>, + id: String, invoice: Bolt11Invoice, ) { if let Some(ui_handle) = ui_handle { - ui_handle.clone().send_lightning(invoice).await; + ui_handle.clone().send_lightning(id, invoice).await; } else { panic!("UI handle is None"); } @@ -167,29 +174,32 @@ impl HarborWallet { async fn async_send_onchain( ui_handle: Option>, + id: String, address: Address, amount_sats: Option, ) { println!("Got to async_send"); if let Some(ui_handle) = ui_handle { - println!("Have a ui_handle, sending the invoice over"); - ui_handle.clone().send_onchain(address, amount_sats).await; + ui_handle + .clone() + .send_onchain(id, address, amount_sats) + .await; } else { panic!("UI handle is None"); } } - async fn async_receive(ui_handle: Option>, amount: u64) { + async fn async_receive(ui_handle: Option>, id: String, amount: u64) { if let Some(ui_handle) = ui_handle { - ui_handle.clone().receive(amount).await; + ui_handle.clone().receive(id, amount).await; } else { panic!("UI handle is None"); } } - async fn async_receive_onchain(ui_handle: Option>) { + async fn async_receive_onchain(ui_handle: Option>, id: String) { if let Some(ui_handle) = ui_handle { - ui_handle.clone().receive_onchain().await; + ui_handle.clone().receive_onchain(id).await; } else { panic!("UI handle is None"); } @@ -308,9 +318,10 @@ impl HarborWallet { SendStatus::Sending => Command::none(), _ => { self.send_failure_reason = None; + let id = uuid::Uuid::new_v4().to_string(); // todo use this id somewhere if let Ok(invoice) = Bolt11Invoice::from_str(&invoice_str) { Command::perform( - Self::async_send_lightning(self.ui_handle.clone(), invoice), + Self::async_send_lightning(self.ui_handle.clone(), id, invoice), |_| Message::Noop, ) } else if let Ok(address) = Address::from_str(&invoice_str) { @@ -321,7 +332,7 @@ impl HarborWallet { Some(self.send_amount_input_str.parse::().unwrap()) }; Command::perform( - Self::async_send_onchain(self.ui_handle.clone(), address, amount), + Self::async_send_onchain(self.ui_handle.clone(), id, address, amount), |_| Message::Noop, ) } else { @@ -334,9 +345,10 @@ impl HarborWallet { ReceiveStatus::Generating => Command::none(), _ => { self.receive_failure_reason = None; + let id = uuid::Uuid::new_v4().to_string(); // todo use this id somewhere match self.receive_amount_str.parse::() { Ok(amount) => Command::perform( - Self::async_receive(self.ui_handle.clone(), amount), + Self::async_receive(self.ui_handle.clone(), id, amount), |_| Message::Noop, ), Err(e) => { @@ -350,10 +362,12 @@ impl HarborWallet { Message::GenerateAddress => match self.receive_status { ReceiveStatus::Generating => Command::none(), _ => { + let id = uuid::Uuid::new_v4().to_string(); // todo use this id somewhere self.receive_failure_reason = None; - Command::perform(Self::async_receive_onchain(self.ui_handle.clone()), |_| { - Message::Noop - }) + Command::perform( + Self::async_receive_onchain(self.ui_handle.clone(), id), + |_| Message::Noop, + ) } }, Message::Donate => match self.donate_amount_str.parse::() { @@ -361,9 +375,10 @@ impl HarborWallet { // TODO: don't hardcode this! let hardcoded_donation_address = "tb1qd28npep0s8frcm3y7dxqajkcy2m40eysplyr9v"; let address = Address::from_str(hardcoded_donation_address).unwrap(); + let id = uuid::Uuid::new_v4().to_string(); // todo use this id somewhere Command::perform( - Self::async_send_onchain(self.ui_handle.clone(), address, Some(amount)), + Self::async_send_onchain(self.ui_handle.clone(), id, address, Some(amount)), |_| Message::Noop, ) } @@ -421,7 +436,7 @@ impl HarborWallet { } } // Handle any messages we get from core - Message::CoreMessage(msg) => match msg { + Message::CoreMessage(msg) => match msg.msg { CoreUIMsg::Sending => { self.send_status = SendStatus::Sending; Command::none()