Skip to content

feat(coin-updates): integrate komodo_coin_updates into komodo_coins#190

Merged
CharlVS merged 43 commits intodevfrom
feat/runtime-coin-updates
Aug 25, 2025
Merged

feat(coin-updates): integrate komodo_coin_updates into komodo_coins#190
CharlVS merged 43 commits intodevfrom
feat/runtime-coin-updates

Conversation

@takenagain
Copy link
Copy Markdown
Contributor

@takenagain takenagain commented Aug 14, 2025

  • Refactors komodo_coin_updates to use Asset for storage and retrieval, removing most of the legacy models and adapters in the process.
  • Migrates komodo_coin_updates to hive_ce.
  • Adds support for reading build_config.json to komodo_coin_updates to read the coin configuration settings.
  • Adds unit test coverage for both komodo_coin_updates and komodo_coins to validate the desired functionality works as expected.
  • Adds GPT5-generated documentation to the komodo_coin_updates package.
  • Integrates komodo_coin_updates into komodo_coins, replacing the hard-coded URL bypassing any local coin config files.
  • Adds the current and latest commit hash to the SDK example app as a demonstration and for testing purposes.
  • Adds a GitHub workflow to run the unit tests in each of the packages as an automated test case for open PRs and pushes to main. This workflow also allows for manual dispatch with a filter to only run one package at a time.
Screen.Recording.2025-08-22.at.17.02.07.mov

Local testing

  1. Update packages/komodo_defi_framework/assets/config with the contents of coins_config.json from 23b16a0.

  2. Modify the following values in packages/komodo_defi_framework/app_build/build_config.json with the following values. This will prevent the coins_config.json from being overridden with an updated version at build time.

     "fetch_at_build_enabled": false,
     "update_commit_on_build": false,
     "bundled_coins_repo_commit": "23b16a00557b914ca73b030ce77968c4de401b9f",
  3. Register a new account.

  4. Search for "NYC" and "DIMI". Confirm that "NYC" does not have a UTXO/Smart coin and "DIMI" cannot be activated due to missing derivation path.

  5. Refresh page and sign back in.

  6. Search for "NYC" and "DIMI" again and confirm that NYC now has a UTXO coin and "DIMI" can now be activated.

Summary by CodeRabbit

  • New Features
    • Pluggable coin config system with GitHub/local providers, Hive-backed storage, and auto-update manager.
    • Commit tracking surfaced; example app shows current vs latest commit.
    • Startup provider to supply raw coins for initialization.
    • Typed sparkline caching with recovery and request de-duplication.
  • Changes
    • Seed node fetching now requires a runtime config parameter.
  • Documentation
    • Extensive docs and examples for configuration, usage, advanced transforms, FAQs, and market-data rate limiting.
  • Tests
    • Broad unit/integration coverage across providers, storage, update strategies, caching, and CI matrix.
  • Chores
    • New GitHub Actions for Flutter tests; env token wiring for web builds.

@takenagain takenagain self-assigned this Aug 14, 2025
@takenagain takenagain added the enhancement New feature or request label Aug 14, 2025
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Aug 14, 2025

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.

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.

Walkthrough

Refactors coin configuration handling across packages: introduces provider/repository architecture using Asset models and Hive CE, removes legacy Coin/CoinConfig models/adapters, adds generated Hive registrar, new runtime config loader, new asset/update managers and strategies in komodo_coins, integrates into SDK, enhances CEX market data caching with typed Hive, updates CI workflows/docs, and adjusts build transformer/CDN handling.

Changes

