mirror of
https://github.com/cypherstack/stack_wallet.git
synced 2024-12-23 11:59:30 +00:00
Merge remote-tracking branch 'origin_SW/staging' into custom_fee_selection
This commit is contained in:
commit
f60dee0304
12 changed files with 448 additions and 150 deletions
|
@ -463,6 +463,12 @@ class _MaterialAppWithThemeState extends ConsumerState<MaterialAppWithTheme>
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void didChangeLocales(List<Locale>? locales) {
|
||||||
|
ref.read(localeServiceChangeNotifierProvider).loadLocale();
|
||||||
|
super.didChangeLocales(locales);
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void didChangeAppLifecycleState(AppLifecycleState state) async {
|
void didChangeAppLifecycleState(AppLifecycleState state) async {
|
||||||
debugPrint("didChangeAppLifecycleState: ${state.name}");
|
debugPrint("didChangeAppLifecycleState: ${state.name}");
|
||||||
|
|
|
@ -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';
|
||||||
|
@ -41,6 +40,7 @@ import 'package:stackwallet/themes/stack_colors.dart';
|
||||||
import 'package:stackwallet/utilities/address_utils.dart';
|
import 'package:stackwallet/utilities/address_utils.dart';
|
||||||
import 'package:stackwallet/utilities/amount/amount.dart';
|
import 'package:stackwallet/utilities/amount/amount.dart';
|
||||||
import 'package:stackwallet/utilities/amount/amount_formatter.dart';
|
import 'package:stackwallet/utilities/amount/amount_formatter.dart';
|
||||||
|
import 'package:stackwallet/utilities/amount/amount_input_formatter.dart';
|
||||||
import 'package:stackwallet/utilities/amount/amount_unit.dart';
|
import 'package:stackwallet/utilities/amount/amount_unit.dart';
|
||||||
import 'package:stackwallet/utilities/assets.dart';
|
import 'package:stackwallet/utilities/assets.dart';
|
||||||
import 'package:stackwallet/utilities/barcode_scanner_interface.dart';
|
import 'package:stackwallet/utilities/barcode_scanner_interface.dart';
|
||||||
|
@ -128,27 +128,11 @@ 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 != "." &&
|
);
|
||||||
cryptoAmount != ",") {
|
if (cryptoAmount != null) {
|
||||||
if (cryptoAmount.startsWith("~")) {
|
_amountToSend = cryptoAmount;
|
||||||
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);
|
|
||||||
if (_cachedAmountToSend != null &&
|
if (_cachedAmountToSend != null &&
|
||||||
_cachedAmountToSend == _amountToSend) {
|
_cachedAmountToSend == _amountToSend) {
|
||||||
return;
|
return;
|
||||||
|
@ -1567,13 +1551,21 @@ class _SendViewState extends ConsumerState<SendView> {
|
||||||
),
|
),
|
||||||
textAlign: TextAlign.right,
|
textAlign: TextAlign.right,
|
||||||
inputFormatters: [
|
inputFormatters: [
|
||||||
|
AmountInputFormatter(
|
||||||
|
decimals: coin.decimals,
|
||||||
|
unit: ref.watch(pAmountUnit(coin)),
|
||||||
|
locale: locale,
|
||||||
|
),
|
||||||
|
|
||||||
// regex to validate a crypto amount with 8 decimal places
|
// regex to validate a crypto amount with 8 decimal places
|
||||||
TextInputFormatter.withFunction((oldValue,
|
// TextInputFormatter.withFunction((oldValue,
|
||||||
newValue) =>
|
// newValue) =>
|
||||||
RegExp(r'^([0-9]*[,.]?[0-9]{0,8}|[,.][0-9]{0,8})$')
|
// // RegExp(r'^([0-9]*[,.]?[0-9]{0,8}|[,.][0-9]{0,8})$')
|
||||||
.hasMatch(newValue.text)
|
// // RegExp(r'^\d{1,3}([,\.]\d+)?|[,\.\d]+$')
|
||||||
? newValue
|
// getAmountRegex(locale, coin.decimals)
|
||||||
: oldValue),
|
// .hasMatch(newValue.text)
|
||||||
|
// ? newValue
|
||||||
|
// : oldValue),
|
||||||
],
|
],
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
contentPadding: const EdgeInsets.only(
|
contentPadding: const EdgeInsets.only(
|
||||||
|
@ -1628,26 +1620,25 @@ class _SendViewState extends ConsumerState<SendView> {
|
||||||
),
|
),
|
||||||
textAlign: TextAlign.right,
|
textAlign: TextAlign.right,
|
||||||
inputFormatters: [
|
inputFormatters: [
|
||||||
|
AmountInputFormatter(
|
||||||
|
decimals: 2,
|
||||||
|
locale: locale,
|
||||||
|
),
|
||||||
// regex to validate a fiat amount with 2 decimal places
|
// regex to validate a fiat amount with 2 decimal places
|
||||||
TextInputFormatter.withFunction((oldValue,
|
// TextInputFormatter.withFunction((oldValue,
|
||||||
newValue) =>
|
// newValue) =>
|
||||||
RegExp(r'^([0-9]*[,.]?[0-9]{0,2}|[,.][0-9]{0,2})$')
|
// // RegExp(r'^([0-9]*[,.]?[0-9]{0,2}|[,.][0-9]{0,2})$')
|
||||||
.hasMatch(newValue.text)
|
// getAmountRegex(locale, 2)
|
||||||
? newValue
|
// .hasMatch(newValue.text)
|
||||||
: oldValue),
|
// ? newValue
|
||||||
|
// : 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)
|
||||||
|
|
|
@ -31,6 +31,7 @@ import 'package:stackwallet/themes/stack_colors.dart';
|
||||||
import 'package:stackwallet/utilities/address_utils.dart';
|
import 'package:stackwallet/utilities/address_utils.dart';
|
||||||
import 'package:stackwallet/utilities/amount/amount.dart';
|
import 'package:stackwallet/utilities/amount/amount.dart';
|
||||||
import 'package:stackwallet/utilities/amount/amount_formatter.dart';
|
import 'package:stackwallet/utilities/amount/amount_formatter.dart';
|
||||||
|
import 'package:stackwallet/utilities/amount/amount_input_formatter.dart';
|
||||||
import 'package:stackwallet/utilities/assets.dart';
|
import 'package:stackwallet/utilities/assets.dart';
|
||||||
import 'package:stackwallet/utilities/barcode_scanner_interface.dart';
|
import 'package:stackwallet/utilities/barcode_scanner_interface.dart';
|
||||||
import 'package:stackwallet/utilities/clipboard_interface.dart';
|
import 'package:stackwallet/utilities/clipboard_interface.dart';
|
||||||
|
@ -218,16 +219,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 +268,12 @@ 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 != "." &&
|
ethContract: tokenContract,
|
||||||
cryptoAmount != ",") {
|
);
|
||||||
if (cryptoAmount.startsWith("~")) {
|
if (cryptoAmount != null) {
|
||||||
cryptoAmount = cryptoAmount.substring(1);
|
_amountToSend = cryptoAmount;
|
||||||
}
|
|
||||||
if (cryptoAmount.contains(" ")) {
|
|
||||||
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;
|
||||||
|
@ -952,13 +938,18 @@ class _TokenSendViewState extends ConsumerState<TokenSendView> {
|
||||||
),
|
),
|
||||||
textAlign: TextAlign.right,
|
textAlign: TextAlign.right,
|
||||||
inputFormatters: [
|
inputFormatters: [
|
||||||
// regex to validate a crypto amount with 8 decimal places
|
AmountInputFormatter(
|
||||||
TextInputFormatter.withFunction((oldValue,
|
decimals: tokenContract.decimals,
|
||||||
newValue) =>
|
unit: ref.watch(pAmountUnit(coin)),
|
||||||
RegExp(r'^([0-9]*[,.]?[0-9]{0,8}|[,.][0-9]{0,8})$')
|
locale: locale,
|
||||||
.hasMatch(newValue.text)
|
),
|
||||||
? newValue
|
// // regex to validate a crypto amount with 8 decimal places
|
||||||
: oldValue),
|
// TextInputFormatter.withFunction((oldValue,
|
||||||
|
// newValue) =>
|
||||||
|
// RegExp(r'^([0-9]*[,.]?[0-9]{0,8}|[,.][0-9]{0,8})$')
|
||||||
|
// .hasMatch(newValue.text)
|
||||||
|
// ? newValue
|
||||||
|
// : oldValue),
|
||||||
],
|
],
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
contentPadding: const EdgeInsets.only(
|
contentPadding: const EdgeInsets.only(
|
||||||
|
@ -1011,13 +1002,17 @@ class _TokenSendViewState extends ConsumerState<TokenSendView> {
|
||||||
),
|
),
|
||||||
textAlign: TextAlign.right,
|
textAlign: TextAlign.right,
|
||||||
inputFormatters: [
|
inputFormatters: [
|
||||||
// regex to validate a fiat amount with 2 decimal places
|
AmountInputFormatter(
|
||||||
TextInputFormatter.withFunction((oldValue,
|
decimals: 2,
|
||||||
newValue) =>
|
locale: locale,
|
||||||
RegExp(r'^([0-9]*[,.]?[0-9]{0,2}|[,.][0-9]{0,2})$')
|
),
|
||||||
.hasMatch(newValue.text)
|
// // regex to validate a fiat amount with 2 decimal places
|
||||||
? newValue
|
// TextInputFormatter.withFunction((oldValue,
|
||||||
: oldValue),
|
// newValue) =>
|
||||||
|
// RegExp(r'^([0-9]*[,.]?[0-9]{0,2}|[,.][0-9]{0,2})$')
|
||||||
|
// .hasMatch(newValue.text)
|
||||||
|
// ? newValue
|
||||||
|
// : oldValue),
|
||||||
],
|
],
|
||||||
onChanged: _onFiatAmountFieldChanged,
|
onChanged: _onFiatAmountFieldChanged,
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
|
@ -1187,7 +1182,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),
|
||||||
|
|
|
@ -10,16 +10,17 @@
|
||||||
|
|
||||||
import 'package:decimal/decimal.dart';
|
import 'package:decimal/decimal.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
import 'package:flutter_rounded_date_picker/flutter_rounded_date_picker.dart';
|
import 'package:flutter_rounded_date_picker/flutter_rounded_date_picker.dart';
|
||||||
import 'package:flutter_svg/svg.dart';
|
import 'package:flutter_svg/svg.dart';
|
||||||
import 'package:stackwallet/models/transaction_filter.dart';
|
import 'package:stackwallet/models/transaction_filter.dart';
|
||||||
|
import 'package:stackwallet/providers/global/locale_provider.dart';
|
||||||
import 'package:stackwallet/providers/ui/transaction_filter_provider.dart';
|
import 'package:stackwallet/providers/ui/transaction_filter_provider.dart';
|
||||||
import 'package:stackwallet/themes/stack_colors.dart';
|
import 'package:stackwallet/themes/stack_colors.dart';
|
||||||
import 'package:stackwallet/themes/theme_providers.dart';
|
import 'package:stackwallet/themes/theme_providers.dart';
|
||||||
import 'package:stackwallet/utilities/amount/amount.dart';
|
import 'package:stackwallet/utilities/amount/amount.dart';
|
||||||
import 'package:stackwallet/utilities/amount/amount_formatter.dart';
|
import 'package:stackwallet/utilities/amount/amount_formatter.dart';
|
||||||
|
import 'package:stackwallet/utilities/amount/amount_input_formatter.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';
|
||||||
|
@ -757,12 +758,20 @@ class _TransactionSearchViewState
|
||||||
decimal: true,
|
decimal: true,
|
||||||
),
|
),
|
||||||
inputFormatters: [
|
inputFormatters: [
|
||||||
// regex to validate a crypto amount with 8 decimal places
|
AmountInputFormatter(
|
||||||
TextInputFormatter.withFunction((oldValue, newValue) =>
|
decimals: widget.coin.decimals,
|
||||||
RegExp(r'^([0-9]*[,.]?[0-9]{0,8}|[,.][0-9]{0,8})$')
|
unit: ref.watch(pAmountUnit(widget.coin)),
|
||||||
.hasMatch(newValue.text)
|
locale: ref.watch(
|
||||||
? newValue
|
localeServiceChangeNotifierProvider
|
||||||
: oldValue),
|
.select((value) => value.locale),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
// // regex to validate a crypto amount with 8 decimal places
|
||||||
|
// TextInputFormatter.withFunction((oldValue, newValue) =>
|
||||||
|
// RegExp(r'^([0-9]*[,.]?[0-9]{0,8}|[,.][0-9]{0,8})$')
|
||||||
|
// .hasMatch(newValue.text)
|
||||||
|
// ? newValue
|
||||||
|
// : oldValue),
|
||||||
],
|
],
|
||||||
style: isDesktop
|
style: isDesktop
|
||||||
? STextStyles.desktopTextExtraSmall(context).copyWith(
|
? STextStyles.desktopTextExtraSmall(context).copyWith(
|
||||||
|
|
|
@ -40,6 +40,7 @@ import 'package:stackwallet/themes/stack_colors.dart';
|
||||||
import 'package:stackwallet/utilities/address_utils.dart';
|
import 'package:stackwallet/utilities/address_utils.dart';
|
||||||
import 'package:stackwallet/utilities/amount/amount.dart';
|
import 'package:stackwallet/utilities/amount/amount.dart';
|
||||||
import 'package:stackwallet/utilities/amount/amount_formatter.dart';
|
import 'package:stackwallet/utilities/amount/amount_formatter.dart';
|
||||||
|
import 'package:stackwallet/utilities/amount/amount_input_formatter.dart';
|
||||||
import 'package:stackwallet/utilities/amount/amount_unit.dart';
|
import 'package:stackwallet/utilities/amount/amount_unit.dart';
|
||||||
import 'package:stackwallet/utilities/assets.dart';
|
import 'package:stackwallet/utilities/assets.dart';
|
||||||
import 'package:stackwallet/utilities/barcode_scanner_interface.dart';
|
import 'package:stackwallet/utilities/barcode_scanner_interface.dart';
|
||||||
|
@ -1054,12 +1055,17 @@ class _DesktopSendState extends ConsumerState<DesktopSend> {
|
||||||
),
|
),
|
||||||
textAlign: TextAlign.right,
|
textAlign: TextAlign.right,
|
||||||
inputFormatters: [
|
inputFormatters: [
|
||||||
// regex to validate a crypto amount with 8 decimal places
|
AmountInputFormatter(
|
||||||
TextInputFormatter.withFunction((oldValue, newValue) =>
|
decimals: coin.decimals,
|
||||||
RegExp(r'^([0-9]*[,.]?[0-9]{0,8}|[,.][0-9]{0,8})$')
|
unit: ref.watch(pAmountUnit(coin)),
|
||||||
.hasMatch(newValue.text)
|
locale: locale,
|
||||||
? newValue
|
),
|
||||||
: oldValue),
|
// // regex to validate a crypto amount with 8 decimal places
|
||||||
|
// TextInputFormatter.withFunction((oldValue, newValue) =>
|
||||||
|
// RegExp(r'^([0-9]*[,.]?[0-9]{0,8}|[,.][0-9]{0,8})$')
|
||||||
|
// .hasMatch(newValue.text)
|
||||||
|
// ? newValue
|
||||||
|
// : oldValue),
|
||||||
],
|
],
|
||||||
onChanged: (newValue) {},
|
onChanged: (newValue) {},
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
|
@ -1111,12 +1117,16 @@ class _DesktopSendState extends ConsumerState<DesktopSend> {
|
||||||
),
|
),
|
||||||
textAlign: TextAlign.right,
|
textAlign: TextAlign.right,
|
||||||
inputFormatters: [
|
inputFormatters: [
|
||||||
// regex to validate a fiat amount with 2 decimal places
|
AmountInputFormatter(
|
||||||
TextInputFormatter.withFunction((oldValue, newValue) =>
|
decimals: 2,
|
||||||
RegExp(r'^([0-9]*[,.]?[0-9]{0,2}|[,.][0-9]{0,2})$')
|
locale: locale,
|
||||||
.hasMatch(newValue.text)
|
),
|
||||||
? newValue
|
// // regex to validate a fiat amount with 2 decimal places
|
||||||
: oldValue),
|
// TextInputFormatter.withFunction((oldValue, newValue) =>
|
||||||
|
// RegExp(r'^([0-9]*[,.]?[0-9]{0,2}|[,.][0-9]{0,2})$')
|
||||||
|
// .hasMatch(newValue.text)
|
||||||
|
// ? newValue
|
||||||
|
// : oldValue),
|
||||||
],
|
],
|
||||||
onChanged: fiatTextFieldOnChanged,
|
onChanged: fiatTextFieldOnChanged,
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
|
|
|
@ -31,6 +31,7 @@ import 'package:stackwallet/themes/stack_colors.dart';
|
||||||
import 'package:stackwallet/utilities/address_utils.dart';
|
import 'package:stackwallet/utilities/address_utils.dart';
|
||||||
import 'package:stackwallet/utilities/amount/amount.dart';
|
import 'package:stackwallet/utilities/amount/amount.dart';
|
||||||
import 'package:stackwallet/utilities/amount/amount_formatter.dart';
|
import 'package:stackwallet/utilities/amount/amount_formatter.dart';
|
||||||
|
import 'package:stackwallet/utilities/amount/amount_input_formatter.dart';
|
||||||
import 'package:stackwallet/utilities/barcode_scanner_interface.dart';
|
import 'package:stackwallet/utilities/barcode_scanner_interface.dart';
|
||||||
import 'package:stackwallet/utilities/clipboard_interface.dart';
|
import 'package:stackwallet/utilities/clipboard_interface.dart';
|
||||||
import 'package:stackwallet/utilities/constants.dart';
|
import 'package:stackwallet/utilities/constants.dart';
|
||||||
|
@ -50,7 +51,7 @@ import 'package:stackwallet/widgets/icon_widgets/x_icon.dart';
|
||||||
import 'package:stackwallet/widgets/stack_text_field.dart';
|
import 'package:stackwallet/widgets/stack_text_field.dart';
|
||||||
import 'package:stackwallet/widgets/textfield_icon_button.dart';
|
import 'package:stackwallet/widgets/textfield_icon_button.dart';
|
||||||
|
|
||||||
const _kCryptoAmountRegex = r'^([0-9]*[,.]?[0-9]{0,8}|[,.][0-9]{0,8})$';
|
// const _kCryptoAmountRegex = r'^([0-9]*[,.]?[0-9]{0,8}|[,.][0-9]{0,8})$';
|
||||||
|
|
||||||
class DesktopTokenSend extends ConsumerStatefulWidget {
|
class DesktopTokenSend extends ConsumerStatefulWidget {
|
||||||
const DesktopTokenSend({
|
const DesktopTokenSend({
|
||||||
|
@ -717,15 +718,23 @@ class _DesktopTokenSendState extends ConsumerState<DesktopTokenSend> {
|
||||||
),
|
),
|
||||||
textAlign: TextAlign.right,
|
textAlign: TextAlign.right,
|
||||||
inputFormatters: [
|
inputFormatters: [
|
||||||
|
AmountInputFormatter(
|
||||||
|
decimals: tokenContract.decimals,
|
||||||
|
unit: ref.watch(pAmountUnit(coin)),
|
||||||
|
locale: ref.watch(
|
||||||
|
localeServiceChangeNotifierProvider
|
||||||
|
.select((value) => value.locale),
|
||||||
|
),
|
||||||
|
),
|
||||||
// regex to validate a crypto amount with 8 decimal places
|
// regex to validate a crypto amount with 8 decimal places
|
||||||
TextInputFormatter.withFunction((oldValue, newValue) => RegExp(
|
// TextInputFormatter.withFunction((oldValue, newValue) => RegExp(
|
||||||
_kCryptoAmountRegex.replaceAll(
|
// _kCryptoAmountRegex.replaceAll(
|
||||||
"0,8",
|
// "0,8",
|
||||||
"0,${tokenContract.decimals}",
|
// "0,${tokenContract.decimals}",
|
||||||
),
|
// ),
|
||||||
).hasMatch(newValue.text)
|
// ).hasMatch(newValue.text)
|
||||||
? newValue
|
// ? newValue
|
||||||
: oldValue),
|
// : oldValue),
|
||||||
],
|
],
|
||||||
onChanged: (newValue) {},
|
onChanged: (newValue) {},
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
|
@ -777,12 +786,19 @@ class _DesktopTokenSendState extends ConsumerState<DesktopTokenSend> {
|
||||||
),
|
),
|
||||||
textAlign: TextAlign.right,
|
textAlign: TextAlign.right,
|
||||||
inputFormatters: [
|
inputFormatters: [
|
||||||
// regex to validate a fiat amount with 2 decimal places
|
AmountInputFormatter(
|
||||||
TextInputFormatter.withFunction((oldValue, newValue) =>
|
decimals: 2,
|
||||||
RegExp(r'^([0-9]*[,.]?[0-9]{0,2}|[,.][0-9]{0,2})$')
|
locale: ref.watch(
|
||||||
.hasMatch(newValue.text)
|
localeServiceChangeNotifierProvider
|
||||||
? newValue
|
.select((value) => value.locale),
|
||||||
: oldValue),
|
),
|
||||||
|
),
|
||||||
|
// // regex to validate a fiat amount with 2 decimal places
|
||||||
|
// TextInputFormatter.withFunction((oldValue, newValue) =>
|
||||||
|
// RegExp(r'^([0-9]*[,.]?[0-9]{0,2}|[,.][0-9]{0,2})$')
|
||||||
|
// .hasMatch(newValue.text)
|
||||||
|
// ? newValue
|
||||||
|
// : oldValue),
|
||||||
],
|
],
|
||||||
onChanged: fiatTextFieldOnChanged,
|
onChanged: fiatTextFieldOnChanged,
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -63,4 +63,11 @@ class AmountFormatter {
|
||||||
tokenContract: ethContract,
|
tokenContract: ethContract,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Amount? tryParse(
|
||||||
|
String string, {
|
||||||
|
EthContract? ethContract,
|
||||||
|
}) {
|
||||||
|
return unit.tryParse(string, locale: locale, coin: coin);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
93
lib/utilities/amount/amount_input_formatter.dart
Normal file
93
lib/utilities/amount/amount_input_formatter.dart
Normal file
|
@ -0,0 +1,93 @@
|
||||||
|
import 'dart:math';
|
||||||
|
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
|
import 'package:intl/number_symbols.dart';
|
||||||
|
import 'package:intl/number_symbols_data.dart';
|
||||||
|
import 'package:stackwallet/utilities/amount/amount_unit.dart';
|
||||||
|
|
||||||
|
class AmountInputFormatter extends TextInputFormatter {
|
||||||
|
final int decimals;
|
||||||
|
final String locale;
|
||||||
|
final AmountUnit? unit;
|
||||||
|
|
||||||
|
AmountInputFormatter({
|
||||||
|
required this.decimals,
|
||||||
|
required this.locale,
|
||||||
|
this.unit,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
TextEditingValue formatEditUpdate(
|
||||||
|
TextEditingValue oldValue, TextEditingValue newValue) {
|
||||||
|
// get number symbols for decimal place and group separator
|
||||||
|
final numberSymbols = numberFormatSymbols[locale] as NumberSymbols? ??
|
||||||
|
numberFormatSymbols[locale.substring(0, 2)] as NumberSymbols?;
|
||||||
|
|
||||||
|
final decimalSeparator = numberSymbols?.DECIMAL_SEP ?? ".";
|
||||||
|
final groupSeparator = numberSymbols?.GROUP_SEP ?? ",";
|
||||||
|
|
||||||
|
String newText = newValue.text.replaceAll(groupSeparator, "");
|
||||||
|
|
||||||
|
final selectionIndexFromTheRight =
|
||||||
|
newValue.text.length - newValue.selection.end;
|
||||||
|
|
||||||
|
String? fraction;
|
||||||
|
if (newText.contains(decimalSeparator)) {
|
||||||
|
final parts = newText.split(decimalSeparator);
|
||||||
|
|
||||||
|
if (parts.length > 2) {
|
||||||
|
return oldValue;
|
||||||
|
}
|
||||||
|
if (newText.startsWith(decimalSeparator)) {
|
||||||
|
return TextEditingValue(
|
||||||
|
text: newText,
|
||||||
|
selection: TextSelection.collapsed(
|
||||||
|
offset: newText.length - selectionIndexFromTheRight,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
newText = parts.first;
|
||||||
|
if (parts.length == 2) {
|
||||||
|
fraction = parts.last;
|
||||||
|
} else {
|
||||||
|
fraction = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
final fractionDigits =
|
||||||
|
unit == null ? decimals : max(decimals - unit!.shift, 0);
|
||||||
|
|
||||||
|
if (fraction.length > fractionDigits) {
|
||||||
|
return oldValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newText.trim() == '' || newText.trim() == '0') {
|
||||||
|
return newValue.copyWith(text: '');
|
||||||
|
} else if (BigInt.parse(newText) < BigInt.one) {
|
||||||
|
return newValue.copyWith(text: '');
|
||||||
|
}
|
||||||
|
|
||||||
|
// insert group separator
|
||||||
|
final regex = RegExp(r'\B(?=(\d{3})+(?!\d))');
|
||||||
|
|
||||||
|
String newString = newText.replaceAllMapped(
|
||||||
|
regex,
|
||||||
|
(m) => "${m.group(0)}${numberSymbols?.GROUP_SEP ?? ","}",
|
||||||
|
);
|
||||||
|
|
||||||
|
if (fraction != null) {
|
||||||
|
newString += decimalSeparator;
|
||||||
|
if (fraction.isNotEmpty) {
|
||||||
|
newString += fraction;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return TextEditingValue(
|
||||||
|
text: newString,
|
||||||
|
selection: TextSelection.collapsed(
|
||||||
|
offset: newString.length - selectionIndexFromTheRight,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -164,6 +164,51 @@ extension AmountUnitExt on AmountUnit {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Amount? tryParse(
|
||||||
|
String value, {
|
||||||
|
required String locale,
|
||||||
|
required Coin coin,
|
||||||
|
EthContract? tokenContract,
|
||||||
|
}) {
|
||||||
|
final precisionLost = value.startsWith("~");
|
||||||
|
|
||||||
|
final parts = (precisionLost ? value.substring(1) : 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, ".");
|
||||||
|
final Decimal? decimal = Decimal.tryParse(decimalString);
|
||||||
|
|
||||||
|
if (decimal == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
final decimalPlaces = tokenContract?.decimals ?? coin.decimals;
|
||||||
|
final realShift = math.min(shift, decimalPlaces);
|
||||||
|
|
||||||
|
return decimal.shift(0 - realShift).toAmount(fractionDigits: decimalPlaces);
|
||||||
|
}
|
||||||
|
|
||||||
String displayAmount({
|
String displayAmount({
|
||||||
required Amount amount,
|
required Amount amount,
|
||||||
required String locale,
|
required String locale,
|
||||||
|
@ -191,6 +236,17 @@ extension AmountUnitExt on AmountUnit {
|
||||||
// start building the return value with just the whole value
|
// start building the return value with just the whole value
|
||||||
String returnValue = wholeNumber.toString();
|
String returnValue = wholeNumber.toString();
|
||||||
|
|
||||||
|
// get number symbols for decimal place and group separator
|
||||||
|
final numberSymbols = numberFormatSymbols[locale] as NumberSymbols? ??
|
||||||
|
numberFormatSymbols[locale.substring(0, 2)] as NumberSymbols?;
|
||||||
|
|
||||||
|
// insert group separator
|
||||||
|
final regex = RegExp(r'\B(?=(\d{3})+(?!\d))');
|
||||||
|
returnValue = returnValue.replaceAllMapped(
|
||||||
|
regex,
|
||||||
|
(m) => "${m.group(0)}${numberSymbols?.GROUP_SEP ?? ","}",
|
||||||
|
);
|
||||||
|
|
||||||
// if true and withUnitName is true, we will show "~" prepended on amount
|
// if true and withUnitName is true, we will show "~" prepended on amount
|
||||||
bool didLosePrecision = false;
|
bool didLosePrecision = false;
|
||||||
|
|
||||||
|
@ -239,11 +295,7 @@ extension AmountUnitExt on AmountUnit {
|
||||||
}
|
}
|
||||||
|
|
||||||
// get decimal separator based on locale
|
// get decimal separator based on locale
|
||||||
final String separator =
|
final String separator = numberSymbols?.DECIMAL_SEP ?? ".";
|
||||||
(numberFormatSymbols[locale] as NumberSymbols?)?.DECIMAL_SEP ??
|
|
||||||
(numberFormatSymbols[locale.substring(0, 2)] as NumberSymbols?)
|
|
||||||
?.DECIMAL_SEP ??
|
|
||||||
".";
|
|
||||||
|
|
||||||
// append separator and fractional amount
|
// append separator and fractional amount
|
||||||
returnValue += "$separator$remainder";
|
returnValue += "$separator$remainder";
|
||||||
|
|
|
@ -9,17 +9,19 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.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/aggregate_currency.dart';
|
import 'package:stackwallet/models/exchange/aggregate_currency.dart';
|
||||||
import 'package:stackwallet/pages/buy_view/sub_widgets/crypto_selection_view.dart';
|
import 'package:stackwallet/pages/buy_view/sub_widgets/crypto_selection_view.dart';
|
||||||
|
import 'package:stackwallet/providers/global/locale_provider.dart';
|
||||||
import 'package:stackwallet/themes/stack_colors.dart';
|
import 'package:stackwallet/themes/stack_colors.dart';
|
||||||
|
import 'package:stackwallet/utilities/amount/amount_input_formatter.dart';
|
||||||
import 'package:stackwallet/utilities/assets.dart';
|
import 'package:stackwallet/utilities/assets.dart';
|
||||||
import 'package:stackwallet/utilities/text_styles.dart';
|
import 'package:stackwallet/utilities/text_styles.dart';
|
||||||
import 'package:stackwallet/utilities/util.dart';
|
import 'package:stackwallet/utilities/util.dart';
|
||||||
import 'package:stackwallet/widgets/loading_indicator.dart';
|
import 'package:stackwallet/widgets/loading_indicator.dart';
|
||||||
|
|
||||||
class ExchangeTextField extends StatefulWidget {
|
class ExchangeTextField extends ConsumerStatefulWidget {
|
||||||
const ExchangeTextField({
|
const ExchangeTextField({
|
||||||
Key? key,
|
Key? key,
|
||||||
this.borderRadius = 0,
|
this.borderRadius = 0,
|
||||||
|
@ -55,10 +57,10 @@ class ExchangeTextField extends StatefulWidget {
|
||||||
final AggregateCurrency? currency;
|
final AggregateCurrency? currency;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<ExchangeTextField> createState() => _ExchangeTextFieldState();
|
ConsumerState<ExchangeTextField> createState() => _ExchangeTextFieldState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _ExchangeTextFieldState extends State<ExchangeTextField> {
|
class _ExchangeTextFieldState extends ConsumerState<ExchangeTextField> {
|
||||||
late final TextEditingController controller;
|
late final TextEditingController controller;
|
||||||
late final FocusNode focusNode;
|
late final FocusNode focusNode;
|
||||||
late final TextStyle textStyle;
|
late final TextStyle textStyle;
|
||||||
|
@ -130,12 +132,17 @@ class _ExchangeTextFieldState extends State<ExchangeTextField> {
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
inputFormatters: [
|
inputFormatters: [
|
||||||
// regex to validate a crypto amount with 8 decimal places
|
AmountInputFormatter(
|
||||||
TextInputFormatter.withFunction((oldValue, newValue) =>
|
decimals: 8, // todo change this
|
||||||
RegExp(r'^([0-9]*[,.]?[0-9]{0,8}|[,.][0-9]{0,8})$')
|
locale: ref.watch(localeServiceChangeNotifierProvider
|
||||||
.hasMatch(newValue.text)
|
.select((value) => value.locale)),
|
||||||
? newValue
|
),
|
||||||
: oldValue),
|
// // regex to validate a crypto amount with 8 decimal places
|
||||||
|
// TextInputFormatter.withFunction((oldValue, newValue) =>
|
||||||
|
// RegExp(r'^([0-9]*[,.]?[0-9]{0,8}|[,.][0-9]{0,8})$')
|
||||||
|
// .hasMatch(newValue.text)
|
||||||
|
// ? newValue
|
||||||
|
// : oldValue),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
|
@ -28,7 +28,7 @@ void main() {
|
||||||
coin: Coin.bitcoin,
|
coin: Coin.bitcoin,
|
||||||
maxDecimalPlaces: 8,
|
maxDecimalPlaces: 8,
|
||||||
),
|
),
|
||||||
"10123.45678 mBTC",
|
"10,123.45678 mBTC",
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
|
@ -38,7 +38,7 @@ void main() {
|
||||||
coin: Coin.bitcoin,
|
coin: Coin.bitcoin,
|
||||||
maxDecimalPlaces: 8,
|
maxDecimalPlaces: 8,
|
||||||
),
|
),
|
||||||
"10123456.78 µBTC",
|
"10,123,456.78 µBTC",
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
|
@ -48,7 +48,7 @@ void main() {
|
||||||
coin: Coin.bitcoin,
|
coin: Coin.bitcoin,
|
||||||
maxDecimalPlaces: 8,
|
maxDecimalPlaces: 8,
|
||||||
),
|
),
|
||||||
"1012345678 sats",
|
"1,012,345,678 sats",
|
||||||
);
|
);
|
||||||
final dec = Decimal.parse("10.123456789123456789");
|
final dec = Decimal.parse("10.123456789123456789");
|
||||||
|
|
||||||
|
@ -98,7 +98,7 @@ void main() {
|
||||||
coin: Coin.ethereum,
|
coin: Coin.ethereum,
|
||||||
maxDecimalPlaces: 9,
|
maxDecimalPlaces: 9,
|
||||||
),
|
),
|
||||||
"~10123.456789123 mETH",
|
"~10,123.456789123 mETH",
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
|
@ -108,7 +108,7 @@ void main() {
|
||||||
coin: Coin.ethereum,
|
coin: Coin.ethereum,
|
||||||
maxDecimalPlaces: 8,
|
maxDecimalPlaces: 8,
|
||||||
),
|
),
|
||||||
"~10123456.78912345 µETH",
|
"~10,123,456.78912345 µETH",
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
|
@ -118,7 +118,7 @@ void main() {
|
||||||
coin: Coin.ethereum,
|
coin: Coin.ethereum,
|
||||||
maxDecimalPlaces: 1,
|
maxDecimalPlaces: 1,
|
||||||
),
|
),
|
||||||
"~10123456789.1 gwei",
|
"~10,123,456,789.1 gwei",
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
|
@ -128,7 +128,7 @@ void main() {
|
||||||
coin: Coin.ethereum,
|
coin: Coin.ethereum,
|
||||||
maxDecimalPlaces: 18,
|
maxDecimalPlaces: 18,
|
||||||
),
|
),
|
||||||
"10123456789123.456789 mwei",
|
"10,123,456,789,123.456789 mwei",
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
|
@ -138,7 +138,7 @@ void main() {
|
||||||
coin: Coin.ethereum,
|
coin: Coin.ethereum,
|
||||||
maxDecimalPlaces: 4,
|
maxDecimalPlaces: 4,
|
||||||
),
|
),
|
||||||
"10123456789123456.789 kwei",
|
"10,123,456,789,123,456.789 kwei",
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
|
@ -148,7 +148,78 @@ void main() {
|
||||||
coin: Coin.ethereum,
|
coin: Coin.ethereum,
|
||||||
maxDecimalPlaces: 1,
|
maxDecimalPlaces: 1,
|
||||||
),
|
),
|
||||||
"10123456789123456789 wei",
|
"10,123,456,789,123,456,789 wei",
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("parse eth string to amount", () {
|
||||||
|
final Amount amount = Amount.fromDecimal(
|
||||||
|
Decimal.parse("10.123456789123456789"),
|
||||||
|
fractionDigits: Coin.ethereum.decimals,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(
|
||||||
|
AmountUnit.nano.tryParse(
|
||||||
|
"~10,123,456,789.1 gwei",
|
||||||
|
locale: "en_US",
|
||||||
|
coin: Coin.ethereum,
|
||||||
|
),
|
||||||
|
Amount.fromDecimal(
|
||||||
|
Decimal.parse("10.1234567891"),
|
||||||
|
fractionDigits: Coin.ethereum.decimals,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(
|
||||||
|
AmountUnit.atto.tryParse(
|
||||||
|
"10,123,456,789,123,456,789 wei",
|
||||||
|
locale: "en_US",
|
||||||
|
coin: Coin.ethereum,
|
||||||
|
),
|
||||||
|
amount,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("parse btc string to amount", () {
|
||||||
|
final Amount amount = Amount(
|
||||||
|
rawValue: BigInt.from(1012345678),
|
||||||
|
fractionDigits: 8,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(
|
||||||
|
AmountUnit.normal.tryParse(
|
||||||
|
"10.12345678 BTC",
|
||||||
|
locale: "en_US",
|
||||||
|
coin: Coin.bitcoin,
|
||||||
|
),
|
||||||
|
amount,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(
|
||||||
|
AmountUnit.milli.tryParse(
|
||||||
|
"10,123.45678 mBTC",
|
||||||
|
locale: "en_US",
|
||||||
|
coin: Coin.bitcoin,
|
||||||
|
),
|
||||||
|
amount,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(
|
||||||
|
AmountUnit.micro.tryParse(
|
||||||
|
"10,123,456.7822 µBTC",
|
||||||
|
locale: "en_US",
|
||||||
|
coin: Coin.bitcoin,
|
||||||
|
),
|
||||||
|
amount,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(
|
||||||
|
AmountUnit.nano.tryParse(
|
||||||
|
"1,012,345,678 sats",
|
||||||
|
locale: "en_US",
|
||||||
|
coin: Coin.bitcoin,
|
||||||
|
),
|
||||||
|
amount,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue