Skip to content

fix(coins): unauthenticated coin list and chart issues#3138

Merged
CharlVS merged 5 commits intodevfrom
cursor/fix-unauthenticated-coin-list-and-chart-issues-a7d0
Sep 15, 2025
Merged

fix(coins): unauthenticated coin list and chart issues#3138
CharlVS merged 5 commits intodevfrom
cursor/fix-unauthenticated-coin-list-and-chart-issues-a7d0

Conversation

@CharlVS
Copy link
Copy Markdown
Collaborator

@CharlVS CharlVS commented Sep 12, 2025

Fix unauthenticated coins list not showing prices and empty chart selector, and improve coin dropdown text legibility.

The unauthenticated coins list was not displaying prices or 24h changes because CoinsRepo.fetchCurrentPrices only fetched prices for activated assets. The charts' coin selector was empty when unauthenticated because PriceChartBloc.availableCoins was not being populated. The coin dropdown text was illegible due to an incorrect text color.


Open in Cursor Open in Web

Summary by CodeRabbit

  • New Features

    • Price chart now auto-populates available coins from your assets when the list is empty.
    • Broader price coverage, including for unauthenticated users.
    • Prices now include 24h change where available.
  • Bug Fixes

    • More resilient price updates: missing 24h data no longer interrupts other price fetches.
  • Style

    • Improved readability in coin selection: text color now matches the app’s on-surface color.

Co-authored-by: charl <charl@vanstaden.info>
@cursor
Copy link
Copy Markdown

cursor bot commented Sep 12, 2025

Cursor Agent can help with this pull request. Just @cursor in comments and I'll start working on changes in this branch.
Learn more about Cursor Agents

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Sep 12, 2025

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Note

Other AI code review bot(s) detected

CodeRabbit 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.

Walkthrough

Implements SDK-driven lazy initialization of price chart coins, updates coins_repo to select assets from activated or all SDK assets, adds 24h change fetching and uppercase symbol caching, and adjusts a UI text style to use bodyMedium with onSurface color.

Changes

Cohort / File(s) Summary
Price chart lazy init via SDK
lib/bloc/cex_market_data/price_chart/price_chart_bloc.dart
Lazily populates availableCoins by fetching SDK assets when empty, excluding configured/testnet assets; maps assets to CoinPriceInfo; imports app_config for exclusion list.
Coins price fetch: selection, 24h change, caching
lib/bloc/coins_bloc/coins_repo.dart
fetchCurrentPrices now targets activated assets or all SDK assets, filters exclusions/testnets, fetches fiat price and optional 24h change per asset, logs non-fatal errors, caches by uppercase symbol, and constructs CexPrice with change24h.
UI text style adjustment
lib/shared/widgets/coin_select_item_widget.dart
Changes DefaultTextStyle to theme.textTheme.bodyMedium!.copyWith(color: theme.colorScheme.onSurface), removing dependency on inputDecorationTheme.labelStyle.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant UI as PriceChart UI
  participant B as PriceChartBloc
  participant SDK as KomodoDefiSdk
  participant C as AppConfig

  UI->>B: Request availableCoins
  alt availableCoins empty
    Note over B: Lazy init
    B->>SDK: getAllAssets()
    SDK-->>B: assets[]
    B->>C: get excluded/testnet lists
    B-->>B: Filter assets, map to CoinPriceInfo
    B-->>UI: availableCoins (initialized)
  else not empty
    B-->>UI: availableCoins (cached)
  end
Loading
sequenceDiagram
  autonumber
  participant U as Caller
  participant R as CoinsRepo.fetchCurrentPrices
  participant SDK as KomodoDefiSdk
  participant PX as PriceProvider
  participant Log as Logger
  participant Cache as PriceCache

  U->>R: fetchCurrentPrices()
  R->>SDK: getActivatedAssets()
  alt none or unavailable
    R->>SDK: getAllAssets()
    SDK-->>R: assets (all)
  else available
    SDK-->>R: assets (activated)
  end
  R-->>R: Filter exclusions + testnets -> validAssets
  loop for each asset in validAssets
    R->>PX: maybeFiatPrice(asset)
    PX-->>R: price? (nullable)
    opt if price available
      R->>PX: priceChange24h(asset)
      alt success
        PX-->>R: change24h
      else error
        PX-->>R: error
        R->>Log: warn(24h retrieval failed)
        R-->>R: change24h = null
      end
      R-->>Cache: set(symbol.toUpperCase(), CexPrice{price, change24h, ...})
    end
  end
  R-->>U: Completed
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Suggested labels

