make Send dialogs return results to force correct usage.
MODIFY
WalletWasabi.Fluent/ViewModels/Wallets/Send/PrivacyControlViewModel.cs
WalletWasabi.Fluent/ViewModels/Wallets/Send/PrivacyControlViewModel.cs
using System;
+using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Reactive;
@@ -8,6 +9,7 @@ using DynamicData;
using DynamicData.Aggregation;
using NBitcoin;
using ReactiveUI;
+using WalletWasabi.Blockchain.TransactionOutputs;
using WalletWasabi.Fluent.Helpers;
using WalletWasabi.Fluent.ViewModels.Dialogs.Base;
using WalletWasabi.Logging;
@@ -16,7 +18,7 @@ using WalletWasabi.Wallets;
namespace WalletWasabi.Fluent.ViewModels.Wallets.Send
{
[NavigationMetaData(Title = "Privacy Control")]
- public partial class PrivacyControlViewModel : DialogViewModelBase<Unit>
+ public partial class PrivacyControlViewModel : DialogViewModelBase<IEnumerable<SmartCoin>>
{
private readonly Wallet _wallet;
private readonly TransactionInfo _transactionInfo;
@@ -69,9 +71,7 @@ namespace WalletWasabi.Fluent.ViewModels.Wallets.Send
private void Complete()
{
- _transactionInfo.Coins = _selectedPockets.Items.SelectMany(x => x.Coins).ToArray();
-
- Close();
+ Close(DialogResultKind.Normal, _selectedPockets.Items.SelectMany(x => x.Coins).ToArray());
}
public ReadOnlyObservableCollection<PocketViewModel> Pockets => _pockets;

MODIFY
WalletWasabi.Fluent/ViewModels/Wallets/Send/SendFeeViewModel.cs
WalletWasabi.Fluent/ViewModels/Wallets/Send/SendFeeViewModel.cs
using System;
using System.Collections.Generic;
-using System.Reactive;
using System.Reactive.Disposables;
using System.Reactive.Linq;
using NBitcoin;
@@ -18,7 +17,7 @@ namespace WalletWasabi.Fluent.ViewModels.Wallets.Send
NavBarPosition = NavBarPosition.None,
Searchable = false,
NavigationTarget = NavigationTarget.DialogScreen)]
- public partial class SendFeeViewModel : DialogViewModelBase<Unit>
+ public partial class SendFeeViewModel : DialogViewModelBase<FeeRate>
{
private readonly Wallet _wallet;
private readonly TransactionInfo _transactionInfo;
@@ -55,9 +54,7 @@ namespace WalletWasabi.Fluent.ViewModels.Wallets.Send
{
var transactionInfo = _transactionInfo;
- transactionInfo.FeeRate = new FeeRate(FeeChart.GetSatoshiPerByte(FeeChart.CurrentConfirmationTarget));
-
- Close();
+ Close(DialogResultKind.Normal, new FeeRate(FeeChart.GetSatoshiPerByte(FeeChart.CurrentConfirmationTarget)));
}
protected override void OnNavigatedTo(bool isInHistory, CompositeDisposable disposables)
@@ -87,7 +84,7 @@ namespace WalletWasabi.Fluent.ViewModels.Wallets.Send
}
else
{
- // TODO What to do?
+ // TODO What to do? Perhaps wait for fee provider to be updated.
}
if (_isSilent)

