Merge pull request #234 from cypherstack/desktop

Desktop
This commit is contained in:
Diego Salazar 2022-11-23 18:52:04 -07:00 committed by GitHub
commit eae00866c3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
32 changed files with 787 additions and 582 deletions

View file

@ -2,6 +2,7 @@ import 'package:dart_numerics/dart_numerics.dart';
import 'package:decimal/decimal.dart'; import 'package:decimal/decimal.dart';
import 'package:hive/hive.dart'; import 'package:hive/hive.dart';
import 'package:stackwallet/utilities/constants.dart'; import 'package:stackwallet/utilities/constants.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
part '../type_adaptors/transactions_model.g.dart'; part '../type_adaptors/transactions_model.g.dart';
@ -220,14 +221,16 @@ class Transaction {
(DateTime.now().millisecondsSinceEpoch ~/ 1000), (DateTime.now().millisecondsSinceEpoch ~/ 1000),
txType: json['txType'] as String, txType: json['txType'] as String,
amount: (Decimal.parse(json["amount"].toString()) * amount: (Decimal.parse(json["amount"].toString()) *
Decimal.fromInt(Constants.satsPerCoin)) Decimal.fromInt(Constants.satsPerCoin(Coin
.firo))) // dirty hack but we need 8 decimal places here to keep consistent data structure
.toBigInt() .toBigInt()
.toInt(), .toInt(),
aliens: [], aliens: [],
worthNow: json['worthNow'] as String, worthNow: json['worthNow'] as String,
worthAtBlockTimestamp: json['worthAtBlockTimestamp'] as String? ?? "0", worthAtBlockTimestamp: json['worthAtBlockTimestamp'] as String? ?? "0",
fees: (Decimal.parse(json["fees"].toString()) * fees: (Decimal.parse(json["fees"].toString()) *
Decimal.fromInt(Constants.satsPerCoin)) Decimal.fromInt(Constants.satsPerCoin(Coin
.firo))) // dirty hack but we need 8 decimal places here to keep consistent data structure
.toBigInt() .toBigInt()
.toInt(), .toInt(),
inputSize: json['inputSize'] as int? ?? 0, inputSize: json['inputSize'] as int? ?? 0,
@ -386,7 +389,8 @@ class Output {
scriptpubkeyType: json['scriptPubKey']['type'] as String?, scriptpubkeyType: json['scriptPubKey']['type'] as String?,
scriptpubkeyAddress: address, scriptpubkeyAddress: address,
value: (Decimal.parse(json["value"].toString()) * value: (Decimal.parse(json["value"].toString()) *
Decimal.fromInt(Constants.satsPerCoin)) Decimal.fromInt(Constants.satsPerCoin(Coin
.firo))) // dirty hack but we need 8 decimal places here to keep consistent data structure
.toBigInt() .toBigInt()
.toInt(), .toInt(),
); );

View file

@ -155,7 +155,7 @@ class _RestoreOptionsViewState extends ConsumerState<RestoreOptionsView> {
final date = await showRoundedDatePicker( final date = await showRoundedDatePicker(
context: context, context: context,
initialDate: DateTime.now(), initialDate: DateTime.now(),
height: height * 0.5, height: height / 3.2,
theme: ThemeData( theme: ThemeData(
primarySwatch: Util.createMaterialColor(fetchedColor), primarySwatch: Util.createMaterialColor(fetchedColor),
), ),

View file

@ -342,6 +342,9 @@ class _ConfirmChangeNowSendViewState
localeServiceChangeNotifierProvider localeServiceChangeNotifierProvider
.select((value) => value.locale), .select((value) => value.locale),
), ),
ref.watch(
managerProvider.select((value) => value.coin),
),
)} ${ref.watch( )} ${ref.watch(
managerProvider.select((value) => value.coin), managerProvider.select((value) => value.coin),
).ticker}", ).ticker}",
@ -382,6 +385,9 @@ class _ConfirmChangeNowSendViewState
localeServiceChangeNotifierProvider localeServiceChangeNotifierProvider
.select((value) => value.locale), .select((value) => value.locale),
), ),
ref.watch(
managerProvider.select((value) => value.coin),
),
)} ${ref.watch( )} ${ref.watch(
managerProvider.select((value) => value.coin), managerProvider.select((value) => value.coin),
).ticker}", ).ticker}",
@ -563,13 +569,12 @@ class _ConfirmChangeNowSendViewState
], ],
), ),
child: Text( child: Text(
"${Format.satoshiAmountToPrettyString( "${Format.satoshiAmountToPrettyString(transactionInfo["recipientAmt"] as int, ref.watch(
transactionInfo["recipientAmt"] as int, localeServiceChangeNotifierProvider
ref.watch( .select((value) => value.locale),
localeServiceChangeNotifierProvider ), ref.watch(
.select((value) => value.locale), managerProvider.select((value) => value.coin),
), ))} ${ref.watch(
)} ${ref.watch(
managerProvider.select((value) => value.coin), managerProvider.select((value) => value.coin),
).ticker}", ).ticker}",
style: STextStyles.itemSubtitle12(context), style: STextStyles.itemSubtitle12(context),
@ -597,13 +602,12 @@ class _ConfirmChangeNowSendViewState
style: STextStyles.smallMed12(context), style: STextStyles.smallMed12(context),
), ),
Text( Text(
"${Format.satoshiAmountToPrettyString( "${Format.satoshiAmountToPrettyString(transactionInfo["fee"] as int, ref.watch(
transactionInfo["fee"] as int, localeServiceChangeNotifierProvider
ref.watch( .select((value) => value.locale),
localeServiceChangeNotifierProvider ), ref.watch(
.select((value) => value.locale), managerProvider.select((value) => value.coin),
), ))} ${ref.watch(
)} ${ref.watch(
managerProvider.select((value) => value.coin), managerProvider.select((value) => value.coin),
).ticker}", ).ticker}",
style: STextStyles.itemSubtitle12(context), style: STextStyles.itemSubtitle12(context),
@ -685,14 +689,12 @@ class _ConfirmChangeNowSendViewState
), ),
), ),
Text( Text(
"${Format.satoshiAmountToPrettyString( "${Format.satoshiAmountToPrettyString((transactionInfo["fee"] as int) + (transactionInfo["recipientAmt"] as int), ref.watch(
(transactionInfo["fee"] as int) + localeServiceChangeNotifierProvider
(transactionInfo["recipientAmt"] as int), .select((value) => value.locale),
ref.watch( ), ref.watch(
localeServiceChangeNotifierProvider managerProvider.select((value) => value.coin),
.select((value) => value.locale), ))} ${ref.watch(
),
)} ${ref.watch(
managerProvider.select((value) => value.coin), managerProvider.select((value) => value.coin),
).ticker}", ).ticker}",
style: STextStyles.itemSubtitle12(context).copyWith( style: STextStyles.itemSubtitle12(context).copyWith(

View file

@ -1281,28 +1281,30 @@ class _ExchangeFormState extends ConsumerState<ExchangeForm> {
condition: isDesktop, condition: isDesktop,
builder: (child) => MouseRegion( builder: (child) => MouseRegion(
cursor: SystemMouseCursors.click, cursor: SystemMouseCursors.click,
child: RoundedContainer( child: child,
padding: const EdgeInsets.all(6),
color: Theme.of(context)
.extension<StackColors>()!
.buttonBackSecondary,
radiusMultiplier: 0.75,
child: child,
),
), ),
child: GestureDetector( child: RoundedContainer(
onTap: () async { padding: isDesktop
await _swap(); ? const EdgeInsets.all(6)
}, : const EdgeInsets.all(2),
child: Padding( color: Theme.of(context)
padding: const EdgeInsets.all(4), .extension<StackColors>()!
child: SvgPicture.asset( .buttonBackSecondary,
Assets.svg.swap, radiusMultiplier: 0.75,
width: 20, child: GestureDetector(
height: 20, onTap: () async {
color: Theme.of(context) await _swap();
.extension<StackColors>()! },
.accentColorDark, child: Padding(
padding: const EdgeInsets.all(4),
child: SvgPicture.asset(
Assets.svg.swap,
width: 20,
height: 20,
color: Theme.of(context)
.extension<StackColors>()!
.accentColorDark,
),
), ),
), ),
), ),
@ -1310,7 +1312,7 @@ class _ExchangeFormState extends ConsumerState<ExchangeForm> {
], ],
), ),
SizedBox( SizedBox(
height: isDesktop ? 10 : 4, height: isDesktop ? 10 : 7,
), ),
ExchangeTextField( ExchangeTextField(
focusNode: _receiveFocusNode, focusNode: _receiveFocusNode,

View file

@ -7,8 +7,6 @@ import 'package:stackwallet/pages/address_book_views/subviews/contact_popup.dart
import 'package:stackwallet/pages/exchange_view/choose_from_stack_view.dart'; import 'package:stackwallet/pages/exchange_view/choose_from_stack_view.dart';
import 'package:stackwallet/pages/exchange_view/exchange_step_views/step_3_view.dart'; import 'package:stackwallet/pages/exchange_view/exchange_step_views/step_3_view.dart';
import 'package:stackwallet/pages/exchange_view/sub_widgets/step_row.dart'; import 'package:stackwallet/pages/exchange_view/sub_widgets/step_row.dart';
import 'package:stackwallet/providers/exchange/exchange_flow_is_active_state_provider.dart';
import 'package:stackwallet/providers/exchange/exchange_send_from_wallet_id_provider.dart';
import 'package:stackwallet/providers/providers.dart'; import 'package:stackwallet/providers/providers.dart';
import 'package:stackwallet/utilities/address_utils.dart'; import 'package:stackwallet/utilities/address_utils.dart';
import 'package:stackwallet/utilities/barcode_scanner_interface.dart'; import 'package:stackwallet/utilities/barcode_scanner_interface.dart';
@ -20,6 +18,7 @@ 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/custom_buttons/app_bar_icon_button.dart'; import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
import 'package:stackwallet/widgets/custom_buttons/blue_text_button.dart'; import 'package:stackwallet/widgets/custom_buttons/blue_text_button.dart';
import 'package:stackwallet/widgets/desktop/primary_button.dart';
import 'package:stackwallet/widgets/icon_widgets/addressbook_icon.dart'; import 'package:stackwallet/widgets/icon_widgets/addressbook_icon.dart';
import 'package:stackwallet/widgets/icon_widgets/clipboard_icon.dart'; import 'package:stackwallet/widgets/icon_widgets/clipboard_icon.dart';
import 'package:stackwallet/widgets/icon_widgets/qrcode_icon.dart'; import 'package:stackwallet/widgets/icon_widgets/qrcode_icon.dart';
@ -57,6 +56,8 @@ class _Step2ViewState extends ConsumerState<Step2View> {
late final FocusNode _toFocusNode; late final FocusNode _toFocusNode;
late final FocusNode _refundFocusNode; late final FocusNode _refundFocusNode;
bool enableNext = false;
bool isStackCoin(String ticker) { bool isStackCoin(String ticker) {
try { try {
coinFromTickerCaseInsensitive(ticker); coinFromTickerCaseInsensitive(ticker);
@ -207,6 +208,12 @@ class _Step2ViewState extends ConsumerState<Step2View> {
_toController.text = manager.walletName; _toController.text = manager.walletName;
model.recipientAddress = await manager model.recipientAddress = await manager
.currentReceivingAddress; .currentReceivingAddress;
setState(() {
enableNext = _toController
.text.isNotEmpty &&
_refundController.text.isNotEmpty;
});
} }
}); });
} catch (e, s) { } catch (e, s) {
@ -275,7 +282,12 @@ class _Step2ViewState extends ConsumerState<Step2View> {
model.recipientAddress = model.recipientAddress =
_toController.text; _toController.text;
setState(() {}); setState(() {
enableNext = _toController
.text.isNotEmpty &&
_refundController
.text.isNotEmpty;
});
}, },
child: const XIcon(), child: const XIcon(),
) )
@ -295,7 +307,12 @@ class _Step2ViewState extends ConsumerState<Step2View> {
model.recipientAddress = model.recipientAddress =
_toController.text; _toController.text;
setState(() {}); setState(() {
enableNext = _toController
.text.isNotEmpty &&
_refundController
.text.isNotEmpty;
});
} }
}, },
child: _toController.text.isEmpty child: _toController.text.isEmpty
@ -338,6 +355,12 @@ class _Step2ViewState extends ConsumerState<Step2View> {
.state) .state)
.state = ""; .state = "";
} }
setState(() {
enableNext = _toController
.text.isNotEmpty &&
_refundController
.text.isNotEmpty;
});
}); });
}, },
child: const AddressBookIcon(), child: const AddressBookIcon(),
@ -361,14 +384,24 @@ class _Step2ViewState extends ConsumerState<Step2View> {
model.recipientAddress = model.recipientAddress =
_toController.text; _toController.text;
setState(() {}); setState(() {
enableNext = _toController
.text.isNotEmpty &&
_refundController
.text.isNotEmpty;
});
} else { } else {
_toController.text = _toController.text =
qrResult.rawContent; qrResult.rawContent;
model.recipientAddress = model.recipientAddress =
_toController.text; _toController.text;
setState(() {}); setState(() {
enableNext = _toController
.text.isNotEmpty &&
_refundController
.text.isNotEmpty;
});
} }
} on PlatformException catch (e, s) { } on PlatformException catch (e, s) {
Logging.instance.log( Logging.instance.log(
@ -429,6 +462,11 @@ class _Step2ViewState extends ConsumerState<Step2View> {
model.refundAddress = await manager model.refundAddress = await manager
.currentReceivingAddress; .currentReceivingAddress;
} }
setState(() {
enableNext = _toController
.text.isNotEmpty &&
_refundController.text.isNotEmpty;
});
}); });
} catch (e, s) { } catch (e, s) {
Logging.instance Logging.instance
@ -495,7 +533,12 @@ class _Step2ViewState extends ConsumerState<Step2View> {
model.refundAddress = model.refundAddress =
_refundController.text; _refundController.text;
setState(() {}); setState(() {
enableNext = _toController
.text.isNotEmpty &&
_refundController
.text.isNotEmpty;
});
}, },
child: const XIcon(), child: const XIcon(),
) )
@ -516,7 +559,12 @@ class _Step2ViewState extends ConsumerState<Step2View> {
model.refundAddress = model.refundAddress =
_refundController.text; _refundController.text;
setState(() {}); setState(() {
enableNext = _toController
.text.isNotEmpty &&
_refundController
.text.isNotEmpty;
});
} }
}, },
child: child:
@ -555,6 +603,12 @@ class _Step2ViewState extends ConsumerState<Step2View> {
model.refundAddress = model.refundAddress =
_refundController.text; _refundController.text;
} }
setState(() {
enableNext = _toController
.text.isNotEmpty &&
_refundController
.text.isNotEmpty;
});
}); });
}, },
child: const AddressBookIcon(), child: const AddressBookIcon(),
@ -578,14 +632,24 @@ class _Step2ViewState extends ConsumerState<Step2View> {
model.refundAddress = model.refundAddress =
_refundController.text; _refundController.text;
setState(() {}); setState(() {
enableNext = _toController
.text.isNotEmpty &&
_refundController
.text.isNotEmpty;
});
} else { } else {
_refundController.text = _refundController.text =
qrResult.rawContent; qrResult.rawContent;
model.refundAddress = model.refundAddress =
_refundController.text; _refundController.text;
setState(() {}); setState(() {
enableNext = _toController
.text.isNotEmpty &&
_refundController
.text.isNotEmpty;
});
} }
} on PlatformException catch (e, s) { } on PlatformException catch (e, s) {
Logging.instance.log( Logging.instance.log(
@ -637,20 +701,15 @@ class _Step2ViewState extends ConsumerState<Step2View> {
width: 16, width: 16,
), ),
Expanded( Expanded(
child: TextButton( child: PrimaryButton(
label: "Next",
enabled: enableNext,
onPressed: () { onPressed: () {
Navigator.of(context).pushNamed( Navigator.of(context).pushNamed(
Step3View.routeName, Step3View.routeName,
arguments: model, arguments: model,
); );
}, },
style: Theme.of(context)
.extension<StackColors>()!
.getPrimaryEnabledButtonColor(context),
child: Text(
"Next",
style: STextStyles.button(context),
),
), ),
), ),
], ],

View file