bug, QA

Suggested reviewers

  • takenagain
  • AndrewDelaney
  • ShantanuSharma9873

Poem

A whisk of code, a hop so light,
I fetched the coins by SDK’s night.
Prices rise, and 24h sings,
Uppercase keys in caching rings.
UI dressed in onSurface hue—
Thump-thump! This bunny ships for you. 🐇✨

Pre-merge checks

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.
Title Check ✅ Passed The title "fix(coins): unauthenticated coin list and chart issues" succinctly and accurately summarizes the main changes in this PR—restoring prices and 24h changes for unauthenticated users and populating chart coin selections—matching the PR objectives and file diffs; it is concise and on-topic, though it does not explicitly call out the minor text-color tweak which is acceptable for a short title.

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.

@CharlVS CharlVS marked this pull request as ready for review September 12, 2025 15:20
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.

Pull Request Overview

This PR fixes issues with unauthenticated user experience by ensuring coin prices and chart functionality work properly. The changes address three main problems: missing price data in coin lists, empty chart selectors, and poor text visibility in dropdowns.

  • Modified price fetching to include all available assets when no activated assets exist for unauthenticated users
  • Enhanced chart selector to populate available coins from SDK assets when empty
  • Fixed coin dropdown text legibility by using proper theme colors

Reviewed Changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

File Description
lib/bloc/coins_bloc/coins_repo.dart Updates price fetching logic to include all SDK assets for unauthenticated users and normalizes cache keys
lib/bloc/cex_market_data/price_chart/price_chart_bloc.dart Populates chart selector with available coins from SDK when empty
lib/shared/widgets/coin_select_item_widget.dart Fixes text color to use proper theme color for better legibility

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

@CharlVS
Copy link
Copy Markdown
Collaborator Author

CharlVS commented Sep 12, 2025

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Sep 12, 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.

cursor[bot]

This comment was marked as outdated.

@github-actions
Copy link
Copy Markdown

github-actions bot commented Sep 12, 2025

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

https://walletrc--pull-3138-merge-bfumakdv.web.app

(expires Sun, 21 Sep 2025 16:05:26 GMT)

🔥 via Firebase Hosting GitHub Action 🌎

Sign: f66a4ff03faa546f12f0ae5a841bd9eff2714dcc

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: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
lib/bloc/coins_bloc/coins_repo.dart (1)

571-577: Bug: cache key case change will break existing reads.

Prices are now written with an uppercase key, but multiple readers still fetch by the original-case configSymbol (e.g., _assetToCoinWithoutAddress at Line 206). This will make usdPrice null across the app.

Minimal fix: write both keys to preserve backwards compatibility.

-          final symbolKey = asset.id.symbol.configSymbol.toUpperCase();
-          _pricesCache[symbolKey] = CexPrice(
-            assetId: asset.id,
-            price: fiatPrice,
-            lastUpdated: DateTime.now(),
-            change24h: change24h,
-          );
+          final symbol = asset.id.symbol.configSymbol;
+          final entry = CexPrice(
+            assetId: asset.id,
+            price: fiatPrice,
+            lastUpdated: DateTime.now(),
+            change24h: change24h,
+          );
+          _pricesCache[symbol.toUpperCase()] = entry; // new canonical form
+          _pricesCache[symbol] = entry;               // backward-compat

Follow-up (optional): centralize a _symbolKey() helper and migrate all call sites in a dedicated cleanup.

♻️ Duplicate comments (1)
lib/bloc/cex_market_data/price_chart/price_chart_bloc.dart (1)

41-45: Avoid using 0.0 as a “data not loaded” sentinel for percentage.

Hardcoding 0.0 can be mistaken for “no change.” Prefer a dedicated placeholder strategy (e.g., a constant like kPercentageNotAvailable = 0.0 with UI hinting) or make the field nullable if feasible. This mirrors a prior note on this topic.

