diff --git a/packages/komodo_defi_framework/app_build/build_config.json b/packages/komodo_defi_framework/app_build/build_config.json index b2745ddd..f26a8393 100644 --- a/packages/komodo_defi_framework/app_build/build_config.json +++ b/packages/komodo_defi_framework/app_build/build_config.json @@ -68,7 +68,7 @@ "coins": { "fetch_at_build_enabled": true, "update_commit_on_build": true, - "bundled_coins_repo_commit": "9d99819f3f7a8357464240c8c26f7442f5a7da32", + "bundled_coins_repo_commit": "3d23cb5dcc82d4bb8c88f8ebf67ad3fb51ed3b6b", "coins_repo_api_url": "https://api.github.com/repos/KomodoPlatform/coins", "coins_repo_content_url": "https://raw.githubusercontent.com/KomodoPlatform/coins", "coins_repo_branch": "master", diff --git a/packages/komodo_defi_framework/lib/komodo_defi_framework.dart b/packages/komodo_defi_framework/lib/komodo_defi_framework.dart index d4a213af..3bf496e0 100644 --- a/packages/komodo_defi_framework/lib/komodo_defi_framework.dart +++ b/packages/komodo_defi_framework/lib/komodo_defi_framework.dart @@ -8,6 +8,7 @@ import 'package:komodo_defi_framework/src/operations/kdf_operations_factory.dart import 'package:komodo_defi_framework/src/operations/kdf_operations_interface.dart'; import 'package:komodo_defi_types/komodo_defi_type_utils.dart'; import 'package:komodo_defi_types/komodo_defi_types.dart'; +import 'package:logging/logging.dart'; export 'package:komodo_defi_framework/src/client/kdf_api_client.dart'; export 'package:komodo_defi_framework/src/config/kdf_config.dart'; @@ -32,6 +33,12 @@ class KomodoDefiFramework implements ApiClient { } } + /// Enable debug logging for RPC calls (method names, durations, success/failure) + /// This can be controlled via app configuration + static bool enableDebugLogging = true; + + final Logger _logger = Logger('KomodoDefiFramework'); + factory KomodoDefiFramework.create({ required IKdfHostConfig hostConfig, void Function(String)? externalLogger, @@ -171,15 +178,120 @@ class KomodoDefiFramework implements ApiClient { return version; } + /// Checks if KDF is healthy and responsive by attempting a version RPC call. + /// Returns true if KDF is running and responsive, false otherwise. + /// This is useful for detecting when KDF has become unavailable, especially + /// on mobile platforms after app backgrounding. + Future isHealthy() async { + try { + final isRunningCheck = await isRunning(); + if (!isRunningCheck) { + _log('KDF health check failed: not running'); + return false; + } + + // Additional check: try to get version to verify RPC is responsive + final versionCheck = await version(); + if (versionCheck == null) { + _log('KDF health check failed: version call returned null'); + return false; + } + + _log('KDF health check passed'); + return true; + } catch (e) { + _log('KDF health check failed with exception: $e'); + return false; + } + } + @override Future executeRpc(JsonMap request) async { - final response = (await _kdfOperations.mm2Rpc( - request..setIfAbsentOrEmpty('userpass', _hostConfig.rpcPassword), - )).ensureJson(); - if (KdfLoggingConfig.verboseLogging) { - _log('RPC response: ${response.toJsonString()}'); + if (!enableDebugLogging) { + final response = (await _kdfOperations.mm2Rpc( + request..setIfAbsentOrEmpty('userpass', _hostConfig.rpcPassword), + )).ensureJson(); + if (KdfLoggingConfig.verboseLogging) { + _log('RPC response: ${response.toJsonString()}'); + } + return response; + } + + // Extract method name for logging + final method = request['method'] as String?; + final stopwatch = Stopwatch()..start(); + + try { + final response = (await _kdfOperations.mm2Rpc( + request..setIfAbsentOrEmpty('userpass', _hostConfig.rpcPassword), + )).ensureJson(); + stopwatch.stop(); + + _logger.info( + '[RPC] ${method ?? 'unknown'} completed in ${stopwatch.elapsedMilliseconds}ms', + ); + + // Log electrum-related methods with more detail + if (method != null && _isElectrumRelatedMethod(method)) { + _logger.info('[ELECTRUM] Method: $method, Duration: ${stopwatch.elapsedMilliseconds}ms'); + _logElectrumConnectionInfo(method, response); + } + + if (KdfLoggingConfig.verboseLogging) { + _log('RPC response: ${response.toJsonString()}'); + } + return response; + } catch (e) { + stopwatch.stop(); + _logger.warning( + '[RPC] ${method ?? 'unknown'} failed after ${stopwatch.elapsedMilliseconds}ms: $e', + ); + rethrow; + } + } + + bool _isElectrumRelatedMethod(String method) { + return method.contains('electrum') || + method.contains('enable') || + method.contains('utxo') || + method == 'get_enabled_coins' || + method == 'my_balance'; + } + + void _logElectrumConnectionInfo(String method, JsonMap response) { + try { + // Log connection information from enable responses + if (method.contains('enable') && response['result'] != null) { + final result = response['result'] as Map?; + if (result != null) { + final address = result['address'] as String?; + final balance = result['balance'] as String?; + _logger.info( + '[ELECTRUM] Coin enabled - Address: ${address ?? 'N/A'}, Balance: ${balance ?? 'N/A'}', + ); + + // Log server information if available + if (result['servers'] != null) { + final servers = result['servers']; + _logger.info('[ELECTRUM] Connected servers: $servers'); + } + } + } + + // Log balance information + if (method == 'my_balance' && response['result'] != null) { + final result = response['result'] as Map?; + if (result != null) { + final coin = result['coin'] as String?; + final balance = result['balance'] as String?; + _logger.info( + '[ELECTRUM] Balance query - Coin: ${coin ?? 'N/A'}, Balance: ${balance ?? 'N/A'}', + ); + } + } + } catch (e) { + // Silently ignore logging errors } - return response; } void _assertHostConfigMatchesStartupConfig( diff --git a/packages/komodo_defi_framework/lib/src/client/kdf_api_client.dart b/packages/komodo_defi_framework/lib/src/client/kdf_api_client.dart index 02c0ab5c..d79b3d8c 100644 --- a/packages/komodo_defi_framework/lib/src/client/kdf_api_client.dart +++ b/packages/komodo_defi_framework/lib/src/client/kdf_api_client.dart @@ -1,24 +1,107 @@ import 'package:komodo_defi_types/komodo_defi_type_utils.dart'; import 'package:komodo_defi_types/komodo_defi_types.dart'; +import 'package:logging/logging.dart'; class KdfApiClient implements ApiClient { KdfApiClient( this._rpcCallback, // this. /*{required String rpcPassword}*/ - ); + ) { + _logger = Logger('KdfApiClient'); + } final JsonMap Function(JsonMap) _rpcCallback; // final Future Function() _stopCallback; // String? _rpcPassword; + + late final Logger _logger; + + /// Enable debug logging for RPC calls (method names, durations, success/failure) + /// This can be controlled via app configuration + static bool enableDebugLogging = true; @override Future executeRpc(JsonMap request) async { // if (!await isInitialized()) { // throw StateError('API client is not initialized'); // } - return _rpcCallback(request); + + if (!enableDebugLogging) { + return _rpcCallback(request); + } + + // Extract method name for logging + final method = request['method'] as String?; + final stopwatch = Stopwatch()..start(); + + try { + final response = _rpcCallback(request); + stopwatch.stop(); + + _logger.info( + '[RPC] ${method ?? 'unknown'} completed in ${stopwatch.elapsedMilliseconds}ms', + ); + + // Log electrum-related methods with more detail + if (method != null && _isElectrumRelatedMethod(method)) { + _logger.info('[ELECTRUM] Method: $method, Duration: ${stopwatch.elapsedMilliseconds}ms'); + _logElectrumConnectionInfo(method, response); + } + + return response; + } catch (e) { + stopwatch.stop(); + _logger.warning( + '[RPC] ${method ?? 'unknown'} failed after ${stopwatch.elapsedMilliseconds}ms: $e', + ); + rethrow; + } + } + + bool _isElectrumRelatedMethod(String method) { + return method.contains('electrum') || + method.contains('enable') || + method.contains('utxo') || + method == 'get_enabled_coins' || + method == 'my_balance'; + } + + void _logElectrumConnectionInfo(String method, JsonMap response) { + try { + // Log connection information from enable responses + if (method.contains('enable') && response['result'] != null) { + final result = response['result'] as Map?; + if (result != null) { + final address = result['address'] as String?; + final balance = result['balance'] as String?; + _logger.info( + '[ELECTRUM] Coin enabled - Address: ${address ?? 'N/A'}, Balance: ${balance ?? 'N/A'}', + ); + + // Log server information if available + if (result['servers'] != null) { + final servers = result['servers']; + _logger.info('[ELECTRUM] Connected servers: $servers'); + } + } + } + + // Log balance information + if (method == 'my_balance' && response['result'] != null) { + final result = response['result'] as Map?; + if (result != null) { + final coin = result['coin'] as String?; + final balance = result['balance'] as String?; + _logger.info( + '[ELECTRUM] Balance query - Coin: ${coin ?? 'N/A'}, Balance: ${balance ?? 'N/A'}', + ); + } + } + } catch (e) { + // Silently ignore logging errors + } } // Not sure if this belongs here diff --git a/packages/komodo_defi_framework/lib/src/operations/kdf_operations_native.dart b/packages/komodo_defi_framework/lib/src/operations/kdf_operations_native.dart index c577f382..8997e261 100644 --- a/packages/komodo_defi_framework/lib/src/operations/kdf_operations_native.dart +++ b/packages/komodo_defi_framework/lib/src/operations/kdf_operations_native.dart @@ -255,7 +255,10 @@ class KdfOperationsNativeLibrary implements IKdfOperations { Future isRunning() => Future.sync(() => _kdfMainStatus() == MainStatus.rpcIsUp); - final Uri _url = Uri.parse('http://localhost:7783'); + // Use 127.0.0.1 instead of localhost to avoid DNS resolution issues on mobile + // platforms, especially after app backgrounding. See: + // https://github.com/KomodoPlatform/komodo-wallet/issues/3213 + final Uri _url = Uri.parse('http://127.0.0.1:7783'); final Client _client = Client(); @override diff --git a/packages/komodo_defi_local_auth/lib/src/auth/auth_service.dart b/packages/komodo_defi_local_auth/lib/src/auth/auth_service.dart index 9043d086..d015bca8 100644 --- a/packages/komodo_defi_local_auth/lib/src/auth/auth_service.dart +++ b/packages/komodo_defi_local_auth/lib/src/auth/auth_service.dart @@ -87,6 +87,13 @@ abstract interface class IAuthService { /// Only works if the KDF API is running and the wallet exists Future restoreSession(KdfUser user); + /// Ensures that KDF is healthy and responsive. If KDF is not healthy, + /// attempts to restart it with the current user's configuration. + /// This is useful for recovering from situations where KDF has become + /// unavailable, especially on mobile platforms after app backgrounding. + /// Returns true if KDF is healthy or was successfully restarted, false otherwise. + Future ensureKdfHealthy(); + Stream get authStateChanges; Future dispose(); } @@ -484,4 +491,30 @@ class KdfAuthService implements IAuthService { } }); } + + @override + Future ensureKdfHealthy() async { + try { + // First check if KDF is healthy + if (await _kdfFramework.isHealthy()) { + return true; + } + + // KDF is not healthy, try to get the current active user + final currentUser = await _getActiveUser(); + if (currentUser == null) { + // No current user, just ensure KDF is running in no-auth mode + await _ensureKdfRunning(); + return await _kdfFramework.isHealthy(); + } + + // We have a current user but KDF is not healthy + // Try to restart KDF in no-auth mode first as we don't have the password + await _ensureKdfRunning(); + return await _kdfFramework.isHealthy(); + } catch (e) { + // Log the error but don't throw - return false to indicate failure + return false; + } + } } diff --git a/packages/komodo_defi_local_auth/lib/src/komodo_defi_local_auth.dart b/packages/komodo_defi_local_auth/lib/src/komodo_defi_local_auth.dart index bd253bc4..a637be0a 100644 --- a/packages/komodo_defi_local_auth/lib/src/komodo_defi_local_auth.dart +++ b/packages/komodo_defi_local_auth/lib/src/komodo_defi_local_auth.dart @@ -233,6 +233,13 @@ abstract interface class KomodoDefiAuth { /// during cancellation. Future cancelHardwareDeviceInitialization(int taskId); + /// Ensures that KDF is healthy and responsive. If KDF is not healthy, + /// attempts to restart it with the current user's configuration. + /// This is useful for recovering from situations where KDF has become + /// unavailable, especially on mobile platforms after app backgrounding. + /// Returns true if KDF is healthy or was successfully restarted, false otherwise. + Future ensureKdfHealthy(); + /// Disposes of any resources held by the authentication service. /// /// This method should be called when the authentication service is no longer @@ -680,6 +687,12 @@ class KomodoDefiLocalAuth implements KomodoDefiAuth { } } + @override + Future ensureKdfHealthy() async { + await ensureInitialized(); + return _authService.ensureKdfHealthy(); + } + @override Future dispose() async { await _authService.dispose(); diff --git a/packages/komodo_defi_local_auth/lib/src/trezor/trezor_auth_service.dart b/packages/komodo_defi_local_auth/lib/src/trezor/trezor_auth_service.dart index eb5f07fd..2fef1f74 100644 --- a/packages/komodo_defi_local_auth/lib/src/trezor/trezor_auth_service.dart +++ b/packages/komodo_defi_local_auth/lib/src/trezor/trezor_auth_service.dart @@ -129,6 +129,9 @@ class TrezorAuthService implements IAuthService { required String password, }) => _authService.deleteWallet(walletName: walletName, password: password); + @override + Future ensureKdfHealthy() => _authService.ensureKdfHealthy(); + @override Future signIn({ required String walletName, diff --git a/packages/komodo_defi_sdk/lib/src/activation/protocol_strategies/custom_erc20_activation_strategy.dart b/packages/komodo_defi_sdk/lib/src/activation/protocol_strategies/custom_erc20_activation_strategy.dart index d8fcf3a7..c3aed6b1 100644 --- a/packages/komodo_defi_sdk/lib/src/activation/protocol_strategies/custom_erc20_activation_strategy.dart +++ b/packages/komodo_defi_sdk/lib/src/activation/protocol_strategies/custom_erc20_activation_strategy.dart @@ -25,6 +25,7 @@ class CustomErc20ActivationStrategy extends ProtocolActivationStrategy { CoinSubClass.hecoChain, CoinSubClass.rskSmartBitcoin, CoinSubClass.arbitrum, + CoinSubClass.base, }; @override @@ -94,4 +95,4 @@ class CustomErc20ActivationStrategy extends ProtocolActivationStrategy { ); } } -} \ No newline at end of file +} diff --git a/packages/komodo_defi_sdk/lib/src/activation/protocol_strategies/erc20_activation_strategy.dart b/packages/komodo_defi_sdk/lib/src/activation/protocol_strategies/erc20_activation_strategy.dart index 7c1a5acb..1a1b4e90 100644 --- a/packages/komodo_defi_sdk/lib/src/activation/protocol_strategies/erc20_activation_strategy.dart +++ b/packages/komodo_defi_sdk/lib/src/activation/protocol_strategies/erc20_activation_strategy.dart @@ -26,6 +26,7 @@ class Erc20ActivationStrategy extends ProtocolActivationStrategy { CoinSubClass.hecoChain, CoinSubClass.rskSmartBitcoin, CoinSubClass.arbitrum, + CoinSubClass.base, }; @override @@ -95,4 +96,4 @@ class Erc20ActivationStrategy extends ProtocolActivationStrategy { ); } } -} \ No newline at end of file +} diff --git a/packages/komodo_defi_sdk/lib/src/activation/protocol_strategies/eth_task_activation_strategy.dart b/packages/komodo_defi_sdk/lib/src/activation/protocol_strategies/eth_task_activation_strategy.dart index 9d1c81a5..a19bc18b 100644 --- a/packages/komodo_defi_sdk/lib/src/activation/protocol_strategies/eth_task_activation_strategy.dart +++ b/packages/komodo_defi_sdk/lib/src/activation/protocol_strategies/eth_task_activation_strategy.dart @@ -28,6 +28,7 @@ class EthTaskActivationStrategy extends ProtocolActivationStrategy { CoinSubClass.hecoChain, CoinSubClass.rskSmartBitcoin, CoinSubClass.arbitrum, + CoinSubClass.base, }; @override diff --git a/packages/komodo_defi_sdk/lib/src/activation/protocol_strategies/eth_with_tokens_activation_strategy.dart b/packages/komodo_defi_sdk/lib/src/activation/protocol_strategies/eth_with_tokens_activation_strategy.dart index 4d3a6e1b..88227591 100644 --- a/packages/komodo_defi_sdk/lib/src/activation/protocol_strategies/eth_with_tokens_activation_strategy.dart +++ b/packages/komodo_defi_sdk/lib/src/activation/protocol_strategies/eth_with_tokens_activation_strategy.dart @@ -28,6 +28,7 @@ class EthWithTokensActivationStrategy extends ProtocolActivationStrategy { CoinSubClass.hecoChain, CoinSubClass.rskSmartBitcoin, CoinSubClass.arbitrum, + CoinSubClass.base, }; @override diff --git a/packages/komodo_defi_sdk/lib/src/balances/balance_manager.dart b/packages/komodo_defi_sdk/lib/src/balances/balance_manager.dart index 57bd5b66..599c4180 100644 --- a/packages/komodo_defi_sdk/lib/src/balances/balance_manager.dart +++ b/packages/komodo_defi_sdk/lib/src/balances/balance_manager.dart @@ -76,6 +76,9 @@ class BalanceManager implements IBalanceManager { final KomodoDefiLocalAuth _auth; StreamSubscription? _authSubscription; final Duration _defaultPollingInterval = const Duration(seconds: 30); + + /// Enable debug logging for balance polling + static bool enableDebugLogging = true; /// Cache of the latest known balances for each asset final Map _balanceCache = {}; @@ -351,6 +354,12 @@ class BalanceManager implements IBalanceManager { return null; // Don't fetch balance if user changed or logged out } + if (enableDebugLogging) { + _logger.info( + '[POLLING] Fetching balance for ${assetId.name} (every ${_defaultPollingInterval.inSeconds}s)', + ); + } + try { // Ensure asset is activated if needed final isActive = await _ensureAssetActivated( @@ -361,11 +370,19 @@ class BalanceManager implements IBalanceManager { // Only fetch balance if asset is active if (isActive) { final balance = await getBalance(assetId); + if (enableDebugLogging) { + _logger.info( + '[POLLING] Balance fetched for ${assetId.name}: ${balance.total}', + ); + } return balance; } } catch (e) { // 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'); + } } // Return the last known balance if we can't fetch a new one diff --git a/packages/komodo_defi_sdk/lib/src/transaction_history/strategies/etherscan_transaction_history_strategy.dart b/packages/komodo_defi_sdk/lib/src/transaction_history/strategies/etherscan_transaction_history_strategy.dart index 7ac61005..80e6421b 100644 --- a/packages/komodo_defi_sdk/lib/src/transaction_history/strategies/etherscan_transaction_history_strategy.dart +++ b/packages/komodo_defi_sdk/lib/src/transaction_history/strategies/etherscan_transaction_history_strategy.dart @@ -268,24 +268,20 @@ class EtherscanProtocolHelper { String? _getBaseEndpoint(AssetId id) { final isParentChain = id.parentId == null; return switch (id.subClass) { - CoinSubClass.hecoChain when isParentChain => _hecoUrl, - CoinSubClass.hecoChain => _hecoTokenUrl, CoinSubClass.bep20 when isParentChain => _bnbUrl, CoinSubClass.bep20 => _bnbTokenUrl, CoinSubClass.matic when isParentChain => _maticUrl, CoinSubClass.matic => _maticTokenUrl, - CoinSubClass.ftm20 when isParentChain => _ftmUrl, - CoinSubClass.ftm20 => _ftmTokenUrl, CoinSubClass.avx20 when isParentChain => _avaxUrl, CoinSubClass.avx20 => _avaxTokenUrl, CoinSubClass.moonriver when isParentChain => _mvrUrl, CoinSubClass.moonriver => _mvrTokenUrl, - CoinSubClass.krc20 when isParentChain => _kcsUrl, - CoinSubClass.krc20 => _kcsTokenUrl, CoinSubClass.erc20 when isParentChain => _ethUrl, CoinSubClass.erc20 => _ethTokenUrl, CoinSubClass.arbitrum when isParentChain => _arbUrl, CoinSubClass.arbitrum => _arbTokenUrl, + CoinSubClass.base when isParentChain => _ethBaseUrl, + CoinSubClass.base => _ethBaseTokenUrl, CoinSubClass.rskSmartBitcoin => _rskUrl, CoinSubClass.moonbeam => _glmrUrl, CoinSubClass.ethereumClassic => _etcUrl, @@ -300,21 +296,17 @@ class EtherscanProtocolHelper { String get _arbUrl => '$_baseUrl/v2/arb_tx_history'; String get _avaxUrl => '$_baseUrl/v2/avax_tx_history'; + String get _ethBaseUrl => '$_baseUrl/v2/base_tx_history'; String get _bnbUrl => '$_baseUrl/v2/bnb_tx_history'; String get _ethUrl => '$_baseUrl/v2/eth_tx_history'; - String get _ftmUrl => '$_baseUrl/v2/ftm_tx_history'; - String get _hecoUrl => '$_baseUrl/v2/ht_tx_history'; - String get _kcsUrl => '$_baseUrl/v2/krc_tx_history'; String get _maticUrl => '$_baseUrl/v2/matic_tx_history'; String get _mvrUrl => '$_baseUrl/v2/movr_tx_history'; String get _arbTokenUrl => '$_baseUrl/v2/arb20_tx_history'; String get _avaxTokenUrl => '$_baseUrl/v2/avx20_tx_history'; + String get _ethBaseTokenUrl => '$_baseUrl/v2/base20_tx_history'; String get _bnbTokenUrl => '$_baseUrl/v2/bep20_tx_history'; String get _ethTokenUrl => '$_baseUrl/v2/erc20_tx_history'; - String get _ftmTokenUrl => '$_baseUrl/v2/ftm20_tx_history'; - String get _hecoTokenUrl => '$_baseUrl/v2/hco20_tx_history'; - String get _kcsTokenUrl => '$_baseUrl/v2/krc20_tx_history'; String get _maticTokenUrl => '$_baseUrl/v2/plg20_tx_history'; String get _mvrTokenUrl => '$_baseUrl/v2/mvr20_tx_history'; diff --git a/packages/komodo_defi_types/lib/src/coin_classes/coin_subclasses.dart b/packages/komodo_defi_types/lib/src/coin_classes/coin_subclasses.dart index f97aea10..e43dbcd4 100644 --- a/packages/komodo_defi_types/lib/src/coin_classes/coin_subclasses.dart +++ b/packages/komodo_defi_types/lib/src/coin_classes/coin_subclasses.dart @@ -6,6 +6,7 @@ enum CoinSubClass { moonbeam, ftm20, arbitrum, + base, @Deprecated('No longer active. Will be removed in the future.') slp, sia, @@ -44,6 +45,8 @@ enum CoinSubClass { return 'FTM'; case CoinSubClass.arbitrum: return 'ARB'; + case CoinSubClass.base: + return 'BASE'; // ignore: deprecated_member_use_from_same_package case CoinSubClass.slp: return 'SLP'; @@ -100,6 +103,8 @@ enum CoinSubClass { return 'FTM'; case CoinSubClass.arbitrum: return 'ARB'; + case CoinSubClass.base: + return 'BASE'; // ignore: deprecated_member_use_from_same_package case CoinSubClass.slp: return 'SLP'; @@ -257,6 +262,8 @@ enum CoinSubClass { return 'Fantom'; case CoinSubClass.arbitrum: return 'Arbitrum'; + case CoinSubClass.base: + return 'Base'; case CoinSubClass.slp: return 'Simple Ledger Protocol'; case CoinSubClass.sia: @@ -312,6 +319,8 @@ enum CoinSubClass { return const Color(0xFF14B4EC); // ftm: "#14b4ec" case CoinSubClass.arbitrum: return const Color(0xFF28A0F0); // arb: "#28a0f0" + case CoinSubClass.base: + return const Color(0xFF0052FF); // base: "#0052ff" // ignore: deprecated_member_use_from_same_package case CoinSubClass.slp: return const Color(0xFF0CC38C); // slp: "#0cc38c" @@ -377,6 +386,8 @@ extension CoinSubClassTokenStandard on CoinSubClass { return 'FTM20'; case CoinSubClass.arbitrum: return 'ARB20'; + case CoinSubClass.base: + return 'BASE'; case CoinSubClass.avx20: return 'AVX20'; case CoinSubClass.matic: @@ -416,6 +427,7 @@ const Set evmCoinSubClasses = { CoinSubClass.matic, CoinSubClass.hrc20, CoinSubClass.arbitrum, + CoinSubClass.base, CoinSubClass.moonriver, CoinSubClass.moonbeam, CoinSubClass.ethereumClassic, diff --git a/packages/komodo_defi_types/lib/src/coin_classes/protocol_class.dart b/packages/komodo_defi_types/lib/src/coin_classes/protocol_class.dart index e5873018..557304ad 100644 --- a/packages/komodo_defi_types/lib/src/coin_classes/protocol_class.dart +++ b/packages/komodo_defi_types/lib/src/coin_classes/protocol_class.dart @@ -47,6 +47,7 @@ abstract class ProtocolClass with ExplorerUrlMixin implements Equatable { CoinSubClass.matic || CoinSubClass.hrc20 || CoinSubClass.arbitrum || + CoinSubClass.base || CoinSubClass.moonriver || CoinSubClass.moonbeam || CoinSubClass.ethereumClassic ||