From 1a3d47748dd89fbb323d00a36b04198bc8a6b566 Mon Sep 17 00:00:00 2001 From: Omar Hatem Date: Wed, 10 May 2023 16:58:31 +0300 Subject: [PATCH] V4.6.4 bug fixes (#922) * Fix Concurrent modification exception * Fix minor UI issues * Change onramper crypto asset name for Litcoin * Fix secure storage issue, fetching password/PIN with null * - Fix Navigation issue while keyboard is displaying - Remove deprecated screen * Take currency From/To info from our trade not the returned one * Fix anon pay fields UI * Fix Anonpay border/icons UI * Add extra padding in QR image as a safe layer * Generalize ignored connection error * Remove Bio Auth option from desktop * Fix some Transaction info not parsed correctly --- cw_bitcoin/lib/electrum.dart | 2 +- lib/buy/onramper/onramper_buy_provider.dart | 14 +++- lib/router.dart | 6 +- .../dashboard/widgets/address_page.dart | 5 +- .../present_receive_option_picker.dart | 18 ++-- .../widgets/anonpay_currency_input_field.dart | 2 +- .../receive/widgets/anonpay_input_form.dart | 6 +- .../receive/widgets/currency_input_field.dart | 18 ++-- lib/src/screens/receive/widgets/qr_image.dart | 2 +- .../screens/receive/widgets/qr_widget.dart | 1 + .../screens/restore/restore_from_keys.dart | 83 ------------------- .../settings/security_backup_page.dart | 42 +++++----- lib/utils/exception_handler.dart | 9 +- .../exchange/exchange_trade_view_model.dart | 8 +- .../exchange/exchange_view_model.dart | 50 ++++++----- pubspec_base.yaml | 4 +- 16 files changed, 113 insertions(+), 157 deletions(-) delete mode 100644 lib/src/screens/restore/restore_from_keys.dart diff --git a/cw_bitcoin/lib/electrum.dart b/cw_bitcoin/lib/electrum.dart index 81f2da161..70b072f7b 100644 --- a/cw_bitcoin/lib/electrum.dart +++ b/cw_bitcoin/lib/electrum.dart @@ -88,7 +88,7 @@ class ElectrumClient { unterminatedString = ''; } } on TypeError catch (e) { - if (!e.toString().contains('Map') || !e.toString().contains('Map')) { + if (!e.toString().contains('Map') && !e.toString().contains('Map')) { return; } diff --git a/lib/buy/onramper/onramper_buy_provider.dart b/lib/buy/onramper/onramper_buy_provider.dart index a887f98dc..faf2e6da7 100644 --- a/lib/buy/onramper/onramper_buy_provider.dart +++ b/lib/buy/onramper/onramper_buy_provider.dart @@ -1,6 +1,7 @@ import 'package:cake_wallet/.secrets.g.dart' as secrets; import 'package:cake_wallet/store/settings_store.dart'; import 'package:cake_wallet/themes/theme_base.dart'; +import 'package:cw_core/crypto_currency.dart'; import 'package:cw_core/wallet_base.dart'; class OnRamperBuyProvider { @@ -13,7 +14,16 @@ class OnRamperBuyProvider { static const _baseUrl = 'buy.onramper.com'; - static String get _apiKey => secrets.onramperApiKey; + String get _apiKey => secrets.onramperApiKey; + + String get _normalizeCryptoCurrency { + switch (_wallet.currency) { + case CryptoCurrency.ltc: + return "LTC_LITECOIN"; + default: + return _wallet.currency.title; + } + } Uri requestUrl() { String primaryColor, @@ -53,7 +63,7 @@ class OnRamperBuyProvider { return Uri.https(_baseUrl, '', { 'apiKey': _apiKey, - 'defaultCrypto': _wallet.currency.title, + 'defaultCrypto': _normalizeCryptoCurrency, 'defaultFiat': _settingsStore.fiatCurrency.title, 'wallets': '${_wallet.currency.title}:${_wallet.walletAddresses.address}', 'supportSell': "false", diff --git a/lib/router.dart b/lib/router.dart index 661a827e7..ccafe6abc 100644 --- a/lib/router.dart +++ b/lib/router.dart @@ -169,6 +169,7 @@ Route createRoute(RouteSettings settings) { fullscreenDialog: true); } else if (isSingleCoin) { return MaterialPageRoute( + fullscreenDialog: true, builder: (_) => getIt.get( param1: availableWalletTypes.first )); @@ -188,6 +189,7 @@ Route createRoute(RouteSettings settings) { case Routes.restoreWallet: return MaterialPageRoute( + fullscreenDialog: true, builder: (_) => getIt.get( param1: settings.arguments as WalletType)); @@ -509,7 +511,9 @@ Route createRoute(RouteSettings settings) { case Routes.anonPayInvoicePage: final args = settings.arguments as List; - return CupertinoPageRoute(builder: (_) => getIt.get(param1: args)); + return CupertinoPageRoute( + fullscreenDialog: true, + builder: (_) => getIt.get(param1: args)); case Routes.anonPayReceivePage: final anonInvoiceViewData = settings.arguments as AnonpayInfoBase; diff --git a/lib/src/screens/dashboard/widgets/address_page.dart b/lib/src/screens/dashboard/widgets/address_page.dart index 465c494d1..975887a7a 100644 --- a/lib/src/screens/dashboard/widgets/address_page.dart +++ b/lib/src/screens/dashboard/widgets/address_page.dart @@ -96,7 +96,10 @@ class AddressPage extends BasePage { @override Widget middle(BuildContext context) => - PresentReceiveOptionPicker(receiveOptionViewModel: receiveOptionViewModel); + PresentReceiveOptionPicker( + receiveOptionViewModel: receiveOptionViewModel, + hasWhiteBackground: currentTheme.type == ThemeType.light, + ); @override Widget Function(BuildContext, Widget) get rootWrapper => diff --git a/lib/src/screens/dashboard/widgets/present_receive_option_picker.dart b/lib/src/screens/dashboard/widgets/present_receive_option_picker.dart index 8b3ffb894..7b02765b3 100644 --- a/lib/src/screens/dashboard/widgets/present_receive_option_picker.dart +++ b/lib/src/screens/dashboard/widgets/present_receive_option_picker.dart @@ -9,14 +9,22 @@ import 'package:flutter_mobx/flutter_mobx.dart'; import 'package:cake_wallet/generated/i18n.dart'; class PresentReceiveOptionPicker extends StatelessWidget { - PresentReceiveOptionPicker({required this.receiveOptionViewModel}); + PresentReceiveOptionPicker( + {required this.receiveOptionViewModel, this.hasWhiteBackground = false}); final ReceiveOptionViewModel receiveOptionViewModel; + final bool hasWhiteBackground; @override Widget build(BuildContext context) { - final arrowBottom = - Image.asset('assets/images/arrow_bottom_purple_icon.png', color: Colors.white, height: 6); + final textIconTheme = hasWhiteBackground + ? Theme.of(context).accentTextTheme.headline2!.backgroundColor! + : Colors.white; + final arrowBottom = Image.asset( + 'assets/images/arrow_bottom_purple_icon.png', + color: textIconTheme, + height: 6, + ); return TextButton( onPressed: () => _showPicker(context), @@ -40,14 +48,14 @@ class PresentReceiveOptionPicker extends StatelessWidget { fontSize: 18.0, fontWeight: FontWeight.bold, fontFamily: 'Lato', - color: Theme.of(context).accentTextTheme.headline2!.backgroundColor!), + color: textIconTheme), ), Observer( builder: (_) => Text(receiveOptionViewModel.selectedReceiveOption.toString(), style: TextStyle( fontSize: 10.0, fontWeight: FontWeight.w500, - color: Theme.of(context).textTheme.headline5!.color!))) + color: textIconTheme))) ], ), SizedBox(width: 5), diff --git a/lib/src/screens/receive/widgets/anonpay_currency_input_field.dart b/lib/src/screens/receive/widgets/anonpay_currency_input_field.dart index 6f2d5179c..824044333 100644 --- a/lib/src/screens/receive/widgets/anonpay_currency_input_field.dart +++ b/lib/src/screens/receive/widgets/anonpay_currency_input_field.dart @@ -32,7 +32,7 @@ class AnonpayCurrencyInputField extends StatelessWidget { decoration: BoxDecoration( border: Border( bottom: BorderSide( - color: Theme.of(context).accentTextTheme.headline6!.backgroundColor!, + color: Theme.of(context).primaryTextTheme.bodyText1!.color!, width: 1)), ), child: Padding( diff --git a/lib/src/screens/receive/widgets/anonpay_input_form.dart b/lib/src/screens/receive/widgets/anonpay_input_form.dart index 974601baa..bd8a23d9c 100644 --- a/lib/src/screens/receive/widgets/anonpay_input_form.dart +++ b/lib/src/screens/receive/widgets/anonpay_input_form.dart @@ -69,7 +69,7 @@ class AnonInvoiceForm extends StatelessWidget { BaseTextFormField( controller: nameController, focusNode: _nameFocusNode, - borderColor: Theme.of(context).accentTextTheme.headline6!.backgroundColor, + borderColor: Theme.of(context).primaryTextTheme.bodyText1!.color!, suffixIcon: SizedBox(width: 36), hintText: S.of(context).optional_name, textInputAction: TextInputAction.next, @@ -88,7 +88,7 @@ class AnonInvoiceForm extends StatelessWidget { controller: descriptionController, focusNode: _descriptionFocusNode, textInputAction: TextInputAction.next, - borderColor: Theme.of(context).accentTextTheme.headline6!.backgroundColor, + borderColor: Theme.of(context).primaryTextTheme.bodyText1!.color!, suffixIcon: SizedBox(width: 36), hintText: S.of(context).optional_description, placeholderTextStyle: TextStyle( @@ -104,7 +104,7 @@ class AnonInvoiceForm extends StatelessWidget { controller: emailController, textInputAction: TextInputAction.next, focusNode: _emailFocusNode, - borderColor: Theme.of(context).accentTextTheme.headline6!.backgroundColor, + borderColor: Theme.of(context).primaryTextTheme.bodyText1!.color!, suffixIcon: SizedBox(width: 36), keyboardType: TextInputType.emailAddress, hintText: S.of(context).optional_email_hint, diff --git a/lib/src/screens/receive/widgets/currency_input_field.dart b/lib/src/screens/receive/widgets/currency_input_field.dart index 286c6f1cd..273bbb46b 100644 --- a/lib/src/screens/receive/widgets/currency_input_field.dart +++ b/lib/src/screens/receive/widgets/currency_input_field.dart @@ -1,4 +1,3 @@ -import 'package:cake_wallet/core/amount_validator.dart'; import 'package:cake_wallet/src/widgets/base_text_form_field.dart'; import 'package:cw_core/currency.dart'; import 'package:flutter/material.dart'; @@ -10,18 +9,20 @@ class CurrencyInputField extends StatelessWidget { required this.onTapPicker, required this.selectedCurrency, this.focusNode, - required this.controller, + required this.controller, required this.isLight, }); + final Function() onTapPicker; final Currency selectedCurrency; final FocusNode? focusNode; final TextEditingController controller; + final bool isLight; @override Widget build(BuildContext context) { final arrowBottomPurple = Image.asset( 'assets/images/arrow_bottom_purple_icon.png', - color: Colors.white, + color: Theme.of(context).accentTextTheme.headline2!.backgroundColor!, height: 8, ); final _width = MediaQuery.of(context).size.width; @@ -38,14 +39,14 @@ class CurrencyInputField extends StatelessWidget { keyboardType: TextInputType.numberWithOptions(signed: false, decimal: true), inputFormatters: [FilteringTextInputFormatter.allow(RegExp(r'^\d+(\.|\,)?\d{0,8}'))], hintText: '0.000', - placeholderTextStyle: TextStyle( + placeholderTextStyle: isLight ? null : TextStyle( color: Theme.of(context).primaryTextTheme.headline5!.color!, fontWeight: FontWeight.w600, ), borderColor: Theme.of(context).accentTextTheme.headline6!.backgroundColor!, - textColor: Colors.white, + textColor: Theme.of(context).accentTextTheme.headline2!.backgroundColor!, textStyle: TextStyle( - color: Colors.white, + color: Theme.of(context).accentTextTheme.headline2!.backgroundColor!, ), prefixIcon: Padding( padding: EdgeInsets.only( @@ -68,7 +69,7 @@ class CurrencyInputField extends StatelessWidget { style: TextStyle( fontWeight: FontWeight.w600, fontSize: 16, - color: Colors.white, + color: Theme.of(context).accentTextTheme.headline2!.backgroundColor!, ), ), if (selectedCurrency.tag != null) @@ -103,7 +104,8 @@ class CurrencyInputField extends StatelessWidget { style: TextStyle( fontWeight: FontWeight.w600, fontSize: 20, - color: Colors.white, + color: + Theme.of(context).accentTextTheme.headline2!.backgroundColor!, ), ), ), diff --git a/lib/src/screens/receive/widgets/qr_image.dart b/lib/src/screens/receive/widgets/qr_image.dart index c624ad3c0..f4c1eb177 100644 --- a/lib/src/screens/receive/widgets/qr_image.dart +++ b/lib/src/screens/receive/widgets/qr_image.dart @@ -23,7 +23,7 @@ class QrImage extends StatelessWidget { size: size, foregroundColor: Colors.black, backgroundColor: Colors.white, - padding: EdgeInsets.zero, + padding: const EdgeInsets.all(8.0), ); } } diff --git a/lib/src/screens/receive/widgets/qr_widget.dart b/lib/src/screens/receive/widgets/qr_widget.dart index 33cc3d598..610b0d245 100644 --- a/lib/src/screens/receive/widgets/qr_widget.dart +++ b/lib/src/screens/receive/widgets/qr_widget.dart @@ -119,6 +119,7 @@ class QRWidget extends StatelessWidget { controller: amountController, onTapPicker: () => _presentPicker(context), selectedCurrency: addressListViewModel.selectedCurrency, + isLight: isLight, ), ), ), diff --git a/lib/src/screens/restore/restore_from_keys.dart b/lib/src/screens/restore/restore_from_keys.dart deleted file mode 100644 index cd0116e56..000000000 --- a/lib/src/screens/restore/restore_from_keys.dart +++ /dev/null @@ -1,83 +0,0 @@ -import 'package:flutter/services.dart'; -import 'package:flutter/cupertino.dart'; -import 'package:flutter/material.dart'; -import 'package:cake_wallet/generated/i18n.dart'; -import 'package:cake_wallet/src/widgets/blockchain_height_widget.dart'; -import 'package:cake_wallet/src/widgets/base_text_form_field.dart'; - -class RestoreFromKeysFrom extends StatefulWidget { - @override - _RestoreFromKeysFromState createState() => _RestoreFromKeysFromState(); -} - -class _RestoreFromKeysFromState extends State { - final _formKey = GlobalKey(); - final _blockchainHeightKey = GlobalKey(); - final _nameController = TextEditingController(); - final _addressController = TextEditingController(); - final _viewKeyController = TextEditingController(); - final _spendKeyController = TextEditingController(); - final _wifController = TextEditingController(); - - @override - void initState() { - // _nameController.addListener(() => - // widget.walletRestorationFromKeysVM.name = _nameController.text); - // _addressController.addListener(() => - // widget.walletRestorationFromKeysVM.address = _addressController.text); - // _viewKeyController.addListener(() => - // widget.walletRestorationFromKeysVM.viewKey = _viewKeyController.text); - // _spendKeyController.addListener(() => - // widget.walletRestorationFromKeysVM.spendKey = _spendKeyController.text); - // _wifController.addListener(() => - // widget.walletRestorationFromKeysVM.wif = _wifController.text); - - super.initState(); - } - - @override - void dispose() { - _nameController.dispose(); - _addressController.dispose(); - _viewKeyController.dispose(); - _spendKeyController.dispose(); - _wifController.dispose(); - super.dispose(); - } - - @override - Widget build(BuildContext context) { - return Container( - padding: EdgeInsets.only(left: 24, right: 24), - child: Form( - key: _formKey, - child: Column(children: [ - BaseTextFormField( - controller: _addressController, - keyboardType: TextInputType.multiline, - maxLines: null, - hintText: S.of(context).restore_address, - ), - Container( - padding: EdgeInsets.only(top: 20.0), - child: BaseTextFormField( - controller: _viewKeyController, - hintText: S.of(context).restore_view_key_private, - )), - Container( - padding: EdgeInsets.only(top: 20.0), - child: BaseTextFormField( - controller: _spendKeyController, - hintText: S.of(context).restore_spend_key_private, - )), - BlockchainHeightWidget( - key: _blockchainHeightKey, - onHeightChange: (height) { - // widget.walletRestorationFromKeysVM.height = height; - print(height); - }), - ]), - ), - ); - } -} diff --git a/lib/src/screens/settings/security_backup_page.dart b/lib/src/screens/settings/security_backup_page.dart index 0933560f7..24c597a00 100644 --- a/lib/src/screens/settings/security_backup_page.dart +++ b/lib/src/screens/settings/security_backup_page.dart @@ -8,6 +8,7 @@ import 'package:cake_wallet/src/screens/settings/widgets/settings_cell_with_arro import 'package:cake_wallet/src/screens/settings/widgets/settings_picker_cell.dart'; import 'package:cake_wallet/src/screens/settings/widgets/settings_switcher_cell.dart'; import 'package:cake_wallet/src/widgets/standard_list.dart'; +import 'package:cake_wallet/utils/device_info.dart'; import 'package:cake_wallet/view_model/settings/security_settings_view_model.dart'; import 'package:flutter/material.dart'; import 'package:flutter_mobx/flutter_mobx.dart'; @@ -48,29 +49,30 @@ class SecurityBackupPage extends BasePage { ), ), StandardListSeparator(padding: EdgeInsets.symmetric(horizontal: 24)), - Observer(builder: (_) { - return SettingsSwitcherCell( - title: S.current.settings_allow_biometrical_authentication, - value: _securitySettingsViewModel.allowBiometricalAuthentication, - onValueChange: (BuildContext context, bool value) { - if (value) { - _authService.authenticateAction(context, - onAuthSuccess: (isAuthenticatedSuccessfully) async { - if (isAuthenticatedSuccessfully) { - if (await _securitySettingsViewModel.biometricAuthenticated()) { + if (DeviceInfo.instance.isMobile) + Observer(builder: (_) { + return SettingsSwitcherCell( + title: S.current.settings_allow_biometrical_authentication, + value: _securitySettingsViewModel.allowBiometricalAuthentication, + onValueChange: (BuildContext context, bool value) { + if (value) { + _authService.authenticateAction(context, + onAuthSuccess: (isAuthenticatedSuccessfully) async { + if (isAuthenticatedSuccessfully) { + if (await _securitySettingsViewModel.biometricAuthenticated()) { + _securitySettingsViewModel + .setAllowBiometricalAuthentication(isAuthenticatedSuccessfully); + } + } else { _securitySettingsViewModel .setAllowBiometricalAuthentication(isAuthenticatedSuccessfully); } - } else { - _securitySettingsViewModel - .setAllowBiometricalAuthentication(isAuthenticatedSuccessfully); - } - }); - } else { - _securitySettingsViewModel.setAllowBiometricalAuthentication(value); - } - }); - }), + }); + } else { + _securitySettingsViewModel.setAllowBiometricalAuthentication(value); + } + }); + }), Observer(builder: (_) { return SettingsPickerCell( title: S.current.require_pin_after, diff --git a/lib/utils/exception_handler.dart b/lib/utils/exception_handler.dart index d3689e7e0..4b156ade1 100644 --- a/lib/utils/exception_handler.dart +++ b/lib/utils/exception_handler.dart @@ -141,9 +141,9 @@ class ExceptionHandler { "errno = 103", // SocketException: Software caused connection abort "errno = 104", // SocketException: Connection reset by peer "errno = 110", // SocketException: Connection timed out - "HttpException: Connection reset by peer", - "HttpException: Connection closed before full header was received", - "HandshakeException: Connection terminated during handshake", + "Connection reset by peer", + "Connection closed before full header was received", + "Connection terminated during handshake", "PERMISSION_NOT_GRANTED", ]; @@ -172,7 +172,7 @@ class ExceptionHandler { } await file.writeAsString( - "App Version: $currentVersion\n\nDevice Info $deviceInfo", + "App Version: $currentVersion\n\nDevice Info $deviceInfo\n\n", mode: FileMode.append, ); } @@ -193,6 +193,7 @@ class ExceptionHandler { 'systemVersion': data.systemVersion, 'model': data.model, 'localizedModel': data.localizedModel, + 'isPhysicalDevice': data.isPhysicalDevice, }; } diff --git a/lib/view_model/exchange/exchange_trade_view_model.dart b/lib/view_model/exchange/exchange_trade_view_model.dart index 194dc9d45..1d9f4f582 100644 --- a/lib/view_model/exchange/exchange_trade_view_model.dart +++ b/lib/view_model/exchange/exchange_trade_view_model.dart @@ -123,8 +123,8 @@ abstract class ExchangeTradeViewModelBase with Store { } void _updateItems() { - final tagFrom = trade.from.tag != null ? '${trade.from.tag}' + ' ' : ''; - final tagTo = trade.to.tag != null ? '${trade.to.tag}' + ' ' : ''; + final tagFrom = tradesStore.trade!.from.tag != null ? '${tradesStore.trade!.from.tag}' + ' ' : ''; + final tagTo = tradesStore.trade!.to.tag != null ? '${tradesStore.trade!.to.tag}' + ' ' : ''; items.clear(); items.add(ExchangeTradeItem( title: "${trade.provider.title} ${S.current.id}", data: '${trade.id}', isCopied: true)); @@ -142,11 +142,11 @@ abstract class ExchangeTradeViewModelBase with Store { items.addAll([ ExchangeTradeItem(title: S.current.amount, data: '${trade.amount}', isCopied: true), ExchangeTradeItem( - title: S.current.send_to_this_address('${trade.from}', tagFrom) + ':', + title: S.current.send_to_this_address('${tradesStore.trade!.from}', tagFrom) + ':', data: trade.inputAddress ?? '', isCopied: true), ExchangeTradeItem( - title: S.current.arrive_in_this_address('${trade.to}', tagTo) + ':', + title: S.current.arrive_in_this_address('${tradesStore.trade!.to}', tagTo) + ':', data: trade.payoutAddress ?? '', isCopied: true), ]); diff --git a/lib/view_model/exchange/exchange_view_model.dart b/lib/view_model/exchange/exchange_view_model.dart index 3c016d4b0..77fb9a3d4 100644 --- a/lib/view_model/exchange/exchange_view_model.dart +++ b/lib/view_model/exchange/exchange_view_model.dart @@ -3,7 +3,6 @@ import 'dart:collection'; import 'dart:convert'; import 'package:cake_wallet/entities/exchange_api_mode.dart'; -import 'package:cake_wallet/entities/fiat_api_mode.dart'; import 'package:cake_wallet/entities/preferences_key.dart'; import 'package:cake_wallet/exchange/sideshift/sideshift_exchange_provider.dart'; import 'package:cake_wallet/exchange/sideshift/sideshift_request.dart'; @@ -244,7 +243,7 @@ abstract class ExchangeViewModelBase with Store { List depositCurrencies; - NumberFormat _cryptoNumberFormat; + final NumberFormat _cryptoNumberFormat; final SettingsStore _settingsStore; @@ -388,27 +387,36 @@ abstract class ExchangeViewModelBase with Store { double? lowestMin = double.maxFinite; double? highestMax = 0.0; - for (var provider in selectedProviders) { - /// if this provider is not valid for the current pair, skip it - if (!providersForCurrentPair().contains(provider)) { - continue; - } - - try { - final tempLimits = await provider.fetchLimits( - from: from, - to: to, - isFixedRateMode: isFixedRateMode); - - if (lowestMin != null && (tempLimits.min ?? -1) < lowestMin) { - lowestMin = tempLimits.min; + try { + for (var provider in selectedProviders) { + /// if this provider is not valid for the current pair, skip it + if (!providersForCurrentPair().contains(provider)) { + continue; } - if (highestMax != null && (tempLimits.max ?? double.maxFinite) > highestMax) { - highestMax = tempLimits.max; + + try { + final tempLimits = await provider.fetchLimits( + from: from, + to: to, + isFixedRateMode: isFixedRateMode); + + if (lowestMin != null && (tempLimits.min ?? -1) < lowestMin) { + lowestMin = tempLimits.min; + } + if (highestMax != null && (tempLimits.max ?? double.maxFinite) > highestMax) { + highestMax = tempLimits.max; + } + } catch (e) { + continue; } - } catch (e) { - continue; } + } on ConcurrentModificationError { + /// if user changed the selected providers while fetching limits + /// then delay the fetching limits a bit and try again + /// + /// this is because the limitation of collections that + /// you can't modify it while iterating through it + Future.delayed(Duration(milliseconds: 200), loadLimits); } if (lowestMin != double.maxFinite) { @@ -534,7 +542,7 @@ abstract class ExchangeViewModelBase with Store { /// /// this is because the limitation of the SplayTreeMap that /// you can't modify it while iterating through it - Future.delayed(Duration(milliseconds: 500), createTrade); + Future.delayed(Duration(milliseconds: 200), createTrade); } } diff --git a/pubspec_base.yaml b/pubspec_base.yaml index 0d6aa36e8..ebe276a54 100644 --- a/pubspec_base.yaml +++ b/pubspec_base.yaml @@ -17,8 +17,8 @@ dependencies: git: url: https://github.com/cake-tech/flutter_secure_storage.git path: flutter_secure_storage - ref: cake-6.0.0 - version: 6.0.0 + ref: cake-8.0.0 + version: 8.0.0 # provider: ^6.0.3 rxdart: ^0.27.4 yaml: ^3.1.1