🧹 Nitpick comments (5)
lib/bloc/cex_market_data/price_chart/price_chart_bloc.dart (1)

30-49: Populate availableCoins immediately (even on fetch failures).

Currently availableCoins is only set in the success emit. If OHLC fetch fails, the selector can remain empty for unauthenticated users. Emit the populated map right after building it.

Apply:

     try {
-      // Populate available coins for the selector from SDK assets if empty
+      // Populate available coins for the selector from SDK assets if empty
       Map<AssetId, CoinPriceInfo> fetchedCexCoins = state.availableCoins;
       if (fetchedCexCoins.isEmpty) {
         final Map<AssetId, Asset> allAssets = _sdk.assets.available;
         final entries = allAssets.values
             .where((asset) => !excludedAssetList.contains(asset.id.id))
             .where((asset) => !asset.protocol.isTestnet)
             .map(
               (asset) => MapEntry(
                 asset.id,
                 CoinPriceInfo(
                   ticker: asset.id.symbol.assetConfigId,
                   selectedPeriodIncreasePercentage: 0.0,
                   id: asset.id.id,
                   name: asset.id.name,
                 ),
               ),
             );
         fetchedCexCoins = Map<AssetId, CoinPriceInfo>.fromEntries(entries);
+        // Ensure the selector is populated right away
+        emit(state.copyWith(availableCoins: fetchedCexCoins));
       }
lib/bloc/coins_bloc/coins_repo.dart (4)

128-131: Filtering excluded assets looks good.

This aligns getKnownCoins with app-config exclusions.

Consider also filtering out testnet assets here for consistency with chart filtering.


139-141: Consistent exclusion in map helper.

Mirrors the list variant correctly.

Same optional note about excluding testnets for parity with chart behavior.


556-582: Sequential per-asset requests will be slow; add bounded parallelism.

Fetching prices and 24h change one-by-one will not scale when unauthenticated (all assets). Extract a helper and process in chunks (e.g., 8–16 concurrency) to reduce total latency without overloading providers.

Example (outline):

Future<void> _fetchAndCache(Asset asset) async {
  final symbol = asset.id.symbol.configSymbol;
  final now = DateTime.now();
  final results = await Future.wait<Decimal?>([
    _kdfSdk.marketData.maybeFiatPrice(asset.id),
    _kdfSdk.marketData.priceChange24h(asset.id).catchError((_) => null),
  ], eagerError: false);
  final fiatPrice = results[0];
  final change24h = results[1];
  if (fiatPrice == null) return;
  final entry = CexPrice(assetId: asset.id, price: fiatPrice, lastUpdated: now, change24h: change24h);
  _pricesCache[symbol.toUpperCase()] = entry;
  _pricesCache[symbol] = entry; // backward-compat
}

final assets = validAssets.toList();
const batch = 12;
for (var i = 0; i < assets.length; i += batch) {
  final chunk = assets.sublist(i, (i + batch).clamp(0, assets.length));
  await Future.wait(chunk.map(_fetchAndCache), eagerError: false);
}

540-585: Return type can be non-nullable.

fetchCurrentPrices always returns _pricesCache; consider Future<Map<String, CexPrice>> to simplify callers.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 043e8d3 and 1b63921.

📒 Files selected for processing (3)
  • lib/bloc/cex_market_data/price_chart/price_chart_bloc.dart (2 hunks)
  • lib/bloc/coins_bloc/coins_repo.dart (2 hunks)
  • lib/shared/widgets/coin_select_item_widget.dart (1 hunks)
🧰 Additional context used
🧠 Learnings (5)
📓 Common learnings
Learnt from: takenagain
PR: KomodoPlatform/komodo-wallet#3109
File: lib/bloc/cex_market_data/profit_loss/profit_loss_bloc.dart:50-54
Timestamp: 2025-08-27T22:24:30.511Z
Learning: During SDK migration for CEX market data in Komodo Wallet, functionality like coin filtering for profit/loss charts was moved to the SDK. The app-level filtering was kept as a safety net until SDK behavior could be confirmed, particularly for test coin filtering.
📚 Learning: 2025-04-01T15:51:37.060Z
Learnt from: takenagain
PR: KomodoPlatform/komodo-wallet#2566
File: lib/bloc/coins_bloc/coins_bloc.dart:10-10
Timestamp: 2025-04-01T15:51:37.060Z
Learning: The `excludedAssetList` from `app_config.dart` is used in the `_filterExcludedAssets` method in `coins_state.dart`. Since `coins_state.dart` is a part file of `coins_bloc.dart`, the import needs to be in the parent file even though it's not directly used there. In Dart, part files share the namespace and imports of their parent files.

Applied to files:

  • lib/bloc/cex_market_data/price_chart/price_chart_bloc.dart
📚 Learning: 2025-04-01T15:51:37.060Z
Learnt from: takenagain
PR: KomodoPlatform/komodo-wallet#2566
File: lib/bloc/coins_bloc/coins_bloc.dart:10-10
Timestamp: 2025-04-01T15:51:37.060Z
Learning: In the Komodo Wallet project, part files share imports with their parent files. The import for `app_config.dart` in `coins_bloc.dart` is necessary because the part file `coins_state.dart` uses `excludedAssetList` from that package.

Applied to files:

  • lib/bloc/cex_market_data/price_chart/price_chart_bloc.dart
📚 Learning: 2025-08-31T19:24:53.317Z
Learnt from: CR
PR: KomodoPlatform/komodo-wallet#0
File: AGENTS.md:0-0
Timestamp: 2025-08-31T19:24:53.317Z
Learning: For Komodo DeFi Flutter SDK repository, reference `/KDF_API_DOCUMENTATION.md` and applicable RPCs, data structures, and notes when implementing RPC-related features

Applied to files:

  • lib/bloc/cex_market_data/price_chart/price_chart_bloc.dart
📚 Learning: 2025-05-01T21:00:36.970Z
Learnt from: takenagain
PR: KomodoPlatform/komodo-wallet#2608
File: lib/bloc/fiat/fiat_onramp_form/fiat_form_bloc.dart:2-3
Timestamp: 2025-05-01T21:00:36.970Z
Learning: It's acceptable to use unconditional `dart:io` imports in the Komodo wallet codebase when the usage is guarded by `!kIsWeb` conditional checks that prevent the platform-specific code from being executed in web environments.

Applied to files:

  • lib/bloc/cex_market_data/price_chart/price_chart_bloc.dart
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
  • GitHub Check: Build Desktop (linux)
  • GitHub Check: Build Desktop (windows)
  • GitHub Check: Build Mobile (Android)
  • GitHub Check: Build Mobile (iOS)
  • GitHub Check: Test web-app-linux-profile
  • GitHub Check: validate_code_guidelines
🔇 Additional comments (4)
lib/shared/widgets/coin_select_item_widget.dart (1)

94-96: Good fix for legibility with onSurface.

Using bodyMedium + onSurface makes the dropdown text readable in both themes. No further changes needed here.

lib/bloc/cex_market_data/price_chart/price_chart_bloc.dart (2)

32-37: Verify exclusion key type.

excludedAssetList is checked against asset.id.id. Confirm excludedAssetList indeed contains AssetId.id values (not configId/ticker) to avoid false negatives.


59-66: Potential off-by-one in time buckets.

List.generate uses floor division and excludes endAt. If the API expects an end-inclusive series, you may miss the last bucket. Consider ceil and/or explicitly appending endAt.

lib/bloc/coins_bloc/coins_repo.dart (1)

541-549: Asset target selection logic: sensible defaulting.

Preferring activated assets when signed in reduces load; falling back to all assets enables unauthenticated prices.

If all-assets is large, confirm provider rate limits are respected and UX remains acceptable.

Copy link
Copy Markdown

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

This PR is being reviewed by Cursor Bugbot

Details

You are on the Bugbot Free tier. On this plan, Bugbot will review limited PRs each billing cycle.

To receive Bugbot reviews on all of your PRs, please upgrade to Bugbot Pro by visiting the Cursor dashboard. Your first 14 days will be free!

);
final change24h = price?.change24h ?? Decimal.zero;
final change24h =
await _sdk.marketData.priceChange24h(coin.id) ?? Decimal.zero;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Bug: Direct SDK Call Without Error Handling

The _calculateTotalChange24h method now calls _sdk.marketData.priceChange24h directly within a loop. This call lacks exception handling, meaning if the SDK method throws an exception for any coin, the entire portfolio change calculation will fail. This is less resilient than the previous cached approach and inconsistent with error handling for the same SDK call elsewhere in the codebase.

Fix in Cursor Fix in Web

Copy link
Copy Markdown
Contributor

@takenagain takenagain left a comment

Choose a reason for hiding this comment

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

LGTM aside from two SDK-related issues that are out of scope for this PR,

  • VIA -> USDT Binance request error (coin not supported).
  • XRP and USDT activation failing with local debug builds
    [1] KDF: 13 12:00:09, mm2_main::rpc::dispatcher:128] ERROR RPC error response: platform_coin_with_tokens:455] prelude:116] eth_with_token_activation:106] Unexpected platform protocol {"type":"ERC20","protocol_data":{"platform":"ETH","contract_address":"0xdAC17F958D2ee523a2206206994597C13D831ec7"}} for USDT-ERC20 js_primitives.dart:28
    [1] KDF: 13 12:00:09, mm2_main::rpc::dispatcher:128] ERROR RPC error response: platform_coin_with_tokens:455] prelude:116] eth_with_token_activation:106] Unexpected platform protocol {"type":"ERC20","protocol_data":{"platform":"ETH","contract_address":"0x39fBBABf11738317a448031930706cd3e612e1B9"}} for XRP-ERC20 js_primitives.dart:28 
    

@smk762
Copy link
Copy Markdown
Collaborator

smk762 commented Sep 14, 2025

LGTM aside from two SDK-related issues that are out of scope for this PR,

  • VIA -> USDT Binance request error (coin not supported).
  • XRP and USDT activation failing with local debug builds
    [1] KDF: 13 12:00:09, mm2_main::rpc::dispatcher:128] ERROR RPC error response: platform_coin_with_tokens:455] prelude:116] eth_with_token_activation:106] Unexpected platform protocol {"type":"ERC20","protocol_data":{"platform":"ETH","contract_address":"0xdAC17F958D2ee523a2206206994597C13D831ec7"}} for USDT-ERC20 js_primitives.dart:28
    [1] KDF: 13 12:00:09, mm2_main::rpc::dispatcher:128] ERROR RPC error response: platform_coin_with_tokens:455] prelude:116] eth_with_token_activation:106] Unexpected platform protocol {"type":"ERC20","protocol_data":{"platform":"ETH","contract_address":"0x39fBBABf11738317a448031930706cd3e612e1B9"}} for XRP-ERC20 js_primitives.dart:28 
    

same issue as reported in #3129 (comment)

@smk762
Copy link
Copy Markdown
Collaborator

smk762 commented Sep 14, 2025

Confirmed prices and 24h change available in https://walletrc--pull-3138-merge-bfumakdv.web.app/wallet before login.
Confirmed prices available in https://walletrc--pull-3138-merge-bfumakdv.web.app/dex before login.

Price info appears to arrive much faster than before after login for auto-enabled coins 🎉, though adding extras still had some lag, including the case below where DGB/DGB-segwit were toggled to be activated at the same time, and despite sharing the same price, only one is displayed
image

This may be related
image

After second login, the above error was not shown (it seems to occur when entering a coin page before its ready, putting the coin in a broken state), though both LTC and DGB were a little slower to show pricing info than their segwit equivalents. For context, both non-segwit variants had zero balance, and the segwit variants were funded.

@CharlVS CharlVS changed the title Fix unauthenticated coin list and chart issues fix(coins): unauthenticated coin list and chart issues Sep 14, 2025
Co-authored-by: charl <charl@vanstaden.info>
@CharlVS CharlVS merged commit 49684f1 into dev Sep 15, 2025
17 of 27 checks passed
@CharlVS CharlVS deleted the cursor/fix-unauthenticated-coin-list-and-chart-issues-a7d0 branch September 15, 2025 12:09
@CharlVS CharlVS mentioned this pull request Oct 5, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants