mirror of
https://github.com/cypherstack/stack_wallet.git
synced 2025-01-22 02:24:30 +00:00
fiat amount string formatting and parsing and more WIP usages thereof
This commit is contained in:
parent
7bcfc87f4d
commit
f88d7f200c
4 changed files with 74 additions and 67 deletions
|
@ -10,7 +10,6 @@
|
||||||
|
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
import 'dart:math';
|
|
||||||
|
|
||||||
import 'package:bip47/bip47.dart';
|
import 'package:bip47/bip47.dart';
|
||||||
import 'package:cw_core/monero_transaction_priority.dart';
|
import 'package:cw_core/monero_transaction_priority.dart';
|
||||||
|
@ -127,27 +126,13 @@ class _SendViewState extends ConsumerState<SendView> {
|
||||||
|
|
||||||
void _cryptoAmountChanged() async {
|
void _cryptoAmountChanged() async {
|
||||||
if (!_cryptoAmountChangeLock) {
|
if (!_cryptoAmountChangeLock) {
|
||||||
String cryptoAmount = cryptoAmountController.text;
|
final cryptoAmount = ref.read(pAmountFormatter(coin)).tryParse(
|
||||||
if (cryptoAmount.isNotEmpty &&
|
cryptoAmountController.text,
|
||||||
cryptoAmount != "." &&
|
locale: ref.read(localeServiceChangeNotifierProvider).locale,
|
||||||
cryptoAmount != ",") {
|
coin: coin,
|
||||||
if (cryptoAmount.startsWith("~")) {
|
);
|
||||||
cryptoAmount = cryptoAmount.substring(1);
|
if (cryptoAmount != null) {
|
||||||
}
|
_amountToSend = cryptoAmount;
|
||||||
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);
|
|
||||||
if (_cachedAmountToSend != null &&
|
if (_cachedAmountToSend != null &&
|
||||||
_cachedAmountToSend == _amountToSend) {
|
_cachedAmountToSend == _amountToSend) {
|
||||||
return;
|
return;
|
||||||
|
@ -1623,17 +1608,11 @@ class _SendViewState extends ConsumerState<SendView> {
|
||||||
: oldValue),
|
: oldValue),
|
||||||
],
|
],
|
||||||
onChanged: (baseAmountString) {
|
onChanged: (baseAmountString) {
|
||||||
if (baseAmountString.isNotEmpty &&
|
final baseAmount = Amount.tryParseFiatString(
|
||||||
baseAmountString != "." &&
|
baseAmountString,
|
||||||
baseAmountString != ",") {
|
locale: locale,
|
||||||
final Amount baseAmount =
|
);
|
||||||
baseAmountString.contains(",")
|
if (baseAmount != null) {
|
||||||
? Decimal.parse(baseAmountString
|
|
||||||
.replaceFirst(",", "."))
|
|
||||||
.toAmount(fractionDigits: 2)
|
|
||||||
: Decimal.parse(baseAmountString)
|
|
||||||
.toAmount(fractionDigits: 2);
|
|
||||||
|
|
||||||
final Decimal _price = ref
|
final Decimal _price = ref
|
||||||
.read(priceAnd24hChangeNotifierProvider)
|
.read(priceAnd24hChangeNotifierProvider)
|
||||||
.getPrice(coin)
|
.getPrice(coin)
|
||||||
|
|
|
@ -218,16 +218,11 @@ class _TokenSendViewState extends ConsumerState<TokenSendView> {
|
||||||
}
|
}
|
||||||
|
|
||||||
void _onFiatAmountFieldChanged(String baseAmountString) {
|
void _onFiatAmountFieldChanged(String baseAmountString) {
|
||||||
if (baseAmountString.isNotEmpty &&
|
final baseAmount = Amount.tryParseFiatString(
|
||||||
baseAmountString != "." &&
|
baseAmountString,
|
||||||
baseAmountString != ",") {
|
locale: ref.read(localeServiceChangeNotifierProvider).locale,
|
||||||
final baseAmount = Amount.fromDecimal(
|
);
|
||||||
baseAmountString.contains(",")
|
if (baseAmount != null) {
|
||||||
? Decimal.parse(baseAmountString.replaceFirst(",", "."))
|
|
||||||
: Decimal.parse(baseAmountString),
|
|
||||||
fractionDigits: tokenContract.decimals,
|
|
||||||
);
|
|
||||||
|
|
||||||
final _price = ref
|
final _price = ref
|
||||||
.read(priceAnd24hChangeNotifierProvider)
|
.read(priceAnd24hChangeNotifierProvider)
|
||||||
.getTokenPrice(tokenContract.address)
|
.getTokenPrice(tokenContract.address)
|
||||||
|
@ -272,22 +267,14 @@ class _TokenSendViewState extends ConsumerState<TokenSendView> {
|
||||||
|
|
||||||
void _cryptoAmountChanged() async {
|
void _cryptoAmountChanged() async {
|
||||||
if (!_cryptoAmountChangeLock) {
|
if (!_cryptoAmountChangeLock) {
|
||||||
String cryptoAmount = cryptoAmountController.text;
|
final cryptoAmount = ref.read(pAmountFormatter(coin)).tryParse(
|
||||||
if (cryptoAmount.isNotEmpty &&
|
cryptoAmountController.text,
|
||||||
cryptoAmount != "." &&
|
locale: ref.read(localeServiceChangeNotifierProvider).locale,
|
||||||
cryptoAmount != ",") {
|
coin: coin,
|
||||||
if (cryptoAmount.startsWith("~")) {
|
ethContract: tokenContract,
|
||||||
cryptoAmount = cryptoAmount.substring(1);
|
);
|
||||||
}
|
if (cryptoAmount != null) {
|
||||||
if (cryptoAmount.contains(" ")) {
|
_amountToSend = cryptoAmount;
|
||||||
cryptoAmount = cryptoAmount.split(" ").first;
|
|
||||||
}
|
|
||||||
|
|
||||||
_amountToSend = Amount.fromDecimal(
|
|
||||||
cryptoAmount.contains(",")
|
|
||||||
? Decimal.parse(cryptoAmount.replaceFirst(",", "."))
|
|
||||||
: Decimal.parse(cryptoAmount),
|
|
||||||
fractionDigits: tokenContract.decimals);
|
|
||||||
if (_cachedAmountToSend != null &&
|
if (_cachedAmountToSend != null &&
|
||||||
_cachedAmountToSend == _amountToSend) {
|
_cachedAmountToSend == _amountToSend) {
|
||||||
return;
|
return;
|
||||||
|
@ -1185,7 +1172,7 @@ class _TokenSendViewState extends ConsumerState<TokenSendView> {
|
||||||
ConnectionState.done &&
|
ConnectionState.done &&
|
||||||
snapshot.hasData) {
|
snapshot.hasData) {
|
||||||
return Text(
|
return Text(
|
||||||
"~${snapshot.data! as String}",
|
"~${snapshot.data!}",
|
||||||
style:
|
style:
|
||||||
STextStyles.itemSubtitle(
|
STextStyles.itemSubtitle(
|
||||||
context),
|
context),
|
||||||
|
|
|
@ -32,6 +32,39 @@ class Amount {
|
||||||
: assert(fractionDigits >= 0),
|
: assert(fractionDigits >= 0),
|
||||||
_value = amount.shift(fractionDigits).toBigInt();
|
_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 ===============================================
|
// ======= Instance properties ===============================================
|
||||||
|
|
||||||
|
@ -67,15 +100,23 @@ class Amount {
|
||||||
}) {
|
}) {
|
||||||
final wholeNumber = decimal.truncate();
|
final wholeNumber = decimal.truncate();
|
||||||
|
|
||||||
final String separator =
|
// get number symbols for decimal place and group separator
|
||||||
(numberFormatSymbols[locale] as NumberSymbols?)?.DECIMAL_SEP ??
|
final numberSymbols = numberFormatSymbols[locale] as NumberSymbols? ??
|
||||||
(numberFormatSymbols[locale.substring(0, 2)] as NumberSymbols?)
|
numberFormatSymbols[locale.substring(0, 2)] as NumberSymbols?;
|
||||||
?.DECIMAL_SEP ??
|
|
||||||
".";
|
final String separator = numberSymbols?.DECIMAL_SEP ?? ".";
|
||||||
|
|
||||||
final fraction = decimal - wholeNumber;
|
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({
|
// String localizedStringAsFixed({
|
||||||
// required String locale,
|
// required String locale,
|
||||||
|
|
|
@ -64,7 +64,7 @@ class AmountFormatter {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Amount? amountFrom(
|
Amount? tryParse(
|
||||||
String string, {
|
String string, {
|
||||||
required String locale,
|
required String locale,
|
||||||
required Coin coin,
|
required Coin coin,
|
||||||
|
|
Loading…
Reference in a new issue