Cohort / File(s) Summary
Repo/workflow/docs
./.github/workflows/*, docs/*, packages/**/README.md, packages/**/analysis_options.yaml, packages/**/index_generator.yaml, packages/**/.gitignore
Adds Flutter tests matrix workflow; passes GitHub token env; extensive new docs and indices; ignore/build configs updated.
Public API re-exports (komodo_coin_updates)
packages/komodo_coin_updates/lib/komodo_coin_updates.dart, .../src/data/data.dart, .../lib/src/coins_config/_coins_config_index.dart, .../lib/src/runtime_update_config/_runtime_update_config_index.dart
Reorganizes exports to new coins_config and runtime_update_config surfaces; removes legacy data/models barrels.
Data layer refactor (providers/repository/storage)
packages/komodo_coin_updates/lib/src/coins_config/{coin_config_provider.dart,github_coin_config_provider.dart,local_asset_coin_config_provider.dart,coin_config_repository.dart,coin_config_repository_factory.dart,coin_config_storage.dart,asset_parser.dart,config_transform.dart}
Introduces pluggable providers (GitHub/local), repository with Hive-backed storage, asset parser, instance-based transform pipeline, and a creation factory.
Runtime update config loader
packages/komodo_coin_updates/lib/src/runtime_update_config/asset_runtime_update_config_repository.dart
Adds repository to load build-time runtime config from asset bundle.
Hive CE adapters/registrar/init
packages/komodo_coin_updates/lib/hive/hive_adapters.dart, .../lib/hive/hive_registrar.g.dart, .../lib/src/komodo_coin_updater.dart, .../test/hive/*
Adds manual AssetAdapter, generated registrar, and updater to register adapters (main and isolates); tests cover roundtrip/put/delete.
Legacy models/adapters removal
packages/komodo_coin_updates/lib/src/models/*, .../lib/src/models/adapters/*, .../lib/src/persistence/*
Removes Coin/CoinConfig and related adapters, persistence provider/box providers, and associated types.
Tests (komodo_coin_updates)
packages/komodo_coin_updates/test/*, .../integration_test/*, .../example/*
Adds extensive unit/integration tests for providers, repository, transforms, registrars, runtime config model/repo, seed nodes example adjusted to require config.
komodo_coins new managers/strategies
packages/komodo_coins/lib/komodo_coins.dart, .../lib/src/{asset_management/*,update_management/*,startup/startup_coins_provider.dart,asset_filter.dart}, .../test/*
Adds CoinConfigManager, update manager with strategies, loading strategies/sources, startup provider; tightens trezor filter; removes old KomodoCoins class; new tests.
SDK integration
packages/komodo_defi_sdk/lib/src/{bootstrap.dart,assets/asset_manager.dart}, .../example/lib/*
Wires KomodoAssetsUpdateManager into DI and AssetManager; exposes current/latest commits; example UI shows commit info; adds logging bridge.
Types updates (komodo_defi_types)
packages/komodo_defi_types/lib/src/assets/{asset.dart,asset_id.dart}, .../src/runtime_update_config/*, .../src/utils/json_type_utils.dart
Asset.fromJson accepts knownIds; removes AssetId.parseAllTypes; adds Freezed models for runtime update config; adds convertToJsonMap utility.
CEX Market Data (Hive CE + caching)
packages/komodo_cex_market_data/lib/src/{hive_adapters*.{dart,g.dart,g.yaml},models/sparkline_data.dart,sparkline_repository.dart,hive_registrar.g.dart,repository_priority_manager.dart}, .../build.yaml, .../pubspec.yaml, .../README.md, .../example/*, .../test/*
Migrates to Hive CE; introduces typed SparklineData caching, registrar, init/recovery, request dedup; adds rate-limit aware fallback mixin; example and tests updated.
Build transformer & tests
packages/komodo_wallet_build_transformer/lib/src/steps/fetch_coin_assets_build_step.dart, .../test/steps/*
Uses effectiveContentUrl without mutating config; extensive tests for CDN mirrors and downloader behavior; cleans obsolete test.
Framework config/seed nodes
packages/komodo_defi_framework/app_build/build_config.json, .../lib/src/services/seed_node_service.dart, packages/komodo_coin_updates/lib/src/seed_node_updater.dart, .../example/seed_nodes_example.dart
Updates bundled commit and content URL; seed nodes fetch now config-driven via AssetRuntimeUpdateConfig.buildContentUrl; service loads config and forwards it.
Pubspecs
packages/*/pubspec.yaml, packages/komodo_coins/pubspec_overrides.yaml, packages/komodo_defi_sdk/example/pubspec.yaml
Switches to hive_ce, adds dependencies (freezed/json/logging/etc.), adds local path dependency on komodo_coin_updates, adds komodo_cex_market_data to example.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor App
  participant SDK as KomodoAssetsUpdateManager
  participant Cfg as AssetRuntimeUpdateConfigRepository
  participant Factory as CoinConfigDataFactory
  participant Repo as CoinConfigRepository
  participant ProvG as GithubCoinConfigProvider
  participant ProvA as LocalAssetCoinConfigProvider
  participant Hive as Hive (assets/settings)

  App->>SDK: init()
  SDK->>Cfg: load()
  Cfg-->>SDK: AssetRuntimeUpdateConfig
  SDK->>Factory: createRepository(config, transformer)
  Factory-->>SDK: Repo
  SDK->>Factory: createLocalProvider(config)
  Factory-->>SDK: ProvA
  SDK->>Repo: updatedAssetStorageExists()
  alt storage empty
    SDK->>ProvA: getAssets()
    ProvA-->>SDK: [Asset]
    SDK->>Hive: upsertAssets + commit (bundled)
  else storage present
    SDK->>ProvG: getLatestCommit()
    ProvG-->>SDK: latest SHA
    SDK->>Repo: isLatestCommit()
    alt outdated
      SDK->>Repo: updateCoinConfig()
      Repo->>ProvG: getAssetsForCommit(latest)
      ProvG-->>Repo: [Asset]
      Repo->>Hive: upsertAssets + commit (latest)
    else up-to-date
      SDK-->>App: init complete
    end
  end
  SDK-->>App: assets available
