Skip to content

Commit

Permalink
lots of changes
Browse files Browse the repository at this point in the history
  • Loading branch information
ichthus1604 committed Apr 25, 2024
1 parent 1a57ba4 commit 9cf3b18
Show file tree
Hide file tree
Showing 18 changed files with 190 additions and 114 deletions.
2 changes: 1 addition & 1 deletion WalletWasabi.Fluent/Controls/AmountControl.axaml
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
<ControlTemplate>
<Border Background="{DynamicResource TileRegionColor}"
Padding="10" CornerRadius="10">
<StackPanel Orientation="Horizontal" Spacing="5"
<StackPanel Orientation="Horizontal" Spacing="10"
DataContext="{Binding Path=Amount, RelativeSource={RelativeSource TemplatedParent}}"
IsVisible="{Binding Path=Amount, RelativeSource={RelativeSource TemplatedParent}, Converter={x:Static ObjectConverters.IsNotNull}}">
<TextBlock Classes="monoSpaced" TextWrapping="Wrap"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,15 +33,15 @@ public partial class PrivacySuggestionsModel
private readonly AsyncLock _asyncLock = new();

private readonly CoinJoinManager _cjManager;
private readonly SendParameters _sendParameters;
private readonly SendFlowModel _sendFlow;
private readonly Wallet _wallet;
private CancellationTokenSource? _singleRunCancellationTokenSource;
private CancellationTokenSource? _linkedCancellationTokenSource;

public PrivacySuggestionsModel(SendParameters sendParameters)
public PrivacySuggestionsModel(SendFlowModel sendFlow)
{
_sendParameters = sendParameters;
_wallet = sendParameters.Wallet;
_sendFlow = sendFlow;
_wallet = sendFlow.Wallet;
_cjManager = Services.HostedServices.Get<CoinJoinManager>();
}

Expand Down Expand Up @@ -105,7 +105,7 @@ private IEnumerable<PrivacyItem> VerifyLabels(Parameters parameters)

private PrivacyItem? GetLabelWarning(BuildTransactionResult transactionResult, LabelsArray recipient)
{
var pockets = _sendParameters.GetPockets();
var pockets = _sendFlow.GetPockets();
var spentCoins = transactionResult.SpentCoins;
var nonPrivateSpentCoins = spentCoins.Where(x => x.GetPrivacyLevel(_wallet.AnonScoreTarget) == PrivacyLevel.NonPrivate).ToList();
var usedPockets = pockets.Where(x => x.Coins.Any(coin => nonPrivateSpentCoins.Contains(coin))).ToList();
Expand Down Expand Up @@ -157,7 +157,7 @@ private IEnumerable<PrivacyItem> VerifyPrivacyLevel(Parameters parameters)
yield break;
}

var availableCoins = _sendParameters.AvailableCoins;
var availableCoins = _sendFlow.AvailableCoins;

ImmutableList<SmartCoin> coinsToExclude = _cjManager.CoinsInCriticalPhase[_wallet.WalletId];
bool wasCoinjoiningCoinUsed = parameters.Transaction.SpentCoins.Any(coinsToExclude.Contains);
Expand Down Expand Up @@ -274,7 +274,7 @@ private async Task<List<ChangeAvoidanceSuggestion>> CreateChangeAvoidanceSuggest
// Only allow to create 1 more input with BnB. This accounts for the change created.
int maxInputCount = transaction.SpentCoins.Count() + 1;

var pockets = _sendParameters.GetPockets();
var pockets = _sendFlow.GetPockets();
var spentCoins = transaction.SpentCoins;
var usedPockets = pockets.Where(x => x.Coins.Any(coin => spentCoins.Contains(coin)));
ImmutableArray<SmartCoin> coinsToUse = usedPockets.SelectMany(x => x.Coins).ToImmutableArray();
Expand Down
51 changes: 51 additions & 0 deletions WalletWasabi.Fluent/Models/Transactions/SendFlowModel.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
using NBitcoin;
using ReactiveUI;
using System.Collections.Generic;
using System.Linq;
using WalletWasabi.Blockchain.Analysis.Clustering;
using WalletWasabi.Blockchain.TransactionOutputs;
using WalletWasabi.Fluent.Helpers;
using WalletWasabi.Fluent.Models.Wallets;
using WalletWasabi.Fluent.ViewModels.Wallets.Send;
using WalletWasabi.Wallets;

