port GUI notification messages
MODIFY
WalletWasabi.Fluent/Helpers/TransactionHelpers.cs
WalletWasabi.Fluent/Helpers/TransactionHelpers.cs
@@ -5,7 +5,9 @@ using NBitcoin;
using WalletWasabi.Blockchain.Analysis.Clustering;
using WalletWasabi.Blockchain.TransactionBuilding;
using WalletWasabi.Blockchain.TransactionOutputs;
+using WalletWasabi.Blockchain.TransactionProcessing;
using WalletWasabi.Fluent.ViewModels.Wallets.Send;
+using WalletWasabi.Logging;
using WalletWasabi.Wallets;
using WalletWasabi.WebClients.PayJoin;
@@ -55,5 +57,97 @@ namespace WalletWasabi.Fluent.Helpers
isPayJoin ? transactionInfo.PayJoinClient : null);
}
+
+ public static (string, string) GetNotificationInputs(ProcessedResult e)
+ {
+ try
+ {
+ // ToDo
+ // Double spent.
+ // Anonymity set gained?
+ // Received dust
+
+ bool isSpent = e.NewlySpentCoins.Any();
+ bool isReceived = e.NewlyReceivedCoins.Any();
+ bool isConfirmedReceive = e.NewlyConfirmedReceivedCoins.Any();
+ bool isConfirmedSpent = e.NewlyConfirmedReceivedCoins.Any();
+ Money miningFee = e.Transaction.Transaction.GetFee(e.SpentCoins.Select(x => x.Coin).ToArray());
+ if (isReceived || isSpent)
+ {
+ Money receivedSum = e.NewlyReceivedCoins.Sum(x => x.Amount);
+ Money spentSum = e.NewlySpentCoins.Sum(x => x.Amount);
+ Money incoming = receivedSum - spentSum;
+ Money receiveSpentDiff = incoming.Abs();
+ string amountString = receiveSpentDiff.ToString(false, true);
+
+ if (e.Transaction.Transaction.IsCoinBase)
+ {
+ return ("Mined", $"{amountString} BTC");
+ }
+ else if (isSpent && receiveSpentDiff == miningFee)
+ {
+ return ("Self Spend", $"Mining Fee: {amountString} BTC");
+ }
+ else if (isSpent && receiveSpentDiff.Almost(Money.Zero, Money.Coins(0.01m)) && e.IsLikelyOwnCoinJoin)
+ {
+ return ("", $"CoinJoin Completed!");
+ }
+ else if (incoming > Money.Zero)
+ {
+ if (e.Transaction.IsRBF && e.Transaction.IsReplacement)
+ {
+ return ("Received Replaceable Replacement Transaction", $"{amountString} BTC");
+ }
+ else if (e.Transaction.IsRBF)
+ {
+ return ("Received Replaceable Transaction", $"{amountString} BTC");
+ }
+ else if (e.Transaction.IsReplacement)
+ {
+ return ("Received Replacement Transaction", $"{amountString} BTC");
+ }
+ else
+ {
+ return ("Received", $"{amountString} BTC");
+ }
+ }
+ else if (incoming < Money.Zero)
+ {
+ return ("Sent", $"{amountString} BTC");
+ }
+ }
+ else if (isConfirmedReceive || isConfirmedSpent)
+ {
+ Money receivedSum = e.ReceivedCoins.Sum(x => x.Amount);
+ Money spentSum = e.SpentCoins.Sum(x => x.Amount);
+ Money incoming = receivedSum - spentSum;
+ Money receiveSpentDiff = incoming.Abs();
+ string amountString = receiveSpentDiff.ToString(false, true);
+
+ if (isConfirmedSpent && receiveSpentDiff == miningFee)
+ {
+ return ("Self Spend Confirmed", $"Mining Fee: {amountString} BTC");
+ }
+ else if (isConfirmedSpent && receiveSpentDiff.Almost(Money.Zero, Money.Coins(0.01m)) && e.IsLikelyOwnCoinJoin)
+ {
+ return ("", $"CoinJoin Confirmed!");
+ }
+ else if (incoming > Money.Zero)
+ {
+ return ("Receive Confirmed", $"{amountString} BTC");
+ }
+ else if (incoming < Money.Zero)
+ {
+ return ("Send Confirmed", $"{amountString} BTC");
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ Logger.LogWarning(ex);
+ }
+
+ return ("", "");
+ }
}
}

MODIFY
WalletWasabi.Fluent/ViewModels/Wallets/WalletViewModel.cs
WalletWasabi.Fluent/ViewModels/Wallets/WalletViewModel.cs
@@ -4,6 +4,8 @@ using System.Collections.Generic;
using System.Reactive;
using System.Reactive.Disposables;
using System.Reactive.Linq;
+using WalletWasabi.Blockchain.TransactionProcessing;
+using WalletWasabi.Fluent.Helpers;
using WalletWasabi.Fluent.ViewModels.Wallets.HardwareWallet;
using WalletWasabi.Fluent.ViewModels.Wallets.Home.History;
using WalletWasabi.Fluent.ViewModels.Wallets.Home.Tiles;
@@ -71,6 +73,21 @@ namespace WalletWasabi.Fluent.ViewModels.Wallets
WalletPieChart,
BalanceChartTile
};
+
+ Observable.FromEventPattern<ProcessedResult>(Wallet.TransactionProcessor, nameof(Wallet.TransactionProcessor.WalletRelevantTransactionProcessed))
+ .Subscribe(arg =>
+ {
+ var (sender, e) = arg;
+
+ if (uiConfig.PrivacyMode || !e.IsNews)
+ {
+ return;
+ }
+
+ var (title, message) = TransactionHelpers.GetNotificationInputs(e);
+
+ NotificationHelpers.Show(title, message);
+ });
}
private CompositeDisposable Disposables { get; set; }

port GUI notification messages