Loading
sequenceDiagram
  autonumber
  actor App
  participant Upd as StrategicCoinUpdateManager
  participant Strat as UpdateStrategy
  participant Repo as CoinConfigRepository
  participant ProvG as CoinConfigProvider (fallback)

  App->>Upd: startBackgroundUpdates()
  loop every updateInterval
    Upd->>Strat: shouldUpdate(requestType=background, repo, times, commits)
    Strat-->>Upd: true/false
    alt true
      Upd->>Repo: updateCoinConfig()
      Repo-->>Upd: done
      Upd->>Repo: getCurrentCommit()
      Repo-->>Upd: new SHA
      Upd-->>App: emit UpdateResult(success, counts, hashes)
    else false
      Upd-->>App: no-op
    end
  end

  App->>Upd: getLatestCommitHash()
  Upd->>Repo: isLatestCommit()
  alt error or null
    Upd->>ProvG: getLatestCommit()
    ProvG-->>Upd: latest SHA
  end
Loading

Estimated code review effort

🎯 5 (Critical) | ⏱️ ~180 minutes

Possibly related PRs

Suggested reviewers

  • smk762
  • CharlVS

Poem

I hop through commits with whiskered grace,
New boxes burrow, adapters in place.
Coins now update while I sip my tea,
From GitHub trees to Hive’s cozy key.
CDN winds at my floppy ears—
“Latest!” I cheer, tail full of gears. 🐇✨

✨ Finishing Touches
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/runtime-coin-updates

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
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@takenagain takenagain requested a review from Copilot August 14, 2025 17:10
@takenagain
Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Aug 14, 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.

This comment was marked as outdated.

coderabbitai[bot]

This comment was marked as outdated.

@takenagain takenagain changed the title feat(coin-updates): integrate komodo_coin_updates into komodo_coins @takenagain feat(coin-updates): integrate komodo_coin_updates into komodo_coins Aug 15, 2025
Comment thread .github/workflows/flutter-tests.yml Fixed
Comment thread .github/workflows/flutter-tests.yml Fixed
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 refactors the coin management system to replace the legacy komodo_coins implementation with komodo_coin_updates, introducing a comprehensive asset runtime update system. The primary goal is to enable runtime coin configuration updates while maintaining backward compatibility and improving test coverage.

  • Integrates komodo_coin_updates package for runtime asset management with GitHub/CDN providers
  • Replaces hard-coded coin configuration with dynamic build configuration reading
  • Adds comprehensive unit test coverage with asset config builders and mock implementations
  • Migrates to hive_ce for persistent storage with automatic adapter registration

Reviewed Changes

