Skip to content

Commit

Permalink
Support System Text Json and bump to net8
Browse files Browse the repository at this point in the history
  • Loading branch information
Kukks committed Jun 28, 2024
1 parent 061bcaa commit 4bd4933
Show file tree
Hide file tree
Showing 26 changed files with 656 additions and 178 deletions.
27 changes: 20 additions & 7 deletions LNURL.Tests/LNURL.Tests.csproj
Original file line number Diff line number Diff line change
@@ -1,21 +1,34 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework>net8.0</TargetFramework>

<IsPackable>false</IsPackable>

<Configurations>Debug;Release;Debug JSONNET;Release JSONNET</Configurations>

<Platforms>AnyCPU</Platforms>
</PropertyGroup>

<PropertyGroup Condition=" '$(Configuration)' == 'Debug JSONNET' ">
<DebugSymbols Condition=" '$(DebugSymbols)' == '' ">true</DebugSymbols>
<Optimize Condition=" '$(Optimize)' == '' ">false</Optimize>
</PropertyGroup>

<PropertyGroup Condition=" '$(Configuration)' == 'Release JSONNET' ">
<Optimize Condition=" '$(Optimize)' == '' ">true</Optimize>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.1.0" />
<PackageReference Include="NBitcoin" Version="7.0.30" />
<PackageReference Include="NBitcoin.Altcoins" Version="3.0.20" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.10.0" />
<PackageReference Include="NBitcoin" Version="7.0.37" />
<PackageReference Include="NBitcoin.Altcoins" Version="3.0.24" />
<PackageReference Include="xunit" Version="2.8.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.1">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="coverlet.collector" Version="3.0.2">
<PackageReference Include="coverlet.collector" Version="6.0.2">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
Expand Down
53 changes: 52 additions & 1 deletion LNURL.Tests/UnitTest1.cs
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
using System;
using System.Diagnostics;
using System.Linq;
using System.Text.Json;
using System.Threading.Tasks;
using LNURL.Requests;
using NBitcoin;
using NBitcoin.Altcoins.Elements;
using NBitcoin.Crypto;
using NBitcoin.DataEncoders;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Xunit;
using JsonSerializer = System.Text.Json.JsonSerializer;

namespace LNURL.Tests
{
Expand All @@ -29,8 +33,10 @@ public void CanHandlePayLinkEdgeCase()
"}";

var req = JsonConvert.DeserializeObject<LNURLWithdrawRequest>(json);
var req2 = JsonSerializer.Deserialize<LNURLWithdrawRequest>(json);

Assert.Null(req.PayLink);
Assert.Null(req2.PayLink);

json =
"{" +
Expand All @@ -43,8 +49,10 @@ public void CanHandlePayLinkEdgeCase()
"}";

req = JsonConvert.DeserializeObject<LNURLWithdrawRequest>(json);
req2 = JsonSerializer.Deserialize<LNURLWithdrawRequest>(json);

Assert.Null(req.PayLink);
Assert.Null(req2.PayLink);
}

[Theory]
Expand Down Expand Up @@ -146,6 +154,14 @@ public async Task payerDataSerializerTest()
Assert.False(req.PayerData.Auth.Mandatory);
Assert.Null(req.PayerData.Email);

req = JsonSerializer.Deserialize<LNURLPayRequest>(JsonSerializer.Serialize(req));

Assert.NotNull(req.PayerData);
Assert.True(req.PayerData.Pubkey.Mandatory);
Assert.False(req.PayerData.Name.Mandatory);
Assert.False(req.PayerData.Auth.Mandatory);
Assert.Null(req.PayerData.Email);

var k = new Key();

var resp = new LNURLPayRequest.LUD18PayerDataResponse()
Expand All @@ -161,10 +177,19 @@ public async Task payerDataSerializerTest()
resp = JsonConvert.DeserializeObject<LNURLPayRequest.LUD18PayerDataResponse>(
JsonConvert.SerializeObject(resp));
Assert.False(req.VerifyPayerData(resp));

