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
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,6 @@ class MarketMakerBotRepository {
};
return MarketMakerBotParameters(
botRefreshRate: mmSettings.botRefreshRate,
priceUrl: mmSettings.priceUrl,
tradeCoinPairs: tradePairs,
);
}
Expand Down
67 changes: 41 additions & 26 deletions lib/mm2/mm2_api/rpc/rpc_error.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import 'dart:convert';

import 'package:equatable/equatable.dart';
import 'package:web_dex/mm2/mm2_api/rpc/rpc_error_type.dart';

Expand All @@ -23,15 +25,36 @@ class RpcError extends Equatable {
this.id,
});

factory RpcError.fromJson(Map<String, dynamic> json) => RpcError(
mmrpc: json['mmrpc'] as String?,
error: json['error'] as String?,
errorPath: json['error_path'] as String?,
errorTrace: json['error_trace'] as String?,
errorType: RpcErrorType.fromString(json['error_type'] as String? ?? ''),
errorData: json['error_data'] as String?,
id: json['id'] as int?,
);
factory RpcError.fromJson(Map<String, dynamic> json) {
// Handle nested error format where RPC error is in 'message' field
if (json.containsKey('message') && json['message'] is String) {
try {
final Map<String, dynamic> nestedError =
jsonDecode(json['message'] as String) as Map<String, dynamic>;
return RpcError._fromDirectJson(nestedError);
} catch (_) {
// If parsing fails, fall back to treating message as error string
return RpcError(
error: json['message'] as String?,
errorData: json['error'] as String?,
);
}
}

return RpcError._fromDirectJson(json);
}

factory RpcError._fromDirectJson(Map<String, dynamic> json) => RpcError(
mmrpc: json['mmrpc'] as String?,
error: json['error'] as String?,
errorPath: json['error_path'] as String?,
errorTrace: json['error_trace'] as String?,
errorType: json['error_type'] != null
? RpcErrorType.fromString(json['error_type'] as String)
: null,
errorData: json['error_data'] as String?,
id: json['id'] as int?,
);

final String? mmrpc;
final String? error;
Expand All @@ -42,14 +65,14 @@ class RpcError extends Equatable {
final int? id;

Map<String, dynamic> toJson() => {
'mmrpc': mmrpc,
'error': error,
'error_path': errorPath,
'error_trace': errorTrace,
'error_type': errorType?.toString(),
'error_data': errorData,
'id': id,
};
'mmrpc': mmrpc,
'error': error,
'error_path': errorPath,
'error_trace': errorTrace,
'error_type': errorType?.toString(),
'error_data': errorData,
'id': id,
};

RpcError copyWith({
String? mmrpc,
Expand Down Expand Up @@ -87,14 +110,6 @@ RpcError: {

@override
List<Object?> get props {
return [
mmrpc,
error,
errorPath,
errorTrace,
errorType,
errorData,
id,
];
return [mmrpc, error, errorPath, errorTrace, errorType, errorData, id];
}
}
4 changes: 2 additions & 2 deletions lib/mm2/mm2_api/rpc/rpc_error_type.dart
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ enum RpcErrorType {
}
}

static RpcErrorType fromString(String value) {
static RpcErrorType? fromString(String value) {
switch (value) {
case 'AlreadyStarted':
return RpcErrorType.alreadyStarted;
Expand All @@ -34,7 +34,7 @@ enum RpcErrorType {
case 'InvalidRequest':
return RpcErrorType.invalidRequest;
default:
throw ArgumentError('Invalid value: $value');
return null;
}
}
}
26 changes: 8 additions & 18 deletions lib/model/settings/market_maker_bot_settings.dart
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
import 'package:equatable/equatable.dart';
import 'package:web_dex/mm2/mm2_api/rpc/market_maker_bot/message_service_config/message_service_config.dart';
import 'package:web_dex/mm2/mm2_api/rpc/market_maker_bot/trade_coin_pair_config.dart';
import 'package:web_dex/shared/constants.dart';

/// Settings for the KDF Simple Market Maker Bot.
class MarketMakerBotSettings extends Equatable {
const MarketMakerBotSettings({
required this.isMMBotEnabled,
required this.priceUrl,
required this.botRefreshRate,
required this.tradeCoinPairConfigs,
this.messageServiceConfig,
Expand All @@ -20,7 +18,6 @@ class MarketMakerBotSettings extends Equatable {
factory MarketMakerBotSettings.initial() {
return MarketMakerBotSettings(
isMMBotEnabled: false,
priceUrl: pricesUrlV3.toString(),
botRefreshRate: 60,
tradeCoinPairConfigs: const [],
messageServiceConfig: null,
Expand All @@ -37,7 +34,6 @@ class MarketMakerBotSettings extends Equatable {

return MarketMakerBotSettings(
isMMBotEnabled: json['is_market_maker_bot_enabled'] as bool,
priceUrl: json['price_url'] as String,
botRefreshRate: json['bot_refresh_rate'] as int,
tradeCoinPairConfigs: (json['trade_coin_pair_configs'] as List<dynamic>)
.map((e) => TradeCoinPairConfig.fromJson(e as Map<String, dynamic>))
Expand All @@ -53,9 +49,6 @@ class MarketMakerBotSettings extends Equatable {
/// Whether the Market Maker Bot is enabled (menu item is shown or not).
final bool isMMBotEnabled;

/// The URL to fetch the price data from.
final String priceUrl;

/// The refresh rate of the bot in seconds.
final int botRefreshRate;

Expand All @@ -70,25 +63,23 @@ class MarketMakerBotSettings extends Equatable {
Map<String, dynamic> toJson() {
return {
'is_market_maker_bot_enabled': isMMBotEnabled,
'price_url': priceUrl,
'bot_refresh_rate': botRefreshRate,
'trade_coin_pair_configs':
tradeCoinPairConfigs.map((e) => e.toJson()).toList(),
'trade_coin_pair_configs': tradeCoinPairConfigs
.map((e) => e.toJson())
.toList(),
if (messageServiceConfig != null)
'message_service_config': messageServiceConfig?.toJson(),
};
}

MarketMakerBotSettings copyWith({
bool? isMMBotEnabled,
String? priceUrl,
int? botRefreshRate,
List<TradeCoinPairConfig>? tradeCoinPairConfigs,
MessageServiceConfig? messageServiceConfig,
}) {
return MarketMakerBotSettings(
isMMBotEnabled: isMMBotEnabled ?? this.isMMBotEnabled,
priceUrl: priceUrl ?? this.priceUrl,
botRefreshRate: botRefreshRate ?? this.botRefreshRate,
tradeCoinPairConfigs: tradeCoinPairConfigs ?? this.tradeCoinPairConfigs,
messageServiceConfig: messageServiceConfig ?? this.messageServiceConfig,
Expand All @@ -97,10 +88,9 @@ class MarketMakerBotSettings extends Equatable {

@override
List<Object?> get props => [
isMMBotEnabled,
priceUrl,
botRefreshRate,
tradeCoinPairConfigs,
messageServiceConfig,
];
isMMBotEnabled,
botRefreshRate,
tradeCoinPairConfigs,
messageServiceConfig,
];
}
2 changes: 1 addition & 1 deletion lib/shared/constants.dart
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ final RegExp matrixIdRegex = RegExp(
r'^@[a-zA-Z0-9._=-]+:[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$',
);
final Uri pricesUrlV3 = Uri.parse(
'https://defi-stats.komodo.earth/api/v3/prices/tickers_v2?expire_at=60',
'https://prices.komodian.info/api/v2/tickers?expire_at=60',
Comment thread
takenagain marked this conversation as resolved.
);

const int millisecondsIn24H = 86400000;
Expand Down
11 changes: 7 additions & 4 deletions lib/views/dex/dex_list_filter/mobile/dex_list_header_mobile.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,30 +3,32 @@ import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:komodo_ui_kit/komodo_ui_kit.dart';
import 'package:web_dex/app_config/app_config.dart';
import 'package:web_dex/blocs/trading_entities_bloc.dart';
import 'package:web_dex/generated/codegen_loader.g.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/trading_entities_filter.dart';
import 'package:komodo_ui_kit/komodo_ui_kit.dart';

class DexListHeaderMobile extends StatelessWidget {
const DexListHeaderMobile({
Key? key,
super.key,
required this.listType,
required this.entitiesFilterData,
required this.onFilterPressed,
required this.onFilterDataChange,
required this.isFilterShown,
this.centerWidget,
}) : super(key: key);
this.onCancelAll,
});
final DexListType listType;
final TradingEntitiesFilter? entitiesFilterData;
final bool isFilterShown;
final VoidCallback onFilterPressed;
final void Function(TradingEntitiesFilter?) onFilterDataChange;
final Widget? centerWidget;
final VoidCallback? onCancelAll;

@override
Widget build(BuildContext context) {
Expand Down Expand Up @@ -54,7 +56,8 @@ class DexListHeaderMobile extends StatelessWidget {
text: LocaleKeys.cancelAll.tr(),
width: 100,
height: 30,
onPressed: () => tradingEntitiesBloc.cancelAllOrders(),
onPressed:
onCancelAll ?? () => tradingEntitiesBloc.cancelAllOrders(),
textStyle: const TextStyle(
fontSize: 14,
fontWeight: FontWeight.w500,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,10 @@ class _MobileWidget extends StatelessWidget {
onFilterDataChange: onApplyFilter,
onFilterPressed: onFilterTap,
centerWidget: type == MarketMakerBotTabType.orders
? _buildBotControls(context)
? const _SimplifiedTradingBotControls()
: null,
onCancelAll: type == MarketMakerBotTabType.orders
? () => _handleCancelAllOrders(context)
: null,
),
const SizedBox(height: 6),
Expand All @@ -204,7 +207,23 @@ class _MobileWidget extends StatelessWidget {
}
}

Widget _buildBotControls(BuildContext context) {
void _handleCancelAllOrders(BuildContext context) {
final orderListBloc = context.read<MarketMakerOrderListBloc>();
final marketMakerBotBloc = context.read<MarketMakerBotBloc>();
final orders = orderListBloc.state.makerBotOrders;

if (orders.isNotEmpty) {
final tradePairs = orders.map((e) => e.config).toList();
marketMakerBotBloc.add(MarketMakerBotOrderCancelRequested(tradePairs));
}
}
}

class _SimplifiedTradingBotControls extends StatelessWidget {
const _SimplifiedTradingBotControls({super.key});

@override
Widget build(BuildContext context) {
return BlocBuilder<MarketMakerBotBloc, MarketMakerBotState>(
builder: (context, botState) {
return BlocBuilder<MarketMakerOrderListBloc, MarketMakerOrderListState>(
Expand Down
Loading