RoundSate Serializarion
MODIFY
WalletWasabi.Tests/UnitTests/WabiSabi/Models/SerializationTests.cs
WalletWasabi.Tests/UnitTests/WabiSabi/Models/SerializationTests.cs
@@ -146,11 +146,19 @@ namespace WalletWasabi.Tests.UnitTests.WabiSabi.Models
AssertSerialization(message);
}
+ [Fact]
+ public void RoundStateMessageSerialization()
+ {
+ var round = WabiSabiFactory.CreateRound(new WalletWasabi.WabiSabi.Backend.WabiSabiConfig());
+ AssertSerialization(RoundState.FromRound(round));
+ }
+
private static void AssertSerialization<T>(T message)
{
var serializedMessage = JsonConvert.SerializeObject(message, JsonSerializationOptions.Default.Settings);
var deserializedMessage = JsonConvert.DeserializeObject<T>(serializedMessage, JsonSerializationOptions.Default.Settings);
var reserializedMessage = JsonConvert.SerializeObject(deserializedMessage, JsonSerializationOptions.Default.Settings);
+
Assert.Equal(reserializedMessage, serializedMessage);
}

ADD
WalletWasabi/JsonConverters/Bitcoin/FeeRateJsonConverter.cs
+using NBitcoin;
+using Newtonsoft.Json;
+using System;
+
+namespace WalletWasabi.JsonConverters.Bitcoin
+{
+ public class FeeRateJsonConverter : JsonConverter
+ {
+ public override bool CanConvert(Type objectType)
+ {
+ return objectType == typeof(FeeRate);
+ }
+
+ public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
+ {
+ return new FeeRate(Money.Satoshis((long)reader.Value));
+ }
+
+ public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
+ {
+ var feerate = (FeeRate)value;
+
+ writer.WriteValue(feerate.FeePerK.Satoshi);
+ }
+ }
+}

ADD
WalletWasabi/WabiSabi/Models/Serialization/IStateJsonConverter.cs
+using System;
+using Newtonsoft.Json;
+using Newtonsoft.Json.Linq;
+using WalletWasabi.WabiSabi.Models.MultipartyTransaction;
+
+namespace WalletWasabi.WabiSabi.Models.Serialization
+{
+ public class IStateJsonConverter : JsonConverter
+ {
+ // This converter is a bit unusual because we need to add a new property to the
+ // serialized json string but the converter is called recursively and fails with
+ // an "Self referencing loop" exception.
+ // The workaround is detect it and prevent reentering by setting CanRead and
+ // CanWrite to false immediately after entering.
+ // see: https://github.com/JamesNK/Newtonsoft.Json/issues/386
+ [ThreadStatic]
+ private static bool _isReading;
+
+ [ThreadStatic]
+ private static bool _isWriting;
+
+ public override bool CanWrite
+ {
+ get
+ {
+ if (!_isWriting)
+ {
+ return true;
+ }
+ _isWriting = false;
+
+ return false;
+ }
+ }
+
+ public override bool CanRead
+ {
+ get
+ {
+ if (!_isReading)
+ {
+ return true;
+ }
+ _isReading = false;
+
+ return false;
+ }
+ }
+
+ public override bool CanConvert(Type objectType)
+ {
+ return typeof(IState).IsAssignableFrom(objectType);
+ }
+
+ public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
+ {
+ try
+ {
+ _isWriting = true;
+
+ var stateTypeName = value switch
+ {
+ ConstructionState => "Constructing",
+ SigningState => "Signing",
+ _ => throw new InvalidOperationException("")
+ };
+ var jObject = (JObject)JToken.FromObject(value, serializer);
+ jObject.AddFirst(new JProperty("State", stateTypeName));
+ jObject.WriteTo(writer);
+ }
+ finally
+ {
+ _isWriting = false;
+ }
+ }
+
+ public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
+ {
+ try
+ {
+ _isReading = true;
+
+ var jsonObject = JObject.Load(reader);
+ var stateType = jsonObject.Value<string>("State") switch
+ {
+ "Constructing" => typeof(ConstructionState),
+ "Signing" => typeof(SigningState),
+ _ => throw new InvalidOperationException("")
+ };
+ return serializer.Deserialize(jsonObject.CreateReader(), stateType);
+ }
+ finally
+ {
+ _isReading = false;
+ }
+ }
+ }
+}

MODIFY
WalletWasabi/WabiSabi/Models/Serialization/JsonSerializationOptions.cs
WalletWasabi/WabiSabi/Models/Serialization/JsonSerializationOptions.cs
-using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using WalletWasabi.JsonConverters;
@@ -19,6 +18,11 @@ namespace WalletWasabi.WabiSabi.Models.Serialization
new WitScriptJsonConverter(),
new ScriptJsonConverter(),
new OwnershipProofJsonConverter(),
+ new NetworkJsonConverter(),
+ new FeeRateJsonConverter(),
+ new MoneySatoshiJsonConverter(),
+ new Uint256JsonConverter(),
+ new IStateJsonConverter()
}
};
public static readonly JsonSerializationOptions Default = new();

RoundSate Serializarion