refactor CJ group logic
DELETE
WalletWasabi.Fluent/ViewModels/Wallets/Home/History/HistoryItems/CoinJoinHistoryItemViewModel.cs
-using System;
-using NBitcoin;
-using ReactiveUI;
-using WalletWasabi.Blockchain.Transactions;
-using WalletWasabi.Fluent.ViewModels.Navigation;
-
-namespace WalletWasabi.Fluent.ViewModels.Wallets.Home.History.HistoryItems
-{
- public class CoinJoinHistoryItemViewModel : HistoryItemViewModelBase
- {
- public CoinJoinHistoryItemViewModel(
- int orderIndex,
- TransactionSummary transactionSummary,
- WalletViewModel walletViewModel,
- Money balance,
- DateTimeOffset lastCjDateInGroup)
- : base(orderIndex, transactionSummary, balance)
- {
- LastCjDateInGroup = lastCjDateInGroup;
- OutgoingAmount = transactionSummary.Amount * -1;
- IsCoinJoin = true;
-
- ShowDetailsCommand = ReactiveCommand.Create(() =>
- RoutableViewModel.Navigate(NavigationTarget.DialogScreen).To(new CoinJoinDetailsViewModel()));
-
- UpdateDateString();
- }
-
- public DateTimeOffset LastCjDateInGroup { get; private set; }
-
- public override void Update(HistoryItemViewModelBase item)
- {
- if (item is not CoinJoinHistoryItemViewModel coinJoinHistoryItemViewModel)
- {
- throw new InvalidOperationException("Not the same type!");
- }
-
- LastCjDateInGroup = coinJoinHistoryItemViewModel.LastCjDateInGroup;
-
- base.Update(item);
- }
-
- protected sealed override void UpdateDateString()
- {
- DateString = Date.Day == LastCjDateInGroup.Day
- ? $"{Date.ToLocalTime():MM/dd/yyyy}"
- : $"{Date.ToLocalTime():MM/dd/yy} - {LastCjDateInGroup.ToLocalTime():MM/dd/yy}";
- }
- }
-}

ADD
WalletWasabi.Fluent/ViewModels/Wallets/Home/History/HistoryItems/CoinJoinsHistoryItemViewModel.cs
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using NBitcoin;
+using ReactiveUI;
+using WalletWasabi.Blockchain.Transactions;
+using WalletWasabi.Fluent.Extensions;
+using WalletWasabi.Fluent.ViewModels.Navigation;
+
+namespace WalletWasabi.Fluent.ViewModels.Wallets.Home.History.HistoryItems
+{
+ public class CoinJoinsHistoryItemViewModel : HistoryItemViewModelBase
+ {
+ private List<TransactionSummary> _transactions;
+
+ public CoinJoinsHistoryItemViewModel(int orderIndex, TransactionSummary firstItem)
+ : base(orderIndex, firstItem)
+ {
+ _transactions = new List<TransactionSummary>( );
+ Label = new List<string> { "Privacy Increasement" };
+ FilteredLabel = new List<string>();
+ IsCoinJoin = true;
+
+ ShowDetailsCommand = ReactiveCommand.Create(() =>
+ RoutableViewModel.Navigate(NavigationTarget.DialogScreen).To(new CoinJoinDetailsViewModel()));
+
+ Add(firstItem);
+ }
+
+ public void Add(TransactionSummary item)
+ {
+ _transactions.Add(item);
+
+ IsConfirmed = _transactions.All(x => x.IsConfirmed());
+ Date = _transactions.Last().DateTime.ToLocalTime();
+ UpdateAmount();
+ UpdateDateString();
+ }
+
+ public override void Update(HistoryItemViewModelBase item)
+ {
+ if (item is not CoinJoinsHistoryItemViewModel coinJoinHistoryItemViewModel)
+ {
+ throw new InvalidOperationException("Not the same type!");
+ }
+
+ _transactions = coinJoinHistoryItemViewModel._transactions;
+ UpdateAmount();
+
+ base.Update(item);
+ }
+
+ protected void UpdateDateString()
+ {
+ var firstDate = _transactions.First().DateTime.ToLocalTime();
+ var lastDate = _transactions.Last().DateTime.ToLocalTime();
+
+ DateString = firstDate.Day == lastDate.Day
+ ? $"{firstDate:MM/dd/yyyy}"
+ : $"{firstDate:MM/dd/yy} - {lastDate:MM/dd/yy}";
+ }
+
+ private void UpdateAmount()
+ {
+ OutgoingAmount = _transactions.Sum(x => x.Amount) * -1;
+ }
+
+ public void SetBalance(Money balance)
+ {
+ Balance = balance;
+ }
+ }
+}

MODIFY
WalletWasabi.Fluent/ViewModels/Wallets/Home/History/HistoryItems/HistoryItemViewModelBase.cs
WalletWasabi.Fluent/ViewModels/Wallets/Home/History/HistoryItems/HistoryItemViewModelBase.cs
using System;
using System.Collections.Generic;
-using System.Linq;
using System.Reactive.Linq;
using System.Threading.Tasks;
using System.Windows.Input;
using NBitcoin;
using ReactiveUI;
using WalletWasabi.Blockchain.Transactions;
-using WalletWasabi.Fluent.Extensions;
namespace WalletWasabi.Fluent.ViewModels.Wallets.Home.History.HistoryItems
{
@@ -19,15 +17,10 @@ namespace WalletWasabi.Fluent.ViewModels.Wallets.Home.History.HistoryItems
[AutoNotify] private string? _dateString;
[AutoNotify] private bool _isConfirmed;
- protected HistoryItemViewModelBase(int orderIndex, TransactionSummary transactionSummary, Money balance)
+ protected HistoryItemViewModelBase(int orderIndex, TransactionSummary transactionSummary)
{
- TransactionSummary = transactionSummary;
- Date = transactionSummary.DateTime.ToLocalTime();
OrderIndex = orderIndex;
- Balance = balance;
- IsConfirmed = transactionSummary.IsConfirmed();
- Label = transactionSummary.Label.Take(1).ToList();
- FilteredLabel = transactionSummary.Label.Skip(1).ToList();
+ Id = transactionSummary.TransactionId;
this.WhenAnyValue(x => x.IsFlashing)
.Where(x => x)
@@ -38,17 +31,15 @@ namespace WalletWasabi.Fluent.ViewModels.Wallets.Home.History.HistoryItems
});
}
- public uint256 TransactionId => TransactionSummary.TransactionId;
+ public uint256 Id { get; }
- public List<string> FilteredLabel { get; protected set; }
+ public List<string>? FilteredLabel { get; protected set; }
- public List<string> Label { get; protected set; }
+ public List<string>? Label { get; protected set; }
public bool IsCoinJoin { get; protected set; }
- public TransactionSummary TransactionSummary { get; }
-
- public Money Balance { get; set; }
+ public Money? Balance { get; protected set; }
public Money? OutgoingAmount { get; protected set; }
@@ -60,9 +51,10 @@ namespace WalletWasabi.Fluent.ViewModels.Wallets.Home.History.HistoryItems
{
OrderIndex = item.OrderIndex;
Date = item.Date;
+ DateString = item.DateString;
IsConfirmed = item.IsConfirmed;
}
- protected abstract void UpdateDateString();
+ public bool IsSimilar(HistoryItemViewModelBase item) => Id == item.Id;
}
}

