Skip to content

fix: flush balance, transaction history, and pubkey watchers on auth event#3168

Closed
takenagain wants to merge 2 commits intodevfrom
fix/flush-watchers-on-auth-change
Closed

fix: flush balance, transaction history, and pubkey watchers on auth event#3168
takenagain wants to merge 2 commits intodevfrom
fix/flush-watchers-on-auth-change

Conversation

@takenagain
Copy link
Copy Markdown
Contributor

@takenagain takenagain commented Oct 3, 2025

Summary by CodeRabbit

  • New Features

    • None
  • Bug Fixes

    • Ensures transaction history resets and updates correctly after login, logout, or wallet switch.
    • Prevents duplicate/failed coin activations and handles activation conflicts more gracefully.
    • Fixes cache flushing race conditions during login/logout.
  • Performance and Stability

    • Improves reliability of real-time transaction updates and subscription cleanup.
    • Enhances activation lifecycle handling and balance watcher management for smoother state transitions.
    • Adds robust error handling to reduce unexpected failures and improve overall stability.

@takenagain takenagain self-assigned this Oct 3, 2025
@takenagain takenagain added the bug Something isn't working label Oct 3, 2025
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Oct 3, 2025

Walkthrough

Updates introduce private dependency fields and logging in CoinAddressesBloc, add an auth-change event, adjust CoinsBloc to await async cache flush, overhaul activation flow and cache flush in CoinsRepo with refined logging and error handling, and add auth-aware subscription reset/start logic in TransactionHistoryBloc with a new auth-change event.

Changes

Cohort / File(s) Summary of Changes
Coin Addresses: private deps, logging, auth event
lib/bloc/coin_addresses/bloc/coin_addresses_bloc.dart, lib/bloc/coin_addresses/bloc/coin_addresses_event.dart
Bloc now uses private fields (_sdk, _assetId, _analyticsBloc), adds a private logger, improves pubkey subscription start/cancel/error logging, introduces _cancelPubkeySubscription, and adds new event CoinAddressesAuthStateChanged(KdfUser?).
Coins: await cache flush, activation/logging refactor
lib/bloc/coins_bloc/coins_bloc.dart, lib/bloc/coins_bloc/coins_repo.dart
CoinsBloc awaits _coinsRepo.flushCache() during login/logout. CoinsRepo refactors activation lifecycle (activating/active/suspended), adds granular coordination/conflict/error logging, per-asset exception handling, parent activation logging, and changes flushCache() to async with watcher cancellation and logging.
Transaction History: auth-aware lifecycle
lib/bloc/transaction_history/transaction_history_bloc.dart, lib/bloc/transaction_history/transaction_history_event.dart
Adds auth-state listener and TransactionHistoryAuthStateChanged event. On auth changes, cancels subscriptions, clears processed IDs, and resets state. Starts live subscription after historical fetch completes; cleans up auth subscription on close.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor User
  participant UI
  participant CoinsBloc
  participant CoinsRepo
  participant SDK

  User->>UI: Activate assets
  UI->>CoinsBloc: activate(assets)
  CoinsBloc->>CoinsRepo: activate(assets)

  loop For each asset
    CoinsRepo->>CoinsRepo: emit "activating"
    CoinsRepo->>SDK: sdk.activate(asset)
    alt Activation coordination conflict
      CoinsRepo->>CoinsRepo: log info (conflict)
      CoinsRepo->>CoinsRepo: emit state (expected)
    else Success
      CoinsRepo->>CoinsRepo: log success\n(parent if applicable)
      CoinsRepo->>CoinsRepo: emit "active"
    else Error
      CoinsRepo->>CoinsRepo: log warning/severe
      CoinsRepo->>CoinsRepo: emit "suspended"
    end
  end

  note over CoinsRepo: Async flushCache cancels watchers\nand clears caches with logging
Loading
sequenceDiagram
  autonumber
  participant Auth as AuthService
  participant TH as TransactionHistoryBloc
  participant SDK

  Auth-->>TH: onUserChanged(user/wallet)
  TH->>TH: add(TransactionHistoryAuthStateChanged)
  TH->>TH: cancel history & new-tx subscriptions\nclear processed IDs\nreset to initial

  TH->>SDK: streamHistoricalTx()
  SDK-->>TH: historical batches
  SDK-->>TH: onDone
  TH->>TH: _subscribeToNewTransactions()
  SDK-->>TH: new tx stream
  TH-->>TH: map to state updates / errors
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Suggested labels

QA

Suggested reviewers

  • CharlVS
  • gcharang
  • smk762

Poem

Bunny taps logs with a gentle thump,
Watching caches flush—glug, gloop, glump.
Keys hop in, subs hop out, neat and spry,
Histories reset as wallets fly by.
Coins awaken—no fuss, no fright—
Every carrot counted just right. 🥕✨

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The title clearly and concisely summarizes the primary change of flushing balance data, transaction history, and pubkey watchers upon authentication events, directly matching the pull request’s main objective.
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.
✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/flush-watchers-on-auth-change

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions
Copy link
Copy Markdown

github-actions bot commented Oct 3, 2025

Visit the preview URL for this PR (updated for commit 8cf4d94):

https://walletrc--pull-3168-merge-d4261r31.web.app

(expires Fri, 10 Oct 2025 16:55:54 GMT)

🔥 via Firebase Hosting GitHub Action 🌎

Sign: f66a4ff03faa546f12f0ae5a841bd9eff2714dcc

CoinAddressesBloc is created at lower levels within buttons etc, so the auth state replay causes issues with the pubkey loading (initial state + current state = clear listeners while starting listeners)
@takenagain
Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@takenagain takenagain requested a review from Copilot October 3, 2025 17:35
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Oct 3, 2025

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (2)
lib/bloc/coin_addresses/bloc/coin_addresses_bloc.dart (1)

