mirror of
https://github.com/cypherstack/stack_wallet.git
synced 2025-01-24 19:25:52 +00:00
aggregate currency
This commit is contained in:
parent
a14cca58ee
commit
b1c8a56ba6
5 changed files with 148 additions and 133 deletions
26
lib/models/exchange/aggregate_currency.dart
Normal file
26
lib/models/exchange/aggregate_currency.dart
Normal 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;
|
||||
}
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
// }
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
Loading…
Reference in a new issue