From a37b518f7efea14c482bc775cdefd54373bc6c84 Mon Sep 17 00:00:00 2001 From: julian Date: Tue, 4 Oct 2022 13:10:44 -0600 Subject: [PATCH] WIP show rates --- lib/models/exchange/exchange_form_state.dart | 32 ++- lib/pages/exchange_view/exchange_form.dart | 26 +- .../exchange_provider_options.dart | 223 ++++++++++++++++-- 3 files changed, 251 insertions(+), 30 deletions(-) diff --git a/lib/models/exchange/exchange_form_state.dart b/lib/models/exchange/exchange_form_state.dart index e5aac8f0a..892149f3f 100644 --- a/lib/models/exchange/exchange_form_state.dart +++ b/lib/models/exchange/exchange_form_state.dart @@ -6,6 +6,7 @@ import 'package:stackwallet/models/exchange/response_objects/estimate.dart'; import 'package:stackwallet/models/exchange/response_objects/fixed_rate_market.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/simpleswap/simpleswap_exchange.dart'; import 'package:stackwallet/utilities/logger.dart'; class ExchangeFormState extends ChangeNotifier { @@ -184,7 +185,7 @@ class ExchangeFormState extends ChangeNotifier { ); debugPrint( - "_updated TO: _from=${_from!.ticker} _to=${_to!.ticker} _fromAmount=$fromAmount _toAmount=$toAmount rate:$rate"); + "_updated TO: _from=${_from!.ticker} _to=${_to!.ticker} _fromAmount=$fromAmount _toAmount=$toAmount rate:$rate for: $exchange"); if (shouldNotifyListeners) { notifyListeners(); @@ -212,7 +213,7 @@ class ExchangeFormState extends ChangeNotifier { ); debugPrint( - "_updated FROM: _from=${_from!.ticker} _to=${_to!.ticker} _fromAmount=$fromAmount _toAmount=$toAmount rate:$rate"); + "_updated FROM: _from=${_from!.ticker} _to=${_to!.ticker} _fromAmount=$fromAmount _toAmount=$toAmount rate:$rate for: $exchange"); if (shouldNotifyListeners) { notifyListeners(); } @@ -254,15 +255,23 @@ class ExchangeFormState extends ChangeNotifier { } void _onExchangeTypeChanged() { - print("_onExchangeTypeChanged"); + updateRanges(shouldNotifyListeners: true).then( + (_) => updateEstimate( + shouldNotifyListeners: true, + reversed: reversed, + ), + ); } Future updateRanges({required bool shouldNotifyListeners}) async { + if (exchange?.name == SimpleSwapExchange.exchangeName) { + reversed = false; + } final _fromTicker = reversed ? toTicker : fromTicker; final _toTicker = reversed ? fromTicker : toTicker; if (_fromTicker == null || _toTicker == null) { Logging.instance.log( - "Tried to $runtimeType.updateRanges where (from: $_fromTicker || to: $_toTicker)", + "Tried to $runtimeType.updateRanges where (from: $_fromTicker || to: $_toTicker) for: $exchange", level: LogLevel.Info, ); return; @@ -275,7 +284,7 @@ class ExchangeFormState extends ChangeNotifier { if (response?.value == null) { Logging.instance.log( - "Tried to $runtimeType.updateRanges where response: $response", + "Tried to $runtimeType.updateRanges for: $exchange where response: $response", level: LogLevel.Info, ); return; @@ -286,7 +295,8 @@ class ExchangeFormState extends ChangeNotifier { minAmount = range.min; maxAmount = range.max; - debugPrint("updated range for $_fromTicker-$_toTicker: $range"); + debugPrint( + "updated range for: $exchange for $_fromTicker-$_toTicker: $range"); if (shouldNotifyListeners) { notifyListeners(); @@ -297,13 +307,16 @@ class ExchangeFormState extends ChangeNotifier { required bool shouldNotifyListeners, required bool reversed, }) async { + if (exchange?.name == SimpleSwapExchange.exchangeName) { + reversed = false; + } final amount = reversed ? toAmount : fromAmount; if (fromTicker == null || toTicker == null || amount == null || amount <= Decimal.zero) { Logging.instance.log( - "Tried to $runtimeType.updateEstimate where (from: $fromTicker || to: $toTicker || amount: $amount)", + "Tried to $runtimeType.updateEstimate for: $exchange where (from: $fromTicker || to: $toTicker || amount: $amount)", level: LogLevel.Info, ); return; @@ -318,7 +331,7 @@ class ExchangeFormState extends ChangeNotifier { if (response?.value == null) { Logging.instance.log( - "Tried to $runtimeType.updateEstimate where response: $response", + "Tried to $runtimeType.updateEstimate for: $exchange where response: $response", level: LogLevel.Info, ); return; @@ -334,7 +347,8 @@ class ExchangeFormState extends ChangeNotifier { rate = (toAmount! / fromAmount!).toDecimal(scaleOnInfinitePrecision: 12); - debugPrint("updated estimate for $fromTicker-$toTicker: $estimate"); + debugPrint( + "updated estimate for: $exchange for $fromTicker-$toTicker: $estimate"); if (shouldNotifyListeners) { notifyListeners(); diff --git a/lib/pages/exchange_view/exchange_form.dart b/lib/pages/exchange_view/exchange_form.dart index 30d333b8c..4928cec57 100644 --- a/lib/pages/exchange_view/exchange_form.dart +++ b/lib/pages/exchange_view/exchange_form.dart @@ -294,8 +294,7 @@ class _ExchangeFormState extends ConsumerState { ), ); - if (ref.watch(prefsChangeNotifierProvider - .select((pref) => pref.exchangeRateType)) == + if (ref.read(prefsChangeNotifierProvider).exchangeRateType == ExchangeRateType.estimated) { await ref.read(exchangeFormStateProvider).swap(); } else { @@ -912,6 +911,10 @@ class _ExchangeFormState extends ConsumerState { Widget build(BuildContext context) { debugPrint("BUILD: $runtimeType"); + ref.listen(currentExchangeNameStateProvider, (previous, next) { + ref.read(exchangeFormStateProvider).exchange = ref.read(exchangeProvider); + }); + final isEstimated = ref.watch(prefsChangeNotifierProvider .select((pref) => pref.exchangeRateType)) == ExchangeRateType.estimated; @@ -920,7 +923,12 @@ class _ExchangeFormState extends ConsumerState { exchangeFormStateProvider.select((value) => value.toAmountString), (previous, String next) { if (!_receiveFocusNode.hasFocus) { - _receiveController.text = isEstimated && next.isEmpty ? "-" : next; + _receiveController.text = isEstimated && + ref.watch(exchangeProvider).name == + SimpleSwapExchange.exchangeName && + next.isEmpty + ? "-" + : next; debugPrint("RECEIVE AMOUNT LISTENER ACTIVATED"); if (_swapLock) { _sendController.text = @@ -1164,8 +1172,10 @@ class _ExchangeFormState extends ConsumerState { focusNode: _receiveFocusNode, controller: _receiveController, readOnly: ref.watch(prefsChangeNotifierProvider - .select((value) => value.exchangeRateType)) == - ExchangeRateType.estimated, + .select((value) => value.exchangeRateType)) == + ExchangeRateType.estimated || + ref.watch(exchangeProvider).name == + SimpleSwapExchange.exchangeName, onTap: () { if (!(ref.read(prefsChangeNotifierProvider).exchangeRateType == ExchangeRateType.estimated) && @@ -1306,8 +1316,10 @@ class _ExchangeFormState extends ConsumerState { height: 8, ), ExchangeProviderOptions( - fromAmount: null, - toAmount: null, + from: ref.watch(exchangeFormStateProvider).fromTicker, + to: ref.watch(exchangeFormStateProvider).toTicker, + fromAmount: ref.watch(exchangeFormStateProvider).fromAmount, + toAmount: ref.watch(exchangeFormStateProvider).toAmount, fixedRate: ref.watch(prefsChangeNotifierProvider .select((value) => value.exchangeRateType)) == ExchangeRateType.fixed, diff --git a/lib/pages/exchange_view/sub_widgets/exchange_provider_options.dart b/lib/pages/exchange_view/sub_widgets/exchange_provider_options.dart index fc960f88a..20d39f986 100644 --- a/lib/pages/exchange_view/sub_widgets/exchange_provider_options.dart +++ b/lib/pages/exchange_view/sub_widgets/exchange_provider_options.dart @@ -2,23 +2,34 @@ import 'package:decimal/decimal.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/svg.dart'; +import 'package:stackwallet/models/exchange/response_objects/estimate.dart'; import 'package:stackwallet/providers/providers.dart'; import 'package:stackwallet/services/exchange/change_now/change_now_exchange.dart'; +import 'package:stackwallet/services/exchange/exchange_response.dart'; import 'package:stackwallet/services/exchange/simpleswap/simpleswap_exchange.dart'; import 'package:stackwallet/utilities/assets.dart'; +import 'package:stackwallet/utilities/constants.dart'; +import 'package:stackwallet/utilities/enums/coin_enum.dart'; +import 'package:stackwallet/utilities/format.dart'; +import 'package:stackwallet/utilities/logger.dart'; import 'package:stackwallet/utilities/text_styles.dart'; import 'package:stackwallet/utilities/theme/stack_colors.dart'; +import 'package:stackwallet/widgets/animated_text.dart'; import 'package:stackwallet/widgets/rounded_white_container.dart'; class ExchangeProviderOptions extends ConsumerWidget { const ExchangeProviderOptions({ Key? key, + required this.from, + required this.to, required this.fromAmount, required this.toAmount, required this.fixedRate, required this.reversed, }) : super(key: key); + final String? from; + final String? to; final Decimal? fromAmount; final Decimal? toAmount; final bool fixedRate; @@ -87,14 +98,106 @@ class ExchangeProviderOptions extends ConsumerWidget { .textDark2, ), ), - Text( - ChangeNowExchange.exchangeName, - style: STextStyles.itemSubtitle12(context).copyWith( - color: Theme.of(context) - .extension()! - .textSubtitle1, + if (from != null && + to != null && + toAmount != null && + toAmount! > Decimal.zero && + fromAmount != null && + fromAmount! > Decimal.zero) + FutureBuilder( + future: ChangeNowExchange().getEstimate( + from!, + to!, + reversed ? toAmount! : fromAmount!, + fixedRate, + reversed, + ), + builder: (context, + AsyncSnapshot> + snapshot) { + if (snapshot.connectionState == + ConnectionState.done && + snapshot.hasData) { + final estimate = snapshot.data?.value; + if (estimate != null) { + Decimal rate; + if (estimate.reversed) { + rate = + (toAmount! / estimate.estimatedAmount) + .toDecimal( + scaleOnInfinitePrecision: 12); + } else { + rate = + (estimate.estimatedAmount / fromAmount!) + .toDecimal( + scaleOnInfinitePrecision: 12); + } + return Text( + "1 ${from!.toUpperCase()} ~ ${Format.localizedStringAsFixed( + value: rate, + locale: ref.watch( + localeServiceChangeNotifierProvider + .select((value) => value.locale), + ), + decimalPlaces: to!.toUpperCase() == + Coin.monero.ticker.toUpperCase() + ? Constants.decimalPlacesMonero + : Constants.decimalPlaces, + )} ${to!.toUpperCase()}", + style: STextStyles.itemSubtitle12(context) + .copyWith( + color: Theme.of(context) + .extension()! + .textSubtitle1, + ), + ); + } else { + Logging.instance.log( + "$runtimeType failed to fetch rate for ChangeNOW: ${snapshot.data}", + level: LogLevel.Warning, + ); + return Text( + "Failed to fetch rate", + style: STextStyles.itemSubtitle12(context) + .copyWith( + color: Theme.of(context) + .extension()! + .textSubtitle1, + ), + ); + } + } else { + return AnimatedText( + stringsToLoopThrough: const [ + "Loading", + "Loading.", + "Loading..", + "Loading...", + ], + style: STextStyles.itemSubtitle12(context) + .copyWith( + color: Theme.of(context) + .extension()! + .textSubtitle1, + ), + ); + } + }, + ), + if (!(from != null && + to != null && + toAmount != null && + toAmount! > Decimal.zero && + fromAmount != null && + fromAmount! > Decimal.zero)) + Text( + "n/a", + style: STextStyles.itemSubtitle12(context).copyWith( + color: Theme.of(context) + .extension()! + .textSubtitle1, + ), ), - ), ], ), ), @@ -163,14 +266,106 @@ class ExchangeProviderOptions extends ConsumerWidget { .textDark2, ), ), - Text( - SimpleSwapExchange.exchangeName, - style: STextStyles.itemSubtitle12(context).copyWith( - color: Theme.of(context) - .extension()! - .textSubtitle1, + if (from != null && + to != null && + toAmount != null && + toAmount! > Decimal.zero && + fromAmount != null && + fromAmount! > Decimal.zero) + FutureBuilder( + future: SimpleSwapExchange().getEstimate( + from!, + to!, + // reversed ? toAmount! : fromAmount!, + fromAmount!, + fixedRate, + // reversed, + false, + ), + builder: (context, + AsyncSnapshot> + snapshot) { + if (snapshot.connectionState == + ConnectionState.done && + snapshot.hasData) { + final estimate = snapshot.data?.value; + if (estimate != null) { + Decimal rate = (estimate.estimatedAmount / + fromAmount!) + .toDecimal(scaleOnInfinitePrecision: 12); + + return Text( + "1 ${from!.toUpperCase()} ~ ${Format.localizedStringAsFixed( + value: rate, + locale: ref.watch( + localeServiceChangeNotifierProvider + .select((value) => value.locale), + ), + decimalPlaces: to!.toUpperCase() == + Coin.monero.ticker.toUpperCase() + ? Constants.decimalPlacesMonero + : Constants.decimalPlaces, + )} ${to!.toUpperCase()}", + style: STextStyles.itemSubtitle12(context) + .copyWith( + color: Theme.of(context) + .extension()! + .textSubtitle1, + ), + ); + } else { + Logging.instance.log( + "$runtimeType failed to fetch rate for SimpleSwap: ${snapshot.data}", + level: LogLevel.Warning, + ); + return Text( + "Failed to fetch rate", + style: STextStyles.itemSubtitle12(context) + .copyWith( + color: Theme.of(context) + .extension()! + .textSubtitle1, + ), + ); + } + } else { + return AnimatedText( + stringsToLoopThrough: const [ + "Loading", + "Loading.", + "Loading..", + "Loading...", + ], + style: STextStyles.itemSubtitle12(context) + .copyWith( + color: Theme.of(context) + .extension()! + .textSubtitle1, + ), + ); + } + }, + ), + // if (!(from != null && + // to != null && + // (reversed + // ? toAmount != null && toAmount! > Decimal.zero + // : fromAmount != null && + // fromAmount! > Decimal.zero))) + if (!(from != null && + to != null && + toAmount != null && + toAmount! > Decimal.zero && + fromAmount != null && + fromAmount! > Decimal.zero)) + Text( + "n/a", + style: STextStyles.itemSubtitle12(context).copyWith( + color: Theme.of(context) + .extension()! + .textSubtitle1, + ), ), - ), ], ), ),