fiat amount string formatting and parsing and more WIP usages thereof

This commit is contained in:
julian 2023-06-16 13:42:37 -06:00
parent 7bcfc87f4d
commit f88d7f200c
4 changed files with 74 additions and 67 deletions

View file

@ -10,7 +10,6 @@
import 'dart:async';
import 'dart:io';
import 'dart:math';
import 'package:bip47/bip47.dart';
import 'package:cw_core/monero_transaction_priority.dart';
@ -127,27 +126,13 @@ class _SendViewState extends ConsumerState<SendView> {
void _cryptoAmountChanged() async {
if (!_cryptoAmountChangeLock) {
String cryptoAmount = cryptoAmountController.text;
if (cryptoAmount.isNotEmpty &&
cryptoAmount != "." &&
cryptoAmount != ",") {
if (cryptoAmount.startsWith("~")) {
cryptoAmount = cryptoAmount.substring(1);
}
if (cryptoAmount.contains(" ")) {
cryptoAmount = cryptoAmount.split(" ").first;
}
// ensure we don't shift past minimum atomic value
final shift = min(ref.read(pAmountUnit(coin)).shift, coin.decimals);
_amountToSend = cryptoAmount.contains(",")
? Decimal.parse(cryptoAmount.replaceFirst(",", "."))
.shift(0 - shift)
.toAmount(fractionDigits: coin.decimals)
: Decimal.parse(cryptoAmount)
.shift(0 - shift)
.toAmount(fractionDigits: coin.decimals);
final cryptoAmount = ref.read(pAmountFormatter(coin)).tryParse(
cryptoAmountController.text,
locale: ref.read(localeServiceChangeNotifierProvider).locale,
coin: coin,
);
if (cryptoAmount != null) {
_amountToSend = cryptoAmount;
if (_cachedAmountToSend != null &&
_cachedAmountToSend == _amountToSend) {
return;
@ -1623,17 +1608,11 @@ class _SendViewState extends ConsumerState<SendView> {
: oldValue),
],
onChanged: (baseAmountString) {
if (baseAmountString.isNotEmpty &&
baseAmountString != "." &&
baseAmountString != ",") {
final Amount baseAmount =
baseAmountString.contains(",")
? Decimal.parse(baseAmountString
.replaceFirst(",", "."))
.toAmount(fractionDigits: 2)
: Decimal.parse(baseAmountString)
.toAmount(fractionDigits: 2);
final baseAmount = Amount.tryParseFiatString(
baseAmountString,
locale: locale,
);
if (baseAmount != null) {
final Decimal _price = ref
.read(priceAnd24hChangeNotifierProvider)
.getPrice(coin)

View file

@ -218,16 +218,11 @@ class _TokenSendViewState extends ConsumerState<TokenSendView> {
}
void _onFiatAmountFieldChanged(String baseAmountString) {
if (baseAmountString.isNotEmpty &&
baseAmountString != "." &&
baseAmountString != ",") {
final baseAmount = Amount.fromDecimal(
baseAmountString.contains(",")
? Decimal.parse(baseAmountString.replaceFirst(",", "."))
: Decimal.parse(baseAmountString),
fractionDigits: tokenContract.decimals,
);
final baseAmount = Amount.tryParseFiatString(
baseAmountString,
locale: ref.read(localeServiceChangeNotifierProvider).locale,
);
if (baseAmount != null) {
final _price = ref
.read(priceAnd24hChangeNotifierProvider)
.getTokenPrice(tokenContract.address)
@ -272,22 +267,14 @@ class _TokenSendViewState extends ConsumerState<TokenSendView> {
void _cryptoAmountChanged() async {
if (!_cryptoAmountChangeLock) {
String cryptoAmount = cryptoAmountController.text;
if (cryptoAmount.isNotEmpty &&
cryptoAmount != "." &&
cryptoAmount != ",") {
if (cryptoAmount.startsWith("~")) {
cryptoAmount = cryptoAmount.substring(1);
}
if (cryptoAmount.contains(" ")) {
cryptoAmount = cryptoAmount.split(" ").first;
}
_amountToSend = Amount.fromDecimal(
cryptoAmount.contains(",")
? Decimal.parse(cryptoAmount.replaceFirst(",", "."))
: Decimal.parse(cryptoAmount),
fractionDigits: tokenContract.decimals);
final cryptoAmount = ref.read(pAmountFormatter(coin)).tryParse(
cryptoAmountController.text,
locale: ref.read(localeServiceChangeNotifierProvider).locale,
coin: coin,
ethContract: tokenContract,
);
if (cryptoAmount != null) {
_amountToSend = cryptoAmount;
if (_cachedAmountToSend != null &&
_cachedAmountToSend == _amountToSend) {
return;
@ -1185,7 +1172,7 @@ class _TokenSendViewState extends ConsumerState<TokenSendView> {
ConnectionState.done &&
snapshot.hasData) {
return Text(
"~${snapshot.data! as String}",
"~${snapshot.data!}",
style:
STextStyles.itemSubtitle(
context),

View file

@ -32,6 +32,39 @@ class Amount {
: assert(fractionDigits >= 0),
_value = amount.shift(fractionDigits).toBigInt();
static Amount? tryParseFiatString(
String value, {
required String locale,
}) {
final parts = value.split(" ");
if (parts.first.isEmpty) {
return null;
}
String str = parts.first;
if (str.startsWith(RegExp(r'[+-]'))) {
str = str.substring(1);
}
if (str.isEmpty) {
return null;
}
// get number symbols for decimal place and group separator
final numberSymbols = numberFormatSymbols[locale] as NumberSymbols? ??
numberFormatSymbols[locale.substring(0, 2)] as NumberSymbols?;
final groupSeparator = numberSymbols?.GROUP_SEP ?? ",";
final decimalSeparator = numberSymbols?.DECIMAL_SEP ?? ".";
str = str.replaceAll(groupSeparator, "");
final decimalString = str.replaceFirst(decimalSeparator, ".");
return Decimal.tryParse(decimalString)?.toAmount(fractionDigits: 2);
}
// ===========================================================================
// ======= Instance properties ===============================================
@ -67,15 +100,23 @@ class Amount {
}) {
final wholeNumber = decimal.truncate();
final String separator =
(numberFormatSymbols[locale] as NumberSymbols?)?.DECIMAL_SEP ??
(numberFormatSymbols[locale.substring(0, 2)] as NumberSymbols?)
?.DECIMAL_SEP ??
".";
// get number symbols for decimal place and group separator
final numberSymbols = numberFormatSymbols[locale] as NumberSymbols? ??
numberFormatSymbols[locale.substring(0, 2)] as NumberSymbols?;
final String separator = numberSymbols?.DECIMAL_SEP ?? ".";
final fraction = decimal - wholeNumber;
return "${wholeNumber.toStringAsFixed(0)}$separator${fraction.toStringAsFixed(2).substring(2)}";
String wholeNumberString = wholeNumber.toStringAsFixed(0);
// insert group separator
final regex = RegExp(r'\B(?=(\d{3})+(?!\d))');
wholeNumberString = wholeNumberString.replaceAllMapped(
regex,
(m) => "${m.group(0)}${numberSymbols?.GROUP_SEP ?? ","}",
);
return "$wholeNumberString$separator${fraction.toStringAsFixed(2).substring(2)}";
}
// String localizedStringAsFixed({
// required String locale,

View file

@ -64,7 +64,7 @@ class AmountFormatter {
);
}
Amount? amountFrom(
Amount? tryParse(
String string, {
required String locale,
required Coin coin,