Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions assets/translations/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -672,4 +672,6 @@
"createNewAddress": "Create New Address",
"searchAddresses": "Search addresses",
"chart": "Chart"
"tradingDisabledTooltip": "Trading features are currently disabled",
"tradingDisabled": "Trading is currently unavailable",
}
1 change: 0 additions & 1 deletion lib/app_config/app_config.dart
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ const bool isBitrefillIntegrationEnabled = false;
///! You are solely responsible for any losses/damage that may occur. Komodo
///! Platform does not condone the use of this app for trading purposes and
///! unequivocally forbids it.
const bool kIsWalletOnly = !kDebugMode;

const Duration kPerformanceLogInterval = Duration(minutes: 1);

Expand Down
8 changes: 8 additions & 0 deletions lib/bloc/app_bloc_root.dart
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ import 'package:web_dex/bloc/settings/settings_bloc.dart';
import 'package:web_dex/bloc/settings/settings_repository.dart';
import 'package:web_dex/bloc/system_health/system_clock_repository.dart';
import 'package:web_dex/bloc/system_health/system_health_bloc.dart';
import 'package:web_dex/bloc/trading_status/trading_status_bloc.dart';
import 'package:web_dex/bloc/taker_form/taker_bloc.dart';
import 'package:web_dex/bloc/transaction_history/transaction_history_bloc.dart';
import 'package:web_dex/bloc/transaction_history/transaction_history_repo.dart';
Expand Down Expand Up @@ -177,6 +178,7 @@ class AppBlocRoot extends StatelessWidget {
RepositoryProvider(
create: (_) => KmdRewardsBloc(coinsRepository, mm2Api),
),
RepositoryProvider(create: (_) => TradingStatusRepository()),
],
child: MultiBlocProvider(
providers: [
Expand Down Expand Up @@ -287,6 +289,12 @@ class AppBlocRoot extends StatelessWidget {
),
),
),
BlocProvider<TradingStatusBloc>(
lazy: false,
create: (_) => TradingStatusBloc(
context.read<TradingStatusRepository>(),
)..add(TradingStatusCheckRequested()),
),
BlocProvider<SystemHealthBloc>(
create: (_) => SystemHealthBloc(SystemClockRepository(), mm2Api)
..add(SystemHealthPeriodicCheckStarted()),
Expand Down
27 changes: 27 additions & 0 deletions lib/bloc/trading_status/trading_status_bloc.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart';
import 'trading_status_repository.dart';

part 'trading_status_event.dart';
part 'trading_status_state.dart';

class TradingStatusBloc extends Bloc<TradingStatusEvent, TradingStatusState> {
TradingStatusBloc(this._repository) : super(TradingStatusInitial()) {
on<TradingStatusCheckRequested>(_onCheckRequested);
}

final TradingStatusRepository _repository;

Future<void> _onCheckRequested(
TradingStatusCheckRequested event,
Emitter<TradingStatusState> emit,
) async {
emit(TradingStatusLoadInProgress());
try {
final enabled = await _repository.isTradingEnabled();
emit(enabled ? TradingEnabled() : TradingDisabled());
} catch (_) {
emit(TradingStatusLoadFailure());
}
}
}
8 changes: 8 additions & 0 deletions lib/bloc/trading_status/trading_status_event.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
part of 'trading_status_bloc.dart';

abstract class TradingStatusEvent extends Equatable {
@override
List<Object?> get props => [];
}

class TradingStatusCheckRequested extends TradingStatusEvent {}
27 changes: 27 additions & 0 deletions lib/bloc/trading_status/trading_status_repository.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import 'dart:async';
import 'package:http/http.dart' as http;

class TradingStatusRepository {
TradingStatusRepository({http.Client? httpClient, Duration? timeout})
: _httpClient = httpClient ?? http.Client(),
_timeout = timeout ?? const Duration(seconds: 4);

final http.Client _httpClient;
final Duration _timeout;

Future<bool> isTradingEnabled() async {
try {
final uri =
Uri.parse('https://defi-stats.komodo.earth/api/v3/utils/bouncer');
final res = await _httpClient.get(uri).timeout(_timeout);
return res.statusCode == 200;
} catch (_) {
// Do not block trading features on network failure
return true;
}
}

void dispose() {
_httpClient.close();
}
}
16 changes: 16 additions & 0 deletions lib/bloc/trading_status/trading_status_state.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
part of 'trading_status_bloc.dart';

abstract class TradingStatusState extends Equatable {
@override
List<Object?> get props => [];
}

class TradingStatusInitial extends TradingStatusState {}

class TradingStatusLoadInProgress extends TradingStatusState {}

class TradingEnabled extends TradingStatusState {}

class TradingDisabled extends TradingStatusState {}

class TradingStatusLoadFailure extends TradingStatusState {}
9 changes: 4 additions & 5 deletions lib/model/main_menu_value.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import 'package:easy_localization/easy_localization.dart';
import 'package:web_dex/app_config/app_config.dart';
import 'package:web_dex/bloc/trading_status/trading_status_bloc.dart';
import 'package:web_dex/generated/codegen_loader.g.dart';

enum MainMenuValue {
Expand All @@ -13,11 +13,10 @@ enum MainMenuValue {
support,
none;

static MainMenuValue defaultMenu() =>
kIsWalletOnly ? MainMenuValue.wallet : MainMenuValue.dex;
static MainMenuValue defaultMenu() => MainMenuValue.dex;

bool isEnabledInCurrentMode() {
return !(kIsWalletOnly && isDisabledWhenWalletOnly);
bool isEnabledInCurrentMode({required bool tradingEnabled}) {
return tradingEnabled || !isDisabledWhenWalletOnly;
}

// Getter to determine if the item is disabled if the wallet is in wallet-only mode
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,6 @@ class PageContentRouterDelegate extends RouterDelegate<AppRoutePath>

@override
Widget build(BuildContext context) {
// Redirect to the Wallet page if the selected menu is disabled in
// wallet-only mode and the wallet is in wallet-only mode.
if (routingState.selectedMenu.isDisabledWhenWalletOnly && kIsWalletOnly) {
return WalletPage(
coinAbbr: routingState.walletState.selectedCoin,
action: routingState.walletState.coinsManagerAction,
);
}

switch (routingState.selectedMenu) {
case MainMenuValue.fiat:
return const FiatPage();
Expand Down
3 changes: 1 addition & 2 deletions lib/router/parsers/root_route_parser.dart
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,7 @@ class RootRouteInformationParser extends RouteInformationParser<AppRoutePath> {
}

BaseRouteParser _getRoutParser(Uri uri) {
final defaultRouteParser =
kIsWalletOnly ? _parsers[firstUriSegment.wallet]! : dexRouteParser;
final defaultRouteParser = dexRouteParser;

if (uri.pathSegments.isEmpty) return defaultRouteParser;
return _parsers[uri.pathSegments.first] ?? defaultRouteParser;
Expand Down
6 changes: 4 additions & 2 deletions lib/shared/ui/clock_warning_banner.dart
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:web_dex/app_config/app_config.dart';
import 'package:web_dex/bloc/system_health/system_health_bloc.dart';
import 'package:web_dex/bloc/trading_status/trading_status_bloc.dart';
import 'package:web_dex/generated/codegen_loader.g.dart';

class ClockWarningBanner extends StatelessWidget {
Expand All @@ -12,9 +12,11 @@ class ClockWarningBanner extends StatelessWidget {
Widget build(BuildContext context) {
return BlocBuilder<SystemHealthBloc, SystemHealthState>(
builder: (context, systemHealthState) {
final tradingEnabled =
context.watch<TradingStatusBloc>().state is TradingEnabled;
if (systemHealthState is SystemHealthLoadSuccess &&
!systemHealthState.isValid &&
!kIsWalletOnly) {
tradingEnabled) {
return _buildWarningBanner();
}
return const SizedBox.shrink();
Expand Down
4 changes: 2 additions & 2 deletions lib/shared/widgets/logout_popup.dart
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:web_dex/app_config/app_config.dart';
import 'package:web_dex/bloc/trading_status/trading_status_bloc.dart';
import 'package:komodo_ui_kit/komodo_ui_kit.dart';
import 'package:web_dex/bloc/auth_bloc/auth_bloc.dart';
import 'package:web_dex/bloc/coins_bloc/coins_bloc.dart';
Expand Down Expand Up @@ -39,7 +39,7 @@ class LogOutPopup extends StatelessWidget {
if (currentWallet?.config.type == WalletType.iguana ||
currentWallet?.config.type == WalletType.hdwallet)
SelectableText(
kIsWalletOnly
context.watch<TradingStatusBloc>().state is! TradingEnabled
? LocaleKeys.logoutPopupDescriptionWalletOnly.tr()
: LocaleKeys.logoutPopupDescription.tr(),
style: const TextStyle(
Expand Down
17 changes: 16 additions & 1 deletion lib/views/bridge/bridge_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import 'package:web_dex/model/swap.dart';
import 'package:web_dex/router/state/bridge_section_state.dart';
import 'package:web_dex/router/state/routing_state.dart';
import 'package:web_dex/shared/ui/clock_warning_banner.dart';
import 'package:web_dex/bloc/trading_status/trading_status_bloc.dart';
import 'package:web_dex/generated/codegen_loader.g.dart';
import 'package:web_dex/shared/utils/utils.dart';
import 'package:web_dex/shared/widgets/hidden_without_wallet.dart';
import 'package:web_dex/views/bridge/bridge_form.dart';
Expand Down Expand Up @@ -50,7 +52,20 @@ class _BridgePageState extends State<BridgePage> with TickerProviderStateMixin {
});
}
},
child: _showSwap ? _buildTradingDetails() : _buildBridgePage(),
child: Builder(builder: (context) {
final tradingEnabled =
context.watch<TradingStatusBloc>().state is TradingEnabled;
final page = _showSwap ? _buildTradingDetails() : _buildBridgePage();
if (!tradingEnabled) {
return Stack(
children: [
AbsorbPointer(child: page),
Center(child: Text(LocaleKeys.tradingDisabled.tr())),
],
);
}
return page;
}),
);
}

Expand Down
46 changes: 31 additions & 15 deletions lib/views/common/main_menu/main_menu_bar_mobile.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:web_dex/bloc/auth_bloc/auth_bloc.dart';
import 'package:web_dex/bloc/settings/settings_bloc.dart';
import 'package:web_dex/bloc/settings/settings_state.dart';
import 'package:web_dex/bloc/trading_status/trading_status_bloc.dart';
import 'package:web_dex/model/main_menu_value.dart';
import 'package:web_dex/model/wallet.dart';
import 'package:web_dex/router/state/routing_state.dart';
Expand All @@ -18,6 +19,8 @@ class MainMenuBarMobile extends StatelessWidget {
return BlocBuilder<SettingsBloc, SettingsState>(
builder: (context, state) {
final bool isMMBotEnabled = state.mmBotSettings.isMMBotEnabled;
final bool tradingEnabled =
context.watch<TradingStatusBloc>().state is TradingEnabled;
return DecoratedBox(
decoration: BoxDecoration(
color: theme.currentGlobal.cardColor,
Expand Down Expand Up @@ -45,21 +48,36 @@ class MainMenuBarMobile extends StatelessWidget {
enabled: currentWallet?.isHW != true,
isActive: selected == MainMenuValue.fiat,
),
MainMenuBarMobileItem(
value: MainMenuValue.dex,
enabled: currentWallet?.isHW != true,
isActive: selected == MainMenuValue.dex,
Tooltip(
message: tradingEnabled
? ''
: LocaleKeys.tradingDisabledTooltip.tr(),
child: MainMenuBarMobileItem(
value: MainMenuValue.dex,
enabled: tradingEnabled && currentWallet?.isHW != true,
isActive: selected == MainMenuValue.dex,
),
),
MainMenuBarMobileItem(
value: MainMenuValue.bridge,
enabled: currentWallet?.isHW != true,
isActive: selected == MainMenuValue.bridge,
Tooltip(
message: tradingEnabled
? ''
: LocaleKeys.tradingDisabledTooltip.tr(),
child: MainMenuBarMobileItem(
value: MainMenuValue.bridge,
enabled: tradingEnabled && currentWallet?.isHW != true,
isActive: selected == MainMenuValue.bridge,
),
),
if (isMMBotEnabled)
MainMenuBarMobileItem(
enabled: currentWallet?.isHW != true,
value: MainMenuValue.marketMakerBot,
isActive: selected == MainMenuValue.marketMakerBot,
Tooltip(
message: tradingEnabled
? ''
: LocaleKeys.tradingDisabledTooltip.tr(),
child: MainMenuBarMobileItem(
enabled: tradingEnabled && currentWallet?.isHW != true,
value: MainMenuValue.marketMakerBot,
isActive: selected == MainMenuValue.marketMakerBot,
),
),
MainMenuBarMobileItem(
value: MainMenuValue.nft,
Expand All @@ -70,9 +88,7 @@ class MainMenuBarMobile extends StatelessWidget {
value: MainMenuValue.settings,
isActive: selected == MainMenuValue.settings,
),
]
.where((element) => element.value.isEnabledInCurrentMode())
.toList(),
],
),
),
),
Expand Down
Loading
Loading