aggregate currency

This commit is contained in:
julian 2023-02-08 13:06:26 -06:00
parent a14cca58ee
commit b1c8a56ba6
5 changed files with 148 additions and 133 deletions

View file

@ -0,0 +1,26 @@
import 'package:stackwallet/models/isar/exchange_cache/currency.dart';
import 'package:stackwallet/models/isar/exchange_cache/pair.dart';
import 'package:tuple/tuple.dart';
class AggregateCurrency {
final Map<String, Currency?> _map = {};
AggregateCurrency(
{required List<Tuple2<String, Currency>> exchangeCurrencyPairs}) {
assert(exchangeCurrencyPairs.isNotEmpty);
for (final item in exchangeCurrencyPairs) {
_map[item.item1] = item.item2;
}
}
Currency? forExchange(String exchangeName) {
return _map[exchangeName];
}
String get ticker => _map.values.first!.ticker;
String get name => _map.values.first!.name;
String get image => _map.values.first!.image;
SupportedRateType get rateType => _map.values.first!.rateType;
bool get isStackCoin => _map.values.first!.isStackCoin;
}

View file

@ -1,12 +1,9 @@
import 'package:decimal/decimal.dart';
import 'package:flutter/foundation.dart';
import 'package:isar/isar.dart';
import 'package:stackwallet/models/exchange/aggregate_currency.dart';
import 'package:stackwallet/models/exchange/response_objects/estimate.dart';
import 'package:stackwallet/models/isar/exchange_cache/currency.dart';
import 'package:stackwallet/models/isar/exchange_cache/pair.dart';
import 'package:stackwallet/pages/exchange_view/sub_widgets/exchange_rate_sheet.dart';
import 'package:stackwallet/services/exchange/exchange.dart';
import 'package:stackwallet/services/exchange/exchange_data_loading_service.dart';
import 'package:stackwallet/utilities/logger.dart';
class ExchangeFormState extends ChangeNotifier {
@ -51,15 +48,15 @@ class ExchangeFormState extends ChangeNotifier {
//
}
Currency? _sendCurrency;
Currency? get sendCurrency => _sendCurrency;
AggregateCurrency? _sendCurrency;
AggregateCurrency? get sendCurrency => _sendCurrency;
// set sendCurrency(Currency? sendCurrency) {
// _sendCurrency = sendCurrency;
// //
// }
Currency? _receiveCurrency;
Currency? get receiveCurrency => _receiveCurrency;
AggregateCurrency? _receiveCurrency;
AggregateCurrency? get receiveCurrency => _receiveCurrency;
// set receiveCurrency(Currency? receiveCurrency) {
// _receiveCurrency = receiveCurrency;
// //
@ -111,8 +108,8 @@ class ExchangeFormState extends ChangeNotifier {
receiveAmount != null &&
rate != null &&
rate! >= Decimal.zero &&
exchange.name == sendCurrency!.exchangeName &&
exchange.name == receiveCurrency!.exchangeName &&
sendCurrency!.forExchange(exchange.name) != null &&
receiveCurrency!.forExchange(exchange.name) != null &&
warning.isEmpty;
}
@ -154,46 +151,6 @@ class ExchangeFormState extends ChangeNotifier {
}) async {
_exchange = exchange;
if (shouldUpdateData) {
if (_sendCurrency != null) {
_sendCurrency = await ExchangeDataLoadingService
.instance.isar.currencies
.where()
.exchangeNameEqualTo(exchange.name)
.filter()
.tickerEqualTo(_sendCurrency!.ticker)
.and()
.group((q) => exchangeRateType == ExchangeRateType.fixed
? q
.rateTypeEqualTo(SupportedRateType.both)
.or()
.rateTypeEqualTo(SupportedRateType.fixed)
: q
.rateTypeEqualTo(SupportedRateType.both)
.or()
.rateTypeEqualTo(SupportedRateType.estimated))
.findFirst();
}
if (_receiveCurrency != null) {
_receiveCurrency = await ExchangeDataLoadingService
.instance.isar.currencies
.where()
.exchangeNameEqualTo(exchange.name)
.filter()
.tickerEqualTo(_receiveCurrency!.ticker)
.and()
.group((q) => exchangeRateType == ExchangeRateType.fixed
? q
.rateTypeEqualTo(SupportedRateType.both)
.or()
.rateTypeEqualTo(SupportedRateType.fixed)
: q
.rateTypeEqualTo(SupportedRateType.both)
.or()
.rateTypeEqualTo(SupportedRateType.estimated))
.findFirst();
}
await _updateRangesAndEstimate(
shouldNotifyListeners: false,
);
@ -204,7 +161,7 @@ class ExchangeFormState extends ChangeNotifier {
}
}
void setCurrencies(Currency from, Currency to) {
void setCurrencies(AggregateCurrency from, AggregateCurrency to) {
_sendCurrency = from;
_receiveCurrency = to;
}
@ -282,7 +239,7 @@ class ExchangeFormState extends ChangeNotifier {
}
Future<void> updateSendCurrency(
Currency sendCurrency,
AggregateCurrency sendCurrency,
bool shouldNotifyListeners,
) async {
try {
@ -306,7 +263,7 @@ class ExchangeFormState extends ChangeNotifier {
}
Future<void> updateReceivingCurrency(
Currency receiveCurrency,
AggregateCurrency receiveCurrency,
bool shouldNotifyListeners,
) async {
try {
@ -341,7 +298,7 @@ class ExchangeFormState extends ChangeNotifier {
_minReceiveAmount = null;
_maxReceiveAmount = null;
final Currency? tmp = sendCurrency;
final AggregateCurrency? tmp = sendCurrency;
_sendCurrency = receiveCurrency;
_receiveCurrency = tmp;

View file

@ -26,14 +26,14 @@ import 'package:stackwallet/widgets/textfield_icon_button.dart';
class ExchangeCurrencySelectionView extends StatefulWidget {
const ExchangeCurrencySelectionView({
Key? key,
required this.willChange,
required this.paired,
required this.willChangeTicker,
required this.pairedTicker,
required this.isFixedRate,
required this.willChangeIsSend,
}) : super(key: key);
final Currency? willChange;
final Currency? paired;
final String? willChangeTicker;
final String? pairedTicker;
final bool isFixedRate;
final bool willChangeIsSend;
@ -87,7 +87,7 @@ class _ExchangeCurrencySelectionViewState
}
Future<List<Currency>> _loadCurrencies() async {
if (widget.paired == null) {
if (widget.pairedTicker == null) {
return await _getCurrencies();
}
@ -136,8 +136,8 @@ class _ExchangeCurrencySelectionViewState
.rateTypeEqualTo(SupportedRateType.estimated))
.and()
.group((q) => widget.willChangeIsSend
? q.toEqualTo(widget.paired!.ticker, caseSensitive: false)
: q.fromEqualTo(widget.paired!.ticker, caseSensitive: false));
? q.toEqualTo(widget.pairedTicker!, caseSensitive: false)
: q.fromEqualTo(widget.pairedTicker!, caseSensitive: false));
if (widget.willChangeIsSend) {
return query.sortByFrom().findAll();
@ -170,7 +170,7 @@ class _ExchangeCurrencySelectionViewState
return _currencies;
}
if (widget.paired == null) {
if (widget.pairedTicker == null) {
return _currencies
.where((e) =>
e.name.toLowerCase().contains(text.toLowerCase()) ||
@ -179,7 +179,7 @@ class _ExchangeCurrencySelectionViewState
} else {
return _currencies
.where((e) =>
e.ticker.toLowerCase() != widget.paired!.ticker.toLowerCase() &&
e.ticker.toLowerCase() != widget.pairedTicker!.toLowerCase() &&
(e.name.toLowerCase().contains(text.toLowerCase()) ||
e.ticker.toLowerCase().contains(text.toLowerCase())))
.toList(growable: false);
@ -318,8 +318,7 @@ class _ExchangeCurrencySelectionViewState
Flexible(
child: Builder(builder: (context) {
final coins = Coin.values.where((e) =>
e.ticker.toLowerCase() !=
widget.paired?.ticker.toLowerCase());
e.ticker.toLowerCase() != widget.pairedTicker?.toLowerCase());
final items = filter(_searchString)
.where((e) => coins

View file

@ -6,6 +6,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:flutter_svg/svg.dart';
import 'package:isar/isar.dart';
import 'package:stackwallet/models/exchange/aggregate_currency.dart';
import 'package:stackwallet/models/exchange/incomplete_exchange.dart';
import 'package:stackwallet/models/isar/exchange_cache/currency.dart';
import 'package:stackwallet/models/isar/exchange_cache/pair.dart';
@ -128,6 +129,35 @@ class _ExchangeFormState extends ConsumerState<ExchangeForm> {
});
}
Future<AggregateCurrency> _getAggregateCurrency(Currency currency) async {
final rateType = ref.read(prefsChangeNotifierProvider).exchangeRateType;
final currencies = await ExchangeDataLoadingService.instance.isar.currencies
.filter()
.group((q) => rateType == ExchangeRateType.fixed
? q
.rateTypeEqualTo(SupportedRateType.both)
.or()
.rateTypeEqualTo(SupportedRateType.fixed)
: q
.rateTypeEqualTo(SupportedRateType.both)
.or()
.rateTypeEqualTo(SupportedRateType.estimated))
.and()
.tickerEqualTo(
currency.ticker,
caseSensitive: false,
)
.findAll();
final items = [Tuple2(currency.exchangeName, currency)];
for (final currency in currencies) {
items.add(Tuple2(currency.exchangeName, currency));
}
return AggregateCurrency(exchangeCurrencyPairs: items);
}
void selectSendCurrency() async {
final type = (ref.read(prefsChangeNotifierProvider).exchangeRateType);
final fromTicker = ref.read(exchangeFormStateProvider).fromTicker ?? "";
@ -139,17 +169,18 @@ class _ExchangeFormState extends ConsumerState<ExchangeForm> {
}
final selectedCurrency = await _showCurrencySelectionSheet(
willChange: ref.read(exchangeFormStateProvider).sendCurrency,
willChange: ref.read(exchangeFormStateProvider).sendCurrency?.ticker,
willChangeIsSend: true,
paired: ref.read(exchangeFormStateProvider).receiveCurrency,
paired: ref.read(exchangeFormStateProvider).receiveCurrency?.ticker,
isFixedRate: type == ExchangeRateType.fixed,
);
if (selectedCurrency != null) {
await showUpdatingExchangeRate(
whileFuture: ref
.read(exchangeFormStateProvider)
.updateSendCurrency(selectedCurrency, true),
whileFuture: _getAggregateCurrency(selectedCurrency).then(
(aggregateSelected) => ref
.read(exchangeFormStateProvider)
.updateSendCurrency(aggregateSelected, true)),
);
}
}
@ -163,18 +194,19 @@ class _ExchangeFormState extends ConsumerState<ExchangeForm> {
}
final selectedCurrency = await _showCurrencySelectionSheet(
willChange: ref.read(exchangeFormStateProvider).receiveCurrency,
willChange: ref.read(exchangeFormStateProvider).receiveCurrency?.ticker,
willChangeIsSend: false,
paired: ref.read(exchangeFormStateProvider).sendCurrency,
paired: ref.read(exchangeFormStateProvider).sendCurrency?.ticker,
isFixedRate: ref.read(prefsChangeNotifierProvider).exchangeRateType ==
ExchangeRateType.fixed,
);
if (selectedCurrency != null) {
await showUpdatingExchangeRate(
whileFuture: ref
.read(exchangeFormStateProvider)
.updateReceivingCurrency(selectedCurrency, true),
whileFuture: _getAggregateCurrency(selectedCurrency).then(
(aggregateSelected) => ref
.read(exchangeFormStateProvider)
.updateReceivingCurrency(aggregateSelected, true)),
);
}
}
@ -193,8 +225,8 @@ class _ExchangeFormState extends ConsumerState<ExchangeForm> {
}
Future<Currency?> _showCurrencySelectionSheet({
required Currency? willChange,
required Currency? paired,
required String? willChange,
required String? paired,
required bool isFixedRate,
required bool willChangeIsSend,
}) async {
@ -241,8 +273,8 @@ class _ExchangeFormState extends ConsumerState<ExchangeForm> {
.extension<StackColors>()!
.background,
child: ExchangeCurrencySelectionView(
willChange: willChange,
paired: paired,
willChangeTicker: willChange,
pairedTicker: paired,
isFixedRate: isFixedRate,
willChangeIsSend: willChangeIsSend,
),
@ -259,8 +291,8 @@ class _ExchangeFormState extends ConsumerState<ExchangeForm> {
: await Navigator.of(context).push(
MaterialPageRoute<dynamic>(
builder: (_) => ExchangeCurrencySelectionView(
willChange: willChange,
paired: paired,
willChangeTicker: willChange,
pairedTicker: paired,
isFixedRate: isFixedRate,
willChangeIsSend: willChangeIsSend,
),
@ -292,57 +324,58 @@ class _ExchangeFormState extends ConsumerState<ExchangeForm> {
ref.read(exchangeFormStateProvider).reversed = false;
if (!(toTicker == "-" || fromTicker == "-")) {
final available = await ExchangeDataLoadingService.instance.isar.pairs
.where()
.exchangeNameEqualTo(
ref.read(currentExchangeNameStateProvider.state).state)
.filter()
.fromEqualTo(fromTicker)
.and()
.toEqualTo(toTicker)
.findAll();
// final available = await ExchangeDataLoadingService.instance.isar.pairs
// .where()
// .exchangeNameEqualTo(
// ref.read(currentExchangeNameStateProvider.state).state)
// .filter()
// .fromEqualTo(fromTicker)
// .and()
// .toEqualTo(toTicker)
// .findAll();
await ref.read(exchangeFormStateProvider).refresh();
if (available.isNotEmpty) {
final availableCurrencies = await ExchangeDataLoadingService
.instance.isar.currencies
.where()
.exchangeNameEqualTo(
ref.read(currentExchangeNameStateProvider.state).state)
.filter()
.tickerEqualTo(fromTicker)
.or()
.tickerEqualTo(toTicker)
.findAll();
if (availableCurrencies.length > 1) {
final from =
availableCurrencies.firstWhere((e) => e.ticker == fromTicker);
final to =
availableCurrencies.firstWhere((e) => e.ticker == toTicker);
final newFromAmount = Decimal.tryParse(_sendController.text);
ref.read(exchangeFormStateProvider).receiveAmount = newFromAmount;
if (newFromAmount == null) {
_receiveController.text = "";
}
await ref
.read(exchangeFormStateProvider)
.updateReceivingCurrency(to, false);
await ref
.read(exchangeFormStateProvider)
.updateSendCurrency(from, true);
_receiveController.text =
ref.read(exchangeFormStateProvider).toAmountString.isEmpty
? "-"
: ref.read(exchangeFormStateProvider).toAmountString;
if (mounted) {
Navigator.of(context, rootNavigator: isDesktop).pop();
}
return;
}
}
// if (available.isNotEmpty) {
// final availableCurrencies = await ExchangeDataLoadingService
// .instance.isar.currencies
// .where()
// .exchangeNameEqualTo(
// ref.read(currentExchangeNameStateProvider.state).state)
// .filter()
// .tickerEqualTo(fromTicker)
// .or()
// .tickerEqualTo(toTicker)
// .findAll();
//
// if (availableCurrencies.length > 1) {
// final from =
// availableCurrencies.firstWhere((e) => e.ticker == fromTicker);
// final to =
// availableCurrencies.firstWhere((e) => e.ticker == toTicker);
//
// final newFromAmount = Decimal.tryParse(_sendController.text);
// ref.read(exchangeFormStateProvider).receiveAmount = newFromAmount;
// if (newFromAmount == null) {
// _receiveController.text = "";
// }
//
// await ref
// .read(exchangeFormStateProvider)
// .updateReceivingCurrency(to, false);
// await ref
// .read(exchangeFormStateProvider)
// .updateSendCurrency(from, true);
//
// _receiveController.text =
// ref.read(exchangeFormStateProvider).toAmountString.isEmpty
// ? "-"
// : ref.read(exchangeFormStateProvider).toAmountString;
// if (mounted) {
// Navigator.of(context, rootNavigator: isDesktop).pop();
// }
// return;
// }
// }
}
}

View file

@ -1,7 +1,7 @@
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_svg/svg.dart';
import 'package:stackwallet/models/isar/exchange_cache/currency.dart';
import 'package:stackwallet/models/exchange/aggregate_currency.dart';
import 'package:stackwallet/pages/buy_view/sub_widgets/crypto_selection_view.dart';
import 'package:stackwallet/utilities/assets.dart';
import 'package:stackwallet/utilities/text_styles.dart';
@ -42,7 +42,7 @@ class ExchangeTextField extends StatefulWidget {
final bool isWalletCoin;
final bool readOnly;
final Currency? currency;
final AggregateCurrency? currency;
@override
State<ExchangeTextField> createState() => _ExchangeTextFieldState();