194-201: Optional: guard fine/finest logs to avoid building message strings when disabled

Wrap with isLoggable to skip interpolation cost at lower levels.

-      _log.fine('Starting pubkey watching for asset ${asset.id.id}');
+      if (_log.isLoggable(Level.FINE)) {
+        _log.fine('Starting pubkey watching for asset ${asset.id.id}');
+      }
@@
-                _log.finest(
-                  'Received pubkey update for asset ${asset.id.id}: ${assetPubkeys.keys.length} addresses',
-                );
+                if (_log.isLoggable(Level.FINEST)) {
+                  _log.finest(
+                    'Received pubkey update for asset ${asset.id.id}: ${assetPubkeys.keys.length} addresses',
+                  );
+                }
@@
-      _log.fine(
-        'Pubkey watching started successfully for asset ${asset.id.id}',
-      );
+      if (_log.isLoggable(Level.FINE)) {
+        _log.fine(
+          'Pubkey watching started successfully for asset ${asset.id.id}',
+        );
+      }
@@
-      _log.severe(
-        'Failed to start pubkey watching for asset ${asset.id.id}: $e',
-      );
+      _log.severe(
+        'Failed to start pubkey watching for asset ${asset.id.id}: $e',
+      );

Based on learnings

Also applies to: 206-209, 222-224, 226-228

lib/bloc/transaction_history/transaction_history_bloc.dart (1)

219-226: Fix comparator: comparing to DateTime.now() is incorrect

Simplify to pure descending timestamp sort.

-int _sortTransactions(Transaction tx1, Transaction tx2) {
-  if (tx2.timestamp == DateTime.now()) {
-    return 1;
-  } else if (tx1.timestamp == DateTime.now()) {
-    return -1;
-  }
-  return tx2.timestamp.compareTo(tx1.timestamp);
-}
+int _sortTransactions(Transaction a, Transaction b) =>
+    b.timestamp.compareTo(a.timestamp);
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c91431e and 8cf4d94.

📒 Files selected for processing (6)
  • lib/bloc/coin_addresses/bloc/coin_addresses_bloc.dart (8 hunks)
  • lib/bloc/coin_addresses/bloc/coin_addresses_event.dart (2 hunks)
  • lib/bloc/coins_bloc/coins_bloc.dart (2 hunks)
  • lib/bloc/coins_bloc/coins_repo.dart (5 hunks)
  • lib/bloc/transaction_history/transaction_history_bloc.dart (6 hunks)
  • lib/bloc/transaction_history/transaction_history_event.dart (1 hunks)
🔇 Additional comments (5)
lib/bloc/transaction_history/transaction_history_event.dart (1)

28-31: New auth-change event looks good

Const, sealed hierarchy preserved. OK.

lib/bloc/coin_addresses/bloc/coin_addresses_event.dart (1)

2-3: Auth-change event for CoinAddresses is well-formed

Import + Equatable props are correct. LGTM.

Also applies to: 51-59

lib/bloc/coin_addresses/bloc/coin_addresses_bloc.dart (1)

51-76: General: pre-cache + cancel-before-start is solid

Precaching pubkeys, cancelling prior sub, and re-requesting after address creation is correct and improves UX. Nice.

lib/bloc/transaction_history/transaction_history_bloc.dart (2)

27-33: Auth-change handling LGTM

Auth listener + clearing history/new subscriptions and resetting state is correct and matches the PR goal.

Also applies to: 43-49, 201-216


81-84: Address set is captured once; verify behavior when new addresses are created later

myAddresses is built before subscriptions and not refreshed. If users create new addresses, sanitize() may misclassify later txs. Consider re-fetching pubkeys periodically or subscribing to pubkey updates to refresh the set.

Also applies to: 146-178

Comment on lines +153 to 162
Future<void> flushCache() async {
// Intentionally avoid flushing the prices cache - prices are independent
// of the user's session and should be updated on a regular basis.
_addressCache.clear();

enabledAssetsChanges.close();
_log.info('Clearing ${_balanceWatchers.length} balance watchers');
final cancelFutures = _balanceWatchers.values.map((sub) => sub.cancel());
await Future.wait(cancelFutures);
_balanceWatchers.clear();
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Also clear _balancesCache when flushing on auth changes

flushCache() now runs on every auth transition, but it only clears _addressCache and cancels watchers. _balancesCache still holds the previous wallet’s balances, so subsequent _assetToCoinWithoutAddress calls (e.g., during the next login’s pre-population) will surface stale balances from the prior session. That’s a correctness issue: the newly signed-in wallet briefly displays someone else’s balances until fresh updates arrive. Please clear _balancesCache alongside the watcher teardown.

Apply this diff:

   _addressCache.clear();
+  _balancesCache.clear();
🤖 Prompt for AI Agents
In lib/bloc/coins_bloc/coins_repo.dart around lines 153 to 162, flushCache()
currently clears _addressCache and cancels balance watchers but fails to clear
_balancesCache, which allows stale balances from the previous session to be
shown after auth transitions; update flushCache() to also clear _balancesCache
(e.g., call _balancesCache.clear()) alongside _addressCache and the watcher
teardown so any cached balances are removed when auth changes.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

@takenagain
Copy link
Copy Markdown
Contributor Author

Closing as unnecessary. This PR refactors existing logic, and does not fix a bug or improve performance. The root cause was found and fixed in the SDK (linked PR), and the duplicate activation issue was resolved for me on current dev

@takenagain takenagain closed this Oct 4, 2025
@takenagain takenagain deleted the fix/flush-watchers-on-auth-change branch October 4, 2025 23:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants