diff --git a/cli/Cargo.lock b/cli/Cargo.lock index 458d0fc15..cd2a178c2 100644 --- a/cli/Cargo.lock +++ b/cli/Cargo.lock @@ -203,19 +203,6 @@ dependencies = [ "secp256k1 0.24.3", ] -[[package]] -name = "bitcoin" -version = "0.30.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1945a5048598e4189e239d3f809b19bdad4845c4b2ba400d304d2dcf26d2c462" -dependencies = [ - "bech32 0.9.1", - "bitcoin-private", - "bitcoin_hashes 0.12.0", - "hex_lit", - "secp256k1 0.27.0", -] - [[package]] name = "bitcoin" version = "0.31.1" @@ -253,15 +240,6 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "90064b8dee6815a6470d60bad07bbbaee885c0e12d04177138fa3291a01b7bc4" -[[package]] -name = "bitcoin_hashes" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d7066118b13d4b20b23645932dfb3a81ce7e29f95726c2036fa33cd7b092501" -dependencies = [ - "bitcoin-private", -] - [[package]] name = "bitcoin_hashes" version = "0.13.0" @@ -290,7 +268,7 @@ dependencies = [ "electrum-client", "elements", "hex", - "lightning-invoice 0.26.0", + "lightning-invoice", "rand_core", "serde", "serde_json", @@ -304,7 +282,6 @@ dependencies = [ "anyhow", "bip39", "boltz-client", - "lightning-invoice 0.29.0", "log", "lwk_common", "lwk_signer", @@ -701,7 +678,6 @@ version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "afc22eff61b133b115c6e8c74e818c628d6d5e7a502afea6f64dee076dd94326" dependencies = [ - "cc", "pkg-config", "vcpkg", ] @@ -715,16 +691,6 @@ dependencies = [ "bitcoin 0.29.2", ] -[[package]] -name = "lightning" -version = "0.0.121" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b0c1f811ae288f86c6767055c55b5f7a721ca1e61bf1897a9ae2ec663e8aba1" -dependencies = [ - "bitcoin 0.30.2", - "hex-conservative", -] - [[package]] name = "lightning-invoice" version = "0.26.0" @@ -734,24 +700,11 @@ dependencies = [ "bech32 0.9.1", "bitcoin 0.29.2", "bitcoin_hashes 0.11.0", - "lightning 0.0.118", + "lightning", "num-traits", "secp256k1 0.24.3", ] -[[package]] -name = "lightning-invoice" -version = "0.29.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b186aca4a605d4db3b85979922be287b9ebd5dedd8132963bb9dbeb8f7d2a04" -dependencies = [ - "bech32 0.9.1", - "bitcoin 0.30.2", - "lightning 0.0.121", - "num-traits", - "secp256k1 0.27.0", -] - [[package]] name = "linux-raw-sys" version = "0.4.13" @@ -1084,7 +1037,6 @@ dependencies = [ "fallible-streaming-iterator", "hashlink", "libsqlite3-sys", - "serde_json", "smallvec", ] @@ -1199,16 +1151,6 @@ dependencies = [ "secp256k1-sys 0.6.1", ] -[[package]] -name = "secp256k1" -version = "0.27.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25996b82292a7a57ed3508f052cfff8640d38d32018784acd714758b43da9c8f" -dependencies = [ - "bitcoin_hashes 0.12.0", - "secp256k1-sys 0.8.1", -] - [[package]] name = "secp256k1" version = "0.28.2" @@ -1230,15 +1172,6 @@ dependencies = [ "cc", ] -[[package]] -name = "secp256k1-sys" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70a129b9e9efbfb223753b9163c4ab3b13cff7fd9c7f010fbac25ab4099fa07e" -dependencies = [ - "cc", -] - [[package]] name = "secp256k1-sys" version = "0.9.2" diff --git a/cli/src/commands.rs b/cli/src/commands.rs index f79611d20..4489fa0ac 100644 --- a/cli/src/commands.rs +++ b/cli/src/commands.rs @@ -16,6 +16,8 @@ pub(crate) enum Command { SendPayment { bolt11: String }, /// Receive lbtc and send btc through a swap ReceivePayment { amount_sat: u64 }, + /// List incoming and outgoing payments + ListPayments, /// Get the balance of the currently loaded wallet GetInfo, } @@ -56,7 +58,7 @@ pub(crate) async fn handle_command( response.txid )) } - Command::GetInfo {} => { + Command::GetInfo => { let info = wallet.get_info(true)?; Ok(format!( @@ -64,5 +66,26 @@ pub(crate) async fn handle_command( info.balance_sat, info.pubkey, info.active_address )) } + Command::ListPayments => { + let payments_str = wallet + .list_payments(true, true)? + .iter() + .map(|tx| { + format!( + "Id: {} | Type: {} | Amount: {} sat | Timestamp: {}", + tx.id.clone().unwrap_or("None".to_string()), + tx.payment_type.to_string(), + tx.amount_sat, + match tx.timestamp { + Some(t) => t.to_string(), + None => "None".to_string(), + }, + ) + }) + .collect::>() + .join("\n"); + + Ok(payments_str) + } } } diff --git a/lib/Cargo.lock b/lib/Cargo.lock index 0df8047aa..7a5afd358 100644 --- a/lib/Cargo.lock +++ b/lib/Cargo.lock @@ -67,9 +67,9 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "1.1.2" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" dependencies = [ "memchr", ] @@ -205,9 +205,9 @@ dependencies = [ [[package]] name = "bitflags" -version = "2.4.2" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf" +checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" [[package]] name = "boltz-client" @@ -963,9 +963,9 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.13.1" +version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" [[package]] name = "spin" diff --git a/lib/src/model.rs b/lib/src/model.rs index 4c1b5cd05..d3639c182 100644 --- a/lib/src/model.rs +++ b/lib/src/model.rs @@ -78,6 +78,9 @@ pub enum SwapError { #[error("Could not store the swap details locally")] PersistError, + #[error("The generated preimage is not valid")] + InvalidPreimage, + #[error("Generic boltz error: {err}")] BoltzGeneric { err: String }, } @@ -106,4 +109,29 @@ pub struct OngoingSwap { pub preimage: String, pub redeem_script: String, pub blinding_key: String, + pub invoice_amount_sat: u64, +} + +pub enum PaymentType { + Sent, + Received, + PendingReceive, +} + +impl ToString for PaymentType { + fn to_string(&self) -> String { + match self { + PaymentType::Sent => "Sent", + PaymentType::Received => "Received", + PaymentType::PendingReceive => "Pending Receive", + } + .to_string() + } +} + +pub struct Payment { + pub id: Option, + pub timestamp: Option, + pub amount_sat: u64, + pub payment_type: PaymentType, } diff --git a/lib/src/persist/migrations.rs b/lib/src/persist/migrations.rs index e3ef99f38..5c59612bc 100644 --- a/lib/src/persist/migrations.rs +++ b/lib/src/persist/migrations.rs @@ -4,7 +4,8 @@ pub(crate) fn current_migrations() -> Vec<&'static str> { id TEXT NOT NULL PRIMARY KEY, preimage TEXT NOT NULL, redeem_script TEXT NOT NULL, - blinding_key TEXT NOT NULL + blinding_key TEXT NOT NULL, + invoice_amount_sat INTEGER ) STRICT;", ] } diff --git a/lib/src/persist/mod.rs b/lib/src/persist/mod.rs index cb8d674a7..da3785c3e 100644 --- a/lib/src/persist/mod.rs +++ b/lib/src/persist/mod.rs @@ -44,9 +44,10 @@ impl Persister { id, preimage, redeem_script, - blinding_key + blinding_key, + invoice_amount_sat ) - VALUES (?, ?, ?, ?) + VALUES (?, ?, ?, ?, ?) ", )?; @@ -56,6 +57,7 @@ impl Persister { &swap.preimage, &swap.redeem_script, &swap.blinding_key, + &swap.invoice_amount_sat, ))? } @@ -90,6 +92,7 @@ impl Persister { preimage: row.get(1)?, redeem_script: row.get(2)?, blinding_key: row.get(3)?, + invoice_amount_sat: row.get(4)?, }) } } diff --git a/lib/src/wallet.rs b/lib/src/wallet.rs index 6a6595ae2..5dc652ed5 100644 --- a/lib/src/wallet.rs +++ b/lib/src/wallet.rs @@ -23,8 +23,8 @@ use lwk_wollet::{ }; use crate::{ - persist::Persister, Network, OngoingSwap, SendPaymentResponse, SwapError, SwapLbtcResponse, - WalletInfo, WalletOptions, + persist::Persister, Network, OngoingSwap, Payment, PaymentType, SendPaymentResponse, SwapError, + SwapLbtcResponse, WalletInfo, WalletOptions, }; // To avoid sendrawtransaction error "min relay fee not met" @@ -294,6 +294,7 @@ impl Wallet { let lsk = LiquidSwapKey::from(swap_key); let preimage = Preimage::new(); + let preimage_str = preimage.to_string().ok_or(SwapError::InvalidPreimage)?; let preimage_hash = preimage.sha256.to_string(); let swap_response = client.create_swap(CreateSwapRequest::new_lbtc_reverse_invoice_amt( @@ -323,9 +324,10 @@ impl Wallet { self.swap_persister .insert_ongoing_swaps(&[OngoingSwap { id: swap_id.clone(), - preimage: preimage.to_string().expect("Expecting valid preimage"), + preimage: preimage_str, blinding_key: blinding_str, redeem_script, + invoice_amount_sat: amount_sat, }]) .map_err(|_| SwapError::PersistError)?; @@ -335,6 +337,49 @@ impl Wallet { }) } + pub fn list_payments(&self, with_scan: bool, include_pending: bool) -> Result> { + if with_scan { + self.scan()?; + } + + let transactions = self.wallet.lock().unwrap().transactions()?; + + let mut payments: Vec = transactions + .iter() + .map(|tx| { + let amount_sat = tx.balance.values().sum::(); + + Payment { + id: Some(tx.tx.txid().to_string()), + timestamp: tx.timestamp, + amount_sat: amount_sat.unsigned_abs(), + payment_type: match amount_sat >= 0 { + true => PaymentType::Received, + false => PaymentType::Sent, + }, + } + }) + .collect(); + + if include_pending { + let pending_swaps = self.swap_persister.list_ongoing_swaps()?; + + for swap in pending_swaps { + payments.insert( + 0, + Payment { + id: None, + timestamp: None, + payment_type: PaymentType::PendingReceive, + amount_sat: swap.invoice_amount_sat, + }, + ); + } + } + + Ok(payments) + } + pub fn recover_funds(&self, recovery: &LBtcReverseRecovery) -> Result { let script: LBtcSwapScript = recovery.try_into().unwrap(); let network_config = self.get_network_config();