diff --git a/BTCPayServer.Tests/PaymentHandlerTest.cs b/BTCPayServer.Tests/PaymentHandlerTest.cs new file mode 100644 index 000000000..6a71f3a08 --- /dev/null +++ b/BTCPayServer.Tests/PaymentHandlerTest.cs @@ -0,0 +1,430 @@ +using BTCPayServer.Tests.Logging; +using NBitcoin; +using Xunit; +using Xunit.Abstractions; +using BTCPayServer.Data; +using BTCPayServer.Services.Rates; +using System.Collections.Generic; +using System.Threading.Tasks; +using BTCPayServer.Payments; +using BTCPayServer.Payments.Bitcoin; +using BTCPayServer.Payments.Lightning; +using BTCPayServer.Rating; + +namespace BTCPayServer.Tests +{ + public class PaymentHandlerTest + { + private BitcoinLikePaymentHandler handlerBTC; + private LightningLikePaymentHandler handlerLN; + private Dictionary> currencyPairRateResult; + + public PaymentHandlerTest(ITestOutputHelper helper) + { + +#pragma warning disable CS0618 + + Logs.Tester = new XUnitLog(helper) { Name = "Tests" }; + Logs.LogProvider = new XUnitLogProvider(helper); + + var dummy = new Key().PubKey.GetAddress(ScriptPubKeyType.Legacy, Network.RegTest).ToString(); + var networkProvider = new BTCPayNetworkProvider(NetworkType.Regtest); + + currencyPairRateResult = new Dictionary>(); + + var rateResultUSDBTC = new RateResult(); + rateResultUSDBTC.BidAsk= new BidAsk(1m); + + var rateResultBTCUSD = new RateResult(); + rateResultBTCUSD.BidAsk= new BidAsk(1m); + + currencyPairRateResult.Add(new CurrencyPair("USD", "BTC"), Task.FromResult(rateResultUSDBTC)); + currencyPairRateResult.Add(new CurrencyPair("BTC", "USD"), Task.FromResult(rateResultBTCUSD)); + + handlerBTC = new BitcoinLikePaymentHandler(null, networkProvider, null, null); + handlerLN = new LightningLikePaymentHandler(null, null, networkProvider, null); + +#pragma warning restore CS0618 + } + + [Fact] + public void CanPayWithLightningWhenInvoiceTotalUnderLightningMaxValue() + { + +#pragma warning disable CS0618 + + //Given + var store = new StoreBlob + { + OnChainMinValue = null, + LightningMaxValue = new CurrencyValue() {Value = 100.00m, Currency = "USD"} + }; + var paymentMethodId = new PaymentMethodId("BTC", PaymentTypes.LightningLike); + + //When + var totalInvoiceAmount = new Money(98m, MoneyUnit.BTC); + + + //Then + var errorMessage = handlerLN.IsPaymentMethodAllowedBasedOnInvoiceAmount(store, currencyPairRateResult, + totalInvoiceAmount, paymentMethodId); + + Assert.Equal(errorMessage.Result, string.Empty); + +#pragma warning restore CS0618 + } + + + [Fact] + public void CannotPayWithLightningWhenInvoiceTotalAboveLightningMaxValue() + { + +#pragma warning disable CS0618 + + //Given + var store = new StoreBlob + { + OnChainMinValue = null, + LightningMaxValue = new CurrencyValue() {Value = 100.00m, Currency = "USD"} + }; + var totalInvoiceAmount = new Money(102m, MoneyUnit.BTC); + + //When + var paymentMethodId = new PaymentMethodId("BTC", PaymentTypes.LightningLike); + + //Then + var errorMessage = handlerLN.IsPaymentMethodAllowedBasedOnInvoiceAmount(store, currencyPairRateResult, + totalInvoiceAmount, paymentMethodId); + + Assert.NotEqual(errorMessage.Result, string.Empty); + +#pragma warning restore CS0618 + } + + [Fact] + public void CanPayWithLightningWhenInvoiceTotalEqualLightningMaxValue() + { + +#pragma warning disable CS0618 + + //Given + var store = new StoreBlob + { + OnChainMinValue = null, + LightningMaxValue = new CurrencyValue() {Value = 100.00m, Currency = "USD"} + }; + var paymentMethodId = new PaymentMethodId("BTC", PaymentTypes.LightningLike); + + //When + var totalInvoiceAmount = new Money(100m, MoneyUnit.BTC); + + //Then + var errorMessage = handlerLN.IsPaymentMethodAllowedBasedOnInvoiceAmount(store, currencyPairRateResult, + totalInvoiceAmount, paymentMethodId); + + Assert.Equal(errorMessage.Result, string.Empty); + +#pragma warning restore CS0618 + } + + + [Fact] + public void CanPayWithLightningWhenInvoiceTotalUnderLightningMaxValueWhenOnChainMinValueIsGreater() + { + +#pragma warning disable CS0618 + + //Given + var store = new StoreBlob + { + OnChainMinValue = new CurrencyValue() {Value = 100.00m, Currency = "USD"}, + LightningMaxValue = new CurrencyValue() {Value = 50.00m, Currency = "USD"} + }; + var paymentMethodId = new PaymentMethodId("BTC", PaymentTypes.LightningLike); + + //When + var totalInvoiceAmount = new Money(80m, MoneyUnit.BTC); + + //Then + var errorMessage = handlerLN.IsPaymentMethodAllowedBasedOnInvoiceAmount(store, currencyPairRateResult, + totalInvoiceAmount, paymentMethodId); + + Assert.Equal(errorMessage.Result, string.Empty); + +#pragma warning restore CS0618 + } + + + [Fact] + public void CanPayWithLightningWhenInvoiceTotalUnderLightningMaxValueWhenOnChainMinValueIsLower() + { + +#pragma warning disable CS0618 + + //Given + var store = new StoreBlob + { + OnChainMinValue = new CurrencyValue() {Value = 50.00m, Currency = "USD"}, + LightningMaxValue = new CurrencyValue() {Value = 100.00m, Currency = "USD"} + }; + var paymentMethodId = new PaymentMethodId("BTC", PaymentTypes.LightningLike); + + //When + var totalInvoiceAmount = new Money(80m, MoneyUnit.BTC); + + //Then + var errorMessage = handlerLN.IsPaymentMethodAllowedBasedOnInvoiceAmount(store, currencyPairRateResult, + totalInvoiceAmount, paymentMethodId); + + Assert.Equal(errorMessage.Result, string.Empty); + +#pragma warning restore CS0618 + } + + + [Fact] + public void CannotPayWithLightningWhenInvoiceTotalUnderLightningMaxValueWhenOnChainMinValueIsGreater() + { + +#pragma warning disable CS0618 + + //Given + var store = new StoreBlob + { + OnChainMinValue = new CurrencyValue() {Value = 100.00m, Currency = "USD"}, + LightningMaxValue = new CurrencyValue() {Value = 50.00m, Currency = "USD"} + }; + var paymentMethodId = new PaymentMethodId("BTC", PaymentTypes.LightningLike); + + //When + var totalInvoiceAmount = new Money(105m, MoneyUnit.BTC); + + //Then + var errorMessage = handlerLN.IsPaymentMethodAllowedBasedOnInvoiceAmount(store, currencyPairRateResult, + totalInvoiceAmount, paymentMethodId); + + Assert.NotEqual(errorMessage.Result, string.Empty); + +#pragma warning restore CS0618 + } + + + [Fact] + public void CannotPayWithLightningWhenInvoiceTotalUnderLightningMaxValueWhenOnChainMinValueIsLower() + { + +#pragma warning disable CS0618 + + //Given + var store = new StoreBlob + { + OnChainMinValue = new CurrencyValue() {Value = 50.00m, Currency = "USD"}, + LightningMaxValue = new CurrencyValue() {Value = 100.00m, Currency = "USD"} + }; + var paymentMethodId = new PaymentMethodId("BTC", PaymentTypes.LightningLike); + + //When + var totalInvoiceAmount = new Money(105m, MoneyUnit.BTC); + + //Then + var errorMessage = handlerLN.IsPaymentMethodAllowedBasedOnInvoiceAmount(store, currencyPairRateResult, + totalInvoiceAmount, paymentMethodId); + + Assert.NotEqual(errorMessage.Result, string.Empty); + +#pragma warning restore CS0618 + } + + //---- + + + [Fact] + public void CanPayWithBitcoinWhenInvoiceTotalAboveOnChainMinValue() + { + +#pragma warning disable CS0618 + + //Given + var store = new StoreBlob + { + OnChainMinValue = new CurrencyValue() {Value = 100.00m, Currency = "USD"}, + LightningMaxValue = null + }; + var paymentMethodId = new PaymentMethodId("BTC", PaymentTypes.BTCLike); + + //When + var totalInvoiceAmount = new Money(105m, MoneyUnit.BTC); + + + //Then + var errorMessage = handlerBTC.IsPaymentMethodAllowedBasedOnInvoiceAmount(store, currencyPairRateResult, + totalInvoiceAmount, paymentMethodId); + + Assert.Equal(errorMessage.Result, string.Empty); + +#pragma warning restore CS0618 + } + + + [Fact] + public void CannotPayWithBitcoinWhenInvoiceTotalUnderOnChainMinValue() + { + +#pragma warning disable CS0618 + + //Given + var store = new StoreBlob + { + OnChainMinValue = new CurrencyValue() {Value = 100.00m, Currency = "USD"}, + LightningMaxValue = null + }; + var totalInvoiceAmount = new Money(98m, MoneyUnit.BTC); + + //When + var paymentMethodId = new PaymentMethodId("BTC", PaymentTypes.BTCLike); + + //Then + var errorMessage = handlerBTC.IsPaymentMethodAllowedBasedOnInvoiceAmount(store, currencyPairRateResult, + totalInvoiceAmount, paymentMethodId); + + Assert.NotEqual(errorMessage.Result, string.Empty); + +#pragma warning restore CS0618 + } + + [Fact] + public void CanPayWithBitcoinWhenInvoiceTotalEqualOnChainMinValue() + { + +#pragma warning disable CS0618 + + //Given + var store = new StoreBlob + { + OnChainMinValue = new CurrencyValue() {Value = 100.00m, Currency = "USD"}, + LightningMaxValue = null + }; + var paymentMethodId = new PaymentMethodId("BTC", PaymentTypes.BTCLike); + + //When + var totalInvoiceAmount = new Money(100m, MoneyUnit.BTC); + + //Then + var errorMessage = handlerBTC.IsPaymentMethodAllowedBasedOnInvoiceAmount(store, currencyPairRateResult, + totalInvoiceAmount, paymentMethodId); + + Assert.Equal(errorMessage.Result, string.Empty); + +#pragma warning restore CS0618 + } + + + [Fact] + public void CanPayWithBitcoinWhenInvoiceTotalAboveOnchainMinValueWhenLightningMaxValueIsLower() + { + +#pragma warning disable CS0618 + + //Given + var store = new StoreBlob + { + OnChainMinValue = new CurrencyValue() {Value = 100.00m, Currency = "USD"}, + LightningMaxValue = new CurrencyValue() {Value = 50.00m, Currency = "USD"} + }; + var paymentMethodId = new PaymentMethodId("BTC", PaymentTypes.BTCLike); + + //When + var totalInvoiceAmount = new Money(80m, MoneyUnit.BTC); + + //Then + var errorMessage = handlerBTC.IsPaymentMethodAllowedBasedOnInvoiceAmount(store, currencyPairRateResult, + totalInvoiceAmount, paymentMethodId); + + Assert.Equal(errorMessage.Result, string.Empty); + +#pragma warning restore CS0618 + } + + + [Fact] + public void CanPayWithBitcoinWhenInvoiceTotalAboveOnChainMinValueWhenLightningMaxValueIsGreater() + { + +#pragma warning disable CS0618 + + //Given + var store = new StoreBlob + { + OnChainMinValue = new CurrencyValue() {Value = 50.00m, Currency = "USD"}, + LightningMaxValue = new CurrencyValue() {Value = 100.00m, Currency = "USD"} + }; + var paymentMethodId = new PaymentMethodId("BTC", PaymentTypes.BTCLike); + + //When + var totalInvoiceAmount = new Money(80m, MoneyUnit.BTC); + + //Then + var errorMessage = handlerBTC.IsPaymentMethodAllowedBasedOnInvoiceAmount(store, currencyPairRateResult, + totalInvoiceAmount, paymentMethodId); + + Assert.Equal(errorMessage.Result, string.Empty); + +#pragma warning restore CS0618 + } + + + [Fact] + public void CannotPayWithBitcoinWhenInvoiceTotalUnderOnChainMinValueWhenLightningMaxValueIsLower() + { + +#pragma warning disable CS0618 + + //Given + var store = new StoreBlob + { + OnChainMinValue = new CurrencyValue() {Value = 100.00m, Currency = "USD"}, + LightningMaxValue = new CurrencyValue() {Value = 50.00m, Currency = "USD"} + }; + var paymentMethodId = new PaymentMethodId("BTC", PaymentTypes.BTCLike); + + //When + var totalInvoiceAmount = new Money(45m, MoneyUnit.BTC); + + //Then + var errorMessage = handlerBTC.IsPaymentMethodAllowedBasedOnInvoiceAmount(store, currencyPairRateResult, + totalInvoiceAmount, paymentMethodId); + + Assert.NotEqual(errorMessage.Result, string.Empty); + +#pragma warning restore CS0618 + } + + + [Fact] + public void CannotPayWithBitcoinWhenInvoiceTotalUnderOnChainMinValueWhenLightningMaxValueIsGreater() + { + +#pragma warning disable CS0618 + + //Given + var store = new StoreBlob + { + OnChainMinValue = new CurrencyValue() {Value = 50.00m, Currency = "USD"}, + LightningMaxValue = new CurrencyValue() {Value = 100.00m, Currency = "USD"} + }; + var paymentMethodId = new PaymentMethodId("BTC", PaymentTypes.BTCLike); + + //When + var totalInvoiceAmount = new Money(45m, MoneyUnit.BTC); + + //Then + var errorMessage = handlerBTC.IsPaymentMethodAllowedBasedOnInvoiceAmount(store, currencyPairRateResult, + totalInvoiceAmount, paymentMethodId); + + Assert.NotEqual(errorMessage.Result, string.Empty); + +#pragma warning restore CS0618 + } + + } +} diff --git a/BTCPayServer/Payments/Bitcoin/BitcoinLikePaymentHandler.cs b/BTCPayServer/Payments/Bitcoin/BitcoinLikePaymentHandler.cs index e2c1ad50f..bcb09b668 100644 --- a/BTCPayServer/Payments/Bitcoin/BitcoinLikePaymentHandler.cs +++ b/BTCPayServer/Payments/Bitcoin/BitcoinLikePaymentHandler.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Globalization; using System.Linq; using System.Threading.Tasks; using BTCPayServer.Data; @@ -11,9 +10,6 @@ using BTCPayServer.Services; using BTCPayServer.Services.Invoices; using BTCPayServer.Services.Rates; using NBitcoin; -using NBitpayClient; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; namespace BTCPayServer.Payments.Bitcoin { diff --git a/BTCPayServer/Payments/IPaymentMethodHandler.cs b/BTCPayServer/Payments/IPaymentMethodHandler.cs index 5cf3403cc..d0a7d099e 100644 --- a/BTCPayServer/Payments/IPaymentMethodHandler.cs +++ b/BTCPayServer/Payments/IPaymentMethodHandler.cs @@ -7,8 +7,6 @@ using BTCPayServer.Rating; using BTCPayServer.Services.Invoices; using BTCPayServer.Services.Rates; using NBitcoin; -using NBitpayClient; -using Newtonsoft.Json.Linq; using InvoiceResponse = BTCPayServer.Models.InvoiceResponse; namespace BTCPayServer.Payments diff --git a/BTCPayServer/Payments/Lightning/LightningLikePaymentHandler.cs b/BTCPayServer/Payments/Lightning/LightningLikePaymentHandler.cs index 770d3da2c..10167709e 100644 --- a/BTCPayServer/Payments/Lightning/LightningLikePaymentHandler.cs +++ b/BTCPayServer/Payments/Lightning/LightningLikePaymentHandler.cs @@ -13,9 +13,6 @@ using BTCPayServer.Services.Invoices; using BTCPayServer.Services; using BTCPayServer.Services.Rates; using NBitcoin; -using NBitpayClient; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; namespace BTCPayServer.Payments.Lightning { @@ -159,7 +156,7 @@ namespace BTCPayServer.Payments.Lightning if (storeBlob.LightningMaxValue != null && storeBlob.OnChainMinValue == null) { - compare = (value, limit) => value >= limit; + compare = (value, limit) => value > limit; limitValue = storeBlob.LightningMaxValue; errorMessage = "The amount of the invoice is too high to be paid with lightning"; } @@ -171,7 +168,7 @@ namespace BTCPayServer.Payments.Lightning { //Case where both fields are set but LightningMaxValue is greater // --> then use LightningMaxValue as limit - compare = (value, limit) => value >= limit; + compare = (value, limit) => value > limit; limitValue = storeBlob.LightningMaxValue; errorMessage = "The amount of the invoice is too high to be paid with lightning"; } @@ -181,7 +178,7 @@ namespace BTCPayServer.Payments.Lightning //Case where both fields are set but OnChainMinValue is greater // --> then use OnChainMinValue as limit // (Otherwise a gap of price value with no payment method is possible) - compare = (value, limit) => value >= limit; + compare = (value, limit) => value > limit; limitValue = storeBlob.OnChainMinValue; errorMessage = "The amount of the invoice is too high to be paid with lightning"; }