mirror of
https://github.com/cake-tech/cake_wallet.git
synced 2025-03-12 09:32:33 +00:00
Merge branch 'cw-62' of https://github.com/cake-tech/cake_wallet into CW-62-send-all-fee-calculation
Conflicts: cw_bitcoin/lib/electrum_wallet.dart cw_monero/ios/Classes/monero_api.cpp cw_monero/lib/api/signatures.dart cw_monero/lib/api/types.dart cw_monero/lib/api/wallet.dart cw_monero/lib/monero_wallet.dart lib/reactions/on_current_wallet_change.dart lib/reactions/on_wallet_sync_status_change.dart lib/src/screens/send/send_page.dart lib/src/screens/send/widgets/send_card.dart lib/view_model/send/output.dart lib/view_model/send/send_view_model.dart
This commit is contained in:
commit
ee08fe77c1
17 changed files with 226 additions and 95 deletions
20
cw_bitcoin/lib/electrum_fee_estimate.dart
Normal file
20
cw_bitcoin/lib/electrum_fee_estimate.dart
Normal file
|
@ -0,0 +1,20 @@
|
|||
import 'package:cw_bitcoin/electrum_wallet.dart';
|
||||
import 'package:cw_core/fee_estimate.dart';
|
||||
import 'package:cw_core/transaction_priority.dart';
|
||||
|
||||
class ElectrumFeeEstimate extends FeeEstimate {
|
||||
ElectrumFeeEstimate(ElectrumWalletBase wallet)
|
||||
: _wallet = wallet;
|
||||
|
||||
ElectrumWalletBase _wallet;
|
||||
|
||||
int get({TransactionPriority priority, int amount, int outputsCount}) {
|
||||
// Electrum doesn't require an async call to obtain the estimated fee.
|
||||
// We don't bother caching and just obtain it directly.
|
||||
return _wallet.calculateEstimatedFee(priority,amount, outputsCount: outputsCount);
|
||||
}
|
||||
|
||||
void update({TransactionPriority priority, int amount, int outputsCount}) {}
|
||||
|
||||
void set({TransactionPriority priority, int outputsCount, int fee}) {}
|
||||
}
|
|
@ -2,6 +2,7 @@ import 'dart:async';
|
|||
import 'dart:convert';
|
||||
import 'dart:math';
|
||||
import 'dart:typed_data';
|
||||
import 'package:cw_core/fee_estimate.dart';
|
||||
import 'package:cw_core/unspent_coins_info.dart';
|
||||
import 'package:hive/hive.dart';
|
||||
import 'package:cw_bitcoin/electrum_wallet_addresses.dart';
|
||||
|
@ -34,6 +35,7 @@ import 'package:cw_core/wallet_info.dart';
|
|||
import 'package:cw_bitcoin/electrum.dart';
|
||||
import 'package:hex/hex.dart';
|
||||
import 'package:cw_core/crypto_currency.dart';
|
||||
import 'package:cw_bitcoin/electrum_fee_estimate.dart';
|
||||
|
||||
part 'electrum_wallet.g.dart';
|
||||
|
||||
|
@ -67,6 +69,7 @@ abstract class ElectrumWalletBase extends WalletBase<ElectrumBalance,
|
|||
ElectrumTransactionHistory(walletInfo: walletInfo, password: password);
|
||||
unspentCoins = [];
|
||||
_scripthashesUpdateSubject = {};
|
||||
feeEstimate = ElectrumFeeEstimate(this);
|
||||
}
|
||||
|
||||
static int estimatedTransactionSize(int inputsCount, int outputsCounts) =>
|
||||
|
@ -89,6 +92,10 @@ abstract class ElectrumWalletBase extends WalletBase<ElectrumBalance,
|
|||
@observable
|
||||
SyncStatus syncStatus;
|
||||
|
||||
@override
|
||||
@observable
|
||||
ElectrumFeeEstimate feeEstimate;
|
||||
|
||||
List<String> get scriptHashes => walletAddresses.addresses
|
||||
.map((addr) => scriptHash(addr.address, networkType: networkType))
|
||||
.toList();
|
||||
|
@ -314,7 +321,7 @@ abstract class ElectrumWalletBase extends WalletBase<ElectrumBalance,
|
|||
} else {
|
||||
feeAmount = feeRate(transactionCredentials.priority) * estimatedSize;
|
||||
}
|
||||
|
||||
|
||||
final changeValue = totalInputAmount - amount - feeAmount;
|
||||
|
||||
if (changeValue > minAmount) {
|
||||
|
@ -369,8 +376,7 @@ abstract class ElectrumWalletBase extends WalletBase<ElectrumBalance,
|
|||
feeRate * estimatedTransactionSize(inputsCount, outputsCount);
|
||||
|
||||
@override
|
||||
int calculateEstimatedFee(TransactionPriority priority, int amount,
|
||||
{int outputsCount}) {
|
||||
int calculateEstimatedFee(TransactionPriority priority, int amount, {int outputsCount = 1}) {
|
||||
if (priority is BitcoinTransactionPriority) {
|
||||
return calculateEstimatedFeeWithFeeRate(
|
||||
feeRate(priority),
|
||||
|
|
10
cw_core/lib/fee_estimate.dart
Normal file
10
cw_core/lib/fee_estimate.dart
Normal file
|
@ -0,0 +1,10 @@
|
|||
import 'package:cw_core/transaction_priority.dart';
|
||||
|
||||
abstract class FeeEstimate
|
||||
{
|
||||
void update({TransactionPriority priority, int outputsCount});
|
||||
|
||||
int get({TransactionPriority priority, int amount, int outputsCount});
|
||||
|
||||
void set({TransactionPriority priority, int outputsCount, int fee});
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
import 'package:mobx/mobx.dart';
|
||||
import 'package:cw_core/balance.dart';
|
||||
import 'package:cw_core/fee_estimate.dart';
|
||||
import 'package:cw_core/transaction_info.dart';
|
||||
import 'package:cw_core/transaction_priority.dart';
|
||||
import 'package:cw_core/wallet_addresses.dart';
|
||||
|
@ -40,6 +41,8 @@ abstract class WalletBase<
|
|||
|
||||
SyncStatus get syncStatus;
|
||||
|
||||
FeeEstimate get feeEstimate;
|
||||
|
||||
set syncStatus(SyncStatus status);
|
||||
|
||||
String get seed;
|
||||
|
@ -56,8 +59,6 @@ abstract class WalletBase<
|
|||
|
||||
Future<PendingTransaction> createTransaction(Object credentials);
|
||||
|
||||
int calculateEstimatedFee(TransactionPriority priority, int amount);
|
||||
|
||||
// void fetchTransactionsAsync(
|
||||
// void Function(TransactionType transaction) onTransactionLoaded,
|
||||
// {void Function() onFinished});
|
||||
|
|
|
@ -783,6 +783,25 @@ extern "C"
|
|||
return strdup(get_current_wallet()->getSubaddressLabel(accountIndex, addressIndex).c_str());
|
||||
}
|
||||
|
||||
uint64_t estimate_transaction_fee(int outputs, uint8_t priority_raw)
|
||||
{
|
||||
// estimateTransactionFee only cares about the number of outputs
|
||||
std::vector<std::pair<std::string, uint64_t>> destinations;
|
||||
for (int i = 0; i < outputs; i++) {
|
||||
destinations.push_back({"", 0});
|
||||
}
|
||||
auto priority = static_cast<Monero::PendingTransaction::Priority>(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
|
||||
|
|
|
@ -125,4 +125,8 @@ typedef rescan_blockchain = Void Function();
|
|||
|
||||
typedef get_subaddress_label = Pointer<Utf8> Function(
|
||||
Int32 accountIndex,
|
||||
Int32 addressIndex);
|
||||
Int32 addressIndex);
|
||||
|
||||
typedef estimate_transaction_fee = Int64 Function(
|
||||
Int32 outputs,
|
||||
Int8 priorityRaw);
|
|
@ -123,4 +123,6 @@ typedef RescanBlockchainAsync = void Function();
|
|||
|
||||
typedef GetSubaddressLabel = Pointer<Utf8> Function(
|
||||
int accountIndex,
|
||||
int addressIndex);
|
||||
int addressIndex);
|
||||
|
||||
typedef EstimateTransactionFee = int Function(int, int);
|
||||
|
|
|
@ -120,6 +120,10 @@ final getSubaddressLabelNative = moneroApi
|
|||
.lookup<NativeFunction<get_subaddress_label>>('get_subaddress_label')
|
||||
.asFunction<GetSubaddressLabel>();
|
||||
|
||||
final estimateTransactionFeeNative = moneroApi
|
||||
.lookup<NativeFunction<estimate_transaction_fee>>('estimate_transaction_fee')
|
||||
.asFunction<EstimateTransactionFee>();
|
||||
|
||||
int getSyncingHeight() => getSyncingHeightNative();
|
||||
|
||||
bool isNeededToRefresh() => isNeededToRefreshNative() != 0;
|
||||
|
@ -206,7 +210,7 @@ void setPasswordSync(String password) {
|
|||
final errorMessagePointer = allocate<Utf8Box>();
|
||||
final changed = setPasswordNative(passwordPointer, errorMessagePointer) != 0;
|
||||
free(passwordPointer);
|
||||
|
||||
|
||||
if (!changed) {
|
||||
final message = errorMessagePointer.ref.getValue();
|
||||
free(errorMessagePointer);
|
||||
|
@ -353,4 +357,19 @@ void rescanBlockchainAsync() => rescanBlockchainAsyncNative();
|
|||
|
||||
String getSubaddressLabel(int accountIndex, int addressIndex) {
|
||||
return convertUTF8ToString(pointer: getSubaddressLabelNative(accountIndex, addressIndex));
|
||||
}
|
||||
|
||||
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<int> estimateTransactionFee({int priorityRaw, int outputsCount}) {
|
||||
return compute(_estimateTransactionFee, {'priorityRaw': priorityRaw, 'outputsCount': outputsCount});
|
||||
}
|
38
cw_monero/lib/monero_fee_estimate.dart
Normal file
38
cw_monero/lib/monero_fee_estimate.dart
Normal file
|
@ -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_monero/api/wallet.dart' as monero_wallet;
|
||||
|
||||
part 'monero_fee_estimate.g.dart';
|
||||
|
||||
class MoneroFeeEstimate = _MoneroFeeEstimate with _$MoneroFeeEstimate;
|
||||
|
||||
abstract class _MoneroFeeEstimate extends FeeEstimate with Store {
|
||||
_MoneroFeeEstimate()
|
||||
: _estimatedFee = new ObservableMap<String, int>();
|
||||
|
||||
@observable
|
||||
ObservableMap<String, int> _estimatedFee;
|
||||
|
||||
@override
|
||||
void update({TransactionPriority priority, int outputsCount}) {
|
||||
Future(() async {
|
||||
final fee = await monero_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";
|
||||
}
|
||||
}
|
|
@ -16,8 +16,9 @@ import 'package:cw_monero/api/transaction_history.dart' as transaction_history;
|
|||
import 'package:cw_monero/api/monero_output.dart';
|
||||
import 'package:cw_monero/monero_transaction_creation_credentials.dart';
|
||||
import 'package:cw_monero/pending_monero_transaction.dart';
|
||||
import 'package:cw_core/monero_wallet_keys.dart';
|
||||
import 'package:cw_core/monero_balance.dart';
|
||||
import 'package:cw_monero/monero_wallet_keys.dart';
|
||||
import 'package:cw_monero/monero_balance.dart';
|
||||
import 'package:cw_monero/monero_fee_estimate.dart';
|
||||
import 'package:cw_monero/monero_transaction_history.dart';
|
||||
import 'package:cw_core/account.dart';
|
||||
import 'package:cw_core/pending_transaction.dart';
|
||||
|
@ -58,6 +59,7 @@ abstract class MoneroWalletBase extends WalletBase<MoneroBalance,
|
|||
});
|
||||
walletAddresses.updateSubaddressList(accountIndex: account.id);
|
||||
});
|
||||
feeEstimate = MoneroFeeEstimate();
|
||||
}
|
||||
|
||||
static const int _autoSaveInterval = 30;
|
||||
|
@ -73,6 +75,9 @@ abstract class MoneroWalletBase extends WalletBase<MoneroBalance,
|
|||
@observable
|
||||
ObservableMap<CryptoCurrency, MoneroBalance> balance;
|
||||
|
||||
@override
|
||||
MoneroFeeEstimate feeEstimate;
|
||||
|
||||
@override
|
||||
String get seed => monero_wallet.getSeed();
|
||||
|
||||
|
@ -229,28 +234,6 @@ abstract class MoneroWalletBase extends WalletBase<MoneroBalance,
|
|||
return PendingMoneroTransaction(pendingTransactionDescription);
|
||||
}
|
||||
|
||||
@override
|
||||
int calculateEstimatedFee(TransactionPriority priority, int amount) {
|
||||
// FIXME: hardcoded value;
|
||||
|
||||
if (priority is MoneroTransactionPriority) {
|
||||
switch (priority) {
|
||||
case MoneroTransactionPriority.slow:
|
||||
return 24590000;
|
||||
case MoneroTransactionPriority.regular:
|
||||
return 123050000;
|
||||
case MoneroTransactionPriority.medium:
|
||||
return 245029999;
|
||||
case MoneroTransactionPriority.fast:
|
||||
return 614530000;
|
||||
case MoneroTransactionPriority.fastest:
|
||||
return 26021600000;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> save() async {
|
||||
await walletAddresses.updateAddressesInBox();
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
import 'package:cake_wallet/bitcoin/bitcoin.dart';
|
||||
import 'package:cake_wallet/monero/monero.dart';
|
||||
import 'package:cw_core/wallet_type.dart';
|
||||
|
||||
String formatAmount(String amount) {
|
||||
if ((!amount.contains('.'))&&(!amount.contains(','))) {
|
||||
return amount + '.00';
|
||||
|
@ -5,4 +9,16 @@ String formatAmount(String amount) {
|
|||
return amount + '00';
|
||||
}
|
||||
return amount;
|
||||
}
|
||||
|
||||
double formatAmountToDouble({WalletType type, int amount}) {
|
||||
if (type == WalletType.bitcoin || type == WalletType.litecoin) {
|
||||
return bitcoin.formatterBitcoinAmountToDouble(amount: amount);
|
||||
}
|
||||
|
||||
if (type == WalletType.monero) {
|
||||
return monero.formatterMoneroAmountToDouble(amount: amount);
|
||||
}
|
||||
|
||||
return 0.0;
|
||||
}
|
|
@ -1,8 +1,11 @@
|
|||
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';
|
||||
|
@ -13,10 +16,8 @@ import 'package:flutter/services.dart';
|
|||
|
||||
ReactionDisposer _onWalletSyncStatusChangeReaction;
|
||||
|
||||
void startWalletSyncStatusChangeReaction(
|
||||
WalletBase<Balance, TransactionHistoryBase<TransactionInfo>,
|
||||
TransactionInfo> wallet,
|
||||
FiatConversionStore fiatConversionStore) {
|
||||
void startWalletSyncStatusChangeReaction(WalletBase<Balance, TransactionHistoryBase<TransactionInfo>, TransactionInfo> wallet,
|
||||
FiatConversionStore fiatConversionStore, SettingsStore settingsStore) {
|
||||
final _wakeLock = getIt.get<WakeLock>();
|
||||
_onWalletSyncStatusChangeReaction?.reaction?.dispose();
|
||||
_onWalletSyncStatusChangeReaction =
|
||||
|
@ -34,5 +35,9 @@ void startWalletSyncStatusChangeReaction(
|
|||
if (status is SyncedSyncStatus || status is FailedSyncStatus) {
|
||||
await _wakeLock.disableWake();
|
||||
}
|
||||
|
||||
if (status is SyncedSyncStatus) {
|
||||
wallet.feeEstimate.update(priority: settingsStore.priority[wallet.type], outputsCount: 1);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -296,6 +296,7 @@ class SendPage extends BasePage {
|
|||
child: PrimaryButton(
|
||||
onPressed: () {
|
||||
sendViewModel.addOutput();
|
||||
sendViewModel.estimateFee();
|
||||
Future.delayed(const Duration(milliseconds: 250), () {
|
||||
controller.jumpToPage(sendViewModel.outputs.length - 1);
|
||||
});
|
||||
|
@ -333,7 +334,7 @@ class SendPage extends BasePage {
|
|||
showErrorValidationAlert(context);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
await sendViewModel.createTransaction();
|
||||
|
||||
},
|
||||
|
|
|
@ -424,12 +424,7 @@ class SendCardState extends State<SendCard>
|
|||
crossAxisAlignment: CrossAxisAlignment.end,
|
||||
children: [
|
||||
Text(
|
||||
output
|
||||
.estimatedFee
|
||||
.toString() +
|
||||
' ' +
|
||||
sendViewModel
|
||||
.selectedCryptoCurrency.toString(),
|
||||
sendViewModel.estimatedFee.toString() + ' ' + sendViewModel.currency.title,
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
fontWeight:
|
||||
|
@ -441,11 +436,7 @@ class SendCardState extends State<SendCard>
|
|||
padding:
|
||||
EdgeInsets.only(top: 5),
|
||||
child: Text(
|
||||
output
|
||||
.estimatedFeeFiatAmount
|
||||
+ ' ' +
|
||||
sendViewModel
|
||||
.fiat.title,
|
||||
sendViewModel.estimatedFeeFiatAmount + ' ' + sendViewModel.fiat.title,
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
fontWeight:
|
||||
|
@ -551,18 +542,25 @@ class SendCardState extends State<SendCard>
|
|||
}
|
||||
});
|
||||
|
||||
reaction((_) => sendViewModel.estimatedFee, (double estimatedFee) {
|
||||
final firstOutput = sendViewModel.outputs[0];
|
||||
if (firstOutput != null && firstOutput.sendAll) {
|
||||
firstOutput.updateFiatAmount();
|
||||
}
|
||||
});
|
||||
|
||||
reaction((_) => output.sendAll, (bool all) {
|
||||
if (all) {
|
||||
cryptoAmountController.text = S.current.all;
|
||||
fiatAmountController.text = null;
|
||||
}
|
||||
});
|
||||
|
||||
reaction((_) => output.fiatAmount, (String amount) {
|
||||
if (amount != fiatAmountController.text) {
|
||||
final doubleAmount = double.tryParse(amount) ?? 0;
|
||||
final doubleFee = double.tryParse(sendViewModel.estimatedFiatFee(sendViewModel.balance)) ?? 0;
|
||||
fiatAmountController.text = doubleAmount - doubleFee > 0 ? "${doubleAmount - doubleFee}" : "0.00";
|
||||
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";
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -360,7 +360,7 @@ abstract class ExchangeViewModelBase with Store {
|
|||
if (wallet.type == WalletType.bitcoin) {
|
||||
final availableBalance = wallet.balance[wallet.currency].available;
|
||||
final priority = _settingsStore.priority[wallet.type];
|
||||
final fee = wallet.calculateEstimatedFee(priority, null);
|
||||
final fee = wallet.feeEstimate.get(priority: priority);
|
||||
|
||||
if (availableBalance < fee || availableBalance == 0) {
|
||||
return;
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import 'dart:math';
|
||||
import 'package:cake_wallet/di.dart';
|
||||
import 'package:cake_wallet/entities/calculate_fiat_amount_raw.dart';
|
||||
import 'package:cake_wallet/entities/format_amount.dart';
|
||||
import 'package:cake_wallet/entities/parse_address_from_domain.dart';
|
||||
import 'package:cake_wallet/entities/parsed_address.dart';
|
||||
import 'package:cake_wallet/haven/haven.dart';
|
||||
|
@ -97,43 +98,6 @@ abstract class OutputBase with Store {
|
|||
return amount;
|
||||
}
|
||||
|
||||
@computed
|
||||
double get estimatedFee {
|
||||
try {
|
||||
final fee = _wallet.calculateEstimatedFee(
|
||||
_settingsStore.priority[_wallet.type], formattedCryptoAmount);
|
||||
|
||||
if (_wallet.type == WalletType.bitcoin ||
|
||||
_wallet.type == WalletType.litecoin) {
|
||||
return bitcoin.formatterBitcoinAmountToDouble(amount: fee);
|
||||
}
|
||||
|
||||
if (_wallet.type == WalletType.monero) {
|
||||
return monero.formatterMoneroAmountToDouble(amount: fee);
|
||||
}
|
||||
|
||||
if (_wallet.type == WalletType.haven) {
|
||||
return haven.formatterMoneroAmountToDouble(amount: fee);
|
||||
}
|
||||
} catch (e) {
|
||||
print(e.toString());
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@computed
|
||||
String get estimatedFeeFiatAmount {
|
||||
try {
|
||||
final fiat = calculateFiatAmountRaw(
|
||||
price: _fiatConversationStore.prices[cryptoCurrencyHandler()],
|
||||
cryptoAmount: estimatedFee);
|
||||
return fiat;
|
||||
} catch (_) {
|
||||
return '0.00';
|
||||
}
|
||||
}
|
||||
|
||||
WalletType get walletType => _wallet.type;
|
||||
final CryptoCurrency Function() cryptoCurrencyHandler;
|
||||
final WalletBase _wallet;
|
||||
|
@ -166,7 +130,7 @@ abstract class OutputBase with Store {
|
|||
}
|
||||
|
||||
cryptoAmount = amount;
|
||||
_updateFiatAmount();
|
||||
updateFiatAmount();
|
||||
}
|
||||
|
||||
@action
|
||||
|
@ -176,11 +140,11 @@ abstract class OutputBase with Store {
|
|||
}
|
||||
|
||||
@action
|
||||
void _updateFiatAmount() {
|
||||
void updateFiatAmount() {
|
||||
try {
|
||||
final fiat = calculateFiatAmount(
|
||||
price: _fiatConversationStore.prices[cryptoCurrencyHandler()],
|
||||
cryptoAmount: cryptoAmount.replaceAll(',', '.'));
|
||||
price: _fiatConversationStore.prices[_wallet.currency],
|
||||
cryptoAmount: (cryptoAmount.toUpperCase() == S.current.all) ? _cryptoNumberFormat.format(formatAmountToDouble(type: _wallet.type, amount: _estimateAmountAll())) : cryptoAmount.replaceAll(',', '.'));
|
||||
if (fiatAmount != fiat) {
|
||||
fiatAmount = fiat;
|
||||
}
|
||||
|
@ -227,6 +191,11 @@ abstract class OutputBase with Store {
|
|||
_cryptoNumberFormat.maximumFractionDigits = maximumFractionDigits;
|
||||
}
|
||||
|
||||
int _estimateAmountAll() {
|
||||
final fee = _wallet.feeEstimate.get(priority: _settingsStore.priority[_wallet.type], outputsCount: 1);
|
||||
return max(0, _wallet.balance.available - fee);
|
||||
}
|
||||
|
||||
Future<void> fetchParsedAddress(BuildContext context) async {
|
||||
final domain = address;
|
||||
final ticker = cryptoCurrencyHandler().title.toLowerCase();
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
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';
|
||||
import 'package:cw_core/transaction_priority.dart';
|
||||
|
@ -27,6 +28,7 @@ import 'package:cake_wallet/view_model/send/send_view_model_state.dart';
|
|||
import 'package:cake_wallet/entities/parsed_address.dart';
|
||||
import 'package:cake_wallet/bitcoin/bitcoin.dart';
|
||||
import 'package:cake_wallet/haven/haven.dart';
|
||||
import 'package:cake_wallet/entities/calculate_fiat_amount_raw.dart';
|
||||
|
||||
part 'send_view_model.g.dart';
|
||||
|
||||
|
@ -52,6 +54,10 @@ abstract class SendViewModelBase with Store {
|
|||
|
||||
outputs = ObservableList<Output>()
|
||||
..add(Output(_wallet, _settingsStore, _fiatConversationStore, () => selectedCryptoCurrency));
|
||||
|
||||
_settingsStore.priority.observe((change) async {
|
||||
_wallet.feeEstimate.update(priority: change.newValue, outputsCount: outputs.length);
|
||||
});
|
||||
}
|
||||
|
||||
@observable
|
||||
|
@ -267,4 +273,38 @@ abstract class SendViewModelBase with Store {
|
|||
|
||||
bool _isEqualCurrency(String currency) =>
|
||||
currency.toLowerCase() == _wallet.currency.title.toLowerCase();
|
||||
|
||||
void estimateFee() {
|
||||
_wallet.feeEstimate.update(priority: _settingsStore.priority[_wallet.type], outputsCount: outputs.length);
|
||||
}
|
||||
|
||||
@computed
|
||||
double get estimatedFee {
|
||||
try {
|
||||
var totalFormattedCryptoAmount = 0;
|
||||
for (final output in outputs) {
|
||||
totalFormattedCryptoAmount += output.formattedCryptoAmount;
|
||||
}
|
||||
|
||||
final fee = _wallet.feeEstimate.get(priority: _settingsStore.priority[_wallet.type], amount: totalFormattedCryptoAmount, outputsCount: outputs.length);
|
||||
|
||||
return formatAmountToDouble(type: _wallet.type, amount: fee);
|
||||
} catch (e) {
|
||||
print(e.toString());
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@computed
|
||||
String get estimatedFeeFiatAmount {
|
||||
try {
|
||||
final fiat = calculateFiatAmountRaw(
|
||||
price: _fiatConversationStore.prices[_wallet.currency],
|
||||
cryptoAmount: this.estimatedFee);
|
||||
return fiat;
|
||||
} catch (_) {
|
||||
return '0.00';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue