diff --git a/lib/bloc/dex_tab_bar/dex_tab_bar_bloc.dart b/lib/bloc/dex_tab_bar/dex_tab_bar_bloc.dart index 1bf31ebd4a..5111f1024f 100644 --- a/lib/bloc/dex_tab_bar/dex_tab_bar_bloc.dart +++ b/lib/bloc/dex_tab_bar/dex_tab_bar_bloc.dart @@ -7,6 +7,7 @@ import 'package:komodo_defi_types/komodo_defi_types.dart'; import 'package:web_dex/bloc/market_maker_bot/market_maker_order_list/market_maker_bot_order_list_repository.dart'; import 'package:web_dex/bloc/market_maker_bot/market_maker_order_list/trade_pair.dart'; import 'package:web_dex/blocs/trading_entities_bloc.dart'; +import 'package:web_dex/model/dex_list_type.dart'; import 'package:web_dex/model/my_orders/my_order.dart'; import 'package:web_dex/model/swap.dart'; import 'package:web_dex/model/trading_entities_filter.dart'; @@ -91,7 +92,9 @@ class DexTabBarBloc extends Bloc { } FutureOr _onTabChanged(TabChanged event, Emitter emit) { - emit(state.copyWith(tabIndex: event.tabIndex)); + // Validate tabIndex to prevent out-of-bounds access + final validatedIndex = event.tabIndex.clamp(0, DexListType.values.length - 1); + emit(state.copyWith(tabIndex: validatedIndex)); } void _onFilterChanged(FilterChanged event, Emitter emit) { diff --git a/lib/views/common/hw_wallet_dialog/trezor_steps/trezor_dialog_select_wallet.dart b/lib/views/common/hw_wallet_dialog/trezor_steps/trezor_dialog_select_wallet.dart index 98d14a5fc2..011bb96082 100644 --- a/lib/views/common/hw_wallet_dialog/trezor_steps/trezor_dialog_select_wallet.dart +++ b/lib/views/common/hw_wallet_dialog/trezor_steps/trezor_dialog_select_wallet.dart @@ -74,6 +74,13 @@ class _TrezorHiddenWalletState extends State<_TrezorHiddenWallet> { super.initState(); } + @override + void dispose() { + _passphraseController.dispose(); + _passphraseFieldFocusNode.dispose(); + super.dispose(); + } + @override Widget build(BuildContext context) { return Column( diff --git a/lib/views/dex/dex_page.dart b/lib/views/dex/dex_page.dart index b083480b5a..ae35be62b6 100644 --- a/lib/views/dex/dex_page.dart +++ b/lib/views/dex/dex_page.dart @@ -65,10 +65,19 @@ class _DexPageState extends State { ], child: BlocBuilder( builder: (context, state) { - final tab = DexListType.values[state.tabIndex]; - final kind = tab == DexListType.orders - ? TradingEntityKind.order - : TradingEntityKind.swap; + // Defensive bounds check for tabIndex + final bool inRange = + state.tabIndex >= 0 && state.tabIndex < DexListType.values.length; + final tab = inRange + ? DexListType.values[state.tabIndex] + : DexListType.swap; + // Explicit mapping: only orders tab shows order entities, all others show swaps + final kind = switch (tab) { + DexListType.orders => TradingEntityKind.order, + DexListType.swap => TradingEntityKind.swap, + DexListType.inProgress => TradingEntityKind.swap, + DexListType.history => TradingEntityKind.swap, + }; return isTradingDetails ? TradingDetails(uuid: routingState.dexState.uuid, kind: kind) : _DexContent(); @@ -116,7 +125,9 @@ class _DexContentState extends State<_DexContent> { child: shouldShowTabContent(state.tabIndex) ? DexListWrapper( key: Key('dex-list-wrapper-${state.tabIndex}'), - DexListType.values[state.tabIndex], + state.tabIndex >= 0 && state.tabIndex < DexListType.values.length + ? DexListType.values[state.tabIndex] + : DexListType.swap, ) : const SizedBox.shrink(), ), @@ -138,6 +149,6 @@ class _DexContentState extends State<_DexContent> { } bool shouldShowTabContent(int tabIndex) { - return DexListType.values.length > tabIndex; + return tabIndex >= 0 && tabIndex < DexListType.values.length; } } diff --git a/lib/views/dex/entity_details/trading_details.dart b/lib/views/dex/entity_details/trading_details.dart index 37cbe5b95e..21f22bb201 100644 --- a/lib/views/dex/entity_details/trading_details.dart +++ b/lib/views/dex/entity_details/trading_details.dart @@ -29,7 +29,7 @@ class TradingDetails extends StatefulWidget { const TradingDetails({super.key, required this.uuid, this.kind = TradingEntityKind.swap}); final String uuid; - final TradingEntityKind? kind; + final TradingEntityKind kind; @override State createState() => _TradingDetailsState(); @@ -116,7 +116,7 @@ class _TradingDetailsState extends State { } catch (e, s) { log( e.toString(), - path: 'trading_details =>_updateStatus ${widget.kind ?? TradingEntityKind.swap} error | uuid=${widget.uuid}', + path: 'trading_details =>_updateStatus ${widget.kind} error | uuid=${widget.uuid}', trace: s, isError: true, ); diff --git a/lib/views/market_maker_bot/market_maker_bot_page.dart b/lib/views/market_maker_bot/market_maker_bot_page.dart index 45fe7e09bd..6160a0093f 100644 --- a/lib/views/market_maker_bot/market_maker_bot_page.dart +++ b/lib/views/market_maker_bot/market_maker_bot_page.dart @@ -88,10 +88,19 @@ class _MarketMakerBotPageState extends State { }, child: BlocBuilder( builder: (context, state) { - final tab = DexListType.values[state.tabIndex]; - final kind = tab == DexListType.orders - ? TradingEntityKind.order - : TradingEntityKind.swap; + // Defensive bounds check for tabIndex + final bool inRange = + state.tabIndex >= 0 && state.tabIndex < DexListType.values.length; + final tab = inRange + ? DexListType.values[state.tabIndex] + : DexListType.swap; + // Explicit mapping: only orders tab shows order entities, all others show swaps + final kind = switch (tab) { + DexListType.orders => TradingEntityKind.order, + DexListType.swap => TradingEntityKind.swap, + DexListType.inProgress => TradingEntityKind.swap, + DexListType.history => TradingEntityKind.swap, + }; return isTradingDetails ? TradingDetails(uuid: routingState.marketMakerState.uuid, kind: kind) : MarketMakerBotView();