load paired currencies directly with no pair caching

This commit is contained in:
julian 2023-02-13 09:05:22 -06:00
parent 8a3d1af7e5
commit aa91311cca
7 changed files with 152 additions and 171 deletions

View file

@ -6,7 +6,9 @@ import 'package:isar/isar.dart';
import 'package:stackwallet/models/isar/exchange_cache/currency.dart';
import 'package:stackwallet/models/isar/exchange_cache/pair.dart';
import 'package:stackwallet/pages/buy_view/sub_widgets/crypto_selection_view.dart';
import 'package:stackwallet/services/exchange/change_now/change_now_exchange.dart';
import 'package:stackwallet/services/exchange/exchange_data_loading_service.dart';
import 'package:stackwallet/services/exchange/majestic_bank/majestic_bank_exchange.dart';
import 'package:stackwallet/utilities/assets.dart';
import 'package:stackwallet/utilities/constants.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
@ -17,9 +19,12 @@ import 'package:stackwallet/widgets/background.dart';
import 'package:stackwallet/widgets/conditional_parent.dart';
import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
import 'package:stackwallet/widgets/custom_loading_overlay.dart';
import 'package:stackwallet/widgets/desktop/primary_button.dart';
import 'package:stackwallet/widgets/desktop/secondary_button.dart';
import 'package:stackwallet/widgets/icon_widgets/x_icon.dart';
import 'package:stackwallet/widgets/loading_indicator.dart';
import 'package:stackwallet/widgets/rounded_white_container.dart';
import 'package:stackwallet/widgets/stack_dialog.dart';
import 'package:stackwallet/widgets/stack_text_field.dart';
import 'package:stackwallet/widgets/textfield_icon_button.dart';
@ -49,7 +54,6 @@ class _ExchangeCurrencySelectionViewState
final isDesktop = Util.isDesktop;
List<Currency> _currencies = [];
List<Pair> pairs = [];
bool _loaded = false;
String _searchString = "";
@ -90,64 +94,45 @@ class _ExchangeCurrencySelectionViewState
if (widget.pairedTicker == null) {
return await _getCurrencies();
}
List<Currency> currencies = await ExchangeDataLoadingService
.instance.isar.currencies
.where()
.exchangeNameEqualTo(MajesticBankExchange.exchangeName)
.findAll();
final pairs = await _loadAvailablePairs();
List<Currency> currencies = [];
for (final pair in pairs) {
final currency =
await _getCurrency(widget.willChangeIsSend ? pair.from : pair.to);
if (currency != null) {
currencies.add(currency);
}
final cn = await ChangeNowExchange.instance.getPairedCurrencies(
widget.pairedTicker!,
widget.isFixedRate,
);
if (cn.value == null) {
await showDialog<void>(
context: context,
builder: (context) => StackDialog(
title: "ChangeNOW Error",
message: "Failed to load currency data: ${cn.exception}",
leftButton: SecondaryButton(
label: "Ok",
onPressed: Navigator.of(context, rootNavigator: isDesktop).pop,
),
rightButton: PrimaryButton(
label: "Retry",
onPressed: () async {
Navigator.of(context, rootNavigator: isDesktop).pop();
_currencies =
await _showUpdatingCurrencies(whileFuture: _loadCurrencies());
setState(() {});
},
),
),
);
} else {
currencies.addAll(cn.value!);
}
return currencies;
}
Future<Currency?> _getCurrency(String ticker) {
return ExchangeDataLoadingService.instance.isar.currencies
.where()
.filter()
.isFiatEqualTo(false)
.and()
.tickerEqualTo(ticker, caseSensitive: false)
.group((q) => widget.isFixedRate
? q
.rateTypeEqualTo(SupportedRateType.both)
.or()
.rateTypeEqualTo(SupportedRateType.fixed)
: q
.rateTypeEqualTo(SupportedRateType.both)
.or()
.rateTypeEqualTo(SupportedRateType.estimated))
.findFirst();
}
Future<List<Pair>> _loadAvailablePairs() {
final query = ExchangeDataLoadingService.instance.isar.pairs
.where()
.filter()
.group((q) => widget.isFixedRate
? q
.rateTypeEqualTo(SupportedRateType.both)
.or()
.rateTypeEqualTo(SupportedRateType.fixed)
: q
.rateTypeEqualTo(SupportedRateType.both)
.or()
.rateTypeEqualTo(SupportedRateType.estimated))
.and()
.group((q) => widget.willChangeIsSend
? q.toEqualTo(widget.pairedTicker!, caseSensitive: false)
: q.fromEqualTo(widget.pairedTicker!, caseSensitive: false));
if (widget.willChangeIsSend) {
return query.sortByFrom().findAll();
} else {
return query.sortByTo().findAll();
}
}
Future<List<Currency>> _getCurrencies() async {
return ExchangeDataLoadingService.instance.isar.currencies
.where()

View file

@ -32,7 +32,6 @@ 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/desktop/simple_desktop_dialog.dart';
import 'package:stackwallet/widgets/rounded_container.dart';
import 'package:stackwallet/widgets/rounded_white_container.dart';
import 'package:stackwallet/widgets/stack_dialog.dart';
@ -386,50 +385,10 @@ class _ExchangeFormState extends ConsumerState<ExchangeForm> {
final sendAmount = ref.read(exchangeFormStateProvider).sendAmount!;
final estimate = ref.read(exchangeFormStateProvider).estimate!;
final exchangeName = ref.read(exchangeFormStateProvider).exchange.name;
String rate;
switch (rateType) {
case ExchangeRateType.estimated:
final pair = await ExchangeDataLoadingService.instance.isar.pairs
.where()
.exchangeNameEqualTo(exchangeName)
.filter()
.group((q) => q
.rateTypeEqualTo(SupportedRateType.estimated)
.or()
.rateTypeEqualTo(SupportedRateType.both))
.and()
.fromEqualTo(fromTicker, caseSensitive: false)
.and()
.toEqualTo(toTicker, caseSensitive: false)
.findFirst();
if (pair == null) {
unawaited(
showDialog<dynamic>(
context: context,
barrierDismissible: true,
builder: (_) {
if (isDesktop) {
return SimpleDesktopDialog(
title: "Selected trade pair unavailable",
message:
"The $fromTicker - $toTicker market is currently disabled for estimated/floating rate trades",
);
} else {
return StackDialog(
title: "Selected trade pair unavailable",
message:
"The $fromTicker - $toTicker market is currently disabled for estimated/floating rate trades",
);
}
},
),
);
return;
}
rate =
"1 ${fromTicker.toUpperCase()} ~${(estimate.estimatedAmount / sendAmount).toDecimal(scaleOnInfinitePrecision: 8).toStringAsFixed(8)} ${toTicker.toUpperCase()}";
break;

View file

@ -88,6 +88,17 @@ class ChangeNowExchange extends Exchange {
);
}
@override
Future<ExchangeResponse<List<Currency>>> getPairedCurrencies(
String forCurrency,
bool fixedRate,
) async {
return await ChangeNowAPI.instance.getPairedCurrencies(
ticker: forCurrency,
fixedRate: fixedRate,
);
}
@override
Future<ExchangeResponse<List<Pair>>> getAllPairs(bool fixedRate) async {
if (fixedRate) {

View file

@ -29,6 +29,11 @@ abstract class Exchange {
Future<ExchangeResponse<List<Currency>>> getAllCurrencies(bool fixedRate);
Future<ExchangeResponse<List<Currency>>> getPairedCurrencies(
String forCurrency,
bool fixedRate,
);
Future<ExchangeResponse<List<Pair>>> getPairsFor(
String currency,
bool fixedRate,

View file

@ -45,13 +45,13 @@ class ExchangeDataLoadingService {
_isar = await Isar.open(
[
CurrencySchema,
PairSchema,
// PairSchema,
],
directory: (await StackFileSystem.applicationIsarDirectory()).path,
// inspector: kDebugMode,
inspector: false,
name: "exchange_cache",
maxSizeMiB: 256,
maxSizeMiB: 64,
);
}
@ -122,8 +122,9 @@ class ExchangeDataLoadingService {
loadMajesticBankCurrencies(),
]);
await _loadChangeNowFixedRatePairs();
await _loadChangeNowEstimatedRatePairs();
// quicker to load available currencies on the fly for a specific base currency
// await _loadChangeNowFixedRatePairs();
// await _loadChangeNowEstimatedRatePairs();
Logging.instance.log(
"ExchangeDataLoadingService.loadAll finished in ${DateTime.now().difference(start).inSeconds} seconds",
@ -163,55 +164,55 @@ class ExchangeDataLoadingService {
}
}
Future<void> _loadChangeNowFixedRatePairs() async {
final exchange = ChangeNowExchange.instance;
// Future<void> _loadChangeNowFixedRatePairs() async {
// final exchange = ChangeNowExchange.instance;
//
// final responsePairs = await compute(exchange.getAllPairs, true);
//
// if (responsePairs.value != null) {
// await isar.writeTxn(() async {
// final idsToDelete2 = await isar.pairs
// .where()
// .exchangeNameEqualTo(ChangeNowExchange.exchangeName)
// .filter()
// .rateTypeEqualTo(SupportedRateType.fixed)
// .idProperty()
// .findAll();
// await isar.pairs.deleteAll(idsToDelete2);
// await isar.pairs.putAll(responsePairs.value!);
// });
// } else {
// Logging.instance.log(
// "Failed to load changeNOW available fixed rate pairs: ${responsePairs.exception?.message}",
// level: LogLevel.Error);
// return;
// }
// }
final responsePairs = await compute(exchange.getAllPairs, true);
if (responsePairs.value != null) {
await isar.writeTxn(() async {
final idsToDelete2 = await isar.pairs
.where()
.exchangeNameEqualTo(ChangeNowExchange.exchangeName)
.filter()
.rateTypeEqualTo(SupportedRateType.fixed)
.idProperty()
.findAll();
await isar.pairs.deleteAll(idsToDelete2);
await isar.pairs.putAll(responsePairs.value!);
});
} else {
Logging.instance.log(
"Failed to load changeNOW available fixed rate pairs: ${responsePairs.exception?.message}",
level: LogLevel.Error);
return;
}
}
Future<void> _loadChangeNowEstimatedRatePairs() async {
final exchange = ChangeNowExchange.instance;
final responsePairs = await compute(exchange.getAllPairs, false);
if (responsePairs.value != null) {
await isar.writeTxn(() async {
final idsToDelete = await isar.pairs
.where()
.exchangeNameEqualTo(ChangeNowExchange.exchangeName)
.filter()
.rateTypeEqualTo(SupportedRateType.estimated)
.idProperty()
.findAll();
await isar.pairs.deleteAll(idsToDelete);
await isar.pairs.putAll(responsePairs.value!);
});
} else {
Logging.instance.log(
"Failed to load changeNOW available floating rate pairs: ${responsePairs.exception?.message}",
level: LogLevel.Error);
return;
}
}
// Future<void> _loadChangeNowEstimatedRatePairs() async {
// final exchange = ChangeNowExchange.instance;
//
// final responsePairs = await compute(exchange.getAllPairs, false);
//
// if (responsePairs.value != null) {
// await isar.writeTxn(() async {
// final idsToDelete = await isar.pairs
// .where()
// .exchangeNameEqualTo(ChangeNowExchange.exchangeName)
// .filter()
// .rateTypeEqualTo(SupportedRateType.estimated)
// .idProperty()
// .findAll();
// await isar.pairs.deleteAll(idsToDelete);
// await isar.pairs.putAll(responsePairs.value!);
// });
// } else {
// Logging.instance.log(
// "Failed to load changeNOW available floating rate pairs: ${responsePairs.exception?.message}",
// level: LogLevel.Error);
// return;
// }
// }
//
// Future<void> loadSimpleswapFloatingRateCurrencies(WidgetRef ref) async {
// final exchange = SimpleSwapExchange();
@ -276,31 +277,15 @@ class ExchangeDataLoadingService {
final responseCurrencies = await exchange.getAllCurrencies(false);
if (responseCurrencies.value != null) {
final responsePairs = await exchange.getAllPairs(false);
if (responsePairs.value != null) {
await isar.writeTxn(() async {
final idsToDelete = await isar.currencies
.where()
.exchangeNameEqualTo(MajesticBankExchange.exchangeName)
.idProperty()
.findAll();
await isar.currencies.deleteAll(idsToDelete);
await isar.currencies.putAll(responseCurrencies.value!);
final idsToDelete2 = await isar.pairs
.where()
.exchangeNameEqualTo(MajesticBankExchange.exchangeName)
.idProperty()
.findAll();
await isar.pairs.deleteAll(idsToDelete2);
await isar.pairs.putAll(responsePairs.value!);
});
} else {
Logging.instance.log(
"loadMajesticBankCurrencies: $responsePairs",
level: LogLevel.Warning,
);
}
await isar.writeTxn(() async {
final idsToDelete = await isar.currencies
.where()
.exchangeNameEqualTo(MajesticBankExchange.exchangeName)
.idProperty()
.findAll();
await isar.currencies.deleteAll(idsToDelete);
await isar.currencies.putAll(responseCurrencies.value!);
});
} else {
Logging.instance.log(
"loadMajesticBankCurrencies: $responseCurrencies",
@ -308,4 +293,26 @@ class ExchangeDataLoadingService {
);
}
}
// Future<void> loadMajesticBankPairs() async {
// final exchange = MajesticBankExchange.instance;
//
// final responsePairs = await exchange.getAllPairs(false);
// if (responsePairs.value != null) {
// await isar.writeTxn(() async {
// final idsToDelete2 = await isar.pairs
// .where()
// .exchangeNameEqualTo(MajesticBankExchange.exchangeName)
// .idProperty()
// .findAll();
// await isar.pairs.deleteAll(idsToDelete2);
// await isar.pairs.putAll(responsePairs.value!);
// });
// } else {
// Logging.instance.log(
// "loadMajesticBankCurrencies: $responsePairs",
// level: LogLevel.Warning,
// );
// }
// }
}

View file

@ -124,6 +124,13 @@ class MajesticBankExchange extends Exchange {
return ExchangeResponse(value: currencies);
}
@override
Future<ExchangeResponse<List<Currency>>> getPairedCurrencies(
String forCurrency, bool fixedRate) {
// TODO: change this if the api changes to allow getting by paired currency
return getAllCurrencies(fixedRate);
}
@override
Future<ExchangeResponse<List<Pair>>> getAllPairs(bool fixedRate) async {
final response = await MajesticBankAPI.instance.getRates();

View file

@ -156,4 +156,11 @@ class SimpleSwapExchange extends Exchange {
// TODO: implement getTrades
throw UnimplementedError();
}
@override
Future<ExchangeResponse<List<Currency>>> getPairedCurrencies(
String forCurrency, bool fixedRate) {
// TODO: implement getPairedCurrencies
throw UnimplementedError();
}
}