diff --git a/lib/screens/sell/cubits/sell_balance/sell_balance_cubit.dart b/lib/screens/sell/cubits/sell_balance/sell_balance_cubit.dart index dc80bd20..42e58ef1 100644 --- a/lib/screens/sell/cubits/sell_balance/sell_balance_cubit.dart +++ b/lib/screens/sell/cubits/sell_balance/sell_balance_cubit.dart @@ -1,4 +1,5 @@ import 'dart:async'; +import 'dart:developer' as developer; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:realunit_wallet/models/balance.dart'; @@ -19,7 +20,21 @@ class SellBalanceCubit extends Cubit { asset: appStore.apiConfig.asset, ), ) { - _subscription = _repository.watchBalance(state).listen(emit); + // Register an onError handler so a balance-stream error is logged instead + // of escaping as an unhandled async error that silently stops the sell + // balance (issue #657 P4 S6). cancelOnError defaults to false, so the + // subscription stays alive and later balances still update. + _subscription = _repository.watchBalance(state).listen( + emit, + onError: (Object error, StackTrace stackTrace) { + developer.log( + 'sell balance stream error', + name: '$SellBalanceCubit', + error: error, + stackTrace: stackTrace, + ); + }, + ); } final BalanceRepository _repository; diff --git a/test/screens/sell/cubits/sell_balance_cubit_test.dart b/test/screens/sell/cubits/sell_balance_cubit_test.dart index 23882851..163bed89 100644 --- a/test/screens/sell/cubits/sell_balance_cubit_test.dart +++ b/test/screens/sell/cubits/sell_balance_cubit_test.dart @@ -75,6 +75,31 @@ void main() { expect(cubit.state.balance, BigInt.from(7000)); }); + test( + 'a stream error is handled (not unhandled) and later balances still ' + 'update (issue #657 P4 S6 regression)', () async { + final cubit = SellBalanceCubit(repo, appStore); + + // Without an onError handler this error escaped as an unhandled async + // error (failing the test) and stopped the sell balance. It must now be + // logged, and — cancelOnError being false — a later balance still lands. + controller.addError(Exception('balance backend blip')); + await Future.delayed(Duration.zero); + + final updated = Balance( + chainId: realUnitAsset.chainId, + contractAddress: realUnitAsset.address, + walletAddress: _wallet, + balance: BigInt.from(4242), + asset: realUnitAsset, + ); + final ready = cubit.stream.firstWhere((b) => b.balance == BigInt.from(4242)); + controller.add(updated); + await ready.timeout(const Duration(seconds: 1)); + + expect(cubit.state.balance, BigInt.from(4242)); + }); + test('close() cancels the subscription cleanly', () async { final cubit = SellBalanceCubit(repo, appStore);