This commit is contained in:
Kukks 2024-07-22 11:56:26 +02:00
parent 63cd54d6fc
commit 308882234c
No known key found for this signature in database
GPG Key ID: 8E5530D9D1C93097
5 changed files with 53 additions and 81 deletions

View File

@ -3,24 +3,24 @@ using System.Collections.Generic;
using System.Threading.Tasks;
using BTCPayServer.Client.Models;
using BTCPayServer.Lightning;
using LightningPayment = BTCPayApp.CommonServer.Models.LightningPayment;
using NBitcoin;
namespace BTCPayApp.CommonServer;
//methods available on the hub in the client
public interface IBTCPayAppHubClient
{
Task NotifyServerEvent(ServerEvent ev);
Task NotifyServerEvent(IServerEvent ev);
Task NotifyNetwork(string network);
Task NotifyServerNode(string nodeInfo);
Task TransactionDetected(TransactionDetectedRequest request);
Task NewBlock(string block);
Task<LightningPayment> CreateInvoice(CreateLightningInvoiceRequest createLightningInvoiceRequest);
Task<LightningPayment?> GetLightningInvoice(string paymentHash);
Task<LightningPayment?> GetLightningPayment(string paymentHash);
Task<LightningInvoice> CreateInvoice(CreateLightningInvoiceRequest createLightningInvoiceRequest);
Task<LightningInvoice?> GetLightningInvoice(uint256 paymentHash);
Task<LightningPayment?> GetLightningPayment(uint256 paymentHash);
Task<List<LightningPayment>> GetLightningPayments(ListPaymentsParams request);
Task<List<LightningPayment>> GetLightningInvoices(ListInvoicesParams request);
Task<List<LightningInvoice>> GetLightningInvoices(ListInvoicesParams request);
Task<PayResponse> PayInvoice(string bolt11, long? amountMilliSatoshi);
}
@ -43,7 +43,7 @@ public interface IBTCPayAppHubServer
Task<CoinResponse[]> GetUTXOs(string[] identifiers);
Task<Dictionary<string, TxResp[]>> GetTransactions(string[] identifiers);
Task SendPaymentUpdate(string identifier, LightningPayment lightningPayment);
Task SendInvoiceUpdate(string identifier, LightningInvoice lightningPayment);
}
public interface IServerEvent

View File

@ -9,23 +9,23 @@ using Newtonsoft.Json;
namespace BTCPayApp.CommonServer.Models;
public partial class LightningPayment
{
public string PaymentHash { get; set; }
public string? PaymentId { get; set; }
public string? Preimage { get; set; }
public string? Secret { get; set; }
public bool Inbound { get; set; }
public DateTimeOffset Timestamp { get; set; }
public long Value { get; set; }
public LightningPaymentStatus Status { get; set; }
//you can have multiple requests generated for the same payment hash, but once you reveal the preimage, you should reject any attempt to pay the same payment hash
public List<string> PaymentRequests { get; set; }
[JsonIgnore]
public Dictionary<string, JsonDocument> AdditionalData { get; set; }
}
// public partial class LightningPayment
// {
// public string PaymentHash { get; set; }
// public string? PaymentId { get; set; }
// public string? Preimage { get; set; }
// public string? Secret { get; set; }
// public bool Inbound { get; set; }
// public DateTimeOffset Timestamp { get; set; }
// public long Value { get; set; }
// public LightningPaymentStatus Status { get; set; }
//
// //you can have multiple requests generated for the same payment hash, but once you reveal the preimage, you should reject any attempt to pay the same payment hash
// public List<string> PaymentRequests { get; set; }
// [JsonIgnore]
// public Dictionary<string, JsonDocument> AdditionalData { get; set; }
//
// }
public class AppUserInfo
{

View File

@ -10,6 +10,7 @@ using BTCPayServer.Abstractions.Constants;
using BTCPayServer.Data;
using BTCPayServer.Events;
using BTCPayServer.HostedServices;
using BTCPayServer.Lightning;
using BTCPayServer.Services;
using BTCPayServer.Services.Stores;
using BTCPayServer.Services.Wallets;
@ -311,9 +312,14 @@ public class BTCPayAppHub : Hub<IBTCPayAppHubClient>, IBTCPayAppHubServer
return result;
}
public async Task SendPaymentUpdate(string identifier, LightningPayment lightningPayment)
public async Task SendInvoiceUpdate(string identifier, LightningPayment lightningPayment)
{
await _appState.PaymentUpdate(identifier, lightningPayment);
throw new NotImplementedException();
}
public async Task SendInvoiceUpdate(string identifier, LightningInvoice lightningInvoice)
{
await _appState.InvoiceUpdate(identifier, lightningInvoice);
}
public async Task<bool> IdentifierActive(string group, bool active)

