diff --git a/BTCPayServer.Client/BTCPayServer.Client.csproj b/BTCPayServer.Client/BTCPayServer.Client.csproj index a910e48f8..adac09d2e 100644 --- a/BTCPayServer.Client/BTCPayServer.Client.csproj +++ b/BTCPayServer.Client/BTCPayServer.Client.csproj @@ -31,7 +31,7 @@ - + diff --git a/BTCPayServer.Client/Models/OnChainPaymentMethodPreviewResultData.cs b/BTCPayServer.Client/Models/OnChainPaymentMethodPreviewResultData.cs index 313f36c5d..c107d8cce 100644 --- a/BTCPayServer.Client/Models/OnChainPaymentMethodPreviewResultData.cs +++ b/BTCPayServer.Client/Models/OnChainPaymentMethodPreviewResultData.cs @@ -18,6 +18,7 @@ namespace BTCPayServer.Client.Models public string KeyPath { get; set; } //The address generated at the key path public string Address { get; set; } + public int Index { get; set; } } } } diff --git a/BTCPayServer.Common/BTCPayServer.Common.csproj b/BTCPayServer.Common/BTCPayServer.Common.csproj index 5a39ed787..4171ff96a 100644 --- a/BTCPayServer.Common/BTCPayServer.Common.csproj +++ b/BTCPayServer.Common/BTCPayServer.Common.csproj @@ -2,7 +2,7 @@ - + diff --git a/BTCPayServer.Data/BTCPayServer.Data.csproj b/BTCPayServer.Data/BTCPayServer.Data.csproj index 9c15d05c0..7cc74c1ae 100644 --- a/BTCPayServer.Data/BTCPayServer.Data.csproj +++ b/BTCPayServer.Data/BTCPayServer.Data.csproj @@ -8,7 +8,7 @@ runtime; build; native; contentfiles; analyzers; buildtransitive - + diff --git a/BTCPayServer.Rating/BTCPayServer.Rating.csproj b/BTCPayServer.Rating/BTCPayServer.Rating.csproj index 66fe503e9..63cafbadc 100644 --- a/BTCPayServer.Rating/BTCPayServer.Rating.csproj +++ b/BTCPayServer.Rating/BTCPayServer.Rating.csproj @@ -6,7 +6,7 @@ - + diff --git a/BTCPayServer.Tests/FastTests.cs b/BTCPayServer.Tests/FastTests.cs index 91f1c6839..4ef90b413 100644 --- a/BTCPayServer.Tests/FastTests.cs +++ b/BTCPayServer.Tests/FastTests.cs @@ -918,7 +918,7 @@ namespace BTCPayServer.Tests for (int i = 0; i < 5; i++) { var expectedScripts = script.Derive(AddressIntent.Deposit, i).Miniscript.ToScripts(); - var actual = scheme.AccountDerivation.GetDerivation(new KeyPath(0, (uint)i)); + var actual = ((StandardDerivationStrategyBase)scheme.AccountDerivation).GetDerivation(new KeyPath(0, (uint)i)); Assert.Equal(expectedScripts.ScriptPubKey, actual.ScriptPubKey); Assert.Equal(expectedScripts.RedeemScript, actual.Redeem); if (i == 0) @@ -1029,7 +1029,7 @@ namespace BTCPayServer.Tests "ypub6WWc2gWwHbdnAAyJDnR4SPL1phRh7REqrPBfZeizaQ1EmTshieRXJC3Z5YoU4wkcdKHEjQGkh6AYEzCQC1Kz3DNaWSwdc1pc8416hAjzqyD", settings.AccountOriginal); Assert.Equal(root.Derive(new KeyPath("m/49'/0'/0'")).Neuter().PubKey.WitHash.ScriptPubKey.Hash.ScriptPubKey, - settings.AccountDerivation.GetDerivation().ScriptPubKey); + ((StandardDerivationStrategyBase)settings.AccountDerivation).GetDerivation(new KeyPath()).ScriptPubKey); Assert.Equal("ElectrumFile", settings.Source); Assert.Null(error); @@ -1101,8 +1101,7 @@ bc1qfzu57kgu5jthl934f9xrdzzx8mmemx7gn07tf0grnvz504j6kzusu2v0ku Assert.True(multsig.LexicographicOrder); Assert.Equal(1, multsig.RequiredSignatures); - var deposit = new NBXplorer.KeyPathTemplates(null).GetKeyPathTemplate(DerivationFeature.Deposit); - var line = nunchuk.AccountDerivation.GetLineFor(deposit).Derive(0); + var line = nunchuk.AccountDerivation.GetLineFor(DerivationFeature.Deposit).Derive(0); Assert.Equal(BitcoinAddress.Create("bc1qfzu57kgu5jthl934f9xrdzzx8mmemx7gn07tf0grnvz504j6kzusu2v0ku", Network.Main).ScriptPubKey, line.ScriptPubKey); diff --git a/BTCPayServer.Tests/FeatureTests/MultisigTests.cs b/BTCPayServer.Tests/FeatureTests/MultisigTests.cs index 6a1596ad2..a70ce3a46 100644 --- a/BTCPayServer.Tests/FeatureTests/MultisigTests.cs +++ b/BTCPayServer.Tests/FeatureTests/MultisigTests.cs @@ -176,7 +176,7 @@ public class MultisigTests : UnitTestBase var resp1 = new GenerateWalletResponse { MasterHDKey = key1, - DerivationScheme = parser.Parse(derivation), + DerivationScheme = (StandardDerivationStrategyBase)parser.Parse(derivation), AccountKeyPath = RootedKeyPath.Parse(keypath) }; return resp1; diff --git a/BTCPayServer.Tests/UnitTest1.cs b/BTCPayServer.Tests/UnitTest1.cs index fe26e4fbd..63a781030 100644 --- a/BTCPayServer.Tests/UnitTest1.cs +++ b/BTCPayServer.Tests/UnitTest1.cs @@ -78,6 +78,7 @@ using Microsoft.Extensions.Caching.Memory; using PosViewType = BTCPayServer.Client.Models.PosViewType; using BTCPayServer.PaymentRequest; using BTCPayServer.Views.Stores; +using NBXplorer.DerivationStrategy; namespace BTCPayServer.Tests { @@ -730,7 +731,7 @@ namespace BTCPayServer.Tests // Sending a coin var txId = tester.ExplorerNode.SendToAddress( - btcDerivationScheme.GetDerivation(new KeyPath("0/90")).ScriptPubKey, Money.Coins(1.0m)); + ((StandardDerivationStrategyBase)btcDerivationScheme).GetDerivation(new KeyPath("0/90")).ScriptPubKey, Money.Coins(1.0m)); tester.ExplorerNode.Generate(1); var transactions = Assert.IsType(Assert .IsType(walletController.WalletTransactions(walletId, loadTransactions: true).Result).Model); diff --git a/BTCPayServer.Tests/docker-compose.altcoins.yml b/BTCPayServer.Tests/docker-compose.altcoins.yml index 7d059a457..2281ac351 100644 --- a/BTCPayServer.Tests/docker-compose.altcoins.yml +++ b/BTCPayServer.Tests/docker-compose.altcoins.yml @@ -99,7 +99,7 @@ services: custom: nbxplorer: - image: nicolasdorier/nbxplorer:2.5.26 + image: nicolasdorier/nbxplorer:2.5.28 restart: unless-stopped ports: - "32838:32838" diff --git a/BTCPayServer.Tests/docker-compose.mutinynet.yml b/BTCPayServer.Tests/docker-compose.mutinynet.yml index 8e0258cbd..8289be149 100644 --- a/BTCPayServer.Tests/docker-compose.mutinynet.yml +++ b/BTCPayServer.Tests/docker-compose.mutinynet.yml @@ -62,7 +62,7 @@ services: custom: nbxplorer: - image: nicolasdorier/nbxplorer:2.5.26 + image: nicolasdorier/nbxplorer:2.5.28 restart: unless-stopped ports: - "32838:32838" diff --git a/BTCPayServer.Tests/docker-compose.testnet.yml b/BTCPayServer.Tests/docker-compose.testnet.yml index 58a924800..56400a824 100644 --- a/BTCPayServer.Tests/docker-compose.testnet.yml +++ b/BTCPayServer.Tests/docker-compose.testnet.yml @@ -57,7 +57,7 @@ services: custom: nbxplorer: - image: nicolasdorier/nbxplorer:2.5.26 + image: nicolasdorier/nbxplorer:2.5.28 restart: unless-stopped ports: - "32838:32838" diff --git a/BTCPayServer.Tests/docker-compose.yml b/BTCPayServer.Tests/docker-compose.yml index cfd3f0463..2bc457785 100644 --- a/BTCPayServer.Tests/docker-compose.yml +++ b/BTCPayServer.Tests/docker-compose.yml @@ -95,7 +95,7 @@ services: custom: nbxplorer: - image: nicolasdorier/nbxplorer:2.5.26 + image: nicolasdorier/nbxplorer:2.5.28 restart: unless-stopped ports: - "32838:32838" diff --git a/BTCPayServer/BTCPayServer.csproj b/BTCPayServer/BTCPayServer.csproj index be86ef759..9e73eb74a 100644 --- a/BTCPayServer/BTCPayServer.csproj +++ b/BTCPayServer/BTCPayServer.csproj @@ -51,9 +51,9 @@ - + - + diff --git a/BTCPayServer/Controllers/GreenField/GreenfieldStoreOnChainPaymentMethodsController.cs b/BTCPayServer/Controllers/GreenField/GreenfieldStoreOnChainPaymentMethodsController.cs index 1bd924e3f..5fb52a417 100644 --- a/BTCPayServer/Controllers/GreenField/GreenfieldStoreOnChainPaymentMethodsController.cs +++ b/BTCPayServer/Controllers/GreenField/GreenfieldStoreOnChainPaymentMethodsController.cs @@ -15,6 +15,8 @@ using BTCPayServer.Services.Wallets; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Cors; using Microsoft.AspNetCore.Mvc; +using NBitcoin; +using NBXplorer; using NBXplorer.DerivationStrategy; using Newtonsoft.Json.Linq; using StoreData = BTCPayServer.Data.StoreData; @@ -115,18 +117,26 @@ namespace BTCPayServer.Controllers.Greenfield internal static OnChainPaymentMethodPreviewResultData GetPreviewResultData(int offset, int count, BTCPayNetwork network, DerivationStrategyBase strategy) { - var deposit = new NBXplorer.KeyPathTemplates(null).GetKeyPathTemplate(DerivationFeature.Deposit); - var line = strategy.GetLineFor(deposit); + var line = strategy.GetLineFor(DerivationFeature.Deposit); var result = new OnChainPaymentMethodPreviewResultData(); for (var i = offset; i < count; i++) { + var keyPath = new KeyPath(0, (uint)i); + if (strategy is PolicyDerivationStrategy) + keyPath = null; var derivation = line.Derive((uint)i); result.Addresses.Add( new() { - KeyPath = deposit.GetKeyPath((uint)i).ToString(), + KeyPath = keyPath?.ToString(), + Index = i, Address = - network.NBXplorerNetwork.CreateAddress(strategy, deposit.GetKeyPath((uint)i), derivation.ScriptPubKey) +#pragma warning disable CS0612 // Type or member is obsolete + // We should be able to derive the address from the scriptPubKey. + // However, Elements has blinded addresses, so we can't derive the address from the scriptPubKey. + // We should probably just use a special if/else just for elements here instead of relying on obsolete stuff. + network.NBXplorerNetwork.CreateAddress(strategy, keyPath ?? new(), derivation.ScriptPubKey) +#pragma warning restore CS0612 // Type or member is obsolete .ToString() }); } diff --git a/BTCPayServer/Controllers/UIInvoiceController.UI.cs b/BTCPayServer/Controllers/UIInvoiceController.UI.cs index ffd64f788..3b317a5f0 100644 --- a/BTCPayServer/Controllers/UIInvoiceController.UI.cs +++ b/BTCPayServer/Controllers/UIInvoiceController.UI.cs @@ -1125,7 +1125,7 @@ namespace BTCPayServer.Controllers { var appsById = apps.ToDictionary(a => a.Id); var searchTexts = appIds.Select(a => appsById.TryGet(a)).Where(a => a != null) - .Select(a => AppService.GetAppSearchTerm(a.AppType, a.Id)) + .Select(a => AppService.GetAppSearchTerm(a!.AppType, a!.Id)) .ToList(); searchTexts.Add(fs.TextSearch); textSearch = string.Join(' ', searchTexts.Where(t => !string.IsNullOrEmpty(t)).ToList()); diff --git a/BTCPayServer/Controllers/UIStoresController.Onchain.cs b/BTCPayServer/Controllers/UIStoresController.Onchain.cs index f320e9c21..05f95b943 100644 --- a/BTCPayServer/Controllers/UIStoresController.Onchain.cs +++ b/BTCPayServer/Controllers/UIStoresController.Onchain.cs @@ -184,7 +184,7 @@ public partial class UIStoresController } catch { - ModelState.AddModelError(nameof(vm.DerivationScheme), StringLocalizer["Invalid derivation scheme"]); + ModelState.AddModelError(nameof(vm.DerivationScheme), StringLocalizer["NBXplorer is unable to track this derivation scheme. You may need to update it."]); return View(vm.ViewName, vm); } await _storeRepo.UpdateStore(store); diff --git a/BTCPayServer/DerivationSchemeParser.cs b/BTCPayServer/DerivationSchemeParser.cs index 936d74daa..5216eb32b 100644 --- a/BTCPayServer/DerivationSchemeParser.cs +++ b/BTCPayServer/DerivationSchemeParser.cs @@ -7,6 +7,7 @@ using System.Text.RegularExpressions; using NBitcoin; using NBitcoin.Scripting; using NBitcoin.WalletPolicies; +using NBXplorer; using NBXplorer.DerivationStrategy; using static NBitcoin.WalletPolicies.MiniscriptNode; @@ -69,7 +70,7 @@ namespace BTCPayServer }).ToArray() ?? new AccountKeySettings[result.Item1.GetExtPubKeys().Count()]; if (result.Item2?.Length > 1) derivationSchemeSettings.IsMultiSigOnServer = true; - var isTaproot = derivationSchemeSettings.AccountDerivation.GetDerivation().ScriptPubKey.IsScriptType(ScriptType.Taproot); + var isTaproot = derivationSchemeSettings.AccountDerivation.GetLineFor(DerivationFeature.Deposit).Derive(0).ScriptPubKey.IsScriptType(ScriptType.Taproot); derivationSchemeSettings.DefaultIncludeNonWitnessUtxo = !isTaproot; return derivationSchemeSettings; } @@ -209,10 +210,41 @@ namespace BTCPayServer ScriptPubKeyType = ScriptPubKeyType.SegwitP2SH, KeepOrder = desc.Name == "multi" }), rpks), - _ => throw new FormatException("Not supporting this script policy (BIP388) yet.") + _ => ParsePolicy(factory, str) }; } + private (DerivationStrategyBase, RootedKeyPath[]) ParsePolicy(DerivationStrategyFactory factory, string str) + { + var policy = factory.Parse(str) as PolicyDerivationStrategy; + if (policy is null) + throw new FormatException("Invalid miniscript derivation"); + var v = new RootKeyPathVisitor(); + policy.Policy.FullDescriptor.Visit(v); + return (policy, v.RootedKeyPaths.ToArray()); + } + + class RootKeyPathVisitor : MiniscriptVisitor + { + public List RootedKeyPaths { get; set; } = new(); + public override void Visit(MiniscriptNode node) + { + // Match all '[12345678]xpub/**' + if (node is MiniscriptNode.MultipathNode + { + Target: HDKeyNode hd + }) + { + RootedKeyPaths.Add(hd.RootedKeyPath); + } + else + { + base.Visit(node); + } + } + } + + private (DerivationStrategyBase, RootedKeyPath[]) ParseLegacyOutputDescriptor(string str) { (DerivationStrategyBase, RootedKeyPath[]) ExtractFromPkProvider(PubKeyProvider pubKeyProvider, diff --git a/BTCPayServer/Payments/Bitcoin/BitcoinLikePaymentData.cs b/BTCPayServer/Payments/Bitcoin/BitcoinLikePaymentData.cs index e2e8d67fd..69f2e724f 100644 --- a/BTCPayServer/Payments/Bitcoin/BitcoinLikePaymentData.cs +++ b/BTCPayServer/Payments/Bitcoin/BitcoinLikePaymentData.cs @@ -1,3 +1,4 @@ +using System.Linq; using BTCPayServer.Client.JsonConverters; using BTCPayServer.Client.Models; using BTCPayServer.Services.Invoices; @@ -14,12 +15,18 @@ namespace BTCPayServer.Payments.Bitcoin } - public BitcoinLikePaymentData(OutPoint outpoint, bool rbf, KeyPath keyPath) + public BitcoinLikePaymentData(OutPoint outpoint, bool rbf, KeyPath keyPath, int keyIndex) { + if (keyPath != null) + // This shouldn't be needed on new version of NBXplorer, but old version of NBXplorer + // are not returning KeyIndex, and it is thus set to '0'. + keyIndex = (int)keyPath.Indexes.Last(); + Outpoint = outpoint; ConfirmationCount = 0; RBF = rbf; KeyPath = keyPath; + KeyIndex = keyIndex; } [JsonConverter(typeof(SaneOutpointJsonConverter))] public OutPoint Outpoint { get; set; } @@ -28,6 +35,8 @@ namespace BTCPayServer.Payments.Bitcoin public bool RBF { get; set; } [JsonConverter(typeof(NBitcoin.JsonConverters.KeyPathJsonConverter))] public KeyPath KeyPath { get; set; } + + public int? KeyIndex { get; set; } [JsonConverter(typeof(NBitcoin.JsonConverters.UInt256JsonConverter))] [JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)] public uint256 AssetId { get; set; } diff --git a/BTCPayServer/Payments/Bitcoin/BitcoinLikePaymentHandler.cs b/BTCPayServer/Payments/Bitcoin/BitcoinLikePaymentHandler.cs index 350578e84..07b8f3e40 100644 --- a/BTCPayServer/Payments/Bitcoin/BitcoinLikePaymentHandler.cs +++ b/BTCPayServer/Payments/Bitcoin/BitcoinLikePaymentHandler.cs @@ -190,6 +190,7 @@ namespace BTCPayServer.Payments.Bitcoin paymentMethod.Destination = reserved.Address.ToString(); paymentContext.TrackedDestinations.Add(Network.GetTrackedDestination(reserved.Address.ScriptPubKey)); onchainMethod.KeyPath = reserved.KeyPath; + onchainMethod.KeyIndex = reserved.Index ?? (int)reserved.KeyPath.Indexes.Last(); onchainMethod.AccountDerivation = accountDerivation; onchainMethod.PayjoinEnabled = blob.PayJoinEnabled && accountDerivation.ScriptPubKeyType() != ScriptPubKeyType.Legacy && diff --git a/BTCPayServer/Payments/Bitcoin/BitcoinPaymentPromptDetails.cs b/BTCPayServer/Payments/Bitcoin/BitcoinPaymentPromptDetails.cs index a2c9197dd..234b1f833 100644 --- a/BTCPayServer/Payments/Bitcoin/BitcoinPaymentPromptDetails.cs +++ b/BTCPayServer/Payments/Bitcoin/BitcoinPaymentPromptDetails.cs @@ -35,6 +35,7 @@ namespace BTCPayServer.Payments.Bitcoin public FeeRate RecommendedFeeRate { get; set; } [JsonConverter(typeof(NBitcoin.JsonConverters.KeyPathJsonConverter))] public KeyPath KeyPath { get; set; } + public int KeyIndex { get; set; } public DerivationStrategyBase AccountDerivation { get; set; } } } diff --git a/BTCPayServer/Payments/Bitcoin/NBXplorerListener.cs b/BTCPayServer/Payments/Bitcoin/NBXplorerListener.cs index d87245317..5d0bcb6a4 100644 --- a/BTCPayServer/Payments/Bitcoin/NBXplorerListener.cs +++ b/BTCPayServer/Payments/Bitcoin/NBXplorerListener.cs @@ -164,7 +164,7 @@ namespace BTCPayServer.Payments.Bitcoin if (invoice != null) { var handler = _handlers[pmi]; - var details = new BitcoinLikePaymentData(output.outPoint, evt.TransactionData.Transaction.RBF, output.matchedOutput.KeyPath) + var details = new BitcoinLikePaymentData(output.outPoint, evt.TransactionData.Transaction.RBF, output.matchedOutput.KeyPath, output.matchedOutput.KeyIndex) { AssetId = output.matchedOutput.Value.GetAssetId(network) }; @@ -414,7 +414,7 @@ namespace BTCPayServer.Payments.Bitcoin Status = PaymentStatus.Processing, Amount = coin.Value.GetValue(network), Currency = network.CryptoCode - }.Set(invoice, handler, new BitcoinLikePaymentData(coin.OutPoint, transaction?.Transaction is null ? true : transaction.Transaction.RBF, coin.KeyPath) + }.Set(invoice, handler, new BitcoinLikePaymentData(coin.OutPoint, transaction?.Transaction is null ? true : transaction.Transaction.RBF, coin.KeyPath, coin.KeyIndex) { AssetId = coin.Value.GetAssetId(network) }); diff --git a/BTCPayServer/Payments/PayJoin/PayJoinEndpointController.cs b/BTCPayServer/Payments/PayJoin/PayJoinEndpointController.cs index fcd408a74..cd2c8d0bf 100644 --- a/BTCPayServer/Payments/PayJoin/PayJoinEndpointController.cs +++ b/BTCPayServer/Payments/PayJoin/PayJoinEndpointController.cs @@ -255,7 +255,7 @@ namespace BTCPayServer.Payments.PayJoin Dictionary selectedUTXOs = new Dictionary(); PSBTOutput? originalPaymentOutput = null; BitcoinAddress? paymentAddress = null; - KeyPath? paymentAddressIndex = null; + (KeyPath KeyPath, int KeyIndex)? paymentAddressIndex = null; InvoiceEntity? invoice = null; DerivationStrategyBase? accountDerivation = null; WalletId? walletId = null; @@ -312,7 +312,7 @@ namespace BTCPayServer.Payments.PayJoin } paymentAddress = BitcoinAddress.Create(paymentMethod.Destination, network.NBitcoinNetwork); - paymentAddressIndex = paymentDetails.KeyPath; + paymentAddressIndex = (paymentDetails.KeyPath, paymentDetails.KeyIndex); if (invoice.GetAllBitcoinPaymentData(handler, false).Any()) { @@ -325,7 +325,8 @@ namespace BTCPayServer.Payments.PayJoin { due = Money.Zero; paymentAddress = walletReceiveMatch.Item2.Address; - paymentAddressIndex = walletReceiveMatch.Item2.KeyPath; + // Old versions of NBX doesn't have the Index property, we can remove ?? (int)walletReceiveMatch.Item2.KeyPath.Indexes.Last() later. + paymentAddressIndex = (walletReceiveMatch.Item2.KeyPath, walletReceiveMatch.Item2.Index ?? (int)walletReceiveMatch.Item2.KeyPath.Indexes.Last()); } @@ -500,7 +501,7 @@ namespace BTCPayServer.Payments.PayJoin // broadcast the payjoin. var outpoint = new OutPoint(ctx.OriginalTransaction.GetHash(), originalPaymentOutput.Index); - var details = new BitcoinLikePaymentData(outpoint, ctx.OriginalTransaction.RBF, paymentAddressIndex) + var details = new BitcoinLikePaymentData(outpoint, ctx.OriginalTransaction.RBF, paymentAddressIndex.Value.KeyPath, paymentAddressIndex.Value.KeyIndex) { ConfirmationCount = -1, PayjoinInformation = new PayjoinInformation() diff --git a/BTCPayServer/Payments/PayJoin/Sender/PayjoinWallet.cs b/BTCPayServer/Payments/PayJoin/Sender/PayjoinWallet.cs index 0b59b3ca2..f85f506d2 100644 --- a/BTCPayServer/Payments/PayJoin/Sender/PayjoinWallet.cs +++ b/BTCPayServer/Payments/PayJoin/Sender/PayjoinWallet.cs @@ -21,11 +21,6 @@ namespace BTCPayServer.Payments.PayJoin.Sender return ((IHDScriptPubKey)_derivationSchemeSettings.AccountDerivation).Derive(keyPath); } - public bool CanDeriveHardenedPath() - { - return _derivationSchemeSettings.AccountDerivation.CanDeriveHardenedPath(); - } - public Script ScriptPubKey => ((IHDScriptPubKey)_derivationSchemeSettings.AccountDerivation).ScriptPubKey; public ScriptPubKeyType ScriptPubKeyType => _derivationSchemeSettings.AccountDerivation.ScriptPubKeyType(); diff --git a/BTCPayServer/Services/WalletFileParsing/BSMSWalletFileParser.cs b/BTCPayServer/Services/WalletFileParsing/BSMSWalletFileParser.cs index a1f010756..4e7f77e68 100644 --- a/BTCPayServer/Services/WalletFileParsing/BSMSWalletFileParser.cs +++ b/BTCPayServer/Services/WalletFileParsing/BSMSWalletFileParser.cs @@ -4,6 +4,7 @@ using System.Diagnostics.CodeAnalysis; using System.Linq; using BTCPayServer; using NBitcoin; +using NBXplorer; using NBXplorer.DerivationStrategy; using AccountKeySettings = BTCPayServer.AccountKeySettings; using BTCPayNetwork = BTCPayServer.BTCPayNetwork; @@ -37,8 +38,7 @@ public class BSMSWalletFileParser : IWalletFileParser derivationSchemeSettings = network.GetDerivationSchemeParser().ParseOD(descriptor); derivationSchemeSettings.Source = "BSMS"; - var deposit = new NBXplorer.KeyPathTemplates(null).GetKeyPathTemplate(DerivationFeature.Deposit); - var line = derivationSchemeSettings.AccountDerivation.GetLineFor(deposit).Derive(0); + var line = derivationSchemeSettings.AccountDerivation.GetLineFor(DerivationFeature.Deposit).Derive(0); return testAddress.ScriptPubKey == line.ScriptPubKey; } } diff --git a/BTCPayServer/Services/Wallets/BTCPayWallet.cs b/BTCPayServer/Services/Wallets/BTCPayWallet.cs index 7f1ff46ad..e840f8856 100644 --- a/BTCPayServer/Services/Wallets/BTCPayWallet.cs +++ b/BTCPayServer/Services/Wallets/BTCPayWallet.cs @@ -33,6 +33,7 @@ namespace BTCPayServer.Services.Wallets public Coin Coin { get; set; } public long Confirmations { get; set; } public BitcoinAddress Address { get; set; } + public int KeyIndex { get; set; } } public class NetworkCoins { @@ -500,6 +501,7 @@ namespace BTCPayServer.Services.Wallets .Select(c => new ReceivedCoin() { KeyPath = c.KeyPath, + KeyIndex = c.KeyIndex, Value = c.Value, Timestamp = c.Timestamp, OutPoint = c.Outpoint, diff --git a/BTCPayServer/Views/Shared/Bitcoin/ViewBitcoinLikePaymentData.cshtml b/BTCPayServer/Views/Shared/Bitcoin/ViewBitcoinLikePaymentData.cshtml index e32705b44..6b8db37be 100644 --- a/BTCPayServer/Views/Shared/Bitcoin/ViewBitcoinLikePaymentData.cshtml +++ b/BTCPayServer/Views/Shared/Bitcoin/ViewBitcoinLikePaymentData.cshtml @@ -81,7 +81,7 @@ { @payment.PaymentMethodId - @(payment.CryptoPaymentData.KeyPath?.ToString()?? StringLocalizer["Unknown"]) + @(payment.CryptoPaymentData.KeyPath?.ToString() ?? payment.CryptoPaymentData.KeyIndex?.ToString() ?? StringLocalizer["Unknown"])