MODIFY
WalletWasabi.Fluent/ViewModels/Wallets/Home/History/HistoryItems/TransactionHistoryItemViewModel.cs
WalletWasabi.Fluent/ViewModels/Wallets/Home/History/HistoryItems/TransactionHistoryItemViewModel.cs
using System;
+using System.Linq;
using System.Reactive;
using NBitcoin;
using ReactiveUI;
using WalletWasabi.Blockchain.Transactions;
+using WalletWasabi.Fluent.Extensions;
using WalletWasabi.Fluent.ViewModels.Navigation;
namespace WalletWasabi.Fluent.ViewModels.Wallets.Home.History.HistoryItems
{
public class TransactionHistoryItemViewModel : HistoryItemViewModelBase
{
- public TransactionHistoryItemViewModel(int orderIndex, TransactionSummary transactionSummary, WalletViewModel walletViewModel, Money balance, IObservable<Unit> updateTrigger)
- : base(orderIndex, transactionSummary, balance)
+ public TransactionHistoryItemViewModel(
+ int orderIndex,
+ TransactionSummary transactionSummary,
+ WalletViewModel walletViewModel,
+ Money balance,
+ IObservable<Unit> updateTrigger)
+ : base(orderIndex, transactionSummary)
{
+ Label = transactionSummary.Label.Take(1).ToList();
+ FilteredLabel = transactionSummary.Label.Skip(1).ToList();
+ IsConfirmed = transactionSummary.IsConfirmed();
+ Date = transactionSummary.DateTime.ToLocalTime();
+ Balance = balance;
+
var amount = transactionSummary.Amount;
if (amount < Money.Zero)
{
@@ -26,11 +39,6 @@ namespace WalletWasabi.Fluent.ViewModels.Wallets.Home.History.HistoryItems
RoutableViewModel.Navigate(NavigationTarget.DialogScreen).To(
new TransactionDetailsViewModel(transactionSummary, walletViewModel.Wallet, updateTrigger)));
- UpdateDateString();
- }
-
- protected sealed override void UpdateDateString()
- {
DateString = $"{Date.ToLocalTime():MM/dd/yyyy HH:mm}";
}
}

MODIFY
WalletWasabi.Fluent/ViewModels/Wallets/Home/History/HistoryViewModel.cs
WalletWasabi.Fluent/ViewModels/Wallets/Home/History/HistoryViewModel.cs
@@ -64,7 +64,7 @@ namespace WalletWasabi.Fluent.ViewModels.Wallets.Home.History
public void SelectTransaction(uint256 txid)
{
- var txnItem = Transactions.FirstOrDefault(x => x.TransactionSummary.TransactionId == txid);
+ var txnItem = Transactions.FirstOrDefault(x => x.Id == txid);
if (txnItem is { })
{
@@ -96,7 +96,7 @@ namespace WalletWasabi.Fluent.ViewModels.Wallets.Home.History
foreach (var oldItem in copyList)
{
- if (newTransactionsList.All(x => x.TransactionId != oldItem.TransactionId))
+ if (newTransactionsList.All(x => x.Id != oldItem.Id))
{
_transactionSourceList.Remove(oldItem);
}
@@ -104,7 +104,7 @@ namespace WalletWasabi.Fluent.ViewModels.Wallets.Home.History
foreach (var newItem in newTransactionsList)
{
- if (_transactions.FirstOrDefault(x => x.TransactionId == newItem.TransactionId) is { } item)
+ if (_transactions.FirstOrDefault(x => x.Id == newItem.Id) is { } item)
{
item.Update(newItem);
}
@@ -129,6 +129,7 @@ namespace WalletWasabi.Fluent.ViewModels.Wallets.Home.History
private IEnumerable<HistoryItemViewModelBase> GetHistoryList(List<TransactionSummary> txRecordList)
{
Money balance = Money.Zero;
+ CoinJoinsHistoryItemViewModel? coinJoinGroup = default;
for (var i = 0; i < txRecordList.Count; i++)
{
@@ -138,33 +139,29 @@ namespace WalletWasabi.Fluent.ViewModels.Wallets.Home.History
if (item.IsLikelyCoinJoinOutput)
{
- item.Label = "Privacy Increasement";
- DateTimeOffset lastCjDateInGroup = item.DateTime;
-
- for (var j = i + 1; j < txRecordList.Count; j++)
- {
- var nextItem = txRecordList[j];
-
- if (!nextItem.IsLikelyCoinJoinOutput)
+ if (!item.IsConfirmed())
{
- i = j - 1;
- yield return new CoinJoinHistoryItemViewModel(i, item, _walletViewModel, balance, lastCjDateInGroup);
- break;
+ continue;
}
- balance += nextItem.Amount;
-
- if (!nextItem.IsConfirmed())
+ if (coinJoinGroup is null)
{
- continue;
+ coinJoinGroup = new CoinJoinsHistoryItemViewModel(i, item);
}
-
- item.Amount += nextItem.Amount;
- lastCjDateInGroup = nextItem.DateTime;
+ else
+ {
+ coinJoinGroup.Add(item);
}
}
else
{
+ if (coinJoinGroup is { } cjg)
+ {
+ cjg.SetBalance(balance);
+ yield return cjg;
+ coinJoinGroup = null;
+ }
+
yield return new TransactionHistoryItemViewModel(i, item, _walletViewModel, balance, _updateTrigger);
}
}

MODIFY
WalletWasabi.Fluent/ViewModels/Wallets/Home/Tiles/WalletBalanceTileViewModel.cs
WalletWasabi.Fluent/ViewModels/Wallets/Home/Tiles/WalletBalanceTileViewModel.cs
@@ -10,7 +10,6 @@ using ReactiveUI;
using WalletWasabi.Wallets;
using WalletWasabi.Fluent.Helpers;
using WalletWasabi.Fluent.ViewModels.Wallets.Home.History.HistoryItems;
-using WalletWasabi.Models;
namespace WalletWasabi.Fluent.ViewModels.Wallets.Home.Tiles
{
@@ -24,7 +23,7 @@ namespace WalletWasabi.Fluent.ViewModels.Wallets.Home.Tiles
[AutoNotify(SetterModifier = AccessModifier.Private)] private string? _balancePrivateBtc;
[AutoNotify(SetterModifier = AccessModifier.Private)] private string? _balanceNonPrivateBtc;
[AutoNotify(SetterModifier = AccessModifier.Private)] private string? _recentTransactionName;
- [AutoNotify(SetterModifier = AccessModifier.Private)] private DateTimeOffset? _recentTransactionDate;
+ [AutoNotify(SetterModifier = AccessModifier.Private)] private string? _recentTransactionDate;
[AutoNotify(SetterModifier = AccessModifier.Private)] private string? _recentTransactionStatus;
[AutoNotify(SetterModifier = AccessModifier.Private)] private bool _showRecentTransaction;
@@ -73,25 +72,12 @@ namespace WalletWasabi.Fluent.ViewModels.Wallets.Home.Tiles
var recent = _history.FirstOrDefault();
if (recent is { })
{
- var transactionSummary = recent.TransactionSummary;
- var confirmations = transactionSummary.Height.Type == HeightType.Chain ?
- (int)_wallet.BitcoinStore.SmartHeaderChain.TipHeight - transactionSummary.Height.Value + 1
- : 0;
- var isConfirmed = confirmations > 0;
- var isIncoming = true;
- var amount = transactionSummary.Amount;
- if (amount < Money.Zero)
- {
- amount *= -1;
- isIncoming = false;
- }
- RecentTransactionName = isIncoming ? "Incoming" : "Outgoing";
+ var isIncoming = recent.IncomingAmount is { };
- RecentTransactionDate = transactionSummary.DateTime.ToLocalTime();
-
- RecentTransactionStatus = $"{(amount.ToDecimal(MoneyUnit.BTC).FormattedBtc() + " BTC")}" +
- $" - {(isConfirmed ? "Confirmed" : "Pending")}";
+ RecentTransactionName = isIncoming ? "Incoming" : "Outgoing";
+ RecentTransactionDate = recent.DateString;
+ RecentTransactionStatus = $"{(isIncoming ? recent.IncomingAmount : recent.OutgoingAmount)} BTC - {(recent.IsConfirmed ? "Confirmed" : "Pending")}";
ShowRecentTransaction = true;
}

MODIFY
WalletWasabi.Fluent/Views/Wallets/Home/Tiles/WalletBalance/WalletBalanceWideTileView.axaml
WalletWasabi.Fluent/Views/Wallets/Home/Tiles/WalletBalance/WalletBalanceWideTileView.axaml
Height="14" Width="14" Foreground="{DynamicResource SystemAccentColor}" />
</Viewbox>
<TextBlock
- Text="{Binding RecentTransactionDate, StringFormat='{}{0:MM/dd/yyyy HH:mm}', FallbackValue='7/12/2020'}"
+ Text="{Binding RecentTransactionDate, FallbackValue='7/12/2020'}"
Opacity="0.8" FontSize="12" Margin="10,0,0,0" />
</DockPanel>
<!-- Recent transaction status -->

refactor CJ group logic