diff --git a/BTCPayServer.Client/Models/GenerateOnChainWalletRequest.cs b/BTCPayServer.Client/Models/GenerateOnChainWalletRequest.cs index 0ae0fd22e..ce2e6da56 100644 --- a/BTCPayServer.Client/Models/GenerateOnChainWalletRequest.cs +++ b/BTCPayServer.Client/Models/GenerateOnChainWalletRequest.cs @@ -10,6 +10,7 @@ namespace BTCPayServer.Client { public class GenerateOnChainWalletRequest { + public string Label { get; set; } public int AccountNumber { get; set; } = 0; [JsonConverter(typeof(MnemonicJsonConverter))] public Mnemonic ExistingMnemonic { get; set; } @@ -29,6 +30,7 @@ namespace BTCPayServer.Client { public class ConfigData { + public string Label { get; set; } public string AccountDerivation { get; set; } [JsonExtensionData] IDictionary AdditionalData { get; set; } diff --git a/BTCPayServer.Tests/GreenfieldAPITests.cs b/BTCPayServer.Tests/GreenfieldAPITests.cs index 8c6113933..906a5271a 100644 --- a/BTCPayServer.Tests/GreenfieldAPITests.cs +++ b/BTCPayServer.Tests/GreenfieldAPITests.cs @@ -3158,8 +3158,8 @@ namespace BTCPayServer.Tests await client.RemoveStorePaymentMethod(store.Id, "BTC-CHAIN"); generateResponse = await client.GenerateOnChainWallet(store.Id, "BTC", - new GenerateOnChainWalletRequest() { ExistingMnemonic = allMnemonic, AccountNumber = 1 }); - + new GenerateOnChainWalletRequest() { ExistingMnemonic = allMnemonic, AccountNumber = 1, Label = "test" }); + Assert.Equal("test", generateResponse.Config.Label); Assert.Equal(generateResponse.Mnemonic.ToString(), allMnemonic.ToString()); Assert.Equal(new Mnemonic("all all all all all all all all all all all all").DeriveExtKey() diff --git a/BTCPayServer/Controllers/GreenField/GreenfieldStoreOnChainPaymentMethodsController.WalletGeneration.cs b/BTCPayServer/Controllers/GreenField/GreenfieldStoreOnChainPaymentMethodsController.WalletGeneration.cs index f694b8b47..ecbb89a41 100644 --- a/BTCPayServer/Controllers/GreenField/GreenfieldStoreOnChainPaymentMethodsController.WalletGeneration.cs +++ b/BTCPayServer/Controllers/GreenField/GreenfieldStoreOnChainPaymentMethodsController.WalletGeneration.cs @@ -24,9 +24,9 @@ namespace BTCPayServer.Controllers.Greenfield public async Task GenerateOnChainWallet(string storeId, [ModelBinder(typeof(PaymentMethodIdModelBinder))] PaymentMethodId paymentMethodId, - GenerateWalletRequest request) + GenerateOnChainWalletRequest request) { - + request ??= new GenerateOnChainWalletRequest(); AssertCryptoCodeWallet(paymentMethodId, out var network, out _); if (!_walletProvider.IsAvailable(network)) @@ -34,6 +34,8 @@ namespace BTCPayServer.Controllers.Greenfield return this.CreateAPIError(503, "not-available", $"{paymentMethodId} services are not currently available"); } + if (request.Label is { Length: > 300 }) + ModelState.AddModelError(nameof(request.Label), "Label is too long (Max 300 characters)"); if (IsConfigured(paymentMethodId, out _)) { @@ -63,7 +65,17 @@ namespace BTCPayServer.Controllers.Greenfield GenerateWalletResponse response; try { - response = await client.GenerateWalletAsync(request); + response = await client.GenerateWalletAsync(new() + { + AccountNumber = request.AccountNumber, + ExistingMnemonic = request.ExistingMnemonic?.ToString(), + WordList = request.WordList, + WordCount = request.WordCount, + ScriptPubKeyType = request.ScriptPubKeyType, + Passphrase = request.Passphrase, + ImportKeysToRPC = request.ImportKeysToRPC, + SavePrivateKeys = request.SavePrivateKeys, + }); if (response == null) { return this.CreateAPIError(503, "not-available", @@ -79,9 +91,9 @@ namespace BTCPayServer.Controllers.Greenfield var derivationSchemeSettings = new DerivationSchemeSettings(response.DerivationScheme, network); derivationSchemeSettings.Source = - string.IsNullOrEmpty(request.ExistingMnemonic) ? "NBXplorerGenerated" : "ImportedSeed"; + request.ExistingMnemonic is null ? "NBXplorerGenerated" : "ImportedSeed"; derivationSchemeSettings.IsHotWallet = request.SavePrivateKeys; - + derivationSchemeSettings.Label = request.Label; var accountSettings = derivationSchemeSettings.GetSigningAccountKeySettings(); accountSettings.AccountKeyPath = response.AccountKeyPath.KeyPath; accountSettings.RootFingerprint = response.AccountKeyPath.MasterFingerprint; diff --git a/BTCPayServer/Controllers/GreenField/LocalBTCPayServerClient.cs b/BTCPayServer/Controllers/GreenField/LocalBTCPayServerClient.cs index 6925789df..da8429bbd 100644 --- a/BTCPayServer/Controllers/GreenField/LocalBTCPayServerClient.cs +++ b/BTCPayServer/Controllers/GreenField/LocalBTCPayServerClient.cs @@ -937,17 +937,7 @@ namespace BTCPayServer.Controllers.Greenfield { return GetFromActionResult( await GetController().GenerateOnChainWallet(storeId, Payments.PaymentMethodId.Parse(paymentMethodId), - new GenerateWalletRequest() - { - Passphrase = request.Passphrase, - AccountNumber = request.AccountNumber, - ExistingMnemonic = request.ExistingMnemonic?.ToString(), - WordCount = request.WordCount, - WordList = request.WordList, - SavePrivateKeys = request.SavePrivateKeys, - ScriptPubKeyType = request.ScriptPubKeyType, - ImportKeysToRPC = request.ImportKeysToRPC - })); + request)); } public override async Task SendEmail(string storeId, SendEmailRequest request, diff --git a/BTCPayServer/wwwroot/swagger/v1/swagger.template.stores-payment-methods.on-chain.json b/BTCPayServer/wwwroot/swagger/v1/swagger.template.stores-payment-methods.on-chain.json index cf7bd179e..c881693f7 100644 --- a/BTCPayServer/wwwroot/swagger/v1/swagger.template.stores-payment-methods.on-chain.json +++ b/BTCPayServer/wwwroot/swagger/v1/swagger.template.stores-payment-methods.on-chain.json @@ -322,6 +322,10 @@ "type": "object", "additionalProperties": false, "properties": { + "label": { + "type": "string", + "description": "A label that will be shown in the UI" + }, "existingMnemonic": { "$ref": "#/components/schemas/Mnemonic" },