resp = JsonSerializer.Deserialize<LNURLPayRequest.LUD18PayerDataResponse>(
JsonSerializer.Serialize(resp));
Assert.False(req.VerifyPayerData(resp));

resp.Pubkey = k.PubKey;
resp = JsonConvert.DeserializeObject<LNURLPayRequest.LUD18PayerDataResponse>(
JsonConvert.SerializeObject(resp));
Assert.True(req.VerifyPayerData(resp));

resp = JsonSerializer.Deserialize<LNURLPayRequest.LUD18PayerDataResponse>(
JsonSerializer.Serialize(resp));

resp.Email = "[email protected]";
Assert.False(req.VerifyPayerData(resp));

Expand Down Expand Up @@ -248,14 +273,14 @@ public async Task DeterministicCards()
}
}
}

//from https://github.com/boltcard/boltcard/blob/7745c9f20d5ad0129cb4b3fc534441038e79f5e6/docs/TEST_VECTORS.md
[Theory]
[InlineData("4E2E289D945A66BB13377A728884E867", "E19CCB1FED8892CE", "04996c6a926980", 3)]
[InlineData("00F48C4F8E386DED06BCDC78FA92E2FE", "66B4826EA4C155B4", "04996c6a926980", 5)]
[InlineData("0DBF3C59B59B0638D60B5842A997D4D1", "CC61660C020B4D96", "04996c6a926980", 7)]
public void TestDecryptAndValidate(string pValueHex, string cValueHex, string expectedUidHex, uint expectedCtr)
{

var aesDecryptKey = Convert.FromHexString("0c3b25d92b38ae443229dd59ad34b85d");
var aesCmacKey = Convert.FromHexString("b45775776cb224c75bcde7ca3704e933");
byte[] pValue = Convert.FromHexString(pValueHex);
Expand All @@ -273,5 +298,31 @@ public void TestDecryptAndValidate(string pValueHex, string cValueHex, string ex
Assert.True(cmacIsValid, "CMAC validation failed");
}

[Fact]
public void TestErrorStatus()
{
var validErrorJson = "{\"status\": \"ERROR\", \"reason\": \"error details...\"}";
var noterror = "{\"status\": \"ok\", \"reason\": \"error details...\"}";

Assert.True(LNUrlStatusResponse.IsErrorResponse(JObject.Parse(validErrorJson), out var status));
Assert.Equal(status.Reason, "error details...");
Assert.True(LNUrlStatusResponse.IsErrorResponse(JsonSerializer.Deserialize<JsonElement>(validErrorJson),
out var status2));

Assert.Equal(status2.Reason, "error details...");

Assert.False(LNUrlStatusResponse.IsErrorResponse(JObject.Parse(noterror), out var status3));
Assert.Null(status3);
Assert.False(LNUrlStatusResponse.IsErrorResponse(JsonSerializer.Deserialize<JsonElement>(noterror),
out var status4));
Assert.Null(status4);
}

[Fact]
public void TestUnknownLnurl()
{


}
}
}
10 changes: 10 additions & 0 deletions LNURL.sln
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,25 @@ Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
Debug JSONNET|Any CPU = Debug JSONNET|Any CPU
Release JSONNET|Any CPU = Release JSONNET|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{8AE80152-6EF0-47BC-AE09-B9C72DBC6902}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8AE80152-6EF0-47BC-AE09-B9C72DBC6902}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8AE80152-6EF0-47BC-AE09-B9C72DBC6902}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8AE80152-6EF0-47BC-AE09-B9C72DBC6902}.Release|Any CPU.Build.0 = Release|Any CPU
{8AE80152-6EF0-47BC-AE09-B9C72DBC6902}.Debug JSONNET|Any CPU.ActiveCfg = Debug JSONNET|Any CPU
{8AE80152-6EF0-47BC-AE09-B9C72DBC6902}.Debug JSONNET|Any CPU.Build.0 = Debug JSONNET|Any CPU
{8AE80152-6EF0-47BC-AE09-B9C72DBC6902}.Release JSONNET|Any CPU.ActiveCfg = Release JSONNET|Any CPU
{8AE80152-6EF0-47BC-AE09-B9C72DBC6902}.Release JSONNET|Any CPU.Build.0 = Release JSONNET|Any CPU
{0D55DB17-C3F5-4FB4-A456-58C3E8593AC2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0D55DB17-C3F5-4FB4-A456-58C3E8593AC2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0D55DB17-C3F5-4FB4-A456-58C3E8593AC2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0D55DB17-C3F5-4FB4-A456-58C3E8593AC2}.Release|Any CPU.Build.0 = Release|Any CPU
{0D55DB17-C3F5-4FB4-A456-58C3E8593AC2}.Debug JSONNET|Any CPU.ActiveCfg = Debug JSONNET|Any CPU
{0D55DB17-C3F5-4FB4-A456-58C3E8593AC2}.Debug JSONNET|Any CPU.Build.0 = Debug JSONNET|Any CPU
{0D55DB17-C3F5-4FB4-A456-58C3E8593AC2}.Release JSONNET|Any CPU.ActiveCfg = Release JSONNET|Any CPU
{0D55DB17-C3F5-4FB4-A456-58C3E8593AC2}.Release JSONNET|Any CPU.Build.0 = Release JSONNET|Any CPU
EndGlobalSection
EndGlobal
40 changes: 40 additions & 0 deletions LNURL/Json/Newtonsoft/LNURLPayRequestSuccessActionJsonConverter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
using System;
using LNURL.Requests;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