namespace WalletWasabi.Fluent.Models.Transactions;

public record SendFlowModel
{
private SendFlowModel(Wallet wallet, ICoinsView availableCoins, ICoinListModel coinListModel)
{
Wallet = wallet;
AvailableCoins = availableCoins;
CoinListModel = coinListModel;
}

/// <summary>Regular Send Flow. Uses all wallet coins</summary>
public SendFlowModel(Wallet wallet, IWalletModel walletModel):
this(wallet, wallet.Coins, walletModel.Coins)
{
}

/// <summary>Manual Control Send Flow. Uses only the specified coins.</summary>
public SendFlowModel(Wallet wallet, IWalletModel walletModel, IEnumerable<SmartCoin> coins):
this(wallet, new CoinsView(coins), new UserSelectionCoinListModel(wallet, walletModel, coins.ToArray()))
{
}

public Wallet Wallet { get; }

public ICoinsView AvailableCoins { get; }

public ICoinListModel CoinListModel { get; }

public TransactionInfo? TransactionInfo { get; init; } = null;

public decimal AvailableAmountBtc => AvailableAmount.ToDecimal(MoneyUnit.BTC);

public Money AvailableAmount => AvailableCoins.TotalAmount();

public bool IsManual => AvailableCoins.TotalAmount() != Wallet.Coins.TotalAmount();

public IEnumerable<(LabelsArray Labels, ICoinsView Coins)> GetPockets() => AvailableCoins.GetPockets(Wallet.AnonScoreTarget);

}
27 changes: 0 additions & 27 deletions WalletWasabi.Fluent/Models/Transactions/SendParameters.cs

This file was deleted.

62 changes: 62 additions & 0 deletions WalletWasabi.Fluent/Models/Wallets/CoinListModel.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
using System.Linq;
using System.Reactive.Disposables;
using System.Reactive.Linq;
using DynamicData;
using ReactiveUI;
using WalletWasabi.Blockchain.Analysis.Clustering;
using WalletWasabi.Blockchain.TransactionOutputs;
using WalletWasabi.Fluent.Extensions;
using WalletWasabi.Logging;
using WalletWasabi.Wallets;

namespace WalletWasabi.Fluent.Models.Wallets;

[AutoInterface]
public abstract partial class CoinListModel : IDisposable
{
private readonly CompositeDisposable _disposables = new();

public CoinListModel(Wallet wallet, IWalletModel walletModel)
{
Wallet = wallet;
WalletModel = walletModel;
var transactionProcessed = walletModel.Transactions.TransactionProcessed;
var anonScoreTargetChanged = this.WhenAnyValue(x => x.WalletModel.Settings.AnonScoreTarget).Skip(1).ToSignal();
var isCoinjoinRunningChanged = walletModel.Coinjoin.IsRunning.ToSignal();

var signals =
transactionProcessed
.Merge(anonScoreTargetChanged)
.Merge(isCoinjoinRunningChanged)
.Publish();

List = signals.Fetch(GetCoins, x => x.Key).DisposeWith(_disposables);
Pockets = signals.Fetch(GetPockets, x => x.Labels).DisposeWith(_disposables);

signals
.Do(_ => Logger.LogDebug($"Refresh signal emitted in {walletModel.Name}"))
.Subscribe()
.DisposeWith(_disposables);

signals.Connect()
.DisposeWith(_disposables);
}

protected Wallet Wallet { get; }
protected IWalletModel WalletModel { get; }

public IObservableCache<ICoinModel, int> List { get; }

public IObservableCache<Pocket, LabelsArray> Pockets { get; }

public ICoinModel GetCoinModel(SmartCoin smartCoin)
{
return new CoinModel(smartCoin, WalletModel.Settings.AnonScoreTarget);
}

protected abstract Pocket[] GetPockets();

protected abstract ICoinModel[] GetCoins();

public void Dispose() => _disposables.Dispose();
}
7 changes: 7 additions & 0 deletions WalletWasabi.Fluent/Models/Wallets/IWalletCoinsModel.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
using DynamicData;
using WalletWasabi.Blockchain.Analysis.Clustering;
using WalletWasabi.Blockchain.TransactionOutputs;

