Allow specifing fee block target for onchain payout processor (#4065)

Co-authored-by: d11n <mail@dennisreimann.de>
This commit is contained in:
Andrew Camilleri
2022-08-23 12:35:20 +02:00
committed by GitHub
parent 01ab21e4c0
commit 7c8f4c0405
8 changed files with 53 additions and 11 deletions

View File

@@ -10,4 +10,6 @@ public class OnChainAutomatedPayoutSettings
[JsonConverter(typeof(TimeSpanJsonConverter.Seconds))] [JsonConverter(typeof(TimeSpanJsonConverter.Seconds))]
public TimeSpan IntervalSeconds { get; set; } public TimeSpan IntervalSeconds { get; set; }
public int? FeeBlockTarget { get; set; }
} }

View File

@@ -52,16 +52,22 @@ namespace BTCPayServer.Controllers.Greenfield
private static OnChainAutomatedPayoutSettings ToModel(PayoutProcessorData data) private static OnChainAutomatedPayoutSettings ToModel(PayoutProcessorData data)
{ {
var blob = BaseAutomatedPayoutProcessor<OnChainAutomatedPayoutBlob>.GetBlob(data);
return new OnChainAutomatedPayoutSettings() return new OnChainAutomatedPayoutSettings()
{ {
FeeBlockTarget = blob.FeeTargetBlock,
PaymentMethod = data.PaymentMethod, PaymentMethod = data.PaymentMethod,
IntervalSeconds = InvoiceRepository.FromBytes<AutomatedPayoutBlob>(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)] [Authorize(Policy = Policies.CanModifyStoreSettings, AuthenticationSchemes = AuthenticationSchemes.Greenfield)]

View File

@@ -0,0 +1,8 @@
using BTCPayServer.PayoutProcessors.Settings;
namespace BTCPayServer.PayoutProcessors.OnChain;
public class OnChainAutomatedPayoutBlob : AutomatedPayoutBlob
{
public int FeeTargetBlock { get; set; } = 1;
}

View File

@@ -23,7 +23,7 @@ using PayoutProcessorData = BTCPayServer.Data.Data.PayoutProcessorData;
namespace BTCPayServer.PayoutProcessors.OnChain namespace BTCPayServer.PayoutProcessors.OnChain
{ {
public class OnChainAutomatedPayoutProcessor : BaseAutomatedPayoutProcessor<AutomatedPayoutBlob> public class OnChainAutomatedPayoutProcessor : BaseAutomatedPayoutProcessor<OnChainAutomatedPayoutBlob>
{ {
private readonly ExplorerClientProvider _explorerClientProvider; private readonly ExplorerClientProvider _explorerClientProvider;
private readonly BTCPayWalletProvider _btcPayWalletProvider; private readonly BTCPayWalletProvider _btcPayWalletProvider;
@@ -89,8 +89,9 @@ namespace BTCPayServer.PayoutProcessors.OnChain
decimal? failedAmount = null; decimal? failedAmount = null;
var changeAddress = await explorerClient.GetUnusedAsync( var changeAddress = await explorerClient.GetUnusedAsync(
storePaymentMethod.AccountDerivation, DerivationFeature.Change, 0, true); 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<PayoutData>(); var transfersProcessing = new List<PayoutData>();
foreach (var transferRequest in payouts) foreach (var transferRequest in payouts)

View File

@@ -22,7 +22,8 @@ public class OnChainAutomatedPayoutSenderFactory : EventHostedServiceBase, IPayo
public string FriendlyName { get; } = "Automated Bitcoin Sender"; public string FriendlyName { get; } = "Automated Bitcoin Sender";
public OnChainAutomatedPayoutSenderFactory(EventAggregator eventAggregator, public OnChainAutomatedPayoutSenderFactory(EventAggregator eventAggregator,
ILogger<OnChainAutomatedPayoutSenderFactory> logger, ILogger<OnChainAutomatedPayoutSenderFactory> logger,
BTCPayNetworkProvider btcPayNetworkProvider, IServiceProvider serviceProvider, LinkGenerator linkGenerator) : base(eventAggregator, logger) BTCPayNetworkProvider btcPayNetworkProvider,
IServiceProvider serviceProvider, LinkGenerator linkGenerator) : base(eventAggregator, logger)
{ {
_btcPayNetworkProvider = btcPayNetworkProvider; _btcPayNetworkProvider = btcPayNetworkProvider;
_serviceProvider = serviceProvider; _serviceProvider = serviceProvider;

View File

@@ -72,7 +72,7 @@ public class UIOnChainAutomatedPayoutProcessorsController : Controller
})) }))
.FirstOrDefault(); .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}")] [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; IntervalMinutes = blob.Interval.TotalMinutes;
FeeTargetBlock = blob.FeeTargetBlock;
} }
public int FeeTargetBlock { get; set; }
public double IntervalMinutes { 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)
};
} }
} }
} }

View File

@@ -22,6 +22,13 @@
<input asp-for="IntervalMinutes" class="form-control" inputmode="numeric" style="max-width:10ch;"> <input asp-for="IntervalMinutes" class="form-control" inputmode="numeric" style="max-width:10ch;">
<span class="input-group-text">minutes</span> <span class="input-group-text">minutes</span>
</div> </div>
</div>
<div class="form-group">
<label asp-for="FeeTargetBlock" class="form-label" data-required>Fee block target</label>
<div class="input-group">
<input asp-for="FeeTargetBlock" class="form-control" min="1" inputmode="numeric" style="max-width:10ch;">
<span class="input-group-text">blocks</span>
</div>
</div> </div>
<button name="command" type="submit" class="btn btn-primary mt-2" value="Save" id="Save">Save</button> <button name="command" type="submit" class="btn btn-primary mt-2" value="Save" id="Save">Save</button>
</form> </form>

View File

@@ -607,6 +607,11 @@
"type": "object", "type": "object",
"additionalProperties": false, "additionalProperties": false,
"properties": { "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": { "intervalSeconds": {
"description": "How often should the processor run", "description": "How often should the processor run",
"allOf": [ "allOf": [
@@ -625,6 +630,10 @@
"description": "payment method of the payout processor", "description": "payment method of the payout processor",
"type": "string" "type": "string"
}, },
"feeTargetBlock": {
"type": "number",
"description": "How many blocks should the fee rate calculation target to confirm in."
},
"intervalSeconds": { "intervalSeconds": {
"description": "How often should the processor run", "description": "How often should the processor run",
"allOf": [ "allOf": [