Merge pull request #2575 from NicolasDorier/refactor/wallet-cleanup

Cleanup some old code in wallet setup
This commit is contained in:
Nicolas Dorier
2021-06-17 21:20:28 +09:00
committed by GitHub
11 changed files with 122 additions and 224 deletions

View File

@@ -954,28 +954,6 @@ normal:
result = testnetParser.Parse(tpub);
Assert.Equal(tpub, result.ToString());
testnetParser.HintScriptPubKey = BitcoinAddress
.Create("tb1q4s33amqm8l7a07zdxcunqnn3gcsjcfz3xc573l", testnetParser.Network).ScriptPubKey;
result = testnetParser.Parse(tpub);
Assert.Equal(tpub, result.ToString());
testnetParser.HintScriptPubKey = BitcoinAddress
.Create("2N2humNio3YTApSfY6VztQ9hQwDnhDvaqFQ", testnetParser.Network).ScriptPubKey;
result = testnetParser.Parse(tpub);
Assert.Equal($"{tpub}-[p2sh]", result.ToString());
testnetParser.HintScriptPubKey = BitcoinAddress
.Create("mwD8bHS65cdgUf6rZUUSoVhi3wNQFu1Nfi", testnetParser.Network).ScriptPubKey;
result = testnetParser.Parse(tpub);
Assert.Equal($"{tpub}-[legacy]", result.ToString());
testnetParser.HintScriptPubKey = BitcoinAddress
.Create("2N2humNio3YTApSfY6VztQ9hQwDnhDvaqFQ", testnetParser.Network).ScriptPubKey;
result = testnetParser.Parse($"{tpub}-[legacy]");
Assert.Equal($"{tpub}-[p2sh]", result.ToString());
result = testnetParser.Parse(tpub);
Assert.Equal($"{tpub}-[p2sh]", result.ToString());
var regtestParser = new DerivationSchemeParser(regtestNetworkProvider.GetNetwork<BTCPayNetwork>("BTC"));
var parsed =

View File

@@ -179,30 +179,18 @@ namespace BTCPayServer.Tests
if (StoreId is null)
await CreateStoreAsync();
SupportedNetwork = parent.NetworkProvider.GetNetwork<BTCPayNetwork>(cryptoCode);
var store = parent.PayTester.GetController<StoresController>(UserId, StoreId);
GenerateWalletResponseV = await parent.ExplorerClient.GenerateWalletAsync(new GenerateWalletRequest()
var store = parent.PayTester.GetController<StoresController>(UserId, StoreId, true);
var generateRequest = new GenerateWalletRequest()
{
ScriptPubKeyType = segwit,
SavePrivateKeys = importKeysToNBX,
ImportKeysToRPC = importsKeysToBitcoinCore
});
await store.UpdateWallet(
new WalletSetupViewModel
{
StoreId = StoreId,
Method = importKeysToNBX ? WalletSetupMethod.HotWallet : WalletSetupMethod.WatchOnly,
Enabled = true,
CryptoCode = cryptoCode,
Network = SupportedNetwork,
RootFingerprint = GenerateWalletResponseV.AccountKeyPath.MasterFingerprint.ToString(),
RootKeyPath = SupportedNetwork.GetRootKeyPath(),
Source = "NBXplorer",
AccountKey = GenerateWalletResponseV.AccountHDKey.Neuter().ToWif(),
DerivationSchemeFormat = "BTCPay",
KeyPath = GenerateWalletResponseV.AccountKeyPath.KeyPath.ToString(),
DerivationScheme = DerivationScheme.ToString(),
Confirmation = true
});
};
await store.GenerateWallet(StoreId, cryptoCode, WalletSetupMethod.HotWallet, generateRequest);
Assert.NotNull(store.GenerateWalletResponse);
GenerateWalletResponseV = store.GenerateWalletResponse;
return new WalletId(StoreId, cryptoCode);
}

View File