View File

@ -18,7 +18,6 @@ using Microsoft.Extensions.Logging;
using NBitcoin;
using NBXplorer;
using NBXplorer.Models;
using LightningPayment = BTCPayApp.CommonServer.Models.LightningPayment;
using NewBlockEvent = BTCPayServer.Events.NewBlockEvent;
namespace BTCPayServer.Controllers;
@ -39,7 +38,7 @@ public class BTCPayAppState : IHostedService
private CancellationTokenSource? _cts;
// private readonly ConcurrentDictionary<string, TrackedSource> _connectionScheme = new();
public event EventHandler<(string,LightningPayment)>? OnPaymentUpdate;
public event EventHandler<(string,LightningInvoice)>? OnInvoiceUpdate;
public BTCPayAppState(
IHubContext<BTCPayAppHub, IBTCPayAppHubClient> hubContext,
ILogger<BTCPayAppState> logger,
@ -283,9 +282,9 @@ public class BTCPayAppState : IHostedService
await _hubContext.Clients.Client(contextConnectionId).NotifyServerNode(_nodeInfo);
}
public async Task PaymentUpdate(string identifier, LightningPayment lightningPayment)
public async Task InvoiceUpdate(string identifier, LightningInvoice lightningInvoice)
{
_logger.LogInformation($"Payment update for {identifier} {lightningPayment.Value} {lightningPayment.PaymentHash}");
OnPaymentUpdate?.Invoke(this, (identifier, lightningPayment));
_logger.LogInformation($"Invoice update for {identifier} {lightningInvoice.Amount} {lightningInvoice.PaymentHash}");
OnInvoiceUpdate?.Invoke(this, (identifier, lightningInvoice));
}
}

View File

