diff --git a/BTCPayServer.Client/BTCPayServer.Client.csproj b/BTCPayServer.Client/BTCPayServer.Client.csproj
index 7ee47c484..d92e2bd7e 100644
--- a/BTCPayServer.Client/BTCPayServer.Client.csproj
+++ b/BTCPayServer.Client/BTCPayServer.Client.csproj
@@ -29,7 +29,7 @@
-
+
diff --git a/BTCPayServer.Client/Models/PayLightningInvoiceRequest.cs b/BTCPayServer.Client/Models/PayLightningInvoiceRequest.cs
index a02837914..6d7e6a404 100644
--- a/BTCPayServer.Client/Models/PayLightningInvoiceRequest.cs
+++ b/BTCPayServer.Client/Models/PayLightningInvoiceRequest.cs
@@ -1,5 +1,6 @@
using BTCPayServer.Client.JsonConverters;
using BTCPayServer.JsonConverters;
+using BTCPayServer.Lightning;
using NBitcoin;
using Newtonsoft.Json;
@@ -15,5 +16,8 @@ namespace BTCPayServer.Client.Models
[JsonConverter(typeof(MoneyJsonConverter))]
public Money MaxFeeFlat { get; set; }
+
+ [JsonConverter(typeof(LightMoneyJsonConverter))]
+ public LightMoney Amount { get; set; }
}
}
diff --git a/BTCPayServer.Tests/SeleniumTests.cs b/BTCPayServer.Tests/SeleniumTests.cs
index 4d3db7bb7..53a136e5d 100644
--- a/BTCPayServer.Tests/SeleniumTests.cs
+++ b/BTCPayServer.Tests/SeleniumTests.cs
@@ -1518,11 +1518,9 @@ namespace BTCPayServer.Tests
var lnurlResponse2 = await fetchedReuqest.SendRequest(new LightMoney(0.000002m, LightMoneyUnit.BTC),
network, new HttpClient(), comment: "lol2");
Assert.Equal(new LightMoney(0.000002m, LightMoneyUnit.BTC), lnurlResponse2.GetPaymentRequest(network).MinimumAmount);
- await Assert.ThrowsAnyAsync(async () =>
- {
- // Initial bolt was cancelled
- await s.Server.CustomerLightningD.Pay(lnurlResponse.Pr);
- });
+ // Initial bolt was cancelled
+ var res = await s.Server.CustomerLightningD.Pay(lnurlResponse.Pr);
+ Assert.Equal(PayResult.Error, res.Result);
await s.Server.CustomerLightningD.Pay(lnurlResponse2.Pr);
await TestUtils.EventuallyAsync(async () =>
diff --git a/BTCPayServer.Tests/ServerTester.cs b/BTCPayServer.Tests/ServerTester.cs
index 84e8a6fc5..a46fef0df 100644
--- a/BTCPayServer.Tests/ServerTester.cs
+++ b/BTCPayServer.Tests/ServerTester.cs
@@ -4,7 +4,6 @@ using System.Globalization;
using System.IO;
using System.Linq;
using System.Net.Http;
-using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using BTCPayServer.Lightning;
using BTCPayServer.Lightning.CLightning;
@@ -174,11 +173,11 @@ namespace BTCPayServer.Tests
SendLightningPaymentAsync(invoice).GetAwaiter().GetResult();
}
- public async Task SendLightningPaymentAsync(Invoice invoice)
+ public async Task SendLightningPaymentAsync(Invoice invoice)
{
var bolt11 = invoice.CryptoInfo.Where(o => o.PaymentUrls.BOLT11 != null).First().PaymentUrls.BOLT11;
bolt11 = bolt11.Replace("lightning:", "", StringComparison.OrdinalIgnoreCase);
- await CustomerLightningD.Pay(bolt11);
+ return await CustomerLightningD.Pay(bolt11);
}
public async Task WaitForEvent(Func action, Func correctEvent = null)
diff --git a/BTCPayServer.Tests/UnitTest1.cs b/BTCPayServer.Tests/UnitTest1.cs
index 25e2dffdd..9d808365b 100644
--- a/BTCPayServer.Tests/UnitTest1.cs
+++ b/BTCPayServer.Tests/UnitTest1.cs
@@ -5,8 +5,6 @@ using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
-using System.Runtime.CompilerServices;
-using System.Security;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
@@ -17,7 +15,6 @@ using BTCPayServer.Abstractions.Extensions;
using BTCPayServer.Abstractions.Models;
using BTCPayServer.Client;
using BTCPayServer.Client.Models;
-using BTCPayServer.Configuration;
using BTCPayServer.Controllers;
using BTCPayServer.Data;
using BTCPayServer.Events;
@@ -26,7 +23,6 @@ using BTCPayServer.Fido2.Models;
using BTCPayServer.HostedServices;
using BTCPayServer.Hosting;
using BTCPayServer.Lightning;
-using BTCPayServer.Lightning.CLightning;
using BTCPayServer.Models;
using BTCPayServer.Models.AccountViewModels;
using BTCPayServer.Models.AppViewModels;
@@ -39,33 +35,26 @@ using BTCPayServer.Payments;
using BTCPayServer.Payments.Bitcoin;
using BTCPayServer.Payments.Lightning;
using BTCPayServer.Payments.PayJoin.Sender;
-using BTCPayServer.Rating;
using BTCPayServer.Security.Bitpay;
using BTCPayServer.Services;
using BTCPayServer.Services.Apps;
using BTCPayServer.Services.Invoices;
-using BTCPayServer.Services.Labels;
using BTCPayServer.Services.Mails;
using BTCPayServer.Services.Rates;
using BTCPayServer.Storage.Models;
using BTCPayServer.Storage.Services.Providers.FileSystemStorage.Configuration;
using BTCPayServer.Storage.ViewModels;
-using BTCPayServer.Tests.Logging;
-using BTCPayServer.Validation;
using ExchangeSharp;
using Fido2NetLib;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
-using Microsoft.Extensions.Options;
using NBitcoin;
using NBitcoin.DataEncoders;
using NBitcoin.Payment;
-using NBitcoin.Socks;
using NBitpayClient;
using NBXplorer;
-using NBXplorer.DerivationStrategy;
using NBXplorer.Models;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
@@ -390,11 +379,9 @@ namespace BTCPayServer.Tests
Assert.Equal(InvoiceExceptionStatus.None, fetchedInvoice.ExceptionStatus);
//BTCPay will attempt to cancel previous bolt11 invoices so that there are less weird edge case scenarios
- TestLogs.LogInformation($"Attempting to pay invoice {invoice.Id} original full amount bolt11 invoice ");
- await Assert.ThrowsAsync(async () =>
- {
- await tester.SendLightningPaymentAsync(invoice);
- });
+ TestLogs.LogInformation($"Attempting to pay invoice {invoice.Id} original full amount bolt11 invoice");
+ var res = await tester.SendLightningPaymentAsync(invoice);
+ Assert.Equal(PayResult.Error, res.Result);
//NOTE: Eclair does not support cancelling invoice so the below test case would make sense for it
// TestLogs.LogInformation($"Paying invoice {invoice.Id} original full amount bolt11 invoice ");
diff --git a/BTCPayServer/BTCPayServer.csproj b/BTCPayServer/BTCPayServer.csproj
index 14565b37d..de25650cc 100644
--- a/BTCPayServer/BTCPayServer.csproj
+++ b/BTCPayServer/BTCPayServer.csproj
@@ -48,7 +48,7 @@
-
+
diff --git a/BTCPayServer/Controllers/GreenField/GreenfieldLightningNodeApiController.cs b/BTCPayServer/Controllers/GreenField/GreenfieldLightningNodeApiController.cs
index fda96aa8a..bd1d16185 100644
--- a/BTCPayServer/Controllers/GreenField/GreenfieldLightningNodeApiController.cs
+++ b/BTCPayServer/Controllers/GreenField/GreenfieldLightningNodeApiController.cs
@@ -6,10 +6,8 @@ using BTCPayServer.Abstractions.Contracts;
using BTCPayServer.Abstractions.Extensions;
using BTCPayServer.Client;
using BTCPayServer.Client.Models;
-using BTCPayServer.HostedServices;
using BTCPayServer.Lightning;
using BTCPayServer.Security;
-using BTCPayServer.Services;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
@@ -187,8 +185,8 @@ namespace BTCPayServer.Controllers.Greenfield
return this.CreateValidationError(ModelState);
}
- var param = lightningInvoice?.MaxFeeFlat != null || lightningInvoice?.MaxFeePercent != null
- ? new PayInvoiceParams { MaxFeePercent = lightningInvoice.MaxFeePercent, MaxFeeFlat = lightningInvoice.MaxFeeFlat }
+ var param = lightningInvoice?.MaxFeeFlat != null || lightningInvoice?.MaxFeePercent != null || lightningInvoice?.Amount != null
+ ? new PayInvoiceParams { MaxFeePercent = lightningInvoice.MaxFeePercent, MaxFeeFlat = lightningInvoice.MaxFeeFlat, Amount = lightningInvoice.Amount }
: null;
var result = await lightningClient.Pay(lightningInvoice.BOLT11, param, cancellationToken);
diff --git a/BTCPayServer/wwwroot/swagger/v1/swagger.template.lightning.common.json b/BTCPayServer/wwwroot/swagger/v1/swagger.template.lightning.common.json
index 6214eafdf..0878e3916 100644
--- a/BTCPayServer/wwwroot/swagger/v1/swagger.template.lightning.common.json
+++ b/BTCPayServer/wwwroot/swagger/v1/swagger.template.lightning.common.json
@@ -204,6 +204,11 @@
"type": "string",
"description": "The BOLT11 of the invoice to pay"
},
+ "amount": {
+ "type": "string",
+ "description": "Optional explicit payment amount in millisatoshi (if specified, it overrides the BOLT11 amount)",
+ "nullable": true
+ },
"maxFeePercent": {
"type": "string",
"format": "float",