diff --git a/android/gradle.properties b/android/gradle.properties index 38c8d4544..7199c1559 100644 --- a/android/gradle.properties +++ b/android/gradle.properties @@ -2,3 +2,4 @@ org.gradle.jvmargs=-Xmx1536M android.enableR8=true android.useAndroidX=true android.enableJetifier=true +org.gradle.java.home=C:\\Program Files\\Java\\jdk1.8.0_181 diff --git a/cw_haven/ios/Classes/haven_api.cpp b/cw_haven/ios/Classes/haven_api.cpp index c1013bf87..65957c277 100644 --- a/cw_haven/ios/Classes/haven_api.cpp +++ b/cw_haven/ios/Classes/haven_api.cpp @@ -927,6 +927,25 @@ extern "C" return static_cast(rates.size()); } + uint64_t estimate_transaction_fee(int outputs, uint8_t priority_raw) + { + // estimateTransactionFee only cares about the number of outputs + std::vector> destinations; + for (int i = 0; i < outputs; i++) { + destinations.push_back({"", 0}); + } + auto priority = static_cast(priority_raw); + + try { + return m_wallet->estimateTransactionFee(destinations, priority); + } + catch (...) { + // estimateTransactionFee can throw an exception if there is a problem with the + // network request. We must catch it here because exceptions don't propagate to Dart. + return 0; + } + } + #ifdef __cplusplus } #endif diff --git a/cw_haven/lib/api/signatures.dart b/cw_haven/lib/api/signatures.dart index 9dd1c8dac..5c4c80d7a 100644 --- a/cw_haven/lib/api/signatures.dart +++ b/cw_haven/lib/api/signatures.dart @@ -137,4 +137,8 @@ typedef get_rate = Pointer Function(); typedef size_of_rate = Int32 Function(); -typedef update_rate = Void Function(); \ No newline at end of file +typedef update_rate = Void Function(); + +typedef estimate_transaction_fee = Int64 Function( + Int32 outputs, + Int8 priorityRaw); \ No newline at end of file diff --git a/cw_haven/lib/api/types.dart b/cw_haven/lib/api/types.dart index 878297501..c789f0599 100644 --- a/cw_haven/lib/api/types.dart +++ b/cw_haven/lib/api/types.dart @@ -135,4 +135,6 @@ typedef GetRate = Pointer Function(); typedef SizeOfRate = int Function(); -typedef UpdateRate = void Function(); \ No newline at end of file +typedef UpdateRate = void Function(); + +typedef EstimateTransactionFee = int Function(int, int); \ No newline at end of file diff --git a/cw_haven/lib/api/wallet.dart b/cw_haven/lib/api/wallet.dart index 3370fd3e0..9dbefce8e 100644 --- a/cw_haven/lib/api/wallet.dart +++ b/cw_haven/lib/api/wallet.dart @@ -8,7 +8,6 @@ import 'package:cw_haven/api/types.dart'; import 'package:cw_haven/api/haven_api.dart'; import 'package:cw_haven/api/exceptions/setup_wallet_exception.dart'; import 'package:flutter/foundation.dart'; -import 'package:flutter/services.dart'; int _boolToInt(bool value) => value ? 1 : 0; @@ -116,6 +115,10 @@ final rescanBlockchainAsyncNative = havenApi .lookup>('rescan_blockchain') .asFunction(); +final estimateTransactionFeeNative = havenApi + .lookup>('estimate_transaction_fee') + .asFunction(); + int getSyncingHeight() => getSyncingHeightNative(); bool isNeededToRefresh() => isNeededToRefreshNative() != 0; @@ -346,3 +349,18 @@ Future isConnected() => compute(_isConnected, 0); Future getNodeHeight() => compute(_getNodeHeight, 0); void rescanBlockchainAsync() => rescanBlockchainAsyncNative(); + +int estimateTransactionFeeSync(int outputs, int priorityRaw) { + return estimateTransactionFeeNative(outputs, priorityRaw); +} + +int _estimateTransactionFee(Map args) { + final priorityRaw = args['priorityRaw'] as int; + final outputsCount = args['outputsCount'] as int; + + return estimateTransactionFeeSync(outputsCount, priorityRaw); +} + +Future estimateTransactionFee({int priorityRaw, int outputsCount}) { + return compute(_estimateTransactionFee, {'priorityRaw': priorityRaw, 'outputsCount': outputsCount}); +} \ No newline at end of file diff --git a/cw_haven/lib/haven_fee_estimate.dart b/cw_haven/lib/haven_fee_estimate.dart new file mode 100644 index 000000000..826690887 --- /dev/null +++ b/cw_haven/lib/haven_fee_estimate.dart @@ -0,0 +1,38 @@ +import 'package:mobx/mobx.dart'; +import 'package:cw_core/fee_estimate.dart'; +import 'package:cw_core/transaction_priority.dart'; +import 'package:cw_haven/api/wallet.dart' as haven_wallet; + +part 'haven_fee_estimate.g.dart'; + +class HavenFeeEstimate = _HavenFeeEstimate with _$HavenFeeEstimate; + +abstract class _HavenFeeEstimate extends FeeEstimate with Store { + _HavenFeeEstimate() + : _estimatedFee = new ObservableMap(); + + @observable + ObservableMap _estimatedFee; + + @override + void update({TransactionPriority priority, int outputsCount}) { + Future(() async { + final fee = await haven_wallet.estimateTransactionFee(priorityRaw: priority.raw, outputsCount: outputsCount); + set(priority: priority, fee: fee, outputsCount: outputsCount); + }); + } + + @override + int get({TransactionPriority priority, int amount, int outputsCount}) { + return _estimatedFee[_key(priority, outputsCount)] ?? 0; + } + + @override + void set({TransactionPriority priority, int outputsCount, int fee}) { + _estimatedFee[_key(priority, outputsCount)] = fee; + } + + String _key(TransactionPriority priority, int outputsCount) { + return "$priority:$outputsCount"; + } +} \ No newline at end of file diff --git a/cw_haven/lib/haven_wallet.dart b/cw_haven/lib/haven_wallet.dart index c107d2f52..50fb2c1bf 100644 --- a/cw_haven/lib/haven_wallet.dart +++ b/cw_haven/lib/haven_wallet.dart @@ -1,6 +1,5 @@ import 'dart:async'; import 'package:cw_core/crypto_currency.dart'; -import 'package:cw_core/transaction_priority.dart'; import 'package:cw_haven/haven_transaction_creation_credentials.dart'; import 'package:cw_core/monero_amount_format.dart'; import 'package:cw_haven/haven_transaction_creation_exception.dart'; @@ -26,8 +25,8 @@ import 'package:cw_core/wallet_base.dart'; import 'package:cw_core/sync_status.dart'; import 'package:cw_core/wallet_info.dart'; import 'package:cw_core/node.dart'; -import 'package:cw_core/monero_transaction_priority.dart'; import 'package:cw_haven/haven_balance.dart'; +import 'package:cw_haven/haven_fee_estimate.dart'; part 'haven_wallet.g.dart'; @@ -49,10 +48,14 @@ abstract class HavenWalletBase extends WalletBase save() async { await walletAddresses.updateAddressesInBox(); diff --git a/lib/reactions/on_current_wallet_change.dart b/lib/reactions/on_current_wallet_change.dart index ab1838d58..5910f90cd 100644 --- a/lib/reactions/on_current_wallet_change.dart +++ b/lib/reactions/on_current_wallet_change.dart @@ -15,7 +15,6 @@ import 'package:cake_wallet/store/settings_store.dart'; import 'package:cake_wallet/core/fiat_conversion_service.dart'; import 'package:cw_core/wallet_base.dart'; import 'package:cw_core/wallet_type.dart'; -import 'package:cake_wallet/store/yat/yat_store.dart'; ReactionDisposer _onCurrentWalletChangeReaction; ReactionDisposer _onCurrentWalletChangeFiatRateUpdateReaction; @@ -53,7 +52,7 @@ void startCurrentWalletChangeReaction(AppStore appStore, wallet) async { try { final node = settingsStore.getCurrentNode(wallet.type); - startWalletSyncStatusChangeReaction(wallet, fiatConversionStore); + startWalletSyncStatusChangeReaction(wallet, fiatConversionStore, settingsStore); startCheckConnectionReaction(wallet, settingsStore); await getIt .get() diff --git a/lib/reactions/on_wallet_sync_status_change.dart b/lib/reactions/on_wallet_sync_status_change.dart index 60e401e82..122c332bc 100644 --- a/lib/reactions/on_wallet_sync_status_change.dart +++ b/lib/reactions/on_wallet_sync_status_change.dart @@ -2,17 +2,14 @@ import 'package:cake_wallet/di.dart'; import 'package:cake_wallet/entities/update_haven_rate.dart'; import 'package:cake_wallet/entities/wake_lock.dart'; import 'package:cake_wallet/store/settings_store.dart'; -import 'package:cw_core/transaction_priority.dart'; import 'package:cake_wallet/store/dashboard/fiat_conversion_store.dart'; import 'package:cw_core/wallet_type.dart'; -import 'package:cw_monero/monero_transaction_priority.dart'; import 'package:mobx/mobx.dart'; import 'package:cw_core/transaction_history.dart'; import 'package:cw_core/wallet_base.dart'; import 'package:cw_core/balance.dart'; import 'package:cw_core/transaction_info.dart'; import 'package:cw_core/sync_status.dart'; -import 'package:flutter/services.dart'; ReactionDisposer _onWalletSyncStatusChangeReaction; diff --git a/lib/src/screens/send/widgets/send_card.dart b/lib/src/screens/send/widgets/send_card.dart index 73b83c213..e4557b360 100644 --- a/lib/src/screens/send/widgets/send_card.dart +++ b/lib/src/screens/send/widgets/send_card.dart @@ -265,7 +265,6 @@ class SendCardState extends State child: InkWell( onTap: () { output.setSendAll(); - cryptoAmountController.text = sendViewModel.balance; }, child: Container( decoration: BoxDecoration( @@ -557,10 +556,13 @@ class SendCardState extends State reaction((_) => output.fiatAmount, (String amount) { if (amount != fiatAmountController.text) { - fiatAmountController.text = amount; - // final doubleAmount = double.tryParse(amount) ?? 0; - // final doubleFee = double.tryParse(sendViewModel.estimatedFiatFee(sendViewModel.balance)) ?? 0; - // fiatAmountController.text = doubleAmount - doubleFee > 0 ? "${doubleAmount - doubleFee}" : "0.00"; + if (sendViewModel.outputs[0].sendAll) { + final doubleAmount = double.tryParse(amount) ?? 0; + final doubleFee = sendViewModel.estimatedFee; + fiatAmountController.text = doubleAmount - doubleFee > 0 ? "${doubleAmount - doubleFee}" : "0.00"; + } else { + fiatAmountController.text = amount; + } } }); diff --git a/lib/view_model/send/output.dart b/lib/view_model/send/output.dart index 9d1eb6dc3..195d77813 100644 --- a/lib/view_model/send/output.dart +++ b/lib/view_model/send/output.dart @@ -193,7 +193,7 @@ abstract class OutputBase with Store { int _estimateAmountAll() { final fee = _wallet.feeEstimate.get(priority: _settingsStore.priority[_wallet.type], outputsCount: 1); - return max(0, _wallet.balance.available - fee); + return max(0, _wallet.balance[cryptoCurrencyHandler()].available - fee); } Future fetchParsedAddress(BuildContext context) async { diff --git a/lib/view_model/send/send_view_model.dart b/lib/view_model/send/send_view_model.dart index f1a59557f..c030b918e 100644 --- a/lib/view_model/send/send_view_model.dart +++ b/lib/view_model/send/send_view_model.dart @@ -1,5 +1,3 @@ -import 'package:cake_wallet/core/amount_converter.dart'; -import 'package:cake_wallet/entities/balance_display_mode.dart'; import 'package:cake_wallet/entities/format_amount.dart'; import 'package:cake_wallet/entities/transaction_description.dart'; import 'package:cake_wallet/view_model/dashboard/balance_view_model.dart'; @@ -58,6 +56,8 @@ abstract class SendViewModelBase with Store { _settingsStore.priority.observe((change) async { _wallet.feeEstimate.update(priority: change.newValue, outputsCount: outputs.length); }); + + estimateFee(); } @observable @@ -166,16 +166,6 @@ abstract class SendViewModelBase with Store { bool get hasCurrecyChanger => walletType == WalletType.haven; - int estimatedFee(String amount) { - return _wallet.calculateEstimatedFee(_settingsStore.priority[_wallet.type], AmountConverter.amountStringToInt( - selectedCryptoCurrency, amount)); - } - - String estimatedFiatFee(String amount) { - return _calculateFiatAmount(AmountConverter.amountIntToString( - selectedCryptoCurrency, estimatedFee(amount))); - } - final WalletBase _wallet; final SettingsStore _settingsStore; final SendTemplateViewModel sendTemplateViewModel; @@ -286,7 +276,11 @@ abstract class SendViewModelBase with Store { totalFormattedCryptoAmount += output.formattedCryptoAmount; } - final fee = _wallet.feeEstimate.get(priority: _settingsStore.priority[_wallet.type], amount: totalFormattedCryptoAmount, outputsCount: outputs.length); + final fee = _wallet.feeEstimate.get( + priority: _settingsStore.priority[_wallet.type], + amount: totalFormattedCryptoAmount, + outputsCount: outputs.length, + ); return formatAmountToDouble(type: _wallet.type, amount: fee); } catch (e) {