mirror of
https://github.com/aljazceru/btcpayserver.git
synced 2025-12-18 14:34:23 +01:00
LNURL tests and small fixes
This commit is contained in:
@@ -132,15 +132,17 @@ namespace BTCPayServer.Tests
|
||||
return usr;
|
||||
}
|
||||
|
||||
public (string storeName, string storeId) CreateNewStore()
|
||||
public (string storeName, string storeId) CreateNewStore(bool keepId = true)
|
||||
{
|
||||
Driver.WaitForElement(By.Id("Stores")).Click();
|
||||
Driver.WaitForElement(By.Id("CreateStore")).Click();
|
||||
var name = "Store" + RandomUtils.GetUInt64();
|
||||
Driver.WaitForElement(By.Id("Name")).SendKeys(name);
|
||||
Driver.WaitForElement(By.Id("Create")).Click();
|
||||
StoreId = Driver.WaitForElement(By.Id("Id")).GetAttribute("value");
|
||||
return (name, StoreId);
|
||||
var storeId = Driver.WaitForElement(By.Id("Id")).GetAttribute("value");
|
||||
if (keepId)
|
||||
StoreId = storeId;
|
||||
return (name, storeId);
|
||||
}
|
||||
|
||||
public Mnemonic GenerateWallet(string cryptoCode = "BTC", string seed = "", bool importkeys = false, bool privkeys = false, ScriptPubKeyType format = ScriptPubKeyType.Segwit)
|
||||
@@ -213,7 +215,7 @@ namespace BTCPayServer.Tests
|
||||
FindAlertMessage();
|
||||
}
|
||||
|
||||
public void AddLightningNode(string cryptoCode = "BTC", LightningConnectionType? connectionType = null)
|
||||
public void AddLightningNode(string cryptoCode = "BTC", LightningConnectionType? connectionType = null, Action beforeEnable = null, bool test = true)
|
||||
{
|
||||
Driver.FindElement(By.Id($"Modify-Lightning{cryptoCode}")).Click();
|
||||
|
||||
@@ -236,13 +238,20 @@ namespace BTCPayServer.Tests
|
||||
else
|
||||
{
|
||||
Driver.FindElement(By.CssSelector("label[for=\"LightningNodeType-Custom\"]")).Click();
|
||||
Driver.FindElement(By.Id("ConnectionString")).Clear();
|
||||
Driver.FindElement(By.Id("ConnectionString")).SendKeys(connectionString);
|
||||
|
||||
Driver.FindElement(By.Id("test")).Click();
|
||||
Assert.Contains("Connection to the Lightning node successful.", FindAlertMessage().Text);
|
||||
if (test)
|
||||
{
|
||||
Driver.FindElement(By.Id("test")).Click();
|
||||
Assert.Contains("Connection to the Lightning node successful.", FindAlertMessage().Text);
|
||||
}
|
||||
}
|
||||
beforeEnable?.Invoke();
|
||||
|
||||
Driver.FindElement(By.Id("save")).Click();
|
||||
//soemtimes selenium slows down and misses a beat
|
||||
if(FindAlertMessage().Text == "Connection to the Lightning node successful.")
|
||||
Driver.FindElement(By.Id("save")).Click();
|
||||
Assert.Contains($"{cryptoCode} Lightning node updated.", FindAlertMessage().Text);
|
||||
|
||||
var enabled = Driver.FindElement(By.Id($"{cryptoCode}LightningEnabled"));
|
||||
@@ -354,7 +363,8 @@ namespace BTCPayServer.Tests
|
||||
decimal? amount = 100,
|
||||
string currency = "USD",
|
||||
string refundEmail = "",
|
||||
string defaultPaymentMethod = null
|
||||
string defaultPaymentMethod = null,
|
||||
StatusMessageModel.StatusSeverity expectedSeverity = StatusMessageModel.StatusSeverity.Success
|
||||
)
|
||||
{
|
||||
GoToInvoices();
|
||||
@@ -370,9 +380,8 @@ namespace BTCPayServer.Tests
|
||||
new SelectElement(Driver.FindElement(By.Name("DefaultPaymentMethod"))).SelectByValue(defaultPaymentMethod);
|
||||
Driver.FindElement(By.Id("Create")).Click();
|
||||
|
||||
var statusElement = FindAlertMessage();
|
||||
var id = statusElement.Text.Split(" ")[1];
|
||||
return id;
|
||||
var statusElement = FindAlertMessage(expectedSeverity);
|
||||
return expectedSeverity == StatusMessageModel.StatusSeverity.Success ? statusElement.Text.Split(" ")[1] : null;
|
||||
}
|
||||
|
||||
public async Task FundStoreWallet(WalletId walletId = null, int coins = 1, decimal denomination = 1m)
|
||||
|
||||
@@ -2,6 +2,7 @@ using System;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading;
|
||||
@@ -11,15 +12,18 @@ using BTCPayServer.Client.Models;
|
||||
using BTCPayServer.Data;
|
||||
using BTCPayServer.Lightning;
|
||||
using BTCPayServer.Lightning.Charge;
|
||||
using BTCPayServer.Lightning.CLightning;
|
||||
using BTCPayServer.Lightning.LND;
|
||||
using BTCPayServer.Payments;
|
||||
using BTCPayServer.Services;
|
||||
using BTCPayServer.Services.Invoices;
|
||||
using BTCPayServer.Services.Wallets;
|
||||
using BTCPayServer.Tests.Logging;
|
||||
using BTCPayServer.Views.Manage;
|
||||
using BTCPayServer.Views.Server;
|
||||
using BTCPayServer.Views.Stores;
|
||||
using BTCPayServer.Views.Wallets;
|
||||
using LNURL;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using NBitcoin;
|
||||
@@ -1222,6 +1226,195 @@ namespace BTCPayServer.Tests
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Selenium", "Selenium")]
|
||||
[Trait("Lightning", "Lightning")]
|
||||
public async Task CanUseLNURL()
|
||||
{
|
||||
using var s = SeleniumTester.Create();
|
||||
s.Server.ActivateLightning();
|
||||
await s.StartAsync();
|
||||
|
||||
await s.Server.EnsureChannelsSetup();
|
||||
await BTCPayServer.Lightning.Tests.ConnectChannels.ConnectAll(s.Server.ExplorerNode,
|
||||
new[] { s.Server.MerchantLightningD },
|
||||
new[] { s.Server.MerchantLnd.Client });
|
||||
s.RegisterNewUser(true);
|
||||
var store = s.CreateNewStore();
|
||||
var network = s.Server.NetworkProvider.GetNetwork<BTCPayNetwork>("BTC").NBitcoinNetwork;
|
||||
s.GoToStore(store.storeId);
|
||||
s.AddLightningNode("BTC", LightningConnectionType.CLightning, () =>
|
||||
{
|
||||
//lnurl is false by default
|
||||
Assert.False( s.Driver.FindElement(By.Id("LNURLEnabled")).Selected);
|
||||
//lnurl settings are not expanded when lnurl is disabled
|
||||
Assert.DoesNotContain("show", s.Driver.FindElement(By.Id("LNURLSettings")).GetAttribute("class"));
|
||||
s.Driver.SetCheckbox(By.Id("LNURLEnabled"), true);
|
||||
|
||||
|
||||
});
|
||||
//topup Invoice test
|
||||
var i = s.CreateInvoice(store.storeName, null, "BTC");
|
||||
s.GoToInvoiceCheckout(i);
|
||||
s.Driver.FindElement(By.Id("copy-tab")).Click();
|
||||
var lnurl = s.Driver.FindElement(By.CssSelector("input.checkoutTextbox")).GetAttribute("value");
|
||||
var parsed = LNURL.LNURL.Parse(lnurl, out var tag);
|
||||
var fetchedReuqest = Assert.IsType<LNURL.LNURLPayRequest>(await LNURL.LNURL.FetchInformation(parsed, new HttpClient()));
|
||||
Assert.Equal(1m, fetchedReuqest.MinSendable.ToDecimal(LightMoneyUnit.Satoshi));
|
||||
Assert.NotEqual(1m, fetchedReuqest.MaxSendable.ToDecimal(LightMoneyUnit.Satoshi));
|
||||
var lnurlResponse = await fetchedReuqest.SendRequest(new LightMoney(0.000001m, LightMoneyUnit.BTC),
|
||||
network, new HttpClient());
|
||||
|
||||
Assert.Equal(new LightMoney(0.000001m, LightMoneyUnit.BTC), lnurlResponse.GetPaymentRequest(network).MinimumAmount);
|
||||
|
||||
var lnurlResponse2 = await fetchedReuqest.SendRequest(new LightMoney(0.000002m, LightMoneyUnit.BTC),
|
||||
network, new HttpClient());
|
||||
Assert.Equal(new LightMoney(0.000002m, LightMoneyUnit.BTC), lnurlResponse2.GetPaymentRequest(network).MinimumAmount);
|
||||
await Assert.ThrowsAnyAsync<LightningRPCException>(async () =>
|
||||
{
|
||||
//the initial bolt was cancelled
|
||||
await s.Server.CustomerLightningD.Pay(lnurlResponse.Pr);
|
||||
});
|
||||
|
||||
await s.Server.CustomerLightningD.Pay(lnurlResponse2.Pr);
|
||||
await TestUtils.EventuallyAsync(async () =>
|
||||
{
|
||||
var inv = await s.Server.PayTester.InvoiceRepository.GetInvoice(i);
|
||||
Assert.Equal(InvoiceStatusLegacy.Complete, inv.Status);
|
||||
});
|
||||
|
||||
//standard invoice test
|
||||
s.GoToHome();
|
||||
i = s.CreateInvoice(store.storeName, 0.0000001m, "BTC");
|
||||
s.GoToInvoiceCheckout(i);
|
||||
s.Driver.FindElement(By.ClassName("payment__currencies")).Click();
|
||||
//bolt 11 is also available for standard invoices
|
||||
Assert.Equal(2, s.Driver.FindElements(By.CssSelector(".vex.vex-theme-btcpay .vex-content .vexmenu li.vexmenuitem")).Count);
|
||||
s.Driver.FindElement(By.CssSelector(".vex.vex-theme-btcpay .vex-content .vexmenu li.vexmenuitem")).Click();
|
||||
s.Driver.FindElement(By.Id("copy-tab")).Click();
|
||||
lnurl = s.Driver.FindElement(By.CssSelector("input.checkoutTextbox")).GetAttribute("value");
|
||||
parsed = LNURL.LNURL.Parse(lnurl, out tag);
|
||||
fetchedReuqest = Assert.IsType<LNURL.LNURLPayRequest>(await LNURL.LNURL.FetchInformation(parsed, new HttpClient()));
|
||||
Assert.Equal(0.0000001m, fetchedReuqest.MaxSendable.ToDecimal(LightMoneyUnit.BTC));
|
||||
Assert.Equal(0.0000001m, fetchedReuqest.MinSendable.ToDecimal(LightMoneyUnit.BTC));
|
||||
|
||||
await Assert.ThrowsAsync<HttpRequestException>(async () =>
|
||||
{
|
||||
|
||||
await fetchedReuqest.SendRequest(new LightMoney(0.0000002m, LightMoneyUnit.BTC),
|
||||
network, new HttpClient());
|
||||
});
|
||||
await Assert.ThrowsAsync<HttpRequestException>(async () =>
|
||||
{
|
||||
|
||||
await fetchedReuqest.SendRequest(new LightMoney(0.00000005m, LightMoneyUnit.BTC),
|
||||
network, new HttpClient());
|
||||
});
|
||||
|
||||
lnurlResponse = await fetchedReuqest.SendRequest(new LightMoney(0.0000001m, LightMoneyUnit.BTC),
|
||||
network, new HttpClient());
|
||||
lnurlResponse2 = await fetchedReuqest.SendRequest(new LightMoney(0.0000001m, LightMoneyUnit.BTC),
|
||||
network, new HttpClient());
|
||||
//invoice amounts do no change so the paymnet request is not regenerated
|
||||
Assert.Equal(lnurlResponse.Pr,lnurlResponse2.Pr);
|
||||
await s.Server.CustomerLightningD.Pay(lnurlResponse.Pr);
|
||||
Assert.Equal(new LightMoney(0.0000001m, LightMoneyUnit.BTC), lnurlResponse2.GetPaymentRequest(network).MinimumAmount);
|
||||
|
||||
|
||||
|
||||
s.GoToStore(s.StoreId);
|
||||
s.AddLightningNode("BTC", LightningConnectionType.CLightning, () =>
|
||||
{
|
||||
|
||||
s.Driver.SetCheckbox(By.Id("LNURLStandardInvoiceEnabled"), false);
|
||||
}, false);
|
||||
i = s.CreateInvoice(store.storeName, 0.000001m, "BTC" );
|
||||
s.GoToInvoiceCheckout(i);
|
||||
s.Driver.FindElement(By.ClassName("payment__currencies_noborder"));
|
||||
|
||||
s.GoToHome();
|
||||
i = s.CreateInvoice(store.storeName, null, "BTC");
|
||||
s.GoToInvoiceCheckout(i);
|
||||
s.Driver.FindElement(By.ClassName("payment__currencies_noborder"));
|
||||
|
||||
s.GoToStore(s.StoreId);
|
||||
s.AddLightningNode("BTC", LightningConnectionType.CLightning, () =>
|
||||
{
|
||||
|
||||
s.Driver.SetCheckbox(By.Id("LNURLBech32Mode"), false);
|
||||
s.Driver.SetCheckbox(By.Id("DisableBolt11PaymentMethod"), true);
|
||||
}, false);
|
||||
s.CreateInvoice(store.storeName, 0.0000001m, "BTC","",null, StatusMessageModel.StatusSeverity.Error);
|
||||
|
||||
|
||||
i = s.CreateInvoice(store.storeName, null, "BTC");
|
||||
s.GoToInvoiceCheckout(i);
|
||||
s.Driver.FindElement(By.ClassName("payment__currencies_noborder"));
|
||||
s.Driver.FindElement(By.Id("copy-tab")).Click();
|
||||
lnurl = s.Driver.FindElement(By.CssSelector("input.checkoutTextbox")).GetAttribute("value");
|
||||
Assert.StartsWith("lnurlp", lnurl);
|
||||
LNURL.LNURL.Parse(lnurl, out tag);
|
||||
|
||||
|
||||
s.GoToHome();
|
||||
var newStore = s.CreateNewStore(false);
|
||||
s.AddLightningNode("BTC", LightningConnectionType.LndREST, () =>
|
||||
{
|
||||
s.Driver.SetCheckbox(By.Id("LNURLEnabled"), true);
|
||||
s.Driver.SetCheckbox(By.Id("DisableBolt11PaymentMethod"), true);
|
||||
}, false);
|
||||
var invForPP = s.CreateInvoice(newStore.storeName, 0.0000001m, "BTC");
|
||||
s.GoToInvoiceCheckout(invForPP);
|
||||
s.Driver.FindElement(By.Id("copy-tab")).Click();
|
||||
lnurl = s.Driver.FindElement(By.CssSelector("input.checkoutTextbox")).GetAttribute("value");
|
||||
parsed = LNURL.LNURL.Parse(lnurl, out tag);
|
||||
|
||||
|
||||
|
||||
//check that pull payment has lightning option
|
||||
s.GoToStore(s.StoreId, StoreNavPages.PullPayments);
|
||||
s.Driver.FindElement(By.Id("NewPullPayment")).Click();
|
||||
Assert.Equal(new PaymentMethodId("BTC", PaymentTypes.LightningLike),PaymentMethodId.Parse(Assert.Single( s.Driver.FindElement(By.Id("PaymentMethods")).FindElements(By.TagName("option"))).GetAttribute("value")));
|
||||
s.Driver.FindElement(By.Id("Name")).SendKeys("PP1");
|
||||
s.Driver.FindElement(By.Id("Amount")).Clear();
|
||||
s.Driver.FindElement(By.Id("Amount")).SendKeys("0.0000001");;
|
||||
s.Driver.FindElement(By.Id("Create")).Click();
|
||||
s.Driver.FindElement(By.LinkText("View")).Click();
|
||||
|
||||
|
||||
s.Driver.FindElement(By.Id("Destination")).SendKeys(lnurl);
|
||||
|
||||
var pullPaymentId = s.Driver.Url.Split('/').Last();
|
||||
s.Driver.FindElement(By.Id("ClaimedAmount")).Clear();
|
||||
s.Driver.FindElement(By.Id("ClaimedAmount")).SendKeys("0.0000001" + Keys.Enter);
|
||||
s.FindAlertMessage();
|
||||
|
||||
|
||||
s.GoToStore(s.StoreId, StoreNavPages.PullPayments);
|
||||
var payouts = s.Driver.FindElements(By.ClassName("pp-payout"));
|
||||
payouts[0].Click();
|
||||
s.Driver.FindElement(By.Id("BTC_LightningLike-view")).Click();
|
||||
Assert.NotEmpty(s.Driver.FindElements(By.ClassName("payout")));
|
||||
s.Driver.FindElement(By.Id($"{PayoutState.AwaitingApproval}-selectAllCheckbox")).Click();
|
||||
s.Driver.FindElement(By.Id($"{PayoutState.AwaitingApproval}-actions")).Click();
|
||||
s.Driver.FindElement(By.Id($"{PayoutState.AwaitingApproval}-approve-pay")).Click();
|
||||
|
||||
Assert.Contains(lnurl, s.Driver.PageSource);
|
||||
|
||||
s.Driver.FindElement(By.Id("pay-invoices-form")).Submit();
|
||||
|
||||
await TestUtils.EventuallyAsync(async () =>
|
||||
{
|
||||
var inv = await s.Server.PayTester.InvoiceRepository.GetInvoice(invForPP);
|
||||
Assert.Equal(InvoiceStatusLegacy.Complete, inv.Status);
|
||||
|
||||
await using var ctx = s.Server.PayTester.GetService<ApplicationDbContextFactory>().CreateContext();
|
||||
var payoutsData = await ctx.Payouts.Where(p => p.PullPaymentDataId == pullPaymentId).ToListAsync();
|
||||
Assert.True(payoutsData.All(p => p.State == PayoutState.Completed));
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
private static void CanBrowseContent(SeleniumTester s)
|
||||
{
|
||||
s.Driver.FindElement(By.ClassName("delivery-content")).Click();
|
||||
|
||||
@@ -63,7 +63,7 @@
|
||||
<PackageReference Include="Fido2" Version="2.0.1" />
|
||||
<PackageReference Include="Fido2.AspNet" Version="2.0.1" />
|
||||
<PackageReference Include="HtmlSanitizer" Version="5.0.372" />
|
||||
<PackageReference Include="LNURL" Version="0.0.8" />
|
||||
<PackageReference Include="LNURL" Version="0.0.13" />
|
||||
<PackageReference Include="McMaster.NETCore.Plugins.Mvc" Version="1.4.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Filter" Version="1.1.2" />
|
||||
<PackageReference Include="Microsoft.NetCore.Analyzers" Version="3.3.2">
|
||||
|
||||
@@ -200,7 +200,8 @@ namespace BTCPayServer.Controllers
|
||||
}
|
||||
else
|
||||
{
|
||||
vm.LNURLEnabled = !lnSet;
|
||||
//disable by default for now
|
||||
//vm.LNURLEnabled = !lnSet;
|
||||
vm.DisableBolt11PaymentMethod = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ namespace BTCPayServer.Models.StoreViewModels
|
||||
public bool LNURLBech32Mode { get; set; } = true;
|
||||
|
||||
[Display(Name = "LNURL enabled for standard invoices")]
|
||||
public bool LNURLStandardInvoiceEnabled { get; set; }
|
||||
public bool LNURLStandardInvoiceEnabled { get; set; } = true;
|
||||
|
||||
[Display(Name = "Allow payee to pass a comment")]
|
||||
public bool LUD12Enabled { get; set; }
|
||||
|
||||
Reference in New Issue
Block a user