mirror of
https://github.com/btcpayserver/btcpayserver.git
synced 2024-11-19 09:54:30 +01:00
[Greenfield]: Add DescriptionHashOnly to include a description hash in the BOLT11 (#4411)
* [Greenfield]: Add DescriptionHashOnly to include a description hash in the BOLT11 * Add CLN test case * Improve description in Swagger file Co-authored-by: Dennis Reimann <mail@dennisreimann.de>
This commit is contained in:
parent
e2c5e2c7fb
commit
cdac238f6d
@ -28,7 +28,7 @@
|
||||
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="BTCPayServer.Lightning.Common" Version="1.3.16" />
|
||||
<PackageReference Include="BTCPayServer.Lightning.Common" Version="1.3.17" />
|
||||
<PackageReference Include="NBitcoin" Version="7.0.20" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
||||
</ItemGroup>
|
||||
|
@ -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; }
|
||||
|
@ -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()
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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",
|
||||
|
Loading…
Reference in New Issue
Block a user