diff --git a/cw_monero/lib/monero_output.dart b/cw_monero/lib/monero_output.dart new file mode 100644 index 000000000..831ee1f22 --- /dev/null +++ b/cw_monero/lib/monero_output.dart @@ -0,0 +1,8 @@ +import 'package:flutter/foundation.dart'; + +class MoneroOutput { + MoneroOutput({@required this.address, @required this.amount}); + + final String address; + final String amount; +} \ No newline at end of file diff --git a/cw_monero/lib/transaction_history.dart b/cw_monero/lib/transaction_history.dart index 799d4d512..58db9c8e3 100644 --- a/cw_monero/lib/transaction_history.dart +++ b/cw_monero/lib/transaction_history.dart @@ -1,5 +1,6 @@ import 'dart:ffi'; import 'package:cw_monero/convert_utf8_to_string.dart'; +import 'package:cw_monero/monero_output.dart'; import 'package:cw_monero/structs/ut8_box.dart'; import 'package:ffi/ffi.dart'; import 'package:flutter/foundation.dart'; @@ -107,21 +108,21 @@ PendingTransactionDescription createTransactionSync( } PendingTransactionDescription createTransactionMultDestSync( - {List addresses, + {List outputs, String paymentId, - List amounts, - int size, int priorityRaw, int accountIndex = 0}) { - final List> addressesPointers = addresses.map(Utf8.toUtf8).toList(); + final int size = outputs.length; + final List> addressesPointers = outputs.map((output) => + Utf8.toUtf8(output.address)).toList(); final Pointer> addressesPointerPointer = allocate(count: size); - - final List> amountsPointers = amounts.map(Utf8.toUtf8).toList(); + final List> amountsPointers = outputs.map((output) => + Utf8.toUtf8(output.amount)).toList(); final Pointer> amountsPointerPointer = allocate(count: size); for (int i = 0; i < size; i++) { - addressesPointerPointer[ i ] = addressesPointers[ i ]; - amountsPointerPointer[ i ] = amountsPointers[ i ]; + addressesPointerPointer[i] = addressesPointers[i]; + amountsPointerPointer[i] = amountsPointers[i]; } final paymentIdPointer = Utf8.toUtf8(paymentId); @@ -190,18 +191,14 @@ PendingTransactionDescription _createTransactionSync(Map args) { } PendingTransactionDescription _createTransactionMultDestSync(Map args) { - final addresses = args['addresses'] as List; + final outputs = args['outputs'] as List; final paymentId = args['paymentId'] as String; - final amounts = args['amounts'] as List; - final size = args['size'] as int; final priorityRaw = args['priorityRaw'] as int; final accountIndex = args['accountIndex'] as int; return createTransactionMultDestSync( - addresses: addresses, + outputs: outputs, paymentId: paymentId, - amounts: amounts, - size: size, priorityRaw: priorityRaw, accountIndex: accountIndex); } @@ -221,17 +218,13 @@ Future createTransaction( }); Future createTransactionMultDest( - {List addresses, + {List outputs, String paymentId, - List amounts, - int size, int priorityRaw, int accountIndex = 0}) => compute(_createTransactionMultDestSync, { - 'addresses': addresses, + 'outputs': outputs, 'paymentId': paymentId, - 'amounts': amounts, - 'size': size, 'priorityRaw': priorityRaw, 'accountIndex': accountIndex }); diff --git a/lib/bitcoin/bitcoin_transaction_credentials.dart b/lib/bitcoin/bitcoin_transaction_credentials.dart index 49a6bebc9..2799dbb28 100644 --- a/lib/bitcoin/bitcoin_transaction_credentials.dart +++ b/lib/bitcoin/bitcoin_transaction_credentials.dart @@ -1,9 +1,9 @@ import 'package:cake_wallet/bitcoin/bitcoin_transaction_priority.dart'; -import 'package:cake_wallet/view_model/send/send_item.dart'; +import 'package:cake_wallet/view_model/send/output.dart'; class BitcoinTransactionCredentials { - BitcoinTransactionCredentials(this.sendItemList, this.priority); + BitcoinTransactionCredentials(this.outputs, this.priority); - final List sendItemList; + final List outputs; BitcoinTransactionPriority priority; } diff --git a/lib/bitcoin/electrum_wallet.dart b/lib/bitcoin/electrum_wallet.dart index cf9fedd06..2df77951c 100644 --- a/lib/bitcoin/electrum_wallet.dart +++ b/lib/bitcoin/electrum_wallet.dart @@ -158,7 +158,8 @@ abstract class ElectrumWalletBase extends WalletBase[]; - final sendItemList = transactionCredentials.sendItemList; + final outputs = transactionCredentials.outputs; + final hasMultiDestination = outputs.length > 1; var allInputsAmount = 0; if (unspentCoins.isEmpty) { @@ -177,61 +178,54 @@ abstract class ElectrumWalletBase extends WalletBase 1) { - final sendAllItems = sendItemList.where((item) => item.sendAll).toList(); + if (hasMultiDestination) { + final sendAllItems = outputs.where((item) => item.sendAll).toList(); if (sendAllItems?.isNotEmpty ?? false) { throw BitcoinTransactionWrongBalanceException(currency); } - final nullAmountItems = sendItemList.where((item) => - stringDoubleToBitcoinAmount(item.cryptoAmount.replaceAll(',', '.')) <= 0) - .toList(); + final nullAmountItems = outputs.where((item) => + item.formattedCryptoAmount <= 0).toList(); if (nullAmountItems?.isNotEmpty ?? false) { throw BitcoinTransactionWrongBalanceException(currency); } - credentialsAmount = sendItemList.fold(0, (previousValue, element) => - previousValue + stringDoubleToBitcoinAmount( - element.cryptoAmount.replaceAll(',', '.'))); + credentialsAmount = outputs.fold(0, (acc, value) => + acc + value.formattedCryptoAmount); - if (credentialsAmount > allAmount) { + if (allAmount - credentialsAmount < minAmount) { throw BitcoinTransactionWrongBalanceException(currency); } - amount = allAmount - credentialsAmount < minAmount - ? allAmount - : credentialsAmount; + amount = credentialsAmount; - fee = amount == allAmount - ? allAmountFee - : calculateEstimatedFee(transactionCredentials.priority, amount, - outputsCount: sendItemList.length + 1); + fee = calculateEstimatedFee(transactionCredentials.priority, amount, + outputsCount: outputs.length + 1); } else { - final sendItem = sendItemList.first; + final output = outputs.first; - credentialsAmount = !sendItem.sendAll - ? stringDoubleToBitcoinAmount( - sendItem.cryptoAmount.replaceAll(',', '.')) + credentialsAmount = !output.sendAll + ? output.formattedCryptoAmount : 0; if (credentialsAmount > allAmount) { throw BitcoinTransactionWrongBalanceException(currency); } - amount = sendItem.sendAll || allAmount - credentialsAmount < minAmount + amount = output.sendAll || allAmount - credentialsAmount < minAmount ? allAmount : credentialsAmount; - fee = sendItem.sendAll || amount == allAmount + fee = output.sendAll || amount == allAmount ? allAmountFee : calculateEstimatedFee(transactionCredentials.priority, amount); } @@ -289,18 +283,18 @@ abstract class ElectrumWalletBase extends WalletBase sendItemList; + final List outputs; final MoneroTransactionPriority priority; } diff --git a/lib/monero/monero_wallet.dart b/lib/monero/monero_wallet.dart index 6652f27ee..3acb67926 100644 --- a/lib/monero/monero_wallet.dart +++ b/lib/monero/monero_wallet.dart @@ -13,6 +13,7 @@ import 'package:cw_monero/transaction_history.dart' import 'package:cw_monero/wallet.dart'; import 'package:cw_monero/wallet.dart' as monero_wallet; import 'package:cw_monero/transaction_history.dart' as transaction_history; +import 'package:cw_monero/monero_output.dart'; import 'package:cake_wallet/monero/monero_transaction_creation_credentials.dart'; import 'package:cake_wallet/monero/pending_monero_transaction.dart'; import 'package:cake_wallet/monero/monero_wallet_keys.dart'; @@ -150,8 +151,8 @@ abstract class MoneroWalletBase extends WalletBase createTransaction(Object credentials) async { final _credentials = credentials as MoneroTransactionCreationCredentials; - final sendItemList = _credentials.sendItemList; - final listSize = sendItemList.length; + final outputs = _credentials.outputs; + final hasMultiDestination = outputs.length > 1; final unlockedBalance = monero_wallet.getUnlockedBalance(accountIndex: walletAddresses.account.id); @@ -161,16 +162,15 @@ abstract class MoneroWalletBase extends WalletBase 1) { - final sendAllItems = sendItemList.where((item) => item.sendAll).toList(); + if (hasMultiDestination) { + final sendAllItems = outputs.where((item) => item.sendAll).toList(); if (sendAllItems?.isNotEmpty ?? false) { throw MoneroTransactionCreationException('Wrong balance. Not enough XMR on your balance.'); } - final nullAmountItems = sendItemList.where((item) => - moneroParseAmount(amount: item.cryptoAmount.replaceAll(',', '.')) <= 0) - .toList(); + final nullAmountItems = outputs.where((item) => + item.formattedCryptoAmount <= 0).toList(); if (nullAmountItems?.isNotEmpty ?? false) { throw MoneroTransactionCreationException('Wrong balance. Not enough XMR on your balance.'); @@ -178,42 +178,41 @@ abstract class MoneroWalletBase extends WalletBase - previousValue + moneroParseAmount( - amount: element.cryptoAmount.replaceAll(',', '.'))); + credentialsAmount = outputs.fold(0, (acc, value) => + acc + value.formattedCryptoAmount); if (unlockedBalance < credentialsAmount) { throw MoneroTransactionCreationException('Wrong balance. Not enough XMR on your balance.'); } - final addresses = sendItemList.map((e) => e.address).toList(); - final amounts = sendItemList.map((e) => - e.cryptoAmount.replaceAll(',', '.')).toList(); + final moneroOutputs = outputs.map((output) => + MoneroOutput( + address: output.address, + amount: output.cryptoAmount.replaceAll(',', '.'))) + .toList(); pendingTransactionDescription = await transaction_history.createTransactionMultDest( - addresses: addresses, + outputs: moneroOutputs, paymentId: '', - amounts: amounts, - size: listSize, priorityRaw: _credentials.priority.serialize(), accountIndex: walletAddresses.account.id); } else { - final item = sendItemList.first; - final address = item.address; - final amount = item.sendAll + final output = outputs.first; + final address = output.address; + final amount = output.sendAll ? null - : item.cryptoAmount.replaceAll(',', '.'); - final formattedAmount = item.sendAll + : output.cryptoAmount.replaceAll(',', '.'); + final formattedAmount = output.sendAll ? null - : moneroParseAmount(amount: amount); + : output.formattedCryptoAmount; if ((formattedAmount != null && unlockedBalance < formattedAmount) || (formattedAmount == null && unlockedBalance <= 0)) { final formattedBalance = moneroAmountToString(amount: unlockedBalance); throw MoneroTransactionCreationException( - 'Incorrect unlocked balance. Unlocked: $formattedBalance. Transaction amount: ${item.cryptoAmount}.'); + 'Incorrect unlocked balance. Unlocked: $formattedBalance. Transaction amount: ${output.cryptoAmount}.'); } pendingTransactionDescription = diff --git a/lib/src/screens/exchange_trade/exchange_trade_page.dart b/lib/src/screens/exchange_trade/exchange_trade_page.dart index df859fe2b..c20b60e3c 100644 --- a/lib/src/screens/exchange_trade/exchange_trade_page.dart +++ b/lib/src/screens/exchange_trade/exchange_trade_page.dart @@ -385,8 +385,8 @@ class ExchangeTradeState extends State { .pendingTransactionFiatAmount + ' ' + widget.exchangeTradeViewModel.sendViewModel.fiat.title, - sendItemList: widget.exchangeTradeViewModel.sendViewModel - .sendItemList); + outputs: widget.exchangeTradeViewModel.sendViewModel + .outputs); }); }); } diff --git a/lib/src/screens/send/send_page.dart b/lib/src/screens/send/send_page.dart index c17ecdc93..4b1e2e65a 100644 --- a/lib/src/screens/send/send_page.dart +++ b/lib/src/screens/send/send_page.dart @@ -3,7 +3,7 @@ import 'package:cake_wallet/src/screens/send/widgets/parse_address_from_domain_a import 'package:cake_wallet/src/screens/send/widgets/send_card.dart'; import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart'; import 'package:cake_wallet/src/widgets/template_tile.dart'; -import 'package:cake_wallet/view_model/send/send_item.dart'; +import 'package:cake_wallet/view_model/send/output.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_mobx/flutter_mobx.dart'; @@ -55,16 +55,16 @@ class SendPage extends BasePage { onPressed: () { var pageToJump = controller.page.round() - 1; pageToJump = pageToJump > 0 ? pageToJump : 0; - final item = _defineCurrentSendItem(); - sendViewModel.removeSendItem(item); + final output = _defineCurrentOutput(); + sendViewModel.removeOutput(output); controller.jumpToPage(pageToJump); }) : TrailButton( caption: S.of(context).clear, onPressed: () { - final item = _defineCurrentSendItem(); + final output = _defineCurrentOutput(); _formKey.currentState.reset(); - item.reset(); + output.reset(); }); }); @@ -85,13 +85,13 @@ class SendPage extends BasePage { return PageView.builder( scrollDirection: Axis.horizontal, controller: controller, - itemCount: sendViewModel.sendItemList.length, + itemCount: sendViewModel.outputs.length, itemBuilder: (context, index) { - final item = sendViewModel.sendItemList[index]; + final output = sendViewModel.outputs[index]; return SendCard( - key: item.key, - item: item, + key: output.key, + output: output, sendViewModel: sendViewModel, ); } @@ -104,7 +104,7 @@ class SendPage extends BasePage { child: Container( height: 10, child: Observer(builder: (_) { - final count = sendViewModel.sendItemList.length; + final count = sendViewModel.outputs.length; return count > 1 ? SmoothPageIndicator( @@ -211,11 +211,11 @@ class SendPage extends BasePage { amount: template.amount, from: template.cryptoCurrency, onTap: () async { - final item = _defineCurrentSendItem(); - item.address = + final output = _defineCurrentOutput(); + output.address = template.address; - item.setCryptoAmount(template.amount); - final parsedAddress = await item + output.setCryptoAmount(template.amount); + final parsedAddress = await output .applyOpenaliasOrUnstoppableDomains(); showAddressAlert(context, parsedAddress); }, @@ -263,7 +263,7 @@ class SendPage extends BasePage { padding: EdgeInsets.only(bottom: 12), child: PrimaryButton( onPressed: () { - sendViewModel.addSendItem(); + sendViewModel.addOutput(); }, text: S.of(context).add_receiver, color: Colors.green, @@ -274,16 +274,16 @@ class SendPage extends BasePage { return LoadingPrimaryButton( onPressed: () async { if (!_formKey.currentState.validate()) { - if (sendViewModel.sendItemList.length > 1) { + if (sendViewModel.outputs.length > 1) { showErrorValidationAlert(context); } return; } - final notValidItems = sendViewModel.sendItemList + final notValidItems = sendViewModel.outputs .where((item) => - item.address.isEmpty || item.cryptoAmount.isEmpty) + item.address.isEmpty || item.cryptoAmount.isEmpty) .toList(); if (notValidItems?.isNotEmpty ?? false) { @@ -343,7 +343,7 @@ class SendPage extends BasePage { feeValue: sendViewModel.pendingTransaction.feeFormatted, feeFiatAmount: sendViewModel.pendingTransactionFeeFiatAmount + ' ' + sendViewModel.fiat.title, - sendItemList: sendViewModel.sendItemList, + outputs: sendViewModel.outputs, rightButtonText: S.of(context).ok, leftButtonText: S.of(context).cancel, actionRightButton: () { @@ -381,7 +381,7 @@ class SendPage extends BasePage { if (state is TransactionCommitted) { WidgetsBinding.instance.addPostFrameCallback((_) { - sendViewModel.clearSendItemList(); + sendViewModel.clearOutputs(); }); } }); @@ -389,9 +389,9 @@ class SendPage extends BasePage { _effectsInstalled = true; } - SendItem _defineCurrentSendItem() { + Output _defineCurrentOutput() { final itemCount = controller.page.round(); - return sendViewModel.sendItemList[itemCount]; + return sendViewModel.outputs[itemCount]; } void showErrorValidationAlert(BuildContext context) async { diff --git a/lib/src/screens/send/send_template_page.dart b/lib/src/screens/send/send_template_page.dart index 27ee71d23..e35f7d71d 100644 --- a/lib/src/screens/send/send_template_page.dart +++ b/lib/src/screens/send/send_template_page.dart @@ -14,7 +14,7 @@ import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart'; class SendTemplatePage extends BasePage { SendTemplatePage({@required this.sendTemplateViewModel}) { - sendTemplateViewModel.sendItem.reset(); + sendTemplateViewModel.output.reset(); } final SendTemplateViewModel sendTemplateViewModel; @@ -258,21 +258,21 @@ class SendTemplatePage extends BasePage { return; } - final item = sendTemplateViewModel.sendItem; + final output = sendTemplateViewModel.output; - reaction((_) => item.fiatAmount, (String amount) { + reaction((_) => output.fiatAmount, (String amount) { if (amount != _fiatAmountController.text) { _fiatAmountController.text = amount; } }); - reaction((_) => item.cryptoAmount, (String amount) { + reaction((_) => output.cryptoAmount, (String amount) { if (amount != _cryptoAmountController.text) { _cryptoAmountController.text = amount; } }); - reaction((_) => item.address, (String address) { + reaction((_) => output.address, (String address) { if (address != _addressController.text) { _addressController.text = address; } @@ -281,24 +281,24 @@ class SendTemplatePage extends BasePage { _cryptoAmountController.addListener(() { final amount = _cryptoAmountController.text; - if (amount != item.cryptoAmount) { - item.setCryptoAmount(amount); + if (amount != output.cryptoAmount) { + output.setCryptoAmount(amount); } }); _fiatAmountController.addListener(() { final amount = _fiatAmountController.text; - if (amount != item.fiatAmount) { - item.setFiatAmount(amount); + if (amount != output.fiatAmount) { + output.setFiatAmount(amount); } }); _addressController.addListener(() { final address = _addressController.text; - if (item.address != address) { - item.address = address; + if (output.address != address) { + output.address = address; } }); diff --git a/lib/src/screens/send/widgets/confirm_sending_alert.dart b/lib/src/screens/send/widgets/confirm_sending_alert.dart index cfe44f80d..f6defa984 100644 --- a/lib/src/screens/send/widgets/confirm_sending_alert.dart +++ b/lib/src/screens/send/widgets/confirm_sending_alert.dart @@ -1,5 +1,5 @@ import 'package:cake_wallet/palette.dart'; -import 'package:cake_wallet/view_model/send/send_item.dart'; +import 'package:cake_wallet/view_model/send/output.dart'; import 'package:flutter/material.dart'; import 'package:cake_wallet/src/widgets/base_alert_dialog.dart'; import 'package:cake_wallet/generated/i18n.dart'; @@ -13,14 +13,14 @@ class ConfirmSendingAlert extends BaseAlertDialog { @required this.fee, @required this.feeValue, @required this.feeFiatAmount, - @required this.sendItemList, + @required this.outputs, @required this.leftButtonText, @required this.rightButtonText, @required this.actionLeftButton, @required this.actionRightButton, this.alertBarrierDismissible = true }) { - itemCount = sendItemList.length; + itemCount = outputs.length; recipientTitle = itemCount > 1 ? S.current.transaction_details_recipient_address : S.current.recipient_address; @@ -33,7 +33,7 @@ class ConfirmSendingAlert extends BaseAlertDialog { final String fee; final String feeValue; final String feeFiatAmount; - final List sendItemList; + final List outputs; final String leftButtonText; final String rightButtonText; final VoidCallback actionLeftButton; @@ -179,10 +179,10 @@ class ConfirmSendingAlert extends BaseAlertDialog { physics: NeverScrollableScrollPhysics(), itemCount: itemCount, itemBuilder: (context, index) { - final item = sendItemList[index]; + final item = outputs[index]; final _address = item.address; final _amount = - item.cryptoAmount.replaceAll(',', '.'); + item.cryptoAmount.replaceAll(',', '.'); return Column( children: [ @@ -225,7 +225,7 @@ class ConfirmSendingAlert extends BaseAlertDialog { : Padding( padding: EdgeInsets.only(top: 8), child: Text( - sendItemList.first.address, + outputs.first.address, style: TextStyle( fontSize: 12, fontWeight: FontWeight.w600, diff --git a/lib/src/screens/send/widgets/send_card.dart b/lib/src/screens/send/widgets/send_card.dart index ccce5c43e..6ac1ded10 100644 --- a/lib/src/screens/send/widgets/send_card.dart +++ b/lib/src/screens/send/widgets/send_card.dart @@ -4,7 +4,7 @@ import 'package:cake_wallet/routes.dart'; import 'package:cake_wallet/src/screens/send/widgets/parse_address_from_domain_alert.dart'; import 'package:cake_wallet/src/widgets/keyboard_done_button.dart'; import 'package:cake_wallet/src/widgets/picker.dart'; -import 'package:cake_wallet/view_model/send/send_item.dart'; +import 'package:cake_wallet/view_model/send/output.dart'; import 'package:cake_wallet/view_model/settings/settings_view_model.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; @@ -19,21 +19,21 @@ import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/src/widgets/base_text_form_field.dart'; class SendCard extends StatefulWidget { - SendCard({Key key, @required this.item, @required this.sendViewModel}) : super(key: key); + SendCard({Key key, @required this.output, @required this.sendViewModel}) : super(key: key); - final SendItem item; + final Output output; final SendViewModel sendViewModel; @override SendCardState createState() => SendCardState( - item: item, + output: output, sendViewModel: sendViewModel ); } class SendCardState extends State with AutomaticKeepAliveClientMixin { - SendCardState({@required this.item, @required this.sendViewModel}) + SendCardState({@required this.output, @required this.sendViewModel}) : addressController = TextEditingController(), cryptoAmountController = TextEditingController(), fiatAmountController = TextEditingController(), @@ -45,7 +45,7 @@ class SendCardState extends State static const prefixIconWidth = 34.0; static const prefixIconHeight = 34.0; - final SendItem item; + final Output output; final SendViewModel sendViewModel; final TextEditingController addressController; @@ -143,7 +143,7 @@ class SendCardState extends State .decorationColor), onPushPasteButton: (context) async { final parsedAddress = - await item.applyOpenaliasOrUnstoppableDomains(); + await output.applyOpenaliasOrUnstoppableDomains(); showAddressAlert(context, parsedAddress); }, validator: sendViewModel.addressValidator, @@ -189,7 +189,7 @@ class SendCardState extends State .decorationColor, fontWeight: FontWeight.w500, fontSize: 14), - validator: item.sendAll + validator: output.sendAll ? sendViewModel.allAmountValidator : sendViewModel .amountValidator), @@ -201,7 +201,7 @@ class SendCardState extends State height: prefixIconHeight, child: InkWell( onTap: () async => - item.setSendAll(), + output.setSendAll(), child: Container( decoration: BoxDecoration( color: Theme.of(context) @@ -349,7 +349,7 @@ class SendCardState extends State crossAxisAlignment: CrossAxisAlignment.end, children: [ Text( - item + output .estimatedFee .toString() + ' ' + @@ -366,7 +366,7 @@ class SendCardState extends State padding: EdgeInsets.only(top: 5), child: Text( - item + output .estimatedFeeFiatAmount + ' ' + sendViewModel @@ -435,10 +435,10 @@ class SendCardState extends State } void _setEffects(BuildContext context) { - addressController.text = item.address; - cryptoAmountController.text = item.cryptoAmount; - fiatAmountController.text = item.fiatAmount; - noteController.text = item.note; + addressController.text = output.address; + cryptoAmountController.text = output.cryptoAmount; + fiatAmountController.text = output.fiatAmount; + noteController.text = output.note; if (_effectsInstalled) { return; @@ -447,48 +447,48 @@ class SendCardState extends State cryptoAmountController.addListener(() { final amount = cryptoAmountController.text; - if (item.sendAll && amount != S.current.all) { - item.sendAll = false; + if (output.sendAll && amount != S.current.all) { + output.sendAll = false; } - if (amount != item.cryptoAmount) { - item.setCryptoAmount(amount); + if (amount != output.cryptoAmount) { + output.setCryptoAmount(amount); } }); fiatAmountController.addListener(() { final amount = fiatAmountController.text; - if (amount != item.fiatAmount) { - item.sendAll = false; - item.setFiatAmount(amount); + if (amount != output.fiatAmount) { + output.sendAll = false; + output.setFiatAmount(amount); } }); noteController.addListener(() { final note = noteController.text ?? ''; - if (note != item.note) { - item.note = note; + if (note != output.note) { + output.note = note; } }); - reaction((_) => item.sendAll, (bool all) { + reaction((_) => output.sendAll, (bool all) { if (all) { cryptoAmountController.text = S.current.all; fiatAmountController.text = null; } }); - reaction((_) => item.fiatAmount, (String amount) { + reaction((_) => output.fiatAmount, (String amount) { if (amount != fiatAmountController.text) { fiatAmountController.text = amount; } }); - reaction((_) => item.cryptoAmount, (String amount) { - if (item.sendAll && amount != S.current.all) { - item.sendAll = false; + reaction((_) => output.cryptoAmount, (String amount) { + if (output.sendAll && amount != S.current.all) { + output.sendAll = false; } if (amount != cryptoAmountController.text) { @@ -496,7 +496,7 @@ class SendCardState extends State } }); - reaction((_) => item.address, (String address) { + reaction((_) => output.address, (String address) { if (address != addressController.text) { addressController.text = address; } @@ -505,12 +505,12 @@ class SendCardState extends State addressController.addListener(() { final address = addressController.text; - if (item.address != address) { - item.address = address; + if (output.address != address) { + output.address = address; } }); - reaction((_) => item.note, (String note) { + reaction((_) => output.note, (String note) { if (note != noteController.text) { noteController.text = note; } @@ -518,7 +518,7 @@ class SendCardState extends State addressFocusNode.addListener(() async { if (!addressFocusNode.hasFocus && addressController.text.isNotEmpty) { - final parsedAddress = await item.applyOpenaliasOrUnstoppableDomains(); + final parsedAddress = await output.applyOpenaliasOrUnstoppableDomains(); showAddressAlert(context, parsedAddress); } }); diff --git a/lib/view_model/exchange/exchange_trade_view_model.dart b/lib/view_model/exchange/exchange_trade_view_model.dart index eeb9bfd26..5445823a2 100644 --- a/lib/view_model/exchange/exchange_trade_view_model.dart +++ b/lib/view_model/exchange/exchange_trade_view_model.dart @@ -79,11 +79,11 @@ abstract class ExchangeTradeViewModelBase with Store { return; } - sendViewModel.clearSendItemList(); - final item = sendViewModel.sendItemList.first; + sendViewModel.clearOutputs(); + final output = sendViewModel.outputs.first; - item.address = trade.inputAddress; - item.setCryptoAmount(trade.amount); + output.address = trade.inputAddress; + output.setCryptoAmount(trade.amount); await sendViewModel.createTransaction(); } diff --git a/lib/view_model/send/send_item.dart b/lib/view_model/send/output.dart similarity index 92% rename from lib/view_model/send/send_item.dart rename to lib/view_model/send/output.dart index 153a6c1d7..e47956d7c 100644 --- a/lib/view_model/send/send_item.dart +++ b/lib/view_model/send/output.dart @@ -15,14 +15,14 @@ import 'package:cake_wallet/store/dashboard/fiat_conversion_store.dart'; import 'package:cake_wallet/store/settings_store.dart'; import 'package:cake_wallet/generated/i18n.dart'; -part 'send_item.g.dart'; +part 'output.g.dart'; const String cryptoNumberPattern = '0.0'; -class SendItem = SendItemBase with _$SendItem; +class Output = OutputBase with _$Output; -abstract class SendItemBase with Store { - SendItemBase(this._wallet, this._settingsStore, this._fiatConversationStore) +abstract class OutputBase with Store { + OutputBase(this._wallet, this._settingsStore, this._fiatConversationStore) :_cryptoNumberFormat = NumberFormat(cryptoNumberPattern) { reset(); _setCryptoNumMaximumFractionDigits(); @@ -47,8 +47,8 @@ abstract class SendItemBase with Store { bool sendAll; @computed - double get estimatedFee { - int amount; + int get formattedCryptoAmount { + int amount = 0; try { if (cryptoAmount?.isNotEmpty ?? false) { @@ -72,9 +72,18 @@ abstract class SendItemBase with Store { amount = _amount; } } + } catch(e) { + amount = 0; + } + return amount; + } + + @computed + double get estimatedFee { + try { final fee = _wallet.calculateEstimatedFee( - _settingsStore.priority[_wallet.type], amount); + _settingsStore.priority[_wallet.type], formattedCryptoAmount); if (_wallet is ElectrumWallet) { return bitcoinAmountToDouble(amount: fee); diff --git a/lib/view_model/send/send_template_view_model.dart b/lib/view_model/send/send_template_view_model.dart index 37848a6ec..9ddd8f5f6 100644 --- a/lib/view_model/send/send_template_view_model.dart +++ b/lib/view_model/send/send_template_view_model.dart @@ -1,4 +1,4 @@ -import 'package:cake_wallet/view_model/send/send_item.dart'; +import 'package:cake_wallet/view_model/send/output.dart'; import 'package:mobx/mobx.dart'; import 'package:cake_wallet/entities/template.dart'; import 'package:cake_wallet/store/templates/send_template_store.dart'; @@ -21,10 +21,10 @@ abstract class SendTemplateViewModelBase with Store { SendTemplateViewModelBase(this._wallet, this._settingsStore, this._sendTemplateStore, this._fiatConversationStore) { - sendItem = SendItem(_wallet, _settingsStore, _fiatConversationStore); + output = Output(_wallet, _settingsStore, _fiatConversationStore); } - SendItem sendItem; + Output output; Validator get amountValidator => AmountValidator(type: _wallet.type); diff --git a/lib/view_model/send/send_view_model.dart b/lib/view_model/send/send_view_model.dart index 9601c4f0e..1a65e5f89 100644 --- a/lib/view_model/send/send_view_model.dart +++ b/lib/view_model/send/send_view_model.dart @@ -2,7 +2,7 @@ import 'package:cake_wallet/bitcoin/bitcoin_transaction_priority.dart'; import 'package:cake_wallet/bitcoin/electrum_wallet.dart'; import 'package:cake_wallet/entities/transaction_description.dart'; import 'package:cake_wallet/entities/transaction_priority.dart'; -import 'package:cake_wallet/view_model/send/send_item.dart'; +import 'package:cake_wallet/view_model/send/output.dart'; import 'package:cake_wallet/view_model/send/send_template_view_model.dart'; import 'package:cake_wallet/view_model/settings/settings_view_model.dart'; import 'package:hive/hive.dart'; @@ -42,33 +42,33 @@ abstract class SendViewModelBase with Store { _settingsStore.priority[_wallet.type] = priorities.first; } - sendItemList = ObservableList() - ..add(SendItem(_wallet, _settingsStore, _fiatConversationStore)); + outputs = ObservableList() + ..add(Output(_wallet, _settingsStore, _fiatConversationStore)); } @observable ExecutionState state; - ObservableList sendItemList; + ObservableList outputs; @action - void addSendItem() { - sendItemList.add(SendItem(_wallet, _settingsStore, _fiatConversationStore)); + void addOutput() { + outputs.add(Output(_wallet, _settingsStore, _fiatConversationStore)); } @action - void removeSendItem(SendItem item) { - sendItemList.remove(item); + void removeOutput(Output output) { + outputs.remove(output); } @action - void clearSendItemList() { - sendItemList.clear(); - addSendItem(); + void clearOutputs() { + outputs.clear(); + addOutput(); } @computed - bool get isBatchSending => sendItemList.length > 1; + bool get isBatchSending => outputs.length > 1; @computed String get pendingTransactionFiatAmount { @@ -150,14 +150,14 @@ abstract class SendViewModelBase with Store { @action Future commitTransaction() async { - String address = sendItemList.fold('', (previousValue, item) { - return previousValue + item.address + '\n'; + String address = outputs.fold('', (acc, value) { + return acc + value.address + '\n'; }); address = address.trim(); - String note = sendItemList.fold('', (previousValue, item) { - return previousValue + item.note + '\n'; + String note = outputs.fold('', (acc, value) { + return acc + value.note + '\n'; }); note = note.trim(); @@ -192,17 +192,17 @@ abstract class SendViewModelBase with Store { final priority = _settingsStore.priority[_wallet.type]; return BitcoinTransactionCredentials( - sendItemList, priority as BitcoinTransactionPriority); + outputs, priority as BitcoinTransactionPriority); case WalletType.litecoin: final priority = _settingsStore.priority[_wallet.type]; return BitcoinTransactionCredentials( - sendItemList, priority as BitcoinTransactionPriority); + outputs, priority as BitcoinTransactionPriority); case WalletType.monero: final priority = _settingsStore.priority[_wallet.type]; return MoneroTransactionCreationCredentials( - sendItemList: sendItemList, + outputs: outputs, priority: priority as MoneroTransactionPriority); default: return null;