mirror of
https://github.com/btcpayserver/btcpayserver.git
synced 2025-01-18 21:32:27 +01:00
163 lines
7.0 KiB
C#
163 lines
7.0 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.ComponentModel.DataAnnotations;
|
|
using System.Linq;
|
|
using System.Threading.Tasks;
|
|
using BTCPayServer.Abstractions.Constants;
|
|
using BTCPayServer.Abstractions.Extensions;
|
|
using BTCPayServer.Abstractions.Models;
|
|
using BTCPayServer.Client;
|
|
using BTCPayServer.Data;
|
|
using BTCPayServer.Payments;
|
|
using BTCPayServer.Services.Invoices;
|
|
using Microsoft.AspNetCore.Authorization;
|
|
using Microsoft.AspNetCore.Mvc;
|
|
|
|
namespace BTCPayServer.PayoutProcessors.OnChain;
|
|
|
|
public class UIOnChainAutomatedPayoutProcessorsController : Controller
|
|
{
|
|
private readonly EventAggregator _eventAggregator;
|
|
private readonly PaymentMethodHandlerDictionary _handlers;
|
|
private readonly OnChainAutomatedPayoutSenderFactory _onChainAutomatedPayoutSenderFactory;
|
|
private readonly PayoutProcessorService _payoutProcessorService;
|
|
|
|
public UIOnChainAutomatedPayoutProcessorsController(
|
|
EventAggregator eventAggregator,
|
|
PaymentMethodHandlerDictionary handlers,
|
|
OnChainAutomatedPayoutSenderFactory onChainAutomatedPayoutSenderFactory,
|
|
PayoutProcessorService payoutProcessorService)
|
|
{
|
|
_eventAggregator = eventAggregator;
|
|
_handlers = handlers;
|
|
_onChainAutomatedPayoutSenderFactory = onChainAutomatedPayoutSenderFactory;
|
|
_payoutProcessorService = payoutProcessorService;
|
|
}
|
|
PaymentMethodId GetPaymentMethodId(string cryptoCode) => PaymentTypes.CHAIN.GetPaymentMethodId(cryptoCode);
|
|
[HttpGet("~/stores/{storeId}/payout-processors/onchain-automated/{cryptocode}")]
|
|
[Authorize(AuthenticationSchemes = AuthenticationSchemes.Cookie)]
|
|
[Authorize(Policy = Policies.CanViewStoreSettings, AuthenticationSchemes = AuthenticationSchemes.Cookie)]
|
|
public async Task<IActionResult> Configure(string storeId, string cryptoCode)
|
|
{
|
|
var id = GetPaymentMethodId(cryptoCode);
|
|
if (!_onChainAutomatedPayoutSenderFactory.GetSupportedPaymentMethods().Any(i => id == i))
|
|
{
|
|
TempData.SetStatusMessageModel(new StatusMessageModel()
|
|
{
|
|
Severity = StatusMessageModel.StatusSeverity.Error,
|
|
Message = $"This processor cannot handle {cryptoCode}."
|
|
});
|
|
return RedirectToAction("ConfigureStorePayoutProcessors", "UiPayoutProcessors");
|
|
}
|
|
var wallet = HttpContext.GetStoreData().GetDerivationSchemeSettings(_handlers, cryptoCode);
|
|
if (wallet?.IsHotWallet is not true)
|
|
{
|
|
TempData.SetStatusMessageModel(new StatusMessageModel()
|
|
{
|
|
Severity = StatusMessageModel.StatusSeverity.Error,
|
|
Message = $"Either your {cryptoCode} wallet is not configured, or it is not a hot wallet. This processor cannot function until a hot wallet is configured in your store."
|
|
});
|
|
}
|
|
var activeProcessor =
|
|
(await _payoutProcessorService.GetProcessors(
|
|
new PayoutProcessorService.PayoutProcessorQuery()
|
|
{
|
|
Stores = new[] { storeId },
|
|
Processors = new[] { _onChainAutomatedPayoutSenderFactory.Processor },
|
|
PaymentMethods = new[]
|
|
{
|
|
PaymentTypes.CHAIN.GetPaymentMethodId(cryptoCode)
|
|
}
|
|
}))
|
|
.FirstOrDefault();
|
|
|
|
return View(new OnChainTransferViewModel(activeProcessor is null ? new OnChainAutomatedPayoutBlob() : OnChainAutomatedPayoutProcessor.GetBlob(activeProcessor)));
|
|
}
|
|
|
|
[HttpPost("~/stores/{storeId}/payout-processors/onchain-automated/{cryptocode}")]
|
|
[Authorize(AuthenticationSchemes = AuthenticationSchemes.Cookie)]
|
|
[Authorize(Policy = Policies.CanModifyStoreSettings, AuthenticationSchemes = AuthenticationSchemes.Cookie)]
|
|
public async Task<IActionResult> Configure(string storeId, string cryptoCode, OnChainTransferViewModel automatedTransferBlob)
|
|
{
|
|
if (!ModelState.IsValid)
|
|
return View(automatedTransferBlob);
|
|
var id = GetPaymentMethodId(cryptoCode);
|
|
if (!_onChainAutomatedPayoutSenderFactory.GetSupportedPaymentMethods().Any(i => id == i))
|
|
{
|
|
TempData.SetStatusMessageModel(new StatusMessageModel()
|
|
{
|
|
Severity = StatusMessageModel.StatusSeverity.Error,
|
|
Message = $"This processor cannot handle {cryptoCode}."
|
|
});
|
|
return RedirectToAction("ConfigureStorePayoutProcessors", "UiPayoutProcessors");
|
|
}
|
|
var activeProcessor =
|
|
(await _payoutProcessorService.GetProcessors(
|
|
new PayoutProcessorService.PayoutProcessorQuery()
|
|
{
|
|
Stores = new[] { storeId },
|
|
Processors = new[] { OnChainAutomatedPayoutSenderFactory.ProcessorName },
|
|
PaymentMethods = new[]
|
|
{
|
|
PaymentTypes.CHAIN.GetPaymentMethodId(cryptoCode)
|
|
}
|
|
}))
|
|
.FirstOrDefault();
|
|
activeProcessor ??= new PayoutProcessorData();
|
|
activeProcessor.HasTypedBlob<OnChainAutomatedPayoutBlob>().SetBlob(automatedTransferBlob.ToBlob());
|
|
activeProcessor.StoreId = storeId;
|
|
activeProcessor.PaymentMethod = PaymentTypes.CHAIN.GetPaymentMethodId(cryptoCode).ToString();
|
|
activeProcessor.Processor = _onChainAutomatedPayoutSenderFactory.Processor;
|
|
var tcs = new TaskCompletionSource();
|
|
_eventAggregator.Publish(new PayoutProcessorUpdated()
|
|
{
|
|
Data = activeProcessor,
|
|
Id = activeProcessor.Id,
|
|
Processed = tcs
|
|
});
|
|
TempData.SetStatusMessageModel(new StatusMessageModel
|
|
{
|
|
Severity = StatusMessageModel.StatusSeverity.Success,
|
|
Message = "Processor updated."
|
|
});
|
|
await tcs.Task;
|
|
return RedirectToAction("ConfigureStorePayoutProcessors", "UiPayoutProcessors", new { storeId });
|
|
}
|
|
|
|
public class OnChainTransferViewModel
|
|
{
|
|
public OnChainTransferViewModel()
|
|
{
|
|
|
|
}
|
|
|
|
public OnChainTransferViewModel(OnChainAutomatedPayoutBlob blob)
|
|
{
|
|
ProcessNewPayoutsInstantly = blob.ProcessNewPayoutsInstantly;
|
|
IntervalMinutes = blob.Interval.TotalMinutes;
|
|
FeeTargetBlock = blob.FeeTargetBlock;
|
|
Threshold = blob.Threshold;
|
|
}
|
|
|
|
public bool ProcessNewPayoutsInstantly { get; set; }
|
|
|
|
[Range(1, 1000)]
|
|
public int FeeTargetBlock { get; set; }
|
|
public decimal Threshold { get; set; }
|
|
|
|
[Range(AutomatedPayoutConstants.MinIntervalMinutes, AutomatedPayoutConstants.MaxIntervalMinutes)]
|
|
public double IntervalMinutes { get; set; }
|
|
|
|
public OnChainAutomatedPayoutBlob ToBlob()
|
|
{
|
|
return new OnChainAutomatedPayoutBlob
|
|
{
|
|
ProcessNewPayoutsInstantly = ProcessNewPayoutsInstantly,
|
|
FeeTargetBlock = FeeTargetBlock,
|
|
Interval = TimeSpan.FromMinutes(IntervalMinutes),
|
|
Threshold = Threshold
|
|
};
|
|
}
|
|
}
|
|
}
|