WIP show rates

This commit is contained in:
julian 2022-10-04 13:10:44 -06:00
parent 2c8ba8405f
commit a37b518f7e
3 changed files with 251 additions and 30 deletions

View file

@ -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/models/exchange/response_objects/fixed_rate_market.dart';
import 'package:stackwallet/pages/exchange_view/sub_widgets/exchange_rate_sheet.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.dart';
import 'package:stackwallet/services/exchange/simpleswap/simpleswap_exchange.dart';
import 'package:stackwallet/utilities/logger.dart'; import 'package:stackwallet/utilities/logger.dart';
class ExchangeFormState extends ChangeNotifier { class ExchangeFormState extends ChangeNotifier {
@ -184,7 +185,7 @@ class ExchangeFormState extends ChangeNotifier {
); );
debugPrint( 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) { if (shouldNotifyListeners) {
notifyListeners(); notifyListeners();
@ -212,7 +213,7 @@ class ExchangeFormState extends ChangeNotifier {
); );
debugPrint( 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) { if (shouldNotifyListeners) {
notifyListeners(); notifyListeners();
} }
@ -254,15 +255,23 @@ class ExchangeFormState extends ChangeNotifier {
} }
void _onExchangeTypeChanged() { void _onExchangeTypeChanged() {
print("_onExchangeTypeChanged"); updateRanges(shouldNotifyListeners: true).then(
(_) => updateEstimate(
shouldNotifyListeners: true,
reversed: reversed,
),
);
} }
Future<void> updateRanges({required bool shouldNotifyListeners}) async { Future<void> updateRanges({required bool shouldNotifyListeners}) async {
if (exchange?.name == SimpleSwapExchange.exchangeName) {
reversed = false;
}
final _fromTicker = reversed ? toTicker : fromTicker; final _fromTicker = reversed ? toTicker : fromTicker;
final _toTicker = reversed ? fromTicker : toTicker; final _toTicker = reversed ? fromTicker : toTicker;
if (_fromTicker == null || _toTicker == null) { if (_fromTicker == null || _toTicker == null) {
Logging.instance.log( 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, level: LogLevel.Info,
); );
return; return;
@ -275,7 +284,7 @@ class ExchangeFormState extends ChangeNotifier {
if (response?.value == null) { if (response?.value == null) {
Logging.instance.log( Logging.instance.log(
"Tried to $runtimeType.updateRanges where response: $response", "Tried to $runtimeType.updateRanges for: $exchange where response: $response",
level: LogLevel.Info, level: LogLevel.Info,
); );
return; return;
@ -286,7 +295,8 @@ class ExchangeFormState extends ChangeNotifier {
minAmount = range.min; minAmount = range.min;
maxAmount = range.max; maxAmount = range.max;
debugPrint("updated range for $_fromTicker-$_toTicker: $range"); debugPrint(
"updated range for: $exchange for $_fromTicker-$_toTicker: $range");
if (shouldNotifyListeners) { if (shouldNotifyListeners) {
notifyListeners(); notifyListeners();
@ -297,13 +307,16 @@ class ExchangeFormState extends ChangeNotifier {
required bool shouldNotifyListeners, required bool shouldNotifyListeners,
required bool reversed, required bool reversed,
}) async { }) async {
if (exchange?.name == SimpleSwapExchange.exchangeName) {
reversed = false;
}
final amount = reversed ? toAmount : fromAmount; final amount = reversed ? toAmount : fromAmount;
if (fromTicker == null || if (fromTicker == null ||
toTicker == null || toTicker == null ||
amount == null || amount == null ||
amount <= Decimal.zero) { amount <= Decimal.zero) {
Logging.instance.log( 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, level: LogLevel.Info,
); );
return; return;
@ -318,7 +331,7 @@ class ExchangeFormState extends ChangeNotifier {
if (response?.value == null) { if (response?.value == null) {
Logging.instance.log( Logging.instance.log(
"Tried to $runtimeType.updateEstimate where response: $response", "Tried to $runtimeType.updateEstimate for: $exchange where response: $response",
level: LogLevel.Info, level: LogLevel.Info,
); );
return; return;
@ -334,7 +347,8 @@ class ExchangeFormState extends ChangeNotifier {
rate = (toAmount! / fromAmount!).toDecimal(scaleOnInfinitePrecision: 12); rate = (toAmount! / fromAmount!).toDecimal(scaleOnInfinitePrecision: 12);
debugPrint("updated estimate for $fromTicker-$toTicker: $estimate"); debugPrint(
"updated estimate for: $exchange for $fromTicker-$toTicker: $estimate");
if (shouldNotifyListeners) { if (shouldNotifyListeners) {
notifyListeners(); notifyListeners();

View file

@ -294,8 +294,7 @@ class _ExchangeFormState extends ConsumerState<ExchangeForm> {
), ),
); );
if (ref.watch(prefsChangeNotifierProvider if (ref.read(prefsChangeNotifierProvider).exchangeRateType ==
.select((pref) => pref.exchangeRateType)) ==
ExchangeRateType.estimated) { ExchangeRateType.estimated) {
await ref.read(exchangeFormStateProvider).swap(); await ref.read(exchangeFormStateProvider).swap();
} else { } else {
@ -912,6 +911,10 @@ class _ExchangeFormState extends ConsumerState<ExchangeForm> {
Widget build(BuildContext context) { Widget build(BuildContext context) {
debugPrint("BUILD: $runtimeType"); debugPrint("BUILD: $runtimeType");
ref.listen<String>(currentExchangeNameStateProvider, (previous, next) {
ref.read(exchangeFormStateProvider).exchange = ref.read(exchangeProvider);
});
final isEstimated = ref.watch(prefsChangeNotifierProvider final isEstimated = ref.watch(prefsChangeNotifierProvider
.select((pref) => pref.exchangeRateType)) == .select((pref) => pref.exchangeRateType)) ==
ExchangeRateType.estimated; ExchangeRateType.estimated;
@ -920,7 +923,12 @@ class _ExchangeFormState extends ConsumerState<ExchangeForm> {
exchangeFormStateProvider.select((value) => value.toAmountString), exchangeFormStateProvider.select((value) => value.toAmountString),
(previous, String next) { (previous, String next) {
if (!_receiveFocusNode.hasFocus) { 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"); debugPrint("RECEIVE AMOUNT LISTENER ACTIVATED");
if (_swapLock) { if (_swapLock) {
_sendController.text = _sendController.text =
@ -1164,8 +1172,10 @@ class _ExchangeFormState extends ConsumerState<ExchangeForm> {
focusNode: _receiveFocusNode, focusNode: _receiveFocusNode,
controller: _receiveController, controller: _receiveController,
readOnly: ref.watch(prefsChangeNotifierProvider readOnly: ref.watch(prefsChangeNotifierProvider
.select((value) => value.exchangeRateType)) == .select((value) => value.exchangeRateType)) ==
ExchangeRateType.estimated, ExchangeRateType.estimated ||
ref.watch(exchangeProvider).name ==
SimpleSwapExchange.exchangeName,
onTap: () { onTap: () {
if (!(ref.read(prefsChangeNotifierProvider).exchangeRateType == if (!(ref.read(prefsChangeNotifierProvider).exchangeRateType ==
ExchangeRateType.estimated) && ExchangeRateType.estimated) &&
@ -1306,8 +1316,10 @@ class _ExchangeFormState extends ConsumerState<ExchangeForm> {
height: 8, height: 8,
), ),
ExchangeProviderOptions( ExchangeProviderOptions(
fromAmount: null, from: ref.watch(exchangeFormStateProvider).fromTicker,
toAmount: null, to: ref.watch(exchangeFormStateProvider).toTicker,
fromAmount: ref.watch(exchangeFormStateProvider).fromAmount,
toAmount: ref.watch(exchangeFormStateProvider).toAmount,
fixedRate: ref.watch(prefsChangeNotifierProvider fixedRate: ref.watch(prefsChangeNotifierProvider
.select((value) => value.exchangeRateType)) == .select((value) => value.exchangeRateType)) ==
ExchangeRateType.fixed, ExchangeRateType.fixed,

View file

@ -2,23 +2,34 @@ 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/models/exchange/response_objects/estimate.dart';
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_response.dart';
import 'package:stackwallet/services/exchange/simpleswap/simpleswap_exchange.dart'; import 'package:stackwallet/services/exchange/simpleswap/simpleswap_exchange.dart';
import 'package:stackwallet/utilities/assets.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/text_styles.dart';
import 'package:stackwallet/utilities/theme/stack_colors.dart'; import 'package:stackwallet/utilities/theme/stack_colors.dart';
import 'package:stackwallet/widgets/animated_text.dart';
import 'package:stackwallet/widgets/rounded_white_container.dart'; import 'package:stackwallet/widgets/rounded_white_container.dart';
class ExchangeProviderOptions extends ConsumerWidget { class ExchangeProviderOptions extends ConsumerWidget {
const ExchangeProviderOptions({ const ExchangeProviderOptions({
Key? key, Key? key,
required this.from,
required this.to,
required this.fromAmount, required this.fromAmount,
required this.toAmount, required this.toAmount,
required this.fixedRate, required this.fixedRate,
required this.reversed, required this.reversed,
}) : super(key: key); }) : super(key: key);
final String? from;
final String? to;
final Decimal? fromAmount; final Decimal? fromAmount;
final Decimal? toAmount; final Decimal? toAmount;
final bool fixedRate; final bool fixedRate;
@ -87,14 +98,106 @@ class ExchangeProviderOptions extends ConsumerWidget {
.textDark2, .textDark2,
), ),
), ),
Text( if (from != null &&
ChangeNowExchange.exchangeName, to != null &&
style: STextStyles.itemSubtitle12(context).copyWith( toAmount != null &&
color: Theme.of(context) toAmount! > Decimal.zero &&
.extension<StackColors>()! fromAmount != null &&
.textSubtitle1, fromAmount! > Decimal.zero)
FutureBuilder(
future: ChangeNowExchange().getEstimate(
from!,
to!,
reversed ? toAmount! : fromAmount!,
fixedRate,
reversed,
),
builder: (context,
AsyncSnapshot<ExchangeResponse<Estimate>>
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<StackColors>()!
.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<StackColors>()!
.textSubtitle1,
),
);
}
} else {
return AnimatedText(
stringsToLoopThrough: const [
"Loading",
"Loading.",
"Loading..",
"Loading...",
],
style: STextStyles.itemSubtitle12(context)
.copyWith(
color: Theme.of(context)
.extension<StackColors>()!
.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<StackColors>()!
.textSubtitle1,
),
), ),
),
], ],
), ),
), ),
@ -163,14 +266,106 @@ class ExchangeProviderOptions extends ConsumerWidget {
.textDark2, .textDark2,
), ),
), ),
Text( if (from != null &&
SimpleSwapExchange.exchangeName, to != null &&
style: STextStyles.itemSubtitle12(context).copyWith( toAmount != null &&
color: Theme.of(context) toAmount! > Decimal.zero &&
.extension<StackColors>()! fromAmount != null &&
.textSubtitle1, fromAmount! > Decimal.zero)
FutureBuilder(
future: SimpleSwapExchange().getEstimate(
from!,
to!,
// reversed ? toAmount! : fromAmount!,
fromAmount!,
fixedRate,
// reversed,
false,
),
builder: (context,
AsyncSnapshot<ExchangeResponse<Estimate>>
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<StackColors>()!
.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<StackColors>()!
.textSubtitle1,
),
);
}
} else {
return AnimatedText(
stringsToLoopThrough: const [
"Loading",
"Loading.",
"Loading..",
"Loading...",
],
style: STextStyles.itemSubtitle12(context)
.copyWith(
color: Theme.of(context)
.extension<StackColors>()!
.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<StackColors>()!
.textSubtitle1,
),
), ),
),
], ],
), ),
), ),