-
Notifications
You must be signed in to change notification settings - Fork 13
feat(coin-config): add custom token support to coin config manager #225
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
Merged
Merged
Changes from 1 commit
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
bc4e6ed
feat(coin-config): add custom token support to coin config manager
takenagain 24bacdc
fix(custom-token-storage): add recovery for closed box from startup
takenagain 2220afe
fix(custom-token-storage): add no-op storage and set flag from storage
takenagain 5013348
refactor(review): rename interface, remove unnecessary async
takenagain f81233e
Merge remote-tracking branch 'origin/dev' into feat/config-custom-tok…
takenagain File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
146 changes: 146 additions & 0 deletions
146
packages/komodo_coin_updates/lib/src/coins_config/custom_token_storage.dart
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,146 @@ | ||
| import 'package:hive_ce/hive.dart'; | ||
| import 'package:komodo_coin_updates/src/coins_config/custom_token_storage_interface.dart'; | ||
| import 'package:komodo_defi_types/komodo_defi_types.dart'; | ||
| import 'package:logging/logging.dart'; | ||
|
|
||
| /// Storage for custom tokens that are not part of the official coin configuration. | ||
| /// These tokens are persisted independently from the main coin configuration | ||
| /// and are not affected by coin config updates. | ||
| class CustomTokenStorage implements ICustomTokenStorage { | ||
| /// Creates a custom token storage instance. | ||
| /// [customTokensBoxName] is the name of the Hive box for storing custom tokens. | ||
| /// [customTokensBox] is an optional pre-opened LazyBox for testing/mocking. | ||
| CustomTokenStorage({ | ||
| this.customTokensBoxName = 'custom_tokens', | ||
| LazyBox<Asset>? customTokensBox, | ||
| }) : _customTokensBox = customTokensBox; | ||
|
|
||
| static final Logger _log = Logger('CustomTokenStorage'); | ||
|
|
||
| /// The name of the Hive box for custom tokens. | ||
| final String customTokensBoxName; | ||
|
|
||
| LazyBox<Asset>? _customTokensBox; | ||
|
|
||
| @override | ||
| Future<void> storeCustomToken(Asset asset) async { | ||
| _log.fine('Storing custom token ${asset.id.id}'); | ||
| final box = await _openCustomTokensBox(); | ||
| await box.put(asset.id.id, asset); | ||
| } | ||
|
|
||
| @override | ||
| Future<void> storeCustomTokens(List<Asset> assets) async { | ||
| _log.fine('Storing ${assets.length} custom tokens'); | ||
| final box = await _openCustomTokensBox(); | ||
| final putMap = <String, Asset>{for (final a in assets) a.id.id: a}; | ||
| await box.putAll(putMap); | ||
| } | ||
|
|
||
| @override | ||
| Future<List<Asset>> getAllCustomTokens() async { | ||
| _log.fine('Retrieving all custom tokens'); | ||
| final box = await _openCustomTokensBox(); | ||
| final keys = box.keys; | ||
| final values = await Future.wait( | ||
| keys.map((dynamic key) => box.get(key as String)), | ||
| ); | ||
| return values.whereType<Asset>().toList(); | ||
| } | ||
|
|
||
| @override | ||
| Future<Asset?> getCustomToken(AssetId assetId) async { | ||
| _log.fine('Retrieving custom token ${assetId.id}'); | ||
| final box = await _openCustomTokensBox(); | ||
| return await box.get(assetId.id); | ||
| } | ||
|
|
||
| @override | ||
| Future<bool> hasCustomToken(AssetId assetId) async { | ||
| final box = await _openCustomTokensBox(); | ||
| return box.containsKey(assetId.id); | ||
| } | ||
|
|
||
| @override | ||
| Future<void> deleteCustomToken(AssetId assetId) async { | ||
| _log.fine('Deleting custom token ${assetId.id}'); | ||
| final box = await _openCustomTokensBox(); | ||
| await box.delete(assetId.id); | ||
| } | ||
|
|
||
| @override | ||
| Future<void> deleteCustomTokens(List<AssetId> assetIds) async { | ||
| _log.fine('Deleting ${assetIds.length} custom tokens'); | ||
| final box = await _openCustomTokensBox(); | ||
| await box.deleteAll(assetIds.map((id) => id.id)); | ||
| } | ||
|
|
||
| @override | ||
| Future<void> deleteAllCustomTokens() async { | ||
| _log.fine('Deleting all custom tokens'); | ||
| final box = await _openCustomTokensBox(); | ||
| await box.clear(); | ||
| } | ||
|
|
||
| @override | ||
| Future<bool> hasCustomTokens() async { | ||
| final boxExists = await Hive.boxExists(customTokensBoxName); | ||
| if (!boxExists) { | ||
| return false; | ||
| } | ||
|
|
||
| final box = await Hive.openLazyBox<Asset>(customTokensBoxName); | ||
| return box.isNotEmpty; | ||
| } | ||
|
|
||
| @override | ||
| Future<bool> updateCustomToken(Asset asset) async { | ||
| final box = await _openCustomTokensBox(); | ||
| final existed = box.containsKey(asset.id.id); | ||
| await box.put(asset.id.id, asset); | ||
|
|
||
| if (existed) { | ||
| _log.fine('Updated existing custom token ${asset.id.id}'); | ||
| } else { | ||
| _log.fine('Stored new custom token ${asset.id.id}'); | ||
| } | ||
|
|
||
| return existed; | ||
| } | ||
|
|
||
| @override | ||
| Future<bool> addCustomTokenIfNotExists(Asset asset) async { | ||
| final box = await _openCustomTokensBox(); | ||
| if (box.containsKey(asset.id.id)) { | ||
| _log.fine('Custom token ${asset.id.id} already exists, skipping'); | ||
| return false; | ||
| } | ||
|
|
||
| await box.put(asset.id.id, asset); | ||
| _log.fine('Added new custom token ${asset.id.id}'); | ||
| return true; | ||
| } | ||
|
|
||
| @override | ||
| Future<int> getCustomTokenCount() async { | ||
| final box = await _openCustomTokensBox(); | ||
| return box.length; | ||
| } | ||
|
|
||
| @override | ||
| Future<void> dispose() async { | ||
| if (_customTokensBox != null) { | ||
| _log.fine('Closing custom tokens box'); | ||
| await _customTokensBox!.close(); | ||
| _customTokensBox = null; | ||
| } | ||
| } | ||
|
|
||
| Future<LazyBox<Asset>> _openCustomTokensBox() async { | ||
| if (_customTokensBox == null) { | ||
| _log.fine('Opening custom tokens box "$customTokensBoxName"'); | ||
| _customTokensBox = await Hive.openLazyBox<Asset>(customTokensBoxName); | ||
| } | ||
| return _customTokensBox!; | ||
| } | ||
| } | ||
50 changes: 50 additions & 0 deletions
50
packages/komodo_coin_updates/lib/src/coins_config/custom_token_storage_interface.dart
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,50 @@ | ||
| import 'package:komodo_defi_types/komodo_defi_types.dart'; | ||
|
|
||
| /// Interface for custom token storage operations | ||
| abstract class ICustomTokenStorage { | ||
| /// Stores a single custom token. | ||
| /// If a token with the same AssetId already exists, it will be overwritten. | ||
| Future<void> storeCustomToken(Asset asset); | ||
|
|
||
| /// Stores multiple custom tokens. | ||
| /// Existing tokens with the same AssetIds will be overwritten. | ||
| Future<void> storeCustomTokens(List<Asset> assets); | ||
|
|
||
| /// Retrieves all custom tokens from storage. | ||
| /// Returns an empty list if no custom tokens are stored. | ||
| Future<List<Asset>> getAllCustomTokens(); | ||
|
|
||
| /// Retrieves a single custom token by its AssetId. | ||
| /// Returns null if the token is not found. | ||
| Future<Asset?> getCustomToken(AssetId assetId); | ||
|
|
||
| /// Checks if a custom token exists in storage. | ||
| Future<bool> hasCustomToken(AssetId assetId); | ||
|
|
||
| /// Deletes a single custom token by its AssetId. | ||
| Future<void> deleteCustomToken(AssetId assetId); | ||
|
|
||
| /// Deletes multiple custom tokens by their AssetIds. | ||
| Future<void> deleteCustomTokens(List<AssetId> assetIds); | ||
|
|
||
| /// Deletes all custom tokens from storage. | ||
| Future<void> deleteAllCustomTokens(); | ||
|
|
||
| /// Returns true if the custom tokens box exists and is not empty. | ||
| Future<bool> hasCustomTokens(); | ||
|
|
||
| /// Updates an existing custom token if it exists, otherwise stores it as new. | ||
| /// Returns true if the token was updated, false if it was newly created. | ||
| Future<bool> updateCustomToken(Asset asset); | ||
|
|
||
| /// Adds a custom token to storage if it doesn't already exist. | ||
| /// Returns true if the token was added, false if it already existed. | ||
| Future<bool> addCustomTokenIfNotExists(Asset asset); | ||
|
|
||
| /// Returns the number of custom tokens in storage. | ||
| Future<int> getCustomTokenCount(); | ||
|
|
||
| /// Closes the storage and releases resources. | ||
| /// This should be called when the storage is no longer needed. | ||
| Future<void> dispose(); | ||
| } | ||
|
takenagain marked this conversation as resolved.
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.