mirror of
https://github.com/btcpayserver/btcpayserver.git
synced 2024-11-19 18:11:36 +01:00
Listen / WaitInvoice for Lnd
This commit is contained in:
parent
431147784e
commit
ce9189caf8
@ -58,8 +58,26 @@ namespace BTCPayServer.Tests.Lnd
|
||||
Assert.Equal(createInvoice.BOLT11, getInvoice.BOLT11);
|
||||
}
|
||||
|
||||
// integration tests
|
||||
[Fact]
|
||||
public async Task TestWaitListenInvoice()
|
||||
{
|
||||
var merchantInvoice = await InvoiceClient.CreateInvoice(10000, "Hello world", TimeSpan.FromSeconds(3600));
|
||||
|
||||
//integration tests
|
||||
var waitToken = default(CancellationToken);
|
||||
var listener = await InvoiceClient.Listen(waitToken);
|
||||
var waitTask = listener.WaitInvoice(waitToken);
|
||||
|
||||
await EnsureLightningChannelAsync();
|
||||
var payResponse = await CustomerLnd.SendPaymentSyncAsync(new LnrpcSendRequest
|
||||
{
|
||||
Payment_request = merchantInvoice.BOLT11
|
||||
});
|
||||
|
||||
var invoice = await waitTask;
|
||||
|
||||
Assert.True(invoice.PaidAt.HasValue);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task CreateLndInvoiceAndPay()
|
||||
|
@ -70,21 +70,18 @@ namespace BTCPayServer.Payments.Lightning.Lnd
|
||||
var resp = await _rpcClient.LookupInvoiceAsync(invoiceId, null, cancellation);
|
||||
return ConvertLndInvoice(resp);
|
||||
}
|
||||
|
||||
// TODO: These two methods where you wait on invoice are still work in progress
|
||||
|
||||
public Task<ILightningListenInvoiceSession> Listen(CancellationToken cancellation = default(CancellationToken))
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
//return Task.FromResult<ILightningListenInvoiceSession>(this);
|
||||
Task.Run(_rpcClient.StartSubscribeInvoiceThread);
|
||||
return Task.FromResult<ILightningListenInvoiceSession>(this);
|
||||
}
|
||||
|
||||
async Task<LightningInvoice> ILightningListenInvoiceSession.WaitInvoice(CancellationToken cancellation)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
//var resp = await _rpcClient.SubscribeInvoicesAsync(cancellation);
|
||||
//return ConvertLndInvoice(resp);
|
||||
var resp = await _rpcClient.InvoiceResponse.Task;
|
||||
return ConvertLndInvoice(resp);
|
||||
}
|
||||
// Eof work in progress
|
||||
|
||||
|
||||
// utility static methods... maybe move to separate class
|
||||
|
@ -1,10 +1,14 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Net.Security;
|
||||
using System.Security.Authentication;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using NBitcoin;
|
||||
|
||||
@ -12,7 +16,7 @@ namespace BTCPayServer.Payments.Lightning.Lnd
|
||||
{
|
||||
public class LndSwaggerClientCustomHttp : LndSwaggerClient, IDisposable
|
||||
{
|
||||
public LndSwaggerClientCustomHttp(string baseUrl, HttpClient httpClient)
|
||||
protected LndSwaggerClientCustomHttp(string baseUrl, HttpClient httpClient)
|
||||
: base(baseUrl, httpClient)
|
||||
{
|
||||
_HttpClient = httpClient;
|
||||
@ -28,23 +32,36 @@ namespace BTCPayServer.Payments.Lightning.Lnd
|
||||
//
|
||||
public static LndSwaggerClientCustomHttp Create(Uri uri, Network network, byte[] tlsCertificate = null, byte[] grpcMacaroon = null)
|
||||
{
|
||||
// for development we are working with custom build of lnd that allows no macaroons and http
|
||||
var clientWithNoMacaroonsTls = tlsCertificate == null || grpcMacaroon == null;
|
||||
var factory = new HttpClientFactoryForLnd(tlsCertificate, grpcMacaroon);
|
||||
var httpClient = factory.Generate();
|
||||
|
||||
var httpClient = clientWithNoMacaroonsTls ? new HttpClient() :
|
||||
HttpClientFactoryForLnd.Generate(tlsCertificate, grpcMacaroon);
|
||||
var swagger = new LndSwaggerClientCustomHttp(uri.ToString().TrimEnd('/'), httpClient);
|
||||
swagger.HttpClientFactory = factory;
|
||||
|
||||
return new LndSwaggerClientCustomHttp(uri.ToString().TrimEnd('/'), httpClient);
|
||||
return swagger;
|
||||
}
|
||||
}
|
||||
|
||||
internal class HttpClientFactoryForLnd
|
||||
{
|
||||
internal static HttpClient Generate(byte[] tlsCertificate, byte[] grpcMacaroon)
|
||||
public HttpClientFactoryForLnd(byte[] tlsCertificate = null, byte[] grpcMacaroon = null)
|
||||
{
|
||||
var httpClient = new HttpClient(GetCertificate(tlsCertificate));
|
||||
var macaroonHex = BitConverter.ToString(grpcMacaroon).Replace("-", "", StringComparison.InvariantCulture);
|
||||
httpClient.DefaultRequestHeaders.Add("Grpc-Metadata-macaroon", macaroonHex);
|
||||
TlsCertificate = tlsCertificate;
|
||||
GrpcMacaroon = grpcMacaroon;
|
||||
}
|
||||
|
||||
public byte[] TlsCertificate { get; set; }
|
||||
public byte[] GrpcMacaroon { get; set; }
|
||||
|
||||
public HttpClient Generate()
|
||||
{
|
||||
var httpClient = new HttpClient(GetCertificate(TlsCertificate));
|
||||
|
||||
if (GrpcMacaroon != null)
|
||||
{
|
||||
var macaroonHex = BitConverter.ToString(GrpcMacaroon).Replace("-", "", StringComparison.InvariantCulture);
|
||||
httpClient.DefaultRequestHeaders.Add("Grpc-Metadata-macaroon", macaroonHex);
|
||||
}
|
||||
|
||||
return httpClient;
|
||||
}
|
||||
@ -92,5 +109,49 @@ namespace BTCPayServer.Payments.Lightning.Lnd
|
||||
|
||||
public partial class LndSwaggerClient
|
||||
{
|
||||
internal HttpClientFactoryForLnd HttpClientFactory { get; set; }
|
||||
|
||||
public TaskCompletionSource<LnrpcInvoice> InvoiceResponse = new TaskCompletionSource<LnrpcInvoice>();
|
||||
public TaskCompletionSource<LndSwaggerClient> SubscribeLost = new TaskCompletionSource<LndSwaggerClient>();
|
||||
|
||||
// TODO: Refactor swagger generated wrapper to include this method directly
|
||||
public async Task StartSubscribeInvoiceThread()
|
||||
{
|
||||
var urlBuilder = new StringBuilder();
|
||||
urlBuilder.Append(BaseUrl).Append("/v1/invoices/subscribe");
|
||||
|
||||
using (var client = HttpClientFactory.Generate())
|
||||
{
|
||||
client.Timeout = TimeSpan.FromMilliseconds(Timeout.Infinite);
|
||||
|
||||
var request = new HttpRequestMessage(HttpMethod.Get, urlBuilder.ToString());
|
||||
|
||||
using (var response = await client.SendAsync(
|
||||
request,
|
||||
HttpCompletionOption.ResponseHeadersRead))
|
||||
{
|
||||
using (var body = await response.Content.ReadAsStreamAsync())
|
||||
using (var reader = new StreamReader(body))
|
||||
{
|
||||
try
|
||||
{
|
||||
while (!reader.EndOfStream)
|
||||
{
|
||||
string line = reader.ReadLine();
|
||||
LnrpcInvoice parsedInvoice = Newtonsoft.Json.JsonConvert.DeserializeObject<LnrpcInvoice>(line, _settings.Value);
|
||||
|
||||
InvoiceResponse?.SetResult(parsedInvoice);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
// TODO: check that the exception type is actually from a closed stream.
|
||||
Debug.WriteLine(e.Message);
|
||||
SubscribeLost?.SetResult(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user