diff --git a/BTCPayServer.Tests/AltcoinTests/AltcoinTests.cs b/BTCPayServer.Tests/AltcoinTests/AltcoinTests.cs index 8d4cc2769..3f361a90f 100644 --- a/BTCPayServer.Tests/AltcoinTests/AltcoinTests.cs +++ b/BTCPayServer.Tests/AltcoinTests/AltcoinTests.cs @@ -877,7 +877,7 @@ normal: InvoiceEntity invoiceEntity = new InvoiceEntity(); invoiceEntity.Networks = networkProvider; invoiceEntity.Payments = new System.Collections.Generic.List(); - invoiceEntity.ProductInformation = new ProductInformation() { Price = 100 }; + invoiceEntity.Price = 100; PaymentMethodDictionary paymentMethods = new PaymentMethodDictionary(); paymentMethods.Add(new PaymentMethod() { Network = networkBTC, CryptoCode = "BTC", Rate = 10513.44m, } .SetPaymentMethodDetails( diff --git a/BTCPayServer.Tests/UnitTest1.cs b/BTCPayServer.Tests/UnitTest1.cs index 6b807c6ae..6788b6d00 100644 --- a/BTCPayServer.Tests/UnitTest1.cs +++ b/BTCPayServer.Tests/UnitTest1.cs @@ -151,6 +151,36 @@ namespace BTCPayServer.Tests } } + [Fact] + [Trait("Fast", "Fast")] + public void CanParsePaymentMethodId() + { + var id = PaymentMethodId.Parse("BTC"); + var id1 = PaymentMethodId.Parse("BTC-OnChain"); + var id2 = PaymentMethodId.Parse("BTC-BTCLike"); + Assert.Equal(id, id1); + Assert.Equal(id, id2); + Assert.Equal("BTC", id.ToString()); + Assert.Equal("BTC", id.ToString()); + id = PaymentMethodId.Parse("LTC"); + Assert.Equal("LTC", id.ToString()); + Assert.Equal("LTC", id.ToStringNormalized()); + id = PaymentMethodId.Parse("LTC-offchain"); + id1 = PaymentMethodId.Parse("LTC-OffChain"); + id2 = PaymentMethodId.Parse("LTC-LightningLike"); + Assert.Equal(id, id1); + Assert.Equal(id, id2); + Assert.Equal("LTC_LightningLike", id.ToString()); + Assert.Equal("LTC-LightningNetwork", id.ToStringNormalized()); +#if ALTCOINS + id = PaymentMethodId.Parse("XMR"); + id1 = PaymentMethodId.Parse("XMR-MoneroLike"); + Assert.Equal(id, id1); + Assert.Equal("XMR_MoneroLike", id.ToString()); + Assert.Equal("XMR", id.ToStringNormalized()); +#endif + } + [Fact] [Trait("Fast", "Fast")] public async Task CheckNoDeadLink() diff --git a/BTCPayServer/Controllers/GreenField/InvoiceController.cs b/BTCPayServer/Controllers/GreenField/InvoiceController.cs index a1774bb10..1f589d09b 100644 --- a/BTCPayServer/Controllers/GreenField/InvoiceController.cs +++ b/BTCPayServer/Controllers/GreenField/InvoiceController.cs @@ -267,7 +267,7 @@ namespace BTCPayServer.Controllers.GreenField Monitoring = entity.MonitoringExpiration - entity.ExpirationTime, PaymentTolerance = entity.PaymentTolerance, PaymentMethods = - entity.GetPaymentMethods().Select(method => method.GetId().ToString()).ToArray(), + entity.GetPaymentMethods().Select(method => method.GetId().ToStringNormalized()).ToArray(), SpeedPolicy = entity.SpeedPolicy } }; diff --git a/BTCPayServer/Payments/PaymentMethodId.cs b/BTCPayServer/Payments/PaymentMethodId.cs index 77a047af5..37a902548 100644 --- a/BTCPayServer/Payments/PaymentMethodId.cs +++ b/BTCPayServer/Payments/PaymentMethodId.cs @@ -64,20 +64,38 @@ namespace BTCPayServer.Payments //BTCLike case is special because it is in legacy mode. return PaymentType == PaymentTypes.BTCLike ? CryptoCode : $"{CryptoCode}_{PaymentType}"; } + /// + /// A string we can expose to Greenfield API, not subjected to internal legacy + /// + /// + public string ToStringNormalized() + { + if (PaymentType == PaymentTypes.BTCLike) + return CryptoCode; +#if ALTCOINS + if (CryptoCode == "XMR" && PaymentType == PaymentTypes.MoneroLike) + return CryptoCode; +#endif + return $"{CryptoCode}-{PaymentType.ToStringNormalized()}"; + } public string ToPrettyString() { return $"{CryptoCode} ({PaymentType.ToPrettyString()})"; } - + static char[] Separators = new[] { '_', '-' }; public static bool TryParse(string str, out PaymentMethodId paymentMethodId) { str ??= ""; paymentMethodId = null; - var parts = str.Split('_', StringSplitOptions.RemoveEmptyEntries); + var parts = str.Split(Separators, StringSplitOptions.RemoveEmptyEntries); if (parts.Length == 0 || parts.Length > 2) return false; PaymentType type = PaymentTypes.BTCLike; +#if ALTCOINS + if (parts[0].ToUpperInvariant() == "XMR") + type = PaymentTypes.MoneroLike; +#endif if (parts.Length == 2) { if (!PaymentTypes.TryParse(parts[1], out type)) diff --git a/BTCPayServer/Payments/PaymentTypes.Bitcoin.cs b/BTCPayServer/Payments/PaymentTypes.Bitcoin.cs index a6fe91f54..ffdbd7b12 100644 --- a/BTCPayServer/Payments/PaymentTypes.Bitcoin.cs +++ b/BTCPayServer/Payments/PaymentTypes.Bitcoin.cs @@ -19,6 +19,10 @@ namespace BTCPayServer.Payments public override string ToPrettyString() => "On-Chain"; public override string GetId() => "BTCLike"; + public override string ToStringNormalized() + { + return "OnChain"; + } public override CryptoPaymentData DeserializePaymentData(BTCPayNetworkBase network, string str) { diff --git a/BTCPayServer/Payments/PaymentTypes.Lightning.cs b/BTCPayServer/Payments/PaymentTypes.Lightning.cs index 9236d39f7..999443d2c 100644 --- a/BTCPayServer/Payments/PaymentTypes.Lightning.cs +++ b/BTCPayServer/Payments/PaymentTypes.Lightning.cs @@ -17,7 +17,10 @@ namespace BTCPayServer.Payments public override string ToPrettyString() => "Off-Chain"; public override string GetId() => "LightningLike"; - + public override string ToStringNormalized() + { + return "LightningNetwork"; + } public override CryptoPaymentData DeserializePaymentData(BTCPayNetworkBase network, string str) { return ((BTCPayNetwork)network)?.ToObject(str); diff --git a/BTCPayServer/Payments/PaymentTypes.cs b/BTCPayServer/Payments/PaymentTypes.cs index 391c79c30..6ca9c0cf2 100644 --- a/BTCPayServer/Payments/PaymentTypes.cs +++ b/BTCPayServer/Payments/PaymentTypes.cs @@ -22,6 +22,13 @@ namespace BTCPayServer.Payments /// public static LightningPaymentType LightningLike => LightningPaymentType.Instance; +#if ALTCOINS + /// + /// Monero payment + /// + public static MoneroPaymentType MoneroLike => MoneroPaymentType.Instance; +#endif + public static bool TryParse(string paymentType, out PaymentType type) { switch (paymentType.ToLowerInvariant()) @@ -36,7 +43,7 @@ namespace BTCPayServer.Payments break; #if ALTCOINS case "monerolike": - type = MoneroPaymentType.Instance; + type = PaymentTypes.MoneroLike; break; #endif default: @@ -61,6 +68,15 @@ namespace BTCPayServer.Payments return GetId(); } + /// + /// A string we can expose to Greenfield API, not subjected to internal legacy + /// + /// + public virtual string ToStringNormalized() + { + return ToString(); + } + public abstract string GetId(); public abstract CryptoPaymentData DeserializePaymentData(BTCPayNetworkBase network, string str); public abstract string SerializePaymentData(BTCPayNetworkBase network, CryptoPaymentData paymentData); diff --git a/BTCPayServer/Services/Altcoins/Monero/Payments/MoneroPaymentType.cs b/BTCPayServer/Services/Altcoins/Monero/Payments/MoneroPaymentType.cs index 184d6c1d6..cdfe86260 100644 --- a/BTCPayServer/Services/Altcoins/Monero/Payments/MoneroPaymentType.cs +++ b/BTCPayServer/Services/Altcoins/Monero/Payments/MoneroPaymentType.cs @@ -14,7 +14,10 @@ namespace BTCPayServer.Services.Altcoins.Monero.Payments public override string ToPrettyString() => "On-Chain"; public override string GetId() => "MoneroLike"; - + public override string ToStringNormalized() + { + return "Monero"; + } public override CryptoPaymentData DeserializePaymentData(BTCPayNetworkBase network, string str) { diff --git a/BTCPayServer/wwwroot/swagger/v1/swagger.template.invoices.json b/BTCPayServer/wwwroot/swagger/v1/swagger.template.invoices.json index 1a376b35c..2cd9b467f 100644 --- a/BTCPayServer/wwwroot/swagger/v1/swagger.template.invoices.json +++ b/BTCPayServer/wwwroot/swagger/v1/swagger.template.invoices.json @@ -587,7 +587,7 @@ "items": { "type": "string" }, - "description": "A specific set of payment methods to use for this invoice (ie. BTC, BTC_OnChain). By default, select all payment methods activated in the store." + "description": "A specific set of payment methods to use for this invoice (ie. BTC, BTC-LightningNetwork). By default, select all payment methods activated in the store." }, "expirationMinutes": { "type": "integer",