diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml index f025bc0..403be6a 100644 --- a/.github/workflows/dotnet.yml +++ b/.github/workflows/dotnet.yml @@ -31,7 +31,7 @@ jobs: run: dotnet clean - name: Build projects - run: dotnet build -c Release --no-restore + run: dotnet build -maxcpucount:1 -c Release --no-restore - name: Deterministic build check run: | diff --git a/BTCPayServer.Plugins.IntegrationTests/BTCPayServer.Plugins.IntegrationTests.csproj b/BTCPayServer.Plugins.IntegrationTests/BTCPayServer.Plugins.IntegrationTests.csproj index 5487a18..b0e1029 100644 --- a/BTCPayServer.Plugins.IntegrationTests/BTCPayServer.Plugins.IntegrationTests.csproj +++ b/BTCPayServer.Plugins.IntegrationTests/BTCPayServer.Plugins.IntegrationTests.csproj @@ -8,9 +8,10 @@ - - - + + + + all runtime; build; native; contentfiles; analyzers; buildtransitive @@ -26,8 +27,8 @@ - - + + diff --git a/BTCPayServer.Plugins.IntegrationTests/Monero/MoneroPluginIntegrationTest.cs b/BTCPayServer.Plugins.IntegrationTests/Monero/MoneroPluginIntegrationTest.cs index 670e03b..ae2aec3 100644 --- a/BTCPayServer.Plugins.IntegrationTests/Monero/MoneroPluginIntegrationTest.cs +++ b/BTCPayServer.Plugins.IntegrationTests/Monero/MoneroPluginIntegrationTest.cs @@ -1,5 +1,9 @@ +using System.Diagnostics; + +using BTCPayServer.Plugins.Monero.Services; using BTCPayServer.Rating; using BTCPayServer.Services.Rates; +using BTCPayServer.Tests; using BTCPayServer.Tests.Mocks; using Xunit; @@ -36,20 +40,25 @@ public class MoneroPluginIntegrationTest(ITestOutputHelper helper) : MoneroAndBi await s.RegisterNewUser(true); await s.CreateNewStore(preferredExchange: "Kraken"); await s.Page.Locator("a.nav-link[href*='monerolike/XMR']").ClickAsync(); - await s.Page.Locator("input#PrimaryAddress").FillAsync("43Pnj6ZKGFTJhaLhiecSFfLfr64KPJZw7MyGH73T6PTDekBBvsTAaWEUSM4bmJqDuYLizhA13jQkMRPpz9VXBCBqQQb6y5L"); - await s.Page.Locator("input#PrivateViewKey").FillAsync("1bfa03b0c78aa6bc8292cf160ec9875657d61e889c41d0ebe5c54fd3a2c4b40e"); + await s.Page.Locator("input#PrimaryAddress") + .FillAsync( + "43Pnj6ZKGFTJhaLhiecSFfLfr64KPJZw7MyGH73T6PTDekBBvsTAaWEUSM4bmJqDuYLizhA13jQkMRPpz9VXBCBqQQb6y5L"); + await s.Page.Locator("input#PrivateViewKey") + .FillAsync("1bfa03b0c78aa6bc8292cf160ec9875657d61e889c41d0ebe5c54fd3a2c4b40e"); await s.Page.Locator("input#RestoreHeight").FillAsync("0"); await s.Page.Locator("input#WalletPassword").FillAsync("pass123"); await s.Page.ClickAsync("button[name='command'][value='set-wallet-details']"); await s.Page.CheckAsync("#Enabled"); await s.Page.SelectOptionAsync("#SettlementConfirmationThresholdChoice", "2"); await s.Page.ClickAsync("#SaveButton"); - var classList = await s.Page.Locator("svg.icon-checkmark").GetAttributeAsync("class"); + var classList = await s.Page + .Locator("svg.icon-checkmark") + .GetAttributeAsync("class"); Assert.Contains("text-success", classList); // Set rate provider - await s.Page.Locator("#StoreNav-General").ClickAsync(); - await s.Page.Locator("#mainNav #StoreNav-Rates").ClickAsync(); + await s.Page.Locator("#menu-item-General").ClickAsync(); + await s.Page.Locator("#menu-item-Rates").ClickAsync(); await s.Page.FillAsync("#DefaultCurrencyPairs", "BTC_USD,XMR_USD,XMR_BTC"); await s.Page.SelectOptionAsync("#PrimarySource_PreferredExchange", "kraken"); await s.Page.Locator("#page-primary").ClickAsync(); @@ -69,7 +78,9 @@ public class MoneroPluginIntegrationTest(ITestOutputHelper helper) : MoneroAndBi await s.Page.ClickAsync("#DetailsToggle"); // Verify the total fiat amount is $4.20 - var totalFiat = await s.Page.Locator("#PaymentDetails-TotalFiat dd.clipboard-button").InnerTextAsync(); + var totalFiat = await s.Page + .Locator("#PaymentDetails-TotalFiat dd.clipboard-button") + .InnerTextAsync(); Assert.Equal("$4.20", totalFiat); await s.Page.GoBackAsync(); @@ -92,5 +103,90 @@ public class MoneroPluginIntegrationTest(ITestOutputHelper helper) : MoneroAndBi // Select confirmation time to 0 await s.Page.SelectOptionAsync("#SettlementConfirmationThresholdChoice", "3"); await s.Page.ClickAsync("#SaveButton"); + + await CleanUp(s); + } + + [Fact] + public async Task ShouldFailWhenWrongPrimaryAddress() + { + await using var s = CreatePlaywrightTester(); + await s.StartAsync(); + + await s.RegisterNewUser(true); + await s.CreateNewStore(); + await s.Page.Locator("a.nav-link[href*='monerolike/XMR']").ClickAsync(); + await s.Page.Locator("input#PrimaryAddress") + .FillAsync("wrongprimaryaddressfSF6ZKGFT7MyGH73T6PTDekBBvsTAaWEUSM4bmJqDuYLizhA13jQkMRPpz9VXBCBqQQb6y5L"); + await s.Page.Locator("input#PrivateViewKey") + .FillAsync("1bfa03b0c78aa6bc8292cf160ec9875657d61e889c41d0ebe5c54fd3a2c4b40e"); + await s.Page.Locator("input#RestoreHeight").FillAsync("0"); + await s.Page.Locator("input#WalletPassword").FillAsync("pass123"); + await s.Page.ClickAsync("button[name='command'][value='set-wallet-details']"); + var errorText = await s.Page + .Locator("div.validation-summary-errors li") + .InnerTextAsync(); + + Assert.Equal("Could not generate view wallet from keys: Failed to parse public address", errorText); + + await CleanUp(s); + } + + private static async Task CleanUp(PlaywrightTester playwrightTester) + { + MoneroRPCProvider moneroRpcProvider = playwrightTester.Server.PayTester.GetService(); + if (moneroRpcProvider.IsAvailable("XMR")) + { + await moneroRpcProvider.CloseWallet("XMR"); + await moneroRpcProvider.UpdateSummary("XMR"); + } + + if (playwrightTester.Server.PayTester.InContainer) + { + moneroRpcProvider.DeleteWallet(); + } + else + { + await RemoveWalletFromLocalDocker(); + } + } + + static async Task RemoveWalletFromLocalDocker() + { + try + { + var removeWalletFromDocker = new ProcessStartInfo + { + FileName = "docker", + Arguments = "exec xmr_wallet sh -c \"rm -rf /wallet/*\"", + RedirectStandardOutput = true, + RedirectStandardError = true + }; + + using var process = Process.Start(removeWalletFromDocker); + if (process is null) + { + return; + } + + var stdout = await process.StandardOutput.ReadToEndAsync(); + var stderr = await process.StandardError.ReadToEndAsync(); + + await process.WaitForExitAsync(); + + if (!string.IsNullOrWhiteSpace(stdout)) + { + Console.WriteLine(stdout); + } + + if (!string.IsNullOrWhiteSpace(stderr)) + { + Console.WriteLine(stderr); + } + } + catch (Exception ex) + { + Console.WriteLine($"Cleanup failed: {ex}"); + } } } \ No newline at end of file diff --git a/BTCPayServer.Plugins.IntegrationTests/docker-compose.yml b/BTCPayServer.Plugins.IntegrationTests/docker-compose.yml index 64e1d79..cc69d76 100644 --- a/BTCPayServer.Plugins.IntegrationTests/docker-compose.yml +++ b/BTCPayServer.Plugins.IntegrationTests/docker-compose.yml @@ -22,6 +22,7 @@ services: - "tests:127.0.0.1" volumes: - ../coverage:/coverage + - xmr_wallet:/wallet # The dev container is not used, it is just handy to run `docker-compose up dev` to start all services dev: @@ -89,7 +90,7 @@ services: - "bitcoin_datadir:/data" monerod: - image: btcpayserver/monero:0.18.4.2 + image: btcpayserver/monero:0.18.4.3 restart: unless-stopped container_name: monerod command: monerod --fixed-difficulty 1 --log-level=2 --rpc-bind-ip=0.0.0.0 --confirm-external-bind --rpc-bind-port=18081 --block-notify="/bin/sh ./scripts/notifier.sh -k -X GET https://host.docker.internal:14142/monerolikedaemoncallback/block?cryptoCode=xmr&hash=%s" --regtest --no-igd --hide-my-port --offline --non-interactive @@ -99,7 +100,7 @@ services: - "18081:18081" xmr_wallet: - image: btcpayserver/monero:0.18.4.2 + image: btcpayserver/monero:0.18.4.3 restart: unless-stopped container_name: xmr_wallet command: monero-wallet-rpc --log-level 2 --allow-mismatched-daemon-version --rpc-bind-ip=0.0.0.0 --disable-rpc-login --confirm-external-bind --rpc-bind-port=18082 --non-interactive --trusted-daemon --daemon-address=monerod:18081 --wallet-dir=/wallet --tx-notify="/bin/sh ./scripts/notifier.sh -k -X GET https://host.docker.internal:14142/monerolikedaemoncallback/tx?cryptoCode=xmr&hash=%s" diff --git a/Plugins/Monero/BTCPayServer.Plugins.Monero.csproj b/Plugins/Monero/BTCPayServer.Plugins.Monero.csproj index 3287596..4a848b8 100644 --- a/Plugins/Monero/BTCPayServer.Plugins.Monero.csproj +++ b/Plugins/Monero/BTCPayServer.Plugins.Monero.csproj @@ -39,10 +39,7 @@ - - -