Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Clean up UI <> Core messages #14

Merged
merged 1 commit into from
May 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 19 additions & 12 deletions src/bridge.rs
Original file line number Diff line number Diff line change
@@ -1,26 +1,37 @@
use bitcoin::Txid;
use fedimint_core::api::InviteCode;
use fedimint_core::Amount;
use fedimint_ln_common::lightning_invoice::Bolt11Invoice;
use tokio::sync::mpsc;

#[derive(Debug, Clone)]
pub enum UICoreMsg {
Test(u64),
FakeSend(u64),
Send(Bolt11Invoice),
Receive(u64),
SendLightning(Bolt11Invoice),
ReceiveLightning(Amount),
AddFederation(InviteCode),
Unlock(String),
}

#[derive(Debug, Clone, PartialEq)]
pub enum SendSuccessMsg {
Lightning { preimage: [u8; 32] },
Onchain { txid: Txid },
}

#[derive(Debug, Clone, PartialEq)]
pub enum ReceiveSuccessMsg {
Lightning,
Onchain { txid: Txid },
}

#[derive(Debug, Clone)]
pub enum CoreUIMsg {
Sending,
SendSuccess,
SendSuccess(SendSuccessMsg),
SendFailure(String),
ReceiveInvoiceGenerating,
ReceiveInvoiceGenerated(Bolt11Invoice),
ReceiveSuccess,
ReceiveSuccess(ReceiveSuccessMsg),
ReceiveFailed(String),
BalanceUpdated(Amount),
AddFederationFailed(String),
Expand All @@ -45,16 +56,12 @@ impl UIHandle {
self.ui_to_core_tx.send(msg).await.unwrap();
}

pub async fn fake_send(&self, amount: u64) {
self.msg_send(UICoreMsg::FakeSend(amount)).await;
}

pub async fn send(&self, invoice: Bolt11Invoice) {
self.msg_send(UICoreMsg::Send(invoice)).await;
self.msg_send(UICoreMsg::SendLightning(invoice)).await;
}

pub async fn receive(&self, amount: u64) {
self.msg_send(UICoreMsg::Receive(amount)).await;
self.msg_send(UICoreMsg::ReceiveLightning(Amount::from_sats(amount))).await;
}

pub async fn unlock(&self, password: String) {
Expand Down
46 changes: 9 additions & 37 deletions src/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,14 @@ use std::collections::HashMap;
use std::path::PathBuf;
use std::str::FromStr;
use std::sync::atomic::AtomicBool;
use std::{sync::Arc, time::Duration};
use std::sync::Arc;

use iced::{
futures::{channel::mpsc::Sender, SinkExt},
subscription::{self, Subscription},
};
use log::error;
use tokio::sync::RwLock;
use tokio::time::sleep;

use crate::{
bridge::{self, CoreUIMsg, UICoreMsg},
Expand Down Expand Up @@ -64,32 +63,12 @@ impl HarborCore {
self.msg(CoreUIMsg::BalanceUpdated(self.balance)).await;
}

async fn fake_send(&mut self, amount: u64) {
self.msg(CoreUIMsg::Sending).await;
sleep(Duration::from_secs(1)).await;
println!("Sending {amount}");

let amount = Amount::from_sats(amount);
if amount > self.balance {
self.msg(CoreUIMsg::SendFailure("Insufficient funds".to_string()))
.await;
return;
}

// Save it in our struct
self.balance = self.balance.saturating_sub(amount);
// Tell the UI we did a good job
self.msg(CoreUIMsg::SendSuccess).await;
// Tell the UI the new balance
self.msg(CoreUIMsg::BalanceUpdated(self.balance)).await;
}

// todo for now just use the first client, but eventually we'll want to have a way to select a client
async fn get_client(&self) -> FedimintClient {
self.clients.read().await.values().next().unwrap().clone()
}

async fn send(&self, invoice: Bolt11Invoice) -> anyhow::Result<()> {
async fn send_lightning(&self, invoice: Bolt11Invoice) -> 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 lightning_module = client.get_first_module::<LightningClientModule>();
Expand Down Expand Up @@ -118,7 +97,7 @@ impl HarborCore {
Ok(())
}

async fn receive(&self, amount: u64) -> anyhow::Result<Bolt11Invoice> {
async fn receive_lightning(&self, amount: Amount) -> anyhow::Result<Bolt11Invoice> {
let client = self.get_client().await.fedimint_client;
let lightning_module = client.get_first_module::<LightningClientModule>();

Expand All @@ -129,7 +108,7 @@ impl HarborCore {
let desc = Description::new(String::new()).expect("empty string is valid");
let (op_id, invoice, _) = lightning_module
.create_bolt11_invoice(
Amount::from_sats(amount),
amount,
Bolt11InvoiceDescription::Direct(&desc),
None,
(),
Expand Down Expand Up @@ -221,7 +200,7 @@ pub fn run_core() -> Subscription<Message> {
balance += client.fedimint_client.get_balance().await;
}

let mut core = HarborCore {
let core = HarborCore {
balance,
tx,
mnemonic,
Expand All @@ -246,24 +225,17 @@ pub fn run_core() -> Subscription<Message> {

if let Some(msg) = msg {
match msg {
UICoreMsg::Test(counter) => {
println!("{counter}");
}
UICoreMsg::FakeSend(amount) => {
core.fake_send(amount).await;
}
UICoreMsg::Send(invoice) => {
UICoreMsg::SendLightning(invoice) => {
log::info!("Got UICoreMsg::Send");
core.msg(CoreUIMsg::Sending).await;
if let Err(e) = core.send(invoice).await {
if let Err(e) = core.send_lightning(invoice).await {
error!("Error sending: {e}");
core.msg(CoreUIMsg::SendFailure(e.to_string())).await;
}
core.msg(CoreUIMsg::SendSuccess).await;
}
UICoreMsg::Receive(amount) => {
UICoreMsg::ReceiveLightning(amount) => {
core.msg(CoreUIMsg::ReceiveInvoiceGenerating).await;
match core.receive(amount).await {
match core.receive_lightning(amount).await {
Err(e) => {
core.msg(CoreUIMsg::ReceiveFailed(e.to_string())).await;
}
Expand Down
21 changes: 15 additions & 6 deletions src/fedimint_client.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use crate::bridge::CoreUIMsg;
use crate::bridge::{CoreUIMsg, ReceiveSuccessMsg, SendSuccessMsg};
use crate::Message;
use bip39::Mnemonic;
use bitcoin::hashes::hex::FromHex;
use bitcoin::Network;
use fedimint_bip39::Bip39RootSecretStrategy;
use fedimint_client::oplog::UpdateStreamOrOutcome;
Expand Down Expand Up @@ -204,7 +205,9 @@ pub(crate) async fn spawn_invoice_receive_subscription(
LnReceiveState::Claimed => {
info!("Payment claimed");
sender
.send(Message::CoreMessage(CoreUIMsg::ReceiveSuccess))
.send(Message::CoreMessage(CoreUIMsg::ReceiveSuccess(
ReceiveSuccessMsg::Lightning,
)))
.await
.unwrap();

Expand Down Expand Up @@ -247,10 +250,13 @@ pub(crate) async fn spawn_invoice_payment_subscription(
.await
.unwrap();
}
LnPayState::Success { preimage: _ } => {
LnPayState::Success { preimage } => {
info!("Payment success");
let preimage: [u8; 32] =
FromHex::from_hex(&preimage).expect("Invalid preimage");
let params = SendSuccessMsg::Lightning { preimage };
sender
.send(Message::CoreMessage(CoreUIMsg::SendSuccess))
.send(Message::CoreMessage(CoreUIMsg::SendSuccess(params)))
.await
.unwrap();

Expand Down Expand Up @@ -293,10 +299,13 @@ pub(crate) async fn spawn_internal_payment_subscription(
.await
.unwrap();
}
InternalPayState::Preimage(_preimage) => {
InternalPayState::Preimage(preimage) => {
info!("Payment success");
let params = SendSuccessMsg::Lightning {
preimage: preimage.0,
};
sender
.send(Message::CoreMessage(CoreUIMsg::SendSuccess))
.send(Message::CoreMessage(CoreUIMsg::SendSuccess(params)))
.await
.unwrap();

Expand Down
25 changes: 10 additions & 15 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use iced::widget::row;
use iced::Element;
use iced::{clipboard, program, Color};
use iced::{Command, Font};
use log::info;

pub mod bridge;
pub mod components;
Expand Down Expand Up @@ -133,16 +134,6 @@ impl HarborWallet {
run_core()
}

// We can't use self in these async functions because lifetimes are hard
#[allow(dead_code)] // TODO: remove
async fn async_fake_send(ui_handle: Option<Arc<bridge::UIHandle>>, amount: u64) {
if let Some(ui_handle) = ui_handle {
ui_handle.clone().fake_send(amount).await;
} else {
panic!("UI handle is None");
}
}

async fn async_send(ui_handle: Option<Arc<bridge::UIHandle>>, invoice: Bolt11Invoice) {
println!("Got to async_send");
if let Some(ui_handle) = ui_handle {
Expand Down Expand Up @@ -260,7 +251,8 @@ impl HarborWallet {
self.send_status = SendStatus::Sending;
Command::none()
}
CoreUIMsg::SendSuccess => {
CoreUIMsg::SendSuccess(params) => {
info!("Send success: {params:?}");
self.send_status = SendStatus::Idle;
Command::none()
}
Expand All @@ -269,11 +261,14 @@ impl HarborWallet {
self.send_failure_reason = Some(reason);
Command::none()
}
CoreUIMsg::ReceiveSuccess => Command::none(),
CoreUIMsg::ReceiveSuccess(params) => {
info!("Receive success: {params:?}");
self.receive_status = ReceiveStatus::Idle;
Command::none()
},
CoreUIMsg::ReceiveFailed(reason) => {
// todo use receive failure reason
self.send_status = SendStatus::Idle;
self.send_failure_reason = Some(reason);
self.receive_status = ReceiveStatus::Idle;
self.receive_failure_reason = Some(reason);
Command::none()
}
CoreUIMsg::BalanceUpdated(balance) => {
Expand Down