diff --git a/BTCPayServer.Tests/docker-compose.yml b/BTCPayServer.Tests/docker-compose.yml index 2e093e43e..7a5654eaf 100644 --- a/BTCPayServer.Tests/docker-compose.yml +++ b/BTCPayServer.Tests/docker-compose.yml @@ -63,7 +63,7 @@ services: nbxplorer: - image: nicolasdorier/nbxplorer:1.0.2.14 + image: nicolasdorier/nbxplorer:1.0.2.31 ports: - "32838:32838" expose: diff --git a/BTCPayServer/BTCPayServer.csproj b/BTCPayServer/BTCPayServer.csproj index e2b732c20..9b89bae49 100644 --- a/BTCPayServer/BTCPayServer.csproj +++ b/BTCPayServer/BTCPayServer.csproj @@ -2,7 +2,7 @@ Exe netcoreapp2.1 - 1.0.2.93 + 1.0.2.94 NU1701,CA1816,CA1308,CA1810,CA2208 diff --git a/BTCPayServer/Controllers/InvoiceController.cs b/BTCPayServer/Controllers/InvoiceController.cs index 1b8932914..0add952df 100644 --- a/BTCPayServer/Controllers/InvoiceController.cs +++ b/BTCPayServer/Controllers/InvoiceController.cs @@ -210,6 +210,7 @@ namespace BTCPayServer.Controllers try { var storeBlob = store.GetStoreBlob(); + var preparePayment = handler.PreparePayment(supportedPaymentMethod, store, network); var rate = await fetchingByCurrencyPair[new CurrencyPair(network.CryptoCode, entity.ProductInformation.Currency)]; if (rate.BidAsk == null) { @@ -220,7 +221,7 @@ namespace BTCPayServer.Controllers paymentMethod.Network = network; paymentMethod.SetId(supportedPaymentMethod.PaymentId); paymentMethod.Rate = rate.BidAsk.Bid; - var paymentDetails = await handler.CreatePaymentMethodDetails(supportedPaymentMethod, paymentMethod, store, network); + var paymentDetails = await handler.CreatePaymentMethodDetails(supportedPaymentMethod, paymentMethod, store, network, preparePayment); if (storeBlob.NetworkFeeDisabled) paymentDetails.SetNoTxFee(); paymentMethod.SetPaymentMethodDetails(paymentDetails); diff --git a/BTCPayServer/Payments/Bitcoin/BitcoinLikePaymentHandler.cs b/BTCPayServer/Payments/Bitcoin/BitcoinLikePaymentHandler.cs index 4ddb426aa..f38bd84f6 100644 --- a/BTCPayServer/Payments/Bitcoin/BitcoinLikePaymentHandler.cs +++ b/BTCPayServer/Payments/Bitcoin/BitcoinLikePaymentHandler.cs @@ -27,16 +27,30 @@ namespace BTCPayServer.Payments.Bitcoin _WalletProvider = walletProvider; } - public override async Task CreatePaymentMethodDetails(DerivationStrategy supportedPaymentMethod, PaymentMethod paymentMethod, StoreData store, BTCPayNetwork network) + class Prepare + { + public Task GetFeeRate; + public Task ReserveAddress; + } + + public override object PreparePayment(DerivationStrategy supportedPaymentMethod, StoreData store, BTCPayNetwork network) + { + return new Prepare() + { + GetFeeRate = _FeeRateProviderFactory.CreateFeeProvider(network).GetFeeRateAsync(), + ReserveAddress = _WalletProvider.GetWallet(network).ReserveAddressAsync(supportedPaymentMethod.DerivationStrategyBase) + }; + } + + public override async Task CreatePaymentMethodDetails(DerivationStrategy supportedPaymentMethod, PaymentMethod paymentMethod, StoreData store, BTCPayNetwork network, object preparePaymentObject) { if (!_ExplorerProvider.IsAvailable(network)) throw new PaymentMethodUnavailableException($"Full node not available"); - var getFeeRate = _FeeRateProviderFactory.CreateFeeProvider(network).GetFeeRateAsync(); - var getAddress = _WalletProvider.GetWallet(network).ReserveAddressAsync(supportedPaymentMethod.DerivationStrategyBase); + var prepare = (Prepare)preparePaymentObject; Payments.Bitcoin.BitcoinLikeOnChainPaymentMethod onchainMethod = new Payments.Bitcoin.BitcoinLikeOnChainPaymentMethod(); - onchainMethod.FeeRate = await getFeeRate; + onchainMethod.FeeRate = await prepare.GetFeeRate; onchainMethod.TxFee = onchainMethod.FeeRate.GetFee(100); // assume price for 100 bytes - onchainMethod.DepositAddress = (await getAddress).ToString(); + onchainMethod.DepositAddress = (await prepare.ReserveAddress).ToString(); return onchainMethod; } } diff --git a/BTCPayServer/Payments/IPaymentMethodHandler.cs b/BTCPayServer/Payments/IPaymentMethodHandler.cs index 9ec09fa45..11687caef 100644 --- a/BTCPayServer/Payments/IPaymentMethodHandler.cs +++ b/BTCPayServer/Payments/IPaymentMethodHandler.cs @@ -20,23 +20,46 @@ namespace BTCPayServer.Payments /// /// /// - Task CreatePaymentMethodDetails(ISupportedPaymentMethod supportedPaymentMethod, PaymentMethod paymentMethod, StoreData store, BTCPayNetwork network); + Task CreatePaymentMethodDetails(ISupportedPaymentMethod supportedPaymentMethod, PaymentMethod paymentMethod, StoreData store, BTCPayNetwork network, object preparePaymentObject); + + /// + /// This method called before the rate have been fetched + /// + /// + /// + /// + /// + object PreparePayment(ISupportedPaymentMethod supportedPaymentMethod, StoreData store, BTCPayNetwork network); } public interface IPaymentMethodHandler : IPaymentMethodHandler where T : ISupportedPaymentMethod { - Task CreatePaymentMethodDetails(T supportedPaymentMethod, PaymentMethod paymentMethod, StoreData store, BTCPayNetwork network); + Task CreatePaymentMethodDetails(T supportedPaymentMethod, PaymentMethod paymentMethod, StoreData store, BTCPayNetwork network, object preparePaymentObject); } public abstract class PaymentMethodHandlerBase : IPaymentMethodHandler where T : ISupportedPaymentMethod { - public abstract Task CreatePaymentMethodDetails(T supportedPaymentMethod, PaymentMethod paymentMethod, StoreData store, BTCPayNetwork network); + + public abstract Task CreatePaymentMethodDetails(T supportedPaymentMethod, PaymentMethod paymentMethod, StoreData store, BTCPayNetwork network, object preparePaymentObject); + public virtual object PreparePayment(T supportedPaymentMethod, StoreData store, BTCPayNetwork network) + { + return null; + } - Task IPaymentMethodHandler.CreatePaymentMethodDetails(ISupportedPaymentMethod supportedPaymentMethod, PaymentMethod paymentMethod, StoreData store, BTCPayNetwork network) + object IPaymentMethodHandler.PreparePayment(ISupportedPaymentMethod supportedPaymentMethod, StoreData store, BTCPayNetwork network) { if (supportedPaymentMethod is T method) { - return CreatePaymentMethodDetails(method, paymentMethod, store, network); + return PreparePayment(method, store, network); + } + throw new NotSupportedException("Invalid supportedPaymentMethod"); + } + + Task IPaymentMethodHandler.CreatePaymentMethodDetails(ISupportedPaymentMethod supportedPaymentMethod, PaymentMethod paymentMethod, StoreData store, BTCPayNetwork network, object preparePaymentObject) + { + if (supportedPaymentMethod is T method) + { + return CreatePaymentMethodDetails(method, paymentMethod, store, network, preparePaymentObject); } throw new NotSupportedException("Invalid supportedPaymentMethod"); } diff --git a/BTCPayServer/Payments/Lightning/LightningLikePaymentHandler.cs b/BTCPayServer/Payments/Lightning/LightningLikePaymentHandler.cs index 4b6c263fd..21a37226a 100644 --- a/BTCPayServer/Payments/Lightning/LightningLikePaymentHandler.cs +++ b/BTCPayServer/Payments/Lightning/LightningLikePaymentHandler.cs @@ -26,7 +26,7 @@ namespace BTCPayServer.Payments.Lightning _LightningClientFactory = lightningClientFactory; _Dashboard = dashboard; } - public override async Task CreatePaymentMethodDetails(LightningSupportedPaymentMethod supportedPaymentMethod, PaymentMethod paymentMethod, StoreData store, BTCPayNetwork network) + public override async Task CreatePaymentMethodDetails(LightningSupportedPaymentMethod supportedPaymentMethod, PaymentMethod paymentMethod, StoreData store, BTCPayNetwork network, object preparePaymentObject) { var storeBlob = store.GetStoreBlob(); var test = Test(supportedPaymentMethod, network);