@ -487,7 +487,7 @@ class _Step4ViewState extends ConsumerState<Step4View> {
final amount = final amount =
Format.decimalAmountToSatoshis( Format.decimalAmountToSatoshis(
model.sendAmount); model.sendAmount, manager.coin);
final address = final address =
model.trade!.payInAddress; model.trade!.payInAddress;

View file

@ -61,25 +61,7 @@ class _SendFromViewState extends ConsumerState<SendFromView> {
late final Trade trade; late final Trade trade;
String formatAmount(Decimal amount, Coin coin) { String formatAmount(Decimal amount, Coin coin) {
switch (coin) { return amount.toStringAsFixed(Constants.decimalPlacesForCoin(coin));
case Coin.bitcoin:
case Coin.bitcoincash:
case Coin.litecoin:
case Coin.dogecoin:
case Coin.epicCash:
case Coin.firo:
case Coin.namecoin:
case Coin.bitcoinTestNet:
case Coin.litecoinTestNet:
case Coin.bitcoincashTestnet:
case Coin.dogecoinTestNet:
case Coin.firoTestNet:
return amount.toStringAsFixed(Constants.decimalPlaces);
case Coin.monero:
return amount.toStringAsFixed(Constants.decimalPlacesMonero);
case Coin.wownero:
return amount.toStringAsFixed(Constants.decimalPlacesWownero);
}
} }
@override @override
@ -233,7 +215,7 @@ class _SendFromCardState extends ConsumerState<SendFromCard> {
late final Trade trade; late final Trade trade;
Future<void> _send(Manager manager, {bool? shouldSendPublicFiroFunds}) async { Future<void> _send(Manager manager, {bool? shouldSendPublicFiroFunds}) async {
final _amount = Format.decimalAmountToSatoshis(amount); final _amount = Format.decimalAmountToSatoshis(amount, manager.coin);
try { try {
bool wasCancelled = false; bool wasCancelled = false;
@ -464,7 +446,8 @@ class _SendFromCardState extends ConsumerState<SendFromCard> {
"${Format.localizedStringAsFixed( "${Format.localizedStringAsFixed(
value: snapshot.data!, value: snapshot.data!,
locale: locale, locale: locale,
decimalPlaces: Constants.decimalPlaces, decimalPlaces:
Constants.decimalPlacesForCoin(coin),
)} ${coin.ticker}", )} ${coin.ticker}",
style: STextStyles.itemSubtitle(context), style: STextStyles.itemSubtitle(context),
); );
@ -549,7 +532,8 @@ class _SendFromCardState extends ConsumerState<SendFromCard> {
"${Format.localizedStringAsFixed( "${Format.localizedStringAsFixed(
value: snapshot.data!, value: snapshot.data!,
locale: locale, locale: locale,
decimalPlaces: Constants.decimalPlaces, decimalPlaces:
Constants.decimalPlacesForCoin(coin),
)} ${coin.ticker}", )} ${coin.ticker}",
style: STextStyles.itemSubtitle(context), style: STextStyles.itemSubtitle(context),
); );
@ -657,11 +641,8 @@ class _SendFromCardState extends ConsumerState<SendFromCard> {
"${Format.localizedStringAsFixed( "${Format.localizedStringAsFixed(
value: snapshot.data!, value: snapshot.data!,
locale: locale, locale: locale,
decimalPlaces: coin == Coin.monero decimalPlaces:
? Constants.decimalPlacesMonero Constants.decimalPlacesForCoin(coin),
: coin == Coin.wownero
? Constants.decimalPlacesWownero
: Constants.decimalPlaces,
)} ${coin.ticker}", )} ${coin.ticker}",
style: STextStyles.itemSubtitle(context), style: STextStyles.itemSubtitle(context),
); );

View file

@ -159,6 +159,14 @@ class ExchangeProviderOptions extends ConsumerWidget {
.toDecimal( .toDecimal(
scaleOnInfinitePrecision: 12); scaleOnInfinitePrecision: 12);
} }
Coin coin;
try {
coin =
coinFromTickerCaseInsensitive(to!);
} catch (_) {
coin = Coin.bitcoin;
}
return Text( return Text(
"1 ${from!.toUpperCase()} ~ ${Format.localizedStringAsFixed( "1 ${from!.toUpperCase()} ~ ${Format.localizedStringAsFixed(
value: rate, value: rate,
@ -167,11 +175,9 @@ class ExchangeProviderOptions extends ConsumerWidget {
.select( .select(
(value) => value.locale), (value) => value.locale),
), ),
decimalPlaces: to!.toUpperCase() == decimalPlaces:
Coin.monero.ticker Constants.decimalPlacesForCoin(
.toUpperCase() coin),
? Constants.decimalPlacesMonero
: Constants.decimalPlaces,
)} ${to!.toUpperCase()}", )} ${to!.toUpperCase()}",
style: style:
STextStyles.itemSubtitle12(context) STextStyles.itemSubtitle12(context)
@ -354,6 +360,13 @@ class ExchangeProviderOptions extends ConsumerWidget {
.toDecimal( .toDecimal(
scaleOnInfinitePrecision: 12); scaleOnInfinitePrecision: 12);
Coin coin;
try {
coin =
coinFromTickerCaseInsensitive(to!);
} catch (_) {
coin = Coin.bitcoin;
}
return Text( return Text(
"1 ${from!.toUpperCase()} ~ ${Format.localizedStringAsFixed( "1 ${from!.toUpperCase()} ~ ${Format.localizedStringAsFixed(
value: rate, value: rate,
@ -362,11 +375,9 @@ class ExchangeProviderOptions extends ConsumerWidget {
.select( .select(
(value) => value.locale), (value) => value.locale),
), ),
decimalPlaces: to!.toUpperCase() == decimalPlaces:
Coin.monero.ticker Constants.decimalPlacesForCoin(
.toUpperCase() coin),
? Constants.decimalPlacesMonero
: Constants.decimalPlaces,
)} ${to!.toUpperCase()}", )} ${to!.toUpperCase()}",
style: style:
STextStyles.itemSubtitle12(context) STextStyles.itemSubtitle12(context)

View file

@ -55,7 +55,7 @@ class RateTypeToggle extends ConsumerWidget {
child: RoundedContainer( child: RoundedContainer(
padding: isDesktop padding: isDesktop
? const EdgeInsets.all(17) ? const EdgeInsets.all(17)
: const EdgeInsets.all(0), : const EdgeInsets.all(12),
color: estimated color: estimated
? Theme.of(context) ? Theme.of(context)
.extension<StackColors>()! .extension<StackColors>()!
@ -136,7 +136,7 @@ class RateTypeToggle extends ConsumerWidget {
child: RoundedContainer( child: RoundedContainer(
padding: isDesktop padding: isDesktop
? const EdgeInsets.all(17) ? const EdgeInsets.all(17)
: const EdgeInsets.all(0), : const EdgeInsets.all(12),
color: !estimated color: !estimated
? Theme.of(context) ? Theme.of(context)
.extension<StackColors>()! .extension<StackColors>()!

View file

@ -317,13 +317,12 @@ class _ConfirmTransactionViewState
style: STextStyles.smallMed12(context), style: STextStyles.smallMed12(context),
), ),
Text( Text(
"${Format.satoshiAmountToPrettyString( "${Format.satoshiAmountToPrettyString(transactionInfo["recipientAmt"] as int, ref.watch(
transactionInfo["recipientAmt"] as int, localeServiceChangeNotifierProvider
ref.watch( .select((value) => value.locale),
localeServiceChangeNotifierProvider ), ref.watch(
.select((value) => value.locale), managerProvider.select((value) => value.coin),
), ))} ${ref.watch(
)} ${ref.watch(
managerProvider.select((value) => value.coin), managerProvider.select((value) => value.coin),
).ticker}", ).ticker}",
style: STextStyles.itemSubtitle12(context), style: STextStyles.itemSubtitle12(context),
@ -344,13 +343,12 @@ class _ConfirmTransactionViewState
style: STextStyles.smallMed12(context), style: STextStyles.smallMed12(context),
), ),
Text( Text(
"${Format.satoshiAmountToPrettyString( "${Format.satoshiAmountToPrettyString(transactionInfo["fee"] as int, ref.watch(
transactionInfo["fee"] as int, localeServiceChangeNotifierProvider
ref.watch( .select((value) => value.locale),
localeServiceChangeNotifierProvider ), ref.watch(
.select((value) => value.locale), managerProvider.select((value) => value.coin),
), ))} ${ref.watch(
)} ${ref.watch(
managerProvider.select((value) => value.coin), managerProvider.select((value) => value.coin),
).ticker}", ).ticker}",
style: STextStyles.itemSubtitle12(context), style: STextStyles.itemSubtitle12(context),
@ -494,6 +492,7 @@ class _ConfirmTransactionViewState
localeServiceChangeNotifierProvider localeServiceChangeNotifierProvider
.select((value) => value.locale), .select((value) => value.locale),
), ),
coin,
)} ${coin.ticker}", )} ${coin.ticker}",
style: STextStyles style: STextStyles
.desktopTextExtraExtraSmall( .desktopTextExtraExtraSmall(
@ -638,11 +637,7 @@ class _ConfirmTransactionViewState
value: fee, value: fee,
locale: ref.watch(localeServiceChangeNotifierProvider locale: ref.watch(localeServiceChangeNotifierProvider
.select((value) => value.locale)), .select((value) => value.locale)),
decimalPlaces: coin == Coin.monero decimalPlaces: Constants.decimalPlacesForCoin(coin),
? Constants.decimalPlacesMonero
: coin == Coin.wownero
? Constants.decimalPlacesWownero
: Constants.decimalPlaces,
)} ${coin.ticker}", )} ${coin.ticker}",
style: STextStyles.itemSubtitle(context), style: STextStyles.itemSubtitle(context),
); );
@ -750,6 +745,9 @@ class _ConfirmTransactionViewState
localeServiceChangeNotifierProvider localeServiceChangeNotifierProvider
.select((value) => value.locale), .select((value) => value.locale),
), ),
ref.watch(
managerProvider.select((value) => value.coin),
),
)} ${ref.watch( )} ${ref.watch(
managerProvider.select((value) => value.coin), managerProvider.select((value) => value.coin),
).ticker}", ).ticker}",
@ -782,7 +780,7 @@ class _ConfirmTransactionViewState
: const EdgeInsets.all(0), : const EdgeInsets.all(0),
child: PrimaryButton( child: PrimaryButton(
label: "Send", label: "Send",
buttonHeight: ButtonHeight.l, buttonHeight: isDesktop ? ButtonHeight.l : null,
onPressed: () async { onPressed: () async {
final dynamic unlocked; final dynamic unlocked;

View file

@ -1,5 +1,6 @@
import 'dart:async'; import 'dart:async';
import 'package:cw_core/monero_transaction_priority.dart';
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/services.dart';
@ -30,6 +31,7 @@ import 'package:stackwallet/utilities/logger.dart';
import 'package:stackwallet/utilities/prefs.dart'; import 'package:stackwallet/utilities/prefs.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/utilities/util.dart';
import 'package:stackwallet/widgets/animated_text.dart'; import 'package:stackwallet/widgets/animated_text.dart';
import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart'; import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
import 'package:stackwallet/widgets/custom_buttons/blue_text_button.dart'; import 'package:stackwallet/widgets/custom_buttons/blue_text_button.dart';
@ -41,8 +43,6 @@ import 'package:stackwallet/widgets/stack_dialog.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';
import 'package:stackwallet/utilities/util.dart';
class SendView extends ConsumerStatefulWidget { class SendView extends ConsumerStatefulWidget {
const SendView({ const SendView({
Key? key, Key? key,
@ -211,29 +211,47 @@ class _SendViewState extends ConsumerState<SendView> {
} }
int fee; int fee;
if (coin == Coin.monero) {
MoneroTransactionPriority specialMoneroId;
switch (ref.read(feeRateTypeStateProvider.state).state) {
case FeeRateType.fast:
specialMoneroId = MoneroTransactionPriority.fast;
break;
case FeeRateType.average:
specialMoneroId = MoneroTransactionPriority.regular;
break;
case FeeRateType.slow:
specialMoneroId = MoneroTransactionPriority.slow;
break;
}
if (coin == Coin.firo || coin == Coin.firoTestNet) { fee = await manager.estimateFeeFor(amount, specialMoneroId.raw!);
cachedFees[amount] = Format.satoshisToAmount(fee, coin: coin)
.toStringAsFixed(Constants.decimalPlacesForCoin(coin));
return cachedFees[amount]!;
} else if (coin == Coin.firo || coin == Coin.firoTestNet) {
if (ref.read(publicPrivateBalanceStateProvider.state).state == if (ref.read(publicPrivateBalanceStateProvider.state).state ==
"Private") { "Private") {
fee = await manager.estimateFeeFor(amount, feeRate); fee = await manager.estimateFeeFor(amount, feeRate);
cachedFiroPrivateFees[amount] = Format.satoshisToAmount(fee) cachedFiroPrivateFees[amount] = Format.satoshisToAmount(fee, coin: coin)
.toStringAsFixed(Constants.decimalPlaces); .toStringAsFixed(Constants.decimalPlacesForCoin(coin));
return cachedFiroPrivateFees[amount]!; return cachedFiroPrivateFees[amount]!;
} else { } else {
fee = await (manager.wallet as FiroWallet) fee = await (manager.wallet as FiroWallet)
.estimateFeeForPublic(amount, feeRate); .estimateFeeForPublic(amount, feeRate);
cachedFiroPublicFees[amount] = Format.satoshisToAmount(fee) cachedFiroPublicFees[amount] = Format.satoshisToAmount(fee, coin: coin)
.toStringAsFixed(Constants.decimalPlaces); .toStringAsFixed(Constants.decimalPlacesForCoin(coin));
return cachedFiroPublicFees[amount]!; return cachedFiroPublicFees[amount]!;
} }
} else { } else {
fee = await manager.estimateFeeFor(amount, feeRate); fee = await manager.estimateFeeFor(amount, feeRate);
cachedFees[amount] = cachedFees[amount] = Format.satoshisToAmount(fee, coin: coin)
Format.satoshisToAmount(fee).toStringAsFixed(Constants.decimalPlaces); .toStringAsFixed(Constants.decimalPlacesForCoin(coin));
return cachedFees[amount]!; return cachedFees[amount]!;
} }
@ -296,8 +314,8 @@ class _SendViewState extends ConsumerState<SendView> {
}); });
} else { } else {
setState(() { setState(() {
_calculateFeesFuture = _calculateFeesFuture = calculateFees(
calculateFees(Format.decimalAmountToSatoshis(_amountToSend!)); Format.decimalAmountToSatoshis(_amountToSend!, coin));
}); });
} }
} }
@ -311,8 +329,8 @@ class _SendViewState extends ConsumerState<SendView> {
}); });
} else { } else {
setState(() { setState(() {
_calculateFeesFuture = _calculateFeesFuture = calculateFees(
calculateFees(Format.decimalAmountToSatoshis(_amountToSend!)); Format.decimalAmountToSatoshis(_amountToSend!, coin));
}); });
} }
} }
@ -354,8 +372,8 @@ class _SendViewState extends ConsumerState<SendView> {
}); });
} else { } else {
setState(() { setState(() {
_calculateFeesFuture = _calculateFeesFuture = calculateFees(
calculateFees(Format.decimalAmountToSatoshis(_amountToSend!)); Format.decimalAmountToSatoshis(_amountToSend!, coin));
}); });
} }
}); });
@ -492,7 +510,9 @@ class _SendViewState extends ConsumerState<SendView> {
onTap: () { onTap: () {
cryptoAmountController.text = cryptoAmountController.text =
_cachedBalance!.toStringAsFixed( _cachedBalance!.toStringAsFixed(
Constants.decimalPlaces); Constants
.decimalPlacesForCoin(
coin));
}, },
child: Container( child: Container(
color: Colors.transparent, color: Colors.transparent,
@ -781,8 +801,9 @@ class _SendViewState extends ConsumerState<SendView> {
.read( .read(
localeServiceChangeNotifierProvider) localeServiceChangeNotifierProvider)
.locale, .locale,
decimalPlaces: decimalPlaces: Constants
Constants.decimalPlaces, .decimalPlacesForCoin(
coin),
); );
amount.toString(); amount.toString();
_amountToSend = amount; _amountToSend = amount;
@ -1044,19 +1065,22 @@ class _SendViewState extends ConsumerState<SendView> {
(await firoWallet (await firoWallet
.availablePrivateBalance()) .availablePrivateBalance())
.toStringAsFixed( .toStringAsFixed(
Constants.decimalPlaces); Constants.decimalPlacesForCoin(
coin));
} else { } else {
cryptoAmountController.text = cryptoAmountController.text =
(await firoWallet (await firoWallet
.availablePublicBalance()) .availablePublicBalance())
.toStringAsFixed( .toStringAsFixed(
Constants.decimalPlaces); Constants.decimalPlacesForCoin(
coin));
} }
} else { } else {
cryptoAmountController.text = (await ref cryptoAmountController.text = (await ref
.read(provider) .read(provider)
.availableBalance) .availableBalance)
.toStringAsFixed(Constants.decimalPlaces); .toStringAsFixed(
Constants.decimalPlacesForCoin(coin));
} }
}, },
), ),
@ -1167,7 +1191,8 @@ class _SendViewState extends ConsumerState<SendView> {
? Decimal.zero ? Decimal.zero
: (baseAmount / _price).toDecimal( : (baseAmount / _price).toDecimal(
scaleOnInfinitePrecision: scaleOnInfinitePrecision:
Constants.decimalPlaces); Constants.decimalPlacesForCoin(
coin));
} }
if (_cachedAmountToSend != null && if (_cachedAmountToSend != null &&
_cachedAmountToSend == _amountToSend) { _cachedAmountToSend == _amountToSend) {
@ -1184,7 +1209,8 @@ class _SendViewState extends ConsumerState<SendView> {
locale: ref locale: ref
.read(localeServiceChangeNotifierProvider) .read(localeServiceChangeNotifierProvider)
.locale, .locale,
decimalPlaces: Constants.decimalPlaces, decimalPlaces:
Constants.decimalPlacesForCoin(coin),
); );
_cryptoAmountChangeLock = true; _cryptoAmountChangeLock = true;
@ -1506,7 +1532,7 @@ class _SendViewState extends ConsumerState<SendView> {
} }
final amount = Format.decimalAmountToSatoshis( final amount = Format.decimalAmountToSatoshis(
_amountToSend!); _amountToSend!, coin);
int availableBalance; int availableBalance;
if ((coin == Coin.firo || if ((coin == Coin.firo ||
coin == Coin.firoTestNet)) { coin == Coin.firoTestNet)) {
@ -1520,18 +1546,21 @@ class _SendViewState extends ConsumerState<SendView> {
Format.decimalAmountToSatoshis( Format.decimalAmountToSatoshis(
await (manager.wallet await (manager.wallet
as FiroWallet) as FiroWallet)
.availablePrivateBalance()); .availablePrivateBalance(),
coin);
} else { } else {
availableBalance = availableBalance =
Format.decimalAmountToSatoshis( Format.decimalAmountToSatoshis(
await (manager.wallet await (manager.wallet
as FiroWallet) as FiroWallet)
.availablePublicBalance()); .availablePublicBalance(),
coin);
} }
} else { } else {
availableBalance = availableBalance =
Format.decimalAmountToSatoshis( Format.decimalAmountToSatoshis(
await manager.availableBalance); await manager.availableBalance,
coin);
} }
// confirm send all // confirm send all

View file

