diff --git a/client/asset/dcr/dcr.go b/client/asset/dcr/dcr.go index 00b356299e..9e17109b8c 100644 --- a/client/asset/dcr/dcr.go +++ b/client/asset/dcr/dcr.go @@ -5638,6 +5638,15 @@ func (dcr *ExchangeWallet) monitorBlocks(ctx context.Context) { checkTip() case walletTip := <-walletBlock: + if walletTip == nil { + // Mempool tx seen. + if bal, err := dcr.Balance(); err != nil { + dcr.log.Errorf("Error getting balance after mempool tx notification: %v", err) + } else { + dcr.emit.BalanceChange(bal) + } + continue + } if queuedBlock != nil && walletTip.height >= queuedBlock.height { if !queuedBlock.queue.Stop() && walletTip.hash == queuedBlock.hash { continue diff --git a/client/asset/dcr/spv.go b/client/asset/dcr/spv.go index 080d54a507..ef14d58e48 100644 --- a/client/asset/dcr/spv.go +++ b/client/asset/dcr/spv.go @@ -371,6 +371,13 @@ func (w *spvWallet) notesLoop(ctx context.Context, dcrw *wallet.Wallet) { select { case n := <-txNotes.C: if len(n.AttachedBlocks) == 0 { + if len(n.UnminedTransactions) > 0 { + select { + case w.tipChan <- nil: + default: + w.log.Warnf("tx report channel was blocking") + } + } continue } lastBlock := n.AttachedBlocks[len(n.AttachedBlocks)-1] diff --git a/client/asset/interface.go b/client/asset/interface.go index 32b3b8d6bb..1b930f6692 100644 --- a/client/asset/interface.go +++ b/client/asset/interface.go @@ -1385,6 +1385,13 @@ type TipChangeNote struct { Data any `json:"data"` } +// BalanceChangeNote can be sent when the wallet detects a balance change +// between tip changes. +type BalanceChangeNote struct { + AssetID uint32 + Balance *Balance +} + // CustomWalletNote is any other information the wallet wishes to convey to // the user. type CustomWalletNote struct { @@ -1430,3 +1437,8 @@ func (e *WalletEmitter) TipChange(tip uint64, datas ...any) { } e.emit(&TipChangeNote{AssetID: e.assetID, Tip: tip, Data: data}) } + +// BalanceChange sends a BalanceChangeNote. +func (e *WalletEmitter) BalanceChange(bal *Balance) { + e.emit(&BalanceChangeNote{AssetID: e.assetID, Balance: bal}) +} diff --git a/client/core/core.go b/client/core/core.go index c19b3d398a..df62f28460 100644 --- a/client/core/core.go +++ b/client/core/core.go @@ -2100,16 +2100,20 @@ func (c *Core) updateWalletBalance(wallet *xcWallet) (*WalletBalance, error) { if err != nil { return nil, err } + return walletBal, c.storeAndSendWalletBalance(wallet, walletBal) +} + +func (c *Core) storeAndSendWalletBalance(wallet *xcWallet, walletBal *WalletBalance) error { wallet.setBalance(walletBal) // Store the db.Balance. - err = c.db.UpdateBalance(wallet.dbID, walletBal.Balance) + err := c.db.UpdateBalance(wallet.dbID, walletBal.Balance) if err != nil { - return nil, fmt.Errorf("error updating %s balance in database: %w", unbip(wallet.AssetID), err) + return fmt.Errorf("error updating %s balance in database: %w", unbip(wallet.AssetID), err) } c.notify(newBalanceNote(wallet.AssetID, walletBal)) - return walletBal, nil + return nil } // lockedAmounts returns the total amount locked in unredeemed and unrefunded @@ -9411,6 +9415,25 @@ func (c *Core) handleWalletNotification(ni asset.WalletNotification) { switch n := ni.(type) { case *asset.TipChangeNote: c.tipChange(n.AssetID) + case *asset.BalanceChangeNote: + w, ok := c.wallet(n.AssetID) + if !ok { + return + } + contractLockedAmt, orderLockedAmt, bondLockedAmt := c.lockedAmounts(n.AssetID) + bal := &WalletBalance{ + Balance: &db.Balance{ + Balance: *n.Balance, + Stamp: time.Now(), + }, + OrderLocked: orderLockedAmt, + ContractLocked: contractLockedAmt, + BondLocked: bondLockedAmt, + } + if err := c.storeAndSendWalletBalance(w, bal); err != nil { + c.log.Errorf("Error storing and sending emitted balance: %v", err) + } + return // Notification sent already. } c.notify(newWalletNote(ni)) }