Copilot reviewed 154 out of 155 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
packages/komodo_defi_types/test/utils/asset_config_builders.dart Test utility builders for creating asset configurations in tests
packages/komodo_defi_types/test/assets/asset_roundtrip_test.dart JSON serialization roundtrip tests using asset config builders
packages/komodo_coins/test/*.dart Comprehensive test suite for coin management strategies and fallback behavior
packages/komodo_defi_sdk/lib/src/assets/asset_manager.dart Integration of new KomodoAssetsUpdateManager with commit hash exposure
packages/komodo_defi_framework/lib/src/config/kdf_startup_config.dart Updated to use StartupCoinsProvider instead of legacy KomodoCoins
Comments suppressed due to low confidence (1)

packages/komodo_defi_types/lib/src/types.dart:35

  • The removal of 'protocols/base/protocol_class.dart' export could be a breaking change if other packages depend on this export. Consider adding a deprecation notice before removing public exports.
export 'protocols/erc20/erc20_protocol.dart';

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

Comment thread packages/komodo_defi_types/lib/src/utils/json_type_utils.dart Outdated
Comment thread packages/komodo_defi_types/lib/src/utils/json_type_utils.dart
Comment thread packages/komodo_defi_types/lib/src/assets/asset.dart
Comment thread packages/komodo_defi_framework/app_build/build_config.json
@takenagain
Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Aug 21, 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: 38

Caution

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

⚠️ Outside diff range comments (3)
packages/komodo_coin_updates/docs/testing.md (1)

42-42: Remove stray trailing “42”.

This appears to be an accidental artifact at EOF.

-42
packages/komodo_coin_updates/lib/src/coins_config/config_transform.dart (1)

172-191: Deep-copy entries and filter by protocol, not presence of ws_url

  • Today you mutate each element map in-place and use ws_url as the filter sentinel. If an incoming non-WSS entry happens to carry a ws_url, it will be incorrectly filtered.
  • Clone each entry map before normalization to avoid aliasing originals, then filter using the protocol field.
-  JsonList filterElectrums(
+  JsonList filterElectrums(
     JsonList electrums, {
       required ElectrumServerType serverType,
   }) {
-    final electrumsCopy = JsonList.of(electrums);
-
-    for (final e in electrumsCopy) {
-      if (e['protocol'] == 'WSS') {
-        e['ws_url'] = e['url'];
-      }
-    }
-
-    return electrumsCopy..removeWhere(
-      (JsonMap e) =>
-          serverType == ElectrumServerType.wssOnly
-              ? e['ws_url'] == null
-              : e['ws_url'] != null,
-    );
+    // Clone each entry map to avoid mutating shared references.
+    final electrumsCopy = JsonList.of(
+      electrums.map<JsonMap>((e) => JsonMap.of(e)).toList(),
+    );
+
+    for (final e in electrumsCopy) {
+      if ((e['protocol'] as String?) == 'WSS') {
+        e['ws_url'] = e['url'];
+      } else {
+        e.remove('ws_url'); // keep normalized shape
+      }
+    }
+
+    // Filter using protocol for correctness.
+    return electrumsCopy
+      ..removeWhere((JsonMap e) => serverType == ElectrumServerType.wssOnly
+          ? e['protocol'] != 'WSS'
+          : e['protocol'] == 'WSS');
   }
packages/komodo_coin_updates/docs/providers.md (1)

51-55: Fix minor grammar/whitespace; add a security note on tokens.

Tighten the sentence and remind readers not to hardcode tokens.

-## Testing providers
+## Testing providers
@@
-- Inject `http.Client` in GitHub provider and `AssetBundle` in local provider to
-  supply fakes/mocks in tests.
+- Inject `http.Client` in the GitHub provider and `AssetBundle` in the local provider to supply fakes/mocks in tests.
+
+> Note: Never hardcode a personal access token in source code or assets. Prefer environment variables or encrypted CI secrets.
♻️ Duplicate comments (4)
packages/komodo_defi_sdk/example/lib/blocs/coins_commit/coins_commit_cubit.dart (1)

18-24: Null-safety in truncated getters: avoid ! on nullable values

While ?. short-circuits, the current!.length/latest!.length reads are still brittle and flagged by analyzers. Use a local variable to compute safely.

-  String? get currentTruncated =>
-      current?.substring(0, current!.length >= 7 ? 7 : current!.length);
+  String? get currentTruncated {
+    final value = current;
+    if (value == null) return null;
+    final end = value.length >= 7 ? 7 : value.length;
+    return value.substring(0, end);
+  }
 
   /// Returns the latest commit hash truncated to 7 characters
-  String? get latestTruncated =>
-      latest?.substring(0, latest!.length >= 7 ? 7 : latest!.length);
+  String? get latestTruncated {
+    final value = latest;
+    if (value == null) return null;
+    final end = value.length >= 7 ? 7 : value.length;
+    return value.substring(0, end);
+  }
packages/komodo_cex_market_data/lib/src/hive_adapters.dart (1)

1-2: Uses Hive CE API — ensure runtime dependency aligns

This file imports package:hive_ce/hive.dart. Per my comment in pubspec.yaml, add a runtime dependency on hive_ce and remove hive to avoid mixed APIs.

packages/komodo_defi_framework/app_build/build_config.json (1)

68-69: Raw GitHub as primary content origin: validate rate limits and add commit-pinned fetches

Switching coins_repo_content_url to raw.githubusercontent.com trades CDN caching for direct origin. Ensure:

  • The provider builds content URLs using the pinned commit (when available) instead of branch paths to avoid TOCTOU and reduce cache churn.
  • There is robust fallback to the CDN mirrors already listed in cdn_branch_mirrors.

Run to confirm URL construction and fallback ordering:

#!/bin/bash
set -euo pipefail

# 1) Find where coins_repo_content_url is consumed
rg -n --pretty --glob 'packages/**' 'coins_repo_content_url|coinsGithubContentUrl|GithubCoinConfigProvider|fromConfig' -C3

# 2) Inspect URL assembly for commit vs branch use
rg -n --pretty --glob 'packages/**' -C3 \
  -e 'raw\.githubusercontent\.com' \
  -e 'coins_repo_branch' \
  -e 'bundled_coins_repo_commit' \
  -e 'update_commit_on_build'

# 3) Verify any fallback ordering that prefers CDN mirrors
rg -n --pretty --glob 'packages/**' -C3 'cdn_branch_mirrors'

Note: This echoes concerns previously raised about CDN vs raw GitHub reliability. Validating commit-pinned usage would address most of the risk.

packages/komodo_defi_types/lib/src/assets/asset.dart (1)

28-28: Clarification on past concern

The earlier suggestion about a separate factory for compatibility isn’t necessary here: adding an optional named parameter in Dart does not break existing call sites.

Comment thread .github/workflows/firebase-hosting-pull-request.yml
Comment thread packages/komodo_cex_market_data/lib/src/hive_adapters.dart
Comment thread packages/komodo_cex_market_data/lib/src/sparkline_repository.dart
Comment thread packages/komodo_cex_market_data/lib/src/sparkline_repository.dart
Comment thread packages/komodo_cex_market_data/pubspec.yaml Outdated
Comment thread packages/komodo_coins/test/komodo_coins_cache_behavior_test.dart Outdated
Comment thread packages/komodo_coins/test/strategic_coin_update_manager_test.dart
Comment thread packages/komodo_defi_types/lib/src/assets/asset_id.dart
@takenagain
Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Aug 22, 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: 20

Caution

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

⚠️ Outside diff range comments (4)
packages/komodo_defi_sdk/test/src/market_data/edge_cases/repository_supports_filtering_test.dart (1)

566-568: Fix call to non-existent method.

The test calls recordRepositoryFailureForTest method which doesn't exist on the TestSupportFilteringManager. This should use the new triggerRepositoryFailures method instead.

        // Make Binance unhealthy; since health is keyed by runtimeType, all mocks become unhealthy
-       for (int i = 0; i < 3; i++) {
-         testManager.recordRepositoryFailureForTest(mockBinanceRepo);
-       }
+       when(
+         () => mockBinanceRepo.getCoinFiatPrice(any()),
+       ).thenThrow(Exception('Binance failed'));
+       await testManager.triggerRepositoryFailures(mockBinanceRepo, 4);
packages/komodo_wallet_build_transformer/lib/src/steps/fetch_coin_assets_build_step.dart (2)

121-144: Fix broken URL in user-facing error message

The repository link is misspelled (KomodPlatform missing “o”). Broken link in a build-stop error message is frustrating for users following remediation steps.

Apply:

-        https://github.com/KomodPlatform/flutter
+        https://github.com/KomodoPlatform/flutter

209-221: Prefix mapped file and folder paths with artifactOutputDirectory

The current implementation passes raw keys from config.mappedFiles and config.mappedFolders (e.g. "assets/icons") directly to _getFilesInFolder and revertOrDeleteGitFiles. Those keys are relative to the configured artifact directory, so Git operations will target the wrong paths (or delete unintended project files) instead of the downloaded assets.

Apply this patch to ensure both file and folder paths are rooted at artifactOutputDirectory:

--- a/packages/komodo_wallet_build_transformer/lib/src/steps/fetch_coin_assets_build_step.dart
+++ b/packages/komodo_wallet_build_transformer/lib/src/steps/fetch_coin_assets_build_step.dart
@@ -209,8 +209,15 @@
     _log.info(
       'Reverting fetch coin assets build step. '
       'Reverting or deleting downloaded files.',
     );

-    final mappedFilePaths = config.mappedFiles.keys.toList();
-    final mappedFolderPaths = config.mappedFolders.keys.toList();
+    final mappedFilePaths = config.mappedFiles.keys
+        .map((p) => path.join(artifactOutputDirectory, p))
+        .toList();
+    final mappedFolderPaths = config.mappedFolders.keys
+        .map((p) => path.join(artifactOutputDirectory, p))
+        .toList();

     final mappedFolderFilePaths = mappedFolderPaths.map(_getFilesInFolder);

     final allFiles =
         mappedFilePaths +
         mappedFolderFilePaths.expand((List<String> x) => x).toList();

     await GitHubFileDownloader.revertOrDeleteGitFiles(allFiles);
  • This ensures revertOrDeleteGitFiles operates on the actual locations where assets were written.
  • No further changes to _getFilesInFolder or import statements are required, as path.join is already available.
packages/komodo_coin_updates/lib/src/coins_config/config_transform.dart (1)

33-50: Re-evaluate needsTransform after each transform (avoid pre-filtering pitfall)

Filtering the transforms once against the original config can skip later transforms whose preconditions only become true after an earlier transform. Evaluate needsTransform against the evolving config in sequence.

-  /// Applies all necessary transforms to the given coin configuration.
-  JsonMap apply(JsonMap config) {
-    final neededTransforms = _transforms.where((t) => t.needsTransform(config));
-
-    if (neededTransforms.isEmpty) {
-      return config;
-    }
-
-    return neededTransforms.fold(
-      config,
-      // Instantiating a new map for each transform is not ideal, given the
-      // large size of the config file. However, it is necessary to avoid
-      // mutating the original map and for making the transforms idempotent.
-      // Use sparingly and ideally only once.
-      (config, transform) => transform.transform(JsonMap.of(config)),
-    );
-  }
+  /// Applies all necessary transforms to the given coin configuration.
+  JsonMap apply(JsonMap config) {
+    var out = config;
+    for (final t in _transforms) {
+      if (t.needsTransform(out)) {
+        // Copy to preserve idempotency and avoid mutating caller state
+        out = t.transform(JsonMap.of(out));
+      }
+    }
+    return out;
+  }
♻️ Duplicate comments (12)
.github/workflows/firebase-hosting-pull-request.yml (2)

58-60: Nice: token parity for Playground dry/build steps.

This addresses prior rate-limit failures by ensuring the same token context as the SDK example build.


89-91: LGTM: consistent token usage for the SDK example build.

Parity achieved; this should prevent intermittent GitHub API rate-limit issues during asset generation.

packages/komodo_coins/lib/src/asset_management/coin_config_manager.dart (1)

1-9: Add missing import for firstOrNull (will not compile otherwise).

This file uses Iterable.firstOrNull (Lines 292–296) but doesn’t import the extension provider. Unless a higher-level library re-exports it, this won’t compile. Add the collection import here. Also verify sibling usage in loading_strategy.dart if present.

Apply this diff:

 import 'dart:async';
 import 'dart:collection';
 
+import 'package:collection/collection.dart';
 import 'package:komodo_coins/src/asset_filter.dart';
 import 'package:komodo_coins/src/asset_management/coin_config_fallback_mixin.dart';
 import 'package:komodo_coins/src/asset_management/loading_strategy.dart';

Run to confirm whether a re-export already exists (if so, this import is redundant but harmless):

#!/bin/bash
# Check for re-exports that might already expose Iterable.firstOrNull
rg -nP "export\s+['\"]package:collection/collection.dart['\"]" -C2
# Confirm all files that use firstOrNull have an import or are covered by a re-export
rg -nP --type=dart '\bfirstOrNull\b' -C2
packages/komodo_defi_sdk/example/lib/blocs/coins_commit/coins_commit_cubit.dart (1)

18-24: Avoid forced null checks in substring args; make truncation null-safe and DRY

-  /// Returns the current commit hash truncated to 7 characters
-  String? get currentTruncated =>
-      current?.substring(0, current!.length >= 7 ? 7 : current!.length);
+  /// Returns the current commit hash truncated to 7 characters
+  String? get currentTruncated {
+    final s = current;
+    if (s == null) return null;
+    final len = s.length;
+    return s.substring(0, len >= 7 ? 7 : len);
+  }
 
-  /// Returns the latest commit hash truncated to 7 characters
-  String? get latestTruncated =>
-      latest?.substring(0, latest!.length >= 7 ? 7 : latest!.length);
+  /// Returns the latest commit hash truncated to 7 characters
+  String? get latestTruncated {
+    final s = latest;
+    if (s == null) return null;
+    final len = s.length;
+    return s.substring(0, len >= 7 ? 7 : len);
+  }

Optional: factor the logic into a private helper to remove duplication:

String? _truncate7(String? s) {
  if (s == null) return null;
  final len = s.length;
  return s.substring(0, len >= 7 ? 7 : len);
}
packages/komodo_coin_updates/README.md (1)

16-29: Installation section conflicts with unpublished package status; show path/git dependency instead of dart pub add.

This repo sets publish_to: none, so dart pub add and a versioned pubspec.yaml entry are misleading. Replace with monorepo path and external git usage examples.

Apply this update:

-## Installation
-
-Preferred (adds the latest compatible version):
-
-```sh
-dart pub add komodo_coin_updates
-```
-
-Or manually in `pubspec.yaml`:
-
-```yaml
-dependencies:
-  komodo_coin_updates: ^latest
-```
+## Installation
+
+Add the dependency and import the library.
+
+If you are in this monorepo:
+
+```yaml
+dependencies:
+  komodo_coin_updates:
+    path: packages/komodo_coin_updates
+```
+
+If you consume from another repo (unpublished):
+
+```yaml
+dependencies:
+  komodo_coin_updates:
+    git:
+      url: https://github.com/KomodoPlatform/komodo-defi-sdk-flutter.git
+      path: packages/komodo_coin_updates
+      ref: dev
+```
packages/komodo_cex_market_data/lib/src/sparkline_repository.dart (2)

147-151: Cache check implementation looks correct.

The current implementation properly checks the typed cache through _getCachedSparkline, which handles both positive and negative cache entries as noted in past review comments.


272-305: Typed cache implementation is correct.

The _getCachedSparkline method properly reads from the typed Box<SparklineData> and handles:

  • Type checking with cleanup of unexpected types
  • Expiry checking with automatic deletion
  • Returning immutable copies of cached data
  • Proper error handling

This addresses the issues noted in past review comments about cache misses and negative cache handling.

packages/komodo_coins/lib/src/update_management/coin_update_manager.dart (1)

195-221: Serialize updates to prevent overlapping immediate/background runs

updateNow() can overlap with the periodic background timer’s _performBackgroundUpdate(), causing duplicate work and possible repository races. Introduce an in-flight future and route both paths through it to serialize updates. This also deduplicates concurrent immediate calls.

Apply (excerpt):

@@
   DateTime? _lastUpdateTime;
+  Future<UpdateResult>? _inFlightUpdate;
@@
   Future<UpdateResult> updateNow() async {
@@
-    final result = await retry(
-      () => _performUpdate(UpdateRequestType.immediateUpdate),
+    final result = await retry(
+      () => _runSerialized(UpdateRequestType.immediateUpdate),
       maxAttempts: 3,
@@
     return result;
   }
+
+  // Ensures only one update runs at a time. Background requests are skipped
+  // if an update is already in flight; immediate requests will await it.
+  Future<UpdateResult> _runSerialized(UpdateRequestType requestType) async {
+    final inflight = _inFlightUpdate;
+    if (inflight != null) {
+      if (requestType == UpdateRequestType.backgroundUpdate) {
+        _logger.finer('Update in flight; skipping background request.');
+        return const UpdateResult(success: true, updatedAssetCount: 0);
+      }
+      try {
+        await inflight;
+      } catch (_) {
+        // ignore; we'll attempt our own update
+      }
+    }
+    final completer = Completer<UpdateResult>();
+    _inFlightUpdate = completer.future;
+    try {
+      final result = await _performUpdate(requestType);
+      completer.complete(result);
+      return result;
+    } catch (e, s) {
+      completer.completeError(e, s);
+      rethrow;
+    } finally {
+      _inFlightUpdate = null;
+    }
+  }

And in the background path:

-      final result = await _performUpdate(UpdateRequestType.backgroundUpdate);
+      final result = await _runSerialized(UpdateRequestType.backgroundUpdate);

Check if a similar serializer already exists elsewhere:

#!/bin/bash
rg -nP '\b_inFlightUpdate\b|_runSerialized\b|serialize[d]?\b' packages
rg -nP '(updateNow\(\)|_performBackgroundUpdate\(\))' packages/komodo_coins/lib/src/update_management/coin_update_manager.dart -n -C3
packages/komodo_coins/test/strategic_coin_update_manager_test.dart (2)

441-459: Nice: deterministic stream test using expectLater/emits

This removes flakiness from arbitrary delays and validates the emission precisely.


489-507: Nice: deterministic stream test for fresh manager

Same improvement here — reliable, delay-free stream assertions.

packages/komodo_coin_updates/test/seed_node_updater_test.dart (1)

37-44: Good fix: use const SeedNode and realistic contact email

Switching to const constructors and replacing empty-string email with a realistic test address improves immutability and clarity. This resolves the prior nit.

Also applies to: 45-52

packages/komodo_coin_updates/docs/getting-started.md (1)

26-28: Fix example imports: add komodo_defi_types for AssetRuntimeUpdateConfig

The sample uses AssetRuntimeUpdateConfig but only imports komodo_coin_updates; the snippet won’t compile without importing the type from komodo_defi_types.

Apply this diff to the snippet:

 ```dart
-import 'package:komodo_coin_updates/komodo_coin_updates.dart';
+import 'package:komodo_coin_updates/komodo_coin_updates.dart';
+import 'package:komodo_defi_types/komodo_defi_types.dart'
+    show AssetRuntimeUpdateConfig;

</blockquote></details>

</blockquote></details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->

Comment thread packages/komodo_cex_market_data/example/komodo_cex_market_data_example.dart Outdated
Comment thread packages/komodo_cex_market_data/test/sparkline_repository_test.dart Outdated
Comment thread packages/komodo_coin_updates/docs/getting-started.md Outdated
Comment thread packages/komodo_coin_updates/lib/src/seed_node_updater.dart
Comment thread packages/komodo_coin_updates/README.md
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.

Bugbot free trial expires on August 22, 2025
Learn more in the Cursor dashboard.

Comment thread packages/komodo_cex_market_data/lib/src/sparkline_repository.dart
…t blocking (#207)

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
@takenagain takenagain requested a review from CharlVS August 22, 2025 16:33
@CharlVS CharlVS merged commit 3090619 into dev Aug 25, 2025
6 of 9 checks passed
@CharlVS CharlVS deleted the feat/runtime-coin-updates branch August 25, 2025 12:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants