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

Update balance and tx history when new tx is registered. Clean up listener structure between parent and subpage #733

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
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
4 changes: 2 additions & 2 deletions .github/workflows/go.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ jobs:
runs-on: ubuntu-20.04
steps:
- name: Check out code into the Go module directory
uses: actions/checkout@v1
uses: actions/checkout@v3

- name: Set up Go 1.21
uses: actions/setup-go@v3
Expand All @@ -24,7 +24,7 @@ jobs:
cp "./libwallet/instantswap/instant_example.json" "./libwallet/instantswap/instant.json"

- name: Cache (dependencies)
uses: actions/cache@v1
uses: actions/cache@v4
id: cache
with:
path: ~/go/pkg/mod
Expand Down
15 changes: 9 additions & 6 deletions libwallet/assets_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -1060,14 +1060,15 @@ func (mgr *AssetsManager) DeleteDEXData() error {
return os.Remove(dexDBFile)
}

func (mgr *AssetsManager) WatchBalanceChange(listen func()) {
// Listen when new tx is registered
func (mgr *AssetsManager) ListenForTxAndBlockNotification(listen func(int)) {
// Reload total balance on new tx.
txAndBlockNotificationListener := &sharedW.TxAndBlockNotificationListener{
OnTransactionConfirmed: func(_ int, _ string, _ int32) {
listen()
OnTransactionConfirmed: func(walletID int, _ string, _ int32) {
listen(walletID)
},
OnTransaction: func(_ int, _ *sharedW.Transaction) {
listen()
OnTransaction: func(walletID int, _ *sharedW.Transaction) {
listen(walletID)
},
}

Expand All @@ -1079,8 +1080,10 @@ func (mgr *AssetsManager) WatchBalanceChange(listen func()) {
}
}
}
}

// add rate listener
// Listen when rate changes
func (mgr *AssetsManager) ListenForRate(listen func()) {
rateListener := &ext.RateListener{
OnRateUpdated: func() {
listen()
Expand Down
11 changes: 9 additions & 2 deletions ui/page/components/items_scroll.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,20 +83,27 @@ func (s *Scroll[T]) SetIsHaveKeySearch(isHaveKeySearch bool) {
// FetchScrollData is a mutex protected fetchScrollData function. At the end of
// the function call a window reload is triggered. Returns that latest records.
func (s *Scroll[T]) FetchScrollData(isScrollUp bool, window app.WindowNavigator, isResetList bool) {
s.FetchScrollDataHandler(isScrollUp, window, isResetList, false)
}

// isResetList = false and loadNewItem = true: Reloads the item list but does not alter the current scroll position
func (s *Scroll[T]) FetchScrollDataHandler(isScrollUp bool, window app.WindowNavigator, isResetList, loadNewItem bool) {
s.mu.Lock()
// s.data is not nil when moving from details page to list page.
if s.data != nil {
s.isLoadingItems = false
}

if isResetList {
if isResetList || loadNewItem {
s.loadedAllItems = false
s.isLoadingItems = false
s.offset = 0
s.itemsCount = -1
s.data = nil
s.cacheData = nil
s.list.Position.Offset = 0
if isResetList {
s.list.Position.Offset = 0
}
}
s.mu.Unlock()
if s.data == nil || len(s.data.items) == 0 {
Expand Down
8 changes: 8 additions & 0 deletions ui/page/info/info_page.go
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,14 @@ func (pg *WalletInfo) reloadMixerBalances() {
}
}

// Reload tx list when there is new tx. Called from parent page
func (pg *WalletInfo) ListenForNewTx(walletID int) {
if walletID != pg.wallet.GetWalletID() {
return
}
pg.loadTransactions()
}

func (pg *WalletInfo) loadTransactions() {
pg.showMaterialLoader = true
mapInfo, _ := components.TxPageDropDownFields(pg.wallet.GetAssetType(), 0)
Expand Down
25 changes: 23 additions & 2 deletions ui/page/root/home_page.go
Original file line number Diff line number Diff line change
Expand Up @@ -212,12 +212,33 @@ func (hp *HomePage) OnNavigatedTo() {
if hp.isUpdateAPIAllowed() {
go hp.checkForUpdates()
}

hp.AssetsManager.WatchBalanceChange(func() {
// When the new tx has been registered
hp.AssetsManager.ListenForTxAndBlockNotification(func(walletID int) {
go hp.CalculateAssetsUSDBalance()
go hp.UpdateSubpageWhenHasNewTx(walletID)
})
// When rate change
hp.AssetsManager.ListenForRate(func() {
go hp.CalculateAssetsUSDBalance()
})
}

// Call the update function for subpages when there is a new tx
func (hp *HomePage) UpdateSubpageWhenHasNewTx(walletID int) {
switch hp.CurrentPageID() {
// if overview page
case OverviewPageID:
hp.CurrentPage().(*OverviewPage).ListenForNewTx()
return
// if transactions history page
case transaction.TransactionsPageID:
hp.CurrentPage().(*transaction.TransactionsPage).ListenForTxNotification(walletID)
return
default:
return
}
}

// initDEX initializes a new dex client if dex is not ready. If a dex client has
// never been created before, initDEX will return early and do nothing.
func (hp *HomePage) initDEX() {
Expand Down
7 changes: 7 additions & 0 deletions ui/page/root/overview_page.go
Original file line number Diff line number Diff line change
Expand Up @@ -1122,6 +1122,13 @@ func (pg *OverviewPage) txAndWallet(mtx *multiWalletTx) (*sharedW.Transaction, s
return mtx.Transaction, pg.AssetsManager.WalletWithID(mtx.walletID)
}

// Update balance/USD balance and transaction list when there is a new tx
func (pg *OverviewPage) ListenForNewTx() {
pg.loadTransactions()
pg.updateAssetsSliders()
pg.updateAssetsUSDBalance()
}

func (pg *OverviewPage) updateAssetsUSDBalance() {
if pg.AssetsManager.ExchangeRateFetchingEnabled() {
assetsTotalUSDBalance, err := pg.AssetsManager.CalculateAssetsUSDBalance(pg.assetsTotalBalance)
Expand Down
27 changes: 5 additions & 22 deletions ui/page/transaction/transactions_page.go
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,6 @@ func (pg *TransactionsPage) DisableUniformTab() {
func (pg *TransactionsPage) OnNavigatedTo() {
pg.refreshAvailableTxType()

pg.listenForTxNotifications() // tx ntfn listener is stopped in OnNavigatedFrom().
go pg.scroll.FetchScrollData(false, pg.ParentWindow(), false)
}

Expand Down Expand Up @@ -757,28 +756,12 @@ func exportTxs(assets []sharedW.Asset, fileName string) error {
return nil
}

func (pg *TransactionsPage) listenForTxNotifications() {
txAndBlockNotificationListener := &sharedW.TxAndBlockNotificationListener{
OnTransaction: func(walletID int, _ *sharedW.Transaction) {
// Listen for all new txs but ignore ntfns if the wallet sending the
// ntfn is not the currently selected wallet.
if pg.selectedWallet != nil && pg.selectedWallet.GetWalletID() != walletID {
return // ignore tx
}

pg.scroll.FetchScrollData(false, pg.ParentWindow(), false)
},
}

// Listen for ntfns for all wallets.
for _, w := range pg.assetWallets {
w.RemoveTxAndBlockNotificationListener(TransactionsPageID)
err := w.AddTxAndBlockNotificationListener(txAndBlockNotificationListener, TransactionsPageID)
if err != nil {
log.Errorf("Error adding tx and block notification listener: %v", err)
return
}
// Update transaction list when there is new tx or new confirmed status
func (pg *TransactionsPage) ListenForTxNotification(walletID int) {
if pg.selectedWallet != nil && pg.selectedWallet.GetWalletID() != walletID {
return
}
pg.scroll.FetchScrollDataHandler(false, pg.ParentWindow(), false, true)
}

func (pg *TransactionsPage) stopTxNotificationsListener() {
Expand Down
25 changes: 22 additions & 3 deletions ui/page/wallet/single_wallet_main_page.go
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,9 @@ func (swmp *SingleWalletMasterPage) OnNavigatedTo() {
// set active tab value
swmp.activeTab[swmp.PageNavigationTab.SelectedSegment()] = swmp.CurrentPageID()

swmp.listenForNotifications() // ntfn listeners are stopped in OnNavigatedFrom().
swmp.listenForNotifications(func(walletID int) {
go swmp.ListenNewTxForSubPage(walletID)
}) // ntfn listeners are stopped in OnNavigatedFrom().

if swmp.selectedWallet.GetAssetType() == libutils.DCRWalletAsset {
if swmp.selectedWallet.ReadBoolConfigValueForKey(sharedW.FetchProposalConfigKey, false) && swmp.isGovernanceAPIAllowed() {
Expand All @@ -201,6 +203,19 @@ func (swmp *SingleWalletMasterPage) OnNavigatedTo() {
}
}

// Call the subpage component update functions when there is a new tx
func (swmp *SingleWalletMasterPage) ListenNewTxForSubPage(walletID int) {
switch swmp.CurrentPageID() {
case transaction.TransactionsPageID:
swmp.CurrentPage().(*transaction.TransactionsPage).ListenForTxNotification(walletID)
return
case info.InfoID:
swmp.CurrentPage().(*info.WalletInfo).ListenForNewTx(walletID)
default:
return
}
}

// initTabOptions initializes the page navigation tabs
func (swmp *SingleWalletMasterPage) initTabOptions() {
commonTabs := []string{
Expand Down Expand Up @@ -764,7 +779,7 @@ func initializeBeepNotification(n string) {

// listenForNotifications starts a goroutine to watch for notifications
// and update the UI accordingly.
func (swmp *SingleWalletMasterPage) listenForNotifications() {
func (swmp *SingleWalletMasterPage) listenForNotifications(listenForSubpage func(int)) {
syncProgressListener := &sharedW.SyncProgressListener{
OnSyncCompleted: func() {
swmp.updateBalance()
Expand All @@ -778,7 +793,7 @@ func (swmp *SingleWalletMasterPage) listenForNotifications() {
}

txAndBlockNotificationListener := &sharedW.TxAndBlockNotificationListener{
OnTransaction: func(_ int, transaction *sharedW.Transaction) {
OnTransaction: func(walletID int, transaction *sharedW.Transaction) {
swmp.updateBalance()
if swmp.AssetsManager.IsTransactionNotificationsOn() {
// TODO: SPV wallets only receive mempool tx ntfn for txs that
Expand All @@ -788,6 +803,10 @@ func (swmp *SingleWalletMasterPage) listenForNotifications() {
swmp.postTransactionNotification(transaction)
}
swmp.ParentWindow().Reload()
listenForSubpage(walletID)
},
OnTransactionConfirmed: func(walletID int, _ string, _ int32) {
listenForSubpage(walletID)
},
// OnBlockAttached is also called whenever OnTransactionConfirmed is
// called, so use OnBlockAttached. Also, OnTransactionConfirmed may be
Expand Down