@ -10,7 +10,6 @@ using BTCPayServer.Controllers;
using BTCPayServer.Lightning;
using Microsoft.AspNetCore.SignalR;
using NBitcoin;
using LightningPayment = BTCPayApp.CommonServer.Models.LightningPayment;
namespace BTCPayServer.App;
@ -84,8 +83,7 @@ public class BTCPayAppLightningClient:ILightningClient
public async Task<LightningInvoice> GetInvoice(uint256 paymentHash, CancellationToken cancellation = new CancellationToken())
{
var lp = await HubClient.GetLightningInvoice(paymentHash.ToString());
return lp is null ? null : ToLightningInvoice(lp, _network);
return await HubClient.GetLightningInvoice(paymentHash);
}
public async Task<LightningInvoice[]> ListInvoices(CancellationToken cancellation = new CancellationToken())
@ -95,93 +93,61 @@ public class BTCPayAppLightningClient:ILightningClient
public async Task<LightningInvoice[]> ListInvoices(ListInvoicesParams request, CancellationToken cancellation = new CancellationToken())
{
var invs = await HubClient.GetLightningInvoices(request);
return invs.Select(i => ToLightningInvoice(i, _network)).ToArray();
return (await HubClient.GetLightningInvoices(request)).ToArray();
}
public async Task<Lightning.LightningPayment> GetPayment(string paymentHash, CancellationToken cancellation = new CancellationToken())
{
return ToLightningPayment(await HubClient.GetLightningPayment(paymentHash));
return await HubClient.GetLightningPayment(uint256.Parse(paymentHash));
}
private static Lightning.LightningPayment ToLightningPayment(LightningPayment lightningPayment)
{
return new Lightning.LightningPayment()
{
Id = lightningPayment.PaymentHash,
Amount = LightMoney.MilliSatoshis(lightningPayment.Value),
PaymentHash = lightningPayment.PaymentHash,
Preimage = lightningPayment.Preimage,
BOLT11 = lightningPayment.PaymentRequests.FirstOrDefault(),
Status = lightningPayment.Status
};
}
public async Task<Lightning.LightningPayment[]> ListPayments(CancellationToken cancellation = new CancellationToken())
{
return await ListPayments(new ListPaymentsParams(), cancellation);
}
public async Task<Lightning.LightningPayment[]> ListPayments(ListPaymentsParams request, CancellationToken cancellation = new CancellationToken())
public async Task<LightningPayment[]> ListPayments(ListPaymentsParams request, CancellationToken cancellation = new CancellationToken())
{
var invs = await HubClient.GetLightningPayments(request);
return invs.Select(ToLightningPayment).ToArray();
return (await HubClient.GetLightningPayments(request)).ToArray();
}
public async Task<LightningInvoice> CreateInvoice(LightMoney amount, string description, TimeSpan expiry,
CancellationToken cancellation = new CancellationToken())
CancellationToken cancellation = new())
{
return await CreateInvoice(new CreateInvoiceParams(amount, description, expiry), cancellation);
}
public async Task<LightningInvoice> CreateInvoice(CreateInvoiceParams createInvoiceRequest, CancellationToken cancellation = new CancellationToken())
{
var lp = await HubClient.CreateInvoice(new CreateLightningInvoiceRequest(createInvoiceRequest.Amount, createInvoiceRequest.Description, createInvoiceRequest.Expiry)
return await HubClient.CreateInvoice(new CreateLightningInvoiceRequest(createInvoiceRequest.Amount, createInvoiceRequest.Description, createInvoiceRequest.Expiry)
{
DescriptionHashOnly = createInvoiceRequest.DescriptionHashOnly,
PrivateRouteHints = createInvoiceRequest.PrivateRouteHints,
});
return ToLightningInvoice(lp, _network);
}
private static LightningInvoice ToLightningInvoice(LightningPayment lightningPayment, Network _network)
{
var paymenRequest = BOLT11PaymentRequest.Parse(lightningPayment.PaymentRequests.First(), _network);
return new LightningInvoice()
{
Id = lightningPayment.PaymentHash,
Amount = LightMoney.MilliSatoshis(lightningPayment.Value),
PaymentHash = lightningPayment.PaymentHash,
Preimage = lightningPayment.Preimage,
PaidAt = lightningPayment.Status == LightningPaymentStatus.Complete? DateTimeOffset.UtcNow: null, //TODO: store these in ln payment
BOLT11 = lightningPayment.PaymentRequests.FirstOrDefault(),
Status = lightningPayment.Status == LightningPaymentStatus.Complete? LightningInvoiceStatus.Paid: paymenRequest.ExpiryDate < DateTimeOffset.UtcNow? LightningInvoiceStatus.Expired: LightningInvoiceStatus.Unpaid
};
}
public async Task<ILightningInvoiceListener> Listen(CancellationToken cancellation = new CancellationToken())
{
return new Listener(_appState, _network, _key);
return new Listener(_appState, _key);
}
public class Listener:ILightningInvoiceListener
{
private readonly BTCPayAppState _btcPayAppState;
private readonly Network _network;
private readonly string _key;
private readonly Channel<LightningPayment> _channel = Channel.CreateUnbounded<LightningPayment>();
private readonly Channel<LightningInvoice> _channel = Channel.CreateUnbounded<LightningInvoice>();
private readonly CancellationTokenSource _cts;
public Listener(BTCPayAppState btcPayAppState, Network network, string key)
public Listener(BTCPayAppState btcPayAppState, string key)
{
_btcPayAppState = btcPayAppState;
btcPayAppState.GroupRemoved += BtcPayAppStateOnGroupRemoved;
_network = network;
_key = key;
_cts = new CancellationTokenSource();
_btcPayAppState.OnPaymentUpdate += BtcPayAppStateOnOnPaymentUpdate;
_btcPayAppState.OnInvoiceUpdate += BtcPayAppStateOnOnInvoiceUpdate;
}
private void BtcPayAppStateOnGroupRemoved(object sender, string e)
@ -190,7 +156,7 @@ public class BTCPayAppLightningClient:ILightningClient
_channel.Writer.Complete();
}
private void BtcPayAppStateOnOnPaymentUpdate(object sender, (string, LightningPayment) e)
private void BtcPayAppStateOnOnInvoiceUpdate(object sender, (string, LightningInvoice) e)
{
if (e.Item1.Equals(_key, StringComparison.InvariantCultureIgnoreCase))
_channel.Writer.TryWrite(e.Item2);
@ -200,14 +166,15 @@ public class BTCPayAppLightningClient:ILightningClient
public void Dispose()
{
_cts?.Cancel();
_btcPayAppState.OnPaymentUpdate -= BtcPayAppStateOnOnPaymentUpdate;
_btcPayAppState.OnInvoiceUpdate -= BtcPayAppStateOnOnInvoiceUpdate;
_btcPayAppState.GroupRemoved -= BtcPayAppStateOnGroupRemoved;
_channel.Writer.TryComplete();
}
public async Task<LightningInvoice> WaitInvoice(CancellationToken cancellation)
{
return ToLightningInvoice(await _channel.Reader.ReadAsync( CancellationTokenSource.CreateLinkedTokenSource(cancellation, _cts.Token).Token), _network);
return await _channel.Reader.ReadAsync(CancellationTokenSource
.CreateLinkedTokenSource(cancellation, _cts.Token).Token);
}
}