From 2da9434571cf22ad00506ad52ebb0222d4788147 Mon Sep 17 00:00:00 2001 From: Kukks Date: Fri, 29 Nov 2019 21:24:52 +0100 Subject: [PATCH 01/12] init work --- .../Controllers/StoresController.BTCLike.cs | 26 ++++++++++++++ .../Views/Stores/AddDerivationScheme.cshtml | 2 ++ ...vationSchemes_HardwareWalletDialogs.cshtml | 3 +- ...DerivationSchemes_NBXWalletGenerate.cshtml | 34 +++++++++++++++++++ 4 files changed, 64 insertions(+), 1 deletion(-) create mode 100644 BTCPayServer/Views/Stores/AddDerivationSchemes_NBXWalletGenerate.cshtml diff --git a/BTCPayServer/Controllers/StoresController.BTCLike.cs b/BTCPayServer/Controllers/StoresController.BTCLike.cs index 23082fb37..f852cf065 100644 --- a/BTCPayServer/Controllers/StoresController.BTCLike.cs +++ b/BTCPayServer/Controllers/StoresController.BTCLike.cs @@ -17,6 +17,7 @@ using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using NBitcoin; using NBXplorer.DerivationStrategy; +using NBXplorer.Models; using Newtonsoft.Json; using Newtonsoft.Json.Linq; @@ -319,6 +320,31 @@ namespace BTCPayServer.Controllers return ShowAddresses(vm, strategy); } + [HttpPost] + [Route("{storeId}/derivations/{cryptoCode}/generatenbxwallet")] + public async Task GenerateNBXWallet(string storeId, string cryptoCode, GenerateWalletRequest request) + { + var network = _NetworkProvider.GetNetwork(cryptoCode); + var client = _ExplorerProvider.GetExplorerClient(cryptoCode); + var response = await client.GenerateWalletAsync(request); + var result = await AddDerivationScheme(storeId, new DerivationSchemeViewModel() + { + Confirmation = false, + Network = network, + RootFingerprint = response.AccountKeyPath.MasterFingerprint.ToString(), + RootKeyPath = response.AccountKeyPath.KeyPath, + CryptoCode = cryptoCode, + DerivationScheme = response.DerivationScheme.ToString(), + Source = "NBXplorer", + AccountKey = response.AccountHDKey.ToWif(), + DerivationSchemeFormat = "BTCPay", + KeyPath = response.AccountKeyPath.KeyPath.ToString(), + Enabled = true + }, cryptoCode); + ((ViewResult)result).ViewName = nameof(AddDerivationScheme); + return result; + } + private async Task ReadAllText(IFormFile file) { using (var stream = new StreamReader(file.OpenReadStream())) diff --git a/BTCPayServer/Views/Stores/AddDerivationScheme.cshtml b/BTCPayServer/Views/Stores/AddDerivationScheme.cshtml index 24b32dd3e..8e7d5af21 100644 --- a/BTCPayServer/Views/Stores/AddDerivationScheme.cshtml +++ b/BTCPayServer/Views/Stores/AddDerivationScheme.cshtml @@ -85,6 +85,8 @@ { } + + diff --git a/BTCPayServer/Views/Stores/AddDerivationSchemes_HardwareWalletDialogs.cshtml b/BTCPayServer/Views/Stores/AddDerivationSchemes_HardwareWalletDialogs.cshtml index ad310e1b3..fb776306a 100644 --- a/BTCPayServer/Views/Stores/AddDerivationSchemes_HardwareWalletDialogs.cshtml +++ b/BTCPayServer/Views/Stores/AddDerivationSchemes_HardwareWalletDialogs.cshtml @@ -1,4 +1,4 @@ -@model DerivationSchemeViewModel +@model DerivationSchemeViewModel - From f284ef9052a6f828c244fbc7eb7f43c01797df2b Mon Sep 17 00:00:00 2001 From: Kukks Date: Thu, 5 Dec 2019 18:56:40 +0100 Subject: [PATCH 03/12] Add generate wallet e2e test --- BTCPayServer.Tests/BTCPayServer.Tests.csproj | 2 +- BTCPayServer.Tests/SeleniumTester.cs | 17 +++++++++++++++++ BTCPayServer.Tests/SeleniumTests.cs | 18 +++++++++++------- .../Controllers/StoresController.BTCLike.cs | 2 +- .../Views/Stores/AddDerivationScheme.cshtml | 6 +++--- ...dDerivationSchemes_NBXWalletGenerate.cshtml | 2 +- 6 files changed, 34 insertions(+), 13 deletions(-) diff --git a/BTCPayServer.Tests/BTCPayServer.Tests.csproj b/BTCPayServer.Tests/BTCPayServer.Tests.csproj index 468bd9bdd..cbd940d42 100644 --- a/BTCPayServer.Tests/BTCPayServer.Tests.csproj +++ b/BTCPayServer.Tests/BTCPayServer.Tests.csproj @@ -1,4 +1,4 @@ - + netcoreapp2.1 diff --git a/BTCPayServer.Tests/SeleniumTester.cs b/BTCPayServer.Tests/SeleniumTester.cs index 50131ad81..fc07aca12 100644 --- a/BTCPayServer.Tests/SeleniumTester.cs +++ b/BTCPayServer.Tests/SeleniumTester.cs @@ -109,6 +109,23 @@ namespace BTCPayServer.Tests return (usr, Driver.FindElement(By.Id("Id")).GetAttribute("value")); } + public string GenerateWallet(string cryptoCode = "BTC", string seed = "") + { + Driver.FindElement(By.Id($"Modify{cryptoCode}")).ForceClick(); + Driver.FindElement(By.Id("import-from-btn")).ForceClick(); + Driver.FindElement(By.Id("nbxplorergeneratewalletbtn")).ForceClick(); + Driver.FindElement(By.Id("ExistingMnemonic")).SendKeys(seed); + Driver.FindElement(By.Id("btn-generate")).ForceClick(); + AssertHappyMessage(); + if (string.IsNullOrEmpty(seed)) + { + seed = Driver.FindElements(By.ClassName("alert-success")).First().FindElement(By.TagName("code")).Text; + } + Driver.FindElement(By.Id("Confirm")).ForceClick(); + AssertHappyMessage(); + return seed; + } + public void AddDerivationScheme(string cryptoCode = "BTC", string derivationScheme = "xpub661MyMwAqRbcGABgHMUXDzPzH1tU7eZaAaJQXhDXsSxsqyQzQeU6kznNfSuAyqAK9UaWSaZaMFdNiY5BCF4zBPAzSnwfUAwUhwttuAKwfRX-[legacy]") { Driver.FindElement(By.Id($"Modify{cryptoCode}")).ForceClick(); diff --git a/BTCPayServer.Tests/SeleniumTests.cs b/BTCPayServer.Tests/SeleniumTests.cs index e6b2c23da..cf5d439be 100644 --- a/BTCPayServer.Tests/SeleniumTests.cs +++ b/BTCPayServer.Tests/SeleniumTests.cs @@ -408,14 +408,18 @@ namespace BTCPayServer.Tests { await s.StartAsync(); s.RegisterNewUser(true); - s.CreateNewStore(); + var storeId = s.CreateNewStore(); // In this test, we try to spend from a manual seed. We import the xpub 49'/0'/0', then try to use the seed // to sign the transaction - var mnemonic = "usage fever hen zero slide mammal silent heavy donate budget pulse say brain thank sausage brand craft about save attract muffin advance illegal cabbage"; + var mnemonic = s.GenerateWallet("BTC", ""); + var root = new Mnemonic(mnemonic).DeriveExtKey(); - s.AddDerivationScheme("BTC", "ypub6WWc2gWwHbdnAAyJDnR4SPL1phRh7REqrPBfZeizaQ1EmTshieRXJC3Z5YoU4wkcdKHEjQGkh6AYEzCQC1Kz3DNaWSwdc1pc8416hAjzqyD"); - var tx = s.Server.ExplorerNode.SendToAddress(BitcoinAddress.Create("bcrt1qmxg8fgnmkp354vhe78j6sr4ut64tyz2xyejel4", Network.RegTest), Money.Coins(3.0m)); + var invoiceId = s.CreateInvoice(storeId.storeId); + var invoice = await s.Server.PayTester.InvoiceRepository.GetInvoice( invoiceId); + var address = invoice.EntityToDTO().Addresses["BTC"]; + + var tx = s.Server.ExplorerNode.SendToAddress(BitcoinAddress.Create(address, Network.RegTest), Money.Coins(3.0m)); s.Server.ExplorerNode.Generate(1); s.Driver.FindElement(By.Id("Wallets")).Click(); @@ -429,8 +433,8 @@ namespace BTCPayServer.Tests // We setup the fingerprint and the account key path s.Driver.FindElement(By.Id("WalletSettings")).ForceClick(); - s.Driver.FindElement(By.Id("AccountKeys_0__MasterFingerprint")).SendKeys("8bafd160"); - s.Driver.FindElement(By.Id("AccountKeys_0__AccountKeyPath")).SendKeys("m/49'/0'/0'" + Keys.Enter); +// s.Driver.FindElement(By.Id("AccountKeys_0__MasterFingerprint")).SendKeys("8bafd160"); +// s.Driver.FindElement(By.Id("AccountKeys_0__AccountKeyPath")).SendKeys("m/49'/0'/0'" + Keys.Enter); // Check the tx sent earlier arrived s.Driver.FindElement(By.Id("WalletTransactions")).ForceClick(); @@ -471,7 +475,7 @@ namespace BTCPayServer.Tests } } SignWith(mnemonic); - var accountKey = root.Derive(new KeyPath("m/49'/0'/0'")).GetWif(Network.RegTest).ToString(); + var accountKey = root.Derive(new KeyPath("m/84'/1'/0'")).GetWif(Network.RegTest).ToString(); SignWith(accountKey); } } diff --git a/BTCPayServer/Controllers/StoresController.BTCLike.cs b/BTCPayServer/Controllers/StoresController.BTCLike.cs index 60b8bc0d0..af1cb662a 100644 --- a/BTCPayServer/Controllers/StoresController.BTCLike.cs +++ b/BTCPayServer/Controllers/StoresController.BTCLike.cs @@ -334,7 +334,7 @@ namespace BTCPayServer.Controllers Confirmation = false, Network = network, RootFingerprint = response.AccountKeyPath.MasterFingerprint.ToString(), - RootKeyPath = response.AccountKeyPath.KeyPath, + RootKeyPath = network.GetRootKeyPath(), CryptoCode = cryptoCode, DerivationScheme = response.DerivationScheme.ToString(), Source = "NBXplorer", diff --git a/BTCPayServer/Views/Stores/AddDerivationScheme.cshtml b/BTCPayServer/Views/Stores/AddDerivationScheme.cshtml index 8e7d5af21..7e8e444bb 100644 --- a/BTCPayServer/Views/Stores/AddDerivationScheme.cshtml +++ b/BTCPayServer/Views/Stores/AddDerivationScheme.cshtml @@ -34,7 +34,7 @@ { - From 45e139c5b7c1fcf15853e2cc25ad531ca0d0621f Mon Sep 17 00:00:00 2001 From: Kukks Date: Mon, 16 Dec 2019 09:35:41 +0100 Subject: [PATCH 09/12] define view --- BTCPayServer/Controllers/StoresController.BTCLike.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/BTCPayServer/Controllers/StoresController.BTCLike.cs b/BTCPayServer/Controllers/StoresController.BTCLike.cs index dfd102639..3cb95c69d 100644 --- a/BTCPayServer/Controllers/StoresController.BTCLike.cs +++ b/BTCPayServer/Controllers/StoresController.BTCLike.cs @@ -180,7 +180,7 @@ namespace BTCPayServer.Controllers Message = "Config file was not in the correct format" }); vm.Confirmation = false; - return View("AddDerivationScheme",vm); + return View(nameof(AddDerivationScheme),vm); } } @@ -194,7 +194,7 @@ namespace BTCPayServer.Controllers Message = "Coldcard public file was not in the correct format" }); vm.Confirmation = false; - return View(vm); + return View(nameof(AddDerivationScheme),vm); } } else @@ -230,7 +230,7 @@ namespace BTCPayServer.Controllers { ModelState.AddModelError(nameof(vm.DerivationScheme), "Invalid Derivation Scheme"); vm.Confirmation = false; - return View(vm); + return View(nameof(AddDerivationScheme),vm); } } From 9142c48a0b8b92f66d21f2f38baebee3477ef71c Mon Sep 17 00:00:00 2001 From: Kukks Date: Mon, 16 Dec 2019 09:38:00 +0100 Subject: [PATCH 10/12] return correct view --- BTCPayServer/Controllers/StoresController.BTCLike.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BTCPayServer/Controllers/StoresController.BTCLike.cs b/BTCPayServer/Controllers/StoresController.BTCLike.cs index 3cb95c69d..4809d296f 100644 --- a/BTCPayServer/Controllers/StoresController.BTCLike.cs +++ b/BTCPayServer/Controllers/StoresController.BTCLike.cs @@ -389,7 +389,7 @@ namespace BTCPayServer.Controllers } vm.Confirmation = true; ModelState.Remove(nameof(vm.Config)); // Remove the cached value - return View(vm); + return View(nameof(AddDerivationScheme),vm); } private bool CanUseGenerateWallet() From 1aef7f7ea6ff8dc323357d50fba95bcae6355c82 Mon Sep 17 00:00:00 2001 From: Kukks Date: Mon, 16 Dec 2019 10:25:07 +0100 Subject: [PATCH 11/12] rebase fix --- BTCPayServer/Views/Stores/AddDerivationScheme.cshtml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/BTCPayServer/Views/Stores/AddDerivationScheme.cshtml b/BTCPayServer/Views/Stores/AddDerivationScheme.cshtml index 3321e0a92..f2c3cba43 100644 --- a/BTCPayServer/Views/Stores/AddDerivationScheme.cshtml +++ b/BTCPayServer/Views/Stores/AddDerivationScheme.cshtml @@ -34,7 +34,7 @@ { } -
+ From 7cfe5f042167f3ad10a5d0372edf6b61ec6b5c62 Mon Sep 17 00:00:00 2001 From: Kukks Date: Mon, 16 Dec 2019 12:10:03 +0100 Subject: [PATCH 12/12] failsafe with selenium --- BTCPayServer.Tests/SeleniumTester.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/BTCPayServer.Tests/SeleniumTester.cs b/BTCPayServer.Tests/SeleniumTester.cs index 3e742ea0e..a58e06011 100644 --- a/BTCPayServer.Tests/SeleniumTester.cs +++ b/BTCPayServer.Tests/SeleniumTester.cs @@ -238,6 +238,11 @@ namespace BTCPayServer.Tests { element.Click(); } + + if (value != element.Selected) + { + SetCheckbox(element, value); + } } public void SetCheckbox(SeleniumTester s, string inputName, bool value)