@@ -1,6 +1,7 @@
using System;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using BTCPayServer.Abstractions.Extensions;
using BTCPayServer.Abstractions.Models;
@@ -11,9 +12,11 @@ using BTCPayServer.Models;
using BTCPayServer.Models.StoreViewModels;
using BTCPayServer.Payments;
using BTCPayServer.Services;
using ExchangeSharp;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.ModelBinding.Metadata;
using NBitcoin;
using NBXplorer;
using NBXplorer.DerivationStrategy;
@@ -85,15 +88,6 @@ namespace BTCPayServer.Controllers
return NotFound();
}
if (!string.IsNullOrEmpty(vm.Config))
{
if (!DerivationSchemeSettings.TryParseFromJson(vm.Config, network, out strategy))
{
ModelState.AddModelError(nameof(vm.Config), "Config file was not in the correct format");
return View(vm.ViewName, vm);
}
}
if (vm.WalletFile != null)
{
if (!DerivationSchemeSettings.TryParseFromWalletFile(await ReadAllText(vm.WalletFile), network, out strategy))
@@ -114,16 +108,13 @@ namespace BTCPayServer.Controllers
{
try
{
var newStrategy = ParseDerivationStrategy(vm.DerivationScheme, null, network);
if (newStrategy.AccountDerivation != strategy?.AccountDerivation)
{
var accountKey = string.IsNullOrEmpty(vm.AccountKey)
? null
: new BitcoinExtPubKey(vm.AccountKey, network.NBitcoinNetwork);
if (accountKey != null)
strategy = ParseDerivationStrategy(vm.DerivationScheme, network);
strategy.Source = "ManualDerivationScheme";
if (!string.IsNullOrEmpty(vm.AccountKey))
{
var accountKey = new BitcoinExtPubKey(vm.AccountKey, network.NBitcoinNetwork);
var accountSettings =
newStrategy.AccountKeySettings.FirstOrDefault(a => a.AccountKey == accountKey);
strategy.AccountKeySettings.FirstOrDefault(a => a.AccountKey == accountKey);
if (accountSettings != null)
{
accountSettings.AccountKeyPath =
@@ -134,11 +125,8 @@ namespace BTCPayServer.Controllers
NBitcoin.DataEncoders.Encoders.Hex.DecodeData(vm.RootFingerprint));
}
}
strategy = newStrategy;
strategy.Source = vm.Source;
vm.DerivationScheme = strategy.AccountDerivation.ToString();
}
ModelState.Remove(nameof(vm.DerivationScheme));
}
catch
{
@@ -146,34 +134,33 @@ namespace BTCPayServer.Controllers
return View(vm.ViewName, vm);
}
}
else
else if (!string.IsNullOrEmpty(vm.Config))
{
if (!DerivationSchemeSettings.TryParseFromJson(UnprotectString(vm.Config), network, out strategy))
{
ModelState.AddModelError(nameof(vm.Config), "Config file was not in the correct format");
return View(vm.ViewName, vm);
}
}
if (strategy is null)
{
ModelState.AddModelError(nameof(vm.DerivationScheme), "Please provide your extended public key");
return View(vm.ViewName, vm);
}
var oldConfig = vm.Config;
vm.Config = strategy?.ToJson();
var configChanged = oldConfig != vm.Config;
vm.Config = ProtectString(strategy.ToJson());
ModelState.Remove(nameof(vm.Config));
PaymentMethodId paymentMethodId = new PaymentMethodId(network.CryptoCode, PaymentTypes.BTCLike);
var storeBlob = store.GetStoreBlob();
var willBeExcluded = !vm.Enabled;
var showAddress = // Show addresses if:
// - If the user is testing the hint address in confirmation screen
(vm.Confirmation && !string.IsNullOrWhiteSpace(vm.HintAddress)) ||
// - The user is clicking on continue after changing the config
(!vm.Confirmation && configChanged);
showAddress = showAddress && strategy != null;
if (!showAddress)
if (vm.Confirmation)
{
try
{
if (strategy != null)
await wallet.TrackAsync(strategy.AccountDerivation);
store.SetSupportedPaymentMethod(paymentMethodId, strategy);
storeBlob.SetExcluded(paymentMethodId, willBeExcluded);
storeBlob.SetExcluded(paymentMethodId, false);
storeBlob.Hints.Wallet = false;
store.SetStoreBlob(storeBlob);
}
@@ -184,50 +171,23 @@ namespace BTCPayServer.Controllers
}
await _Repo.UpdateStore(store);
_EventAggregator.Publish(new WalletChangedEvent {WalletId = new WalletId(vm.StoreId, vm.CryptoCode)});
_EventAggregator.Publish(new WalletChangedEvent { WalletId = new WalletId(vm.StoreId, vm.CryptoCode) });
TempData[WellKnownTempData.SuccessMessage] = $"Wallet settings for {network.CryptoCode} have been updated.";
// This is success case when derivation scheme is added to the store
return RedirectToAction(nameof(UpdateStore), new {storeId = vm.StoreId});
return RedirectToAction(nameof(UpdateStore), new { storeId = vm.StoreId });
}
if (!string.IsNullOrEmpty(vm.HintAddress))
{
BitcoinAddress address;
try
{
address = BitcoinAddress.Create(vm.HintAddress, network.NBitcoinNetwork);
}
catch
{
ModelState.AddModelError(nameof(vm.HintAddress), "Invalid hint address");
return ConfirmAddresses(vm, strategy);
}
try
private string ProtectString(string str)
{
var newStrategy = ParseDerivationStrategy(vm.DerivationScheme, address.ScriptPubKey, network);
if (newStrategy.AccountDerivation != strategy.AccountDerivation)
return Convert.ToBase64String(DataProtector.Protect(Encoding.UTF8.GetBytes(str)));
}
private string UnprotectString(string str)
{
strategy.AccountDerivation = newStrategy.AccountDerivation;
strategy.AccountOriginal = null;
}
}
catch
{
ModelState.AddModelError(nameof(vm.HintAddress), "Impossible to find a match with this address. Are you sure the wallet and address provided are correct and from the same source?");
return ConfirmAddresses(vm, strategy);
}
vm.HintAddress = "";
TempData[WellKnownTempData.SuccessMessage] =
"Address successfully found, please verify that the rest is correct and click on \"Confirm\"";
ModelState.Remove(nameof(vm.HintAddress));
ModelState.Remove(nameof(vm.DerivationScheme));
}
return ConfirmAddresses(vm, strategy);
return Encoding.UTF8.GetString(DataProtector.Unprotect(Convert.FromBase64String(str)));
}
[HttpGet("{storeId}/onchain/{cryptoCode}/generate/{method?}")]
@@ -246,14 +206,6 @@ namespace BTCPayServer.Controllers
return NotFound();
}
var derivation = GetExistingDerivationStrategy(vm.CryptoCode, store);
if (derivation != null)
{
vm.DerivationScheme = derivation.AccountDerivation.ToString();
vm.Config = derivation.ToJson();
}
vm.Enabled = !store.GetStoreBlob().IsExcluded(new PaymentMethodId(vm.CryptoCode, PaymentTypes.BTCLike));
vm.CanUseHotWallet = hotWallet;
vm.CanUseRPCImport = rpcImport;
vm.RootKeyPath = network.GetRootKeyPath();
@@ -270,7 +222,7 @@ namespace BTCPayServer.Controllers
return View(vm.ViewName, vm);
}
internal GenerateWalletResponse GenerateWalletResponse;
[HttpPost("{storeId}/onchain/{cryptoCode}/generate/{method}")]
public async Task<IActionResult> GenerateWallet(string storeId, string cryptoCode, WalletSetupMethod method, GenerateWalletRequest request)
{
@@ -288,6 +240,7 @@ namespace BTCPayServer.Controllers
var client = _ExplorerProvider.GetExplorerClient(cryptoCode);
var isImport = method == WalletSetupMethod.Seed;
var vm = new WalletSetupViewModel
{
StoreId = storeId,
@@ -297,8 +250,8 @@ namespace BTCPayServer.Controllers
Confirmation = string.IsNullOrEmpty(request.ExistingMnemonic),
Network = network,
RootKeyPath = network.GetRootKeyPath(),
Enabled = !store.GetStoreBlob().IsExcluded(new PaymentMethodId(cryptoCode, PaymentTypes.BTCLike)),
Source = "NBXplorer",
Source = isImport ? "SeedImported" : "NBXplorerGenerated",
IsHotWallet = isImport ? request.SavePrivateKeys : method == WalletSetupMethod.HotWallet,
DerivationSchemeFormat = "BTCPay",
CanUseHotWallet = true,
CanUseRPCImport = rpcImport
@@ -329,11 +282,26 @@ namespace BTCPayServer.Controllers
return View(vm.ViewName, vm);
}
var derivationSchemeSettings = new DerivationSchemeSettings(response.DerivationScheme, network);
if (method == WalletSetupMethod.Seed)
{
derivationSchemeSettings.Source = "ImportedSeed";
derivationSchemeSettings.IsHotWallet = request.SavePrivateKeys;
}
else
{
derivationSchemeSettings.Source = "NBXplorerGenerated";
derivationSchemeSettings.IsHotWallet = method == WalletSetupMethod.HotWallet;
}
var accountSettings = derivationSchemeSettings.GetSigningAccountKeySettings();
accountSettings.AccountKeyPath = response.AccountKeyPath.KeyPath;
accountSettings.RootFingerprint = response.AccountKeyPath.MasterFingerprint;
derivationSchemeSettings.AccountOriginal = response.DerivationScheme.ToString();
// Set wallet properties from generate response
vm.RootFingerprint = response.AccountKeyPath.MasterFingerprint.ToString();
vm.DerivationScheme = response.DerivationScheme.ToString();
vm.AccountKey = response.AccountHDKey.Neuter().ToWif();
vm.KeyPath = response.AccountKeyPath.KeyPath.ToString();
vm.Config = ProtectString(derivationSchemeSettings.ToJson());
var result = await UpdateWallet(vm);
@@ -353,8 +321,12 @@ namespace BTCPayServer.Controllers
Mnemonic = response.Mnemonic,
Passphrase = response.Passphrase,
IsStored = request.SavePrivateKeys,
ReturnUrl = Url.Action(nameof(GenerateWalletConfirm), new {storeId, cryptoCode})
ReturnUrl = Url.Action(nameof(GenerateWalletConfirm), new { storeId, cryptoCode })
};
if (this._BTCPayEnv.IsDeveloping)
{
GenerateWalletResponse = response;
}
return this.RedirectToRecoverySeedBackup(seedVm);
}
@@ -379,7 +351,7 @@ namespace BTCPayServer.Controllers
TempData[WellKnownTempData.SuccessMessage] = $"Wallet settings for {network.CryptoCode} have been updated.";
return RedirectToAction(nameof(UpdateStore), new {storeId});
return RedirectToAction(nameof(UpdateStore), new { storeId });
}
[HttpGet("{storeId}/onchain/{cryptoCode}/modify")]
@@ -408,8 +380,7 @@ namespace BTCPayServer.Controllers
vm.RootFingerprint = derivation.GetSigningAccountKeySettings().RootFingerprint.ToString();
vm.DerivationScheme = derivation.AccountDerivation.ToString();
vm.KeyPath = derivation.GetSigningAccountKeySettings().AccountKeyPath?.ToString();
vm.Config = derivation.ToJson();
vm.Enabled = !store.GetStoreBlob().IsExcluded(new PaymentMethodId(vm.CryptoCode, PaymentTypes.BTCLike));
vm.Config = ProtectString(derivation.ToJson());
vm.IsHotWallet = isHotWallet;
return View(vm);
@@ -460,7 +431,7 @@ namespace BTCPayServer.Controllers
return NotFound();
}
return RedirectToAction(nameof(SetupWallet), new {storeId, cryptoCode});
return RedirectToAction(nameof(SetupWallet), new { storeId, cryptoCode });
}
[HttpGet("{storeId}/onchain/{cryptoCode}/delete")]
@@ -519,12 +490,12 @@ namespace BTCPayServer.Controllers
storeBlob.SetExcluded(paymentMethodId, !enabled);
store.SetStoreBlob(storeBlob);
await _Repo.UpdateStore(store);
_EventAggregator.Publish(new WalletChangedEvent {WalletId = new WalletId(storeId, cryptoCode)});
_EventAggregator.Publish(new WalletChangedEvent { WalletId = new WalletId(storeId, cryptoCode) });
TempData[WellKnownTempData.SuccessMessage] =
$"{network.CryptoCode} on-chain payments are now {(enabled ? "enabled" : "disabled")} for this store.";
return RedirectToAction(nameof(UpdateStore), new {storeId});
return RedirectToAction(nameof(UpdateStore), new { storeId });
}
[HttpPost("{storeId}/onchain/{cryptoCode}/delete")]
@@ -546,12 +517,12 @@ namespace BTCPayServer.Controllers
store.SetSupportedPaymentMethod(paymentMethodId, null);
await _Repo.UpdateStore(store);
_EventAggregator.Publish(new WalletChangedEvent {WalletId = new WalletId(storeId, cryptoCode)});
_EventAggregator.Publish(new WalletChangedEvent { WalletId = new WalletId(storeId, cryptoCode) });
TempData[WellKnownTempData.SuccessMessage] =
$"On-Chain payment for {network.CryptoCode} has been removed.";
return RedirectToAction(nameof(UpdateStore), new {storeId});
return RedirectToAction(nameof(UpdateStore), new { storeId });
}
private IActionResult ConfirmAddresses(WalletSetupViewModel vm, DerivationSchemeSettings strategy)

