diff --git a/README.md b/README.md
index a516673..b1bf97d 100644
--- a/README.md
+++ b/README.md
@@ -30,7 +30,7 @@ Or with custodial solution for lightning (without having a node of your own) :
- [x] LNDHub / BlueWallet ([Documentation](documentation/client-lndhub.md))
- [x] LNBits ([Documentation](documentation/client-lnbits.md))
-## Extend
+## Extensible
With `LightningPay`, you can easly extend your client by add extension methods to the `ILightningClient` interface.
diff --git a/documentation/client-eclair.md b/documentation/client-eclair.md
index e508652..01b7a34 100644
--- a/documentation/client-eclair.md
+++ b/documentation/client-eclair.md
@@ -57,6 +57,7 @@ The `AddEclairLightningClient` method has optionnal pamameters to configure your
| --------------------- | -------- | -------- | ------------------------------------------------------------ |
| address | `Uri` | Yes | Address of your node server with port (example : http://localhost:8080/) |
| password | `String` | No | Eclair api password |
+| retryOnHttpError | `int` | No | Number of retry on http error |
| certificateThumbprint | `String` | No | Certificate thumbprint used for your https address if the certificate is not public
Ex : "284800A04D0C046636EBE60C37A4F527B8B550F3" |
| allowInsecure | `bool` | No | If you use https address, determine if you allow non secure transport (certificateThumbprint parameter will be ignored) |
diff --git a/documentation/client-lnbits.md b/documentation/client-lnbits.md
index a53464c..0d66066 100644
--- a/documentation/client-lnbits.md
+++ b/documentation/client-lnbits.md
@@ -58,6 +58,7 @@ The `AddLNBitsLightningClient` method has optionnal pamameters to configure your
| --------------------- | -------- | -------- | ------------------------------------------------------------ |
| address | `Uri` | Yes | Address of the LNBits api (example : https://lnbits.com/) |
| apiKey | `String` | Yes | LNBits api key |
+| retryOnHttpError | `int` | No | Number of retry on http error |
| certificateThumbprint | `String` | No | Certificate thumbprint used for your https address if the certificate is not public
Ex : "284800A04D0C046636EBE60C37A4F527B8B550F3" |
| allowInsecure | `bool` | No | If you use https address, determine if you allow non secure transport (certificateThumbprint parameter will be ignored) |
diff --git a/documentation/client-lnd.md b/documentation/client-lnd.md
index eddcbbf..a82fccf 100644
--- a/documentation/client-lnd.md
+++ b/documentation/client-lnd.md
@@ -58,6 +58,7 @@ The `AddLndLightningClient` method has optionnal pamameters to configure your cl
| address | `Uri` | Yes | Address of your node server with port (example : http://localhost:8080/) |
| macaroonHexString | `String` | No | Authentication assertion in hex string format
Tip : To get the hex string of your, type the command xxd -p -c2000 admin.macaroon to get the hex representation of your file. |
| macaroonBytes | `byte[]` | No | Authentication assertion in Byte array (to load macaron from file with .NET code `File.ReadAllBytes(macaroonFilePath)` ) |
+| retryOnHttpError | `int` | No | Number of retry on http error |
| certificateThumbprint | `String` | No | Certificate thumbprint used for your https address if the certificate is not public
Ex : "284800A04D0C046636EBE60C37A4F527B8B550F3" |
| allowInsecure | `bool` | No | If you use https address, determine if you allow non secure transport (certificateThumbprint parameter will be ignored) |
diff --git a/documentation/client-lndhub.md b/documentation/client-lndhub.md
index 08b3e13..0da6e04 100644
--- a/documentation/client-lndhub.md
+++ b/documentation/client-lndhub.md
@@ -61,6 +61,7 @@ The `AddLndHubLightningClient` method has optionnal pamameters to configure your
| address | `Uri` | Yes | Address of the LNDHub api (example : https://lndhub.herokuapp.com/) |
| login | `String` | Yes | LNDHub login |
| password | `String` | Yes | LNDHub Password |
+| retryOnHttpError | `int` | No | Number of retry on http error |
| certificateThumbprint | `String` | No | Certificate thumbprint used for your https address if the certificate is not public
Ex : "284800A04D0C046636EBE60C37A4F527B8B550F3" |
| allowInsecure | `bool` | No | If you use https address, determine if you allow non secure transport (certificateThumbprint parameter will be ignored) |
diff --git a/samples/LightningPay.Samples.WebAppMvc/Startup.cs b/samples/LightningPay.Samples.WebAppMvc/Startup.cs
index 0f30fb7..608b203 100644
--- a/samples/LightningPay.Samples.WebAppMvc/Startup.cs
+++ b/samples/LightningPay.Samples.WebAppMvc/Startup.cs
@@ -52,7 +52,7 @@ public void ConfigureServices(IServiceCollection services)
*/
- services.AddLndLightningClient(new Uri("tcp://127.0.0.1:9835"));
+ services.AddLndLightningClient(new Uri("http://localhost:32736/"));
}
diff --git a/src/LightningPay.DependencyInjection/Extensions/EclairExtensions.cs b/src/LightningPay.DependencyInjection/Extensions/EclairExtensions.cs
index a2cb1f1..bce7abd 100644
--- a/src/LightningPay.DependencyInjection/Extensions/EclairExtensions.cs
+++ b/src/LightningPay.DependencyInjection/Extensions/EclairExtensions.cs
@@ -2,6 +2,9 @@
using Microsoft.Extensions.DependencyInjection;
+using Polly;
+using Polly.Extensions.Http;
+
using LightningPay.Clients.Eclair;
namespace LightningPay
@@ -34,14 +37,14 @@ public static IServiceCollection AddEclairLightningClient(this IServiceCollectio
/// The services.
/// The address of the LNBits api.
/// The password.
+ /// Number of retry on http error
/// if set to true [allow insecure].
/// The certificate thumbprint.
- ///
- /// ServiceCollection
- ///
+ /// ServiceCollection
public static IServiceCollection AddEclairLightningClient(this IServiceCollection services,
Uri address,
string password,
+ int retryOnHttpError = 10,
bool allowInsecure = false,
string certificateThumbprint = null)
{
@@ -57,7 +60,11 @@ public static IServiceCollection AddEclairLightningClient(this IServiceCollectio
CertificateThumbprint = certificateThumbprint.HexStringToByteArray()
});
services.AddSingleton();
+
services.AddHttpClient()
+ .AddPolicyHandler(HttpPolicyExtensions
+ .HandleTransientHttpError()
+ .WaitAndRetryAsync(retryOnHttpError, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt))))
.ConfigurePrimaryHttpMessageHandler();
return services;
diff --git a/src/LightningPay.DependencyInjection/Extensions/LNBitsExtensions.cs b/src/LightningPay.DependencyInjection/Extensions/LNBitsExtensions.cs
index 9592b85..e3ffce2 100644
--- a/src/LightningPay.DependencyInjection/Extensions/LNBitsExtensions.cs
+++ b/src/LightningPay.DependencyInjection/Extensions/LNBitsExtensions.cs
@@ -2,6 +2,9 @@
using Microsoft.Extensions.DependencyInjection;
+using Polly;
+using Polly.Extensions.Http;
+
using LightningPay.Clients.LNBits;
namespace LightningPay
@@ -34,6 +37,7 @@ public static IServiceCollection AddLNBitsLightningClient(this IServiceCollectio
/// The services.
/// The address of the LNBits api.
/// The api key.
+ /// Number of retry on http error
/// if set to true [allow insecure].
/// The certificate thumbprint.
///
@@ -42,6 +46,7 @@ public static IServiceCollection AddLNBitsLightningClient(this IServiceCollectio
public static IServiceCollection AddLNBitsLightningClient(this IServiceCollection services,
Uri address,
string apiKey,
+ int retryOnHttpError = 10,
bool allowInsecure = false,
string certificateThumbprint = null)
{
@@ -57,7 +62,11 @@ public static IServiceCollection AddLNBitsLightningClient(this IServiceCollectio
CertificateThumbprint = certificateThumbprint.HexStringToByteArray()
});
services.AddSingleton();
+
services.AddHttpClient()
+ .AddPolicyHandler(HttpPolicyExtensions
+ .HandleTransientHttpError()
+ .WaitAndRetryAsync(retryOnHttpError, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt))))
.ConfigurePrimaryHttpMessageHandler();
return services;
diff --git a/src/LightningPay.DependencyInjection/Extensions/LndExtensions.cs b/src/LightningPay.DependencyInjection/Extensions/LndExtensions.cs
index 75d910f..f035a04 100644
--- a/src/LightningPay.DependencyInjection/Extensions/LndExtensions.cs
+++ b/src/LightningPay.DependencyInjection/Extensions/LndExtensions.cs
@@ -1,9 +1,12 @@
using System;
+using System.Net;
+using System.Net.Http;
using Microsoft.Extensions.DependencyInjection;
-using LightningPay.Clients.Lnd;
+using Polly;
+using LightningPay.Clients.Lnd;
namespace LightningPay
{
@@ -50,6 +53,7 @@ public static IServiceCollection AddLndLightningClient(this IServiceCollection s
/// The services.
/// The address of the LND server.
/// The macaroon hexadecimal string.
+ /// Number of retry on http error
/// if set to true [allow insecure].
/// The certificate thumbprint.
///
@@ -58,20 +62,23 @@ public static IServiceCollection AddLndLightningClient(this IServiceCollection s
public static IServiceCollection AddLndLightningClient(this IServiceCollection services,
Uri address,
string macaroonHexString = null,
+ int retryOnHttpError = 10,
bool allowInsecure = false,
string certificateThumbprint = null)
{
return AddLndLightningClient(services,
address,
macaroonHexString.HexStringToByteArray(),
- allowInsecure,
- certificateThumbprint);
+ retryOnHttpError: retryOnHttpError,
+ allowInsecure: allowInsecure,
+ certificateThumbprint: certificateThumbprint);
}
/// Adds the LND lightning client.
/// The services.
/// The address of the LND server.
/// The macaroon bytes.
+ /// Number of retry on http error
/// if set to true [allow insecure].
/// The certificate thumbprint.
///
@@ -80,6 +87,7 @@ public static IServiceCollection AddLndLightningClient(this IServiceCollection s
public static IServiceCollection AddLndLightningClient(this IServiceCollection services,
Uri address,
byte[] macaroonBytes = null,
+ int retryOnHttpError = 10,
bool allowInsecure = false,
string certificateThumbprint = null)
{
@@ -96,7 +104,13 @@ public static IServiceCollection AddLndLightningClient(this IServiceCollection s
CertificateThumbprint = certificateThumbprint.HexStringToByteArray()
});
services.AddSingleton();
+
services.AddHttpClient()
+ .AddPolicyHandler(Policy
+ // Add custom handling to exclude 500 because api return 500 for bad request errors
+ .Handle()
+ .OrResult(r => (int)r.StatusCode > 500 || r.StatusCode == HttpStatusCode.RequestTimeout)
+ .WaitAndRetryAsync(retryOnHttpError, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt))))
.ConfigurePrimaryHttpMessageHandler();
return services;
diff --git a/src/LightningPay.DependencyInjection/Extensions/LndHubExtensions.cs b/src/LightningPay.DependencyInjection/Extensions/LndHubExtensions.cs
index 256875b..0e4b1ca 100644
--- a/src/LightningPay.DependencyInjection/Extensions/LndHubExtensions.cs
+++ b/src/LightningPay.DependencyInjection/Extensions/LndHubExtensions.cs
@@ -2,6 +2,9 @@
using Microsoft.Extensions.DependencyInjection;
+using Polly;
+using Polly.Extensions.Http;
+
using LightningPay.Clients.LndHub;
namespace LightningPay
@@ -37,6 +40,7 @@ public static IServiceCollection AddLndHubLightningClient(this IServiceCollectio
/// The address of the LNDHub.
/// The login.
/// The password.
+ /// Number of retry on http error
/// if set to true [allow insecure].
/// The certificate thumbprint.
///
@@ -46,6 +50,7 @@ public static IServiceCollection AddLndHubLightningClient(this IServiceCollectio
Uri address,
string login,
string password,
+ int retryOnHttpError = 10,
bool allowInsecure = false,
string certificateThumbprint = null)
{
@@ -62,7 +67,11 @@ public static IServiceCollection AddLndHubLightningClient(this IServiceCollectio
CertificateThumbprint = certificateThumbprint.HexStringToByteArray()
});
services.AddSingleton();
+
services.AddHttpClient()
+ .AddPolicyHandler(HttpPolicyExtensions
+ .HandleTransientHttpError()
+ .WaitAndRetryAsync(retryOnHttpError, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt))))
.ConfigurePrimaryHttpMessageHandler();
return services;
diff --git a/src/LightningPay.DependencyInjection/LightningPay.DependencyInjection.csproj b/src/LightningPay.DependencyInjection/LightningPay.DependencyInjection.csproj
index 8d1d6ad..fbadf4f 100644
--- a/src/LightningPay.DependencyInjection/LightningPay.DependencyInjection.csproj
+++ b/src/LightningPay.DependencyInjection/LightningPay.DependencyInjection.csproj
@@ -19,27 +19,27 @@
-
+
-
+
-
+
-
+
-
+
diff --git a/tests/LightningPay.IntegrationTest/CLightningClientIntegrationTest.cs b/tests/LightningPay.IntegrationTest/CLightningClientIntegrationTest.cs
index 753b784..dbbbab2 100644
--- a/tests/LightningPay.IntegrationTest/CLightningClientIntegrationTest.cs
+++ b/tests/LightningPay.IntegrationTest/CLightningClientIntegrationTest.cs
@@ -1,6 +1,6 @@
-using System.Threading.Tasks;
+using System;
-using LightningPay.Clients.CLightning;
+using Microsoft.Extensions.DependencyInjection;
namespace LightningPay.IntegrationTest
{
@@ -8,11 +8,10 @@ public class CLightningClientIntegrationTest : LightningClientIntegrationTestBas
{
protected override bool NeedBitcoind => true;
- protected override Task GetClient()
- {
- ILightningClient client = CLightningClient.New("tcp://127.0.0.1:48532");
- return Task.FromResult(client);
+ protected override void ConfigureServices(IServiceCollection services)
+ {
+ services.AddCLightningClient(new Uri("tcp://127.0.0.1:48532"));
}
protected override string SelfPaymentErrorMesssage => "Error code 210";
diff --git a/tests/LightningPay.IntegrationTest/EclairClientIntegrationTest.cs b/tests/LightningPay.IntegrationTest/EclairClientIntegrationTest.cs
index 6e63feb..efd1c2c 100644
--- a/tests/LightningPay.IntegrationTest/EclairClientIntegrationTest.cs
+++ b/tests/LightningPay.IntegrationTest/EclairClientIntegrationTest.cs
@@ -1,6 +1,6 @@
-using System.Threading.Tasks;
+using System;
-using LightningPay.Clients.Eclair;
+using Microsoft.Extensions.DependencyInjection;
namespace LightningPay.IntegrationTest
{
@@ -8,11 +8,9 @@ public class EclairClientIntegrationTest : LightningClientIntegrationTestBase
{
protected override bool NeedBitcoind => true;
- protected override Task GetClient()
+ protected override void ConfigureServices(IServiceCollection services)
{
- ILightningClient client = EclairClient.New("http://localhost:4570/", "eclairpassword");
-
- return Task.FromResult(client);
+ services.AddEclairLightningClient(new Uri("http://localhost:4570/"), "eclairpassword");
}
protected override string SelfPaymentErrorMesssage => "Cannot process to the payment";
diff --git a/tests/LightningPay.IntegrationTest/LNBitsClientIntegrationTest.cs b/tests/LightningPay.IntegrationTest/LNBitsClientIntegrationTest.cs
index 0903c62..138b8e2 100644
--- a/tests/LightningPay.IntegrationTest/LNBitsClientIntegrationTest.cs
+++ b/tests/LightningPay.IntegrationTest/LNBitsClientIntegrationTest.cs
@@ -1,6 +1,6 @@
-using System.Threading.Tasks;
+using System;
-using LightningPay.Clients.LNBits;
+using Microsoft.Extensions.DependencyInjection;
namespace LightningPay.IntegrationTest
{
@@ -8,12 +8,9 @@ public class LNBitsClientIntegrationTest : LightningClientIntegrationTestBase
{
protected override bool NeedBitcoind => false;
- protected override Task GetClient()
+ protected override void ConfigureServices(IServiceCollection services)
{
- ILightningClient client =
- LNBitsClient.New("https://lnbits.lndev.link/", apiKey: "0f920e085f96413fa754b73b9895abbd");
-
- return Task.FromResult(client);
+ services.AddLNBitsLightningClient(new Uri("https://lnbits.lndev.link/"), "0f920e085f96413fa754b73b9895abbd");
}
protected override string SelfPaymentErrorMesssage => "Insufficient balance";
diff --git a/tests/LightningPay.IntegrationTest/LNHubClientIntegrationTest.cs b/tests/LightningPay.IntegrationTest/LNHubClientIntegrationTest.cs
index 30aeb18..ea8bb13 100644
--- a/tests/LightningPay.IntegrationTest/LNHubClientIntegrationTest.cs
+++ b/tests/LightningPay.IntegrationTest/LNHubClientIntegrationTest.cs
@@ -1,6 +1,6 @@
-using System.Threading.Tasks;
+using System;
-using LightningPay.Clients.LndHub;
+using Microsoft.Extensions.DependencyInjection;
namespace LightningPay.IntegrationTest
{
@@ -8,50 +8,12 @@ public class LNHubClientIntegrationTest : LightningClientIntegrationTestBase
{
protected override bool NeedBitcoind => false;
- protected async override Task GetClient()
+ protected override void ConfigureServices(IServiceCollection services)
{
- ILightningClient client = LndHubClient.New("https://lndhub.herokuapp.com/");
-
- var wallet = await client.CreateLndHubWallet();
-
- client = LndHubClient.New("https://lndhub.herokuapp.com/",
- login: wallet.Login,
- password: wallet.Password);
-
- return client;
+ services.AddLndHubLightningClient(new Uri("https://lndhub.herokuapp.com/"), "2073282b83fad2955b57", "a1c4f8c30a93bf3e8cbf");
}
protected override string SelfPaymentErrorMesssage => "not enough balance";
}
- internal static class LNHubClientIntegrationTestExtensions
- {
- internal async static Task CreateLndHubWallet(this ILightningClient client)
- {
- return await client.ToRestClient()
- .Post("/create", new CreateWalletRequest()
- {
- PartnerId = "bluewallet",
- AccountType = "test"
- });
- }
-
- internal class CreateWalletRequest
- {
- [Serializable("partnerid")]
- public string PartnerId { get; set; }
-
- [Serializable("accounttype")]
- public string AccountType { get; set; }
- }
-
- internal class CreateWalletResponse
- {
- [Serializable("login")]
- public string Login { get; set; }
-
- [Serializable("password")]
- public string Password { get; set; }
- }
- }
}
diff --git a/tests/LightningPay.IntegrationTest/LightningClientIntegrationTestBase.cs b/tests/LightningPay.IntegrationTest/LightningClientIntegrationTestBase.cs
index 8030534..b708ebe 100644
--- a/tests/LightningPay.IntegrationTest/LightningClientIntegrationTestBase.cs
+++ b/tests/LightningPay.IntegrationTest/LightningClientIntegrationTestBase.cs
@@ -1,7 +1,10 @@
-using NBitcoin;
+using System.Threading.Tasks;
+
+using Microsoft.Extensions.DependencyInjection;
+
+using NBitcoin;
using NBitcoin.RPC;
-using System;
-using System.Threading.Tasks;
+
using Xunit;
@@ -12,7 +15,11 @@ public abstract class LightningClientIntegrationTestBase
[Fact(Timeout =(2 * 60 * 1000))]
public async Task Run()
{
- var client = await this.GetClient();
+ IServiceCollection serviceCollection = new ServiceCollection();
+ this.ConfigureServices(serviceCollection);
+ var serviceProvider = serviceCollection.BuildServiceProvider();
+
+ var client = serviceProvider.GetRequiredService();
await this.WaitServersAreUp(client);
@@ -63,9 +70,9 @@ protected async Task WaitServersAreUp(ILightningClient client)
}
}
- protected abstract bool NeedBitcoind { get; }
+ protected abstract void ConfigureServices(IServiceCollection services);
- protected abstract Task GetClient();
+ protected abstract bool NeedBitcoind { get; }
protected abstract string SelfPaymentErrorMesssage { get; }
diff --git a/tests/LightningPay.IntegrationTest/LightningPay.IntegrationTest.csproj b/tests/LightningPay.IntegrationTest/LightningPay.IntegrationTest.csproj
index 5535e89..d208b51 100644
--- a/tests/LightningPay.IntegrationTest/LightningPay.IntegrationTest.csproj
+++ b/tests/LightningPay.IntegrationTest/LightningPay.IntegrationTest.csproj
@@ -21,7 +21,7 @@
-
+
diff --git a/tests/LightningPay.IntegrationTest/LndClientIntegrationTest.cs b/tests/LightningPay.IntegrationTest/LndClientIntegrationTest.cs
index 77b32c2..a1e7d8b 100644
--- a/tests/LightningPay.IntegrationTest/LndClientIntegrationTest.cs
+++ b/tests/LightningPay.IntegrationTest/LndClientIntegrationTest.cs
@@ -1,6 +1,6 @@
-using System.Threading.Tasks;
+using System;
-using LightningPay.Clients.Lnd;
+using Microsoft.Extensions.DependencyInjection;
namespace LightningPay.IntegrationTest
{
@@ -8,11 +8,9 @@ public class LndClientIntegrationTest : LightningClientIntegrationTestBase
{
protected override bool NeedBitcoind => true;
- protected override Task GetClient()
+ protected override void ConfigureServices(IServiceCollection services)
{
- ILightningClient client = LndClient.New("http://localhost:32736/");
-
- return Task.FromResult(client);
+ services.AddLndLightningClient(new Uri("http://localhost:32736/"));
}
protected override string SelfPaymentErrorMesssage => "self-payments not allowed";