From fc98457add1778cb0666805a119f0b6206764554 Mon Sep 17 00:00:00 2001 From: Kukks Date: Wed, 8 May 2024 12:16:25 +0200 Subject: [PATCH] update and have working invoice gen --- BTCPayApp.CommonServer/AppUserInfo.cs | 3 + BTCPayApp.CommonServer/IBTCPayAppHubClient.cs | 5 + BTCPayServer/App/BTCPayAppHub.cs | 2 +- BTCPayServer/App/BTCPayAppState.cs | 14 ++- BTCPayServer/App/LN.cs | 92 ++++++++++++++++--- BTCPayServer/BTCPayServer.csproj | 1 + BTCPayServer/Hosting/Startup.cs | 2 +- 7 files changed, 98 insertions(+), 21 deletions(-) diff --git a/BTCPayApp.CommonServer/AppUserInfo.cs b/BTCPayApp.CommonServer/AppUserInfo.cs index 897f864b9..1de28514f 100644 --- a/BTCPayApp.CommonServer/AppUserInfo.cs +++ b/BTCPayApp.CommonServer/AppUserInfo.cs @@ -14,6 +14,9 @@ public partial class LightningPayment 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 PaymentRequests { get; set; } } public class AppUserInfo diff --git a/BTCPayApp.CommonServer/IBTCPayAppHubClient.cs b/BTCPayApp.CommonServer/IBTCPayAppHubClient.cs index f2a696424..a25992833 100644 --- a/BTCPayApp.CommonServer/IBTCPayAppHubClient.cs +++ b/BTCPayApp.CommonServer/IBTCPayAppHubClient.cs @@ -1,6 +1,7 @@ using System.Collections.Generic; using System.Threading.Tasks; using BTCPayServer.Client.Models; +using BTCPayServer.Lightning; namespace BTCPayApp.CommonServer; @@ -14,6 +15,10 @@ public interface IBTCPayAppHubClient Task NewBlock(string block); Task CreateInvoice(CreateLightningInvoiceRequest createLightningInvoiceRequest); + Task GetLightningInvoice(string paymentHash); + Task GetLightningPayment(string paymentHash); + Task> GetLightningPayments(ListPaymentsParams request); + Task> GetLightningInvoices(ListInvoicesParams request); } //methods available on the hub in the server public interface IBTCPayAppHubServer diff --git a/BTCPayServer/App/BTCPayAppHub.cs b/BTCPayServer/App/BTCPayAppHub.cs index 5143048d8..2fae6d0a5 100644 --- a/BTCPayServer/App/BTCPayAppHub.cs +++ b/BTCPayServer/App/BTCPayAppHub.cs @@ -262,7 +262,7 @@ var resultPsbt = PSBT.Parse(psbt, explorerClient.Network.NBitcoinNetwork); public async Task SendPaymentUpdate(string identifier, LightningPayment lightningPayment) { - throw new NotImplementedException(); + await _appState.PaymentUpdate(identifier, lightningPayment); } diff --git a/BTCPayServer/App/BTCPayAppState.cs b/BTCPayServer/App/BTCPayAppState.cs index bc60b9f98..ee8bb033a 100644 --- a/BTCPayServer/App/BTCPayAppState.cs +++ b/BTCPayServer/App/BTCPayAppState.cs @@ -25,26 +25,25 @@ public class BTCPayAppState : IHostedService private readonly ExplorerClientProvider _explorerClientProvider; private readonly BTCPayNetworkProvider _networkProvider; private readonly EventAggregator _eventAggregator; - private readonly HubLifetimeManager _lifetimeManager; private CompositeDisposable? _compositeDisposable; public ExplorerClient ExplorerClient { get; private set; } + private DerivationSchemeParser _derivationSchemeParser; // private readonly ConcurrentDictionary _connectionScheme = new(); + public event EventHandler<(string,LightningPayment)>? OnPaymentUpdate; public BTCPayAppState( IHubContext hubContext, ILogger logger, ExplorerClientProvider explorerClientProvider, BTCPayNetworkProvider networkProvider, - EventAggregator eventAggregator, - HubLifetimeManager lifetimeManager) + EventAggregator eventAggregator) { _hubContext = hubContext; _logger = logger; _explorerClientProvider = explorerClientProvider; _networkProvider = networkProvider; _eventAggregator = eventAggregator; - _lifetimeManager = lifetimeManager; } public Task StartAsync(CancellationToken cancellationToken) @@ -152,4 +151,11 @@ public class BTCPayAppState : IHostedService public async Task Connected(string contextConnectionId) { } + + public async Task PaymentUpdate(string identifier, LightningPayment lightningPayment) + { + OnPaymentUpdate?.Invoke(this, (identifier, lightningPayment)); + } + + } diff --git a/BTCPayServer/App/LN.cs b/BTCPayServer/App/LN.cs index c88893a7c..8015389f0 100644 --- a/BTCPayServer/App/LN.cs +++ b/BTCPayServer/App/LN.cs @@ -1,6 +1,8 @@ using System; using System.Diagnostics.CodeAnalysis; +using System.Linq; using System.Threading; +using System.Threading.Channels; using System.Threading.Tasks; using BTCPayApp.CommonServer; using BTCPayServer.Client.Models; @@ -8,7 +10,7 @@ using BTCPayServer.Controllers; using BTCPayServer.Lightning; using Microsoft.AspNetCore.SignalR; using NBitcoin; -using LightningPayment = BTCPayServer.Lightning.LightningPayment; +using LightningPayment = BTCPayApp.CommonServer.LightningPayment; namespace BTCPayServer.App; @@ -46,7 +48,7 @@ public class BTCPayAppLightningConnectionStringHandler:ILightningConnectionStrin return null; } error = null; - return new BTCPayAppLightningClient(_hubContext, _appState, key); + return new BTCPayAppLightningClient(_hubContext, _appState, key, network ); } @@ -57,12 +59,14 @@ public class BTCPayAppLightningClient:ILightningClient private readonly IHubContext _hubContext; private readonly BTCPayAppState _appState; private readonly string _key; + private readonly Network _network; - public BTCPayAppLightningClient(IHubContext hubContext, BTCPayAppState appState, string key) + public BTCPayAppLightningClient(IHubContext hubContext, BTCPayAppState appState, string key, Network network) { _hubContext = hubContext; _appState = appState; _key = key; + _network = network; } public override string ToString() @@ -80,7 +84,8 @@ public class BTCPayAppLightningClient:ILightningClient public async Task GetInvoice(uint256 paymentHash, CancellationToken cancellation = new CancellationToken()) { - throw new NotImplementedException(); + var lp = await HubClient.GetLightningInvoice(paymentHash.ToString()); + return ToLightningInvoice(lp, _network); } public async Task ListInvoices(CancellationToken cancellation = new CancellationToken()) @@ -90,22 +95,38 @@ public class BTCPayAppLightningClient:ILightningClient public async Task ListInvoices(ListInvoicesParams request, CancellationToken cancellation = new CancellationToken()) { - throw new NotImplementedException(); + var invs = await HubClient.GetLightningInvoices(request); + return invs.Select(i => ToLightningInvoice(i, _network)).ToArray(); } - public async Task GetPayment(string paymentHash, CancellationToken cancellation = new CancellationToken()) + public async Task GetPayment(string paymentHash, CancellationToken cancellation = new CancellationToken()) { - throw new NotImplementedException(); + + return ToLightningPayment(await HubClient.GetLightningPayment(paymentHash)); } - public async Task ListPayments(CancellationToken cancellation = new CancellationToken()) + 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 ListPayments(CancellationToken cancellation = new CancellationToken()) { return await ListPayments(new ListPaymentsParams(), cancellation); } - public async Task ListPayments(ListPaymentsParams request, CancellationToken cancellation = new CancellationToken()) + public async Task ListPayments(ListPaymentsParams request, CancellationToken cancellation = new CancellationToken()) { - throw new NotImplementedException(); + var invs = await HubClient.GetLightningPayments(request); + return invs.Select(ToLightningPayment).ToArray(); } public async Task CreateInvoice(LightMoney amount, string description, TimeSpan expiry, @@ -122,20 +143,61 @@ public class BTCPayAppLightningClient:ILightningClient PrivateRouteHints = createInvoiceRequest.PrivateRouteHints, }); - - - return null; + 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, + BOLT11 = lightningPayment.PaymentRequests.FirstOrDefault(), + Status = lightningPayment.Status == LightningPaymentStatus.Complete? LightningInvoiceStatus.Paid: paymenRequest.ExpiryDate < DateTimeOffset.UtcNow? LightningInvoiceStatus.Expired: LightningInvoiceStatus.Unpaid + }; + } public async Task Listen(CancellationToken cancellation = new CancellationToken()) { - throw new NotImplementedException(); + return new Listener(_appState, _network); + } + + public class Listener:ILightningInvoiceListener + { + private readonly BTCPayAppState _btcPayAppState; + private readonly Network _network; + private readonly Channel _channel = Channel.CreateUnbounded(); + + public Listener(BTCPayAppState btcPayAppState, Network network) + { + _btcPayAppState = btcPayAppState; + _network = network; + _btcPayAppState.OnPaymentUpdate += BtcPayAppStateOnOnPaymentUpdate; + } + + private void BtcPayAppStateOnOnPaymentUpdate(object sender, (string, LightningPayment) e) + { + _channel.Writer.TryWrite(e.Item2); + } + + public void Dispose() + { + _btcPayAppState.OnPaymentUpdate -= BtcPayAppStateOnOnPaymentUpdate; + _channel.Writer.Complete(); + } + + public async Task WaitInvoice(CancellationToken cancellation) + { + return ToLightningInvoice(await _channel.Reader.ReadAsync(cancellation), _network); + } } public async Task GetInfo(CancellationToken cancellation = new CancellationToken()) { - throw new NotImplementedException(); + throw new NotSupportedException(); } public async Task GetBalance(CancellationToken cancellation = new CancellationToken()) diff --git a/BTCPayServer/BTCPayServer.csproj b/BTCPayServer/BTCPayServer.csproj index 5a8b9d68a..3b11e1390 100644 --- a/BTCPayServer/BTCPayServer.csproj +++ b/BTCPayServer/BTCPayServer.csproj @@ -47,6 +47,7 @@ + diff --git a/BTCPayServer/Hosting/Startup.cs b/BTCPayServer/Hosting/Startup.cs index 1ba554e64..2f90ce493 100644 --- a/BTCPayServer/Hosting/Startup.cs +++ b/BTCPayServer/Hosting/Startup.cs @@ -115,7 +115,7 @@ namespace BTCPayServer.Hosting services.AddBTCPayServer(Configuration, Logs); services.AddProviderStorage(); services.AddSession(); - services.AddSignalR(); + services.AddSignalR().AddNewtonsoftJsonProtocol(); services.AddFido2(options => { options.ServerName = "BTCPay Server";