-
Notifications
You must be signed in to change notification settings - Fork 5
fix(rpc): minimise RPC usage with comprehensive caching and streaming support #262
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
Conversation
…apters; hydrate on cold start\n\n- Add Hive adapters for stored pubkeys\n- Persist on fetch, hydrate before first RPC\n- Align balance polling to 60s and integrate with tx watcher\n\nBREAKING CHANGE: none
…e health checks; cache wallet names (#3238)
|
Note Other AI code review bot(s) detectedCodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review. WalkthroughThe PR adds caching and storage infrastructure to reduce redundant RPC calls and polling. It implements a user-list cache with 5-minute TTL in auth service, introduces Hive persistence for pubkey data with adapters and in-flight request deduplication in PubkeyManager, and replaces timer-based transaction polling with balance-change-driven subscription logic in TransactionHistoryManager. Changes
Sequence DiagramssequenceDiagram
participant Consumer
participant THM as TransactionHistoryManager
participant BM as BalanceManager
participant API as API Client
Consumer->>THM: watch(assetId)
THM->>BM: subscribe to balance changes
activate THM
THM->>API: initial poll transactions
API-->>THM: transactions
THM->>Consumer: emit transactions
BM->>BM: balance updates
BM-->>THM: emit BalanceInfo (changed)
THM->>API: poll transactions (balance changed)
API-->>THM: transactions
THM->>Consumer: emit transactions
deactivate THM
sequenceDiagram
participant PubkeyManager
participant Storage as HivePubkeysStorage
participant Hive as Hive Box
participant API as API Client
PubkeyManager->>Storage: hydrate on watch start
activate Storage
Storage->>Hive: listForWallet(walletId)
Hive-->>Storage: cached pubkeys
Storage-->>PubkeyManager: hydrated pubkeys
deactivate Storage
PubkeyManager->>Consumer: emit cached pubkeys
PubkeyManager->>API: fetch fresh pubkeys
API-->>PubkeyManager: fresh pubkeys
PubkeyManager->>Storage: persist asynchronously
activate Storage
Storage->>Hive: savePubkeys(...)
Hive-->>Storage: saved
deactivate Storage
PubkeyManager->>Consumer: emit fresh pubkeys
Estimated code review effort🎯 4 (Complex) | ⏱️ ~75 minutes
Possibly related PRs
Suggested labels
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR refactors transaction history polling and adds pubkey persistence caching. The changes eliminate time-based polling in favor of balance-driven updates, add local storage for pubkeys to improve cold-start performance, and implement caching for user lists to reduce RPC calls.
Key changes:
- Replaced time-based transaction history polling with balance-change-driven updates
- Added Hive-based persistence for pubkeys with cold-start hydration
- Introduced caching for wallet users list with 5-minute TTL
Reviewed Changes
Copilot reviewed 9 out of 9 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| transaction_history_manager.dart | Replaces timer-based polling with balance subscription; triggers history sync only when balance changes |
| pubkeys_storage.dart | New storage interface and Hive implementation for persisting pubkeys |
| pubkey_manager.dart | Adds storage integration, request deduplication, and hydration from persisted cache |
| hive_pubkeys_adapters.dart | New Hive adapters for serializing pubkey data structures |
| bootstrap.dart | Injects BalanceManager dependency into TransactionHistoryManager |
| balance_manager.dart | Increases default polling interval from 30s to 1 minute |
| trezor_auth_service_test.dart | Adds missing ensureKdfHealthy method to FakeAuthService mock |
| auth_service_operations_extension.dart | Reduces health check frequency from 5 seconds to 5 minutes |
| auth_service.dart | Implements 5-minute cache for user lists to reduce get_wallet_names calls |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
packages/komodo_defi_sdk/lib/src/transaction_history/transaction_history_manager.dart
Outdated
Show resolved
Hide resolved
|
Visit the preview URL for this PR (updated for commit 087d545): https://kdf-sdk--pr262-perf-3238-reduce-rpc-0kkt2hl1.web.app (expires Wed, 05 Nov 2025 00:06:12 GMT) 🔥 via Firebase Hosting GitHub Action 🌎 Sign: 9c1b6e6c010cf0b965c455ba7a69c4aedafa8a1d |
|
Visit the preview URL for this PR (updated for commit 087d545): https://komodo-playground--pr262-perf-3238-reduce-rpc-rbzvdd8v.web.app (expires Wed, 05 Nov 2025 00:05:58 GMT) 🔥 via Firebase Hosting GitHub Action 🌎 Sign: 2bfedd77fdea45b25ba7c784416e81f177aa5c47 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Codex Review
https://github.com/KomodoPlatform/komodo-defi-sdk-flutter/blob/0db04b262e32b40c1cbe97c3c16672cb5d6609d2/packages/komodo_defi_local_auth/lib/src/auth/auth_service_operations_extension.dart#L22-L33
Health check no longer queries KDF for active user
_checkKdfHealth() now calls getActiveUser() (lines 25‑33), but getActiveUser() was changed to return _lastEmittedUser whenever it is set (lines 285‑292). After a user signs in, health checks therefore just return the cached user and never hit the KDF RPC, so _emitAuthStateChange is never triggered when the active wallet changes outside this service. Clients depending on auth state updates will miss external sign-outs or user switches unless the health check reads from _getActiveUser() directly.
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| Future<void> _persistPubkeys(Asset asset, AssetPubkeys pubkeys) async { | ||
| try { | ||
| final user = await _auth.currentUser; | ||
| if (user == null) return; | ||
| await _storage.savePubkeys(user.walletId, asset.id.id, pubkeys); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Persist pubkeys under wrong wallet when auth changes mid-fetch
getPubkeys persists fetched addresses via _persistPubkeys, but _persistPubkeys (shown here) reads await _auth.currentUser when it runs. If a user signs out and another signs in before the RPC completes, this function writes wallet A’s pubkeys into wallet B’s Hive record and repopulates the cache with stale data. Capturing the wallet id before starting the request and passing it through avoids cross‑wallet contamination.
Useful? React with 👍 / 👎.
This change ensures that pubkey data is correctly associated with the active wallet, preventing cross-wallet contamination. It also improves the accuracy of KDF health checks by bypassing cached user data. Co-authored-by: charl <[email protected]>
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
There was a problem hiding this 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 (4)
packages/komodo_defi_sdk/lib/src/balances/balance_manager.dart (2)
78-82: Make polling interval configurable; default debug logs to false
- Consider injecting polling interval (from config/constructor) to tune per environment.
- Set enableDebugLogging to false by default to avoid warning spam in production.
- final Duration _defaultPollingInterval = const Duration(minutes: 1); + final Duration _defaultPollingInterval = const Duration(minutes: 1); // consider DI/config override - static bool enableDebugLogging = true; + static bool enableDebugLogging = false;
380-387: Capture stack trace in polling errorsLog with stack trace for diagnosability.
- } catch (e) { + } catch (e, s) { // Just log the error and continue with the last known balance // This prevents the stream from terminating on transient errors if (enableDebugLogging) { - _logger.warning( - '[POLLING] Balance fetch failed for ${assetId.name}: $e', - ); + _logger.warning( + '[POLLING] Balance fetch failed for ${assetId.name}: $e', + e, + s, + ); } }packages/komodo_defi_sdk/lib/src/pubkeys/pubkey_manager.dart (1)
212-263: Remove unused non‑wallet‑stable helpers
_persistPubkeysand_hydrateFromStorageread_auth.currentUserand appear unused after adding wallet‑stable variants. Drop them to reduce confusion.packages/komodo_defi_sdk/lib/src/pubkeys/pubkeys_storage.dart (1)
41-74: Reduce coupling to manager’s JSON shape
listForWalletreturns a Map-of-Maps tailored to_hydrateFromStorage*. Consider returning typedAssetPubkeys(or addinggetForWallet(...) -> Map<String, AssetPubkeys>) and let adapters handle domain mapping. This de-duplicates JSON shape logic and eases future schema changes.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (9)
packages/komodo_defi_local_auth/lib/src/auth/auth_service.dart(7 hunks)packages/komodo_defi_local_auth/lib/src/auth/auth_service_operations_extension.dart(1 hunks)packages/komodo_defi_local_auth/test/src/trezor/trezor_auth_service_test.dart(4 hunks)packages/komodo_defi_sdk/lib/src/balances/balance_manager.dart(2 hunks)packages/komodo_defi_sdk/lib/src/bootstrap.dart(2 hunks)packages/komodo_defi_sdk/lib/src/pubkeys/hive_pubkeys_adapters.dart(1 hunks)packages/komodo_defi_sdk/lib/src/pubkeys/pubkey_manager.dart(8 hunks)packages/komodo_defi_sdk/lib/src/pubkeys/pubkeys_storage.dart(1 hunks)packages/komodo_defi_sdk/lib/src/transaction_history/transaction_history_manager.dart(11 hunks)
🔇 Additional comments (24)
packages/komodo_defi_local_auth/lib/src/auth/auth_service_operations_extension.dart (2)
14-19: LGTM! Health check optimization is well-implemented.Reducing the health check interval from 5 seconds to 5 minutes significantly reduces RPC load while maintaining adequate responsiveness. The explanatory comment clearly justifies the change.
25-26: Correct use of_getActiveUser()to bypass cache.The health check correctly calls
_getActiveUser()instead of the publicgetActiveUser()method to bypass the cached user optimization. This ensures external changes (e.g., another process modifying the active wallet) are detected. The comment clearly explains this important distinction.packages/komodo_defi_local_auth/lib/src/auth/auth_service.dart (7)
116-120: LGTM! Cache infrastructure properly initialized.The cache fields are appropriately scoped as private instance variables with a reasonable 5-minute TTL. This strikes a good balance between reducing RPC load and maintaining data freshness.
226-253: Cache-aside pattern correctly implemented.The caching logic properly checks cache freshness before serving cached data and updates the cache after fetching from the RPC. The implementation is protected by the read lock, ensuring thread safety.
287-294: Effective optimization to reduce RPC calls.Preferring
_lastEmittedUser(which is kept current by health checks every 5 minutes) over making an immediate RPC call is a smart optimization. The fallback to_getActiveUser()ensures correctness when no user has been emitted yet.Note: This means
getActiveUser()could return data up to 5 minutes stale if an external process changes the active user, but this is an acceptable trade-off given the PR's goal of reducing RPC load.
216-216: Cache invalidation correctly placed.Invalidating the users cache after successfully registering a new user ensures cache coherence when the user list changes.
374-374: Cache invalidation correctly placed.Invalidating the users cache after successfully deleting a wallet ensures cache coherence when the user list changes.
417-420: LGTM! Clean cache invalidation helper.Simple, focused helper method for clearing the cache state. Properly resets both the cache data and timestamp.
524-548: Reasonable KDF health recovery strategy.The implementation handles the health check and recovery flow appropriately:
- Checks KDF health first
- Attempts recovery by restarting KDF in no-auth mode (since password is unavailable)
- Gracefully handles errors by returning
falseinstead of throwingNote: Restarting in no-auth mode when a user exists will lose the authenticated session, but this is the best available recovery strategy without the user's password. The caller can then prompt for re-authentication if needed.
packages/komodo_defi_local_auth/test/src/trezor/trezor_auth_service_test.dart (2)
138-139: LGTM! Fake implementation correctly added.The
_FakeAuthServicetest double now implements the newensureKdfHealthy()method from theIAuthServiceinterface. Returningtrue(always healthy) is appropriate for a test fake, allowing tests to proceed without health check complications.
447-460: Test data improved with realistic KdfUser.The test setup now includes a pre-existing
KdfUserwithisBip39Seed: true, making the test scenario more representative of actual usage. This better validates the "existing user" code path.packages/komodo_defi_sdk/lib/src/bootstrap.dart (1)
243-253: DI wiring looks correctBalanceManager is retrieved and passed into TransactionHistoryManager, and dependency order includes BalanceManager to avoid cycles. LGTM.
Also applies to: 256-262
packages/komodo_defi_sdk/lib/src/pubkeys/hive_pubkeys_adapters.dart (1)
36-42: No changes needed; BalanceInfo.total is correctly nullableThe
BalanceInfoconstructor acceptsrequired Decimal? total(nullable), and the constructor assertion allows exactly 2 of 3 balance values to be provided. Settingtotal: nullwhile providingspendableandunspendablesatisfies this constraint and is the intended usage pattern.packages/komodo_defi_sdk/lib/src/pubkeys/pubkey_manager.dart (1)
362-365: No changes required; the code implements equality semantics correctlyAssetPubkeys extends Equatable and properly overrides the
propsgetter (lines 41–47) to include all fields:assetId,keys,availableAddressesCount, andsyncStatus. Since Equatable provides value-based equality whenpropsis correctly defined, the comparisonfirst != hydratedat line 363 will work as intended and will not emit duplicates.packages/komodo_defi_sdk/lib/src/pubkeys/pubkeys_storage.dart (1)
20-25: Hive initialization is guaranteed through proper SDK initialization flow, but no runtime safeguard exists for misuseI confirmed that
Hive.initFlutter()is called during bootstrap inActivationConfigServiceregistration, which occurs beforePubkeyManager(and thusHivePubkeysStorage) is registered. The initialization sequence within bootstrap is correct: Hive is initialized before storage usage.However, the code relies on the caller following the proper initialization pattern (
KomodoDefiSdk.initialize()before any storage usage). SinceHivePubkeysStorage._openBox()has no explicit runtime check verifying Hive is initialized, misuse outside the SDK's initialization context would fail silently. The review's concern about verifying initialization in all app entry points is valid from a defensive programming perspective.packages/komodo_defi_sdk/lib/src/transaction_history/transaction_history_manager.dart (9)
34-47: LGTM! Constructor properly wired for balance-driven polling.The addition of
BalanceManageras a required parameter correctly supports the new balance-driven polling mechanism. The dependency is properly stored and will be used to subscribe to balance changes.Also applies to: 61-61
64-65: LGTM! State management for balance-driven polling.The new state fields properly track balance subscriptions and last observed values per asset, enabling efficient change detection.
69-70: Comment correctly positioned.The comment on line 69 now accurately describes the
_maxPollingRetriesconstant on line 70, resolving the past review concern about comment positioning.
78-94: LGTM! Proper cleanup of balance subscriptions.The method correctly cancels all balance subscriptions and clears related state before closing stream controllers.
248-273: LGTM! Prevents duplicate balance subscriptions.The check on line 258 ensures balance subscriptions are created only once per asset, preventing resource leaks.
359-360: LGTM! Good defensive check.The early exit prevents unnecessary work if the asset is no longer being watched, improving efficiency.
429-432: Balance change detection is focused on transaction-relevant fields.The logic only compares
totalandspendableto detect changes, which aligns with the PR objective of reducing RPC spam by triggering polls only when meaningful balance changes occur.Note: If
BalanceInfohas other fields that could change independently, they won't trigger polling. Verify this is acceptable for your use case.
440-445: LGTM! Proper cleanup of asset-specific balance state.The method correctly cancels the balance subscription and cleans up related state for the specific asset.
116-118: LGTM! Formatting improvements for readability.The multi-line formatting of pagination parameters and transaction conversions improves code readability without changing functionality.
Also applies to: 146-148, 206-212, 220-222, 296-302, 310-312, 353-355, 363-365
packages/komodo_defi_sdk/lib/src/transaction_history/transaction_history_manager.dart
Outdated
Show resolved
Hide resolved
Co-authored-by: charl <[email protected]>
- Wire SDK `ActivatedAssetsCache` into activation/coins flows: updates across `CoinsBloc`, `AssetOverviewBloc`, custom token import, and `sdk_auth_activation_extension` to reuse activation state instead of re-querying. - Debounce/polish polling in `portfolio_growth_bloc` and `profit_loss_bloc` to prevent overlapping requests. - Remove duplicate activation/balance checks in maker/taker validators and forms. - Consolidate repeated calls in `mm2_api`/`mm2_api_nft`/`rpc_native`; prefer cached values. - Reduce startup RPCs in `app_bootstrapper`; stop background timers in `window_close_handler` on app close to avoid trailing calls. - Add shared intervals in `shared/constants`; introduce `lib/shared/utils/activated_assets_cache.dart` for app-specific helpers. - No UI changes; measurable reduction in RPC volume and improved responsiveness. Refs #3238
…on; expose streaming API in framework and rpc methods
…load via package path
- Replace string-based event types with sealed class hierarchy - Create typed event classes for all stream types (Balance, Orderbook, Network, Heartbeat, SwapStatus, OrderStatus, TxHistory, ShutdownSignal) - Use private enum for internal string mapping while exposing typed API - Make StreamEnableResponse generic to link responses to event types - Update event_streaming_service with type-safe filtering methods - Organize events into separate files using part directives - Enable exhaustive pattern matching with switch expressions Benefits: - Compile-time type safety eliminates string-based checks - Better IDE support with autocomplete and type hints - Reduced runtime errors from type mismatches - Clearer public API with explicit event types
…ment - Create EventStreamingManager in komodo_defi_sdk package - Implement automatic stream lifecycle handling (enable/disable) - Add reference counting for shared stream subscriptions - Support all event types: balance, orderbook, tx history, swap status, order status, network, heartbeat, and shutdown signals - Reduce boilerplate with generic _subscribeToStream method using template method pattern - Register manager in DI container for internal use by domain managers - Manager is not publicly exposed, intended for use by domain-specific managers to provide real-time updates
Replace periodic polling with real-time event streaming in BalanceManager and TransactionHistoryManager to reduce RPC spam and improve efficiency. Changes: - BalanceManager: Replace 1-minute polling interval with balance event streaming - TransactionHistoryManager: Replace balance-driven polling with TX history event streaming - Bootstrap: Inject EventStreamingManager into both managers - Remove polling configuration (intervals, retry counters, debug flags) - Fix shouldEnableTransactionHistory to always return true for streaming support Benefits: - Eliminates periodic RPC calls every 60 seconds - Real-time updates instead of up to 1-minute delays - Better resource utilization (updates only when data changes) - Automatic reconnection and error handling via EventStreamingManager Refs: #3238
The _waitForCoinAvailability method was failing to verify asset activation because isAssetActive() was using cached data instead of fetching fresh data from the backend. This caused transaction history to fail with a connection error even though assets were successfully activated. Changes: - Add forceRefresh parameter to ActivationManager.isAssetActive() - Update SharedActivationCoordinator._waitForCoinAvailability() to force refresh on each availability check - This ensures we bypass the 2-second cache TTL and get real-time data Fixes issue where transaction history shows 'Connection to Komodo servers are failing' error after asset activation completes successfully.
… subscriptions The balance and transaction history event subscriptions were using asset.id.name (the human-friendly display name like 'Bitcoin') instead of asset.id.id (the config ID like 'BTC-segwit'). This caused the RPC enable streaming calls to fail because the backend expects the config ID. Changes: - BalanceManager: Use assetId.id instead of assetId.name for subscribeToBalance - TransactionHistoryManager: Use asset.id.id instead of asset.id.name for subscribeToTxHistory - Update event filtering to match using config ID as well This fixes the 'Failed to start balance watcher' errors and resolves the transaction history connection error.
Roll KDF to the `dev` branch version which will be used for KW release.
…mat modified files
…dk-flutter into perf/3238-reduce-rpc-spam # Conflicts: # packages/komodo_defi_framework/lib/komodo_defi_framework.dart # packages/komodo_defi_local_auth/lib/src/auth/auth_service.dart
This change refactors the transaction comparison logic in `InMemoryTransactionStorage` to ensure that all transactions are available during comparison. This prevents potential exceptions and improves the stability of the transaction history storage. Co-authored-by: Cursor Agent <[email protected]>
| required void Function(Object? data) onMessage, | ||
| IKdfHostConfig? hostConfig, | ||
| }) { | ||
| final IKdfHostConfig cfg = hostConfig!; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
#269) * fix(rpc): minimise RPC usage with comprehensive caching and streaming support (#262) * feat(pubkeys): persist AssetPubkeys across sessions using Hive TypeAdapters; hydrate on cold start\n\n- Add Hive adapters for stored pubkeys\n- Persist on fetch, hydrate before first RPC\n- Align balance polling to 60s and integrate with tx watcher\n\nBREAKING CHANGE: none * chore(format): run dart format on pubkey persistence and balance manager files * perf(sdk): dedupe pubkeys/address fetch, cache-first hydrate; throttle health checks; cache wallet names (#3238) * test(local-auth): add ensureKdfHealthy to FakeAuthService for Trezor tests * Refactor: Wallet-aware pubkey persistence and retrieval This change ensures that pubkey data is correctly associated with the active wallet, preventing cross-wallet contamination. It also improves the accuracy of KDF health checks by bypassing cached user data. Co-authored-by: charl <[email protected]> * Refactor: Improve pubkey and balance fetching logic Co-authored-by: charl <[email protected]> * fix: market data resource improvements * perf(assets): cache activated assets and coalesce activation checks - Wire SDK `ActivatedAssetsCache` into activation/coins flows: updates across `CoinsBloc`, `AssetOverviewBloc`, custom token import, and `sdk_auth_activation_extension` to reuse activation state instead of re-querying. - Debounce/polish polling in `portfolio_growth_bloc` and `profit_loss_bloc` to prevent overlapping requests. - Remove duplicate activation/balance checks in maker/taker validators and forms. - Consolidate repeated calls in `mm2_api`/`mm2_api_nft`/`rpc_native`; prefer cached values. - Reduce startup RPCs in `app_bootstrapper`; stop background timers in `window_close_handler` on app close to avoid trailing calls. - Add shared intervals in `shared/constants`; introduce `lib/shared/utils/activated_assets_cache.dart` for app-specific helpers. - No UI changes; measurable reduction in RPC volume and improved responsiveness. Refs #3238 * feat(streaming): add typed stream RPCs and web SharedWorker integration; expose streaming API in framework and rpc methods * feat(web): package event_streaming_worker.js in framework assets and load via package path * fix(web): correct SharedWorker path to package asset under assets/web/ * refactor(streaming): improve type safety with sealed event classes - Replace string-based event types with sealed class hierarchy - Create typed event classes for all stream types (Balance, Orderbook, Network, Heartbeat, SwapStatus, OrderStatus, TxHistory, ShutdownSignal) - Use private enum for internal string mapping while exposing typed API - Make StreamEnableResponse generic to link responses to event types - Update event_streaming_service with type-safe filtering methods - Organize events into separate files using part directives - Enable exhaustive pattern matching with switch expressions Benefits: - Compile-time type safety eliminates string-based checks - Better IDE support with autocomplete and type hints - Reduced runtime errors from type mismatches - Clearer public API with explicit event types * feat(sdk): add internal event streaming manager with lifecycle management - Create EventStreamingManager in komodo_defi_sdk package - Implement automatic stream lifecycle handling (enable/disable) - Add reference counting for shared stream subscriptions - Support all event types: balance, orderbook, tx history, swap status, order status, network, heartbeat, and shutdown signals - Reduce boilerplate with generic _subscribeToStream method using template method pattern - Register manager in DI container for internal use by domain managers - Manager is not publicly exposed, intended for use by domain-specific managers to provide real-time updates * perf: eliminate RPC polling by using event streaming Replace periodic polling with real-time event streaming in BalanceManager and TransactionHistoryManager to reduce RPC spam and improve efficiency. Changes: - BalanceManager: Replace 1-minute polling interval with balance event streaming - TransactionHistoryManager: Replace balance-driven polling with TX history event streaming - Bootstrap: Inject EventStreamingManager into both managers - Remove polling configuration (intervals, retry counters, debug flags) - Fix shouldEnableTransactionHistory to always return true for streaming support Benefits: - Eliminates periodic RPC calls every 60 seconds - Real-time updates instead of up to 1-minute delays - Better resource utilization (updates only when data changes) - Automatic reconnection and error handling via EventStreamingManager Refs: #3238 * fix(cache): address PR review issues - error handling and race conditions - Health check: log transient RPC failures instead of triggering false sign-outs - ActivatedAssetsCache: fix race condition using generation counter and Completer pattern - NFT activation: aggregate and report all errors instead of only the last one - Auth service: document 5-minute user cache staleness trade-off Refs: #262 * chore: add event streaming logging * fix(rpc): address critical review feedback on caching implementation - Fix incorrect unawaited() usage in pubkey_manager by properly extracting Future - Add eagerError: false to event_streaming_manager dispose for robust cleanup - Replace unsafe String cast with whereType<String>() in pubkeys_storage - Add race condition check in transaction_history_manager _startStreaming - Capture timestamp at fetch start in activated_assets_cache for accurate TTL - Add error handling to sparkline_repository dispose to ensure all cleanup * perf(auth): use shutdown event streaming to minimize RPC polling Subscribe to KDF shutdown signals to immediately detect when KDF shuts down, eliminating the need for frequent polling. This provides near-instant shutdown detection (< 1 second) compared to periodic health checks. - Add shutdown signal subscription in KdfAuthService - Subscribe to shutdown events and immediately update auth state - Enable shutdown signal stream via RPC on initialization - Clean up subscription on dispose - Health checks now serve as backup for edge cases Benefits: - Reduces getWalletNames RPC calls significantly - Provides instant user sign-out on KDF shutdown - Maintains graceful degradation if streaming unavailable * feat(rpc): optimize initial balance/history for newly created wallets - Assume zero balance for first-time asset enablement in new wallets - Assume empty transaction history for first-time asset enablement in new wallets - Detect new wallets by absence of any asset activation history - Avoids unnecessary RPC spam when activating first assets in new wallets - Does NOT apply to imported wallets (they have activation history) - Uses AssetHistoryStorage to track which assets have been enabled per wallet - Wire up shared AssetHistoryStorage instance in SDK bootstrap * fix(auth): track imported vs created wallets to prevent incorrect optimizations - Add 'isImported' metadata to KdfUser during registration - Pass mnemonic presence to _registerNewUser to determine if imported - Update balance/history managers to check isImported flag - Prevents incorrectly assuming zero balance for imported wallets - Optimization now only applies to genuinely new wallets (not imported) BREAKING: Imported wallets will now correctly fetch real balances/history on first use instead of incorrectly showing zero * fix: remove errors from KDF merge * chore: roll `coins` * fix: misc streaming fixes * feat(sdk): add event streaming support for task status updates - Add event streaming service and configuration - Implement task event handling and unknown event fallback - Add RPC task shepherd method for task status monitoring - Update balance manager to support event-driven updates - Add platform-specific event streaming implementations - Enhance sync status with event streaming capabilities This reduces RPC polling by leveraging KDF event streaming for task status updates. * fix(activation): force cache refresh when verifying asset availability The _waitForCoinAvailability method was failing to verify asset activation because isAssetActive() was using cached data instead of fetching fresh data from the backend. This caused transaction history to fail with a connection error even though assets were successfully activated. Changes: - Add forceRefresh parameter to ActivationManager.isAssetActive() - Update SharedActivationCoordinator._waitForCoinAvailability() to force refresh on each availability check - This ensures we bypass the 2-second cache TTL and get real-time data Fixes issue where transaction history shows 'Connection to Komodo servers are failing' error after asset activation completes successfully. * fix(streaming): use asset config ID instead of display name for event subscriptions The balance and transaction history event subscriptions were using asset.id.name (the human-friendly display name like 'Bitcoin') instead of asset.id.id (the config ID like 'BTC-segwit'). This caused the RPC enable streaming calls to fail because the backend expects the config ID. Changes: - BalanceManager: Use assetId.id instead of assetId.name for subscribeToBalance - TransactionHistoryManager: Use asset.id.id instead of asset.id.name for subscribeToTxHistory - Update event filtering to match using config ID as well This fixes the 'Failed to start balance watcher' errors and resolves the transaction history connection error. * perf: reduce RPC spam in activation strategies and managers * fix(auth-service): update cache alongside storage for metadata updates * chore: roll KDF to release preview Roll KDF to the `dev` branch version which will be used for KW release. * fix(stream): normalize KDF stream _type parsing for suffixed IDs; format modified files * fix: use correct streaming worker js path * fix: tx history streaming * fix: improve robustness of event parsing * fix: backwards compatibility for KDF API status * Refactor: Improve transaction comparison logic (#268) This change refactors the transaction comparison logic in `InMemoryTransactionStorage` to ensure that all transactions are available during comparison. This prevents potential exceptions and improves the stability of the transaction history storage. Co-authored-by: Cursor Agent <[email protected]> --------- Co-authored-by: Cursor Agent <[email protected]> Co-authored-by: Francois <[email protected]> * fix config * fix timers leak * fix sse --------- Co-authored-by: Nitride <[email protected]> Co-authored-by: Cursor Agent <[email protected]> Co-authored-by: Francois <[email protected]>
Note
Introduces cross-platform event streaming (SSE on native, SharedWorker on web) and integrates it across SDK managers with caching and polling fallbacks to significantly reduce RPC usage.
event_streaming_platform_io.dart, SharedWorker on web viaassets/web/event_streaming_worker.js).Balance,Orderbook,Network,Heartbeat,SwapStatus,OrderStatus,TxHistory,ShutdownSignal).stream::balance/orderbook/tx_history/network/heartbeat/swap_status/order_status/shutdown_signal).EventStreamingConfiguration(CORS, worker path).EventStreamingManagerand wire into DI; expose viaKomodoDefiSdk.ActivatedAssetsCachewith TTL; integrate intoAssetManager,ActivationManager, and SDK config.NftActivationServiceand helpers to wait for enabled assets/tickers.getUsers, prefer last user forgetActiveUser, subscribe to shutdown signal stream; lengthen health-check interval; safer restart logic.dispose()to repositories/providers; ensure DI disposes CoinPaprika resources;SparklineRepository.dispose()cleans up.tx_historywhen not required; addrequiresKdfTransactionHistory()to strategies.Written by Cursor Bugbot for commit 74d4999. This will update automatically on new commits. Configure here.
Summary by CodeRabbit
Release Notes
Performance & Optimization
Tests