CW-674: Improve Exchange Flow With Timeout For Rates (#1536)
* fix: Improve exchange flow by adding a timeout to the call to fetch rate from providers * fix: Adjust time limit for fetching rate to 7 seconds and add timelimit to fetching limits * Improve loadlimits function [skip ci] --------- Co-authored-by: OmarHatem <omarh.ismail1@gmail.com>
Adegoke David committed
Jul 21, 2024 at 00:26 UTC
341e06196da34df29891fb3ec28b47ca94fee3a5
2 files changed
+52
-22
lib/exchange/provider/sideshift_exchange_provider.dart
+15
-1
@@ -1,4 +1,5 @@
1
import 'dart:convert';
2
+import 'dart:developer';
3
4
import 'package:cake_wallet/.secrets.g.dart' as secrets;
5
import 'package:cake_wallet/exchange/provider/exchange_provider.dart';
@@ -29,6 +30,7 @@ class SideShiftExchangeProvider extends ExchangeProvider {
30
CryptoCurrency.bttc,
31
CryptoCurrency.usdt,
32
CryptoCurrency.eos,
33
+ CryptoCurrency.xmr,
34
];
35
36
static const affiliateId = secrets.sideShiftAffiliateId;
@@ -137,8 +139,20 @@ class SideShiftExchangeProvider extends ExchangeProvider {
139
final response = await get(uri);
140
final responseJSON = json.decode(response.body) as Map<String, dynamic>;
141
142
+ if (response.statusCode == 500) {
143
+ final responseJSON = json.decode(response.body) as Map<String, dynamic>;
144
+ final error = responseJSON['error']['message'] as String;
145
+
146
+ throw Exception('SideShift Internal Server Error: $error');
147
+ }
148
+
149
+ if (response.statusCode != 200) {
150
+ throw Exception('Unexpected http status: ${response.statusCode}');
151
+ }
152
+
153
return double.parse(responseJSON['rate'] as String);
141
- } catch (_) {
154
+ } catch (e) {
155
+ log('Error fetching rate in SideShift Provider: ${e.toString()}');
156
return 0.00;
157
}
158
}
lib/view_model/exchange/exchange_view_model.dart
+37
-21
@@ -405,13 +405,22 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
405
.where((element) => !isFixedRateMode || element.supportsFixedRate)
406
.toList();
407
408
- final result = await Future.wait<double>(_providers.map((element) => element.fetchRate(
409
- from: depositCurrency,
410
- to: receiveCurrency,
411
- amount: amount,
412
- isFixedRateMode: isFixedRateMode,
413
- isReceiveAmount: isFixedRateMode)));
414
-
408
+ final result = await Future.wait<double>(
409
+ _providers.map(
410
+ (element) => element
411
+ .fetchRate(
412
+ from: depositCurrency,
413
+ to: receiveCurrency,
414
+ amount: amount,
415
+ isFixedRateMode: isFixedRateMode,
416
+ isReceiveAmount: isFixedRateMode,
417
+ )
418
+ .timeout(
419
+ Duration(seconds: 7),
420
+ onTimeout: () => 0.0,
421
+ ),
422
+ ),
423
+ );
424
_sortedAvailableProviders.clear();
425
426
for (int i = 0; i < result.length; i++) {
@@ -441,22 +450,29 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
450
double? highestMax = 0.0;
451
452
try {
444
- for (var provider in selectedProviders) {
445
- /// if this provider is not valid for the current pair, skip it
446
- if (!providersForCurrentPair().contains(provider)) continue;
447
-
448
- try {
449
- final tempLimits =
450
- await provider.fetchLimits(from: from, to: to, isFixedRateMode: isFixedRateMode);
451
-
452
- if (lowestMin != null && (tempLimits.min ?? -1) < lowestMin) lowestMin = tempLimits.min;
453
+ final result = await Future.wait(selectedProviders
454
+ .where((element) => providersForCurrentPair().contains(provider))
455
+ .map((provider) => provider
456
+ .fetchLimits(
457
+ from: from,
458
+ to: to,
459
+ isFixedRateMode: isFixedRateMode,
460
+ )
461
+ .onError((error, stackTrace) => Limits(max: 0.0, min: double.maxFinite))
462
+ .timeout(
463
+ Duration(seconds: 7),
464
+ onTimeout: () => Limits(max: 0.0, min: double.maxFinite),
465
+ )));
466
+
467
+ result.forEach((tempLimits) {
468
+ if (lowestMin != null && (tempLimits.min ?? -1) < lowestMin!) {
469
+ lowestMin = tempLimits.min;
470
+ }
471
454
- if (highestMax != null && (tempLimits.max ?? double.maxFinite) > highestMax)
455
- highestMax = tempLimits.max;
456
- } catch (e) {
457
- continue;
472
+ if (highestMax != null && (tempLimits.max ?? double.maxFinite) > highestMax!) {
473
+ highestMax = tempLimits.max;
474
}
459
- }
475
+ });
476
} on ConcurrentModificationError {
477
/// if user changed the selected providers while fetching limits
478
/// then delay the fetching limits a bit and try again