View File

@@ -27,6 +27,7 @@ using BTCPayServer.Services.Stores;
using BTCPayServer.Services.Wallets;
using BundlerMinifier.TagHelpers;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.DataProtection;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
@@ -69,7 +70,8 @@ namespace BTCPayServer.Controllers
AppService appService,
IWebHostEnvironment webHostEnvironment,
WebhookNotificationManager webhookNotificationManager,
IOptions<LightningNetworkOptions> lightningNetworkOptions)
IOptions<LightningNetworkOptions> lightningNetworkOptions,
IDataProtectionProvider dataProtector)
{
_RateFactory = rateFactory;
_Repo = repo;
@@ -85,6 +87,7 @@ namespace BTCPayServer.Controllers
_appService = appService;
_webHostEnvironment = webHostEnvironment;
_lightningNetworkOptions = lightningNetworkOptions;
DataProtector = dataProtector.CreateProtector("ConfigProtector");
WebhookNotificationManager = webhookNotificationManager;
_EventAggregator = eventAggregator;
_NetworkProvider = networkProvider;
@@ -689,10 +692,9 @@ namespace BTCPayServer.Controllers
}
private DerivationSchemeSettings ParseDerivationStrategy(string derivationScheme, Script hint, BTCPayNetwork network)
private DerivationSchemeSettings ParseDerivationStrategy(string derivationScheme, BTCPayNetwork network)
{
var parser = new DerivationSchemeParser(network);
parser.HintScriptPubKey = hint;
try
{
var derivationSchemeSettings = new DerivationSchemeSettings();
@@ -827,6 +829,7 @@ namespace BTCPayServer.Controllers
public string GeneratedPairingCode { get; set; }
public WebhookNotificationManager WebhookNotificationManager { get; }
public IDataProtector DataProtector { get; }
[HttpGet]
[Route("{storeId}/Tokens/Create")]

View File

@@ -1088,7 +1088,9 @@ namespace BTCPayServer.Controllers
DerivationScheme = derivationSchemeSettings.AccountDerivation.ToString(),
DerivationSchemeInput = derivationSchemeSettings.AccountOriginal,
SelectedSigningKey = derivationSchemeSettings.SigningKey.ToString(),
NBXSeedAvailable = await CanUseHotWallet() && !string.IsNullOrEmpty(await ExplorerClientProvider.GetExplorerClient(walletId.CryptoCode)
NBXSeedAvailable = derivationSchemeSettings.IsHotWallet &&
await CanUseHotWallet() &&
!string.IsNullOrEmpty(await ExplorerClientProvider.GetExplorerClient(walletId.CryptoCode)
.GetMetadataAsync<string>(GetDerivationSchemeSettings(walletId).AccountDerivation,
WellknownMetadataKeys.MasterHDKey))
};

View File

@@ -13,8 +13,6 @@ namespace BTCPayServer
public Network Network => BtcPayNetwork.NBitcoinNetwork;
public Script HintScriptPubKey { get; set; }
public DerivationSchemeParser(BTCPayNetwork expectedNetwork)
{
if (expectedNetwork == null)
@@ -131,19 +129,6 @@ namespace BTCPayServer
HashSet<string> hintedLabels = new HashSet<string>();
var hintDestination = HintScriptPubKey?.GetDestination();
if (hintDestination != null)
{
if (hintDestination is KeyId)
{
hintedLabels.Add("legacy");
}
if (hintDestination is ScriptId)
{
hintedLabels.Add("p2sh");
}
}
if (!Network.Consensus.SupportSegwit)
{
hintedLabels.Add("legacy");
@@ -152,8 +137,7 @@ namespace BTCPayServer
try
{
var result = BtcPayNetwork.NBXplorerNetwork.DerivationStrategyFactory.Parse(str);
return FindMatch(hintedLabels, result);
return BtcPayNetwork.NBXplorerNetwork.DerivationStrategyFactory.Parse(str);
}
catch
{
@@ -205,22 +189,13 @@ namespace BTCPayServer
catch { continue; }
}
if (hintDestination != null)
{
if (hintDestination is WitKeyId)
{
hintedLabels.Remove("legacy");
hintedLabels.Remove("p2sh");
}
}
str = string.Join('-', parts.Where(p => !IsLabel(p)));
foreach (var label in hintedLabels)
{
str = $"{str}-[{label}]";
}
return FindMatch(hintedLabels, BtcPayNetwork.NBXplorerNetwork.DerivationStrategyFactory.Parse(str));
return BtcPayNetwork.NBXplorerNetwork.DerivationStrategyFactory.Parse(str);
}
public static BitcoinExtPubKey GetBitcoinExtPubKeyByNetwork(Network network, byte[] data)
@@ -235,27 +210,6 @@ namespace BTCPayServer
}
}
private DerivationStrategyBase FindMatch(HashSet<string> hintLabels, DerivationStrategyBase result)
{
var firstKeyPath = new KeyPath("0/0");
if (HintScriptPubKey == null)
return result;
if (HintScriptPubKey == result.GetDerivation(firstKeyPath).ScriptPubKey)
return result;
if (result is MultisigDerivationStrategy)
hintLabels.Add("keeporder");
var resultNoLabels = result.ToString();
resultNoLabels = string.Join('-', resultNoLabels.Split('-').Where(p => !IsLabel(p)));
foreach (var labels in ItemCombinations(hintLabels.ToList()))
{
var hinted = BtcPayNetwork.NBXplorerNetwork.DerivationStrategyFactory.Parse(resultNoLabels + '-' + string.Join('-', labels.Select(l => $"[{l}]").ToArray()));
if (HintScriptPubKey == hinted.GetDerivation(firstKeyPath).ScriptPubKey)
return hinted;
}
throw new FormatException("Could not find any match");
}
private static bool IsLabel(string v)
{

View File

@@ -276,8 +276,8 @@ namespace BTCPayServer
[JsonIgnore]
public BTCPayNetwork Network { get; set; }
public string Source { get; set; }
[JsonIgnore]
public bool IsHotWallet => Source == "NBXplorer";
public bool IsHotWallet { get; set; }
[Obsolete("Use GetSigningAccountKeySettings().AccountKeyPath instead")]
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]

View File

@@ -128,6 +128,12 @@ namespace BTCPayServer.Hosting
settings.MigrateU2FToFIDO2 = true;
await _Settings.UpdateSetting(settings);
}
if (!settings.MigrateHotwalletProperty)
{
await MigrateHotwalletProperty();
settings.MigrateHotwalletProperty = true;
await _Settings.UpdateSetting(settings);
}
}
catch (Exception ex)
{
@@ -136,6 +142,20 @@ namespace BTCPayServer.Hosting
}
}
private async Task MigrateHotwalletProperty()
{
await using var ctx = _DBContextFactory.CreateContext();
foreach (var store in await ctx.Stores.AsQueryable().ToArrayAsync())
{
foreach (var paymentMethod in store.GetSupportedPaymentMethods(_NetworkProvider).OfType<DerivationSchemeSettings>())
{
paymentMethod.IsHotWallet = paymentMethod.Source == "NBXplorer";
paymentMethod.Source = "NBXplorerGenerated";
}
}
await ctx.SaveChangesAsync();
}
private async Task MigrateU2FToFIDO2()
{
await using var ctx = _DBContextFactory.CreateContext();

View File

@@ -20,10 +20,7 @@ namespace BTCPayServer.Models.StoreViewModels
public string KeyPath { get; set; }
[Display(Name = "Root fingerprint")]
public string RootFingerprint { get; set; }
[Display(Name = "Hint address")]
public string HintAddress { get; set; }
public bool Confirmation { get; set; }
public bool Enabled { get; set; } = true;
public KeyPath RootKeyPath { get; set; }

View File

@@ -2,6 +2,7 @@ namespace BTCPayServer.Services
{
public class MigrationSettings
{
public bool MigrateHotwalletProperty { get; set; }
public bool MigrateU2FToFIDO2{ get; set; }
public bool UnreachableStoreCheck { get; set; }
public bool DeprecatedLightningConnectionStringCheck { get; set; }

View File

@@ -50,7 +50,6 @@
<input asp-for="Config" type="hidden"/>
<input asp-for="Confirmation" type="hidden"/>
<input asp-for="DerivationScheme" type="hidden"/>
<input asp-for="Enabled" type="hidden"/>
<div class="form-group">
<table class="table table-sm table-responsive-md">
@@ -83,21 +82,6 @@
</table>
</div>
<div class="text-center mb-4">
<button class="btn btn-link" type="button" data-bs-toggle="collapse" data-bs-target="#wrong-addresses" aria-expanded="false" aria-controls="wrong-addresses">
Wrong addresses?
</button>
<div id="wrong-addresses" class="collapse @(ViewContext.ModelState.IsValid ? "" : "show")">
<div class="pb-1">
<div class="form-group">
<label asp-for="HintAddress" class="form-label">Help us to find the correct settings by telling us the first address of your wallet.</label>
<input asp-for="HintAddress" class="form-control"/>
<span asp-validation-for="HintAddress" class="text-danger"></span>
</div>
</div>
</div>
</div>
<div class="text-center">
<button name="command" type="submit" class="btn btn-primary" value="save" id="Confirm">Confirm</button>
</div>