namespace WalletWasabi.Fluent.Models.Wallets;

partial interface IWalletCoinsModel: ICoinListModel;
24 changes: 24 additions & 0 deletions WalletWasabi.Fluent/Models/Wallets/UserSelectionCoinListModel.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
using System.Linq;
using System.Reactive.Linq;
using WalletWasabi.Blockchain.TransactionOutputs;
using WalletWasabi.Fluent.Helpers;
using WalletWasabi.Wallets;

namespace WalletWasabi.Fluent.Models.Wallets;

[AutoInterface]
public partial class UserSelectionCoinListModel(Wallet wallet, IWalletModel walletModel, SmartCoin[] selectedCoins) : CoinListModel(wallet, walletModel)
{
protected override ICoinModel[] GetCoins()
{
return selectedCoins.Select(GetCoinModel).ToArray();
}

protected override Pocket[] GetPockets()
{
return
new CoinsView(selectedCoins).GetPockets(WalletModel.Settings.AnonScoreTarget)
.Select(x => new Pocket(x))
.ToArray();
}
}
60 changes: 7 additions & 53 deletions WalletWasabi.Fluent/Models/Wallets/WalletCoinsModel.cs
Original file line number Diff line number Diff line change
@@ -1,82 +1,36 @@
using System.Collections.Generic;
using System.Linq;
using System.Reactive.Disposables;
using System.Reactive.Linq;
using DynamicData;
using ReactiveUI;
using WalletWasabi.Blockchain.Analysis.Clustering;
using WalletWasabi.Blockchain.TransactionBuilding;
using WalletWasabi.Blockchain.TransactionOutputs;
using WalletWasabi.Fluent.Extensions;
using WalletWasabi.Fluent.Helpers;
using WalletWasabi.Fluent.ViewModels.Wallets.Send;
using WalletWasabi.Logging;
using WalletWasabi.Wallets;

namespace WalletWasabi.Fluent.Models.Wallets;

[AutoInterface]
public partial class WalletCoinsModel : IDisposable
public partial class WalletCoinsModel(Wallet wallet, IWalletModel walletModel) : CoinListModel(wallet, walletModel)
{
private readonly Wallet _wallet;
private readonly IWalletModel _walletModel;
private readonly CompositeDisposable _disposables = new();

public WalletCoinsModel(Wallet wallet, IWalletModel walletModel)
{
_wallet = wallet;
_walletModel = walletModel;
var transactionProcessed = walletModel.Transactions.TransactionProcessed;
var anonScoreTargetChanged = this.WhenAnyValue(x => x._walletModel.Settings.AnonScoreTarget).Skip(1).ToSignal();
var isCoinjoinRunningChanged = walletModel.Coinjoin.IsRunning.ToSignal();

var signals =
transactionProcessed
.Merge(anonScoreTargetChanged)
.Merge(isCoinjoinRunningChanged)
.Publish();

List = signals.Fetch(GetCoins, x => x.Key).DisposeWith(_disposables);
Pockets = signals.Fetch(GetPockets, x => x.Labels).DisposeWith(_disposables);

signals
.Do(_ => Logger.LogDebug($"Refresh signal emitted in {walletModel.Name}"))
.Subscribe()
.DisposeWith(_disposables);

signals.Connect()
.DisposeWith(_disposables);
}

public IObservableCache<ICoinModel, int> List { get; }

public IObservableCache<Pocket, LabelsArray> Pockets { get; }

public List<ICoinModel> GetSpentCoins(BuildTransactionResult? transaction)
{
var coins = (transaction?.SpentCoins ?? new List<SmartCoin>()).ToList();
return coins.Select(GetCoinModel).ToList();
}

public ICoinModel GetCoinModel(SmartCoin smartCoin)
{
return new CoinModel(smartCoin, _walletModel.Settings.AnonScoreTarget);
}

public bool AreEnoughToCreateTransaction(TransactionInfo transactionInfo, IEnumerable<ICoinModel> coins)
{
return TransactionHelpers.TryBuildTransactionWithoutPrevTx(_wallet.KeyManager, transactionInfo, _wallet.Coins, coins.GetSmartCoins(), _wallet.Kitchen.SaltSoup(), out _);
return TransactionHelpers.TryBuildTransactionWithoutPrevTx(Wallet.KeyManager, transactionInfo, Wallet.Coins, coins.GetSmartCoins(), Wallet.Kitchen.SaltSoup(), out _);
}

private Pocket[] GetPockets()
protected override Pocket[] GetPockets()
{
return _wallet.GetPockets().ToArray();
return Wallet.GetPockets().ToArray();
}

private ICoinModel[] GetCoins()
protected override ICoinModel[] GetCoins()
{
return _wallet.Coins.Select(GetCoinModel).ToArray();
return Wallet.Coins.Select(GetCoinModel).ToArray();
}

public void Dispose() => _disposables.Dispose();
}

