Add FeeTargetAvarageTimeFrame
MODIFY
WalletWasabi/WabiSabi/Client/CoinJoinClient.cs
WalletWasabi/WabiSabi/Client/CoinJoinClient.cs
@@ -3,10 +3,8 @@ using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Net.Http;
-using System.Text;
using System.Threading;
using System.Threading.Tasks;
-using WalletWasabi.Blockchain.Keys;
using WalletWasabi.Blockchain.TransactionOutputs;
using WalletWasabi.Crypto.Randomness;
using WalletWasabi.Helpers;
@@ -34,6 +32,7 @@ public class CoinJoinClient
RoundStateUpdater roundStatusUpdater,
int minAnonScoreTarget = int.MaxValue,
bool consolidationMode = false,
+ TimeSpan feeTargetAvarageTimeFrame = default,
TimeSpan doNotRegisterInLastMinuteTimeLimit = default)
{
HttpClientFactory = httpClientFactory;
@@ -42,6 +41,7 @@ public class CoinJoinClient
RoundStatusUpdater = roundStatusUpdater;
MinAnonScoreTarget = minAnonScoreTarget;
ConsolidationMode = consolidationMode;
+ FeeTargetAvarageTimeFrame = feeTargetAvarageTimeFrame;
SecureRandom = new SecureRandom();
DoNotRegisterInLastMinuteTimeLimit = doNotRegisterInLastMinuteTimeLimit;
}
@@ -61,6 +61,7 @@ public class CoinJoinClient
}
public bool ConsolidationMode { get; private set; }
+ private TimeSpan FeeTargetAvarageTimeFrame { get; }
public async Task<bool> StartCoinJoinAsync(IEnumerable<SmartCoin> coins, CancellationToken cancellationToken)
{
@@ -68,7 +69,8 @@ public class CoinJoinClient
.CreateRoundAwaiter(
roundState =>
roundState.InputRegistrationEnd - DateTimeOffset.UtcNow > DoNotRegisterInLastMinuteTimeLimit &&
- roundState.Phase == Phase.InputRegistration,
+ roundState.Phase == Phase.InputRegistration &&
+ IsRoundEconomic(roundState.FeeRate),
cancellationToken)
.ConfigureAwait(false);
@@ -420,6 +422,21 @@ public class CoinJoinClient
return bestgroup.ToShuffled().ToImmutableList();
}
+ public bool IsRoundEconomic(FeeRate roundFeeRate)
+ {
+ if (FeeTargetAvarageTimeFrame == default)
+ {
+ return true;
+ }
+
+ if (RoundStatusUpdater.CoinJoinFeeRateAverages.TryGetValue(FeeTargetAvarageTimeFrame, out var feeRate))
+ {
+ return roundFeeRate <= feeRate;
+ }
+
+ throw new InvalidOperationException($"Could not find average feeRate for timeframe: {FeeTargetAvarageTimeFrame}.");
+ }
+
/// <summary>
/// Calculates how many inputs are desirable to be registered
/// based on roughly the total number of coins in a wallet.

MODIFY
WalletWasabi/WabiSabi/Client/CoinJoinTrackerFactory.cs
WalletWasabi/WabiSabi/Client/CoinJoinTrackerFactory.cs
@@ -30,6 +30,7 @@ public class CoinJoinTrackerFactory
new InternalDestinationProvider(wallet.KeyManager),
RoundStatusUpdater,
wallet.KeyManager.MinAnonScoreTarget,
+ feeTargetAvarageTimeFrame: TimeSpan.FromHours(wallet.KeyManager.FeeTargetAvarageTimeFrameHours),
doNotRegisterInLastMinuteTimeLimit: TimeSpan.FromMinutes(1));
return new CoinJoinTracker(wallet, coinJoinClient, coinCandidates, CancellationToken);

MODIFY
WalletWasabi/WabiSabi/Client/RoundStateUpdater.cs
WalletWasabi/WabiSabi/Client/RoundStateUpdater.cs
@@ -5,7 +5,6 @@ using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using WalletWasabi.Bases;
-using WalletWasabi.CoinJoin.Common.Models;
using WalletWasabi.WabiSabi.Backend.PostRequests;
using WalletWasabi.WabiSabi.Backend.Rounds;
using WalletWasabi.WabiSabi.Models;
@@ -21,6 +20,7 @@ public class RoundStateUpdater : PeriodicRunner
private IWabiSabiApiRequestHandler ArenaRequestHandler { get; }
private Dictionary<uint256, RoundState> RoundStates { get; set; } = new();
+ public Dictionary<TimeSpan, FeeRate> CoinJoinFeeRateAverages { get; private set; } = new();
private List<RoundStateAwaiter> Awaiters { get; } = new();
private object AwaitersLock { get; } = new();
@@ -35,6 +35,8 @@ public class RoundStateUpdater : PeriodicRunner
var response = await ArenaRequestHandler.GetStatusAsync(request, cancellationToken).ConfigureAwait(false);
RoundState[] statusResponse = response.RoundStates;
+ CoinJoinFeeRateAverages = response.CoinJoinFeeRateAverages.ToDictionary(a => a.TimeFrame, a => a.AverageFeeRate);
+
var updatedRoundStates = statusResponse
.Where(rs => RoundStates.ContainsKey(rs.Id))
.Select(rs => (NewRoundState: rs, CurrentRoundState: RoundStates[rs.Id]))

Add FeeTargetAvarageTimeFrame