Greenfield: Can set the label when generating a wallet for store (#6186)

This commit is contained in:
Nicolas Dorier
2024-09-02 18:54:15 +09:00
committed by GitHub
parent 4a94074595
commit 1c027be106
5 changed files with 26 additions and 18 deletions

View File

@@ -10,6 +10,7 @@ namespace BTCPayServer.Client
{ {
public class GenerateOnChainWalletRequest public class GenerateOnChainWalletRequest
{ {
public string Label { get; set; }
public int AccountNumber { get; set; } = 0; public int AccountNumber { get; set; } = 0;
[JsonConverter(typeof(MnemonicJsonConverter))] [JsonConverter(typeof(MnemonicJsonConverter))]
public Mnemonic ExistingMnemonic { get; set; } public Mnemonic ExistingMnemonic { get; set; }
@@ -29,6 +30,7 @@ namespace BTCPayServer.Client
{ {
public class ConfigData public class ConfigData
{ {
public string Label { get; set; }
public string AccountDerivation { get; set; } public string AccountDerivation { get; set; }
[JsonExtensionData] [JsonExtensionData]
IDictionary<string, JToken> AdditionalData { get; set; } IDictionary<string, JToken> AdditionalData { get; set; }

View File

@@ -3158,8 +3158,8 @@ namespace BTCPayServer.Tests
await client.RemoveStorePaymentMethod(store.Id, "BTC-CHAIN"); await client.RemoveStorePaymentMethod(store.Id, "BTC-CHAIN");
generateResponse = await client.GenerateOnChainWallet(store.Id, "BTC", 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(generateResponse.Mnemonic.ToString(), allMnemonic.ToString());
Assert.Equal(new Mnemonic("all all all all all all all all all all all all").DeriveExtKey() Assert.Equal(new Mnemonic("all all all all all all all all all all all all").DeriveExtKey()

View File

@@ -24,9 +24,9 @@ namespace BTCPayServer.Controllers.Greenfield
public async Task<IActionResult> GenerateOnChainWallet(string storeId, public async Task<IActionResult> GenerateOnChainWallet(string storeId,
[ModelBinder(typeof(PaymentMethodIdModelBinder))] [ModelBinder(typeof(PaymentMethodIdModelBinder))]
PaymentMethodId paymentMethodId, PaymentMethodId paymentMethodId,
GenerateWalletRequest request) GenerateOnChainWalletRequest request)
{ {
request ??= new GenerateOnChainWalletRequest();
AssertCryptoCodeWallet(paymentMethodId, out var network, out _); AssertCryptoCodeWallet(paymentMethodId, out var network, out _);
if (!_walletProvider.IsAvailable(network)) if (!_walletProvider.IsAvailable(network))
@@ -34,6 +34,8 @@ namespace BTCPayServer.Controllers.Greenfield
return this.CreateAPIError(503, "not-available", return this.CreateAPIError(503, "not-available",
$"{paymentMethodId} services are not currently 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 _)) if (IsConfigured(paymentMethodId, out _))
{ {
@@ -63,7 +65,17 @@ namespace BTCPayServer.Controllers.Greenfield
GenerateWalletResponse response; GenerateWalletResponse response;
try 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) if (response == null)
{ {
return this.CreateAPIError(503, "not-available", return this.CreateAPIError(503, "not-available",
@@ -79,9 +91,9 @@ namespace BTCPayServer.Controllers.Greenfield
var derivationSchemeSettings = new DerivationSchemeSettings(response.DerivationScheme, network); var derivationSchemeSettings = new DerivationSchemeSettings(response.DerivationScheme, network);
derivationSchemeSettings.Source = derivationSchemeSettings.Source =
string.IsNullOrEmpty(request.ExistingMnemonic) ? "NBXplorerGenerated" : "ImportedSeed"; request.ExistingMnemonic is null ? "NBXplorerGenerated" : "ImportedSeed";
derivationSchemeSettings.IsHotWallet = request.SavePrivateKeys; derivationSchemeSettings.IsHotWallet = request.SavePrivateKeys;
derivationSchemeSettings.Label = request.Label;
var accountSettings = derivationSchemeSettings.GetSigningAccountKeySettings(); var accountSettings = derivationSchemeSettings.GetSigningAccountKeySettings();
accountSettings.AccountKeyPath = response.AccountKeyPath.KeyPath; accountSettings.AccountKeyPath = response.AccountKeyPath.KeyPath;
accountSettings.RootFingerprint = response.AccountKeyPath.MasterFingerprint; accountSettings.RootFingerprint = response.AccountKeyPath.MasterFingerprint;

View File

@@ -937,17 +937,7 @@ namespace BTCPayServer.Controllers.Greenfield
{ {
return GetFromActionResult<GenerateOnChainWalletResponse>( return GetFromActionResult<GenerateOnChainWalletResponse>(
await GetController<GreenfieldStoreOnChainPaymentMethodsController>().GenerateOnChainWallet(storeId, Payments.PaymentMethodId.Parse(paymentMethodId), await GetController<GreenfieldStoreOnChainPaymentMethodsController>().GenerateOnChainWallet(storeId, Payments.PaymentMethodId.Parse(paymentMethodId),
new GenerateWalletRequest() request));
{
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
}));
} }
public override async Task SendEmail(string storeId, SendEmailRequest request, public override async Task SendEmail(string storeId, SendEmailRequest request,

View File

@@ -322,6 +322,10 @@
"type": "object", "type": "object",
"additionalProperties": false, "additionalProperties": false,
"properties": { "properties": {
"label": {
"type": "string",
"description": "A label that will be shown in the UI"
},
"existingMnemonic": { "existingMnemonic": {
"$ref": "#/components/schemas/Mnemonic" "$ref": "#/components/schemas/Mnemonic"
}, },