diff --git a/node-manager/src/background.rs b/node-manager/src/background.rs index 355f879dc..dd9cd7e85 100644 --- a/node-manager/src/background.rs +++ b/node-manager/src/background.rs @@ -451,8 +451,8 @@ impl BackgroundProcessor { { let stop_thread = Arc::new(AtomicBool::new(false)); let stop_thread_clone = stop_thread.clone(); - let _ = spawn_local(async move { - let _ = define_run_body!( + spawn_local(async move { + define_run_body!( persister, event_handler, chain_monitor, diff --git a/node-manager/src/error.rs b/node-manager/src/error.rs index d96a8f5b4..8511f1ad9 100644 --- a/node-manager/src/error.rs +++ b/node-manager/src/error.rs @@ -1,5 +1,6 @@ use bdk::esplora_client; use lightning::ln::peer_handler::PeerHandleError; +use lightning_invoice::payment::PaymentError; use thiserror::Error; use wasm_bindgen::JsValue; @@ -114,6 +115,16 @@ impl From for MutinyError { } } +impl From for MutinyError { + fn from(e: PaymentError) -> Self { + match e { + PaymentError::Invoice(_) => Self::InvoiceInvalid, + PaymentError::Routing(_) => Self::RoutingFailed, + PaymentError::Sending(_) => Self::RoutingFailed, + } + } +} + impl From for bdk::Error { fn from(e: MutinyStorageError) -> Self { match e { @@ -232,6 +243,16 @@ impl From for MutinyJsError { } } +impl From for MutinyJsError { + fn from(e: PaymentError) -> Self { + match e { + PaymentError::Invoice(_) => Self::InvoiceInvalid, + PaymentError::Routing(_) => Self::RoutingFailed, + PaymentError::Sending(_) => Self::RoutingFailed, + } + } +} + impl From for MutinyJsError { fn from(_e: esplora_client::Error) -> Self { // This is most likely a chain access failure diff --git a/node-manager/src/event.rs b/node-manager/src/event.rs index d1a5a9be0..8d9d8af86 100644 --- a/node-manager/src/event.rs +++ b/node-manager/src/event.rs @@ -21,6 +21,7 @@ pub(crate) struct PaymentInfo { pub secret: Option<[u8; 32]>, pub status: HTLCStatus, pub amt_msat: MillisatAmount, + pub fee_paid_msat: Option, } #[derive(Serialize, Deserialize)] @@ -97,11 +98,11 @@ impl LdkEventHandler for EventHandler { .to_address(); let wallet_thread = self.wallet.clone(); - let channel_values_satoshis_thread = channel_value_satoshis.clone(); + let channel_values_satoshis_thread = *channel_value_satoshis; let channel_manager_thread = self.channel_manager.clone(); let logger_thread = self.logger.clone(); - let temporary_channel_id_thread = temporary_channel_id.clone(); - let counterparty_node_id_thread = counterparty_node_id.clone(); + let temporary_channel_id_thread = *temporary_channel_id; + let counterparty_node_id_thread = *counterparty_node_id; spawn_local(async move { let psbt = match wallet_thread .create_signed_psbt(addr, channel_values_satoshis_thread, None) @@ -239,6 +240,7 @@ impl LdkEventHandler for EventHandler { secret: payment_secret, status: HTLCStatus::Succeeded, amt_msat: MillisatAmount(Some(*amount_msat)), + fee_paid_msat: None, }; match self .persister @@ -261,6 +263,7 @@ impl LdkEventHandler for EventHandler { Event::PaymentSent { payment_preimage, payment_hash, + fee_paid_msat, .. } => { self.logger.log(&Record::new( @@ -271,14 +274,15 @@ impl LdkEventHandler for EventHandler { 0, )); - match self.persister.read_payment_info(*payment_hash, true) { + match self.persister.read_payment_info(*payment_hash, false) { Some(mut saved_payment_info) => { saved_payment_info.status = HTLCStatus::Succeeded; saved_payment_info.preimage = Some(payment_preimage.0); + saved_payment_info.fee_paid_msat = *fee_paid_msat; match self.persister.persist_payment_info( *payment_hash, saved_payment_info, - true, + false, ) { Ok(_) => (), Err(e) => { @@ -359,13 +363,13 @@ impl LdkEventHandler for EventHandler { 0, )); - match self.persister.read_payment_info(*payment_hash, true) { + match self.persister.read_payment_info(*payment_hash, false) { Some(mut saved_payment_info) => { saved_payment_info.status = HTLCStatus::Failed; match self.persister.persist_payment_info( *payment_hash, saved_payment_info, - true, + false, ) { Ok(_) => (), Err(e) => { diff --git a/node-manager/src/localstorage.rs b/node-manager/src/localstorage.rs index 462f0e2b6..91d83ccef 100644 --- a/node-manager/src/localstorage.rs +++ b/node-manager/src/localstorage.rs @@ -34,10 +34,10 @@ impl MutinyBrowserStorage { let data = serde_json::to_string(&value)?; // Only bother encrypting if a password is set if self.password.is_empty() { - return Ok(LocalStorage::set(key, data)?); + Ok(LocalStorage::set(key, data)?) } else { let ciphertext = encrypt(data.as_str(), self.password.as_str()); - return Ok(LocalStorage::set(key, ciphertext)?); + Ok(LocalStorage::set(key, ciphertext)?) } } @@ -49,10 +49,10 @@ impl MutinyBrowserStorage { let data: String = LocalStorage::get(key)?; // Only bother decrypting if a password is set if self.password.is_empty() { - return Ok(serde_json::from_str::(data.as_str())?); + Ok(serde_json::from_str::(data.as_str())?) } else { let decrypted_data = decrypt(data.as_str(), self.password.as_str()); - return Ok(serde_json::from_str::(decrypted_data.as_str())?); + Ok(serde_json::from_str::(decrypted_data.as_str())?) } } diff --git a/node-manager/src/node.rs b/node-manager/src/node.rs index 80fc0d1c0..504b5d354 100644 --- a/node-manager/src/node.rs +++ b/node-manager/src/node.rs @@ -92,7 +92,7 @@ pub struct Node { pub chain_monitor: Arc, pub invoice_payer: Arc>, network: Network, - persister: Arc, + pub persister: Arc, _background_processor: BackgroundProcessor, logger: Arc, } @@ -309,7 +309,7 @@ impl Node { route_hints: Vec, ) -> Result { let invoice = match create_phantom_invoice::>( - Some(amount_sat * 1), + Some(amount_sat * 1_000), None, description, 1500, @@ -345,6 +345,7 @@ impl Node { secret: Some(invoice.payment_secret().0), status: HTLCStatus::Pending, amt_msat: MillisatAmount(Some(amount_sat * 1000)), + fee_paid_msat: None, }; match self .persister diff --git a/node-manager/src/nodemanager.rs b/node-manager/src/nodemanager.rs index 7614aca1a..d8ff0d115 100644 --- a/node-manager/src/nodemanager.rs +++ b/node-manager/src/nodemanager.rs @@ -78,7 +78,7 @@ pub struct MutinyInvoice { payment_hash: String, preimage: Option, pub amount_sats: Option, - pub expire: Option, + pub expire: u64, pub paid: bool, pub fees_paid: Option, pub is_send: bool, @@ -114,13 +114,16 @@ impl From for MutinyInvoice { InvoiceDescription::Hash(_) => None, }; + let timestamp = value.duration_since_epoch().as_secs(); + let expiry = timestamp + value.expiry_time().as_secs(); + MutinyInvoice { bolt11: value.to_string(), description, payment_hash: value.payment_hash().to_owned().to_hex(), preimage: None, amount_sats: value.amount_milli_satoshis().map(|m| m / 1000), - expire: None, // todo + expire: expiry, paid: false, fees_paid: None, // todo is_send: false, // todo this could be bad @@ -245,7 +248,7 @@ impl NodeManager { let id = node .keys_manager .get_node_id(Recipient::Node) - .expect(format!("Failed to get node id for {}", node_item.0).as_str()); + .expect("Failed to get node id"); nodes_map.insert(id.to_hex(), Arc::new(node)); } @@ -513,6 +516,8 @@ impl NodeManager { let invoice = Invoice::from_str(invoice_str.as_str()).map_err(|_| MutinyJsError::InvoiceInvalid)?; + + // todo ensure payment hash is unique let pay_result = node.invoice_payer.pay_invoice(&invoice); match pay_result { @@ -544,23 +549,9 @@ impl NodeManager { let amt_msats = amt_sats * 1000; - let chans = node.channel_manager.list_channels(); - let chan = chans.first().unwrap(); - let usable = node.channel_manager.list_usable_channels(); - - info!( - "confirmations_required: {}", - chan.confirmations_required.unwrap_or(69) - ); - info!("is_channel_ready: {}", chan.is_channel_ready); - info!("is_usable: {}", chan.is_usable); - info!("is_public: {}", chan.is_public); - info!("usable: {}", usable.len()); - let _ = node .invoice_payer - .pay_pubkey(node_id, preimage, amt_msats, 40) - .unwrap(); + .pay_pubkey(node_id, preimage, amt_msats, 40)?; Ok(info!("Keysend successful!")) }