From 0e9273cef909d1a32c731bdf09fadcaacc76aa42 Mon Sep 17 00:00:00 2001 From: DeckerSU Date: Mon, 3 Nov 2025 10:56:43 +0100 Subject: [PATCH 1/2] fix: handle SDK disposal in balance calculations Added error handling for StateError in balance-related methods to ensure that null values are returned gracefully when the SDK has been disposed. Updated the CoinBalance and CoinFiatBalance widgets to utilize the new balance method, improving stability and preventing crashes. --- .../legacy_coin_migration_extensions.dart | 38 +++++++++++++------ lib/shared/widgets/coin_balance.dart | 3 +- lib/shared/widgets/coin_fiat_balance.dart | 8 +++- 3 files changed, 35 insertions(+), 14 deletions(-) diff --git a/lib/shared/utils/extensions/legacy_coin_migration_extensions.dart b/lib/shared/utils/extensions/legacy_coin_migration_extensions.dart index 1bdf3bac4b..b47afd67b0 100644 --- a/lib/shared/utils/extensions/legacy_coin_migration_extensions.dart +++ b/lib/shared/utils/extensions/legacy_coin_migration_extensions.dart @@ -28,8 +28,14 @@ extension LegacyCoinMigrationExtensions on Coin { /// /// NB: This is not a real-time balance. Prefer using [getBalance] or /// [watchBalance] for up-to-date data. - double? balance(KomodoDefiSdk sdk) => - sdk.balances.lastKnown(id)?.spendable.toDouble(); + double? balance(KomodoDefiSdk sdk) { + try { + return sdk.balances.lastKnown(id)?.spendable.toDouble(); + } on StateError { + // SDK has been disposed, return null + return null; + } + } /// Gets the current USD balance of this coin /// @@ -45,20 +51,30 @@ extension LegacyCoinMigrationExtensions on Coin { } double? lastKnownUsdBalance(KomodoDefiSdk sdk) { - final balance = sdk.balances.lastKnown(id); - if (balance == null) return null; - if (balance.spendable == Decimal.zero) return 0; + try { + final balance = sdk.balances.lastKnown(id); + if (balance == null) return null; + if (balance.spendable == Decimal.zero) return 0; - final price = sdk.marketData.priceIfKnown(id); - if (price == null) return null; + final price = sdk.marketData.priceIfKnown(id); + if (price == null) return null; - return (price * balance.spendable).toDouble(); + return (price * balance.spendable).toDouble(); + } on StateError { + // SDK has been disposed, return null + return null; + } } double? lastKnownUsdPrice(KomodoDefiSdk sdk) { - final price = sdk.marketData.priceIfKnown(id); - if (price == null) return null; - return price.toDouble(); + try { + final price = sdk.marketData.priceIfKnown(id); + if (price == null) return null; + return price.toDouble(); + } on StateError { + // SDK has been disposed, return null + return null; + } } /// Get cached 24hr change from CoinsBloc state diff --git a/lib/shared/widgets/coin_balance.dart b/lib/shared/widgets/coin_balance.dart index baa0952374..07dc027800 100644 --- a/lib/shared/widgets/coin_balance.dart +++ b/lib/shared/widgets/coin_balance.dart @@ -17,8 +17,7 @@ class CoinBalance extends StatelessWidget { final baseFont = Theme.of(context).textTheme.bodySmall; final balanceStyle = baseFont?.copyWith(fontWeight: FontWeight.w500); - final balance = - context.sdk.balances.lastKnown(coin.id)?.spendable.toDouble() ?? 0.0; + final balance = coin.balance(context.sdk) ?? 0.0; final children = [ Row( diff --git a/lib/shared/widgets/coin_fiat_balance.dart b/lib/shared/widgets/coin_fiat_balance.dart index 6a966fdedb..06f39a51d3 100644 --- a/lib/shared/widgets/coin_fiat_balance.dart +++ b/lib/shared/widgets/coin_fiat_balance.dart @@ -21,7 +21,13 @@ class CoinFiatBalance extends StatelessWidget { @override Widget build(BuildContext context) { - final balanceStream = context.sdk.balances.watchBalance(coin.id); + Stream? balanceStream; + try { + balanceStream = context.sdk.balances.watchBalance(coin.id); + } on StateError { + // SDK has been disposed, return empty widget + return const SizedBox(); + } final TextStyle mergedStyle = const TextStyle( fontSize: 12, From ec73a000da915d3e8490244cc7418810f3724ddc Mon Sep 17 00:00:00 2001 From: DeckerSU Date: Mon, 3 Nov 2025 11:35:48 +0100 Subject: [PATCH 2/2] fix: improve error handling for SDK disposal in AuthBloc Added try-catch blocks to handle StateError when connecting and disconnecting the streaming service in the AuthBloc. This ensures that if the SDK has been disposed, the application will skip the connect/disconnect operations gracefully, improving stability and preventing potential crashes. --- lib/bloc/auth_bloc/auth_bloc.dart | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/lib/bloc/auth_bloc/auth_bloc.dart b/lib/bloc/auth_bloc/auth_bloc.dart index a36b777ae7..cc7190a890 100644 --- a/lib/bloc/auth_bloc/auth_bloc.dart +++ b/lib/bloc/auth_bloc/auth_bloc.dart @@ -100,7 +100,12 @@ class AuthBloc extends Bloc with TrezorAuthMixin { } finally { // Explicitly disconnect SSE on sign-out _log.info('User signed out, disconnecting SSE...'); - _kdfSdk.streaming.disconnect(); + try { + _kdfSdk.streaming.disconnect(); + } on StateError { + // SDK has been disposed, skip disconnect + _log.info('SDK already disposed, skipping SSE disconnect'); + } await _authChangesSubscription?.cancel(); emit(AuthBlocState.initial()); @@ -467,11 +472,21 @@ class AuthBloc extends Bloc with TrezorAuthMixin { if (user != null) { // User authenticated - connect SSE for balance/tx history streaming _log.info('User authenticated, connecting SSE for streaming...'); - _kdfSdk.streaming.connectIfNeeded(); + try { + _kdfSdk.streaming.connectIfNeeded(); + } on StateError { + // SDK has been disposed, skip connect + _log.info('SDK already disposed, skipping SSE connect'); + } } else { // User signed out - disconnect SSE to clean up resources _log.info('User signed out, disconnecting SSE...'); - _kdfSdk.streaming.disconnect(); + try { + _kdfSdk.streaming.disconnect(); + } on StateError { + // SDK has been disposed, skip disconnect + _log.info('SDK already disposed, skipping SSE disconnect'); + } } }); }