diff --git a/cli/src/command.rs b/cli/src/command.rs index 5250324..adcf285 100644 --- a/cli/src/command.rs +++ b/cli/src/command.rs @@ -96,7 +96,7 @@ pub enum Command { #[clap(short = '2')] v2: bool, - /// Bitcoin invoice, either in form of `@
`. To spend full wallet balance use + /// Bitcoin invoice in form of `@
`. To spend full wallet balance use /// `MAX` for the amount. invoice: Invoice, @@ -192,6 +192,7 @@ impl Exec for Args { addr: false, utxo: false, }; + self.resolver.sync = false; self.exec(config, name)?; } Command::Balance { @@ -210,6 +211,7 @@ impl Exec for Args { addr: false, utxo: false, }; + self.resolver.sync = false; self.exec(config, name)?; } Command::Balance { @@ -229,6 +231,7 @@ impl Exec for Args { addr: false, utxo: false, }; + self.resolver.sync = false; self.exec(config, name)?; } Command::Addr { diff --git a/src/data.rs b/src/data.rs index 37bb8b2..0a34827 100644 --- a/src/data.rs +++ b/src/data.rs @@ -146,6 +146,15 @@ impl Inpoint { pub fn new(txid: Txid, vin: u32) -> Self { Inpoint { txid, vin } } } +impl From for Inpoint { + fn from(outpoint: Outpoint) -> Self { + Inpoint { + txid: outpoint.txid, + vin: outpoint.vout.into_u32(), + } + } +} + #[derive(Clone, Eq, PartialEq, Debug, Display, From, Error)] #[display(doc_comments)] pub enum InpointParseError { @@ -242,6 +251,12 @@ impl Party { _ => None, } } + pub fn from_wallet_addr(wallet_addr: &WalletAddr) -> Self { + Party::Wallet(DerivedAddr { + addr: wallet_addr.addr, + terminal: wallet_addr.terminal, + }) + } } impl Display for Party { diff --git a/src/indexers/esplora.rs b/src/indexers/esplora.rs index e2bc6fe..37ce192 100644 --- a/src/indexers/esplora.rs +++ b/src/indexers/esplora.rs @@ -28,7 +28,6 @@ use descriptors::Descriptor; use esplora::{BlockingClient, Error}; use super::BATCH_SIZE; -use crate::data::Inpoint; use crate::{ Indexer, Layer2, MayError, MiningInfo, Party, TxCredit, TxDebit, TxStatus, WalletAddr, WalletCache, WalletDescr, WalletTx, @@ -133,64 +132,72 @@ impl Indexer for BlockingClient { } } - address_index.insert(script, (derive, txids)); + let wallet_addr = WalletAddr::::from(derive); + address_index.insert(script, (wallet_addr, txids)); } } // TODO: Update headers & tip - for (script, (addr_info, txids)) in address_index { - let mut wallet_addr = WalletAddr::::from(addr_info.clone()); + for (script, (wallet_addr, txids)) in &mut address_index { for txid in txids { - let mut tx = cache.tx.remove(&txid).expect("broken logic"); - for (vin, credit) in tx.inputs.iter_mut().enumerate() { - let Party::Unknown(ref s) = credit.payer else { + let mut tx = cache.tx.remove(txid).expect("broken logic"); + for debit in &mut tx.outputs { + let Party::Unknown(ref s) = debit.beneficiary else { continue; }; - if s == &script { - credit.payer = Party::Wallet(addr_info.clone()); + if s == script { + cache.utxo.insert(debit.outpoint); + debit.beneficiary = Party::from_wallet_addr(wallet_addr); + wallet_addr.used = wallet_addr.used.saturating_add(1); + wallet_addr.volume.saturating_add_assign(debit.value); wallet_addr.balance = wallet_addr .balance - .saturating_sub(credit.value.sats().try_into().expect("sats overflow")); + .saturating_add(debit.value.sats().try_into().expect("sats overflow")); } else { Address::with(s, descriptor.chain()) .map(|addr| { - credit.payer = Party::Counterparty(addr); + debit.beneficiary = Party::Counterparty(addr); }) .ok(); } - if let Some(prev_tx) = cache.tx.get_mut(&credit.outpoint.txid) { - prev_tx - .outputs - .get_mut(credit.outpoint.vout_u32() as usize) - .map(|vout| vout.spent = Some(Inpoint::new(tx.txid, vin as u32))); - } } - for debit in &mut tx.outputs { - let Party::Unknown(ref s) = debit.beneficiary else { + cache.tx.insert(tx.txid, tx); + } + } + + for (script, (wallet_addr, txids)) in &mut address_index { + for txid in txids { + let mut tx = cache.tx.remove(txid).expect("broken logic"); + for credit in &mut tx.inputs { + let Party::Unknown(ref s) = credit.payer else { continue; }; - if s == &script { - cache.utxo.insert(debit.outpoint); - debit.beneficiary = Party::Wallet(addr_info.clone()); - wallet_addr.used = wallet_addr.used.saturating_add(1); - wallet_addr.volume.saturating_add_assign(debit.value); + if s == script { + credit.payer = Party::from_wallet_addr(wallet_addr); wallet_addr.balance = wallet_addr .balance - .saturating_add(debit.value.sats().try_into().expect("sats overflow")); + .saturating_sub(credit.value.sats().try_into().expect("sats overflow")); } else { Address::with(s, descriptor.chain()) .map(|addr| { - debit.beneficiary = Party::Counterparty(addr); + credit.payer = Party::Counterparty(addr); }) .ok(); } + if let Some(prev_tx) = cache.tx.get_mut(&credit.outpoint.txid) { + prev_tx.outputs.get_mut(credit.outpoint.vout_u32() as usize).map(|txout| { + let outpoint = txout.outpoint; + cache.utxo.remove(&outpoint); + txout.spent = Some(credit.outpoint.into()) + }); + } } cache.tx.insert(tx.txid, tx); } cache .addr - .entry(addr_info.terminal.keychain) + .entry(wallet_addr.terminal.keychain) .or_default() .insert(wallet_addr.expect_transmute()); }