4 changes: 2 additions & 2 deletions WalletWasabi.Fluent/Models/Wallets/WalletModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -122,9 +122,9 @@ public IWalletInfoModel GetWalletInfo()
return new WalletInfoModel(Wallet);
}

public IPrivacySuggestionsModel GetPrivacySuggestionsModel(SendParameters sendParameters)
public IPrivacySuggestionsModel GetPrivacySuggestionsModel(SendFlowModel sendFlow)
{
return new PrivacySuggestionsModel(sendParameters);
return new PrivacySuggestionsModel(sendFlow);
}

public void Rename(string newWalletName)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using DynamicData.Binding;
using ReactiveUI;
using WalletWasabi.Blockchain.TransactionOutputs;
using WalletWasabi.Fluent.Models.Transactions;
using WalletWasabi.Fluent.Models.Wallets;
using WalletWasabi.Fluent.ViewModels.Dialogs.Base;
using WalletWasabi.Fluent.ViewModels.Wallets.Coins;
Expand All @@ -21,8 +22,11 @@ namespace WalletWasabi.Fluent.ViewModels.CoinControl;
NavigationTarget = NavigationTarget.DialogScreen)]
public partial class SelectCoinsDialogViewModel : DialogViewModelBase<IEnumerable<SmartCoin>>
{
public SelectCoinsDialogViewModel(IWalletModel wallet, IList<ICoinModel> selectedCoins, TransactionInfo transactionInfo)
public SelectCoinsDialogViewModel(IWalletModel wallet, IList<ICoinModel> selectedCoins, SendFlowModel sendFlow)
{
var transactionInfo = sendFlow.TransactionInfo ?? throw new InvalidOperationException($"Missing required TransactionInfo.");

// TODO: pass the SendFlow here to show only the relevant coins in the list
CoinList = new CoinListViewModel(wallet, selectedCoins, true);

EnoughSelected = CoinList.Selection.ToObservableChangeSet()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,9 +93,9 @@ private async Task OnSendCoinsAsync()

// TODO: Remove this after TransactionPreviewViewModel is decoupled.
var walletVm = MainViewModel.Instance.NavBar.Wallets.First(x => x.Wallet.WalletName == _wallet.Name).WalletViewModel;

var sendParameters = SendParameters.CreateManual(walletVm.Wallet, selectedSmartCoins);

Navigate().To().TransactionPreview(_wallet, sendParameters);
if (walletVm is null)
{
return;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -55,16 +55,17 @@ private ManualControlDialogViewModel(IWalletModel walletModel, Wallet wallet)

protected override void OnNavigatedFrom(bool isInHistory)
{
CoinList.Dispose();

base.OnNavigatedFrom(isInHistory);
if (!isInHistory)
{
CoinList.Dispose();
}
}

private void OnNext()
{
var coins = CoinList.Selection.GetSmartCoins().ToList();

var sendParameters = SendParameters.CreateManual(_wallet, coins);
var sendParameters = new SendFlowModel(_wallet, _walletModel, coins);

Navigate().To().Send(_walletModel, sendParameters);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ public partial class PrivacySuggestionsFlyoutViewModel : ViewModelBase
[AutoNotify] private bool _goodPrivacy;
[AutoNotify] private bool _maxPrivacy;

public PrivacySuggestionsFlyoutViewModel(IWalletModel wallet, SendParameters sendParameters)
public PrivacySuggestionsFlyoutViewModel(IWalletModel wallet, SendFlowModel sendParameters)
{
_privacySuggestionsModel = wallet.GetPrivacySuggestionsModel(sendParameters);
}
Expand Down
Loading

0 comments on commit 9cf3b18

Please sign in to comment.