mirror of
https://github.com/btcpayserver/btcpayserver.git
synced 2025-02-22 14:22:40 +01:00
Greenfield: Graceful return for in-flight HTLCs (#4252)
* Greenfield: Graceful return for in-flight HTLCs Based on btcpayserver/BTCPayServer.Lightning#106 this closes #3781. * Update descriptions
This commit is contained in:
parent
05232414ad
commit
e56cbf0baa
9 changed files with 63 additions and 12 deletions
|
@ -28,7 +28,7 @@
|
||||||
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All" />
|
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="BTCPayServer.Lightning.Common" Version="1.3.13" />
|
<PackageReference Include="BTCPayServer.Lightning.Common" Version="1.3.15" />
|
||||||
<PackageReference Include="NBitcoin" Version="7.0.14" />
|
<PackageReference Include="NBitcoin" Version="7.0.14" />
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
using System;
|
||||||
using BTCPayServer.Client.JsonConverters;
|
using BTCPayServer.Client.JsonConverters;
|
||||||
using BTCPayServer.JsonConverters;
|
using BTCPayServer.JsonConverters;
|
||||||
using BTCPayServer.Lightning;
|
using BTCPayServer.Lightning;
|
||||||
|
@ -19,5 +20,8 @@ namespace BTCPayServer.Client.Models
|
||||||
|
|
||||||
[JsonConverter(typeof(LightMoneyJsonConverter))]
|
[JsonConverter(typeof(LightMoneyJsonConverter))]
|
||||||
public LightMoney Amount { get; set; }
|
public LightMoney Amount { get; set; }
|
||||||
|
|
||||||
|
[JsonConverter(typeof(TimeSpanJsonConverter.Seconds))]
|
||||||
|
public TimeSpan? SendTimeout { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,7 +41,7 @@
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="BIP78.Sender" Version="0.2.2" />
|
<PackageReference Include="BIP78.Sender" Version="0.2.2" />
|
||||||
<PackageReference Include="BTCPayServer.Hwi" Version="2.0.2" />
|
<PackageReference Include="BTCPayServer.Hwi" Version="2.0.2" />
|
||||||
<PackageReference Include="BTCPayServer.Lightning.All" Version="1.4.7" />
|
<PackageReference Include="BTCPayServer.Lightning.All" Version="1.4.8" />
|
||||||
<PackageReference Include="CsvHelper" Version="15.0.5" />
|
<PackageReference Include="CsvHelper" Version="15.0.5" />
|
||||||
<PackageReference Include="Dapper" Version="2.0.123" />
|
<PackageReference Include="Dapper" Version="2.0.123" />
|
||||||
<PackageReference Include="Fido2" Version="2.0.2" />
|
<PackageReference Include="Fido2" Version="2.0.2" />
|
||||||
|
|
|
@ -2,7 +2,6 @@ using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using BTCPayServer.Abstractions.Contracts;
|
|
||||||
using BTCPayServer.Abstractions.Extensions;
|
using BTCPayServer.Abstractions.Extensions;
|
||||||
using BTCPayServer.Client;
|
using BTCPayServer.Client;
|
||||||
using BTCPayServer.Client.Models;
|
using BTCPayServer.Client.Models;
|
||||||
|
@ -222,16 +221,26 @@ namespace BTCPayServer.Controllers.Greenfield
|
||||||
return this.CreateValidationError(ModelState);
|
return this.CreateValidationError(ModelState);
|
||||||
}
|
}
|
||||||
|
|
||||||
var param = lightningInvoice.MaxFeeFlat != null || lightningInvoice.MaxFeePercent != null || lightningInvoice.Amount != null
|
var param = lightningInvoice.MaxFeeFlat != null || lightningInvoice.MaxFeePercent != null
|
||||||
? new PayInvoiceParams { MaxFeePercent = lightningInvoice.MaxFeePercent, MaxFeeFlat = lightningInvoice.MaxFeeFlat, Amount = lightningInvoice.Amount }
|
|| lightningInvoice.Amount != null || lightningInvoice.SendTimeout != null
|
||||||
|
? new PayInvoiceParams
|
||||||
|
{
|
||||||
|
MaxFeePercent = lightningInvoice.MaxFeePercent,
|
||||||
|
MaxFeeFlat = lightningInvoice.MaxFeeFlat,
|
||||||
|
Amount = lightningInvoice.Amount,
|
||||||
|
SendTimeout = lightningInvoice.SendTimeout
|
||||||
|
}
|
||||||
: null;
|
: null;
|
||||||
var result = await lightningClient.Pay(lightningInvoice.BOLT11, param, cancellationToken);
|
var result = await lightningClient.Pay(lightningInvoice.BOLT11, param, cancellationToken);
|
||||||
|
|
||||||
if (result.Result == PayResult.Ok && bolt11?.PaymentHash is not null)
|
if (result.Result is PayResult.Ok or PayResult.Unknown && bolt11?.PaymentHash is not null)
|
||||||
{
|
{
|
||||||
|
// get a new instance of the LN client, because the old one might have disposed its HTTPClient
|
||||||
|
lightningClient = await GetLightningClient(cryptoCode, true);
|
||||||
|
|
||||||
var paymentHash = bolt11.PaymentHash.ToString();
|
var paymentHash = bolt11.PaymentHash.ToString();
|
||||||
var payment = await lightningClient.GetPayment(paymentHash, cancellationToken);
|
var payment = await lightningClient.GetPayment(paymentHash, cancellationToken);
|
||||||
return Ok(new LightningPaymentData
|
var data = new LightningPaymentData
|
||||||
{
|
{
|
||||||
Id = payment.Id,
|
Id = payment.Id,
|
||||||
PaymentHash = paymentHash,
|
PaymentHash = paymentHash,
|
||||||
|
@ -241,19 +250,25 @@ namespace BTCPayServer.Controllers.Greenfield
|
||||||
CreatedAt = payment.CreatedAt,
|
CreatedAt = payment.CreatedAt,
|
||||||
TotalAmount = payment.AmountSent,
|
TotalAmount = payment.AmountSent,
|
||||||
FeeAmount = payment.Fee,
|
FeeAmount = payment.Fee,
|
||||||
});
|
};
|
||||||
|
return result.Result is PayResult.Ok ? Ok(data) : Accepted(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
return result.Result switch
|
return result.Result switch
|
||||||
{
|
{
|
||||||
PayResult.CouldNotFindRoute => this.CreateAPIError("could-not-find-route", "Impossible to find a route to the peer"),
|
PayResult.CouldNotFindRoute => this.CreateAPIError("could-not-find-route", "Impossible to find a route to the peer"),
|
||||||
PayResult.Error => this.CreateAPIError("generic-error", result.ErrorDetail),
|
PayResult.Error => this.CreateAPIError("generic-error", result.ErrorDetail),
|
||||||
|
PayResult.Unknown => Accepted(new LightningPaymentData
|
||||||
|
{
|
||||||
|
Status = LightningPaymentStatus.Unknown
|
||||||
|
}),
|
||||||
PayResult.Ok => Ok(new LightningPaymentData
|
PayResult.Ok => Ok(new LightningPaymentData
|
||||||
{
|
{
|
||||||
|
Status = LightningPaymentStatus.Complete,
|
||||||
TotalAmount = result.Details?.TotalAmount,
|
TotalAmount = result.Details?.TotalAmount,
|
||||||
FeeAmount = result.Details?.FeeAmount
|
FeeAmount = result.Details?.FeeAmount
|
||||||
}),
|
}),
|
||||||
_ => throw new NotSupportedException("Unsupported Payresult")
|
_ => throw new NotSupportedException("Unsupported PayResult")
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -281,6 +281,8 @@ namespace BTCPayServer.Data.Payouts.LightningLike
|
||||||
var proofBlob = new PayoutLightningBlob() {PaymentHash = bolt11PaymentRequest.PaymentHash.ToString()};
|
var proofBlob = new PayoutLightningBlob() {PaymentHash = bolt11PaymentRequest.PaymentHash.ToString()};
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
// TODO: Incorporate the changes from this PR here:
|
||||||
|
// https://github.com/btcpayserver/BTCPayServer.Lightning/pull/106
|
||||||
using var cts = new CancellationTokenSource(SendTimeout);
|
using var cts = new CancellationTokenSource(SendTimeout);
|
||||||
var result = await lightningClient.Pay(bolt11PaymentRequest.ToString(),
|
var result = await lightningClient.Pay(bolt11PaymentRequest.ToString(),
|
||||||
new PayInvoiceParams()
|
new PayInvoiceParams()
|
||||||
|
|
|
@ -100,7 +100,6 @@
|
||||||
},
|
},
|
||||||
"TimeSpanSeconds": {
|
"TimeSpanSeconds": {
|
||||||
"allOf": [ { "$ref": "#/components/schemas/TimeSpan" } ],
|
"allOf": [ { "$ref": "#/components/schemas/TimeSpan" } ],
|
||||||
|
|
||||||
"format": "seconds",
|
"format": "seconds",
|
||||||
"description": "A span of times in seconds"
|
"description": "A span of times in seconds"
|
||||||
},
|
},
|
||||||
|
|
|
@ -323,6 +323,17 @@
|
||||||
"nullable": true,
|
"nullable": true,
|
||||||
"description": "The fee limit expressed as a fixed amount in satoshi",
|
"description": "The fee limit expressed as a fixed amount in satoshi",
|
||||||
"example": "21"
|
"example": "21"
|
||||||
|
},
|
||||||
|
"sendTimeout": {
|
||||||
|
"nullable": true,
|
||||||
|
"example": 30,
|
||||||
|
"default": 30,
|
||||||
|
"description": "The number of seconds after which the payment times out",
|
||||||
|
"allOf": [
|
||||||
|
{
|
||||||
|
"$ref": "#/components/schemas/TimeSpanSeconds"
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -465,7 +465,7 @@
|
||||||
"example": "BTC"
|
"example": "BTC"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"description": "Pay a lightning invoice.",
|
"description": "Pay a lightning invoice. In case the payment response times out, the status will be reported as pending and the final status can be resolved using the [Get payment](#operation/InternalLightningNodeApi_GetPayment) endpoint. The default wait time for payment responses is 30 seconds — it might take longer if multiple routes are tried or a hold invoice is getting paid.",
|
||||||
"operationId": "InternalLightningNodeApi_PayInvoice",
|
"operationId": "InternalLightningNodeApi_PayInvoice",
|
||||||
"responses": {
|
"responses": {
|
||||||
"200": {
|
"200": {
|
||||||
|
@ -478,6 +478,16 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"202": {
|
||||||
|
"description": "Payment initiated",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/LightningPaymentData"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"422": {
|
"422": {
|
||||||
"description": "Unable to validate the request",
|
"description": "Unable to validate the request",
|
||||||
"content": {
|
"content": {
|
||||||
|
|
|
@ -548,7 +548,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"description": "Pay a lightning invoice.",
|
"description": "Pay a lightning invoice. In case the payment response times out, the status will be reported as pending and the final status can be resolved using the [Get payment](#operation/StoreLightningNodeApi_GetPayment) endpoint. The default wait time for payment responses is 30 seconds — it might take longer if multiple routes are tried or a hold invoice is getting paid.",
|
||||||
"operationId": "StoreLightningNodeApi_PayInvoice",
|
"operationId": "StoreLightningNodeApi_PayInvoice",
|
||||||
"responses": {
|
"responses": {
|
||||||
"200": {
|
"200": {
|
||||||
|
@ -561,6 +561,16 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"202": {
|
||||||
|
"description": "Payment initiated",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/LightningPaymentData"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"422": {
|
"422": {
|
||||||
"description": "Unable to validate the request",
|
"description": "Unable to validate the request",
|
||||||
"content": {
|
"content": {
|
||||||
|
|
Loading…
Add table
Reference in a new issue