mirror of
https://github.com/cypherstack/stack_wallet.git
synced 2024-11-17 01:37:54 +00:00
WIP exchange screen state refactor
This commit is contained in:
parent
3564426248
commit
3a97623e5b
19 changed files with 1169 additions and 942 deletions
|
@ -299,7 +299,8 @@ class _MaterialAppWithThemeState extends ConsumerState<MaterialAppWithTheme>
|
||||||
await ref.read(prefsChangeNotifierProvider).isExternalCallsSet()) {
|
await ref.read(prefsChangeNotifierProvider).isExternalCallsSet()) {
|
||||||
if (Constants.enableExchange) {
|
if (Constants.enableExchange) {
|
||||||
await ExchangeDataLoadingService.instance.setCurrenciesIfEmpty(
|
await ExchangeDataLoadingService.instance.setCurrenciesIfEmpty(
|
||||||
ref.read(exchangeFormStateProvider),
|
ref.read(efCurrencyPairProvider),
|
||||||
|
ref.read(efRateTypeProvider),
|
||||||
);
|
);
|
||||||
unawaited(ExchangeDataLoadingService.instance.loadAll());
|
unawaited(ExchangeDataLoadingService.instance.loadAll());
|
||||||
}
|
}
|
||||||
|
|
35
lib/models/exchange/active_pair.dart
Normal file
35
lib/models/exchange/active_pair.dart
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
|
import 'package:stackwallet/models/exchange/aggregate_currency.dart';
|
||||||
|
|
||||||
|
class ActivePair extends ChangeNotifier {
|
||||||
|
AggregateCurrency? _send;
|
||||||
|
AggregateCurrency? _receive;
|
||||||
|
|
||||||
|
AggregateCurrency? get send => _send;
|
||||||
|
AggregateCurrency? get receive => _receive;
|
||||||
|
|
||||||
|
void setSend(
|
||||||
|
AggregateCurrency? newSend, {
|
||||||
|
bool notifyListeners = false,
|
||||||
|
}) {
|
||||||
|
_send = newSend;
|
||||||
|
if (notifyListeners) {
|
||||||
|
this.notifyListeners();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void setReceive(
|
||||||
|
AggregateCurrency? newReceive, {
|
||||||
|
bool notifyListeners = false,
|
||||||
|
}) {
|
||||||
|
_receive = newReceive;
|
||||||
|
if (notifyListeners) {
|
||||||
|
this.notifyListeners();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return "ActivePair{ send: $send, receive: $receive }";
|
||||||
|
}
|
||||||
|
}
|
File diff suppressed because it is too large
Load diff
|
@ -9,6 +9,7 @@ import 'package:intl/intl.dart';
|
||||||
import 'package:isar/isar.dart';
|
import 'package:isar/isar.dart';
|
||||||
import 'package:stackwallet/models/exchange/aggregate_currency.dart';
|
import 'package:stackwallet/models/exchange/aggregate_currency.dart';
|
||||||
import 'package:stackwallet/models/exchange/incomplete_exchange.dart';
|
import 'package:stackwallet/models/exchange/incomplete_exchange.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/currency.dart';
|
||||||
import 'package:stackwallet/models/isar/exchange_cache/pair.dart';
|
import 'package:stackwallet/models/isar/exchange_cache/pair.dart';
|
||||||
import 'package:stackwallet/models/isar/models/ethereum/eth_contract.dart';
|
import 'package:stackwallet/models/isar/models/ethereum/eth_contract.dart';
|
||||||
|
@ -21,10 +22,13 @@ import 'package:stackwallet/pages_desktop_specific/desktop_exchange/exchange_ste
|
||||||
import 'package:stackwallet/providers/providers.dart';
|
import 'package:stackwallet/providers/providers.dart';
|
||||||
import 'package:stackwallet/services/exchange/change_now/change_now_exchange.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/exchange_data_loading_service.dart';
|
||||||
|
import 'package:stackwallet/services/exchange/majestic_bank/majestic_bank_exchange.dart';
|
||||||
|
import 'package:stackwallet/services/exchange/trocador/trocador_exchange.dart';
|
||||||
import 'package:stackwallet/utilities/assets.dart';
|
import 'package:stackwallet/utilities/assets.dart';
|
||||||
import 'package:stackwallet/utilities/constants.dart';
|
import 'package:stackwallet/utilities/constants.dart';
|
||||||
import 'package:stackwallet/utilities/enums/coin_enum.dart';
|
import 'package:stackwallet/utilities/enums/coin_enum.dart';
|
||||||
import 'package:stackwallet/utilities/enums/exchange_rate_type_enum.dart';
|
import 'package:stackwallet/utilities/enums/exchange_rate_type_enum.dart';
|
||||||
|
import 'package:stackwallet/utilities/logger.dart';
|
||||||
import 'package:stackwallet/utilities/text_styles.dart';
|
import 'package:stackwallet/utilities/text_styles.dart';
|
||||||
import 'package:stackwallet/utilities/theme/stack_colors.dart';
|
import 'package:stackwallet/utilities/theme/stack_colors.dart';
|
||||||
import 'package:stackwallet/utilities/util.dart';
|
import 'package:stackwallet/utilities/util.dart';
|
||||||
|
@ -61,6 +65,12 @@ class _ExchangeFormState extends ConsumerState<ExchangeForm> {
|
||||||
late final Coin? coin;
|
late final Coin? coin;
|
||||||
late final bool walletInitiated;
|
late final bool walletInitiated;
|
||||||
|
|
||||||
|
final exchanges = [
|
||||||
|
MajesticBankExchange.instance,
|
||||||
|
ChangeNowExchange.instance,
|
||||||
|
TrocadorExchange.instance,
|
||||||
|
];
|
||||||
|
|
||||||
late final TextEditingController _sendController;
|
late final TextEditingController _sendController;
|
||||||
late final TextEditingController _receiveController;
|
late final TextEditingController _receiveController;
|
||||||
final isDesktop = Util.isDesktop;
|
final isDesktop = Util.isDesktop;
|
||||||
|
@ -105,16 +115,17 @@ class _ExchangeFormState extends ConsumerState<ExchangeForm> {
|
||||||
}
|
}
|
||||||
|
|
||||||
Timer? _sendFieldOnChangedTimer;
|
Timer? _sendFieldOnChangedTimer;
|
||||||
void sendFieldOnChanged(String value) async {
|
void sendFieldOnChanged(String value) {
|
||||||
if (_sendFocusNode.hasFocus) {
|
if (_sendFocusNode.hasFocus) {
|
||||||
_sendFieldOnChangedTimer?.cancel();
|
_sendFieldOnChangedTimer?.cancel();
|
||||||
|
|
||||||
_sendFieldOnChangedTimer = Timer(_valueCheckInterval, () async {
|
_sendFieldOnChangedTimer = Timer(_valueCheckInterval, () async {
|
||||||
final newFromAmount = _localizedStringToNum(value);
|
final newFromAmount = _localizedStringToNum(value);
|
||||||
|
|
||||||
await ref
|
ref.read(efSendAmountProvider.notifier).state = newFromAmount;
|
||||||
.read(exchangeFormStateProvider)
|
if (!_swapLock && !ref.read(efReversedProvider)) {
|
||||||
.setSendAmountAndCalculateReceiveAmount(newFromAmount, true);
|
unawaited(update());
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -126,9 +137,10 @@ class _ExchangeFormState extends ConsumerState<ExchangeForm> {
|
||||||
_receiveFieldOnChangedTimer = Timer(_valueCheckInterval, () async {
|
_receiveFieldOnChangedTimer = Timer(_valueCheckInterval, () async {
|
||||||
final newToAmount = _localizedStringToNum(value);
|
final newToAmount = _localizedStringToNum(value);
|
||||||
|
|
||||||
await ref
|
ref.read(efReceiveAmountProvider.notifier).state = newToAmount;
|
||||||
.read(exchangeFormStateProvider)
|
if (!_swapLock && ref.read(efReversedProvider)) {
|
||||||
.setReceivingAmountAndCalculateSendAmount(newToAmount, true);
|
unawaited(update());
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -147,7 +159,7 @@ class _ExchangeFormState extends ConsumerState<ExchangeForm> {
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<AggregateCurrency> _getAggregateCurrency(Currency currency) async {
|
Future<AggregateCurrency> _getAggregateCurrency(Currency currency) async {
|
||||||
final rateType = ref.read(exchangeFormStateProvider).exchangeRateType;
|
final rateType = ref.read(efRateTypeProvider);
|
||||||
final currencies = await ExchangeDataLoadingService.instance.isar.currencies
|
final currencies = await ExchangeDataLoadingService.instance.isar.currencies
|
||||||
.filter()
|
.filter()
|
||||||
.group((q) => rateType == ExchangeRateType.fixed
|
.group((q) => rateType == ExchangeRateType.fixed
|
||||||
|
@ -178,8 +190,8 @@ class _ExchangeFormState extends ConsumerState<ExchangeForm> {
|
||||||
}
|
}
|
||||||
|
|
||||||
void selectSendCurrency() async {
|
void selectSendCurrency() async {
|
||||||
final type = (ref.read(exchangeFormStateProvider).exchangeRateType);
|
final type = ref.read(efRateTypeProvider);
|
||||||
final fromTicker = ref.read(exchangeFormStateProvider).fromTicker ?? "";
|
final fromTicker = ref.read(efCurrencyPairProvider).send?.ticker ?? "";
|
||||||
|
|
||||||
if (walletInitiated) {
|
if (walletInitiated) {
|
||||||
if (widget.contract != null &&
|
if (widget.contract != null &&
|
||||||
|
@ -194,24 +206,26 @@ class _ExchangeFormState extends ConsumerState<ExchangeForm> {
|
||||||
}
|
}
|
||||||
|
|
||||||
final selectedCurrency = await _showCurrencySelectionSheet(
|
final selectedCurrency = await _showCurrencySelectionSheet(
|
||||||
willChange: ref.read(exchangeFormStateProvider).sendCurrency?.ticker,
|
willChange: ref.read(efCurrencyPairProvider).send?.ticker,
|
||||||
willChangeIsSend: true,
|
willChangeIsSend: true,
|
||||||
paired: ref.read(exchangeFormStateProvider).receiveCurrency?.ticker,
|
paired: ref.read(efCurrencyPairProvider).receive?.ticker,
|
||||||
isFixedRate: type == ExchangeRateType.fixed,
|
isFixedRate: type == ExchangeRateType.fixed,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (selectedCurrency != null) {
|
if (selectedCurrency != null) {
|
||||||
await showUpdatingExchangeRate(
|
await showUpdatingExchangeRate(
|
||||||
whileFuture: _getAggregateCurrency(selectedCurrency).then(
|
whileFuture: _getAggregateCurrency(selectedCurrency).then(
|
||||||
(aggregateSelected) => ref
|
(aggregateSelected) => ref.read(efCurrencyPairProvider).setSend(
|
||||||
.read(exchangeFormStateProvider)
|
aggregateSelected,
|
||||||
.updateSendCurrency(aggregateSelected, true)),
|
notifyListeners: true,
|
||||||
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void selectReceiveCurrency() async {
|
void selectReceiveCurrency() async {
|
||||||
final toTicker = ref.read(exchangeFormStateProvider).toTicker ?? "";
|
final toTicker = ref.read(efCurrencyPairProvider).receive?.ticker ?? "";
|
||||||
if (walletInitiated &&
|
if (walletInitiated &&
|
||||||
toTicker.toLowerCase() == coin!.ticker.toLowerCase()) {
|
toTicker.toLowerCase() == coin!.ticker.toLowerCase()) {
|
||||||
// do not allow changing away from wallet coin
|
// do not allow changing away from wallet coin
|
||||||
|
@ -219,19 +233,20 @@ class _ExchangeFormState extends ConsumerState<ExchangeForm> {
|
||||||
}
|
}
|
||||||
|
|
||||||
final selectedCurrency = await _showCurrencySelectionSheet(
|
final selectedCurrency = await _showCurrencySelectionSheet(
|
||||||
willChange: ref.read(exchangeFormStateProvider).receiveCurrency?.ticker,
|
willChange: ref.read(efCurrencyPairProvider).receive?.ticker,
|
||||||
willChangeIsSend: false,
|
willChangeIsSend: false,
|
||||||
paired: ref.read(exchangeFormStateProvider).sendCurrency?.ticker,
|
paired: ref.read(efCurrencyPairProvider).send?.ticker,
|
||||||
isFixedRate: ref.read(exchangeFormStateProvider).exchangeRateType ==
|
isFixedRate: ref.read(efRateTypeProvider) == ExchangeRateType.fixed,
|
||||||
ExchangeRateType.fixed,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
if (selectedCurrency != null) {
|
if (selectedCurrency != null) {
|
||||||
await showUpdatingExchangeRate(
|
await showUpdatingExchangeRate(
|
||||||
whileFuture: _getAggregateCurrency(selectedCurrency).then(
|
whileFuture: _getAggregateCurrency(selectedCurrency).then(
|
||||||
(aggregateSelected) => ref
|
(aggregateSelected) => ref.read(efCurrencyPairProvider).setReceive(
|
||||||
.read(exchangeFormStateProvider)
|
aggregateSelected,
|
||||||
.updateReceivingCurrency(aggregateSelected, true)),
|
notifyListeners: true,
|
||||||
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -241,10 +256,25 @@ class _ExchangeFormState extends ConsumerState<ExchangeForm> {
|
||||||
_sendFocusNode.unfocus();
|
_sendFocusNode.unfocus();
|
||||||
_receiveFocusNode.unfocus();
|
_receiveFocusNode.unfocus();
|
||||||
|
|
||||||
await showUpdatingExchangeRate(
|
final temp = ref.read(efCurrencyPairProvider).send;
|
||||||
whileFuture:
|
ref.read(efCurrencyPairProvider).setSend(
|
||||||
ref.read(exchangeFormStateProvider).swap(shouldNotifyListeners: true),
|
ref.read(efCurrencyPairProvider).receive,
|
||||||
);
|
notifyListeners: true,
|
||||||
|
);
|
||||||
|
ref.read(efCurrencyPairProvider).setReceive(
|
||||||
|
temp,
|
||||||
|
notifyListeners: true,
|
||||||
|
);
|
||||||
|
|
||||||
|
// final reversed = ref.read(efReversedProvider);
|
||||||
|
|
||||||
|
final amount = ref.read(efSendAmountProvider);
|
||||||
|
ref.read(efSendAmountProvider.notifier).state =
|
||||||
|
ref.read(efReceiveAmountProvider);
|
||||||
|
|
||||||
|
ref.read(efReceiveAmountProvider.notifier).state = amount;
|
||||||
|
|
||||||
|
unawaited(update());
|
||||||
|
|
||||||
_swapLock = false;
|
_swapLock = false;
|
||||||
}
|
}
|
||||||
|
@ -331,89 +361,20 @@ class _ExchangeFormState extends ConsumerState<ExchangeForm> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void onRateTypeChanged(ExchangeRateType newType) async {
|
void onRateTypeChanged(ExchangeRateType newType) {
|
||||||
_receiveFocusNode.unfocus();
|
_receiveFocusNode.unfocus();
|
||||||
_sendFocusNode.unfocus();
|
_sendFocusNode.unfocus();
|
||||||
|
|
||||||
await showUpdatingExchangeRate(
|
ref.read(efRateTypeProvider.notifier).state = newType;
|
||||||
whileFuture: _onRateTypeChangedFuture(newType),
|
update();
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> _onRateTypeChangedFuture(ExchangeRateType newType) async {
|
|
||||||
ref.read(exchangeFormStateProvider).exchangeRateType = newType;
|
|
||||||
|
|
||||||
final fromTicker = ref.read(exchangeFormStateProvider).fromTicker ?? "-";
|
|
||||||
final toTicker = ref.read(exchangeFormStateProvider).toTicker ?? "-";
|
|
||||||
|
|
||||||
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();
|
|
||||||
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;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void onExchangePressed() async {
|
void onExchangePressed() async {
|
||||||
final rateType = ref.read(exchangeFormStateProvider).exchangeRateType;
|
final rateType = ref.read(efRateTypeProvider);
|
||||||
final fromTicker = ref.read(exchangeFormStateProvider).fromTicker ?? "";
|
final fromTicker = ref.read(efCurrencyPairProvider).send?.ticker ?? "";
|
||||||
final toTicker = ref.read(exchangeFormStateProvider).toTicker ?? "";
|
final toTicker = ref.read(efCurrencyPairProvider).receive?.ticker ?? "";
|
||||||
final sendAmount = ref.read(exchangeFormStateProvider).sendAmount!;
|
final estimate = ref.read(efEstimateProvider)!;
|
||||||
final estimate = ref.read(exchangeFormStateProvider).estimates.firstWhere(
|
final sendAmount = ref.read(efSendAmountProvider)!;
|
||||||
(e) =>
|
|
||||||
e.exchangeProvider ==
|
|
||||||
ref.read(exchangeFormStateProvider).providerName,
|
|
||||||
);
|
|
||||||
|
|
||||||
if (rateType == ExchangeRateType.fixed && toTicker.toUpperCase() == "WOW") {
|
if (rateType == ExchangeRateType.fixed && toTicker.toUpperCase() == "WOW") {
|
||||||
await showDialog<void>(
|
await showDialog<void>(
|
||||||
|
@ -430,10 +391,16 @@ class _ExchangeFormState extends ConsumerState<ExchangeForm> {
|
||||||
|
|
||||||
String rate;
|
String rate;
|
||||||
|
|
||||||
|
final amountToSend =
|
||||||
|
estimate.reversed ? estimate.estimatedAmount : sendAmount;
|
||||||
|
final amountToReceive = estimate.reversed
|
||||||
|
? ref.read(efReceiveAmountProvider)!
|
||||||
|
: estimate.estimatedAmount;
|
||||||
|
|
||||||
switch (rateType) {
|
switch (rateType) {
|
||||||
case ExchangeRateType.estimated:
|
case ExchangeRateType.estimated:
|
||||||
rate =
|
rate =
|
||||||
"1 ${fromTicker.toUpperCase()} ~${(estimate.estimatedAmount / sendAmount).toDecimal(scaleOnInfinitePrecision: 8).toStringAsFixed(8)} ${toTicker.toUpperCase()}";
|
"1 ${fromTicker.toUpperCase()} ~${(amountToReceive / sendAmount).toDecimal(scaleOnInfinitePrecision: 8).toStringAsFixed(8)} ${toTicker.toUpperCase()}";
|
||||||
break;
|
break;
|
||||||
case ExchangeRateType.fixed:
|
case ExchangeRateType.fixed:
|
||||||
bool? shouldCancel;
|
bool? shouldCancel;
|
||||||
|
@ -545,7 +512,9 @@ class _ExchangeFormState extends ConsumerState<ExchangeForm> {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
rate =
|
rate =
|
||||||
"1 ${fromTicker.toUpperCase()} ~${ref.read(exchangeFormStateProvider).rate!.toStringAsFixed(8)} ${toTicker.toUpperCase()}";
|
"1 ${fromTicker.toUpperCase()} ~${(amountToReceive / amountToSend).toDecimal(
|
||||||
|
scaleOnInfinitePrecision: 12,
|
||||||
|
).toStringAsFixed(8)} ${toTicker.toUpperCase()}";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -553,10 +522,8 @@ class _ExchangeFormState extends ConsumerState<ExchangeForm> {
|
||||||
sendTicker: fromTicker.toUpperCase(),
|
sendTicker: fromTicker.toUpperCase(),
|
||||||
receiveTicker: toTicker.toUpperCase(),
|
receiveTicker: toTicker.toUpperCase(),
|
||||||
rateInfo: rate,
|
rateInfo: rate,
|
||||||
sendAmount: estimate.reversed ? estimate.estimatedAmount : sendAmount,
|
sendAmount: amountToSend,
|
||||||
receiveAmount: estimate.reversed
|
receiveAmount: amountToReceive,
|
||||||
? ref.read(exchangeFormStateProvider).receiveAmount!
|
|
||||||
: estimate.estimatedAmount,
|
|
||||||
rateType: rateType,
|
rateType: rateType,
|
||||||
estimate: estimate,
|
estimate: estimate,
|
||||||
reversed: estimate.reversed,
|
reversed: estimate.reversed,
|
||||||
|
@ -626,8 +593,8 @@ class _ExchangeFormState extends ConsumerState<ExchangeForm> {
|
||||||
}
|
}
|
||||||
|
|
||||||
String? ticker = isSend
|
String? ticker = isSend
|
||||||
? ref.read(exchangeFormStateProvider).fromTicker
|
? ref.read(efCurrencyPairProvider).send?.ticker
|
||||||
: ref.read(exchangeFormStateProvider).toTicker;
|
: ref.read(efCurrencyPairProvider).receive?.ticker;
|
||||||
|
|
||||||
if (ticker == null) {
|
if (ticker == null) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -636,6 +603,85 @@ class _ExchangeFormState extends ConsumerState<ExchangeForm> {
|
||||||
return coin.ticker.toUpperCase() == ticker.toUpperCase();
|
return coin.ticker.toUpperCase() == ticker.toUpperCase();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> update() async {
|
||||||
|
ref.read(efRefreshingProvider.notifier).state = true;
|
||||||
|
for (final exchange in exchanges) {
|
||||||
|
ref.read(efEstimatesListProvider(exchange.name).notifier).state = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
final reversed = ref.read(efReversedProvider);
|
||||||
|
final amount = reversed
|
||||||
|
? ref.read(efReceiveAmountProvider)
|
||||||
|
: ref.read(efSendAmountProvider);
|
||||||
|
|
||||||
|
if (amount == null || amount <= Decimal.zero) {
|
||||||
|
ref.read(efRefreshingProvider.notifier).state = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final rateType = ref.read(efRateTypeProvider);
|
||||||
|
final pair = ref.read(efCurrencyPairProvider);
|
||||||
|
|
||||||
|
for (final exchange in exchanges) {
|
||||||
|
final sendCurrency = pair.send?.forExchange(exchange.name);
|
||||||
|
final receiveCurrency = pair.receive?.forExchange(exchange.name);
|
||||||
|
|
||||||
|
if (sendCurrency != null && receiveCurrency != null) {
|
||||||
|
final rangeResponse = await exchange.getRange(
|
||||||
|
reversed ? receiveCurrency.ticker : sendCurrency.ticker,
|
||||||
|
reversed ? sendCurrency.ticker : receiveCurrency.ticker,
|
||||||
|
rateType == ExchangeRateType.fixed,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (rangeResponse.value == null) {
|
||||||
|
Logging.instance.log(
|
||||||
|
"Tried to $runtimeType.update Range for:"
|
||||||
|
" $exchange where response: $rangeResponse",
|
||||||
|
level: LogLevel.Info,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
final estimateResponse = await exchange.getEstimates(
|
||||||
|
sendCurrency.ticker,
|
||||||
|
receiveCurrency.ticker,
|
||||||
|
amount,
|
||||||
|
rateType == ExchangeRateType.fixed,
|
||||||
|
reversed,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (estimateResponse.value == null) {
|
||||||
|
Logging.instance.log(
|
||||||
|
"Tried to $runtimeType._fetchEstimateAndRange Estimate for:"
|
||||||
|
" $exchange where response: $estimateResponse",
|
||||||
|
level: LogLevel.Info,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (estimateResponse.value != null && rangeResponse.value != null) {
|
||||||
|
ref.read(efEstimatesListProvider(exchange.name).notifier).state =
|
||||||
|
Tuple2(estimateResponse.value!, rangeResponse.value!);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
|
ref.read(efRefreshingProvider.notifier).state = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateSend(Estimate? estimate) {
|
||||||
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
|
ref.read(efSendAmountProvider.notifier).state = estimate?.estimatedAmount;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateReceive(Estimate? estimate) {
|
||||||
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
|
ref.read(efReceiveAmountProvider.notifier).state =
|
||||||
|
estimate?.estimatedAmount;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
_sendController = TextEditingController();
|
_sendController = TextEditingController();
|
||||||
|
@ -645,9 +691,32 @@ class _ExchangeFormState extends ConsumerState<ExchangeForm> {
|
||||||
coin = widget.coin;
|
coin = widget.coin;
|
||||||
walletInitiated = walletId != null && coin != null;
|
walletInitiated = walletId != null && coin != null;
|
||||||
|
|
||||||
|
_sendFocusNode.addListener(() {
|
||||||
|
if (_sendFocusNode.hasFocus) {
|
||||||
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
|
ref.read(efReversedProvider.notifier).state = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
_receiveFocusNode.addListener(() {
|
||||||
|
if (_receiveFocusNode.hasFocus) {
|
||||||
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
|
ref.read(efReversedProvider.notifier).state = true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
if (walletInitiated) {
|
if (walletInitiated) {
|
||||||
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
|
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
|
||||||
ref.read(exchangeFormStateProvider).reset(shouldNotifyListeners: true);
|
ref.read(efSendAmountProvider.notifier).state = null;
|
||||||
|
ref.read(efReceiveAmountProvider.notifier).state = null;
|
||||||
|
ref.read(efReversedProvider.notifier).state = false;
|
||||||
|
ref.read(efWarningProvider.notifier).state = "";
|
||||||
|
ref.read(efRefreshingProvider.notifier).state = false;
|
||||||
|
ref.read(efCurrencyPairProvider).setSend(null, notifyListeners: true);
|
||||||
|
ref
|
||||||
|
.read(efCurrencyPairProvider)
|
||||||
|
.setReceive(null, notifyListeners: true);
|
||||||
ExchangeDataLoadingService.instance
|
ExchangeDataLoadingService.instance
|
||||||
.getAggregateCurrency(
|
.getAggregateCurrency(
|
||||||
widget.contract == null ? coin!.ticker : widget.contract!.symbol,
|
widget.contract == null ? coin!.ticker : widget.contract!.symbol,
|
||||||
|
@ -656,17 +725,17 @@ class _ExchangeFormState extends ConsumerState<ExchangeForm> {
|
||||||
)
|
)
|
||||||
.then((value) {
|
.then((value) {
|
||||||
if (value != null) {
|
if (value != null) {
|
||||||
ref.read(exchangeFormStateProvider).updateSendCurrency(value, true);
|
ref.read(efCurrencyPairProvider).setSend(
|
||||||
|
value,
|
||||||
|
notifyListeners: true,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
_sendController.text =
|
|
||||||
ref.read(exchangeFormStateProvider).fromAmountString;
|
|
||||||
_receiveController.text =
|
|
||||||
ref.read(exchangeFormStateProvider).toAmountString;
|
|
||||||
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
|
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
|
||||||
ref.read(exchangeFormStateProvider).refresh();
|
_sendController.text = ref.read(efSendAmountStringProvider);
|
||||||
|
_receiveController.text = ref.read(efReceiveAmountStringProvider);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -684,37 +753,42 @@ class _ExchangeFormState extends ConsumerState<ExchangeForm> {
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
debugPrint("BUILD: $runtimeType");
|
debugPrint("BUILD: $runtimeType");
|
||||||
|
|
||||||
final rateType = ref.watch(
|
final rateType = ref.watch(efRateTypeProvider);
|
||||||
exchangeFormStateProvider.select((value) => value.exchangeRateType));
|
|
||||||
|
|
||||||
final isEstimated = rateType == ExchangeRateType.estimated;
|
final isEstimated = rateType == ExchangeRateType.estimated;
|
||||||
|
|
||||||
ref.listen(
|
ref.listen(efReceiveAmountStringProvider, (previous, String next) {
|
||||||
exchangeFormStateProvider.select((value) => value.toAmountString),
|
|
||||||
(previous, String next) {
|
|
||||||
if (!_receiveFocusNode.hasFocus) {
|
if (!_receiveFocusNode.hasFocus) {
|
||||||
_receiveController.text = isEstimated && next.isEmpty ? "-" : next;
|
_receiveController.text = isEstimated && next.isEmpty ? "-" : next;
|
||||||
if (_swapLock) {
|
// if (_swapLock) {
|
||||||
_sendController.text =
|
_sendController.text = ref.read(efSendAmountStringProvider);
|
||||||
ref.read(exchangeFormStateProvider).fromAmountString;
|
// }
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
ref.listen(
|
ref.listen(efSendAmountStringProvider, (previous, String next) {
|
||||||
exchangeFormStateProvider.select((value) => value.fromAmountString),
|
|
||||||
(previous, String next) {
|
|
||||||
if (!_sendFocusNode.hasFocus) {
|
if (!_sendFocusNode.hasFocus) {
|
||||||
_sendController.text = next;
|
_sendController.text = next;
|
||||||
if (_swapLock) {
|
// if (_swapLock) {
|
||||||
_receiveController.text = isEstimated
|
_receiveController.text =
|
||||||
? ref.read(exchangeFormStateProvider).toAmountString.isEmpty
|
isEstimated && ref.read(efReceiveAmountStringProvider).isEmpty
|
||||||
? "-"
|
? "-"
|
||||||
: ref.read(exchangeFormStateProvider).toAmountString
|
: ref.read(efReceiveAmountStringProvider);
|
||||||
: ref.read(exchangeFormStateProvider).toAmountString;
|
// }
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
ref.listen(efEstimateProvider.notifier, (previous, next) {
|
||||||
|
if (ref.read(efReversedProvider)) {
|
||||||
|
updateSend((next as StateController<Estimate?>).state);
|
||||||
|
} else {
|
||||||
|
updateReceive((next as StateController<Estimate?>).state);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
ref.listen(efCurrencyPairProvider, (previous, next) {
|
||||||
|
update();
|
||||||
|
});
|
||||||
|
|
||||||
return Column(
|
return Column(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
|
@ -729,8 +803,9 @@ class _ExchangeFormState extends ConsumerState<ExchangeForm> {
|
||||||
height: isDesktop ? 10 : 4,
|
height: isDesktop ? 10 : 4,
|
||||||
),
|
),
|
||||||
ExchangeTextField(
|
ExchangeTextField(
|
||||||
key: Key(
|
key: Key("exchangeTextFieldKeyFor_"
|
||||||
"exchangeTextFieldKeyFor_${Theme.of(context).extension<StackColors>()!.themeType.name}"),
|
"${Theme.of(context).extension<StackColors>()!.themeType.name}"
|
||||||
|
"${ref.watch(efCurrencyPairProvider.select((value) => value.send?.ticker))}"),
|
||||||
controller: _sendController,
|
controller: _sendController,
|
||||||
focusNode: _sendFocusNode,
|
focusNode: _sendFocusNode,
|
||||||
textStyle: STextStyles.smallMed14(context).copyWith(
|
textStyle: STextStyles.smallMed14(context).copyWith(
|
||||||
|
@ -749,8 +824,8 @@ class _ExchangeFormState extends ConsumerState<ExchangeForm> {
|
||||||
onChanged: sendFieldOnChanged,
|
onChanged: sendFieldOnChanged,
|
||||||
onButtonTap: selectSendCurrency,
|
onButtonTap: selectSendCurrency,
|
||||||
isWalletCoin: isWalletCoin(coin, true),
|
isWalletCoin: isWalletCoin(coin, true),
|
||||||
currency: ref.watch(
|
currency:
|
||||||
exchangeFormStateProvider.select((value) => value.sendCurrency)),
|
ref.watch(efCurrencyPairProvider.select((value) => value.send)),
|
||||||
),
|
),
|
||||||
SizedBox(
|
SizedBox(
|
||||||
height: isDesktop ? 10 : 4,
|
height: isDesktop ? 10 : 4,
|
||||||
|
@ -758,15 +833,10 @@ class _ExchangeFormState extends ConsumerState<ExchangeForm> {
|
||||||
SizedBox(
|
SizedBox(
|
||||||
height: isDesktop ? 10 : 4,
|
height: isDesktop ? 10 : 4,
|
||||||
),
|
),
|
||||||
if (ref
|
if (ref.watch(efWarningProvider).isNotEmpty &&
|
||||||
.watch(
|
!ref.watch(efReversedProvider))
|
||||||
exchangeFormStateProvider.select((value) => value.warning))
|
|
||||||
.isNotEmpty &&
|
|
||||||
!ref.watch(
|
|
||||||
exchangeFormStateProvider.select((value) => value.reversed)))
|
|
||||||
Text(
|
Text(
|
||||||
ref.watch(
|
ref.watch(efWarningProvider),
|
||||||
exchangeFormStateProvider.select((value) => value.warning)),
|
|
||||||
style: STextStyles.errorSmall(context),
|
style: STextStyles.errorSmall(context),
|
||||||
),
|
),
|
||||||
Row(
|
Row(
|
||||||
|
@ -830,8 +900,7 @@ class _ExchangeFormState extends ConsumerState<ExchangeForm> {
|
||||||
background:
|
background:
|
||||||
Theme.of(context).extension<StackColors>()!.textFieldDefaultBG,
|
Theme.of(context).extension<StackColors>()!.textFieldDefaultBG,
|
||||||
onTap: () {
|
onTap: () {
|
||||||
if (!(ref.read(exchangeFormStateProvider).exchangeRateType ==
|
if (!(ref.read(efRateTypeProvider) == ExchangeRateType.estimated) &&
|
||||||
ExchangeRateType.estimated) &&
|
|
||||||
_receiveController.text == "-") {
|
_receiveController.text == "-") {
|
||||||
_receiveController.text = "";
|
_receiveController.text = "";
|
||||||
}
|
}
|
||||||
|
@ -839,22 +908,16 @@ class _ExchangeFormState extends ConsumerState<ExchangeForm> {
|
||||||
onChanged: receiveFieldOnChanged,
|
onChanged: receiveFieldOnChanged,
|
||||||
onButtonTap: selectReceiveCurrency,
|
onButtonTap: selectReceiveCurrency,
|
||||||
isWalletCoin: isWalletCoin(coin, true),
|
isWalletCoin: isWalletCoin(coin, true),
|
||||||
currency: ref.watch(exchangeFormStateProvider
|
currency: ref
|
||||||
.select((value) => value.receiveCurrency)),
|
.watch(efCurrencyPairProvider.select((value) => value.receive)),
|
||||||
readOnly: (rateType) == ExchangeRateType.estimated &&
|
readOnly: (rateType) == ExchangeRateType.estimated &&
|
||||||
ref.watch(exchangeFormStateProvider
|
ref.watch(efExchangeProvider).name ==
|
||||||
.select((value) => value.exchange.name)) ==
|
|
||||||
ChangeNowExchange.exchangeName,
|
ChangeNowExchange.exchangeName,
|
||||||
),
|
),
|
||||||
if (ref
|
if (ref.watch(efWarningProvider).isNotEmpty &&
|
||||||
.watch(
|
ref.watch(efReversedProvider))
|
||||||
exchangeFormStateProvider.select((value) => value.warning))
|
|
||||||
.isNotEmpty &&
|
|
||||||
ref.watch(
|
|
||||||
exchangeFormStateProvider.select((value) => value.reversed)))
|
|
||||||
Text(
|
Text(
|
||||||
ref.watch(
|
ref.watch(efWarningProvider),
|
||||||
exchangeFormStateProvider.select((value) => value.warning)),
|
|
||||||
style: STextStyles.errorSmall(context),
|
style: STextStyles.errorSmall(context),
|
||||||
),
|
),
|
||||||
SizedBox(
|
SizedBox(
|
||||||
|
@ -867,27 +930,28 @@ class _ExchangeFormState extends ConsumerState<ExchangeForm> {
|
||||||
onChanged: onRateTypeChanged,
|
onChanged: onRateTypeChanged,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
// these reads should be watch
|
// AnimatedSize(
|
||||||
if (ref.watch(exchangeFormStateProvider).sendAmount != null &&
|
// duration: const Duration(milliseconds: 250),
|
||||||
ref.watch(exchangeFormStateProvider).sendAmount != Decimal.zero)
|
// curve: Curves.easeInOutCirc,
|
||||||
SizedBox(
|
// child: ref.watch(efSendAmountProvider).sendAmount != null &&
|
||||||
height: isDesktop ? 20 : 12,
|
// ref.watch(exchangeFormStateProvider).sendAmount != Decimal.zero
|
||||||
),
|
// ?
|
||||||
// these reads should be watch
|
Padding(
|
||||||
if (ref.watch(exchangeFormStateProvider).sendAmount != null &&
|
padding: EdgeInsets.only(top: isDesktop ? 20 : 12),
|
||||||
ref.watch(exchangeFormStateProvider).sendAmount != Decimal.zero)
|
child: ExchangeProviderOptions(
|
||||||
ExchangeProviderOptions(
|
|
||||||
fixedRate: rateType == ExchangeRateType.fixed,
|
fixedRate: rateType == ExchangeRateType.fixed,
|
||||||
reversed: ref.watch(
|
reversed: ref.watch(efReversedProvider),
|
||||||
exchangeFormStateProvider.select((value) => value.reversed)),
|
|
||||||
),
|
),
|
||||||
|
// : const SizedBox(
|
||||||
|
// height: 0,
|
||||||
|
// ),
|
||||||
|
),
|
||||||
SizedBox(
|
SizedBox(
|
||||||
height: isDesktop ? 20 : 12,
|
height: isDesktop ? 20 : 12,
|
||||||
),
|
),
|
||||||
PrimaryButton(
|
PrimaryButton(
|
||||||
buttonHeight: isDesktop ? ButtonHeight.l : null,
|
buttonHeight: isDesktop ? ButtonHeight.l : null,
|
||||||
enabled: ref.watch(
|
enabled: ref.watch(efCanExchangeProvider),
|
||||||
exchangeFormStateProvider.select((value) => value.canExchange)),
|
|
||||||
onPressed: onExchangePressed,
|
onPressed: onExchangePressed,
|
||||||
label: "Swap",
|
label: "Swap",
|
||||||
)
|
)
|
||||||
|
|
|
@ -124,9 +124,8 @@ class _Step2ViewState extends ConsumerState<Step2View> {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final supportsRefund = ref.watch(
|
final supportsRefund =
|
||||||
exchangeFormStateProvider.select((value) => value.exchange.name)) !=
|
ref.watch(efExchangeProvider).name != MajesticBankExchange.exchangeName;
|
||||||
MajesticBankExchange.exchangeName;
|
|
||||||
|
|
||||||
return Background(
|
return Background(
|
||||||
child: Scaffold(
|
child: Scaffold(
|
||||||
|
|
|
@ -52,9 +52,8 @@ class _Step3ViewState extends ConsumerState<Step3View> {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final supportsRefund = ref.watch(
|
final supportsRefund =
|
||||||
exchangeFormStateProvider.select((value) => value.exchange.name)) !=
|
ref.watch(efExchangeProvider).name != MajesticBankExchange.exchangeName;
|
||||||
MajesticBankExchange.exchangeName;
|
|
||||||
|
|
||||||
return Background(
|
return Background(
|
||||||
child: Scaffold(
|
child: Scaffold(
|
||||||
|
@ -254,8 +253,7 @@ class _Step3ViewState extends ConsumerState<Step3View> {
|
||||||
|
|
||||||
final ExchangeResponse<Trade> response =
|
final ExchangeResponse<Trade> response =
|
||||||
await ref
|
await ref
|
||||||
.read(exchangeFormStateProvider)
|
.read(efExchangeProvider)
|
||||||
.exchange
|
|
||||||
.createTrade(
|
.createTrade(
|
||||||
from: model.sendTicker,
|
from: model.sendTicker,
|
||||||
to: model.receiveTicker,
|
to: model.receiveTicker,
|
||||||
|
|
|
@ -70,10 +70,8 @@ class _Step4ViewState extends ConsumerState<Step4View> {
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _updateStatus() async {
|
Future<void> _updateStatus() async {
|
||||||
final statusResponse = await ref
|
final statusResponse =
|
||||||
.read(exchangeFormStateProvider)
|
await ref.read(efExchangeProvider).updateTrade(model.trade!);
|
||||||
.exchange
|
|
||||||
.updateTrade(model.trade!);
|
|
||||||
String status = "Waiting";
|
String status = "Waiting";
|
||||||
if (statusResponse.value != null) {
|
if (statusResponse.value != null) {
|
||||||
status = statusResponse.value!.status;
|
status = statusResponse.value!.status;
|
||||||
|
|
|
@ -37,7 +37,8 @@ class _ExchangeViewState extends ConsumerState<ExchangeView> {
|
||||||
ExchangeDataLoadingService.instance.onLoadingComplete = () {
|
ExchangeDataLoadingService.instance.onLoadingComplete = () {
|
||||||
WidgetsBinding.instance.addPostFrameCallback((timeStamp) async {
|
WidgetsBinding.instance.addPostFrameCallback((timeStamp) async {
|
||||||
await ExchangeDataLoadingService.instance.setCurrenciesIfEmpty(
|
await ExchangeDataLoadingService.instance.setCurrenciesIfEmpty(
|
||||||
ref.read(exchangeFormStateProvider),
|
ref.read(efCurrencyPairProvider),
|
||||||
|
ref.read(efRateTypeProvider),
|
||||||
);
|
);
|
||||||
setState(() {
|
setState(() {
|
||||||
_initialCachePopulationUnderway = false;
|
_initialCachePopulationUnderway = false;
|
||||||
|
@ -53,7 +54,8 @@ class _ExchangeViewState extends ConsumerState<ExchangeView> {
|
||||||
ExchangeDataLoadingService.instance.onLoadingComplete = () {
|
ExchangeDataLoadingService.instance.onLoadingComplete = () {
|
||||||
WidgetsBinding.instance.addPostFrameCallback((timeStamp) async {
|
WidgetsBinding.instance.addPostFrameCallback((timeStamp) async {
|
||||||
await ExchangeDataLoadingService.instance.setCurrenciesIfEmpty(
|
await ExchangeDataLoadingService.instance.setCurrenciesIfEmpty(
|
||||||
ref.read(exchangeFormStateProvider),
|
ref.read(efCurrencyPairProvider),
|
||||||
|
ref.read(efRateTypeProvider),
|
||||||
);
|
);
|
||||||
setState(() {
|
setState(() {
|
||||||
_initialCachePopulationUnderway = false;
|
_initialCachePopulationUnderway = false;
|
||||||
|
|
|
@ -2,12 +2,10 @@ import 'package:decimal/decimal.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
import 'package:flutter_svg/svg.dart';
|
import 'package:flutter_svg/svg.dart';
|
||||||
import 'package:stackwallet/exceptions/exchange/pair_unavailable_exception.dart';
|
|
||||||
import 'package:stackwallet/models/exchange/response_objects/estimate.dart';
|
import 'package:stackwallet/models/exchange/response_objects/estimate.dart';
|
||||||
import 'package:stackwallet/providers/exchange/exchange_form_state_provider.dart';
|
import 'package:stackwallet/providers/exchange/exchange_form_state_provider.dart';
|
||||||
import 'package:stackwallet/providers/global/locale_provider.dart';
|
import 'package:stackwallet/providers/global/locale_provider.dart';
|
||||||
import 'package:stackwallet/services/exchange/exchange.dart';
|
import 'package:stackwallet/services/exchange/exchange.dart';
|
||||||
import 'package:stackwallet/services/exchange/exchange_response.dart';
|
|
||||||
import 'package:stackwallet/utilities/amount/amount.dart';
|
import 'package:stackwallet/utilities/amount/amount.dart';
|
||||||
import 'package:stackwallet/utilities/assets.dart';
|
import 'package:stackwallet/utilities/assets.dart';
|
||||||
import 'package:stackwallet/utilities/enums/coin_enum.dart';
|
import 'package:stackwallet/utilities/enums/coin_enum.dart';
|
||||||
|
@ -42,138 +40,121 @@ class _ExchangeMultiProviderOptionState extends ConsumerState<ExchangeOption> {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final sendCurrency = ref
|
final sendCurrency =
|
||||||
.watch(exchangeFormStateProvider.select((value) => value.sendCurrency));
|
ref.watch(efCurrencyPairProvider.select((value) => value.send));
|
||||||
final receivingCurrency = ref.watch(
|
final receivingCurrency =
|
||||||
exchangeFormStateProvider.select((value) => value.receiveCurrency));
|
ref.watch(efCurrencyPairProvider.select((value) => value.receive));
|
||||||
final fromAmount = ref
|
final reversed = ref.watch(efReversedProvider);
|
||||||
.watch(exchangeFormStateProvider.select((value) => value.sendAmount));
|
final amount = reversed
|
||||||
final toAmount = ref.watch(
|
? ref.watch(efReceiveAmountProvider)
|
||||||
exchangeFormStateProvider.select((value) => value.receiveAmount));
|
: ref.watch(efSendAmountProvider);
|
||||||
|
|
||||||
|
final estimates = ref.watch(efEstimatesListProvider(widget.exchange.name));
|
||||||
|
|
||||||
return AnimatedSize(
|
return AnimatedSize(
|
||||||
duration: const Duration(milliseconds: 500),
|
duration: const Duration(milliseconds: 500),
|
||||||
curve: Curves.easeInOutCubicEmphasized,
|
curve: Curves.easeInOutCubicEmphasized,
|
||||||
child: Column(
|
child: Builder(
|
||||||
mainAxisSize: MainAxisSize.min,
|
builder: (_) {
|
||||||
children: [
|
if (ref.watch(efRefreshingProvider)) {
|
||||||
if (sendCurrency != null &&
|
// show loading
|
||||||
|
return _ProviderOption(
|
||||||
|
exchange: widget.exchange,
|
||||||
|
estimate: null,
|
||||||
|
rateString: "",
|
||||||
|
loadingString: true,
|
||||||
|
);
|
||||||
|
} else if (sendCurrency != null &&
|
||||||
receivingCurrency != null &&
|
receivingCurrency != null &&
|
||||||
toAmount != null &&
|
amount != null &&
|
||||||
toAmount > Decimal.zero &&
|
amount > Decimal.zero) {
|
||||||
fromAmount != null &&
|
if (estimates != null && estimates.item1.isNotEmpty) {
|
||||||
fromAmount > Decimal.zero)
|
return Column(
|
||||||
FutureBuilder(
|
mainAxisSize: MainAxisSize.min,
|
||||||
future: widget.exchange.getEstimates(
|
children: [
|
||||||
sendCurrency.ticker,
|
for (int i = 0; i < estimates.item1.length; i++)
|
||||||
receivingCurrency.ticker,
|
Builder(
|
||||||
widget.reversed ? toAmount : fromAmount,
|
builder: (context) {
|
||||||
widget.fixedRate,
|
final e = estimates.item1[i];
|
||||||
widget.reversed,
|
|
||||||
),
|
|
||||||
builder: (context,
|
|
||||||
AsyncSnapshot<ExchangeResponse<List<Estimate>>> snapshot) {
|
|
||||||
if (snapshot.connectionState == ConnectionState.done &&
|
|
||||||
snapshot.hasData) {
|
|
||||||
final estimates = snapshot.data?.value;
|
|
||||||
|
|
||||||
if (estimates != null && estimates.isNotEmpty) {
|
int decimals;
|
||||||
return Column(
|
try {
|
||||||
mainAxisSize: MainAxisSize.min,
|
decimals = coinFromTickerCaseInsensitive(
|
||||||
children: [
|
receivingCurrency.ticker)
|
||||||
for (int i = 0; i < estimates.length; i++)
|
.decimals;
|
||||||
Builder(
|
} catch (_) {
|
||||||
builder: (context) {
|
decimals = 8; // some reasonable alternative
|
||||||
final e = estimates[i];
|
}
|
||||||
int decimals;
|
Amount rate;
|
||||||
try {
|
if (e.reversed) {
|
||||||
decimals = coinFromTickerCaseInsensitive(
|
rate = (amount / e.estimatedAmount)
|
||||||
receivingCurrency.ticker)
|
.toDecimal(scaleOnInfinitePrecision: 18)
|
||||||
.decimals;
|
.toAmount(fractionDigits: decimals);
|
||||||
} catch (_) {
|
} else {
|
||||||
decimals = 8; // some reasonable alternative
|
rate = (e.estimatedAmount / amount)
|
||||||
}
|
.toDecimal(scaleOnInfinitePrecision: 18)
|
||||||
Amount rate;
|
.toAmount(fractionDigits: decimals);
|
||||||
if (e.reversed) {
|
}
|
||||||
rate = (toAmount / e.estimatedAmount)
|
|
||||||
.toDecimal(scaleOnInfinitePrecision: 18)
|
|
||||||
.toAmount(fractionDigits: decimals);
|
|
||||||
} else {
|
|
||||||
rate = (e.estimatedAmount / fromAmount)
|
|
||||||
.toDecimal(scaleOnInfinitePrecision: 18)
|
|
||||||
.toAmount(fractionDigits: decimals);
|
|
||||||
}
|
|
||||||
|
|
||||||
final rateString =
|
final rateString =
|
||||||
"1 ${sendCurrency.ticker.toUpperCase()} ~ ${rate.localizedStringAsFixed(
|
"1 ${sendCurrency.ticker.toUpperCase()} ~ ${rate.localizedStringAsFixed(
|
||||||
locale: ref.watch(
|
locale: ref.watch(
|
||||||
localeServiceChangeNotifierProvider
|
localeServiceChangeNotifierProvider
|
||||||
.select((value) => value.locale),
|
.select((value) => value.locale),
|
||||||
),
|
|
||||||
)} ${receivingCurrency.ticker.toUpperCase()}";
|
|
||||||
|
|
||||||
return ConditionalParent(
|
|
||||||
condition: i > 0,
|
|
||||||
builder: (child) => Column(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: [
|
|
||||||
isDesktop
|
|
||||||
? Container(
|
|
||||||
height: 1,
|
|
||||||
color: Theme.of(context)
|
|
||||||
.extension<StackColors>()!
|
|
||||||
.background,
|
|
||||||
)
|
|
||||||
: const SizedBox(
|
|
||||||
height: 16,
|
|
||||||
),
|
|
||||||
child,
|
|
||||||
],
|
|
||||||
),
|
|
||||||
child: _ProviderOption(
|
|
||||||
key: Key(widget.exchange.name +
|
|
||||||
e.exchangeProvider),
|
|
||||||
exchange: widget.exchange,
|
|
||||||
providerName: e.exchangeProvider,
|
|
||||||
rateString: rateString,
|
|
||||||
kycRating: e.kycRating,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
],
|
)} ${receivingCurrency.ticker.toUpperCase()}";
|
||||||
);
|
|
||||||
} else if (snapshot.data?.exception
|
|
||||||
is PairUnavailableException) {
|
|
||||||
return _ProviderOption(
|
|
||||||
exchange: widget.exchange,
|
|
||||||
providerName: widget.exchange.name,
|
|
||||||
rateString: "Unsupported pair",
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
Logging.instance.log(
|
|
||||||
"$runtimeType failed to fetch rate for ${widget.exchange.name}: ${snapshot.data}",
|
|
||||||
level: LogLevel.Warning,
|
|
||||||
);
|
|
||||||
|
|
||||||
return _ProviderOption(
|
return ConditionalParent(
|
||||||
exchange: widget.exchange,
|
condition: i > 0,
|
||||||
providerName: widget.exchange.name,
|
builder: (child) => Column(
|
||||||
rateString: "Failed to fetch rate",
|
mainAxisSize: MainAxisSize.min,
|
||||||
);
|
children: [
|
||||||
}
|
isDesktop
|
||||||
} else {
|
? Container(
|
||||||
// show loading
|
height: 1,
|
||||||
return _ProviderOption(
|
color: Theme.of(context)
|
||||||
exchange: widget.exchange,
|
.extension<StackColors>()!
|
||||||
providerName: widget.exchange.name,
|
.background,
|
||||||
rateString: "",
|
)
|
||||||
loadingString: true,
|
: const SizedBox(
|
||||||
);
|
height: 16,
|
||||||
}
|
),
|
||||||
},
|
child,
|
||||||
),
|
],
|
||||||
],
|
),
|
||||||
|
child: _ProviderOption(
|
||||||
|
key: Key(widget.exchange.name + e.exchangeProvider),
|
||||||
|
exchange: widget.exchange,
|
||||||
|
estimate: e,
|
||||||
|
rateString: rateString,
|
||||||
|
kycRating: e.kycRating,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
Logging.instance.log(
|
||||||
|
"$runtimeType failed to fetch rate for ${widget.exchange.name}: $estimates",
|
||||||
|
level: LogLevel.Warning,
|
||||||
|
);
|
||||||
|
|
||||||
|
return _ProviderOption(
|
||||||
|
exchange: widget.exchange,
|
||||||
|
estimate: null,
|
||||||
|
rateString: "Failed to fetch rate",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// show n/a
|
||||||
|
return _ProviderOption(
|
||||||
|
exchange: widget.exchange,
|
||||||
|
estimate: null,
|
||||||
|
rateString: "n/a",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -183,14 +164,14 @@ class _ProviderOption extends ConsumerStatefulWidget {
|
||||||
const _ProviderOption({
|
const _ProviderOption({
|
||||||
Key? key,
|
Key? key,
|
||||||
required this.exchange,
|
required this.exchange,
|
||||||
required this.providerName,
|
required this.estimate,
|
||||||
required this.rateString,
|
required this.rateString,
|
||||||
this.kycRating,
|
this.kycRating,
|
||||||
this.loadingString = false,
|
this.loadingString = false,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
final Exchange exchange;
|
final Exchange exchange;
|
||||||
final String providerName;
|
final Estimate? estimate;
|
||||||
final String rateString;
|
final String rateString;
|
||||||
final String? kycRating;
|
final String? kycRating;
|
||||||
final bool loadingString;
|
final bool loadingString;
|
||||||
|
@ -206,25 +187,27 @@ class _ProviderOptionState extends ConsumerState<_ProviderOption> {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
_id = "${widget.exchange.name} (${widget.providerName})";
|
_id =
|
||||||
|
"${widget.exchange.name} (${widget.estimate?.exchangeProvider ?? widget.exchange.name})";
|
||||||
super.initState();
|
super.initState();
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
bool selected = ref.watch(exchangeFormStateProvider
|
String groupValue = ref.watch(currentCombinedExchangeIdProvider);
|
||||||
.select((value) => value.combinedExchangeId)) ==
|
|
||||||
_id;
|
|
||||||
String groupValue = ref.watch(
|
|
||||||
exchangeFormStateProvider.select((value) => value.combinedExchangeId));
|
|
||||||
|
|
||||||
if (ref.watch(
|
if (ref.watch(efExchangeProvider).name ==
|
||||||
exchangeFormStateProvider.select((value) => value.exchange.name)) ==
|
(widget.estimate?.exchangeProvider ?? widget.exchange.name)) {
|
||||||
widget.providerName) {
|
|
||||||
selected = true;
|
|
||||||
groupValue = _id;
|
groupValue = _id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool selected = groupValue == _id;
|
||||||
|
|
||||||
|
print("========================================================");
|
||||||
|
print("gourpValue: $groupValue");
|
||||||
|
print("_id: $_id");
|
||||||
|
print("========================================================");
|
||||||
|
|
||||||
return ConditionalParent(
|
return ConditionalParent(
|
||||||
condition: isDesktop,
|
condition: isDesktop,
|
||||||
builder: (child) => MouseRegion(
|
builder: (child) => MouseRegion(
|
||||||
|
@ -233,15 +216,20 @@ class _ProviderOptionState extends ConsumerState<_ProviderOption> {
|
||||||
),
|
),
|
||||||
child: GestureDetector(
|
child: GestureDetector(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
if (!selected) {
|
ref.read(efExchangeProvider.notifier).state = widget.exchange;
|
||||||
ref.read(exchangeFormStateProvider).updateExchange(
|
ref.read(efExchangeProviderNameProvider.notifier).state =
|
||||||
exchange: widget.exchange,
|
widget.estimate?.exchangeProvider ?? widget.exchange.name;
|
||||||
shouldUpdateData: true,
|
|
||||||
shouldNotifyListeners: true,
|
// if (!selected) {
|
||||||
providerName: widget.providerName,
|
// ref.read(exchangeFormStateProvider).updateExchange(
|
||||||
shouldAwait: false,
|
// exchange: widget.exchange,
|
||||||
);
|
// shouldUpdateData: false,
|
||||||
}
|
// shouldNotifyListeners: false,
|
||||||
|
// providerName:
|
||||||
|
// widget.estimate?.exchangeProvider ?? widget.exchange.name,
|
||||||
|
// shouldAwait: false,
|
||||||
|
// );
|
||||||
|
// }
|
||||||
},
|
},
|
||||||
child: Container(
|
child: Container(
|
||||||
color: Colors.transparent,
|
color: Colors.transparent,
|
||||||
|
@ -263,15 +251,26 @@ class _ProviderOptionState extends ConsumerState<_ProviderOption> {
|
||||||
value: _id,
|
value: _id,
|
||||||
groupValue: groupValue,
|
groupValue: groupValue,
|
||||||
onChanged: (_) {
|
onChanged: (_) {
|
||||||
if (!selected) {
|
ref.read(efExchangeProvider.notifier).state =
|
||||||
ref.read(exchangeFormStateProvider).updateExchange(
|
widget.exchange;
|
||||||
exchange: widget.exchange,
|
ref
|
||||||
shouldUpdateData: false,
|
.read(efExchangeProviderNameProvider.notifier)
|
||||||
shouldNotifyListeners: true,
|
.state =
|
||||||
providerName: widget.providerName,
|
widget.estimate?.exchangeProvider ??
|
||||||
shouldAwait: false,
|
widget.exchange.name;
|
||||||
);
|
// if (!selected) {
|
||||||
}
|
//
|
||||||
|
//
|
||||||
|
// ref.read(exchangeFormStateProvider).updateExchange(
|
||||||
|
// exchange: widget.exchange,
|
||||||
|
// shouldUpdateData: false,
|
||||||
|
// shouldNotifyListeners: false,
|
||||||
|
// providerName:
|
||||||
|
// widget.estimate?.exchangeProvider ??
|
||||||
|
// widget.exchange.name,
|
||||||
|
// shouldAwait: false,
|
||||||
|
// );
|
||||||
|
// }
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -303,7 +302,8 @@ class _ProviderOptionState extends ConsumerState<_ProviderOption> {
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
widget.providerName,
|
widget.estimate?.exchangeProvider ??
|
||||||
|
widget.exchange.name,
|
||||||
style: STextStyles.titleBold12(context).copyWith(
|
style: STextStyles.titleBold12(context).copyWith(
|
||||||
color: Theme.of(context)
|
color: Theme.of(context)
|
||||||
.extension<StackColors>()!
|
.extension<StackColors>()!
|
||||||
|
|
|
@ -49,16 +49,10 @@ class _ExchangeProviderOptionsState
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final sendCurrency = ref.watch(
|
final sendCurrency =
|
||||||
exchangeFormStateProvider.select(
|
ref.watch(efCurrencyPairProvider.select((value) => value.send));
|
||||||
(value) => value.sendCurrency,
|
final receivingCurrency =
|
||||||
),
|
ref.watch(efCurrencyPairProvider.select((value) => value.receive));
|
||||||
);
|
|
||||||
final receivingCurrency = ref.watch(
|
|
||||||
exchangeFormStateProvider.select(
|
|
||||||
(value) => value.receiveCurrency,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
final showChangeNow = exchangeSupported(
|
final showChangeNow = exchangeSupported(
|
||||||
exchangeName: ChangeNowExchange.exchangeName,
|
exchangeName: ChangeNowExchange.exchangeName,
|
||||||
|
|
|
@ -29,9 +29,7 @@ class RateTypeToggle extends ConsumerWidget {
|
||||||
onChanged?.call(ExchangeRateType.estimated);
|
onChanged?.call(ExchangeRateType.estimated);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
isOn: ref.watch(exchangeFormStateProvider
|
isOn: ref.watch(efRateTypeProvider) == ExchangeRateType.fixed,
|
||||||
.select((value) => value.exchangeRateType)) ==
|
|
||||||
ExchangeRateType.fixed,
|
|
||||||
onColor: isDesktop
|
onColor: isDesktop
|
||||||
? Theme.of(context)
|
? Theme.of(context)
|
||||||
.extension<StackColors>()!
|
.extension<StackColors>()!
|
||||||
|
|
|
@ -54,7 +54,8 @@ class _WalletInitiatedExchangeViewState
|
||||||
ExchangeDataLoadingService.instance.onLoadingComplete = () {
|
ExchangeDataLoadingService.instance.onLoadingComplete = () {
|
||||||
WidgetsBinding.instance.addPostFrameCallback((timeStamp) async {
|
WidgetsBinding.instance.addPostFrameCallback((timeStamp) async {
|
||||||
await ExchangeDataLoadingService.instance.setCurrenciesIfEmpty(
|
await ExchangeDataLoadingService.instance.setCurrenciesIfEmpty(
|
||||||
ref.read(exchangeFormStateProvider),
|
ref.read(efCurrencyPairProvider),
|
||||||
|
ref.read(efRateTypeProvider),
|
||||||
);
|
);
|
||||||
setState(() {
|
setState(() {
|
||||||
_initialCachePopulationUnderway = false;
|
_initialCachePopulationUnderway = false;
|
||||||
|
@ -70,7 +71,8 @@ class _WalletInitiatedExchangeViewState
|
||||||
ExchangeDataLoadingService.instance.onLoadingComplete = () {
|
ExchangeDataLoadingService.instance.onLoadingComplete = () {
|
||||||
WidgetsBinding.instance.addPostFrameCallback((timeStamp) async {
|
WidgetsBinding.instance.addPostFrameCallback((timeStamp) async {
|
||||||
await ExchangeDataLoadingService.instance.setCurrenciesIfEmpty(
|
await ExchangeDataLoadingService.instance.setCurrenciesIfEmpty(
|
||||||
ref.read(exchangeFormStateProvider),
|
ref.read(efCurrencyPairProvider),
|
||||||
|
ref.read(efRateTypeProvider),
|
||||||
);
|
);
|
||||||
setState(() {
|
setState(() {
|
||||||
_initialCachePopulationUnderway = false;
|
_initialCachePopulationUnderway = false;
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
import 'package:stackwallet/pages/exchange_view/exchange_form.dart';
|
import 'package:stackwallet/pages/exchange_view/exchange_form.dart';
|
||||||
|
import 'package:stackwallet/pages_desktop_specific/desktop_exchange/desktop_all_trades_view.dart';
|
||||||
import 'package:stackwallet/pages_desktop_specific/desktop_exchange/subwidgets/desktop_trade_history.dart';
|
import 'package:stackwallet/pages_desktop_specific/desktop_exchange/subwidgets/desktop_trade_history.dart';
|
||||||
import 'package:stackwallet/providers/exchange/exchange_form_state_provider.dart';
|
import 'package:stackwallet/providers/exchange/exchange_form_state_provider.dart';
|
||||||
import 'package:stackwallet/providers/global/prefs_provider.dart';
|
import 'package:stackwallet/providers/global/prefs_provider.dart';
|
||||||
|
@ -14,8 +15,6 @@ import 'package:stackwallet/widgets/desktop/desktop_app_bar.dart';
|
||||||
import 'package:stackwallet/widgets/desktop/desktop_scaffold.dart';
|
import 'package:stackwallet/widgets/desktop/desktop_scaffold.dart';
|
||||||
import 'package:stackwallet/widgets/rounded_white_container.dart';
|
import 'package:stackwallet/widgets/rounded_white_container.dart';
|
||||||
|
|
||||||
import 'desktop_all_trades_view.dart';
|
|
||||||
|
|
||||||
class DesktopExchangeView extends ConsumerStatefulWidget {
|
class DesktopExchangeView extends ConsumerStatefulWidget {
|
||||||
const DesktopExchangeView({Key? key}) : super(key: key);
|
const DesktopExchangeView({Key? key}) : super(key: key);
|
||||||
|
|
||||||
|
@ -38,7 +37,8 @@ class _DesktopExchangeViewState extends ConsumerState<DesktopExchangeView> {
|
||||||
ExchangeDataLoadingService.instance.onLoadingComplete = () {
|
ExchangeDataLoadingService.instance.onLoadingComplete = () {
|
||||||
WidgetsBinding.instance.addPostFrameCallback((timeStamp) async {
|
WidgetsBinding.instance.addPostFrameCallback((timeStamp) async {
|
||||||
await ExchangeDataLoadingService.instance.setCurrenciesIfEmpty(
|
await ExchangeDataLoadingService.instance.setCurrenciesIfEmpty(
|
||||||
ref.read(exchangeFormStateProvider),
|
ref.read(efCurrencyPairProvider),
|
||||||
|
ref.read(efRateTypeProvider),
|
||||||
);
|
);
|
||||||
setState(() {
|
setState(() {
|
||||||
_initialCachePopulationUnderway = false;
|
_initialCachePopulationUnderway = false;
|
||||||
|
@ -54,7 +54,8 @@ class _DesktopExchangeViewState extends ConsumerState<DesktopExchangeView> {
|
||||||
ExchangeDataLoadingService.instance.onLoadingComplete = () {
|
ExchangeDataLoadingService.instance.onLoadingComplete = () {
|
||||||
WidgetsBinding.instance.addPostFrameCallback((timeStamp) async {
|
WidgetsBinding.instance.addPostFrameCallback((timeStamp) async {
|
||||||
await ExchangeDataLoadingService.instance.setCurrenciesIfEmpty(
|
await ExchangeDataLoadingService.instance.setCurrenciesIfEmpty(
|
||||||
ref.read(exchangeFormStateProvider),
|
ref.read(efCurrencyPairProvider),
|
||||||
|
ref.read(efRateTypeProvider),
|
||||||
);
|
);
|
||||||
setState(() {
|
setState(() {
|
||||||
_initialCachePopulationUnderway = false;
|
_initialCachePopulationUnderway = false;
|
||||||
|
|
|
@ -84,8 +84,7 @@ class _StepScaffoldState extends ConsumerState<StepScaffold> {
|
||||||
);
|
);
|
||||||
|
|
||||||
final ExchangeResponse<Trade> response = await ref
|
final ExchangeResponse<Trade> response = await ref
|
||||||
.read(exchangeFormStateProvider)
|
.read(efExchangeProvider)
|
||||||
.exchange
|
|
||||||
.createTrade(
|
.createTrade(
|
||||||
from: ref.read(desktopExchangeModelProvider)!.sendTicker,
|
from: ref.read(desktopExchangeModelProvider)!.sendTicker,
|
||||||
to: ref.read(desktopExchangeModelProvider)!.receiveTicker,
|
to: ref.read(desktopExchangeModelProvider)!.receiveTicker,
|
||||||
|
|
|
@ -38,8 +38,7 @@ class DesktopStep1 extends ConsumerWidget {
|
||||||
children: [
|
children: [
|
||||||
DesktopStepItem(
|
DesktopStepItem(
|
||||||
label: "Swap",
|
label: "Swap",
|
||||||
value: ref.watch(exchangeFormStateProvider
|
value: ref.watch(efExchangeProviderNameProvider),
|
||||||
.select((value) => value.exchange.name)),
|
|
||||||
),
|
),
|
||||||
Container(
|
Container(
|
||||||
height: 1,
|
height: 1,
|
||||||
|
|
|
@ -36,8 +36,7 @@ class _DesktopStep3State extends ConsumerState<DesktopStep3> {
|
||||||
children: [
|
children: [
|
||||||
DesktopStepItem(
|
DesktopStepItem(
|
||||||
label: "Swap",
|
label: "Swap",
|
||||||
value: ref.watch(exchangeFormStateProvider
|
value: ref.watch(efExchangeProviderNameProvider),
|
||||||
.select((value) => value.exchange.name)),
|
|
||||||
),
|
),
|
||||||
Container(
|
Container(
|
||||||
height: 1,
|
height: 1,
|
||||||
|
|
|
@ -46,7 +46,7 @@ class _DesktopStep4State extends ConsumerState<DesktopStep4> {
|
||||||
}
|
}
|
||||||
|
|
||||||
final statusResponse =
|
final statusResponse =
|
||||||
await ref.read(exchangeFormStateProvider).exchange.updateTrade(trade);
|
await ref.read(efExchangeProvider).updateTrade(trade);
|
||||||
String status = "Waiting";
|
String status = "Waiting";
|
||||||
if (statusResponse.value != null) {
|
if (statusResponse.value != null) {
|
||||||
status = statusResponse.value!.status;
|
status = statusResponse.value!.status;
|
||||||
|
|
|
@ -1,5 +1,116 @@
|
||||||
|
import 'package:decimal/decimal.dart';
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
import 'package:stackwallet/models/exchange/exchange_form_state.dart';
|
import 'package:stackwallet/models/exchange/active_pair.dart';
|
||||||
|
import 'package:stackwallet/models/exchange/response_objects/estimate.dart';
|
||||||
|
import 'package:stackwallet/models/exchange/response_objects/range.dart';
|
||||||
|
import 'package:stackwallet/services/exchange/exchange.dart';
|
||||||
|
import 'package:stackwallet/utilities/enums/exchange_rate_type_enum.dart';
|
||||||
|
import 'package:tuple/tuple.dart';
|
||||||
|
|
||||||
final exchangeFormStateProvider =
|
final efEstimatesListProvider =
|
||||||
ChangeNotifierProvider<ExchangeFormState>((ref) => ExchangeFormState());
|
StateProvider.family<Tuple2<List<Estimate>, Range>?, String>(
|
||||||
|
(ref, exchangeName) => null);
|
||||||
|
|
||||||
|
final efRateTypeProvider =
|
||||||
|
StateProvider<ExchangeRateType>((ref) => ExchangeRateType.estimated);
|
||||||
|
|
||||||
|
final efExchangeProvider =
|
||||||
|
StateProvider<Exchange>((ref) => Exchange.defaultExchange);
|
||||||
|
final efExchangeProviderNameProvider =
|
||||||
|
StateProvider<String>((ref) => Exchange.defaultExchange.name);
|
||||||
|
|
||||||
|
final currentCombinedExchangeIdProvider = Provider<String>((ref) {
|
||||||
|
return "${ref.watch(efExchangeProvider).name}"
|
||||||
|
" (${ref.watch(efExchangeProviderNameProvider)})";
|
||||||
|
});
|
||||||
|
|
||||||
|
final efSendAmountProvider = StateProvider<Decimal?>((ref) => null);
|
||||||
|
final efReceiveAmountProvider = StateProvider<Decimal?>((ref) => null);
|
||||||
|
|
||||||
|
final efSendAmountStringProvider = StateProvider<String>((ref) {
|
||||||
|
return ref.watch(efSendAmountProvider)?.toStringAsFixed(8) ?? "";
|
||||||
|
});
|
||||||
|
final efReceiveAmountStringProvider = StateProvider<String>((ref) {
|
||||||
|
return ref.watch(efReceiveAmountProvider)?.toStringAsFixed(8) ?? "";
|
||||||
|
});
|
||||||
|
|
||||||
|
final efReversedProvider = StateProvider<bool>((ref) => false);
|
||||||
|
|
||||||
|
final efCurrencyPairProvider = ChangeNotifierProvider<ActivePair>(
|
||||||
|
(ref) => ActivePair(),
|
||||||
|
);
|
||||||
|
|
||||||
|
final efRangeProvider = StateProvider<Range?>((ref) {
|
||||||
|
final exchange = ref.watch(efExchangeProvider);
|
||||||
|
return ref.watch(efEstimatesListProvider(exchange.name))?.item2;
|
||||||
|
});
|
||||||
|
|
||||||
|
final efEstimateProvider = StateProvider<Estimate?>((ref) {
|
||||||
|
final exchange = ref.watch(efExchangeProvider);
|
||||||
|
final provider = ref.watch(efExchangeProviderNameProvider);
|
||||||
|
final reversed = ref.watch(efReversedProvider);
|
||||||
|
final fixedRate = ref.watch(efRateTypeProvider) == ExchangeRateType.fixed;
|
||||||
|
|
||||||
|
final matches =
|
||||||
|
ref.watch(efEstimatesListProvider(exchange.name))?.item1.where((e) {
|
||||||
|
return e.exchangeProvider == provider &&
|
||||||
|
e.fixedRate == fixedRate &&
|
||||||
|
e.reversed == reversed;
|
||||||
|
});
|
||||||
|
|
||||||
|
Estimate? result;
|
||||||
|
|
||||||
|
if (matches != null && matches.isNotEmpty) {
|
||||||
|
result = matches.first;
|
||||||
|
} else {
|
||||||
|
result = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
});
|
||||||
|
|
||||||
|
final efCanExchangeProvider = StateProvider<bool>((ref) {
|
||||||
|
final Estimate? estimate = ref.watch(efEstimateProvider);
|
||||||
|
// final Decimal? amount = ref.watch(efReversedProvider)
|
||||||
|
// ? ref.watch(efSendAmountProvider)
|
||||||
|
// : ref.watch(efReceiveAmountProvider);
|
||||||
|
|
||||||
|
return estimate != null;
|
||||||
|
});
|
||||||
|
|
||||||
|
final efRefreshingProvider = StateProvider<bool>((ref) => false);
|
||||||
|
|
||||||
|
final efWarningProvider = StateProvider((ref) {
|
||||||
|
// if (ref.watch(efReversedProvider)) {
|
||||||
|
// final _receiveCurrency =
|
||||||
|
// ref.watch(efCurrencyPairProvider.select((value) => value.receive));
|
||||||
|
// final _receiveAmount = ref.watch(efReceiveAmountProvider);
|
||||||
|
// if (_receiveCurrency != null && _receiveAmount != null) {
|
||||||
|
// final range = ref.watch(efRangeProvider);
|
||||||
|
// if (range?.min != null &&
|
||||||
|
// _receiveAmount < range!.min! &&
|
||||||
|
// _receiveAmount > Decimal.zero) {
|
||||||
|
// return "Min receive amount ${range.min!.toString()} ${_receiveCurrency.ticker.toUpperCase()}";
|
||||||
|
// } else if (range?.max != null &&
|
||||||
|
// _receiveAmount > ref.watch(efRangeProvider)!.max!) {
|
||||||
|
// return "Max receive amount $range!.max!.toString()} ${_receiveCurrency.ticker.toUpperCase()}";
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// } else {
|
||||||
|
// final _sendCurrency =
|
||||||
|
// ref.watch(efCurrencyPairProvider.select((value) => value.send));
|
||||||
|
// final _sendAmount = ref.watch(efSendAmountProvider);
|
||||||
|
// if (_sendCurrency != null && _sendAmount != null) {
|
||||||
|
// final range = ref.watch(efRangeProvider);
|
||||||
|
// if (range?.min != null &&
|
||||||
|
// _sendAmount < range!.min! &&
|
||||||
|
// _sendAmount > Decimal.zero) {
|
||||||
|
// return "Min send amount ${range.min!.toString()} ${_sendCurrency.ticker.toUpperCase()}";
|
||||||
|
// } else if (range?.max != null && _sendAmount > range!.max!) {
|
||||||
|
// return "Max send amount ${range.max!.toString()} ${_sendCurrency.ticker.toUpperCase()}";
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
return "";
|
||||||
|
});
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:isar/isar.dart';
|
import 'package:isar/isar.dart';
|
||||||
import 'package:stackwallet/db/hive/db.dart';
|
import 'package:stackwallet/db/hive/db.dart';
|
||||||
|
import 'package:stackwallet/models/exchange/active_pair.dart';
|
||||||
import 'package:stackwallet/models/exchange/aggregate_currency.dart';
|
import 'package:stackwallet/models/exchange/aggregate_currency.dart';
|
||||||
import 'package:stackwallet/models/exchange/exchange_form_state.dart';
|
|
||||||
import 'package:stackwallet/models/isar/exchange_cache/currency.dart';
|
import 'package:stackwallet/models/isar/exchange_cache/currency.dart';
|
||||||
import 'package:stackwallet/models/isar/exchange_cache/pair.dart';
|
import 'package:stackwallet/models/isar/exchange_cache/pair.dart';
|
||||||
import 'package:stackwallet/services/exchange/change_now/change_now_exchange.dart';
|
import 'package:stackwallet/services/exchange/change_now/change_now_exchange.dart';
|
||||||
|
@ -57,20 +57,29 @@ class ExchangeDataLoadingService {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> setCurrenciesIfEmpty(ExchangeFormState state) async {
|
Future<void> setCurrenciesIfEmpty(
|
||||||
if (state.sendCurrency == null && state.receiveCurrency == null) {
|
ActivePair? pair,
|
||||||
|
ExchangeRateType rateType,
|
||||||
|
) async {
|
||||||
|
if (pair?.send == null && pair?.receive == null) {
|
||||||
if (await isar.currencies.count() > 0) {
|
if (await isar.currencies.count() > 0) {
|
||||||
final sendCurrency = await getAggregateCurrency(
|
pair?.setSend(
|
||||||
"BTC",
|
await getAggregateCurrency(
|
||||||
state.exchangeRateType,
|
"BTC",
|
||||||
null,
|
rateType,
|
||||||
|
null,
|
||||||
|
),
|
||||||
|
notifyListeners: false,
|
||||||
);
|
);
|
||||||
final receiveCurrency = await getAggregateCurrency(
|
|
||||||
"XMR",
|
pair?.setReceive(
|
||||||
state.exchangeRateType,
|
await getAggregateCurrency(
|
||||||
null,
|
"XMR",
|
||||||
|
rateType,
|
||||||
|
null,
|
||||||
|
),
|
||||||
|
notifyListeners: false,
|
||||||
);
|
);
|
||||||
state.setCurrencies(sendCurrency, receiveCurrency);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue