mirror of
https://github.com/aljazceru/btcpayserver.git
synced 2026-02-23 15:14:49 +01:00
Formatting code to align with .editorconfig
This commit is contained in:
@@ -10,9 +10,12 @@ namespace BTCPayServer.Payments.Lightning
|
||||
{
|
||||
public static bool IsConfigured(this LightningPaymentMethodConfig supportedPaymentMethod, BTCPayNetwork network, LightningNetworkOptions options)
|
||||
{
|
||||
return supportedPaymentMethod.GetExternalLightningUrl() is not null || (supportedPaymentMethod.IsInternalNode && options.InternalLightningByCryptoCode.ContainsKey(network.CryptoCode));
|
||||
return supportedPaymentMethod.GetExternalLightningUrl() is not null ||
|
||||
(supportedPaymentMethod.IsInternalNode && options.InternalLightningByCryptoCode.ContainsKey(network.CryptoCode));
|
||||
}
|
||||
public static ILightningClient CreateLightningClient(this LightningPaymentMethodConfig supportedPaymentMethod, BTCPayNetwork network, LightningNetworkOptions options, LightningClientFactoryService lightningClientFactory)
|
||||
|
||||
public static ILightningClient CreateLightningClient(this LightningPaymentMethodConfig supportedPaymentMethod, BTCPayNetwork network,
|
||||
LightningNetworkOptions options, LightningClientFactoryService lightningClientFactory)
|
||||
{
|
||||
var external = supportedPaymentMethod.GetExternalLightningUrl();
|
||||
if (external != null)
|
||||
|
||||
@@ -26,6 +26,7 @@ namespace BTCPayServer.Payments.Lightning
|
||||
{
|
||||
new LightningPaymentData ParsePaymentDetails(JToken details);
|
||||
}
|
||||
|
||||
public class LightningLikePaymentHandler : IPaymentMethodHandler, ILightningPaymentHandler
|
||||
{
|
||||
public JsonSerializer Serializer { get; }
|
||||
@@ -73,6 +74,7 @@ namespace BTCPayServer.Payments.Lightning
|
||||
|
||||
public BTCPayNetwork Network => _Network;
|
||||
static LightMoney OneSat = LightMoney.FromUnit(1.0m, LightMoneyUnit.Satoshi);
|
||||
|
||||
public async Task ConfigurePrompt(PaymentMethodContext context)
|
||||
{
|
||||
if (context.InvoiceEntity.Type == InvoiceType.TopUp)
|
||||
@@ -101,8 +103,8 @@ namespace BTCPayServer.Payments.Lightning
|
||||
|
||||
string description = storeBlob.LightningDescriptionTemplate;
|
||||
description = description.Replace("{StoreName}", store.StoreName ?? "", StringComparison.OrdinalIgnoreCase)
|
||||
.Replace("{ItemDescription}", invoice.Metadata.ItemDesc ?? "", StringComparison.OrdinalIgnoreCase)
|
||||
.Replace("{OrderId}", invoice.Metadata.OrderId ?? "", StringComparison.OrdinalIgnoreCase);
|
||||
.Replace("{ItemDescription}", invoice.Metadata.ItemDesc ?? "", StringComparison.OrdinalIgnoreCase)
|
||||
.Replace("{OrderId}", invoice.Metadata.OrderId ?? "", StringComparison.OrdinalIgnoreCase);
|
||||
using (var cts = new CancellationTokenSource(LightningTimeout))
|
||||
{
|
||||
try
|
||||
@@ -139,7 +141,8 @@ namespace BTCPayServer.Payments.Lightning
|
||||
}
|
||||
|
||||
|
||||
public async Task<NodeInfo[]> GetNodeInfo(LightningPaymentMethodConfig supportedPaymentMethod, PrefixedInvoiceLogs? invoiceLogs, bool? preferOnion = null, bool throws = false)
|
||||
public async Task<NodeInfo[]> GetNodeInfo(LightningPaymentMethodConfig supportedPaymentMethod, PrefixedInvoiceLogs? invoiceLogs,
|
||||
bool? preferOnion = null, bool throws = false)
|
||||
{
|
||||
var synced = _Dashboard.IsFullySynched(_Network.CryptoCode, out var summary);
|
||||
if (supportedPaymentMethod.IsInternalNode && !synced)
|
||||
@@ -193,6 +196,7 @@ namespace BTCPayServer.Payments.Lightning
|
||||
$"The lightning node is not synched ({blocksGap} blocks left)");
|
||||
}
|
||||
}
|
||||
|
||||
return nodeInfo;
|
||||
}
|
||||
catch (Exception e) when (!throws)
|
||||
@@ -222,30 +226,37 @@ namespace BTCPayServer.Payments.Lightning
|
||||
throw new PaymentMethodUnavailableException($"Error while connecting to the lightning node via {nodeInfo.Host}:{nodeInfo.Port} ({ex.Message})");
|
||||
}
|
||||
}
|
||||
|
||||
public LightningPaymentMethodConfig ParsePaymentMethodConfig(JToken config)
|
||||
{
|
||||
return config.ToObject<LightningPaymentMethodConfig>(Serializer) ?? throw new FormatException($"Invalid {nameof(LightningPaymentMethodConfig)}");
|
||||
}
|
||||
|
||||
object IPaymentMethodHandler.ParsePaymentMethodConfig(JToken config)
|
||||
{
|
||||
return ParsePaymentMethodConfig(config);
|
||||
}
|
||||
|
||||
object IPaymentMethodHandler.ParsePaymentPromptDetails(JToken details)
|
||||
{
|
||||
return ParsePaymentPromptDetails(details);
|
||||
}
|
||||
|
||||
public LigthningPaymentPromptDetails ParsePaymentPromptDetails(JToken details)
|
||||
{
|
||||
return details.ToObject<LigthningPaymentPromptDetails>(Serializer) ?? throw new FormatException($"Invalid {nameof(LigthningPaymentPromptDetails)}");
|
||||
}
|
||||
|
||||
public LightningPaymentData ParsePaymentDetails(JToken details)
|
||||
{
|
||||
return details.ToObject<LightningPaymentData>(Serializer) ?? throw new FormatException($"Invalid {nameof(LightningPaymentData)}");
|
||||
}
|
||||
|
||||
object IPaymentMethodHandler.ParsePaymentDetails(JToken details)
|
||||
{
|
||||
return ParsePaymentDetails(details);
|
||||
}
|
||||
|
||||
public async Task ValidatePaymentMethodConfig(PaymentMethodConfigValidationContext validationContext)
|
||||
{
|
||||
if (validationContext.Config is JValue { Type: JTokenType.String })
|
||||
@@ -273,13 +284,15 @@ namespace BTCPayServer.Payments.Lightning
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!client.IsSafe(config.ConnectionString))
|
||||
{
|
||||
var canManage = (await validationContext.AuthorizationService.AuthorizeAsync(validationContext.User, null,
|
||||
new PolicyRequirement(Policies.CanModifyServerSettings))).Succeeded;
|
||||
new PolicyRequirement(Policies.CanModifyServerSettings))).Succeeded;
|
||||
if (!canManage)
|
||||
{
|
||||
validationContext.ModelState.AddModelError(nameof(config.ConnectionString), $"You do not have 'btcpay.server.canmodifyserversettings' rights, so the connection string should not contain 'cookiefilepath', 'macaroondirectorypath', 'macaroonfilepath', and should not point to a local ip or to a dns name ending with '.internal', '.local', '.lan' or '.'.");
|
||||
validationContext.ModelState.AddModelError(nameof(config.ConnectionString),
|
||||
$"You do not have 'btcpay.server.canmodifyserversettings' rights, so the connection string should not contain 'cookiefilepath', 'macaroondirectorypath', 'macaroonfilepath', and should not point to a local ip or to a dns name ending with '.internal', '.local', '.lan' or '.'.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -299,11 +312,13 @@ namespace BTCPayServer.Payments.Lightning
|
||||
if (oldConfig?.IsInternalNode != config.IsInternalNode && config.IsInternalNode)
|
||||
{
|
||||
var canUseInternalNode = _policies.Settings.AllowLightningInternalNodeForAll ||
|
||||
(await validationContext.AuthorizationService.AuthorizeAsync(validationContext.User, null,
|
||||
new PolicyRequirement(Policies.CanUseInternalLightningNode))).Succeeded && _lightningNetworkOptions.Value.InternalLightningByCryptoCode.ContainsKey(_Network.CryptoCode);
|
||||
(await validationContext.AuthorizationService.AuthorizeAsync(validationContext.User, null,
|
||||
new PolicyRequirement(Policies.CanUseInternalLightningNode))).Succeeded &&
|
||||
_lightningNetworkOptions.Value.InternalLightningByCryptoCode.ContainsKey(_Network.CryptoCode);
|
||||
if (!canUseInternalNode)
|
||||
{
|
||||
validationContext.SetMissingPermission(Policies.CanUseInternalLightningNode, $"You are not authorized to use the internal lightning node. Either add '{Policies.CanUseInternalLightningNode}' to an API Key, or allow non-admin users to use the internal lightning node in the server settings.");
|
||||
validationContext.SetMissingPermission(Policies.CanUseInternalLightningNode,
|
||||
$"You are not authorized to use the internal lightning node. Either add '{Policies.CanUseInternalLightningNode}' to an API Key, or allow non-admin users to use the internal lightning node in the server settings.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -313,6 +328,7 @@ namespace BTCPayServer.Payments.Lightning
|
||||
validationContext.ModelState.AddModelError(nameof(config.ConnectionString), "The connection string or setting the internal node is required");
|
||||
return;
|
||||
}
|
||||
|
||||
validationContext.Config = JToken.FromObject(config, Serializer);
|
||||
#pragma warning restore CS0618 // Type or member is obsolete
|
||||
}
|
||||
|
||||
@@ -40,18 +40,18 @@ namespace BTCPayServer.Payments.Lightning
|
||||
private readonly PaymentMethodHandlerDictionary _handlers;
|
||||
readonly Channel<string> _CheckInvoices = Channel.CreateUnbounded<string>();
|
||||
Task? _CheckingInvoice;
|
||||
readonly Dictionary<(string, string), LightningInstanceListener> _InstanceListeners = new Dictionary<(string, string), LightningInstanceListener>();
|
||||
readonly Dictionary<(string, string), LightningInstanceListener> _InstanceListeners = new();
|
||||
|
||||
public LightningListener(EventAggregator aggregator,
|
||||
InvoiceRepository invoiceRepository,
|
||||
IMemoryCache memoryCache,
|
||||
BTCPayNetworkProvider networkProvider,
|
||||
LightningClientFactoryService lightningClientFactory,
|
||||
StoreRepository storeRepository,
|
||||
IOptions<LightningNetworkOptions> options,
|
||||
PaymentService paymentService,
|
||||
PaymentMethodHandlerDictionary paymentMethodHandlerDictionary,
|
||||
Logs logs)
|
||||
InvoiceRepository invoiceRepository,
|
||||
IMemoryCache memoryCache,
|
||||
BTCPayNetworkProvider networkProvider,
|
||||
LightningClientFactoryService lightningClientFactory,
|
||||
StoreRepository storeRepository,
|
||||
IOptions<LightningNetworkOptions> options,
|
||||
PaymentService paymentService,
|
||||
PaymentMethodHandlerDictionary paymentMethodHandlerDictionary,
|
||||
Logs logs)
|
||||
{
|
||||
Logs = logs;
|
||||
_Aggregator = aggregator;
|
||||
@@ -66,12 +66,13 @@ namespace BTCPayServer.Payments.Lightning
|
||||
}
|
||||
|
||||
bool needCheckOfflinePayments = true;
|
||||
|
||||
async Task CheckingInvoice(CancellationToken cancellation)
|
||||
{
|
||||
var pmis = _handlers.Where(h => h is LightningLikePaymentHandler).Select(handler => handler.PaymentMethodId).ToArray();
|
||||
foreach (var pmi in pmis)
|
||||
{
|
||||
retry:
|
||||
retry:
|
||||
try
|
||||
{
|
||||
Logs.PayServer.LogInformation("Checking if any payment arrived on lightning while the server was offline...");
|
||||
@@ -83,13 +84,13 @@ retry:
|
||||
_memoryCache.Set(GetCacheKey(invoice.Id), invoice, GetExpiration(invoice));
|
||||
}
|
||||
}
|
||||
|
||||
needCheckOfflinePayments = false;
|
||||
Logs.PayServer.LogInformation("Processing lightning payments...");
|
||||
|
||||
|
||||
|
||||
while (await _CheckInvoices.Reader.WaitToReadAsync(cancellation) &&
|
||||
_CheckInvoices.Reader.TryRead(out var invoiceId))
|
||||
_CheckInvoices.Reader.TryRead(out var invoiceId))
|
||||
{
|
||||
var invoice = await GetInvoice(invoiceId);
|
||||
|
||||
@@ -107,9 +108,11 @@ retry:
|
||||
{
|
||||
if (!_InstanceListeners.TryGetValue(instanceListenerKey, out var instanceListener))
|
||||
{
|
||||
instanceListener ??= new LightningInstanceListener(_InvoiceRepository, _Aggregator, lightningClientFactory, listenedInvoice.Network, _handlers, connStr, _paymentService, Logs);
|
||||
instanceListener ??= new LightningInstanceListener(_InvoiceRepository, _Aggregator, lightningClientFactory,
|
||||
listenedInvoice.Network, _handlers, connStr, _paymentService, Logs);
|
||||
_InstanceListeners.TryAdd(instanceListenerKey, instanceListener);
|
||||
}
|
||||
|
||||
instanceListener.AddListenedInvoice(listenedInvoice);
|
||||
_ = instanceListener.PollPayment(listenedInvoice, cancellation);
|
||||
}
|
||||
@@ -135,6 +138,7 @@ retry:
|
||||
{
|
||||
return $"{nameof(GetListenedInvoices)}-{invoiceId}";
|
||||
}
|
||||
|
||||
private Task<InvoiceEntity> GetInvoice(string invoiceId)
|
||||
{
|
||||
return _memoryCache.GetOrCreateAsync(GetCacheKey(invoiceId), async (cacheEntry) =>
|
||||
@@ -176,6 +180,7 @@ retry:
|
||||
yield return (handler, prompt, handler.ParsePaymentPromptDetails(prompt.Details));
|
||||
}
|
||||
}
|
||||
|
||||
private List<ListenedInvoice> GetListenedInvoices(InvoiceEntity invoice)
|
||||
{
|
||||
var listenedInvoices = new List<ListenedInvoice>();
|
||||
@@ -190,11 +195,13 @@ retry:
|
||||
((IHasNetwork)o.Handler).Network,
|
||||
invoice.Id));
|
||||
}
|
||||
|
||||
return listenedInvoices;
|
||||
}
|
||||
|
||||
readonly ConcurrentDictionary<string, LightningInstanceListener> _ListeningInstances = new ConcurrentDictionary<string, LightningInstanceListener>();
|
||||
readonly CompositeDisposable leases = new CompositeDisposable();
|
||||
|
||||
public Task StartAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
leases.Add(_Aggregator.SubscribeAsync<Events.InvoiceEvent>(async inv =>
|
||||
@@ -204,7 +211,8 @@ retry:
|
||||
_CheckInvoices.Writer.TryWrite(inv.Invoice.Id);
|
||||
}
|
||||
|
||||
if (inv.Name == InvoiceEvent.ReceivedPayment && inv.Invoice.Status == InvoiceStatus.New && inv.Invoice.ExceptionStatus == InvoiceExceptionStatus.PaidPartial)
|
||||
if (inv.Name == InvoiceEvent.ReceivedPayment && inv.Invoice.Status == InvoiceStatus.New &&
|
||||
inv.Invoice.ExceptionStatus == InvoiceExceptionStatus.PaidPartial)
|
||||
{
|
||||
var pm = inv.Invoice.GetPaymentPrompts().First();
|
||||
if (pm.Calculate().Due > 0m)
|
||||
@@ -221,7 +229,6 @@ retry:
|
||||
var invoice = await _InvoiceRepository.GetInvoice(inv.InvoiceId);
|
||||
await CreateNewLNInvoiceForBTCPayInvoice(invoice);
|
||||
}
|
||||
|
||||
}));
|
||||
leases.Add(_Aggregator.Subscribe<Events.InvoicePaymentMethodActivated>(inv =>
|
||||
{
|
||||
@@ -249,7 +256,6 @@ retry:
|
||||
CheckConnections();
|
||||
}
|
||||
catch { }
|
||||
|
||||
}, null, 0, (int)PollInterval.TotalMilliseconds);
|
||||
leases.Add(_ListenPoller);
|
||||
return Task.CompletedTask;
|
||||
@@ -318,10 +324,10 @@ retry:
|
||||
{
|
||||
//not a fully supported option
|
||||
}
|
||||
|
||||
lnurlPayPaymentMethodDetails = new LNURLPayPaymentMethodDetails()
|
||||
{
|
||||
Bech32Mode = lnurlPayPaymentMethodDetails.Bech32Mode,
|
||||
NodeInfo = lnurlPayPaymentMethodDetails.NodeInfo,
|
||||
Bech32Mode = lnurlPayPaymentMethodDetails.Bech32Mode, NodeInfo = lnurlPayPaymentMethodDetails.NodeInfo,
|
||||
};
|
||||
|
||||
o.PaymentPrompt.Destination = null;
|
||||
@@ -344,7 +350,8 @@ retry:
|
||||
//not a fully supported option
|
||||
}
|
||||
|
||||
var paymentContext = new PaymentMethodContext(store, store.GetStoreBlob(), JToken.FromObject(lnConfig, _handlers.GetLightningHandler(network).Serializer), lightningHandler, invoice, logs);
|
||||
var paymentContext = new PaymentMethodContext(store, store.GetStoreBlob(),
|
||||
JToken.FromObject(lnConfig, _handlers.GetLightningHandler(network).Serializer), lightningHandler, invoice, logs);
|
||||
var paymentPrompt = paymentContext.Prompt;
|
||||
await paymentContext.BeforeFetchingRates();
|
||||
await paymentContext.CreatePaymentPrompt();
|
||||
@@ -356,6 +363,7 @@ retry:
|
||||
{
|
||||
_InstanceListeners.TryGetValue(instanceListenerKey, out instanceListener);
|
||||
}
|
||||
|
||||
if (instanceListener is not null)
|
||||
{
|
||||
await _InvoiceRepository.NewPaymentPrompt(invoice.Id, paymentContext);
|
||||
@@ -377,10 +385,10 @@ retry:
|
||||
InvoiceEventData.EventSeverity.Error);
|
||||
}
|
||||
}
|
||||
|
||||
await _InvoiceRepository.AddInvoiceLogs(invoice.Id, logs);
|
||||
_CheckInvoices.Writer.TryWrite(invoice.Id);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private string? GetLightningUrl(string cryptoCode, LightningPaymentMethodConfig supportedMethod)
|
||||
@@ -392,6 +400,7 @@ retry:
|
||||
}
|
||||
|
||||
TimeSpan _PollInterval = TimeSpan.FromMinutes(1.0);
|
||||
|
||||
public TimeSpan PollInterval
|
||||
{
|
||||
get
|
||||
@@ -407,6 +416,7 @@ retry:
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Timer? _ListenPoller;
|
||||
|
||||
public IOptions<LightningNetworkOptions> Options { get; }
|
||||
@@ -424,16 +434,16 @@ retry:
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
await Task.WhenAll(_ListeningInstances.Select(c => c.Value.Listening).Where(c => c != null).ToArray()!);
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
Logs.PayServer.LogInformation($"{this.GetType().Name} successfully exited...");
|
||||
}
|
||||
}
|
||||
@@ -453,13 +463,13 @@ retry:
|
||||
public string ConnectionString { get; }
|
||||
|
||||
public LightningInstanceListener(InvoiceRepository invoiceRepository,
|
||||
EventAggregator eventAggregator,
|
||||
LightningClientFactoryService lightningClientFactory,
|
||||
BTCPayNetwork network,
|
||||
PaymentMethodHandlerDictionary handlers,
|
||||
string connectionString,
|
||||
PaymentService paymentService,
|
||||
Logs logs)
|
||||
EventAggregator eventAggregator,
|
||||
LightningClientFactoryService lightningClientFactory,
|
||||
BTCPayNetwork network,
|
||||
PaymentMethodHandlerDictionary handlers,
|
||||
string connectionString,
|
||||
PaymentService paymentService,
|
||||
Logs logs)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(connectionString);
|
||||
Logs = logs;
|
||||
@@ -471,6 +481,7 @@ retry:
|
||||
_lightningClientFactory = lightningClientFactory;
|
||||
ConnectionString = connectionString;
|
||||
}
|
||||
|
||||
internal bool AddListenedInvoice(ListenedInvoice invoice)
|
||||
{
|
||||
return _ListenedInvoices.TryAdd(invoice.PaymentMethodDetails.InvoiceId, invoice);
|
||||
@@ -485,12 +496,14 @@ retry:
|
||||
{
|
||||
Logs.PayServer.LogInformation($"{_network.CryptoCode} (Lightning): Payment detected via polling on {listenedInvoice.InvoiceId}");
|
||||
}
|
||||
|
||||
return lightningInvoice?.Status;
|
||||
}
|
||||
|
||||
public bool Empty => _ListenedInvoices.IsEmpty;
|
||||
public bool IsListening => Listening?.Status is TaskStatus.Running || Listening?.Status is TaskStatus.WaitingForActivation;
|
||||
public Task? Listening { get; set; }
|
||||
|
||||
public void EnsureListening(CancellationToken cancellation)
|
||||
{
|
||||
if (!IsListening)
|
||||
@@ -501,14 +514,16 @@ retry:
|
||||
Listening = Listen(StopListeningCancellationTokenSource.Token);
|
||||
}
|
||||
}
|
||||
|
||||
public CancellationTokenSource? StopListeningCancellationTokenSource;
|
||||
|
||||
async Task Listen(CancellationToken cancellation)
|
||||
{
|
||||
string? uri = null;
|
||||
try
|
||||
{
|
||||
var lightningClient = _lightningClientFactory.Create(ConnectionString, _network);
|
||||
if(lightningClient is null)
|
||||
if (lightningClient is null)
|
||||
return;
|
||||
uri = lightningClient.GetServerUri(ConnectionString)?.RemoveUserInfo() ?? "";
|
||||
Logs.PayServer.LogInformation("{CryptoCode} (Lightning): Start listening {Uri}", _network.CryptoCode, uri);
|
||||
@@ -519,6 +534,7 @@ retry:
|
||||
{
|
||||
Logs.PayServer.LogInformation("{CryptoCode} (Lightning): Could reconnect successfully to {Uri}", _network.CryptoCode, uri);
|
||||
}
|
||||
|
||||
_ErrorAlreadyLogged = false;
|
||||
while (!_ListenedInvoices.IsEmpty)
|
||||
{
|
||||
@@ -534,8 +550,10 @@ retry:
|
||||
{
|
||||
if (await AddPayment(notification, listenedInvoice.InvoiceId, listenedInvoice.PaymentMethod.PaymentMethodId))
|
||||
{
|
||||
Logs.PayServer.LogInformation("{CryptoCode} (Lightning): Payment detected via notification ({InvoiceId})", _network.CryptoCode, listenedInvoice.InvoiceId);
|
||||
Logs.PayServer.LogInformation("{CryptoCode} (Lightning): Payment detected via notification ({InvoiceId})", _network.CryptoCode,
|
||||
listenedInvoice.InvoiceId);
|
||||
}
|
||||
|
||||
_ListenedInvoices.TryRemove(notification.Id, out var _);
|
||||
}
|
||||
else if (notification.Status == LightningInvoiceStatus.Expired)
|
||||
@@ -552,8 +570,10 @@ retry:
|
||||
Logs.PayServer.LogInformation("{CryptoCode} (Lightning): Stop listening {Uri}", _network.CryptoCode, uri);
|
||||
}
|
||||
catch (OperationCanceledException) when (cancellation.IsCancellationRequested) { }
|
||||
|
||||
if (_ListenedInvoices.IsEmpty)
|
||||
Logs.PayServer.LogInformation("{CryptoCode} (Lightning): No more invoice to listen on {Uri}, releasing the connection", _network.CryptoCode, uri);
|
||||
Logs.PayServer.LogInformation("{CryptoCode} (Lightning): No more invoice to listen on {Uri}, releasing the connection", _network.CryptoCode,
|
||||
uri);
|
||||
}
|
||||
|
||||
private uint256? GetPaymentHash(ListenedInvoice listenedInvoice)
|
||||
@@ -570,10 +590,11 @@ retry:
|
||||
{
|
||||
var status = await PollPayment(invoice, cancellation);
|
||||
if (status is null ||
|
||||
status is LightningInvoiceStatus.Paid ||
|
||||
status is LightningInvoiceStatus.Expired)
|
||||
status is LightningInvoiceStatus.Paid ||
|
||||
status is LightningInvoiceStatus.Expired)
|
||||
_ListenedInvoices.TryRemove(invoice.PaymentMethodDetails.InvoiceId, out var _);
|
||||
}
|
||||
|
||||
LastFullPoll = DateTimeOffset.UtcNow;
|
||||
if (_ListenedInvoices.IsEmpty)
|
||||
{
|
||||
@@ -600,28 +621,31 @@ retry:
|
||||
Currency = _network.CryptoCode,
|
||||
InvoiceDataId = invoiceId,
|
||||
Amount = (notification.AmountReceived ?? notification.Amount).ToDecimal(LightMoneyUnit.BTC),
|
||||
}.Set(invoiceEntity, handler, new LightningLikePaymentData()
|
||||
{
|
||||
PaymentHash = paymentHash,
|
||||
Preimage = string.IsNullOrEmpty(notification.Preimage) ? null : uint256.Parse(notification.Preimage),
|
||||
});
|
||||
}.Set(invoiceEntity, handler,
|
||||
new LightningLikePaymentData()
|
||||
{
|
||||
PaymentHash = paymentHash, Preimage = string.IsNullOrEmpty(notification.Preimage) ? null : uint256.Parse(notification.Preimage),
|
||||
});
|
||||
|
||||
var payment = await _paymentService.AddPayment(paymentData, [notification.BOLT11]);
|
||||
if (payment != null)
|
||||
{
|
||||
if (notification.Preimage is not null)
|
||||
{
|
||||
var details = (LigthningPaymentPromptDetails)handler.ParsePaymentPromptDetails(invoiceEntity.GetPaymentPrompt(handler.PaymentMethodId)!.Details);
|
||||
var details = (LigthningPaymentPromptDetails)handler.ParsePaymentPromptDetails(invoiceEntity.GetPaymentPrompt(handler.PaymentMethodId)!
|
||||
.Details);
|
||||
if (details.Preimage is null)
|
||||
{
|
||||
details.Preimage = uint256.Parse(notification.Preimage);
|
||||
await _invoiceRepository.UpdatePaymentDetails(invoiceId, handler, details);
|
||||
}
|
||||
}
|
||||
|
||||
var invoice = await _invoiceRepository.GetInvoice(invoiceId);
|
||||
if (invoice != null)
|
||||
_eventAggregator.Publish(new InvoiceEvent(invoice, InvoiceEvent.ReceivedPayment) { Payment = payment });
|
||||
}
|
||||
|
||||
return payment != null;
|
||||
}
|
||||
|
||||
@@ -632,17 +656,18 @@ retry:
|
||||
if (invoice.Value.IsExpired())
|
||||
_ListenedInvoices.TryRemove(invoice.Key, out var _);
|
||||
}
|
||||
|
||||
if (_ListenedInvoices.IsEmpty)
|
||||
StopListeningCancellationTokenSource?.Cancel();
|
||||
}
|
||||
}
|
||||
|
||||
public record ListenedInvoice(
|
||||
DateTimeOffset Expiration,
|
||||
LigthningPaymentPromptDetails PaymentMethodDetails,
|
||||
PaymentPrompt PaymentMethod,
|
||||
BTCPayNetwork Network,
|
||||
string InvoiceId)
|
||||
DateTimeOffset Expiration,
|
||||
LigthningPaymentPromptDetails PaymentMethodDetails,
|
||||
PaymentPrompt PaymentMethod,
|
||||
BTCPayNetwork Network,
|
||||
string InvoiceId)
|
||||
{
|
||||
public bool IsExpired() { return DateTimeOffset.UtcNow > Expiration; }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user