diff --git a/BTCPayServer.Client/BTCPayServer.Client.csproj b/BTCPayServer.Client/BTCPayServer.Client.csproj
index 88579cfab..4f8b94d29 100644
--- a/BTCPayServer.Client/BTCPayServer.Client.csproj
+++ b/BTCPayServer.Client/BTCPayServer.Client.csproj
@@ -28,7 +28,7 @@
-
+
diff --git a/BTCPayServer.Client/Models/CreateLightningInvoiceRequest.cs b/BTCPayServer.Client/Models/CreateLightningInvoiceRequest.cs
index 9e373eea7..d80a119b3 100644
--- a/BTCPayServer.Client/Models/CreateLightningInvoiceRequest.cs
+++ b/BTCPayServer.Client/Models/CreateLightningInvoiceRequest.cs
@@ -22,8 +22,7 @@ namespace BTCPayServer.Client.Models
[JsonConverter(typeof(JsonConverters.LightMoneyJsonConverter))]
public LightMoney Amount { get; set; }
public string Description { get; set; }
- [JsonConverter(typeof(NBitcoin.JsonConverters.UInt256JsonConverter))]
- public uint256 DescriptionHash { get; set; }
+ public bool DescriptionHashOnly { get; set; }
[JsonConverter(typeof(JsonConverters.TimeSpanJsonConverter.Seconds))]
public TimeSpan Expiry { get; set; }
public bool PrivateRouteHints { get; set; }
diff --git a/BTCPayServer.Tests/GreenfieldAPITests.cs b/BTCPayServer.Tests/GreenfieldAPITests.cs
index f09e1b8b3..df1a72ed4 100644
--- a/BTCPayServer.Tests/GreenfieldAPITests.cs
+++ b/BTCPayServer.Tests/GreenfieldAPITests.cs
@@ -2197,6 +2197,49 @@ namespace BTCPayServer.Tests
await AssertPermissionError("btcpay.store.canuselightningnode", () => client.GetLightningNodeInfo(user.StoreId, "BTC"));
}
+ [Fact(Timeout = 60 * 20 * 1000)]
+ [Trait("Integration", "Integration")]
+ [Trait("Lightning", "Lightning")]
+ public async Task CanUseLightningAPI2()
+ {
+ using var tester = CreateServerTester();
+ tester.ActivateLightning();
+ await tester.StartAsync();
+ await tester.EnsureChannelsSetup();
+ var user = tester.NewAccount();
+ await user.GrantAccessAsync(true);
+
+ var types = new[] { LightningConnectionType.LndREST, LightningConnectionType.CLightning };
+ foreach (var type in types)
+ {
+ user.RegisterLightningNode("BTC", type);
+ var client = await user.CreateClient("btcpay.store.cancreatelightninginvoice");
+ var amount = LightMoney.Satoshis(1000);
+ var expiry = TimeSpan.FromSeconds(600);
+
+ var invoice = await client.CreateLightningInvoice(user.StoreId, "BTC", new CreateLightningInvoiceRequest
+ {
+ Amount = amount,
+ Expiry = expiry,
+ Description = "Hashed description",
+ DescriptionHashOnly = true
+ });
+ var bolt11 = BOLT11PaymentRequest.Parse(invoice.BOLT11, Network.RegTest);
+ Assert.NotNull(bolt11.DescriptionHash);
+ Assert.Null(bolt11.ShortDescription);
+
+ invoice = await client.CreateLightningInvoice(user.StoreId, "BTC", new CreateLightningInvoiceRequest
+ {
+ Amount = amount,
+ Expiry = expiry,
+ Description = "Standard description",
+ });
+ bolt11 = BOLT11PaymentRequest.Parse(invoice.BOLT11, Network.RegTest);
+ Assert.Null(bolt11.DescriptionHash);
+ Assert.NotNull(bolt11.ShortDescription);
+ }
+ }
+
[Fact(Timeout = TestTimeout)]
[Trait("Integration", "Integration")]
public async Task NotificationAPITests()
diff --git a/BTCPayServer/Controllers/GreenField/GreenfieldLightningNodeApiController.cs b/BTCPayServer/Controllers/GreenField/GreenfieldLightningNodeApiController.cs
index 0291b9254..2f829d14d 100644
--- a/BTCPayServer/Controllers/GreenField/GreenfieldLightningNodeApiController.cs
+++ b/BTCPayServer/Controllers/GreenField/GreenfieldLightningNodeApiController.cs
@@ -295,27 +295,28 @@ namespace BTCPayServer.Controllers.Greenfield
ModelState.AddModelError(nameof(request.Amount), "Amount should be more or equals to 0");
}
+ if (request.Description is null && request.DescriptionHashOnly)
+ {
+ ModelState.AddModelError(nameof(request.Description), "Description is required when `descriptionHashOnly` is true");
+ }
+
if (request.Expiry <= TimeSpan.Zero)
{
ModelState.AddModelError(nameof(request.Expiry), "Expiry should be more than 0");
}
-
if (!ModelState.IsValid)
{
return this.CreateValidationError(ModelState);
}
-
+
+ request.Description ??= "";
try
{
- var param = request.DescriptionHash != null
- ? new CreateInvoiceParams(request.Amount, request.DescriptionHash, request.Expiry)
+ var param = new CreateInvoiceParams(request.Amount, request.Description, request.Expiry)
{
- PrivateRouteHints = request.PrivateRouteHints, Description = request.Description
- }
- : new CreateInvoiceParams(request.Amount, request.Description, request.Expiry)
- {
- PrivateRouteHints = request.PrivateRouteHints, DescriptionHash = request.DescriptionHash
- };
+ PrivateRouteHints = request.PrivateRouteHints,
+ DescriptionHashOnly = request.DescriptionHashOnly
+ };
var invoice = await lightningClient.CreateInvoice(param, cancellationToken);
return Ok(ToModel(invoice));
}
diff --git a/BTCPayServer/Controllers/UILNURLController.cs b/BTCPayServer/Controllers/UILNURLController.cs
index c24d90fb9..96e5cb692 100644
--- a/BTCPayServer/Controllers/UILNURLController.cs
+++ b/BTCPayServer/Controllers/UILNURLController.cs
@@ -565,14 +565,14 @@ namespace BTCPayServer
}
}
- var descriptionHash = new uint256(Hashes.SHA256(Encoding.UTF8.GetBytes(metadata)), false);
LightningInvoice invoice;
try
{
var expiry = i.ExpirationTime.ToUniversalTime() - DateTimeOffset.UtcNow;
- var param = new CreateInvoiceParams(amount.Value, descriptionHash, expiry)
+ var param = new CreateInvoiceParams(amount.Value, metadata, expiry)
{
- PrivateRouteHints = blob.LightningPrivateRouteHints
+ PrivateRouteHints = blob.LightningPrivateRouteHints,
+ DescriptionHashOnly = true
};
invoice = await client.CreateInvoice(param);
if (!BOLT11PaymentRequest.Parse(invoice.BOLT11, network.NBitcoinNetwork)
diff --git a/BTCPayServer/wwwroot/swagger/v1/swagger.template.lightning.common.json b/BTCPayServer/wwwroot/swagger/v1/swagger.template.lightning.common.json
index 7418d99fb..0d875a154 100644
--- a/BTCPayServer/wwwroot/swagger/v1/swagger.template.lightning.common.json
+++ b/BTCPayServer/wwwroot/swagger/v1/swagger.template.lightning.common.json
@@ -25,11 +25,11 @@
"nullable": true,
"description": "Description of the invoice in the BOLT11"
},
- "descriptionHash": {
- "type": "string",
- "format": "hex",
+ "descriptionHashOnly": {
+ "type": "boolean",
"nullable": true,
- "description": "Description hash of the invoice in the BOLT11"
+ "default": false,
+ "description": "If `descriptionHashOnly` is `true` (default is `false`), then the BOLT11 returned contains a hash of the `description`, rather than the `description`, itself. This allows for much longer descriptions, but they must be communicated via some other mechanism."
},
"expiry": {
"description": "Expiration time in seconds",