diff --git a/lib/pages/exchange_view/exchange_form.dart b/lib/pages/exchange_view/exchange_form.dart index c4d11d162..b9cd4023f 100644 --- a/lib/pages/exchange_view/exchange_form.dart +++ b/lib/pages/exchange_view/exchange_form.dart @@ -5,7 +5,6 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:flutter_svg/svg.dart'; -import 'package:intl/intl.dart'; import 'package:isar/isar.dart'; import 'package:stackwallet/models/exchange/aggregate_currency.dart'; import 'package:stackwallet/models/exchange/incomplete_exchange.dart'; @@ -152,10 +151,22 @@ class _ExchangeFormState extends ConsumerState { return null; } try { - final numFromLocalised = NumberFormat.decimalPattern( - ref.read(localeServiceChangeNotifierProvider).locale) - .parse(value); - return Decimal.tryParse(numFromLocalised.toString()); + // wtf Dart????? + // This turns "99999999999999999999" into 100000000000000000000.0 + // final numFromLocalised = NumberFormat.decimalPattern( + // ref.read(localeServiceChangeNotifierProvider).locale) + // .parse(value); + // return Decimal.tryParse(numFromLocalised.toString()); + + try { + return Decimal.parse(value); + } catch (_) { + try { + return Decimal.parse(value.replaceAll(",", ".")); + } catch (_) { + rethrow; + } + } } catch (_) { return null; } @@ -953,12 +964,20 @@ class _ExchangeFormState extends ConsumerState { onChanged: onRateTypeChanged, ), ), - Padding( - padding: EdgeInsets.only(top: isDesktop ? 20 : 12), - child: ExchangeProviderOptions( - fixedRate: rateType == ExchangeRateType.fixed, - reversed: ref.watch(efReversedProvider), - ), + AnimatedSize( + duration: const Duration(milliseconds: 300), + child: ref.watch(efSendAmountProvider) == null && + ref.watch(efReceiveAmountProvider) == null + ? const SizedBox( + height: 0, + ) + : Padding( + padding: EdgeInsets.only(top: isDesktop ? 20 : 12), + child: ExchangeProviderOptions( + fixedRate: rateType == ExchangeRateType.fixed, + reversed: ref.watch(efReversedProvider), + ), + ), ), SizedBox( height: isDesktop ? 20 : 12, diff --git a/lib/pages_desktop_specific/desktop_exchange/desktop_exchange_view.dart b/lib/pages_desktop_specific/desktop_exchange/desktop_exchange_view.dart index 36006b7c1..ab8279866 100644 --- a/lib/pages_desktop_specific/desktop_exchange/desktop_exchange_view.dart +++ b/lib/pages_desktop_specific/desktop_exchange/desktop_exchange_view.dart @@ -150,10 +150,14 @@ class _DesktopExchangeViewState extends ConsumerState { child: Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ - const Expanded( - child: RoundedWhiteContainer( - padding: EdgeInsets.all(24), - child: ExchangeForm(), + Expanded( + child: ListView( + children: const [ + RoundedWhiteContainer( + padding: EdgeInsets.all(24), + child: ExchangeForm(), + ), + ], ), ), const SizedBox( diff --git a/lib/providers/exchange/exchange_form_state_provider.dart b/lib/providers/exchange/exchange_form_state_provider.dart index 7828e2771..afac49de8 100644 --- a/lib/providers/exchange/exchange_form_state_provider.dart +++ b/lib/providers/exchange/exchange_form_state_provider.dart @@ -34,7 +34,7 @@ final efSendAmountStringProvider = StateProvider((ref) { if (refreshing && reversed) { return "-"; } else { - return ref.watch(efSendAmountProvider)?.toStringAsFixed(8) ?? ""; + return ref.watch(efSendAmountProvider)?.toString() ?? ""; } }); final efReceiveAmountStringProvider = StateProvider((ref) { @@ -44,7 +44,7 @@ final efReceiveAmountStringProvider = StateProvider((ref) { if (refreshing && reversed == false) { return "-"; } else { - return ref.watch(efReceiveAmountProvider)?.toStringAsFixed(8) ?? ""; + return ref.watch(efReceiveAmountProvider)?.toString() ?? ""; } }); diff --git a/lib/services/exchange/change_now/change_now_api.dart b/lib/services/exchange/change_now/change_now_api.dart index 6f050d2e2..e14b2f128 100644 --- a/lib/services/exchange/change_now/change_now_api.dart +++ b/lib/services/exchange/change_now/change_now_api.dart @@ -100,12 +100,18 @@ class ChangeNowAPI { body: jsonEncode(body), ); - final parsed = jsonDecode(response.body); + try { + final parsed = jsonDecode(response.body); - return parsed; + return parsed; + } catch (_) { + Logging.instance.log("ChangeNOW api failed to parse: ${response.body}", + level: LogLevel.Error); + rethrow; + } } catch (e, s) { Logging.instance - .log("_makeRequest($uri) threw: $e\n$s", level: LogLevel.Error); + .log("_makePostRequest($uri) threw: $e\n$s", level: LogLevel.Error); rethrow; } } diff --git a/lib/services/exchange/trocador/trocador_api.dart b/lib/services/exchange/trocador/trocador_api.dart index 317ebba53..d74ff2460 100644 --- a/lib/services/exchange/trocador/trocador_api.dart +++ b/lib/services/exchange/trocador/trocador_api.dart @@ -302,10 +302,32 @@ abstract class TrocadorAPI { final json = await _makeGetRequest(uri); final map = Map.from(json as Map); - return ExchangeResponse(value: TrocadorTradeNew.fromMap(map)); + try { + return ExchangeResponse(value: TrocadorTradeNew.fromMap(map)); + } catch (e, s) { + String error = map["error"] as String? ?? json.toString(); + if (error == + "trade could not be generated, some unknown error happened") { + error = + "This trade couldn't be completed. Please select another provider."; + } + + Logging.instance.log( + "_getNewTrade failed to parse response: $json\n$e\n$s", + level: LogLevel.Error, + ); + return ExchangeResponse( + exception: ExchangeException( + error, + ExchangeExceptionType.serializeResponseError, + ), + ); + } } catch (e, s) { - Logging.instance - .log("_getNewTrade exception: $e\n$s", level: LogLevel.Error); + Logging.instance.log( + "_getNewTrade exception: $e\n$s", + level: LogLevel.Error, + ); return ExchangeResponse( exception: ExchangeException( e.toString(), diff --git a/lib/widgets/trocador_kyc_rating_info.dart b/lib/widgets/trocador_kyc_rating_info.dart index bfd786e9c..f7d531da7 100644 --- a/lib/widgets/trocador_kyc_rating_info.dart +++ b/lib/widgets/trocador_kyc_rating_info.dart @@ -1,6 +1,9 @@ import 'package:flutter/material.dart'; import 'package:stackwallet/utilities/text_styles.dart'; import 'package:stackwallet/widgets/conditional_parent.dart'; +import 'package:stackwallet/widgets/desktop/desktop_dialog.dart'; +import 'package:stackwallet/widgets/desktop/desktop_dialog_close_button.dart'; +import 'package:stackwallet/widgets/desktop/primary_button.dart'; import 'package:stackwallet/widgets/desktop/secondary_button.dart'; import 'package:stackwallet/widgets/exchange/trocador/trocador_kyc_icon.dart'; import 'package:stackwallet/widgets/exchange/trocador/trocador_rating_type_enum.dart'; @@ -12,9 +15,56 @@ class TrocadorKYCRatingInfo extends StatelessWidget { @override Widget build(BuildContext context) { final small = MediaQuery.of(context).size.width <= 500; + return ConditionalParent( condition: !small, - builder: (child) => child, + builder: (child) => DesktopDialog( + maxHeight: double.infinity, + child: Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Padding( + padding: const EdgeInsets.only(left: 32), + child: Text( + "Trocador KYC Rating", + style: STextStyles.desktopH3(context), + ), + ), + const DesktopDialogCloseButton(), + ], + ), + const SizedBox( + height: 16, + ), + Padding( + padding: const EdgeInsets.symmetric( + horizontal: 32, + ), + child: child, + ), + Padding( + padding: const EdgeInsets.all(32), + child: Row( + children: [ + const Spacer(), + const SizedBox( + width: 16, + ), + Expanded( + child: PrimaryButton( + label: "Ok", + buttonHeight: ButtonHeight.l, + onPressed: Navigator.of(context).pop, + ), + ), + ], + ), + ) + ], + ), + ), child: ConditionalParent( condition: small, builder: (child) { @@ -24,13 +74,15 @@ class TrocadorKYCRatingInfo extends StatelessWidget { }, child: Column( children: [ - Text( - "Trocador KYC Rating", - style: STextStyles.pageTitleH2(context), - ), - const SizedBox( - height: 16, - ), + if (small) + Text( + "Trocador KYC Rating", + style: STextStyles.pageTitleH2(context), + ), + if (small) + const SizedBox( + height: 16, + ), const _Rating( kycType: TrocadorKYCType.a, text: "Never asks for user verification.",