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" />
|
||||
</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="Newtonsoft.Json" Version="13.0.1" />
|
||||
</ItemGroup>
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
using System;
|
||||
using BTCPayServer.Client.JsonConverters;
|
||||
using BTCPayServer.JsonConverters;
|
||||
using BTCPayServer.Lightning;
|
||||
|
@ -19,5 +20,8 @@ namespace BTCPayServer.Client.Models
|
|||
|
||||
[JsonConverter(typeof(LightMoneyJsonConverter))]
|
||||
public LightMoney Amount { get; set; }
|
||||
|
||||
[JsonConverter(typeof(TimeSpanJsonConverter.Seconds))]
|
||||
public TimeSpan? SendTimeout { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,7 +41,7 @@
|
|||
<ItemGroup>
|
||||
<PackageReference Include="BIP78.Sender" Version="0.2.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="Dapper" Version="2.0.123" />
|
||||
<PackageReference Include="Fido2" Version="2.0.2" />
|
||||
|
|
|
@ -2,7 +2,6 @@ using System;
|
|||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using BTCPayServer.Abstractions.Contracts;
|
||||
using BTCPayServer.Abstractions.Extensions;
|
||||
using BTCPayServer.Client;
|
||||
using BTCPayServer.Client.Models;
|
||||
|
@ -222,16 +221,26 @@ namespace BTCPayServer.Controllers.Greenfield
|
|||
return this.CreateValidationError(ModelState);
|
||||
}
|
||||
|
||||
var param = lightningInvoice.MaxFeeFlat != null || lightningInvoice.MaxFeePercent != null || lightningInvoice.Amount != null
|
||||
? new PayInvoiceParams { MaxFeePercent = lightningInvoice.MaxFeePercent, MaxFeeFlat = lightningInvoice.MaxFeeFlat, Amount = lightningInvoice.Amount }
|
||||
var param = lightningInvoice.MaxFeeFlat != null || lightningInvoice.MaxFeePercent != null
|
||||
|| lightningInvoice.Amount != null || lightningInvoice.SendTimeout != null
|
||||
? new PayInvoiceParams
|
||||
{
|
||||
MaxFeePercent = lightningInvoice.MaxFeePercent,
|
||||
MaxFeeFlat = lightningInvoice.MaxFeeFlat,
|
||||
Amount = lightningInvoice.Amount,
|
||||
SendTimeout = lightningInvoice.SendTimeout
|
||||
}
|
||||
: null;
|
||||
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 payment = await lightningClient.GetPayment(paymentHash, cancellationToken);
|
||||
return Ok(new LightningPaymentData
|
||||
var data = new LightningPaymentData
|
||||
{
|
||||
Id = payment.Id,
|
||||
PaymentHash = paymentHash,
|
||||
|
@ -241,19 +250,25 @@ namespace BTCPayServer.Controllers.Greenfield
|
|||
CreatedAt = payment.CreatedAt,
|
||||
TotalAmount = payment.AmountSent,
|
||||
FeeAmount = payment.Fee,
|
||||
});
|
||||
};
|
||||
return result.Result is PayResult.Ok ? Ok(data) : Accepted(data);
|
||||
}
|
||||
|
||||
return result.Result switch
|
||||
{
|
||||
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.Unknown => Accepted(new LightningPaymentData
|
||||
{
|
||||
Status = LightningPaymentStatus.Unknown
|
||||
}),
|
||||
PayResult.Ok => Ok(new LightningPaymentData
|
||||
{
|
||||
Status = LightningPaymentStatus.Complete,
|
||||
TotalAmount = result.Details?.TotalAmount,
|
||||
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()};
|
||||
try
|
||||
{
|
||||
// TODO: Incorporate the changes from this PR here:
|
||||
// https://github.com/btcpayserver/BTCPayServer.Lightning/pull/106
|
||||
using var cts = new CancellationTokenSource(SendTimeout);
|
||||
var result = await lightningClient.Pay(bolt11PaymentRequest.ToString(),
|
||||
new PayInvoiceParams()
|
||||
|
|
|
@ -100,7 +100,6 @@
|
|||
},
|
||||
"TimeSpanSeconds": {
|
||||
"allOf": [ { "$ref": "#/components/schemas/TimeSpan" } ],
|
||||
|
||||
"format": "seconds",
|
||||
"description": "A span of times in seconds"
|
||||
},
|
||||
|
|
|
@ -323,6 +323,17 @@
|
|||
"nullable": true,
|
||||
"description": "The fee limit expressed as a fixed amount in satoshi",
|
||||
"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"
|
||||
}
|
||||
],
|
||||
"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",
|
||||
"responses": {
|
||||
"200": {
|
||||
|
@ -478,6 +478,16 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"202": {
|
||||
"description": "Payment initiated",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/LightningPaymentData"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"422": {
|
||||
"description": "Unable to validate the request",
|
||||
"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",
|
||||
"responses": {
|
||||
"200": {
|
||||
|
@ -561,6 +561,16 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"202": {
|
||||
"description": "Payment initiated",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/LightningPaymentData"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"422": {
|
||||
"description": "Unable to validate the request",
|
||||
"content": {
|
||||
|
|
Loading…
Add table
Reference in a new issue