MODIFY
WalletWasabi.Fluent/ViewModels/Wallets/Send/TransactionPreviewViewModel.cs
WalletWasabi.Fluent/ViewModels/Wallets/Send/TransactionPreviewViewModel.cs
@@ -30,17 +30,19 @@ namespace WalletWasabi.Fluent.ViewModels.Wallets.Send
private BuildTransactionResult? _transaction;
[AutoNotify] private string _confirmationTimeText;
+ [AutoNotify] private string _feeText;
[AutoNotify] private string _nextButtonText;
[AutoNotify] private SmartLabel _labels;
[AutoNotify] private string _amountText;
- [AutoNotify] private string _feeText;
public TransactionPreviewViewModel(Wallet wallet, TransactionInfo info)
{
_wallet = wallet;
_labels = SmartLabel.Empty;
_info = info;
+
SetupCancel(enableCancel: true, enableCancelOnEscape: true, enableCancelOnPressed: false);
+
EnableBack = true;
_confirmationTimeText = "";
@@ -52,6 +54,7 @@ namespace WalletWasabi.Fluent.ViewModels.Wallets.Send
if (PreferPsbtWorkflow)
{
SkipCommand = ReactiveCommand.CreateFromTask(async () => await OnConfirmAsync(_transaction));
+
NextCommand = ReactiveCommand.CreateFromTask(async () =>
{
var saved = await TransactionHelpers.ExportTransactionToBinaryAsync(_transaction);
@@ -61,21 +64,28 @@ namespace WalletWasabi.Fluent.ViewModels.Wallets.Send
Navigate().To(new SuccessViewModel("The PSBT has been successfully created."));
}
});
+
_nextButtonText = "Save PSBT file";
}
else
{
NextCommand = ReactiveCommand.CreateFromTask(async () => await OnConfirmAsync(_transaction));
+
_nextButtonText = "Confirm";
}
AdjustFeeCommand = ReactiveCommand.CreateFromTask(async () =>
{
- await NavigateDialogAsync(new SendFeeViewModel(wallet, info, false));
+ var feeRateDialogResult = await NavigateDialogAsync(new SendFeeViewModel(wallet, info, false));
+
+ if (feeRateDialogResult.Kind == DialogResultKind.Normal)
+ {
+ _info.FeeRate = feeRateDialogResult.Result;
+ }
- // TODO update the preview.
+ await BuildTransactionAsync();
- this.RaisePropertyChanged();
+ UpdatePreview();
});
}
@@ -97,11 +107,24 @@ namespace WalletWasabi.Fluent.ViewModels.Wallets.Send
var totalMixedCoinsAmount = Money.FromUnit(mixedCoins.Sum(coin => coin.Amount), MoneyUnit.Satoshi);
transactionInfo.Coins = mixedCoins;
- await NavigateDialogAsync(new SendFeeViewModel(_wallet, transactionInfo, true));
+ if (transactionInfo.FeeRate is null)
+ {
+ var feeDialogResult = await NavigateDialogAsync(new SendFeeViewModel(_wallet, transactionInfo, true));
- if (transactionInfo.Amount > totalMixedCoinsAmount)
+ if (feeDialogResult.Kind == DialogResultKind.Normal)
{
- await NavigateDialogAsync(new PrivacyControlViewModel(_wallet, transactionInfo));
+ transactionInfo.FeeRate = feeDialogResult.Result;
+ }
+ }
+
+ if (transactionInfo.Amount > totalMixedCoinsAmount && transactionInfo.Coins is null)
+ {
+ var privacyControlDialogResult = await NavigateDialogAsync(new PrivacyControlViewModel(_wallet, transactionInfo));
+
+ if (privacyControlDialogResult.Kind == DialogResultKind.Normal && privacyControlDialogResult.Result is { })
+ {
+ transactionInfo.Coins = privacyControlDialogResult.Result;
+ }
}
try
@@ -119,7 +142,6 @@ namespace WalletWasabi.Fluent.ViewModels.Wallets.Send
{
Logger.LogError(ex);
-
await ShowErrorAsync("Transaction Building", ex.ToUserFriendlyString(),
"Wasabi was unable to create your transaction.");
@@ -127,6 +149,24 @@ namespace WalletWasabi.Fluent.ViewModels.Wallets.Send
}
}
+ private void UpdatePreview()
+ {
+ if (_transaction is { })
+ {
+ var destinationAmount = _transaction.CalculateDestinationAmount().ToDecimal(MoneyUnit.BTC);
+ var btcAmountText = $"{destinationAmount} bitcoins ";
+ var fiatAmountText =
+ destinationAmount.GenerateFiatText(_wallet.Synchronizer.UsdExchangeRate, "USD");
+ AmountText = $"{btcAmountText}{fiatAmountText}";
+
+ var fee = _transaction.Fee;
+ var btcFeeText = $"{fee.ToDecimal(MoneyUnit.Satoshi)} sats ";
+ var fiatFeeText = fee.ToDecimal(MoneyUnit.BTC)
+ .GenerateFiatText(_wallet.Synchronizer.UsdExchangeRate, "USD");
+ FeeText = $"{btcFeeText}{fiatFeeText}";
+ }
+ }
+
protected override void OnNavigatedTo(bool isInHistory, CompositeDisposable disposables)
{
base.OnNavigatedTo(isInHistory, disposables);
@@ -141,21 +181,6 @@ namespace WalletWasabi.Fluent.ViewModels.Wallets.Send
var transaction = await BuildTransactionAsync();
_transaction = transaction;
-
- if (transaction is { })
- {
- var destinationAmount = transaction.CalculateDestinationAmount().ToDecimal(MoneyUnit.BTC);
- var btcAmountText = $"{destinationAmount} bitcoins ";
- var fiatAmountText =
- destinationAmount.GenerateFiatText(_wallet.Synchronizer.UsdExchangeRate, "USD");
- AmountText = $"{btcAmountText}{fiatAmountText}";
-
- var fee = transaction.Fee;
- var btcFeeText = $"{fee.ToDecimal(MoneyUnit.Satoshi)} sats ";
- var fiatFeeText = fee.ToDecimal(MoneyUnit.BTC)
- .GenerateFiatText(_wallet.Synchronizer.UsdExchangeRate, "USD");
- FeeText = $"{btcFeeText}{fiatFeeText}";
- }
});
}
}

make Send dialogs return results to force correct usage.