Add WrongPhaseException
ADD
WalletWasabi/WabiSabi/Backend/Models/WrongPhaseException.cs
+using NBitcoin;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using WalletWasabi.WabiSabi.Backend.Rounds;
+
+namespace WalletWasabi.WabiSabi.Backend.Models;
+
+public class WrongPhaseException : WabiSabiProtocolException
+{
+ public TimeSpan Late { get; }
+ public Phase CurrentPhase { get; }
+ public Phase[] ExpectedPhases { get; }
+ public uint256 RoundId { get; }
+
+ public WrongPhaseException(Round round, Phase[] expectedPhases) : base(WabiSabiProtocolErrorCode.WrongPhase, $"Round ({round.Id}): Wrong phase ({round.Phase}).")
+ {
+ var latestExpectedPhase = expectedPhases.OrderBy(p => (int)p).Last();
+ var now = DateTimeOffset.UtcNow;
+
+ Late = latestExpectedPhase switch
+ {
+ Phase.InputRegistration => now - round.InputRegistrationTimeFrame.EndTime,
+ Phase.ConnectionConfirmation => now - round.ConnectionConfirmationTimeFrame.EndTime,
+ Phase.OutputRegistration => now - round.OutputRegistrationTimeFrame.EndTime,
+ Phase.TransactionSigning => now - round.TransactionSigningTimeFrame.EndTime,
+ _ => TimeSpan.MaxValue
+ };
+
+ CurrentPhase = round.Phase;
+ RoundId = round.Id;
+ ExpectedPhases = expectedPhases;
+ }
+}

MODIFY
WalletWasabi/WabiSabi/Backend/Rounds/Arena.Partial.cs
WalletWasabi/WabiSabi/Backend/Rounds/Arena.Partial.cs
@@ -392,7 +392,7 @@ public partial class Arena : IWabiSabiApiRequestHandler
private Round InPhase(Round round, Phase[] phases) =>
phases.Contains(round.Phase)
? round
- : throw new WabiSabiProtocolException(WabiSabiProtocolErrorCode.WrongPhase, $"Round ({round.Id}): Wrong phase ({round.Phase}).");
+ : throw new WrongPhaseException(round, phases);
private Round GetRound(uint256 roundId, params Phase[] phases) =>
InPhase(GetRound(roundId), phases);

MODIFY
WalletWasabi/WabiSabi/Backend/Rounds/TimeFrame.cs
WalletWasabi/WabiSabi/Backend/Rounds/TimeFrame.cs
@@ -11,7 +11,7 @@ public record TimeFrame
public static TimeFrame Create(TimeSpan duration) =>
new(DateTimeOffset.MinValue, duration);
- private DateTimeOffset EndTime => StartTime + Duration;
+ public DateTimeOffset EndTime => StartTime + Duration;
public DateTimeOffset StartTime { get; init; }
public TimeSpan Duration { get; init; }
public bool HasStarted => StartTime > DateTimeOffset.MinValue && StartTime < DateTimeOffset.UtcNow;

Add WrongPhaseException