diff --git a/BTCPayServer.Client/Models/OnChainAutomatedPayoutSettings.cs b/BTCPayServer.Client/Models/OnChainAutomatedPayoutSettings.cs index 03b12eac9..01832f037 100644 --- a/BTCPayServer.Client/Models/OnChainAutomatedPayoutSettings.cs +++ b/BTCPayServer.Client/Models/OnChainAutomatedPayoutSettings.cs @@ -10,4 +10,6 @@ public class OnChainAutomatedPayoutSettings [JsonConverter(typeof(TimeSpanJsonConverter.Seconds))] public TimeSpan IntervalSeconds { get; set; } + + public int? FeeBlockTarget { get; set; } } diff --git a/BTCPayServer/Controllers/GreenField/GreenfieldStoreAutomatedOnChainPayoutProcessorsController.cs b/BTCPayServer/Controllers/GreenField/GreenfieldStoreAutomatedOnChainPayoutProcessorsController.cs index f70ee14b7..b2c4865e0 100644 --- a/BTCPayServer/Controllers/GreenField/GreenfieldStoreAutomatedOnChainPayoutProcessorsController.cs +++ b/BTCPayServer/Controllers/GreenField/GreenfieldStoreAutomatedOnChainPayoutProcessorsController.cs @@ -52,16 +52,22 @@ namespace BTCPayServer.Controllers.Greenfield private static OnChainAutomatedPayoutSettings ToModel(PayoutProcessorData data) { + var blob = BaseAutomatedPayoutProcessor.GetBlob(data); return new OnChainAutomatedPayoutSettings() { + FeeBlockTarget = blob.FeeTargetBlock, PaymentMethod = data.PaymentMethod, - IntervalSeconds = InvoiceRepository.FromBytes(data.Blob).Interval + IntervalSeconds = blob.Interval }; } - private static AutomatedPayoutBlob FromModel(OnChainAutomatedPayoutSettings data) + private static OnChainAutomatedPayoutBlob FromModel(OnChainAutomatedPayoutSettings data) { - return new AutomatedPayoutBlob() {Interval = data.IntervalSeconds}; + return new OnChainAutomatedPayoutBlob() + { + FeeTargetBlock = data.FeeBlockTarget ?? 1, + Interval = data.IntervalSeconds + }; } [Authorize(Policy = Policies.CanModifyStoreSettings, AuthenticationSchemes = AuthenticationSchemes.Greenfield)] diff --git a/BTCPayServer/PayoutProcessors/OnChain/OnChainAutomatedPayoutBlob.cs b/BTCPayServer/PayoutProcessors/OnChain/OnChainAutomatedPayoutBlob.cs new file mode 100644 index 000000000..bdc355a2c --- /dev/null +++ b/BTCPayServer/PayoutProcessors/OnChain/OnChainAutomatedPayoutBlob.cs @@ -0,0 +1,8 @@ +using BTCPayServer.PayoutProcessors.Settings; + +namespace BTCPayServer.PayoutProcessors.OnChain; + +public class OnChainAutomatedPayoutBlob : AutomatedPayoutBlob +{ + public int FeeTargetBlock { get; set; } = 1; +} diff --git a/BTCPayServer/PayoutProcessors/OnChain/OnChainAutomatedPayoutProcessor.cs b/BTCPayServer/PayoutProcessors/OnChain/OnChainAutomatedPayoutProcessor.cs index 92f0ed9d8..4789dc891 100644 --- a/BTCPayServer/PayoutProcessors/OnChain/OnChainAutomatedPayoutProcessor.cs +++ b/BTCPayServer/PayoutProcessors/OnChain/OnChainAutomatedPayoutProcessor.cs @@ -23,7 +23,7 @@ using PayoutProcessorData = BTCPayServer.Data.Data.PayoutProcessorData; namespace BTCPayServer.PayoutProcessors.OnChain { - public class OnChainAutomatedPayoutProcessor : BaseAutomatedPayoutProcessor + public class OnChainAutomatedPayoutProcessor : BaseAutomatedPayoutProcessor { private readonly ExplorerClientProvider _explorerClientProvider; private readonly BTCPayWalletProvider _btcPayWalletProvider; @@ -89,8 +89,9 @@ namespace BTCPayServer.PayoutProcessors.OnChain decimal? failedAmount = null; var changeAddress = await explorerClient.GetUnusedAsync( storePaymentMethod.AccountDerivation, DerivationFeature.Change, 0, true); - - var feeRate = await explorerClient.GetFeeRateAsync(1, new FeeRate(1m)); + + var processorBlob = GetBlob(_PayoutProcesserSettings); + var feeRate = await explorerClient.GetFeeRateAsync(processorBlob.FeeTargetBlock,new FeeRate(1m)); var transfersProcessing = new List(); foreach (var transferRequest in payouts) diff --git a/BTCPayServer/PayoutProcessors/OnChain/OnChainAutomatedPayoutSenderFactory.cs b/BTCPayServer/PayoutProcessors/OnChain/OnChainAutomatedPayoutSenderFactory.cs index aa981c9f4..bcfb55af7 100644 --- a/BTCPayServer/PayoutProcessors/OnChain/OnChainAutomatedPayoutSenderFactory.cs +++ b/BTCPayServer/PayoutProcessors/OnChain/OnChainAutomatedPayoutSenderFactory.cs @@ -22,7 +22,8 @@ public class OnChainAutomatedPayoutSenderFactory : EventHostedServiceBase, IPayo public string FriendlyName { get; } = "Automated Bitcoin Sender"; public OnChainAutomatedPayoutSenderFactory(EventAggregator eventAggregator, ILogger logger, - BTCPayNetworkProvider btcPayNetworkProvider, IServiceProvider serviceProvider, LinkGenerator linkGenerator) : base(eventAggregator, logger) + BTCPayNetworkProvider btcPayNetworkProvider, + IServiceProvider serviceProvider, LinkGenerator linkGenerator) : base(eventAggregator, logger) { _btcPayNetworkProvider = btcPayNetworkProvider; _serviceProvider = serviceProvider; diff --git a/BTCPayServer/PayoutProcessors/OnChain/UIOnChainAutomatedPayoutProcessorsController.cs b/BTCPayServer/PayoutProcessors/OnChain/UIOnChainAutomatedPayoutProcessorsController.cs index 7a6c65e21..5897e146e 100644 --- a/BTCPayServer/PayoutProcessors/OnChain/UIOnChainAutomatedPayoutProcessorsController.cs +++ b/BTCPayServer/PayoutProcessors/OnChain/UIOnChainAutomatedPayoutProcessorsController.cs @@ -72,7 +72,7 @@ public class UIOnChainAutomatedPayoutProcessorsController : Controller })) .FirstOrDefault(); - return View (new OnChainTransferViewModel(activeProcessor is null? new AutomatedPayoutBlob() : OnChainAutomatedPayoutProcessor.GetBlob(activeProcessor))); + return View (new OnChainTransferViewModel(activeProcessor is null? new OnChainAutomatedPayoutBlob() : OnChainAutomatedPayoutProcessor.GetBlob(activeProcessor))); } [HttpPost("~/stores/{storeId}/payout-processors/onchain-automated/{cryptocode}")] @@ -130,15 +130,23 @@ public class UIOnChainAutomatedPayoutProcessorsController : Controller } - public OnChainTransferViewModel(AutomatedPayoutBlob blob) + public OnChainTransferViewModel(OnChainAutomatedPayoutBlob blob) { IntervalMinutes = blob.Interval.TotalMinutes; + FeeTargetBlock = blob.FeeTargetBlock; } + + public int FeeTargetBlock { get; set; } + public double IntervalMinutes { get; set; } - public AutomatedPayoutBlob ToBlob() + public OnChainAutomatedPayoutBlob ToBlob() { - return new AutomatedPayoutBlob { Interval = TimeSpan.FromMinutes(IntervalMinutes) }; + return new OnChainAutomatedPayoutBlob + { + FeeTargetBlock = FeeTargetBlock, + Interval = TimeSpan.FromMinutes(IntervalMinutes) + }; } } } diff --git a/BTCPayServer/Views/UIOnChainAutomatedPayoutProcessors/Configure.cshtml b/BTCPayServer/Views/UIOnChainAutomatedPayoutProcessors/Configure.cshtml index 4512d1810..10901ca3c 100644 --- a/BTCPayServer/Views/UIOnChainAutomatedPayoutProcessors/Configure.cshtml +++ b/BTCPayServer/Views/UIOnChainAutomatedPayoutProcessors/Configure.cshtml @@ -22,6 +22,13 @@ minutes + +
+ +
+ + blocks +
diff --git a/BTCPayServer/wwwroot/swagger/v1/swagger.template.payout-processors.json b/BTCPayServer/wwwroot/swagger/v1/swagger.template.payout-processors.json index 1855faf85..79f82a33d 100644 --- a/BTCPayServer/wwwroot/swagger/v1/swagger.template.payout-processors.json +++ b/BTCPayServer/wwwroot/swagger/v1/swagger.template.payout-processors.json @@ -607,6 +607,11 @@ "type": "object", "additionalProperties": false, "properties": { + "feeTargetBlock": { + "type": "number", + "description": "How many blocks should the fee rate calculation target to confirm in. Set to 1 if not provided", + "nullable": true + }, "intervalSeconds": { "description": "How often should the processor run", "allOf": [ @@ -625,6 +630,10 @@ "description": "payment method of the payout processor", "type": "string" }, + "feeTargetBlock": { + "type": "number", + "description": "How many blocks should the fee rate calculation target to confirm in." + }, "intervalSeconds": { "description": "How often should the processor run", "allOf": [