namespace LNURL.Json.Newtonsoft;

public class LNURLPayRequestSuccessActionJsonConverter : JsonConverter<LNURLPayRequest.LNURLPayRequestCallbackResponse.ILNURLPayRequestSuccessAction>
{
public override void WriteJson(JsonWriter writer, LNURLPayRequest.LNURLPayRequestCallbackResponse.ILNURLPayRequestSuccessAction value,
JsonSerializer serializer)
{
if (value is null)
{
writer.WriteNull();
return;
}

JObject.FromObject(value).WriteTo(writer);
}

public override LNURLPayRequest.LNURLPayRequestCallbackResponse.ILNURLPayRequestSuccessAction ReadJson(JsonReader reader, Type objectType,
LNURLPayRequest.LNURLPayRequestCallbackResponse.ILNURLPayRequestSuccessAction existingValue,
bool hasExistingValue, JsonSerializer serializer)
{
if (reader.TokenType is JsonToken.Null) return null;
var jobj = JObject.Load(reader);
switch (jobj.GetValue("tag").Value<string>())
{
case "message":
return jobj.ToObject<LNURLPayRequest.LNURLPayRequestCallbackResponse.LNURLPayRequestSuccessActionMessage>();
case "url":
return jobj.ToObject<LNURLPayRequest.LNURLPayRequestCallbackResponse.LNURLPayRequestSuccessActionUrl>();
case "aes":
return jobj.ToObject<LNURLPayRequest.LNURLPayRequestCallbackResponse.LNURLPayRequestSuccessActionAES>();
}

throw new FormatException();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@
using NBitcoin.JsonConverters;
using Newtonsoft.Json;

namespace LNURL.JsonConverters;
namespace LNURL.Json.Newtonsoft;

public class NodeUriJsonConverter : JsonConverter<NodeInfo>
public class NodeUriJsonConverter : global::Newtonsoft.Json.JsonConverter<NodeInfo>
{
public override NodeInfo ReadJson(JsonReader reader, Type objectType, [AllowNull] NodeInfo existingValue,
bool hasExistingValue, JsonSerializer serializer)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
using NBitcoin.JsonConverters;
using Newtonsoft.Json;

namespace LNURL.JsonConverters;
namespace LNURL.Json.Newtonsoft;

public class PubKeyJsonConverter : JsonConverter<PubKey>
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
using NBitcoin.JsonConverters;
using Newtonsoft.Json;

namespace LNURL.JsonConverters;
namespace LNURL.Json.Newtonsoft;

public class SigJsonConverter : JsonConverter<ECDSASignature>
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
using NBitcoin.JsonConverters;
using Newtonsoft.Json;

namespace LNURL.JsonConverters;
namespace LNURL.Json.Newtonsoft;

public class UriJsonConverter : JsonConverter
{
Expand Down
47 changes: 47 additions & 0 deletions LNURL/Json/SystemJson/LNURLPayRequestSuccessActionJsonConverter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
using System;
using System.Text.Json;
using LNURL.Requests;

namespace LNURL.Json.SystemJson;

public class LNURLPayRequestSuccessActionJsonConverter : System.Text.Json.Serialization.JsonConverter<
LNURLPayRequest.LNURLPayRequestCallbackResponse.ILNURLPayRequestSuccessAction>
{
public override LNURLPayRequest.LNURLPayRequestCallbackResponse.ILNURLPayRequestSuccessAction Read(
ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
if (reader.TokenType is JsonTokenType.Null)
return null;
if (reader.TokenType is not JsonTokenType.StartObject)
throw new JsonException("Unexpected token type for LNURLPayRequestSuccessAction");
JsonElement element = JsonDocument.ParseValue(ref reader).RootElement;
switch (element.GetProperty("tag").GetString())
{
case "message":
return element
.Deserialize<LNURLPayRequest.LNURLPayRequestCallbackResponse.LNURLPayRequestSuccessActionMessage>(
options);
case "url":
return element
.Deserialize<LNURLPayRequest.LNURLPayRequestCallbackResponse.LNURLPayRequestSuccessActionUrl>(
options);
case "aes":
return element
.Deserialize<LNURLPayRequest.LNURLPayRequestCallbackResponse.LNURLPayRequestSuccessActionAES>(
options);
default: throw new JsonException("Invalid LNURLPayRequestSuccessAction");
}
}

public override void Write(Utf8JsonWriter writer,
LNURLPayRequest.LNURLPayRequestCallbackResponse.ILNURLPayRequestSuccessAction value,
JsonSerializerOptions options)
{
if (value is null)
writer.WriteNullValue();
else
{
JsonSerializer.Serialize(writer, value);
}
}
}
35 changes: 35 additions & 0 deletions LNURL/Json/SystemJson/LightMoneyJsonConverter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
using System;
using System.Text.Json;
using System.Text.Json.Serialization;
using BTCPayServer.Lightning;

namespace LNURL.Json.SystemJson;
public class LightMoneyJsonConverter:JsonConverter<LightMoney>
{
public override LightMoney Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
try
{
return reader.TokenType switch
{
JsonTokenType.Null => null,
JsonTokenType.Number => new LightMoney(reader.GetInt64()),
JsonTokenType.String => new LightMoney(long.Parse(reader.GetString())),
JsonTokenType.StartObject => reader.Read() ? LightMoney.Zero : null,
_ => null
};
}
catch (InvalidCastException)
{
throw new JsonException("Money amount should be in millisatoshi");
}
}

public override void Write(Utf8JsonWriter writer, LightMoney value, JsonSerializerOptions options)
{
if(value is not null)
writer.WriteNumberValue(value.MilliSatoshi);
else
writer.WriteNullValue();
}
}
28 changes: 28 additions & 0 deletions LNURL/Json/SystemJson/NodeUriJsonConverter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
using System;
using System.Text.Json;
using System.Text.Json.Serialization;
using BTCPayServer.Lightning;

namespace LNURL.Json.SystemJson;

public class NodeUriJsonConverter : JsonConverter<NodeInfo>
{
public override NodeInfo Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
if (reader.TokenType != JsonTokenType.String)
throw new JsonException("Unexpected token type for NodeUri");
if (NodeInfo.TryParse(reader.GetString(), out var info))
return info;
throw new JsonException("Invalid NodeUri");
}

public override void Write(Utf8JsonWriter writer, NodeInfo value, JsonSerializerOptions options)
{
if (value is not null)
writer.WriteStringValue(value.ToString());
else
{
writer.WriteNullValue();
}
}
}
Loading

0 comments on commit 4bd4933

Please sign in to comment.