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>
This commit is contained in:
Adegoke David 2024-07-21 00:26:05 +01:00 committed by GitHub
parent 415d2a3573
commit 341e06196d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 52 additions and 22 deletions

View file

@ -1,4 +1,5 @@
import 'dart:convert'; import 'dart:convert';
import 'dart:developer';
import 'package:cake_wallet/.secrets.g.dart' as secrets; import 'package:cake_wallet/.secrets.g.dart' as secrets;
import 'package:cake_wallet/exchange/provider/exchange_provider.dart'; import 'package:cake_wallet/exchange/provider/exchange_provider.dart';
@ -29,6 +30,7 @@ class SideShiftExchangeProvider extends ExchangeProvider {
CryptoCurrency.bttc, CryptoCurrency.bttc,
CryptoCurrency.usdt, CryptoCurrency.usdt,
CryptoCurrency.eos, CryptoCurrency.eos,
CryptoCurrency.xmr,
]; ];
static const affiliateId = secrets.sideShiftAffiliateId; static const affiliateId = secrets.sideShiftAffiliateId;
@ -137,8 +139,20 @@ class SideShiftExchangeProvider extends ExchangeProvider {
final response = await get(uri); final response = await get(uri);
final responseJSON = json.decode(response.body) as Map<String, dynamic>; final responseJSON = json.decode(response.body) as Map<String, dynamic>;
if (response.statusCode == 500) {
final responseJSON = json.decode(response.body) as Map<String, dynamic>;
final error = responseJSON['error']['message'] as String;
throw Exception('SideShift Internal Server Error: $error');
}
if (response.statusCode != 200) {
throw Exception('Unexpected http status: ${response.statusCode}');
}
return double.parse(responseJSON['rate'] as String); return double.parse(responseJSON['rate'] as String);
} catch (_) { } catch (e) {
log('Error fetching rate in SideShift Provider: ${e.toString()}');
return 0.00; return 0.00;
} }
} }

View file

@ -405,13 +405,22 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
.where((element) => !isFixedRateMode || element.supportsFixedRate) .where((element) => !isFixedRateMode || element.supportsFixedRate)
.toList(); .toList();
final result = await Future.wait<double>(_providers.map((element) => element.fetchRate( final result = await Future.wait<double>(
_providers.map(
(element) => element
.fetchRate(
from: depositCurrency, from: depositCurrency,
to: receiveCurrency, to: receiveCurrency,
amount: amount, amount: amount,
isFixedRateMode: isFixedRateMode, isFixedRateMode: isFixedRateMode,
isReceiveAmount: isFixedRateMode))); isReceiveAmount: isFixedRateMode,
)
.timeout(
Duration(seconds: 7),
onTimeout: () => 0.0,
),
),
);
_sortedAvailableProviders.clear(); _sortedAvailableProviders.clear();
for (int i = 0; i < result.length; i++) { for (int i = 0; i < result.length; i++) {
@ -441,22 +450,29 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
double? highestMax = 0.0; double? highestMax = 0.0;
try { try {
for (var provider in selectedProviders) { final result = await Future.wait(selectedProviders
/// if this provider is not valid for the current pair, skip it .where((element) => providersForCurrentPair().contains(provider))
if (!providersForCurrentPair().contains(provider)) continue; .map((provider) => provider
.fetchLimits(
from: from,
to: to,
isFixedRateMode: isFixedRateMode,
)
.onError((error, stackTrace) => Limits(max: 0.0, min: double.maxFinite))
.timeout(
Duration(seconds: 7),
onTimeout: () => Limits(max: 0.0, min: double.maxFinite),
)));
try { result.forEach((tempLimits) {
final tempLimits = if (lowestMin != null && (tempLimits.min ?? -1) < lowestMin!) {
await provider.fetchLimits(from: from, to: to, isFixedRateMode: isFixedRateMode); lowestMin = tempLimits.min;
}
if (lowestMin != null && (tempLimits.min ?? -1) < lowestMin) lowestMin = tempLimits.min; if (highestMax != null && (tempLimits.max ?? double.maxFinite) > highestMax!) {
if (highestMax != null && (tempLimits.max ?? double.maxFinite) > highestMax)
highestMax = tempLimits.max; highestMax = tempLimits.max;
} catch (e) {
continue;
}
} }
});
} on ConcurrentModificationError { } on ConcurrentModificationError {
/// if user changed the selected providers while fetching limits /// if user changed the selected providers while fetching limits
/// then delay the fetching limits a bit and try again /// then delay the fetching limits a bit and try again