@ -1,3 +1,4 @@
import 'package:cw_core/monero_transaction_priority.dart';
import 'package:decimal/decimal.dart'; 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';
@ -70,16 +71,27 @@ class _TransactionFeeSelectionSheetState
final manager = final manager =
ref.read(walletsChangeNotifierProvider).getManager(walletId); ref.read(walletsChangeNotifierProvider).getManager(walletId);
if ((coin == Coin.firo || coin == Coin.firoTestNet) && if (coin == Coin.monero || coin == Coin.wownero) {
final fee = await manager.estimateFeeFor(
amount, MoneroTransactionPriority.fast.raw!);
ref.read(feeSheetSessionCacheProvider).fast[amount] =
Format.satoshisToAmount(
fee,
coin: coin,
);
} else if ((coin == Coin.firo || coin == Coin.firoTestNet) &&
ref.read(publicPrivateBalanceStateProvider.state).state != ref.read(publicPrivateBalanceStateProvider.state).state !=
"Private") { "Private") {
ref.read(feeSheetSessionCacheProvider).fast[amount] = ref.read(feeSheetSessionCacheProvider).fast[amount] =
Format.satoshisToAmount(await (manager.wallet as FiroWallet) Format.satoshisToAmount(
.estimateFeeForPublic(amount, feeRate)); await (manager.wallet as FiroWallet)
.estimateFeeForPublic(amount, feeRate),
coin: coin);
} else { } else {
ref.read(feeSheetSessionCacheProvider).fast[amount] = ref.read(feeSheetSessionCacheProvider).fast[amount] =
Format.satoshisToAmount( Format.satoshisToAmount(
await manager.estimateFeeFor(amount, feeRate)); await manager.estimateFeeFor(amount, feeRate),
coin: coin);
} }
} }
return ref.read(feeSheetSessionCacheProvider).fast[amount]!; return ref.read(feeSheetSessionCacheProvider).fast[amount]!;
@ -88,17 +100,27 @@ class _TransactionFeeSelectionSheetState
if (ref.read(feeSheetSessionCacheProvider).average[amount] == null) { if (ref.read(feeSheetSessionCacheProvider).average[amount] == null) {
final manager = final manager =
ref.read(walletsChangeNotifierProvider).getManager(walletId); ref.read(walletsChangeNotifierProvider).getManager(walletId);
if (coin == Coin.monero || coin == Coin.wownero) {
if ((coin == Coin.firo || coin == Coin.firoTestNet) && final fee = await manager.estimateFeeFor(
amount, MoneroTransactionPriority.regular.raw!);
ref.read(feeSheetSessionCacheProvider).average[amount] =
Format.satoshisToAmount(
fee,
coin: coin,
);
} else if ((coin == Coin.firo || coin == Coin.firoTestNet) &&
ref.read(publicPrivateBalanceStateProvider.state).state != ref.read(publicPrivateBalanceStateProvider.state).state !=
"Private") { "Private") {
ref.read(feeSheetSessionCacheProvider).average[amount] = ref.read(feeSheetSessionCacheProvider).average[amount] =
Format.satoshisToAmount(await (manager.wallet as FiroWallet) Format.satoshisToAmount(
.estimateFeeForPublic(amount, feeRate)); await (manager.wallet as FiroWallet)
.estimateFeeForPublic(amount, feeRate),
coin: coin);
} else { } else {
ref.read(feeSheetSessionCacheProvider).average[amount] = ref.read(feeSheetSessionCacheProvider).average[amount] =
Format.satoshisToAmount( Format.satoshisToAmount(
await manager.estimateFeeFor(amount, feeRate)); await manager.estimateFeeFor(amount, feeRate),
coin: coin);
} }
} }
return ref.read(feeSheetSessionCacheProvider).average[amount]!; return ref.read(feeSheetSessionCacheProvider).average[amount]!;
@ -107,17 +129,27 @@ class _TransactionFeeSelectionSheetState
if (ref.read(feeSheetSessionCacheProvider).slow[amount] == null) { if (ref.read(feeSheetSessionCacheProvider).slow[amount] == null) {
final manager = final manager =
ref.read(walletsChangeNotifierProvider).getManager(walletId); ref.read(walletsChangeNotifierProvider).getManager(walletId);
if (coin == Coin.monero || coin == Coin.wownero) {
if ((coin == Coin.firo || coin == Coin.firoTestNet) && final fee = await manager.estimateFeeFor(
amount, MoneroTransactionPriority.slow.raw!);
ref.read(feeSheetSessionCacheProvider).slow[amount] =
Format.satoshisToAmount(
fee,
coin: coin,
);
} else if ((coin == Coin.firo || coin == Coin.firoTestNet) &&
ref.read(publicPrivateBalanceStateProvider.state).state != ref.read(publicPrivateBalanceStateProvider.state).state !=
"Private") { "Private") {
ref.read(feeSheetSessionCacheProvider).slow[amount] = ref.read(feeSheetSessionCacheProvider).slow[amount] =
Format.satoshisToAmount(await (manager.wallet as FiroWallet) Format.satoshisToAmount(
.estimateFeeForPublic(amount, feeRate)); await (manager.wallet as FiroWallet)
.estimateFeeForPublic(amount, feeRate),
coin: coin);
} else { } else {
ref.read(feeSheetSessionCacheProvider).slow[amount] = ref.read(feeSheetSessionCacheProvider).slow[amount] =
Format.satoshisToAmount( Format.satoshisToAmount(
await manager.estimateFeeFor(amount, feeRate)); await manager.estimateFeeFor(amount, feeRate),
coin: coin);
} }
} }
return ref.read(feeSheetSessionCacheProvider).slow[amount]!; return ref.read(feeSheetSessionCacheProvider).slow[amount]!;
@ -225,7 +257,7 @@ class _TransactionFeeSelectionSheetState
ref.read(feeRateTypeStateProvider.state).state = ref.read(feeRateTypeStateProvider.state).state =
FeeRateType.fast; FeeRateType.fast;
} }
String? fee = getAmount(FeeRateType.fast); String? fee = getAmount(FeeRateType.fast, manager.coin);
if (fee != null) { if (fee != null) {
widget.updateChosen(fee); widget.updateChosen(fee);
} }
@ -293,7 +325,7 @@ class _TransactionFeeSelectionSheetState
feeRate: feeObject!.fast, feeRate: feeObject!.fast,
amount: Format amount: Format
.decimalAmountToSatoshis( .decimalAmountToSatoshis(
amount)), amount, manager.coin)),
// future: manager.estimateFeeFor( // future: manager.estimateFeeFor(
// Format.decimalAmountToSatoshis( // Format.decimalAmountToSatoshis(
// amount), // amount),
@ -358,7 +390,8 @@ class _TransactionFeeSelectionSheetState
ref.read(feeRateTypeStateProvider.state).state = ref.read(feeRateTypeStateProvider.state).state =
FeeRateType.average; FeeRateType.average;
} }
String? fee = getAmount(FeeRateType.average); String? fee =
getAmount(FeeRateType.average, manager.coin);
if (fee != null) { if (fee != null) {
widget.updateChosen(fee); widget.updateChosen(fee);
} }
@ -424,7 +457,7 @@ class _TransactionFeeSelectionSheetState
feeRate: feeObject!.medium, feeRate: feeObject!.medium,
amount: Format amount: Format
.decimalAmountToSatoshis( .decimalAmountToSatoshis(
amount)), amount, manager.coin)),
// future: manager.estimateFeeFor( // future: manager.estimateFeeFor(
// Format.decimalAmountToSatoshis( // Format.decimalAmountToSatoshis(
// amount), // amount),
@ -489,7 +522,7 @@ class _TransactionFeeSelectionSheetState
ref.read(feeRateTypeStateProvider.state).state = ref.read(feeRateTypeStateProvider.state).state =
FeeRateType.slow; FeeRateType.slow;
} }
String? fee = getAmount(FeeRateType.slow); String? fee = getAmount(FeeRateType.slow, manager.coin);
print("fee $fee"); print("fee $fee");
if (fee != null) { if (fee != null) {
widget.updateChosen(fee); widget.updateChosen(fee);
@ -557,7 +590,7 @@ class _TransactionFeeSelectionSheetState
feeRate: feeObject!.slow, feeRate: feeObject!.slow,
amount: Format amount: Format
.decimalAmountToSatoshis( .decimalAmountToSatoshis(
amount)), amount, manager.coin)),
// future: manager.estimateFeeFor( // future: manager.estimateFeeFor(
// Format.decimalAmountToSatoshis( // Format.decimalAmountToSatoshis(
// amount), // amount),
@ -624,10 +657,10 @@ class _TransactionFeeSelectionSheetState
); );
} }
String? getAmount(FeeRateType feeRateType) { String? getAmount(FeeRateType feeRateType, Coin coin) {
try { try {
print(feeRateType); print(feeRateType);
var amount = Format.decimalAmountToSatoshis(this.amount); var amount = Format.decimalAmountToSatoshis(this.amount, coin);
print(amount); print(amount);
print(ref.read(feeSheetSessionCacheProvider).fast); print(ref.read(feeSheetSessionCacheProvider).fast);
print(ref.read(feeSheetSessionCacheProvider).average); print(ref.read(feeSheetSessionCacheProvider).average);

View file

@ -937,13 +937,9 @@ class _DesktopTransactionCardRowState
flex: 6, flex: 6,
child: Builder( child: Builder(
builder: (_) { builder: (_) {
final amount = coin == Coin.monero final amount = _transaction.amount;
? (_transaction.amount ~/ 10000)
: coin == Coin.wownero
? (_transaction.amount ~/ 1000)
: _transaction.amount;
return Text( return Text(
"$prefix${Format.satoshiAmountToPrettyString(amount, locale)} ${coin.ticker}", "$prefix${Format.satoshiAmountToPrettyString(amount, locale, coin)} ${coin.ticker}",
style: STextStyles.desktopTextExtraExtraSmall(context) style: STextStyles.desktopTextExtraExtraSmall(context)
.copyWith( .copyWith(
color: Theme.of(context) color: Theme.of(context)
@ -960,17 +956,12 @@ class _DesktopTransactionCardRowState
flex: 4, flex: 4,
child: Builder( child: Builder(
builder: (_) { builder: (_) {
// TODO: modify Format.<functions> to take optional Coin parameter so this type oif check isn't done in ui
int value = _transaction.amount; int value = _transaction.amount;
if (coin == Coin.monero) {
value = (value ~/ 10000);
} else if (coin == Coin.wownero) {
value = (value ~/ 1000);
}
return Text( return Text(
"$prefix${Format.localizedStringAsFixed( "$prefix${Format.localizedStringAsFixed(
value: Format.satoshisToAmount(value) * price, value: Format.satoshisToAmount(value, coin: coin) *
price,
locale: locale, locale: locale,
decimalPlaces: 2, decimalPlaces: 2,
)} $baseCurrency", )} $baseCurrency",

View file

@ -78,8 +78,8 @@ class _TransactionDetailsViewState
walletId = widget.walletId; walletId = widget.walletId;
coin = widget.coin; coin = widget.coin;
amount = Format.satoshisToAmount(_transaction.amount); amount = Format.satoshisToAmount(_transaction.amount, coin: coin);
fee = Format.satoshisToAmount(_transaction.fees); fee = Format.satoshisToAmount(_transaction.fees, coin: coin);
if ((coin == Coin.firo || coin == Coin.firoTestNet) && if ((coin == Coin.firo || coin == Coin.firoTestNet) &&
_transaction.subType == "mint") { _transaction.subType == "mint") {
@ -418,21 +418,15 @@ class _TransactionDetailsViewState
children: [ children: [
SelectableText( SelectableText(
"$amountPrefix${Format.localizedStringAsFixed( "$amountPrefix${Format.localizedStringAsFixed(
value: coin == Coin.monero value: amount,
? (amount / 10000.toDecimal())
.toDecimal()
: coin == Coin.wownero
? (amount /
1000.toDecimal())
.toDecimal()
: amount,
locale: ref.watch( locale: ref.watch(
localeServiceChangeNotifierProvider localeServiceChangeNotifierProvider
.select( .select(
(value) => value.locale), (value) => value.locale),
), ),
decimalPlaces: decimalPlaces:
Constants.decimalPlaces, Constants.decimalPlacesForCoin(
coin),
)} ${coin.ticker}", )} ${coin.ticker}",
style: isDesktop style: isDesktop
? STextStyles ? STextStyles
@ -454,11 +448,21 @@ class _TransactionDetailsViewState
(value) => (value) =>
value.externalCalls))) value.externalCalls)))
SelectableText( SelectableText(
"$amountPrefix${Format.localizedStringAsFixed(value: (coin == Coin.monero ? (amount / 10000.toDecimal()).toDecimal() : coin == Coin.wownero ? (amount / 1000.toDecimal()).toDecimal() : amount) * ref.watch(priceAnd24hChangeNotifierProvider.select((value) => value.getPrice(coin).item1)), locale: ref.watch( "$amountPrefix${Format.localizedStringAsFixed(
localeServiceChangeNotifierProvider value: amount *
.select((value) => ref.watch(
value.locale), priceAnd24hChangeNotifierProvider
), decimalPlaces: 2)} ${ref.watch( .select((value) => value
.getPrice(coin)
.item1),
),
locale: ref.watch(
localeServiceChangeNotifierProvider
.select((value) =>
value.locale),
),
decimalPlaces: 2,
)} ${ref.watch(
prefsChangeNotifierProvider prefsChangeNotifierProvider
.select( .select(
(value) => value.currency, (value) => value.currency,
@ -834,32 +838,22 @@ class _TransactionDetailsViewState
final feeString = showFeePending final feeString = showFeePending
? _transaction.confirmedStatus ? _transaction.confirmedStatus
? Format.localizedStringAsFixed( ? Format.localizedStringAsFixed(
value: coin == Coin.monero value: fee,
? (fee / 10000.toDecimal())
.toDecimal()
: coin == Coin.wownero
? (fee / 1000.toDecimal())
.toDecimal()
: fee,
locale: ref.watch( locale: ref.watch(
localeServiceChangeNotifierProvider localeServiceChangeNotifierProvider
.select( .select(
(value) => value.locale)), (value) => value.locale)),
decimalPlaces: decimalPlaces:
Constants.decimalPlaces) Constants.decimalPlacesForCoin(
coin))
: "Pending" : "Pending"
: Format.localizedStringAsFixed( : Format.localizedStringAsFixed(
value: coin == Coin.monero value: fee,
? (fee / 10000.toDecimal())
.toDecimal()
: coin == Coin.wownero
? (fee / 1000.toDecimal())
.toDecimal()
: fee,
locale: ref.watch( locale: ref.watch(
localeServiceChangeNotifierProvider localeServiceChangeNotifierProvider
.select((value) => value.locale)), .select((value) => value.locale)),
decimalPlaces: Constants.decimalPlaces); decimalPlaces:
Constants.decimalPlacesForCoin(coin));
return Row( return Row(
mainAxisAlignment: mainAxisAlignment:

View file

@ -79,7 +79,7 @@ class _TransactionSearchViewState
String amount = ""; String amount = "";
if (filterState.amount != null) { if (filterState.amount != null) {
amount = Format.satoshiAmountToPrettyString(filterState.amount!, amount = Format.satoshiAmountToPrettyString(filterState.amount!,
ref.read(localeServiceChangeNotifierProvider).locale); ref.read(localeServiceChangeNotifierProvider).locale, widget.coin);
} }
_amountTextEditingController.text = amount; _amountTextEditingController.text = amount;
} }
@ -967,22 +967,7 @@ class _TransactionSearchViewState
} }
int? amount; int? amount;
if (amountDecimal != null) { if (amountDecimal != null) {
if (widget.coin == Coin.monero) { amount = Format.decimalAmountToSatoshis(amountDecimal, widget.coin);
amount = (amountDecimal * Decimal.fromInt(Constants.satsPerCoinMonero))
.floor()
.toBigInt()
.toInt();
} else if (widget.coin == Coin.wownero) {
amount = (amountDecimal * Decimal.fromInt(Constants.satsPerCoinWownero))
.floor()
.toBigInt()
.toInt();
} else {
amount = (amountDecimal * Decimal.fromInt(Constants.satsPerCoin))
.floor()
.toBigInt()
.toInt();
}
} }
final TransactionFilter filter = TransactionFilter( final TransactionFilter filter = TransactionFilter(

View file

@ -1,3 +1,4 @@
import 'package:cw_core/monero_transaction_priority.dart';
import 'package:decimal/decimal.dart'; import 'package:decimal/decimal.dart';
import 'package:dropdown_button2/dropdown_button2.dart'; import 'package:dropdown_button2/dropdown_button2.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
@ -55,16 +56,27 @@ class _DesktopFeeDropDownState extends ConsumerState<DesktopFeeDropDown> {
final manager = final manager =
ref.read(walletsChangeNotifierProvider).getManager(walletId); ref.read(walletsChangeNotifierProvider).getManager(walletId);
if ((coin == Coin.firo || coin == Coin.firoTestNet) && if (coin == Coin.monero || coin == Coin.wownero) {
final fee = await manager.estimateFeeFor(
amount, MoneroTransactionPriority.fast.raw!);
ref.read(feeSheetSessionCacheProvider).fast[amount] =
Format.satoshisToAmount(
fee,
coin: coin,
);
} else if ((coin == Coin.firo || coin == Coin.firoTestNet) &&
ref.read(publicPrivateBalanceStateProvider.state).state != ref.read(publicPrivateBalanceStateProvider.state).state !=
"Private") { "Private") {
ref.read(feeSheetSessionCacheProvider).fast[amount] = ref.read(feeSheetSessionCacheProvider).fast[amount] =
Format.satoshisToAmount(await (manager.wallet as FiroWallet) Format.satoshisToAmount(
.estimateFeeForPublic(amount, feeRate)); await (manager.wallet as FiroWallet)
.estimateFeeForPublic(amount, feeRate),
coin: coin);
} else { } else {
ref.read(feeSheetSessionCacheProvider).fast[amount] = ref.read(feeSheetSessionCacheProvider).fast[amount] =
Format.satoshisToAmount( Format.satoshisToAmount(
await manager.estimateFeeFor(amount, feeRate)); await manager.estimateFeeFor(amount, feeRate),
coin: coin);
} }
} }
return ref.read(feeSheetSessionCacheProvider).fast[amount]!; return ref.read(feeSheetSessionCacheProvider).fast[amount]!;
@ -74,16 +86,27 @@ class _DesktopFeeDropDownState extends ConsumerState<DesktopFeeDropDown> {
final manager = final manager =
ref.read(walletsChangeNotifierProvider).getManager(walletId); ref.read(walletsChangeNotifierProvider).getManager(walletId);
if ((coin == Coin.firo || coin == Coin.firoTestNet) && if (coin == Coin.monero || coin == Coin.wownero) {
final fee = await manager.estimateFeeFor(
amount, MoneroTransactionPriority.regular.raw!);
ref.read(feeSheetSessionCacheProvider).average[amount] =
Format.satoshisToAmount(
fee,
coin: coin,
);
} else if ((coin == Coin.firo || coin == Coin.firoTestNet) &&
ref.read(publicPrivateBalanceStateProvider.state).state != ref.read(publicPrivateBalanceStateProvider.state).state !=
"Private") { "Private") {
ref.read(feeSheetSessionCacheProvider).average[amount] = ref.read(feeSheetSessionCacheProvider).average[amount] =
Format.satoshisToAmount(await (manager.wallet as FiroWallet) Format.satoshisToAmount(
.estimateFeeForPublic(amount, feeRate)); await (manager.wallet as FiroWallet)
.estimateFeeForPublic(amount, feeRate),
coin: coin);
} else { } else {
ref.read(feeSheetSessionCacheProvider).average[amount] = ref.read(feeSheetSessionCacheProvider).average[amount] =
Format.satoshisToAmount( Format.satoshisToAmount(
await manager.estimateFeeFor(amount, feeRate)); await manager.estimateFeeFor(amount, feeRate),
coin: coin);
} }
} }
return ref.read(feeSheetSessionCacheProvider).average[amount]!; return ref.read(feeSheetSessionCacheProvider).average[amount]!;
@ -93,47 +116,33 @@ class _DesktopFeeDropDownState extends ConsumerState<DesktopFeeDropDown> {
final manager = final manager =
ref.read(walletsChangeNotifierProvider).getManager(walletId); ref.read(walletsChangeNotifierProvider).getManager(walletId);
if ((coin == Coin.firo || coin == Coin.firoTestNet) && if (coin == Coin.monero || coin == Coin.wownero) {
final fee = await manager.estimateFeeFor(
amount, MoneroTransactionPriority.slow.raw!);
ref.read(feeSheetSessionCacheProvider).slow[amount] =
Format.satoshisToAmount(
fee,
coin: coin,
);
} else if ((coin == Coin.firo || coin == Coin.firoTestNet) &&
ref.read(publicPrivateBalanceStateProvider.state).state != ref.read(publicPrivateBalanceStateProvider.state).state !=
"Private") { "Private") {
ref.read(feeSheetSessionCacheProvider).slow[amount] = ref.read(feeSheetSessionCacheProvider).slow[amount] =
Format.satoshisToAmount(await (manager.wallet as FiroWallet) Format.satoshisToAmount(
.estimateFeeForPublic(amount, feeRate)); await (manager.wallet as FiroWallet)
.estimateFeeForPublic(amount, feeRate),
coin: coin);
} else { } else {
ref.read(feeSheetSessionCacheProvider).slow[amount] = ref.read(feeSheetSessionCacheProvider).slow[amount] =
Format.satoshisToAmount( Format.satoshisToAmount(
await manager.estimateFeeFor(amount, feeRate)); await manager.estimateFeeFor(amount, feeRate),
coin: coin);
} }
} }
return ref.read(feeSheetSessionCacheProvider).slow[amount]!; return ref.read(feeSheetSessionCacheProvider).slow[amount]!;
} }
} }
String estimatedTimeToBeIncludedInNextBlock(
int targetBlockTime, int estimatedNumberOfBlocks) {
int time = targetBlockTime * estimatedNumberOfBlocks;
int hours = (time / 3600).floor();
if (hours > 1) {
return "~$hours hours";
} else if (hours == 1) {
return "~$hours hour";
}
// less than an hour
final string = (time / 60).toStringAsFixed(1);
if (string == "1.0") {
return "~1 minute";
} else {
if (string.endsWith(".0")) {
return "~${(time / 60).floor()} minutes";
}
return "~$string minutes";
}
}
@override @override
void initState() { void initState() {
walletId = widget.walletId; walletId = widget.walletId;
@ -307,7 +316,7 @@ class FeeDropDownChild extends ConsumerWidget {
return FutureBuilder( return FutureBuilder(
future: feeFor( future: feeFor(
coin: manager.coin, coin: manager.coin,
feeRateType: FeeRateType.fast, feeRateType: feeRateType,
feeRate: feeRateType == FeeRateType.fast feeRate: feeRateType == FeeRateType.fast
? feeObject!.fast ? feeObject!.fast
: feeRateType == FeeRateType.slow : feeRateType == FeeRateType.slow
@ -315,6 +324,7 @@ class FeeDropDownChild extends ConsumerWidget {
: feeObject!.medium, : feeObject!.medium,
amount: Format.decimalAmountToSatoshis( amount: Format.decimalAmountToSatoshis(
ref.watch(sendAmountProvider.state).state, ref.watch(sendAmountProvider.state).state,
manager.coin,
), ),
), ),
builder: (_, AsyncSnapshot<Decimal> snapshot) { builder: (_, AsyncSnapshot<Decimal> snapshot) {

View file

@ -161,20 +161,22 @@ class _DesktopSendState extends ConsumerState<DesktopSend> {
return; return;
} }
final amount = Format.decimalAmountToSatoshis(_amountToSend!); final amount = Format.decimalAmountToSatoshis(_amountToSend!, coin);
int availableBalance; int availableBalance;
if ((coin == Coin.firo || coin == Coin.firoTestNet)) { if ((coin == Coin.firo || coin == Coin.firoTestNet)) {
if (ref.read(publicPrivateBalanceStateProvider.state).state == if (ref.read(publicPrivateBalanceStateProvider.state).state ==
"Private") { "Private") {
availableBalance = Format.decimalAmountToSatoshis( availableBalance = Format.decimalAmountToSatoshis(
await (manager.wallet as FiroWallet).availablePrivateBalance()); await (manager.wallet as FiroWallet).availablePrivateBalance(),
coin);
} else { } else {
availableBalance = Format.decimalAmountToSatoshis( availableBalance = Format.decimalAmountToSatoshis(
await (manager.wallet as FiroWallet).availablePublicBalance()); await (manager.wallet as FiroWallet).availablePublicBalance(),
coin);
} }
} else { } else {
availableBalance = availableBalance =
Format.decimalAmountToSatoshis(await manager.availableBalance); Format.decimalAmountToSatoshis(await manager.availableBalance, coin);
} }
// confirm send all // confirm send all
@ -642,7 +644,7 @@ class _DesktopSendState extends ConsumerState<DesktopSend> {
cryptoAmountController.text = Format.localizedStringAsFixed( cryptoAmountController.text = Format.localizedStringAsFixed(
value: amount, value: amount,
locale: ref.read(localeServiceChangeNotifierProvider).locale, locale: ref.read(localeServiceChangeNotifierProvider).locale,
decimalPlaces: Constants.decimalPlaces, decimalPlaces: Constants.decimalPlacesForCoin(coin),
); );
amount.toString(); amount.toString();
_amountToSend = amount; _amountToSend = amount;
@ -709,8 +711,8 @@ class _DesktopSendState extends ConsumerState<DesktopSend> {
} else { } else {
_amountToSend = baseAmount <= Decimal.zero _amountToSend = baseAmount <= Decimal.zero
? Decimal.zero ? Decimal.zero
: (baseAmount / _price) : (baseAmount / _price).toDecimal(
.toDecimal(scaleOnInfinitePrecision: Constants.decimalPlaces); scaleOnInfinitePrecision: Constants.decimalPlacesForCoin(coin));
} }
if (_cachedAmountToSend != null && _cachedAmountToSend == _amountToSend) { if (_cachedAmountToSend != null && _cachedAmountToSend == _amountToSend) {
return; return;
@ -722,7 +724,7 @@ class _DesktopSendState extends ConsumerState<DesktopSend> {
final amountString = Format.localizedStringAsFixed( final amountString = Format.localizedStringAsFixed(
value: _amountToSend!, value: _amountToSend!,
locale: ref.read(localeServiceChangeNotifierProvider).locale, locale: ref.read(localeServiceChangeNotifierProvider).locale,
decimalPlaces: Constants.decimalPlaces, decimalPlaces: Constants.decimalPlacesForCoin(coin),
); );
_cryptoAmountChangeLock = true; _cryptoAmountChangeLock = true;
@ -752,18 +754,18 @@ class _DesktopSendState extends ConsumerState<DesktopSend> {
"Private") { "Private") {
cryptoAmountController.text = cryptoAmountController.text =
(await firoWallet.availablePrivateBalance()) (await firoWallet.availablePrivateBalance())
.toStringAsFixed(Constants.decimalPlaces); .toStringAsFixed(Constants.decimalPlacesForCoin(coin));
} else { } else {
cryptoAmountController.text = cryptoAmountController.text =
(await firoWallet.availablePublicBalance()) (await firoWallet.availablePublicBalance())
.toStringAsFixed(Constants.decimalPlaces); .toStringAsFixed(Constants.decimalPlacesForCoin(coin));
} }
} else { } else {
cryptoAmountController.text = (await ref cryptoAmountController.text = (await ref
.read(walletsChangeNotifierProvider) .read(walletsChangeNotifierProvider)
.getManager(walletId) .getManager(walletId)
.availableBalance) .availableBalance)
.toStringAsFixed(Constants.decimalPlaces); .toStringAsFixed(Constants.decimalPlacesForCoin(coin));
} }
} }

View file

@ -43,6 +43,58 @@ class _UnlockWalletKeysDesktopState
bool continueEnabled = false; bool continueEnabled = false;
bool hidePassword = true; bool hidePassword = true;
Future<void> enterPassphrase() async {
unawaited(
showDialog(
context: context,
builder: (context) => Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: const [
LoadingIndicator(
width: 200,
height: 200,
),
],
),
),
);
await Future<void>.delayed(const Duration(seconds: 1));
final verified = await ref
.read(storageCryptoHandlerProvider)
.verifyPassphrase(passwordController.text);
if (verified) {
Navigator.of(context, rootNavigator: true).pop();
final words = await ref
.read(walletsChangeNotifierProvider)
.getManager(widget.walletId)
.mnemonic;
if (mounted) {
await Navigator.of(context).pushReplacementNamed(
WalletKeysDesktopPopup.routeName,
arguments: words,
);
}
} else {
Navigator.of(context, rootNavigator: true).pop();
await Future<void>.delayed(const Duration(milliseconds: 300));
unawaited(
showFloatingFlushBar(
type: FlushBarType.warning,
message: "Invalid passphrase!",
context: context,
),
);
}
}
@override @override
void initState() { void initState() {
passwordController = TextEditingController(); passwordController = TextEditingController();
@ -120,6 +172,12 @@ class _UnlockWalletKeysDesktopState
obscureText: hidePassword, obscureText: hidePassword,
enableSuggestions: false, enableSuggestions: false,
autocorrect: false, autocorrect: false,
autofocus: true,
onSubmitted: (_) {
if (continueEnabled) {
enterPassphrase();
}
},
decoration: standardInputDecoration( decoration: standardInputDecoration(
"Enter password", "Enter password",
passwordFocusNode, passwordFocusNode,

View file

@ -200,19 +200,21 @@ class BitcoinWallet extends CoinServiceAPI {
Future<Decimal> get availableBalance async { Future<Decimal> get availableBalance async {
final data = await utxoData; final data = await utxoData;
return Format.satoshisToAmount( return Format.satoshisToAmount(
data.satoshiBalance - data.satoshiBalanceUnconfirmed); data.satoshiBalance - data.satoshiBalanceUnconfirmed,
coin: coin);
} }
@override @override
Future<Decimal> get pendingBalance async { Future<Decimal> get pendingBalance async {
final data = await utxoData; final data = await utxoData;
return Format.satoshisToAmount(data.satoshiBalanceUnconfirmed); return Format.satoshisToAmount(data.satoshiBalanceUnconfirmed, coin: coin);
} }
@override @override
Future<Decimal> get balanceMinusMaxFee async => Future<Decimal> get balanceMinusMaxFee async =>
(await availableBalance) - (await availableBalance) -
(Decimal.fromInt((await maxFee)) / Decimal.fromInt(Constants.satsPerCoin)) (Decimal.fromInt((await maxFee)) /
Decimal.fromInt(Constants.satsPerCoin(coin)))
.toDecimal(); .toDecimal();
@override @override
@ -222,13 +224,13 @@ class BitcoinWallet extends CoinServiceAPI {
.get<dynamic>(boxName: walletId, key: 'totalBalance') as int?; .get<dynamic>(boxName: walletId, key: 'totalBalance') as int?;
if (totalBalance == null) { if (totalBalance == null) {
final data = await utxoData; final data = await utxoData;
return Format.satoshisToAmount(data.satoshiBalance); return Format.satoshisToAmount(data.satoshiBalance, coin: coin);
} else { } else {
return Format.satoshisToAmount(totalBalance); return Format.satoshisToAmount(totalBalance, coin: coin);
} }
} }
final data = await utxoData; final data = await utxoData;
return Format.satoshisToAmount(data.satoshiBalance); return Format.satoshisToAmount(data.satoshiBalance, coin: coin);
} }
@override @override
@ -266,7 +268,8 @@ class BitcoinWallet extends CoinServiceAPI {
@override @override
Future<int> get maxFee async { Future<int> get maxFee async {
final fee = (await fees).fast as String; final fee = (await fees).fast as String;
final satsFee = Decimal.parse(fee) * Decimal.fromInt(Constants.satsPerCoin); final satsFee =
Decimal.parse(fee) * Decimal.fromInt(Constants.satsPerCoin(coin));
return satsFee.floor().toBigInt().toInt(); return satsFee.floor().toBigInt().toInt();
} }
@ -1093,7 +1096,8 @@ class BitcoinWallet extends CoinServiceAPI {
// check for send all // check for send all
bool isSendAll = false; bool isSendAll = false;
final balance = Format.decimalAmountToSatoshis(await availableBalance); final balance =
Format.decimalAmountToSatoshis(await availableBalance, coin);
if (satoshiAmount == balance) { if (satoshiAmount == balance) {
isSendAll = true; isSendAll = true;
} }
@ -1297,7 +1301,7 @@ class BitcoinWallet extends CoinServiceAPI {
final String worthNow = Format.localizedStringAsFixed( final String worthNow = Format.localizedStringAsFixed(
value: value:
((currentPrice * Decimal.fromInt(txData["recipientAmt"] as int)) / ((currentPrice * Decimal.fromInt(txData["recipientAmt"] as int)) /
Decimal.fromInt(Constants.satsPerCoin)) Decimal.fromInt(Constants.satsPerCoin(coin)))
.toDecimal(scaleOnInfinitePrecision: 2), .toDecimal(scaleOnInfinitePrecision: 2),
decimalPlaces: 2, decimalPlaces: 2,
locale: locale!); locale: locale!);
@ -1497,9 +1501,9 @@ class BitcoinWallet extends CoinServiceAPI {
numberOfBlocksFast: f, numberOfBlocksFast: f,
numberOfBlocksAverage: m, numberOfBlocksAverage: m,
numberOfBlocksSlow: s, numberOfBlocksSlow: s,
fast: Format.decimalAmountToSatoshis(fast), fast: Format.decimalAmountToSatoshis(fast, coin),
medium: Format.decimalAmountToSatoshis(medium), medium: Format.decimalAmountToSatoshis(medium, coin),
slow: Format.decimalAmountToSatoshis(slow), slow: Format.decimalAmountToSatoshis(slow, coin),
); );
Logging.instance.log("fetched fees: $feeObject", level: LogLevel.Info); Logging.instance.log("fetched fees: $feeObject", level: LogLevel.Info);
@ -1968,7 +1972,7 @@ class BitcoinWallet extends CoinServiceAPI {
utxo["status"]["block_time"] = txn["blocktime"]; utxo["status"]["block_time"] = txn["blocktime"];
final fiatValue = ((Decimal.fromInt(value) * currentPrice) / final fiatValue = ((Decimal.fromInt(value) * currentPrice) /
Decimal.fromInt(Constants.satsPerCoin)) Decimal.fromInt(Constants.satsPerCoin(coin)))
.toDecimal(scaleOnInfinitePrecision: 2); .toDecimal(scaleOnInfinitePrecision: 2);
utxo["rawWorth"] = fiatValue; utxo["rawWorth"] = fiatValue;
utxo["fiatWorth"] = fiatValue.toString(); utxo["fiatWorth"] = fiatValue.toString();
@ -1978,15 +1982,16 @@ class BitcoinWallet extends CoinServiceAPI {
Decimal currencyBalanceRaw = Decimal currencyBalanceRaw =
((Decimal.fromInt(satoshiBalance) * currentPrice) / ((Decimal.fromInt(satoshiBalance) * currentPrice) /
Decimal.fromInt(Constants.satsPerCoin)) Decimal.fromInt(Constants.satsPerCoin(coin)))
.toDecimal(scaleOnInfinitePrecision: 2); .toDecimal(scaleOnInfinitePrecision: 2);
final Map<String, dynamic> result = { final Map<String, dynamic> result = {
"total_user_currency": currencyBalanceRaw.toString(), "total_user_currency": currencyBalanceRaw.toString(),
"total_sats": satoshiBalance, "total_sats": satoshiBalance,
"total_btc": (Decimal.fromInt(satoshiBalance) / "total_btc": (Decimal.fromInt(satoshiBalance) /
Decimal.fromInt(Constants.satsPerCoin)) Decimal.fromInt(Constants.satsPerCoin(coin)))
.toDecimal(scaleOnInfinitePrecision: Constants.decimalPlaces) .toDecimal(
scaleOnInfinitePrecision: Constants.decimalPlacesForCoin(coin))
.toString(), .toString(),
"outputArray": outputArray, "outputArray": outputArray,
"unconfirmed": satoshiBalancePending, "unconfirmed": satoshiBalancePending,
@ -2532,7 +2537,7 @@ class BitcoinWallet extends CoinServiceAPI {
if (prevOut == out["n"]) { if (prevOut == out["n"]) {
inputAmtSentFromWallet += inputAmtSentFromWallet +=
(Decimal.parse(out["value"]!.toString()) * (Decimal.parse(out["value"]!.toString()) *
Decimal.fromInt(Constants.satsPerCoin)) Decimal.fromInt(Constants.satsPerCoin(coin)))
.toBigInt() .toBigInt()
.toInt(); .toInt();
} }
@ -2545,7 +2550,7 @@ class BitcoinWallet extends CoinServiceAPI {
final String address = output["scriptPubKey"]!["address"] as String; final String address = output["scriptPubKey"]!["address"] as String;
final value = output["value"]!; final value = output["value"]!;
final _value = (Decimal.parse(value.toString()) * final _value = (Decimal.parse(value.toString()) *
Decimal.fromInt(Constants.satsPerCoin)) Decimal.fromInt(Constants.satsPerCoin(coin)))
.toBigInt() .toBigInt()
.toInt(); .toInt();
totalOutput += _value; totalOutput += _value;
@ -2570,7 +2575,7 @@ class BitcoinWallet extends CoinServiceAPI {
final address = output["scriptPubKey"]["address"]; final address = output["scriptPubKey"]["address"];
if (address != null) { if (address != null) {
final value = (Decimal.parse(output["value"].toString()) * final value = (Decimal.parse(output["value"].toString()) *
Decimal.fromInt(Constants.satsPerCoin)) Decimal.fromInt(Constants.satsPerCoin(coin)))
.toBigInt() .toBigInt()
.toInt(); .toInt();
totalOut += value; totalOut += value;
@ -2593,7 +2598,7 @@ class BitcoinWallet extends CoinServiceAPI {
for (final out in tx["vout"] as List) { for (final out in tx["vout"] as List) {
if (prevOut == out["n"]) { if (prevOut == out["n"]) {
totalIn += (Decimal.parse(out["value"].toString()) * totalIn += (Decimal.parse(out["value"].toString()) *
Decimal.fromInt(Constants.satsPerCoin)) Decimal.fromInt(Constants.satsPerCoin(coin)))
.toBigInt() .toBigInt()
.toInt(); .toInt();
} }
@ -2615,7 +2620,7 @@ class BitcoinWallet extends CoinServiceAPI {
midSortedTx["amount"] = inputAmtSentFromWallet; midSortedTx["amount"] = inputAmtSentFromWallet;
final String worthNow = final String worthNow =
((currentPrice * Decimal.fromInt(inputAmtSentFromWallet)) / ((currentPrice * Decimal.fromInt(inputAmtSentFromWallet)) /
Decimal.fromInt(Constants.satsPerCoin)) Decimal.fromInt(Constants.satsPerCoin(coin)))
.toDecimal(scaleOnInfinitePrecision: 2) .toDecimal(scaleOnInfinitePrecision: 2)
.toStringAsFixed(2); .toStringAsFixed(2);
midSortedTx["worthNow"] = worthNow; midSortedTx["worthNow"] = worthNow;
@ -2625,7 +2630,7 @@ class BitcoinWallet extends CoinServiceAPI {
midSortedTx["amount"] = outputAmtAddressedToWallet; midSortedTx["amount"] = outputAmtAddressedToWallet;
final worthNow = final worthNow =
((currentPrice * Decimal.fromInt(outputAmtAddressedToWallet)) / ((currentPrice * Decimal.fromInt(outputAmtAddressedToWallet)) /
Decimal.fromInt(Constants.satsPerCoin)) Decimal.fromInt(Constants.satsPerCoin(coin)))
.toDecimal(scaleOnInfinitePrecision: 2) .toDecimal(scaleOnInfinitePrecision: 2)
.toStringAsFixed(2); .toStringAsFixed(2);
midSortedTx["worthNow"] = worthNow; midSortedTx["worthNow"] = worthNow;
@ -3753,7 +3758,8 @@ class BitcoinWallet extends CoinServiceAPI {
@override @override
Future<int> estimateFeeFor(int satoshiAmount, int feeRate) async { Future<int> estimateFeeFor(int satoshiAmount, int feeRate) async {
final available = Format.decimalAmountToSatoshis(await availableBalance); final available =
Format.decimalAmountToSatoshis(await availableBalance, coin);
if (available == satoshiAmount) { if (available == satoshiAmount) {
return satoshiAmount - sweepAllEstimate(feeRate); return satoshiAmount - sweepAllEstimate(feeRate);

View file

@ -170,19 +170,21 @@ class BitcoinCashWallet extends CoinServiceAPI {
Future<Decimal> get availableBalance async { Future<Decimal> get availableBalance async {
final data = await utxoData; final data = await utxoData;
return Format.satoshisToAmount( return Format.satoshisToAmount(
data.satoshiBalance - data.satoshiBalanceUnconfirmed); data.satoshiBalance - data.satoshiBalanceUnconfirmed,
coin: coin);
} }
@override @override
Future<Decimal> get pendingBalance async { Future<Decimal> get pendingBalance async {
final data = await utxoData; final data = await utxoData;
return Format.satoshisToAmount(data.satoshiBalanceUnconfirmed); return Format.satoshisToAmount(data.satoshiBalanceUnconfirmed, coin: coin);
} }
@override @override
Future<Decimal> get balanceMinusMaxFee async => Future<Decimal> get balanceMinusMaxFee async =>
(await availableBalance) - (await availableBalance) -
(Decimal.fromInt((await maxFee)) / Decimal.fromInt(Constants.satsPerCoin)) (Decimal.fromInt((await maxFee)) /
Decimal.fromInt(Constants.satsPerCoin(coin)))
.toDecimal(); .toDecimal();
@override @override
@ -192,13 +194,13 @@ class BitcoinCashWallet extends CoinServiceAPI {
.get<dynamic>(boxName: walletId, key: 'totalBalance') as int?; .get<dynamic>(boxName: walletId, key: 'totalBalance') as int?;
if (totalBalance == null) { if (totalBalance == null) {
final data = await utxoData; final data = await utxoData;
return Format.satoshisToAmount(data.satoshiBalance); return Format.satoshisToAmount(data.satoshiBalance, coin: coin);
} else { } else {
return Format.satoshisToAmount(totalBalance); return Format.satoshisToAmount(totalBalance, coin: coin);
} }
} }
final data = await utxoData; final data = await utxoData;
return Format.satoshisToAmount(data.satoshiBalance); return Format.satoshisToAmount(data.satoshiBalance, coin: coin);
} }
@override @override
@ -232,8 +234,8 @@ class BitcoinCashWallet extends CoinServiceAPI {
@override @override
Future<int> get maxFee async { Future<int> get maxFee async {
final fee = (await fees).fast; final fee = (await fees).fast;
final satsFee = final satsFee = Format.satoshisToAmount(fee, coin: coin) *
Format.satoshisToAmount(fee) * Decimal.fromInt(Constants.satsPerCoin); Decimal.fromInt(Constants.satsPerCoin(coin));
return satsFee.floor().toBigInt().toInt(); return satsFee.floor().toBigInt().toInt();
} }
@ -988,7 +990,8 @@ class BitcoinCashWallet extends CoinServiceAPI {
} }
// check for send all // check for send all
bool isSendAll = false; bool isSendAll = false;
final balance = Format.decimalAmountToSatoshis(await availableBalance); final balance =
Format.decimalAmountToSatoshis(await availableBalance, coin);
if (satoshiAmount == balance) { if (satoshiAmount == balance) {
isSendAll = true; isSendAll = true;
} }
@ -1175,7 +1178,7 @@ class BitcoinCashWallet extends CoinServiceAPI {
final String worthNow = Format.localizedStringAsFixed( final String worthNow = Format.localizedStringAsFixed(
value: value:
((currentPrice * Decimal.fromInt(txData["recipientAmt"] as int)) / ((currentPrice * Decimal.fromInt(txData["recipientAmt"] as int)) /
Decimal.fromInt(Constants.satsPerCoin)) Decimal.fromInt(Constants.satsPerCoin(coin)))
.toDecimal(scaleOnInfinitePrecision: 2), .toDecimal(scaleOnInfinitePrecision: 2),
decimalPlaces: 2, decimalPlaces: 2,
locale: locale!); locale: locale!);
@ -1384,9 +1387,9 @@ class BitcoinCashWallet extends CoinServiceAPI {
numberOfBlocksFast: f, numberOfBlocksFast: f,
numberOfBlocksAverage: m, numberOfBlocksAverage: m,
numberOfBlocksSlow: s, numberOfBlocksSlow: s,
fast: Format.decimalAmountToSatoshis(fast), fast: Format.decimalAmountToSatoshis(fast, coin),
medium: Format.decimalAmountToSatoshis(medium), medium: Format.decimalAmountToSatoshis(medium, coin),
slow: Format.decimalAmountToSatoshis(slow), slow: Format.decimalAmountToSatoshis(slow, coin),
); );
Logging.instance.log("fetched fees: $feeObject", level: LogLevel.Info); Logging.instance.log("fetched fees: $feeObject", level: LogLevel.Info);
@ -1791,7 +1794,7 @@ class BitcoinCashWallet extends CoinServiceAPI {
utxo["status"]["block_time"] = txn["blocktime"]; utxo["status"]["block_time"] = txn["blocktime"];
final fiatValue = ((Decimal.fromInt(value) * currentPrice) / final fiatValue = ((Decimal.fromInt(value) * currentPrice) /
Decimal.fromInt(Constants.satsPerCoin)) Decimal.fromInt(Constants.satsPerCoin(coin)))
.toDecimal(scaleOnInfinitePrecision: 2); .toDecimal(scaleOnInfinitePrecision: 2);
utxo["rawWorth"] = fiatValue; utxo["rawWorth"] = fiatValue;
utxo["fiatWorth"] = fiatValue.toString(); utxo["fiatWorth"] = fiatValue.toString();
@ -1801,15 +1804,16 @@ class BitcoinCashWallet extends CoinServiceAPI {
Decimal currencyBalanceRaw = Decimal currencyBalanceRaw =
((Decimal.fromInt(satoshiBalance) * currentPrice) / ((Decimal.fromInt(satoshiBalance) * currentPrice) /
Decimal.fromInt(Constants.satsPerCoin)) Decimal.fromInt(Constants.satsPerCoin(coin)))
.toDecimal(scaleOnInfinitePrecision: 2); .toDecimal(scaleOnInfinitePrecision: 2);
final Map<String, dynamic> result = { final Map<String, dynamic> result = {
"total_user_currency": currencyBalanceRaw.toString(), "total_user_currency": currencyBalanceRaw.toString(),
"total_sats": satoshiBalance, "total_sats": satoshiBalance,
"total_btc": (Decimal.fromInt(satoshiBalance) / "total_btc": (Decimal.fromInt(satoshiBalance) /
Decimal.fromInt(Constants.satsPerCoin)) Decimal.fromInt(Constants.satsPerCoin(coin)))
.toDecimal(scaleOnInfinitePrecision: Constants.decimalPlaces) .toDecimal(
scaleOnInfinitePrecision: Constants.decimalPlacesForCoin(coin))
.toString(), .toString(),
"outputArray": outputArray, "outputArray": outputArray,
"unconfirmed": satoshiBalancePending, "unconfirmed": satoshiBalancePending,
@ -2332,7 +2336,7 @@ class BitcoinCashWallet extends CoinServiceAPI {
if (prevOut == out["n"]) { if (prevOut == out["n"]) {
inputAmtSentFromWallet += inputAmtSentFromWallet +=
(Decimal.parse(out["value"].toString()) * (Decimal.parse(out["value"].toString()) *
Decimal.fromInt(Constants.satsPerCoin)) Decimal.fromInt(Constants.satsPerCoin(coin)))
.toBigInt() .toBigInt()
.toInt(); .toInt();
} }
@ -2345,7 +2349,7 @@ class BitcoinCashWallet extends CoinServiceAPI {
final address = output["scriptPubKey"]["addresses"][0]; final address = output["scriptPubKey"]["addresses"][0];
final value = output["value"]; final value = output["value"];
final _value = (Decimal.parse(value.toString()) * final _value = (Decimal.parse(value.toString()) *
Decimal.fromInt(Constants.satsPerCoin)) Decimal.fromInt(Constants.satsPerCoin(coin)))
.toBigInt() .toBigInt()
.toInt(); .toInt();
totalOutput += _value; totalOutput += _value;
@ -2370,7 +2374,7 @@ class BitcoinCashWallet extends CoinServiceAPI {
final address = output["scriptPubKey"]["addresses"][0]; final address = output["scriptPubKey"]["addresses"][0];
if (address != null) { if (address != null) {
final value = (Decimal.parse(output["value"].toString()) * final value = (Decimal.parse(output["value"].toString()) *
Decimal.fromInt(Constants.satsPerCoin)) Decimal.fromInt(Constants.satsPerCoin(coin)))
.toBigInt() .toBigInt()
.toInt(); .toInt();
totalOut += value; totalOut += value;
@ -2394,7 +2398,7 @@ class BitcoinCashWallet extends CoinServiceAPI {
for (final out in tx["vout"] as List) { for (final out in tx["vout"] as List) {
if (prevOut == out["n"]) { if (prevOut == out["n"]) {
totalIn += (Decimal.parse(out["value"].toString()) * totalIn += (Decimal.parse(out["value"].toString()) *
Decimal.fromInt(Constants.satsPerCoin)) Decimal.fromInt(Constants.satsPerCoin(coin)))
.toBigInt() .toBigInt()
.toInt(); .toInt();
} }
@ -2416,7 +2420,7 @@ class BitcoinCashWallet extends CoinServiceAPI {
midSortedTx["amount"] = inputAmtSentFromWallet; midSortedTx["amount"] = inputAmtSentFromWallet;
final String worthNow = final String worthNow =
((currentPrice * Decimal.fromInt(inputAmtSentFromWallet)) / ((currentPrice * Decimal.fromInt(inputAmtSentFromWallet)) /
Decimal.fromInt(Constants.satsPerCoin)) Decimal.fromInt(Constants.satsPerCoin(coin)))
.toDecimal(scaleOnInfinitePrecision: 2) .toDecimal(scaleOnInfinitePrecision: 2)
.toStringAsFixed(2); .toStringAsFixed(2);
midSortedTx["worthNow"] = worthNow; midSortedTx["worthNow"] = worthNow;
@ -2426,7 +2430,7 @@ class BitcoinCashWallet extends CoinServiceAPI {
midSortedTx["amount"] = outputAmtAddressedToWallet; midSortedTx["amount"] = outputAmtAddressedToWallet;
final worthNow = final worthNow =
((currentPrice * Decimal.fromInt(outputAmtAddressedToWallet)) / ((currentPrice * Decimal.fromInt(outputAmtAddressedToWallet)) /
Decimal.fromInt(Constants.satsPerCoin)) Decimal.fromInt(Constants.satsPerCoin(coin)))
.toDecimal(scaleOnInfinitePrecision: 2) .toDecimal(scaleOnInfinitePrecision: 2)
.toStringAsFixed(2); .toStringAsFixed(2);
midSortedTx["worthNow"] = worthNow; midSortedTx["worthNow"] = worthNow;
@ -3457,7 +3461,8 @@ class BitcoinCashWallet extends CoinServiceAPI {
@override @override
Future<int> estimateFeeFor(int satoshiAmount, int feeRate) async { Future<int> estimateFeeFor(int satoshiAmount, int feeRate) async {
final available = Format.decimalAmountToSatoshis(await availableBalance); final available =
Format.decimalAmountToSatoshis(await availableBalance, coin);
if (available == satoshiAmount) { if (available == satoshiAmount) {
return satoshiAmount - sweepAllEstimate(feeRate); return satoshiAmount - sweepAllEstimate(feeRate);

View file

@ -167,19 +167,21 @@ class DogecoinWallet extends CoinServiceAPI {
Future<Decimal> get availableBalance async { Future<Decimal> get availableBalance async {
final data = await utxoData; final data = await utxoData;
return Format.satoshisToAmount( return Format.satoshisToAmount(
data.satoshiBalance - data.satoshiBalanceUnconfirmed); data.satoshiBalance - data.satoshiBalanceUnconfirmed,
coin: coin);
} }
@override @override
Future<Decimal> get pendingBalance async { Future<Decimal> get pendingBalance async {
final data = await utxoData; final data = await utxoData;
return Format.satoshisToAmount(data.satoshiBalanceUnconfirmed); return Format.satoshisToAmount(data.satoshiBalanceUnconfirmed, coin: coin);
} }
@override @override
Future<Decimal> get balanceMinusMaxFee async => Future<Decimal> get balanceMinusMaxFee async =>
(await availableBalance) - (await availableBalance) -
(Decimal.fromInt((await maxFee)) / Decimal.fromInt(Constants.satsPerCoin)) (Decimal.fromInt((await maxFee)) /
Decimal.fromInt(Constants.satsPerCoin(coin)))
.toDecimal(); .toDecimal();
@override @override
@ -189,13 +191,13 @@ class DogecoinWallet extends CoinServiceAPI {
.get<dynamic>(boxName: walletId, key: 'totalBalance') as int?; .get<dynamic>(boxName: walletId, key: 'totalBalance') as int?;
if (totalBalance == null) { if (totalBalance == null) {
final data = await utxoData; final data = await utxoData;
return Format.satoshisToAmount(data.satoshiBalance); return Format.satoshisToAmount(data.satoshiBalance, coin: coin);
} else { } else {
return Format.satoshisToAmount(totalBalance); return Format.satoshisToAmount(totalBalance, coin: coin);
} }
} }
final data = await utxoData; final data = await utxoData;
return Format.satoshisToAmount(data.satoshiBalance); return Format.satoshisToAmount(data.satoshiBalance, coin: coin);
} }
@override @override
@ -225,8 +227,8 @@ class DogecoinWallet extends CoinServiceAPI {
@override @override
Future<int> get maxFee async { Future<int> get maxFee async {
final fee = (await fees).fast; final fee = (await fees).fast;
final satsFee = final satsFee = Format.satoshisToAmount(fee, coin: coin) *
Format.satoshisToAmount(fee) * Decimal.fromInt(Constants.satsPerCoin); Decimal.fromInt(Constants.satsPerCoin(coin));
return satsFee.floor().toBigInt().toInt(); return satsFee.floor().toBigInt().toInt();
} }
@ -878,7 +880,8 @@ class DogecoinWallet extends CoinServiceAPI {
} }
// check for send all // check for send all
bool isSendAll = false; bool isSendAll = false;
final balance = Format.decimalAmountToSatoshis(await availableBalance); final balance =
Format.decimalAmountToSatoshis(await availableBalance, coin);
if (satoshiAmount == balance) { if (satoshiAmount == balance) {
isSendAll = true; isSendAll = true;
} }
@ -1065,7 +1068,7 @@ class DogecoinWallet extends CoinServiceAPI {
final String worthNow = Format.localizedStringAsFixed( final String worthNow = Format.localizedStringAsFixed(
value: value:
((currentPrice * Decimal.fromInt(txData["recipientAmt"] as int)) / ((currentPrice * Decimal.fromInt(txData["recipientAmt"] as int)) /
Decimal.fromInt(Constants.satsPerCoin)) Decimal.fromInt(Constants.satsPerCoin(coin)))
.toDecimal(scaleOnInfinitePrecision: 2), .toDecimal(scaleOnInfinitePrecision: 2),
decimalPlaces: 2, decimalPlaces: 2,
locale: locale!); locale: locale!);
@ -1247,9 +1250,9 @@ class DogecoinWallet extends CoinServiceAPI {
numberOfBlocksFast: f, numberOfBlocksFast: f,
numberOfBlocksAverage: m, numberOfBlocksAverage: m,
numberOfBlocksSlow: s, numberOfBlocksSlow: s,
fast: Format.decimalAmountToSatoshis(fast), fast: Format.decimalAmountToSatoshis(fast, coin),
medium: Format.decimalAmountToSatoshis(medium), medium: Format.decimalAmountToSatoshis(medium, coin),
slow: Format.decimalAmountToSatoshis(slow), slow: Format.decimalAmountToSatoshis(slow, coin),
); );
Logging.instance.log("fetched fees: $feeObject", level: LogLevel.Info); Logging.instance.log("fetched fees: $feeObject", level: LogLevel.Info);
@ -1650,7 +1653,7 @@ class DogecoinWallet extends CoinServiceAPI {
utxo["status"]["block_time"] = txn["blocktime"]; utxo["status"]["block_time"] = txn["blocktime"];
final fiatValue = ((Decimal.fromInt(value) * currentPrice) / final fiatValue = ((Decimal.fromInt(value) * currentPrice) /
Decimal.fromInt(Constants.satsPerCoin)) Decimal.fromInt(Constants.satsPerCoin(coin)))
.toDecimal(scaleOnInfinitePrecision: 2); .toDecimal(scaleOnInfinitePrecision: 2);
utxo["rawWorth"] = fiatValue; utxo["rawWorth"] = fiatValue;
utxo["fiatWorth"] = fiatValue.toString(); utxo["fiatWorth"] = fiatValue.toString();
@ -1660,15 +1663,16 @@ class DogecoinWallet extends CoinServiceAPI {
Decimal currencyBalanceRaw = Decimal currencyBalanceRaw =
((Decimal.fromInt(satoshiBalance) * currentPrice) / ((Decimal.fromInt(satoshiBalance) * currentPrice) /
Decimal.fromInt(Constants.satsPerCoin)) Decimal.fromInt(Constants.satsPerCoin(coin)))
.toDecimal(scaleOnInfinitePrecision: 2); .toDecimal(scaleOnInfinitePrecision: 2);
final Map<String, dynamic> result = { final Map<String, dynamic> result = {
"total_user_currency": currencyBalanceRaw.toString(), "total_user_currency": currencyBalanceRaw.toString(),
"total_sats": satoshiBalance, "total_sats": satoshiBalance,
"total_btc": (Decimal.fromInt(satoshiBalance) / "total_btc": (Decimal.fromInt(satoshiBalance) /
Decimal.fromInt(Constants.satsPerCoin)) Decimal.fromInt(Constants.satsPerCoin(coin)))
.toDecimal(scaleOnInfinitePrecision: Constants.decimalPlaces) .toDecimal(
scaleOnInfinitePrecision: Constants.decimalPlacesForCoin(coin))
.toString(), .toString(),
"outputArray": outputArray, "outputArray": outputArray,
"unconfirmed": satoshiBalancePending, "unconfirmed": satoshiBalancePending,
@ -2144,7 +2148,7 @@ class DogecoinWallet extends CoinServiceAPI {
if (prevOut == out["n"]) { if (prevOut == out["n"]) {
inputAmtSentFromWallet += inputAmtSentFromWallet +=
(Decimal.parse(out["value"].toString()) * (Decimal.parse(out["value"].toString()) *
Decimal.fromInt(Constants.satsPerCoin)) Decimal.fromInt(Constants.satsPerCoin(coin)))
.toBigInt() .toBigInt()
.toInt(); .toInt();
} }
@ -2157,7 +2161,7 @@ class DogecoinWallet extends CoinServiceAPI {
final address = output["scriptPubKey"]["addresses"][0]; final address = output["scriptPubKey"]["addresses"][0];
final value = output["value"]; final value = output["value"];
final _value = (Decimal.parse(value.toString()) * final _value = (Decimal.parse(value.toString()) *
Decimal.fromInt(Constants.satsPerCoin)) Decimal.fromInt(Constants.satsPerCoin(coin)))
.toBigInt() .toBigInt()
.toInt(); .toInt();
totalOutput += _value; totalOutput += _value;
@ -2182,7 +2186,7 @@ class DogecoinWallet extends CoinServiceAPI {
final address = output["scriptPubKey"]["addresses"][0]; final address = output["scriptPubKey"]["addresses"][0];
if (address != null) { if (address != null) {
final value = (Decimal.parse(output["value"].toString()) * final value = (Decimal.parse(output["value"].toString()) *
Decimal.fromInt(Constants.satsPerCoin)) Decimal.fromInt(Constants.satsPerCoin(coin)))
.toBigInt() .toBigInt()
.toInt(); .toInt();
totalOut += value; totalOut += value;
@ -2205,7 +2209,7 @@ class DogecoinWallet extends CoinServiceAPI {
for (final out in tx["vout"] as List) { for (final out in tx["vout"] as List) {
if (prevOut == out["n"]) { if (prevOut == out["n"]) {
totalIn += (Decimal.parse(out["value"].toString()) * totalIn += (Decimal.parse(out["value"].toString()) *
Decimal.fromInt(Constants.satsPerCoin)) Decimal.fromInt(Constants.satsPerCoin(coin)))
.toBigInt() .toBigInt()
.toInt(); .toInt();
} }
@ -2227,7 +2231,7 @@ class DogecoinWallet extends CoinServiceAPI {
midSortedTx["amount"] = inputAmtSentFromWallet; midSortedTx["amount"] = inputAmtSentFromWallet;
final String worthNow = final String worthNow =
((currentPrice * Decimal.fromInt(inputAmtSentFromWallet)) / ((currentPrice * Decimal.fromInt(inputAmtSentFromWallet)) /
Decimal.fromInt(Constants.satsPerCoin)) Decimal.fromInt(Constants.satsPerCoin(coin)))
.toDecimal(scaleOnInfinitePrecision: 2) .toDecimal(scaleOnInfinitePrecision: 2)
.toStringAsFixed(2); .toStringAsFixed(2);
midSortedTx["worthNow"] = worthNow; midSortedTx["worthNow"] = worthNow;
@ -2237,7 +2241,7 @@ class DogecoinWallet extends CoinServiceAPI {
midSortedTx["amount"] = outputAmtAddressedToWallet; midSortedTx["amount"] = outputAmtAddressedToWallet;
final worthNow = final worthNow =
((currentPrice * Decimal.fromInt(outputAmtAddressedToWallet)) / ((currentPrice * Decimal.fromInt(outputAmtAddressedToWallet)) /
Decimal.fromInt(Constants.satsPerCoin)) Decimal.fromInt(Constants.satsPerCoin(coin)))
.toDecimal(scaleOnInfinitePrecision: 2) .toDecimal(scaleOnInfinitePrecision: 2)
.toStringAsFixed(2); .toStringAsFixed(2);
midSortedTx["worthNow"] = worthNow; midSortedTx["worthNow"] = worthNow;
@ -3050,7 +3054,8 @@ class DogecoinWallet extends CoinServiceAPI {
@override @override
Future<int> estimateFeeFor(int satoshiAmount, int feeRate) async { Future<int> estimateFeeFor(int satoshiAmount, int feeRate) async {
final available = Format.decimalAmountToSatoshis(await availableBalance); final available =
Format.decimalAmountToSatoshis(await availableBalance, coin);
if (available == satoshiAmount) { if (available == satoshiAmount) {
return satoshiAmount - sweepAllEstimate(feeRate); return satoshiAmount - sweepAllEstimate(feeRate);

View file

@ -620,7 +620,7 @@ Future<dynamic> isolateCreateJoinSplitTransaction(
"txid": txId, "txid": txId,
"txHex": txHex, "txHex": txHex,
"value": amount, "value": amount,
"fees": Format.satoshisToAmount(fee).toDouble(), "fees": Format.satoshisToAmount(fee, coin: coin).toDouble(),
"fee": fee, "fee": fee,
"vSize": extTx.virtualSize(), "vSize": extTx.virtualSize(),
"jmintValue": changeToMint, "jmintValue": changeToMint,
@ -629,11 +629,11 @@ Future<dynamic> isolateCreateJoinSplitTransaction(
"height": locktime, "height": locktime,
"txType": "Sent", "txType": "Sent",
"confirmed_status": false, "confirmed_status": false,
"amount": Format.satoshisToAmount(amount).toDouble(), "amount": Format.satoshisToAmount(amount, coin: coin).toDouble(),
"recipientAmt": amount, "recipientAmt": amount,
"worthNow": Format.localizedStringAsFixed( "worthNow": Format.localizedStringAsFixed(
value: ((Decimal.fromInt(amount) * price) / value: ((Decimal.fromInt(amount) * price) /
Decimal.fromInt(Constants.satsPerCoin)) Decimal.fromInt(Constants.satsPerCoin(coin)))
.toDecimal(scaleOnInfinitePrecision: 2), .toDecimal(scaleOnInfinitePrecision: 2),
decimalPlaces: 2, decimalPlaces: 2,
locale: locale), locale: locale),
@ -883,7 +883,7 @@ class FiroWallet extends CoinServiceAPI {
Future<Decimal> get balanceMinusMaxFee async { Future<Decimal> get balanceMinusMaxFee async {
final balances = await this.balances; final balances = await this.balances;
final maxFee = await this.maxFee; final maxFee = await this.maxFee;
return balances[0] - Format.satoshisToAmount(maxFee); return balances[0] - Format.satoshisToAmount(maxFee, coin: coin);
} }
@override @override
@ -919,7 +919,7 @@ class FiroWallet extends CoinServiceAPI {
final String worthNow = Format.localizedStringAsFixed( final String worthNow = Format.localizedStringAsFixed(
value: value:
((currentPrice * Decimal.fromInt(txData["recipientAmt"] as int)) / ((currentPrice * Decimal.fromInt(txData["recipientAmt"] as int)) /
Decimal.fromInt(Constants.satsPerCoin)) Decimal.fromInt(Constants.satsPerCoin(coin)))
.toDecimal(scaleOnInfinitePrecision: 2), .toDecimal(scaleOnInfinitePrecision: 2),
decimalPlaces: 2, decimalPlaces: 2,
locale: locale!); locale: locale!);
@ -1089,8 +1089,8 @@ class FiroWallet extends CoinServiceAPI {
// check for send all // check for send all
bool isSendAll = false; bool isSendAll = false;
final balance = final balance = Format.decimalAmountToSatoshis(
Format.decimalAmountToSatoshis(await availablePublicBalance()); await availablePublicBalance(), coin);
if (satoshiAmount == balance) { if (satoshiAmount == balance) {
isSendAll = true; isSendAll = true;
} }
@ -1176,7 +1176,7 @@ class FiroWallet extends CoinServiceAPI {
// check for send all // check for send all
bool isSendAll = false; bool isSendAll = false;
final balance = final balance =
Format.decimalAmountToSatoshis(await availablePrivateBalance()); Format.decimalAmountToSatoshis(await availablePrivateBalance(), coin);
if (satoshiAmount == balance) { if (satoshiAmount == balance) {
// print("is send all"); // print("is send all");
isSendAll = true; isSendAll = true;
@ -1222,7 +1222,8 @@ class FiroWallet extends CoinServiceAPI {
// temporarily update apdate available balance until a full refresh is done // temporarily update apdate available balance until a full refresh is done
// TODO: something here causes an exception to be thrown giving user false info that the tx failed // TODO: something here causes an exception to be thrown giving user false info that the tx failed
Decimal sendTotal = Format.satoshisToAmount(txData["value"] as int); Decimal sendTotal =
Format.satoshisToAmount(txData["value"] as int, coin: coin);
sendTotal += Decimal.parse(txData["fees"].toString()); sendTotal += Decimal.parse(txData["fees"].toString());
final bals = await balances; final bals = await balances;
bals[0] -= sendTotal; bals[0] -= sendTotal;
@ -1270,7 +1271,7 @@ class FiroWallet extends CoinServiceAPI {
// temporarily update apdate available balance until a full refresh is done // temporarily update apdate available balance until a full refresh is done
Decimal sendTotal = Decimal sendTotal =
Format.satoshisToAmount(txHexOrError["value"] as int); Format.satoshisToAmount(txHexOrError["value"] as int, coin: coin);
sendTotal += Decimal.parse(txHexOrError["fees"].toString()); sendTotal += Decimal.parse(txHexOrError["fees"].toString());
final bals = await balances; final bals = await balances;
bals[0] -= sendTotal; bals[0] -= sendTotal;
@ -2333,8 +2334,9 @@ class FiroWallet extends CoinServiceAPI {
Future<int> _fetchMaxFee() async { Future<int> _fetchMaxFee() async {
final balance = await availableBalance; final balance = await availableBalance;
int spendAmount = int spendAmount = (balance * Decimal.fromInt(Constants.satsPerCoin(coin)))
(balance * Decimal.fromInt(Constants.satsPerCoin)).toBigInt().toInt(); .toBigInt()
.toInt();
int fee = await estimateJoinSplitFee(spendAmount); int fee = await estimateJoinSplitFee(spendAmount);
return fee; return fee;
} }
@ -2480,18 +2482,20 @@ class FiroWallet extends CoinServiceAPI {
} }
final int utxosIntValue = utxos.satoshiBalance; final int utxosIntValue = utxos.satoshiBalance;
final Decimal utxosValue = Format.satoshisToAmount(utxosIntValue); final Decimal utxosValue =
Format.satoshisToAmount(utxosIntValue, coin: coin);
List<Decimal> balances = List.empty(growable: true); List<Decimal> balances = List.empty(growable: true);
Decimal lelantusBalance = Format.satoshisToAmount(intLelantusBalance); Decimal lelantusBalance =
Format.satoshisToAmount(intLelantusBalance, coin: coin);
balances.add(lelantusBalance); balances.add(lelantusBalance);
balances.add(lelantusBalance * price); balances.add(lelantusBalance * price);
Decimal _unconfirmedLelantusBalance = Decimal _unconfirmedLelantusBalance =
Format.satoshisToAmount(unconfirmedLelantusBalance); Format.satoshisToAmount(unconfirmedLelantusBalance, coin: coin);
balances.add(lelantusBalance + utxosValue + _unconfirmedLelantusBalance); balances.add(lelantusBalance + utxosValue + _unconfirmedLelantusBalance);
@ -2503,7 +2507,7 @@ class FiroWallet extends CoinServiceAPI {
if (availableSats < 0) { if (availableSats < 0) {
availableSats = 0; availableSats = 0;
} }
balances.add(Format.satoshisToAmount(availableSats)); balances.add(Format.satoshisToAmount(availableSats, coin: coin));
Logging.instance.log("balances $balances", level: LogLevel.Info); Logging.instance.log("balances $balances", level: LogLevel.Info);
await DB.instance.put<dynamic>( await DB.instance.put<dynamic>(
@ -2601,7 +2605,8 @@ class FiroWallet extends CoinServiceAPI {
final feesObject = await fees; final feesObject = await fees;
final Decimal fastFee = Format.satoshisToAmount(feesObject.fast); final Decimal fastFee =
Format.satoshisToAmount(feesObject.fast, coin: coin);
int firoFee = int firoFee =
(dvsize * fastFee * Decimal.fromInt(100000)).toDouble().ceil(); (dvsize * fastFee * Decimal.fromInt(100000)).toDouble().ceil();
// int firoFee = (vsize * feesObject.fast * (1 / 1000.0) * 100000000).ceil(); // int firoFee = (vsize * feesObject.fast * (1 / 1000.0) * 100000000).ceil();
@ -2789,15 +2794,15 @@ class FiroWallet extends CoinServiceAPI {
"txid": txId, "txid": txId,
"txHex": txHex, "txHex": txHex,
"value": amount - fee, "value": amount - fee,
"fees": Format.satoshisToAmount(fee).toDouble(), "fees": Format.satoshisToAmount(fee, coin: coin).toDouble(),
"publicCoin": "", "publicCoin": "",
"height": height, "height": height,
"txType": "Sent", "txType": "Sent",
"confirmed_status": false, "confirmed_status": false,
"amount": Format.satoshisToAmount(amount).toDouble(), "amount": Format.satoshisToAmount(amount, coin: coin).toDouble(),
"worthNow": Format.localizedStringAsFixed( "worthNow": Format.localizedStringAsFixed(
value: ((Decimal.fromInt(amount) * price) / value: ((Decimal.fromInt(amount) * price) /
Decimal.fromInt(Constants.satsPerCoin)) Decimal.fromInt(Constants.satsPerCoin(coin)))
.toDecimal(scaleOnInfinitePrecision: 2), .toDecimal(scaleOnInfinitePrecision: 2),
decimalPlaces: 2, decimalPlaces: 2,
locale: locale!), locale: locale!),
@ -3040,9 +3045,9 @@ class FiroWallet extends CoinServiceAPI {
numberOfBlocksFast: f, numberOfBlocksFast: f,
numberOfBlocksAverage: m, numberOfBlocksAverage: m,
numberOfBlocksSlow: s, numberOfBlocksSlow: s,
fast: Format.decimalAmountToSatoshis(fast), fast: Format.decimalAmountToSatoshis(fast, coin),
medium: Format.decimalAmountToSatoshis(medium), medium: Format.decimalAmountToSatoshis(medium, coin),
slow: Format.decimalAmountToSatoshis(slow), slow: Format.decimalAmountToSatoshis(slow, coin),
); );
Logging.instance.log("fetched fees: $feeObject", level: LogLevel.Info); Logging.instance.log("fetched fees: $feeObject", level: LogLevel.Info);
@ -3328,7 +3333,7 @@ class FiroWallet extends CoinServiceAPI {
if (nFees != null) { if (nFees != null) {
nFeesUsed = true; nFeesUsed = true;
fees = (Decimal.parse(nFees.toString()) * fees = (Decimal.parse(nFees.toString()) *
Decimal.fromInt(Constants.satsPerCoin)) Decimal.fromInt(Constants.satsPerCoin(coin)))
.toBigInt() .toBigInt()
.toInt(); .toInt();
} }
@ -3353,7 +3358,7 @@ class FiroWallet extends CoinServiceAPI {
if (value != null) { if (value != null) {
if (changeAddresses.contains(address)) { if (changeAddresses.contains(address)) {
inputAmtSentFromWallet -= (Decimal.parse(value.toString()) * inputAmtSentFromWallet -= (Decimal.parse(value.toString()) *
Decimal.fromInt(Constants.satsPerCoin)) Decimal.fromInt(Constants.satsPerCoin(coin)))
.toBigInt() .toBigInt()
.toInt(); .toInt();
} else { } else {
@ -3363,7 +3368,7 @@ class FiroWallet extends CoinServiceAPI {
} }
if (value != null) { if (value != null) {
outAmount += (Decimal.parse(value.toString()) * outAmount += (Decimal.parse(value.toString()) *
Decimal.fromInt(Constants.satsPerCoin)) Decimal.fromInt(Constants.satsPerCoin(coin)))
.toBigInt() .toBigInt()
.toInt(); .toInt();
} }
@ -3376,7 +3381,7 @@ class FiroWallet extends CoinServiceAPI {
final nFees = input["nFees"]; final nFees = input["nFees"];
if (nFees != null) { if (nFees != null) {
fees += (Decimal.parse(nFees.toString()) * fees += (Decimal.parse(nFees.toString()) *
Decimal.fromInt(Constants.satsPerCoin)) Decimal.fromInt(Constants.satsPerCoin(coin)))
.toBigInt() .toBigInt()
.toInt(); .toInt();
} }
@ -3391,7 +3396,7 @@ class FiroWallet extends CoinServiceAPI {
if (allAddresses.contains(address)) { if (allAddresses.contains(address)) {
outputAmtAddressedToWallet += (Decimal.parse(value.toString()) * outputAmtAddressedToWallet += (Decimal.parse(value.toString()) *
Decimal.fromInt(Constants.satsPerCoin)) Decimal.fromInt(Constants.satsPerCoin(coin)))
.toBigInt() .toBigInt()
.toInt(); .toInt();
outAddress = address; outAddress = address;
@ -3413,7 +3418,7 @@ class FiroWallet extends CoinServiceAPI {
midSortedTx["amount"] = inputAmtSentFromWallet; midSortedTx["amount"] = inputAmtSentFromWallet;
final String worthNow = Format.localizedStringAsFixed( final String worthNow = Format.localizedStringAsFixed(
value: ((currentPrice * Decimal.fromInt(inputAmtSentFromWallet)) / value: ((currentPrice * Decimal.fromInt(inputAmtSentFromWallet)) /
Decimal.fromInt(Constants.satsPerCoin)) Decimal.fromInt(Constants.satsPerCoin(coin)))
.toDecimal(scaleOnInfinitePrecision: 2), .toDecimal(scaleOnInfinitePrecision: 2),
decimalPlaces: 2, decimalPlaces: 2,
locale: locale!); locale: locale!);
@ -3428,7 +3433,7 @@ class FiroWallet extends CoinServiceAPI {
final worthNow = Format.localizedStringAsFixed( final worthNow = Format.localizedStringAsFixed(
value: value:
((currentPrice * Decimal.fromInt(outputAmtAddressedToWallet)) / ((currentPrice * Decimal.fromInt(outputAmtAddressedToWallet)) /
Decimal.fromInt(Constants.satsPerCoin)) Decimal.fromInt(Constants.satsPerCoin(coin)))
.toDecimal(scaleOnInfinitePrecision: 2), .toDecimal(scaleOnInfinitePrecision: 2),
decimalPlaces: 2, decimalPlaces: 2,
locale: locale!); locale: locale!);
@ -3589,7 +3594,7 @@ class FiroWallet extends CoinServiceAPI {
utxo["status"]["block_time"] = txn["blocktime"]; utxo["status"]["block_time"] = txn["blocktime"];
final fiatValue = ((Decimal.fromInt(value) * currentPrice) / final fiatValue = ((Decimal.fromInt(value) * currentPrice) /
Decimal.fromInt(Constants.satsPerCoin)) Decimal.fromInt(Constants.satsPerCoin(coin)))
.toDecimal(scaleOnInfinitePrecision: 2); .toDecimal(scaleOnInfinitePrecision: 2);
utxo["rawWorth"] = fiatValue; utxo["rawWorth"] = fiatValue;
utxo["fiatWorth"] = fiatValue.toString(); utxo["fiatWorth"] = fiatValue.toString();
@ -3600,15 +3605,16 @@ class FiroWallet extends CoinServiceAPI {
Decimal currencyBalanceRaw = Decimal currencyBalanceRaw =
((Decimal.fromInt(satoshiBalance) * currentPrice) / ((Decimal.fromInt(satoshiBalance) * currentPrice) /
Decimal.fromInt(Constants.satsPerCoin)) Decimal.fromInt(Constants.satsPerCoin(coin)))
.toDecimal(scaleOnInfinitePrecision: 2); .toDecimal(scaleOnInfinitePrecision: 2);
final Map<String, dynamic> result = { final Map<String, dynamic> result = {
"total_user_currency": currencyBalanceRaw.toString(), "total_user_currency": currencyBalanceRaw.toString(),
"total_sats": satoshiBalance, "total_sats": satoshiBalance,
"total_btc": (Decimal.fromInt(satoshiBalance) / "total_btc": (Decimal.fromInt(satoshiBalance) /
Decimal.fromInt(Constants.satsPerCoin)) Decimal.fromInt(Constants.satsPerCoin(coin)))
.toDecimal(scaleOnInfinitePrecision: Constants.decimalPlaces) .toDecimal(
scaleOnInfinitePrecision: Constants.decimalPlacesForCoin(coin))
.toString(), .toString(),
"outputArray": outputArray, "outputArray": outputArray,
"unconfirmed": satoshiBalancePending, "unconfirmed": satoshiBalancePending,
@ -4571,8 +4577,9 @@ class FiroWallet extends CoinServiceAPI {
) async { ) async {
var lelantusEntry = await _getLelantusEntry(); var lelantusEntry = await _getLelantusEntry();
final balance = await availableBalance; final balance = await availableBalance;
int spendAmount = int spendAmount = (balance * Decimal.fromInt(Constants.satsPerCoin(coin)))
(balance * Decimal.fromInt(Constants.satsPerCoin)).toBigInt().toInt(); .toBigInt()
.toInt();
if (spendAmount == 0 || lelantusEntry.isEmpty) { if (spendAmount == 0 || lelantusEntry.isEmpty) {
return LelantusFeeData(0, 0, []).fee; return LelantusFeeData(0, 0, []).fee;
} }
@ -4633,7 +4640,7 @@ class FiroWallet extends CoinServiceAPI {
Future<int> estimateFeeForPublic(int satoshiAmount, int feeRate) async { Future<int> estimateFeeForPublic(int satoshiAmount, int feeRate) async {
final available = final available =
Format.decimalAmountToSatoshis(await availablePublicBalance()); Format.decimalAmountToSatoshis(await availablePublicBalance(), coin);
if (available == satoshiAmount) { if (available == satoshiAmount) {
return satoshiAmount - sweepAllEstimate(feeRate); return satoshiAmount - sweepAllEstimate(feeRate);

View file

@ -200,19 +200,21 @@ class LitecoinWallet extends CoinServiceAPI {
Future<Decimal> get availableBalance async { Future<Decimal> get availableBalance async {
final data = await utxoData; final data = await utxoData;
return Format.satoshisToAmount( return Format.satoshisToAmount(
data.satoshiBalance - data.satoshiBalanceUnconfirmed); data.satoshiBalance - data.satoshiBalanceUnconfirmed,
coin: coin);
} }
@override @override
Future<Decimal> get pendingBalance async { Future<Decimal> get pendingBalance async {
final data = await utxoData; final data = await utxoData;
return Format.satoshisToAmount(data.satoshiBalanceUnconfirmed); return Format.satoshisToAmount(data.satoshiBalanceUnconfirmed, coin: coin);
} }
@override @override
Future<Decimal> get balanceMinusMaxFee async => Future<Decimal> get balanceMinusMaxFee async =>
(await availableBalance) - (await availableBalance) -
(Decimal.fromInt((await maxFee)) / Decimal.fromInt(Constants.satsPerCoin)) (Decimal.fromInt((await maxFee)) /
Decimal.fromInt(Constants.satsPerCoin(coin)))
.toDecimal(); .toDecimal();
@override @override
@ -222,13 +224,13 @@ class LitecoinWallet extends CoinServiceAPI {
.get<dynamic>(boxName: walletId, key: 'totalBalance') as int?; .get<dynamic>(boxName: walletId, key: 'totalBalance') as int?;
if (totalBalance == null) { if (totalBalance == null) {
final data = await utxoData; final data = await utxoData;
return Format.satoshisToAmount(data.satoshiBalance); return Format.satoshisToAmount(data.satoshiBalance, coin: coin);
} else { } else {
return Format.satoshisToAmount(totalBalance); return Format.satoshisToAmount(totalBalance, coin: coin);
} }
} }
final data = await utxoData; final data = await utxoData;
return Format.satoshisToAmount(data.satoshiBalance); return Format.satoshisToAmount(data.satoshiBalance, coin: coin);
} }
@override @override
@ -266,7 +268,8 @@ class LitecoinWallet extends CoinServiceAPI {
@override @override
Future<int> get maxFee async { Future<int> get maxFee async {
final fee = (await fees).fast as String; final fee = (await fees).fast as String;
final satsFee = Decimal.parse(fee) * Decimal.fromInt(Constants.satsPerCoin); final satsFee =
Decimal.parse(fee) * Decimal.fromInt(Constants.satsPerCoin(coin));
return satsFee.floor().toBigInt().toInt(); return satsFee.floor().toBigInt().toInt();
} }
@ -1095,7 +1098,8 @@ class LitecoinWallet extends CoinServiceAPI {
// check for send all // check for send all
bool isSendAll = false; bool isSendAll = false;
final balance = Format.decimalAmountToSatoshis(await availableBalance); final balance =
Format.decimalAmountToSatoshis(await availableBalance, coin);
if (satoshiAmount == balance) { if (satoshiAmount == balance) {
isSendAll = true; isSendAll = true;
} }
@ -1299,7 +1303,7 @@ class LitecoinWallet extends CoinServiceAPI {
final String worthNow = Format.localizedStringAsFixed( final String worthNow = Format.localizedStringAsFixed(
value: value:
((currentPrice * Decimal.fromInt(txData["recipientAmt"] as int)) / ((currentPrice * Decimal.fromInt(txData["recipientAmt"] as int)) /
Decimal.fromInt(Constants.satsPerCoin)) Decimal.fromInt(Constants.satsPerCoin(coin)))
.toDecimal(scaleOnInfinitePrecision: 2), .toDecimal(scaleOnInfinitePrecision: 2),
decimalPlaces: 2, decimalPlaces: 2,
locale: locale!); locale: locale!);
@ -1499,9 +1503,9 @@ class LitecoinWallet extends CoinServiceAPI {
numberOfBlocksFast: f, numberOfBlocksFast: f,
numberOfBlocksAverage: m, numberOfBlocksAverage: m,
numberOfBlocksSlow: s, numberOfBlocksSlow: s,
fast: Format.decimalAmountToSatoshis(fast), fast: Format.decimalAmountToSatoshis(fast, coin),
medium: Format.decimalAmountToSatoshis(medium), medium: Format.decimalAmountToSatoshis(medium, coin),
slow: Format.decimalAmountToSatoshis(slow), slow: Format.decimalAmountToSatoshis(slow, coin),
); );
Logging.instance.log("fetched fees: $feeObject", level: LogLevel.Info); Logging.instance.log("fetched fees: $feeObject", level: LogLevel.Info);
@ -1978,7 +1982,7 @@ class LitecoinWallet extends CoinServiceAPI {
utxo["status"]["block_time"] = txn["blocktime"]; utxo["status"]["block_time"] = txn["blocktime"];
final fiatValue = ((Decimal.fromInt(value) * currentPrice) / final fiatValue = ((Decimal.fromInt(value) * currentPrice) /
Decimal.fromInt(Constants.satsPerCoin)) Decimal.fromInt(Constants.satsPerCoin(coin)))
.toDecimal(scaleOnInfinitePrecision: 2); .toDecimal(scaleOnInfinitePrecision: 2);
utxo["rawWorth"] = fiatValue; utxo["rawWorth"] = fiatValue;
utxo["fiatWorth"] = fiatValue.toString(); utxo["fiatWorth"] = fiatValue.toString();
@ -1988,15 +1992,16 @@ class LitecoinWallet extends CoinServiceAPI {
Decimal currencyBalanceRaw = Decimal currencyBalanceRaw =
((Decimal.fromInt(satoshiBalance) * currentPrice) / ((Decimal.fromInt(satoshiBalance) * currentPrice) /
Decimal.fromInt(Constants.satsPerCoin)) Decimal.fromInt(Constants.satsPerCoin(coin)))
.toDecimal(scaleOnInfinitePrecision: 2); .toDecimal(scaleOnInfinitePrecision: 2);
final Map<String, dynamic> result = { final Map<String, dynamic> result = {
"total_user_currency": currencyBalanceRaw.toString(), "total_user_currency": currencyBalanceRaw.toString(),
"total_sats": satoshiBalance, "total_sats": satoshiBalance,
"total_btc": (Decimal.fromInt(satoshiBalance) / "total_btc": (Decimal.fromInt(satoshiBalance) /
Decimal.fromInt(Constants.satsPerCoin)) Decimal.fromInt(Constants.satsPerCoin(coin)))
.toDecimal(scaleOnInfinitePrecision: Constants.decimalPlaces) .toDecimal(
scaleOnInfinitePrecision: Constants.decimalPlacesForCoin(coin))
.toString(), .toString(),
"outputArray": outputArray, "outputArray": outputArray,
"unconfirmed": satoshiBalancePending, "unconfirmed": satoshiBalancePending,
@ -2543,7 +2548,7 @@ class LitecoinWallet extends CoinServiceAPI {
if (prevOut == out["n"]) { if (prevOut == out["n"]) {
inputAmtSentFromWallet += inputAmtSentFromWallet +=
(Decimal.parse(out["value"]!.toString()) * (Decimal.parse(out["value"]!.toString()) *
Decimal.fromInt(Constants.satsPerCoin)) Decimal.fromInt(Constants.satsPerCoin(coin)))
.toBigInt() .toBigInt()
.toInt(); .toInt();
} }
@ -2557,7 +2562,7 @@ class LitecoinWallet extends CoinServiceAPI {
output["scriptPubKey"]!["addresses"][0] as String; output["scriptPubKey"]!["addresses"][0] as String;
final value = output["value"]!; final value = output["value"]!;
final _value = (Decimal.parse(value.toString()) * final _value = (Decimal.parse(value.toString()) *
Decimal.fromInt(Constants.satsPerCoin)) Decimal.fromInt(Constants.satsPerCoin(coin)))
.toBigInt() .toBigInt()
.toInt(); .toInt();
totalOutput += _value; totalOutput += _value;
@ -2582,7 +2587,7 @@ class LitecoinWallet extends CoinServiceAPI {
final address = output["scriptPubKey"]["addresses"][0]; final address = output["scriptPubKey"]["addresses"][0];
if (address != null) { if (address != null) {
final value = (Decimal.parse(output["value"].toString()) * final value = (Decimal.parse(output["value"].toString()) *
Decimal.fromInt(Constants.satsPerCoin)) Decimal.fromInt(Constants.satsPerCoin(coin)))
.toBigInt() .toBigInt()
.toInt(); .toInt();
totalOut += value; totalOut += value;
@ -2605,7 +2610,7 @@ class LitecoinWallet extends CoinServiceAPI {
for (final out in tx["vout"] as List) { for (final out in tx["vout"] as List) {
if (prevOut == out["n"]) { if (prevOut == out["n"]) {
totalIn += (Decimal.parse(out["value"].toString()) * totalIn += (Decimal.parse(out["value"].toString()) *
Decimal.fromInt(Constants.satsPerCoin)) Decimal.fromInt(Constants.satsPerCoin(coin)))
.toBigInt() .toBigInt()
.toInt(); .toInt();
} }
@ -2627,7 +2632,7 @@ class LitecoinWallet extends CoinServiceAPI {
midSortedTx["amount"] = inputAmtSentFromWallet; midSortedTx["amount"] = inputAmtSentFromWallet;
final String worthNow = final String worthNow =
((currentPrice * Decimal.fromInt(inputAmtSentFromWallet)) / ((currentPrice * Decimal.fromInt(inputAmtSentFromWallet)) /
Decimal.fromInt(Constants.satsPerCoin)) Decimal.fromInt(Constants.satsPerCoin(coin)))
.toDecimal(scaleOnInfinitePrecision: 2) .toDecimal(scaleOnInfinitePrecision: 2)
.toStringAsFixed(2); .toStringAsFixed(2);
midSortedTx["worthNow"] = worthNow; midSortedTx["worthNow"] = worthNow;
@ -2637,7 +2642,7 @@ class LitecoinWallet extends CoinServiceAPI {
midSortedTx["amount"] = outputAmtAddressedToWallet; midSortedTx["amount"] = outputAmtAddressedToWallet;
final worthNow = final worthNow =
((currentPrice * Decimal.fromInt(outputAmtAddressedToWallet)) / ((currentPrice * Decimal.fromInt(outputAmtAddressedToWallet)) /
Decimal.fromInt(Constants.satsPerCoin)) Decimal.fromInt(Constants.satsPerCoin(coin)))
.toDecimal(scaleOnInfinitePrecision: 2) .toDecimal(scaleOnInfinitePrecision: 2)
.toStringAsFixed(2); .toStringAsFixed(2);
midSortedTx["worthNow"] = worthNow; midSortedTx["worthNow"] = worthNow;
@ -3769,7 +3774,8 @@ class LitecoinWallet extends CoinServiceAPI {
@override @override
Future<int> estimateFeeFor(int satoshiAmount, int feeRate) async { Future<int> estimateFeeFor(int satoshiAmount, int feeRate) async {
final available = Format.decimalAmountToSatoshis(await availableBalance); final available =
Format.decimalAmountToSatoshis(await availableBalance, coin);
if (available == satoshiAmount) { if (available == satoshiAmount) {
return satoshiAmount - sweepAllEstimate(feeRate); return satoshiAmount - sweepAllEstimate(feeRate);

View file

@ -44,6 +44,7 @@ import 'package:stackwallet/utilities/default_nodes.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart'; import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/utilities/enums/fee_rate_type_enum.dart'; import 'package:stackwallet/utilities/enums/fee_rate_type_enum.dart';
import 'package:stackwallet/utilities/flutter_secure_storage_interface.dart'; import 'package:stackwallet/utilities/flutter_secure_storage_interface.dart';
import 'package:stackwallet/utilities/format.dart';
import 'package:stackwallet/utilities/logger.dart'; import 'package:stackwallet/utilities/logger.dart';
import 'package:stackwallet/utilities/prefs.dart'; import 'package:stackwallet/utilities/prefs.dart';
import 'package:stackwallet/utilities/stack_file_system.dart'; import 'package:stackwallet/utilities/stack_file_system.dart';
@ -533,7 +534,8 @@ class MoneroWallet extends CoinServiceAPI {
@override @override
Future<Decimal> get balanceMinusMaxFee async => Future<Decimal> get balanceMinusMaxFee async =>
(await availableBalance) - (await availableBalance) -
(Decimal.fromInt((await maxFee)) / Decimal.fromInt(Constants.satsPerCoin)) (Decimal.fromInt((await maxFee)) /
Decimal.fromInt(Constants.satsPerCoin(coin)))
.toDecimal(); .toDecimal();
@override @override
@ -542,16 +544,16 @@ class MoneroWallet extends CoinServiceAPI {
@override @override
Future<void> exit() async { Future<void> exit() async {
await stopSyncPercentTimer();
_hasCalledExit = true; _hasCalledExit = true;
isActive = false; stopNetworkAlivePinging();
await walletBase?.save(prioritySave: true);
walletBase?.close();
moneroAutosaveTimer?.cancel(); moneroAutosaveTimer?.cancel();
moneroAutosaveTimer = null; moneroAutosaveTimer = null;
timer?.cancel(); timer?.cancel();
timer = null; timer = null;
stopNetworkAlivePinging(); await stopSyncPercentTimer();
await walletBase?.save(prioritySave: true);
walletBase?.close();
isActive = false;
} }
bool _hasCalledExit = false; bool _hasCalledExit = false;
@ -562,13 +564,15 @@ class MoneroWallet extends CoinServiceAPI {
Future<String>? _currentReceivingAddress; Future<String>? _currentReceivingAddress;
Future<FeeObject> _getFees() async { Future<FeeObject> _getFees() async {
// TODO: not use random hard coded values here
return FeeObject( return FeeObject(
numberOfBlocksFast: 10, numberOfBlocksFast: 10,
numberOfBlocksAverage: 10, numberOfBlocksAverage: 15,
numberOfBlocksSlow: 10, numberOfBlocksSlow: 20,
fast: 4, fast: MoneroTransactionPriority.fast.raw!,
medium: 2, medium: MoneroTransactionPriority.regular.raw!,
slow: 0); slow: MoneroTransactionPriority.slow.raw!,
);
} }
@override @override
@ -868,8 +872,9 @@ class MoneroWallet extends CoinServiceAPI {
Future<int> get maxFee async { Future<int> get maxFee async {
var bal = await availableBalance; var bal = await availableBalance;
var fee = walletBase!.calculateEstimatedFee( var fee = walletBase!.calculateEstimatedFee(
monero.getDefaultTransactionPriority(), bal.toBigInt().toInt()) ~/ monero.getDefaultTransactionPriority(),
10000; Format.decimalAmountToSatoshis(bal, coin),
);
return fee; return fee;
} }
@ -1372,7 +1377,6 @@ class MoneroWallet extends CoinServiceAPI {
} }
@override @override
// TODO: implement availableBalance
Future<Decimal> get availableBalance async { Future<Decimal> get availableBalance async {
var bal = 0; var bal = 0;
for (var element in walletBase!.balance!.entries) { for (var element in walletBase!.balance!.entries) {
@ -1421,13 +1425,13 @@ class MoneroWallet extends CoinServiceAPI {
try { try {
final feeRate = args?["feeRate"]; final feeRate = args?["feeRate"];
if (feeRate is FeeRateType) { if (feeRate is FeeRateType) {
MoneroTransactionPriority feePriority = MoneroTransactionPriority.slow; MoneroTransactionPriority feePriority;
switch (feeRate) { switch (feeRate) {
case FeeRateType.fast: case FeeRateType.fast:
feePriority = MoneroTransactionPriority.fastest; feePriority = MoneroTransactionPriority.fast;
break; break;
case FeeRateType.average: case FeeRateType.average:
feePriority = MoneroTransactionPriority.medium; feePriority = MoneroTransactionPriority.regular;
break; break;
case FeeRateType.slow: case FeeRateType.slow:
feePriority = MoneroTransactionPriority.slow; feePriority = MoneroTransactionPriority.slow;
@ -1440,15 +1444,14 @@ class MoneroWallet extends CoinServiceAPI {
bool isSendAll = false; bool isSendAll = false;
final balance = await availableBalance; final balance = await availableBalance;
final satInDecimal = ((Decimal.fromInt(satoshiAmount) / final satInDecimal = ((Decimal.fromInt(satoshiAmount) /
Decimal.fromInt(Constants.satsPerCoinMonero)) Decimal.fromInt(Constants.satsPerCoin(coin)))
.toDecimal() * .toDecimal());
Decimal.fromInt(10000));
if (satInDecimal == balance) { if (satInDecimal == balance) {
isSendAll = true; isSendAll = true;
} }
Logging.instance Logging.instance
.log("$toAddress $amount $args", level: LogLevel.Info); .log("$toAddress $amount $args", level: LogLevel.Info);
String amountToSend = moneroAmountToString(amount: amount * 10000); String amountToSend = moneroAmountToString(amount: amount);
Logging.instance.log("$amount $amountToSend", level: LogLevel.Info); Logging.instance.log("$amount $amountToSend", level: LogLevel.Info);
monero_output.Output output = monero_output.Output(walletBase!); monero_output.Output output = monero_output.Output(walletBase!);
@ -1470,10 +1473,9 @@ class MoneroWallet extends CoinServiceAPI {
PendingMoneroTransaction pendingMoneroTransaction = PendingMoneroTransaction pendingMoneroTransaction =
await (awaitPendingTransaction!) as PendingMoneroTransaction; await (awaitPendingTransaction!) as PendingMoneroTransaction;
int realfee = (Decimal.parse(pendingMoneroTransaction.feeFormatted) *
100000000.toDecimal()) int realfee = Format.decimalAmountToSatoshis(
.toBigInt() Decimal.parse(pendingMoneroTransaction.feeFormatted), coin);
.toInt();
debugPrint("fee? $realfee"); debugPrint("fee? $realfee");
Map<String, dynamic> txData = { Map<String, dynamic> txData = {
"pendingMoneroTransaction": pendingMoneroTransaction, "pendingMoneroTransaction": pendingMoneroTransaction,
@ -1506,12 +1508,13 @@ class MoneroWallet extends CoinServiceAPI {
@override @override
Future<int> estimateFeeFor(int satoshiAmount, int feeRate) async { Future<int> estimateFeeFor(int satoshiAmount, int feeRate) async {
MoneroTransactionPriority? priority; MoneroTransactionPriority priority;
FeeRateType feeRateType = FeeRateType.slow; FeeRateType feeRateType;
switch (feeRate) { switch (feeRate) {
case 1: case 1:
priority = MoneroTransactionPriority.regular; priority = MoneroTransactionPriority.regular;
feeRateType = FeeRateType.slow; feeRateType = FeeRateType.average;
break; break;
case 2: case 2:
priority = MoneroTransactionPriority.medium; priority = MoneroTransactionPriority.medium;
@ -1519,7 +1522,7 @@ class MoneroWallet extends CoinServiceAPI {
break; break;
case 3: case 3:
priority = MoneroTransactionPriority.fast; priority = MoneroTransactionPriority.fast;
feeRateType = FeeRateType.average; feeRateType = FeeRateType.fast;
break; break;
case 4: case 4:
priority = MoneroTransactionPriority.fastest; priority = MoneroTransactionPriority.fastest;
@ -1531,27 +1534,29 @@ class MoneroWallet extends CoinServiceAPI {
feeRateType = FeeRateType.slow; feeRateType = FeeRateType.slow;
break; break;
} }
var aprox; // int? aprox;
await estimateFeeMutex.protect(() async { // corrupted size vs. prev_size occurs but not sure if related to fees or just generating monero transactions in general
{
try { // await estimateFeeMutex.protect(() async {
aprox = (await prepareSend( // {
// This address is only used for getting an approximate fee, never for sending // try {
address: // aprox = (await prepareSend(
"8347huhmj6Ggzr1BpZPJAD5oa96ob5Fe8GtQdGZDYVVYVsCgtUNH3pEEzExDuaAVZdC16D4FkAb24J6wUfsKkcZtC8EPXB7", // // This address is only used for getting an approximate fee, never for sending
satoshiAmount: satoshiAmount, // address:
args: {"feeRate": feeRateType}))['fee']; // "8347huhmj6Ggzr1BpZPJAD5oa96ob5Fe8GtQdGZDYVVYVsCgtUNH3pEEzExDuaAVZdC16D4FkAb24J6wUfsKkcZtC8EPXB7",
await Future.delayed(const Duration(milliseconds: 1000)); // satoshiAmount: satoshiAmount,
} catch (e, s) { // args: {"feeRate": feeRateType}))['fee'] as int?;
Logging.instance.log("$feeRateType $e $s", level: LogLevel.Error); // await Future<void>.delayed(const Duration(milliseconds: 1000));
aprox = -9999999999999999; // } catch (e, s) {
} // Logging.instance.log("$feeRateType $e $s", level: LogLevel.Error);
} final aprox = walletBase!.calculateEstimatedFee(priority, satoshiAmount);
}); // }
// }
// });
print("this is the aprox fee $aprox for $satoshiAmount"); print("this is the aprox fee $aprox for $satoshiAmount");
final fee = (aprox as int); final fee = aprox;
return fee; return fee;
} }

View file

@ -196,19 +196,21 @@ class NamecoinWallet extends CoinServiceAPI {
Future<Decimal> get availableBalance async { Future<Decimal> get availableBalance async {
final data = await utxoData; final data = await utxoData;
return Format.satoshisToAmount( return Format.satoshisToAmount(
data.satoshiBalance - data.satoshiBalanceUnconfirmed); data.satoshiBalance - data.satoshiBalanceUnconfirmed,
coin: coin);
} }
@override @override
Future<Decimal> get pendingBalance async { Future<Decimal> get pendingBalance async {
final data = await utxoData; final data = await utxoData;
return Format.satoshisToAmount(data.satoshiBalanceUnconfirmed); return Format.satoshisToAmount(data.satoshiBalanceUnconfirmed, coin: coin);
} }
@override @override
Future<Decimal> get balanceMinusMaxFee async => Future<Decimal> get balanceMinusMaxFee async =>
(await availableBalance) - (await availableBalance) -
(Decimal.fromInt((await maxFee)) / Decimal.fromInt(Constants.satsPerCoin)) (Decimal.fromInt((await maxFee)) /
Decimal.fromInt(Constants.satsPerCoin(coin)))
.toDecimal(); .toDecimal();
@override @override
@ -218,13 +220,13 @@ class NamecoinWallet extends CoinServiceAPI {
.get<dynamic>(boxName: walletId, key: 'totalBalance') as int?; .get<dynamic>(boxName: walletId, key: 'totalBalance') as int?;
if (totalBalance == null) { if (totalBalance == null) {
final data = await utxoData; final data = await utxoData;
return Format.satoshisToAmount(data.satoshiBalance); return Format.satoshisToAmount(data.satoshiBalance, coin: coin);
} else { } else {
return Format.satoshisToAmount(totalBalance); return Format.satoshisToAmount(totalBalance, coin: coin);
} }
} }
final data = await utxoData; final data = await utxoData;
return Format.satoshisToAmount(data.satoshiBalance); return Format.satoshisToAmount(data.satoshiBalance, coin: coin);
} }
@override @override
@ -262,7 +264,8 @@ class NamecoinWallet extends CoinServiceAPI {
@override @override
Future<int> get maxFee async { Future<int> get maxFee async {
final fee = (await fees).fast as String; final fee = (await fees).fast as String;
final satsFee = Decimal.parse(fee) * Decimal.fromInt(Constants.satsPerCoin); final satsFee =
Decimal.parse(fee) * Decimal.fromInt(Constants.satsPerCoin(coin));
return satsFee.floor().toBigInt().toInt(); return satsFee.floor().toBigInt().toInt();
} }
@ -1086,7 +1089,8 @@ class NamecoinWallet extends CoinServiceAPI {
// check for send all // check for send all
bool isSendAll = false; bool isSendAll = false;
final balance = Format.decimalAmountToSatoshis(await availableBalance); final balance =
Format.decimalAmountToSatoshis(await availableBalance, coin);
if (satoshiAmount == balance) { if (satoshiAmount == balance) {
isSendAll = true; isSendAll = true;
} }
@ -1290,7 +1294,7 @@ class NamecoinWallet extends CoinServiceAPI {
final String worthNow = Format.localizedStringAsFixed( final String worthNow = Format.localizedStringAsFixed(
value: value:
((currentPrice * Decimal.fromInt(txData["recipientAmt"] as int)) / ((currentPrice * Decimal.fromInt(txData["recipientAmt"] as int)) /
Decimal.fromInt(Constants.satsPerCoin)) Decimal.fromInt(Constants.satsPerCoin(coin)))
.toDecimal(scaleOnInfinitePrecision: 2), .toDecimal(scaleOnInfinitePrecision: 2),
decimalPlaces: 2, decimalPlaces: 2,
locale: locale!); locale: locale!);
@ -1490,9 +1494,9 @@ class NamecoinWallet extends CoinServiceAPI {
numberOfBlocksFast: f, numberOfBlocksFast: f,
numberOfBlocksAverage: m, numberOfBlocksAverage: m,
numberOfBlocksSlow: s, numberOfBlocksSlow: s,
fast: Format.decimalAmountToSatoshis(fast), fast: Format.decimalAmountToSatoshis(fast, coin),
medium: Format.decimalAmountToSatoshis(medium), medium: Format.decimalAmountToSatoshis(medium, coin),
slow: Format.decimalAmountToSatoshis(slow), slow: Format.decimalAmountToSatoshis(slow, coin),
); );
Logging.instance.log("fetched fees: $feeObject", level: LogLevel.Info); Logging.instance.log("fetched fees: $feeObject", level: LogLevel.Info);
@ -1965,7 +1969,7 @@ class NamecoinWallet extends CoinServiceAPI {
utxo["status"]["block_time"] = txn["blocktime"]; utxo["status"]["block_time"] = txn["blocktime"];
final fiatValue = ((Decimal.fromInt(value) * currentPrice) / final fiatValue = ((Decimal.fromInt(value) * currentPrice) /
Decimal.fromInt(Constants.satsPerCoin)) Decimal.fromInt(Constants.satsPerCoin(coin)))
.toDecimal(scaleOnInfinitePrecision: 2); .toDecimal(scaleOnInfinitePrecision: 2);
utxo["rawWorth"] = fiatValue; utxo["rawWorth"] = fiatValue;
utxo["fiatWorth"] = fiatValue.toString(); utxo["fiatWorth"] = fiatValue.toString();
@ -1975,15 +1979,16 @@ class NamecoinWallet extends CoinServiceAPI {
Decimal currencyBalanceRaw = Decimal currencyBalanceRaw =
((Decimal.fromInt(satoshiBalance) * currentPrice) / ((Decimal.fromInt(satoshiBalance) * currentPrice) /
Decimal.fromInt(Constants.satsPerCoin)) Decimal.fromInt(Constants.satsPerCoin(coin)))
.toDecimal(scaleOnInfinitePrecision: 2); .toDecimal(scaleOnInfinitePrecision: 2);
final Map<String, dynamic> result = { final Map<String, dynamic> result = {
"total_user_currency": currencyBalanceRaw.toString(), "total_user_currency": currencyBalanceRaw.toString(),
"total_sats": satoshiBalance, "total_sats": satoshiBalance,
"total_btc": (Decimal.fromInt(satoshiBalance) / "total_btc": (Decimal.fromInt(satoshiBalance) /
Decimal.fromInt(Constants.satsPerCoin)) Decimal.fromInt(Constants.satsPerCoin(coin)))
.toDecimal(scaleOnInfinitePrecision: Constants.decimalPlaces) .toDecimal(
scaleOnInfinitePrecision: Constants.decimalPlacesForCoin(coin))
.toString(), .toString(),
"outputArray": outputArray, "outputArray": outputArray,
"unconfirmed": satoshiBalancePending, "unconfirmed": satoshiBalancePending,
@ -2540,7 +2545,7 @@ class NamecoinWallet extends CoinServiceAPI {
if (prevOut == out["n"]) { if (prevOut == out["n"]) {
inputAmtSentFromWallet += inputAmtSentFromWallet +=
(Decimal.parse(out["value"]!.toString()) * (Decimal.parse(out["value"]!.toString()) *
Decimal.fromInt(Constants.satsPerCoin)) Decimal.fromInt(Constants.satsPerCoin(coin)))
.toBigInt() .toBigInt()
.toInt(); .toInt();
} }
@ -2554,7 +2559,7 @@ class NamecoinWallet extends CoinServiceAPI {
final address = output["scriptPubKey"]["address"]; final address = output["scriptPubKey"]["address"];
final value = output["value"]; final value = output["value"];
final _value = (Decimal.parse(value.toString()) * final _value = (Decimal.parse(value.toString()) *
Decimal.fromInt(Constants.satsPerCoin)) Decimal.fromInt(Constants.satsPerCoin(coin)))
.toBigInt() .toBigInt()
.toInt(); .toInt();
totalOutput += _value; totalOutput += _value;
@ -2582,7 +2587,7 @@ class NamecoinWallet extends CoinServiceAPI {
} }
if (address != null) { if (address != null) {
final value = (Decimal.parse(output["value"].toString()) * final value = (Decimal.parse(output["value"].toString()) *
Decimal.fromInt(Constants.satsPerCoin)) Decimal.fromInt(Constants.satsPerCoin(coin)))
.toBigInt() .toBigInt()
.toInt(); .toInt();
totalOut += value; totalOut += value;
@ -2605,7 +2610,7 @@ class NamecoinWallet extends CoinServiceAPI {
for (final out in tx["vout"] as List) { for (final out in tx["vout"] as List) {
if (prevOut == out["n"]) { if (prevOut == out["n"]) {
totalIn += (Decimal.parse(out["value"].toString()) * totalIn += (Decimal.parse(out["value"].toString()) *
Decimal.fromInt(Constants.satsPerCoin)) Decimal.fromInt(Constants.satsPerCoin(coin)))
.toBigInt() .toBigInt()
.toInt(); .toInt();
} }
@ -2627,7 +2632,7 @@ class NamecoinWallet extends CoinServiceAPI {
midSortedTx["amount"] = inputAmtSentFromWallet; midSortedTx["amount"] = inputAmtSentFromWallet;
final String worthNow = final String worthNow =
((currentPrice * Decimal.fromInt(inputAmtSentFromWallet)) / ((currentPrice * Decimal.fromInt(inputAmtSentFromWallet)) /
Decimal.fromInt(Constants.satsPerCoin)) Decimal.fromInt(Constants.satsPerCoin(coin)))
.toDecimal(scaleOnInfinitePrecision: 2) .toDecimal(scaleOnInfinitePrecision: 2)
.toStringAsFixed(2); .toStringAsFixed(2);
midSortedTx["worthNow"] = worthNow; midSortedTx["worthNow"] = worthNow;
@ -2637,7 +2642,7 @@ class NamecoinWallet extends CoinServiceAPI {
midSortedTx["amount"] = outputAmtAddressedToWallet; midSortedTx["amount"] = outputAmtAddressedToWallet;
final worthNow = final worthNow =
((currentPrice * Decimal.fromInt(outputAmtAddressedToWallet)) / ((currentPrice * Decimal.fromInt(outputAmtAddressedToWallet)) /
Decimal.fromInt(Constants.satsPerCoin)) Decimal.fromInt(Constants.satsPerCoin(coin)))
.toDecimal(scaleOnInfinitePrecision: 2) .toDecimal(scaleOnInfinitePrecision: 2)
.toStringAsFixed(2); .toStringAsFixed(2);
midSortedTx["worthNow"] = worthNow; midSortedTx["worthNow"] = worthNow;
@ -3772,7 +3777,8 @@ class NamecoinWallet extends CoinServiceAPI {
@override @override
Future<int> estimateFeeFor(int satoshiAmount, int feeRate) async { Future<int> estimateFeeFor(int satoshiAmount, int feeRate) async {
final available = Format.decimalAmountToSatoshis(await availableBalance); final available =
Format.decimalAmountToSatoshis(await availableBalance, coin);
if (available == satoshiAmount) { if (available == satoshiAmount) {
return satoshiAmount - sweepAllEstimate(feeRate); return satoshiAmount - sweepAllEstimate(feeRate);

View file

@ -45,6 +45,7 @@ import 'package:stackwallet/utilities/default_nodes.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart'; import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/utilities/enums/fee_rate_type_enum.dart'; import 'package:stackwallet/utilities/enums/fee_rate_type_enum.dart';
import 'package:stackwallet/utilities/flutter_secure_storage_interface.dart'; import 'package:stackwallet/utilities/flutter_secure_storage_interface.dart';
import 'package:stackwallet/utilities/format.dart';
import 'package:stackwallet/utilities/logger.dart'; import 'package:stackwallet/utilities/logger.dart';
import 'package:stackwallet/utilities/prefs.dart'; import 'package:stackwallet/utilities/prefs.dart';
import 'package:stackwallet/utilities/stack_file_system.dart'; import 'package:stackwallet/utilities/stack_file_system.dart';
@ -534,8 +535,7 @@ class WowneroWallet extends CoinServiceAPI {
@override @override
Future<Decimal> get balanceMinusMaxFee async => Future<Decimal> get balanceMinusMaxFee async =>
(await availableBalance) - (await availableBalance) -
(Decimal.fromInt((await maxFee)) / Decimal.fromInt(Constants.satsPerCoin)) Format.satoshisToAmount(await maxFee, coin: Coin.wownero);
.toDecimal();
@override @override
Future<String> get currentReceivingAddress => Future<String> get currentReceivingAddress =>
@ -563,13 +563,15 @@ class WowneroWallet extends CoinServiceAPI {
Future<String>? _currentReceivingAddress; Future<String>? _currentReceivingAddress;
Future<FeeObject> _getFees() async { Future<FeeObject> _getFees() async {
// TODO: not use random hard coded values here
return FeeObject( return FeeObject(
numberOfBlocksFast: 10, numberOfBlocksFast: 10,
numberOfBlocksAverage: 10, numberOfBlocksAverage: 15,
numberOfBlocksSlow: 10, numberOfBlocksSlow: 20,
fast: 4, fast: MoneroTransactionPriority.fast.raw!,
medium: 2, medium: MoneroTransactionPriority.regular.raw!,
slow: 0); slow: MoneroTransactionPriority.slow.raw!,
);
} }
@override @override
@ -873,8 +875,9 @@ class WowneroWallet extends CoinServiceAPI {
Future<int> get maxFee async { Future<int> get maxFee async {
var bal = await availableBalance; var bal = await availableBalance;
var fee = walletBase!.calculateEstimatedFee( var fee = walletBase!.calculateEstimatedFee(
wownero.getDefaultTransactionPriority(), bal.toBigInt().toInt()) ~/ wownero.getDefaultTransactionPriority(),
10000; Format.decimalAmountToSatoshis(bal, coin),
);
return fee; return fee;
} }
@ -1446,13 +1449,13 @@ class WowneroWallet extends CoinServiceAPI {
try { try {
final feeRate = args?["feeRate"]; final feeRate = args?["feeRate"];
if (feeRate is FeeRateType) { if (feeRate is FeeRateType) {
MoneroTransactionPriority feePriority = MoneroTransactionPriority.slow; MoneroTransactionPriority feePriority;
switch (feeRate) { switch (feeRate) {
case FeeRateType.fast: case FeeRateType.fast:
feePriority = MoneroTransactionPriority.fastest; feePriority = MoneroTransactionPriority.fast;
break; break;
case FeeRateType.average: case FeeRateType.average:
feePriority = MoneroTransactionPriority.medium; feePriority = MoneroTransactionPriority.regular;
break; break;
case FeeRateType.slow: case FeeRateType.slow:
feePriority = MoneroTransactionPriority.slow; feePriority = MoneroTransactionPriority.slow;
@ -1465,15 +1468,14 @@ class WowneroWallet extends CoinServiceAPI {
bool isSendAll = false; bool isSendAll = false;
final balance = await availableBalance; final balance = await availableBalance;
final satInDecimal = ((Decimal.fromInt(satoshiAmount) / final satInDecimal = ((Decimal.fromInt(satoshiAmount) /
Decimal.fromInt(Constants.satsPerCoinWownero)) Decimal.fromInt(Constants.satsPerCoin(coin)))
.toDecimal() * .toDecimal());
Decimal.fromInt(1000));
if (satInDecimal == balance) { if (satInDecimal == balance) {
isSendAll = true; isSendAll = true;
} }
Logging.instance Logging.instance
.log("$toAddress $amount $args", level: LogLevel.Info); .log("$toAddress $amount $args", level: LogLevel.Info);
String amountToSend = wowneroAmountToString(amount: amount * 1000); String amountToSend = wowneroAmountToString(amount: amount);
Logging.instance.log("$amount $amountToSend", level: LogLevel.Info); Logging.instance.log("$amount $amountToSend", level: LogLevel.Info);
wownero_output.Output output = wownero_output.Output(walletBase!); wownero_output.Output output = wownero_output.Output(walletBase!);
@ -1495,10 +1497,8 @@ class WowneroWallet extends CoinServiceAPI {
PendingWowneroTransaction pendingWowneroTransaction = PendingWowneroTransaction pendingWowneroTransaction =
await (awaitPendingTransaction!) as PendingWowneroTransaction; await (awaitPendingTransaction!) as PendingWowneroTransaction;
int realfee = (Decimal.parse(pendingWowneroTransaction.feeFormatted) * int realfee = Format.decimalAmountToSatoshis(
100000000.toDecimal()) Decimal.parse(pendingWowneroTransaction.feeFormatted), coin);
.toBigInt()
.toInt();
debugPrint("fee? $realfee"); debugPrint("fee? $realfee");
Map<String, dynamic> txData = { Map<String, dynamic> txData = {
"pendingWowneroTransaction": pendingWowneroTransaction, "pendingWowneroTransaction": pendingWowneroTransaction,
@ -1531,12 +1531,12 @@ class WowneroWallet extends CoinServiceAPI {
@override @override
Future<int> estimateFeeFor(int satoshiAmount, int feeRate) async { Future<int> estimateFeeFor(int satoshiAmount, int feeRate) async {
MoneroTransactionPriority? priority; MoneroTransactionPriority priority;
FeeRateType feeRateType = FeeRateType.slow; FeeRateType feeRateType = FeeRateType.slow;
switch (feeRate) { switch (feeRate) {
case 1: case 1:
priority = MoneroTransactionPriority.regular; priority = MoneroTransactionPriority.regular;
feeRateType = FeeRateType.slow; feeRateType = FeeRateType.average;
break; break;
case 2: case 2:
priority = MoneroTransactionPriority.medium; priority = MoneroTransactionPriority.medium;
@ -1544,7 +1544,7 @@ class WowneroWallet extends CoinServiceAPI {
break; break;
case 3: case 3:
priority = MoneroTransactionPriority.fast; priority = MoneroTransactionPriority.fast;
feeRateType = FeeRateType.average; feeRateType = FeeRateType.fast;
break; break;
case 4: case 4:
priority = MoneroTransactionPriority.fastest; priority = MoneroTransactionPriority.fastest;
@ -1568,7 +1568,7 @@ class WowneroWallet extends CoinServiceAPI {
args: {"feeRate": feeRateType}))['fee']; args: {"feeRate": feeRateType}))['fee'];
await Future.delayed(const Duration(milliseconds: 500)); await Future.delayed(const Duration(milliseconds: 500));
} catch (e, s) { } catch (e, s) {
aprox = -9999999999999999; aprox = walletBase!.calculateEstimatedFee(priority, satoshiAmount);
} }
} }
}); });

View file

@ -23,12 +23,12 @@ abstract class Constants {
static bool enableExchange = Util.isDesktop || !Platform.isIOS; static bool enableExchange = Util.isDesktop || !Platform.isIOS;
//TODO: correct for monero? //TODO: correct for monero?
static const int satsPerCoinMonero = 1000000000000; static const int _satsPerCoinMonero = 1000000000000;
static const int satsPerCoinWownero = 100000000000; static const int _satsPerCoinWownero = 100000000000;
static const int satsPerCoin = 100000000; static const int _satsPerCoin = 100000000;
static const int decimalPlaces = 8; static const int _decimalPlaces = 8;
static const int decimalPlacesWownero = 11; static const int _decimalPlacesWownero = 11;
static const int decimalPlacesMonero = 12; static const int _decimalPlacesMonero = 12;
static const int notificationsMax = 0xFFFFFFFF; static const int notificationsMax = 0xFFFFFFFF;
static const Duration networkAliveTimerDuration = Duration(seconds: 10); static const Duration networkAliveTimerDuration = Duration(seconds: 10);
@ -40,6 +40,30 @@ abstract class Constants {
static const int currentHiveDbVersion = 3; static const int currentHiveDbVersion = 3;
static int satsPerCoin(Coin coin) {
switch (coin) {
case Coin.bitcoin:
case Coin.litecoin:
case Coin.litecoinTestNet:
case Coin.bitcoincash:
case Coin.bitcoincashTestnet:
case Coin.dogecoin:
case Coin.firo:
case Coin.bitcoinTestNet:
case Coin.dogecoinTestNet:
case Coin.firoTestNet:
case Coin.epicCash:
case Coin.namecoin:
return _satsPerCoin;
case Coin.wownero:
return _satsPerCoinWownero;
case Coin.monero:
return _satsPerCoinMonero;
}
}
static int decimalPlacesForCoin(Coin coin) { static int decimalPlacesForCoin(Coin coin) {
switch (coin) { switch (coin) {
case Coin.bitcoin: case Coin.bitcoin:
@ -54,13 +78,13 @@ abstract class Constants {
case Coin.firoTestNet: case Coin.firoTestNet:
case Coin.epicCash: case Coin.epicCash:
case Coin.namecoin: case Coin.namecoin:
return decimalPlaces; return _decimalPlaces;
case Coin.wownero: case Coin.wownero:
return decimalPlacesWownero; return _decimalPlacesWownero;
case Coin.monero: case Coin.monero:
return decimalPlacesMonero; return _decimalPlacesMonero;
} }
} }

View file

@ -8,46 +8,28 @@ import 'package:stackwallet/utilities/enums/backup_frequency_type.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart'; import 'package:stackwallet/utilities/enums/coin_enum.dart';
abstract class Format { abstract class Format {
static Decimal satoshisToAmount(int sats, {Coin? coin}) { static Decimal satoshisToAmount(int sats, {required Coin coin}) {
late final int satsPerCoin; return (Decimal.fromInt(sats) /
Decimal.fromInt(Constants.satsPerCoin(coin)))
switch (coin) { .toDecimal(
case Coin.wownero: scaleOnInfinitePrecision: Constants.decimalPlacesForCoin(coin));
satsPerCoin = Constants.satsPerCoinWownero;
break;
case Coin.monero:
satsPerCoin = Constants.satsPerCoinMonero;
break;
case Coin.bitcoin:
case Coin.bitcoincash:
case Coin.dogecoin:
case Coin.epicCash:
case Coin.firo:
case Coin.litecoin:
case Coin.namecoin:
case Coin.bitcoinTestNet:
case Coin.litecoinTestNet:
case Coin.bitcoincashTestnet:
case Coin.dogecoinTestNet:
case Coin.firoTestNet:
default:
satsPerCoin = Constants.satsPerCoin;
}
return (Decimal.fromInt(sats) / Decimal.fromInt(satsPerCoin))
.toDecimal(scaleOnInfinitePrecision: Constants.decimalPlaces);
} }
/// ///
static String satoshiAmountToPrettyString(int sats, String locale) { static String satoshiAmountToPrettyString(
final amount = satoshisToAmount(sats); int sats, String locale, Coin coin) {
final amount = satoshisToAmount(sats, coin: coin);
return localizedStringAsFixed( return localizedStringAsFixed(
value: amount, locale: locale, decimalPlaces: Constants.decimalPlaces); value: amount,
locale: locale,
decimalPlaces: Constants.decimalPlacesForCoin(coin),
);
} }
static int decimalAmountToSatoshis(Decimal amount) { static int decimalAmountToSatoshis(Decimal amount, Coin coin) {
final value = final value = (Decimal.fromInt(Constants.satsPerCoin(coin)) * amount)
(Decimal.fromInt(Constants.satsPerCoin) * amount).floor().toBigInt(); .floor()
.toBigInt();
return value.toInt(); return value.toInt();
} }

View file

@ -203,7 +203,7 @@ class _ExchangeTextFieldState extends State<ExchangeTextField> {
width: 6, width: 6,
), ),
Text( Text(
widget.ticker ?? "-", widget.ticker?.toUpperCase() ?? "-",
style: STextStyles.smallMed14(context).copyWith( style: STextStyles.smallMed14(context).copyWith(
color: Theme.of(context) color: Theme.of(context)
.extension<StackColors>()! .extension<StackColors>()!

View file

@ -9,7 +9,6 @@ import 'package:stackwallet/pages/wallet_view/transaction_views/transaction_deta
import 'package:stackwallet/providers/providers.dart'; import 'package:stackwallet/providers/providers.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';
import 'package:stackwallet/utilities/enums/flush_bar_type.dart';
import 'package:stackwallet/utilities/format.dart'; import 'package:stackwallet/utilities/format.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';
@ -198,13 +197,9 @@ class _TransactionCardState extends ConsumerState<TransactionCard> {
fit: BoxFit.scaleDown, fit: BoxFit.scaleDown,
child: Builder( child: Builder(
builder: (_) { builder: (_) {
final amount = coin == Coin.monero final amount = _transaction.amount;
? (_transaction.amount ~/ 10000)
: coin == Coin.wownero
? (_transaction.amount ~/ 1000)
: _transaction.amount;
return Text( return Text(
"$prefix${Format.satoshiAmountToPrettyString(amount, locale)} ${coin.ticker}", "$prefix${Format.satoshiAmountToPrettyString(amount, locale, coin)} ${coin.ticker}",
style: style:
STextStyles.itemSubtitle12_600(context), STextStyles.itemSubtitle12_600(context),
); );
@ -242,17 +237,12 @@ class _TransactionCardState extends ConsumerState<TransactionCard> {
fit: BoxFit.scaleDown, fit: BoxFit.scaleDown,
child: Builder( child: Builder(
builder: (_) { builder: (_) {
// TODO: modify Format.<functions> to take optional Coin parameter so this type oif check isn't done in ui
int value = _transaction.amount; int value = _transaction.amount;
if (coin == Coin.monero) {
value = (value ~/ 10000);
} else if (coin == Coin.wownero) {
value = (value ~/ 1000);
}
return Text( return Text(
"$prefix${Format.localizedStringAsFixed( "$prefix${Format.localizedStringAsFixed(
value: Format.satoshisToAmount(value) * value: Format.satoshisToAmount(value,
coin: coin) *
price, price,
locale: locale, locale: locale,
decimalPlaces: 2, decimalPlaces: 2,

View file

@ -11,7 +11,7 @@ description: Stack Wallet
# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion. # In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
# Read more about iOS versioning at # Read more about iOS versioning at
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
version: 1.5.18+90 version: 1.5.19+91
environment: environment:
sdk: ">=2.17.0 <3.0.0" sdk: ">=2.17.0 <3.0.0"

View file

@ -1,54 +1,64 @@
import 'package:decimal/decimal.dart'; import 'package:decimal/decimal.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/utilities/format.dart'; import 'package:stackwallet/utilities/format.dart';
void main() { void main() {
group("satoshisToAmount", () { group("satoshisToAmount", () {
test("12345", () { test("12345", () {
expect(Format.satoshisToAmount(12345), Decimal.parse("0.00012345")); expect(Format.satoshisToAmount(12345, coin: Coin.bitcoin),
Decimal.parse("0.00012345"));
}); });
test("100012345", () { test("100012345", () {
expect(Format.satoshisToAmount(100012345), Decimal.parse("1.00012345")); expect(Format.satoshisToAmount(100012345, coin: Coin.bitcoin),
Decimal.parse("1.00012345"));
}); });
test("0", () { test("0", () {
expect(Format.satoshisToAmount(0), Decimal.zero); expect(Format.satoshisToAmount(0, coin: Coin.bitcoin), Decimal.zero);
}); });
test("1000000000", () { test("1000000000", () {
expect(Format.satoshisToAmount(1000000000), Decimal.parse("10")); expect(Format.satoshisToAmount(1000000000, coin: Coin.bitcoin),
Decimal.parse("10"));
}); });
}); });
group("satoshiAmountToPrettyString", () { group("satoshiAmountToPrettyString", () {
const locale = "en_US"; const locale = "en_US";
test("12345", () { test("12345", () {
expect(Format.satoshiAmountToPrettyString(12345, locale), "0.00012345"); expect(Format.satoshiAmountToPrettyString(12345, locale, Coin.bitcoin),
"0.00012345");
}); });
test("100012345", () { test("100012345", () {
expect( expect(
Format.satoshiAmountToPrettyString(100012345, locale), "1.00012345"); Format.satoshiAmountToPrettyString(100012345, locale, Coin.bitcoin),
"1.00012345");
}); });
test("123450000", () { test("123450000", () {
expect( expect(
Format.satoshiAmountToPrettyString(123450000, locale), "1.23450000"); Format.satoshiAmountToPrettyString(123450000, locale, Coin.bitcoin),
"1.23450000");
}); });
test("1230045000", () { test("1230045000", () {
expect(Format.satoshiAmountToPrettyString(1230045000, locale), expect(
Format.satoshiAmountToPrettyString(1230045000, locale, Coin.bitcoin),
"12.30045000"); "12.30045000");
}); });
test("1000000000", () { test("1000000000", () {
expect(Format.satoshiAmountToPrettyString(1000000000, locale), expect(
Format.satoshiAmountToPrettyString(1000000000, locale, Coin.bitcoin),
"10.00000000"); "10.00000000");
}); });
test("0", () { test("0", () {
expect(Format.satoshiAmountToPrettyString(0, locale), "0.00000000"); expect(Format.satoshiAmountToPrettyString(0, locale, Coin.bitcoin),
"0.00000000");
}); });
}); });