Refactor and decouple Payout logic (#2046)

* Refactor and decouple Payout logic

So that we can support lightning and more complex flows like allowing external payments to payouts.

* fix dropdown align

* switch to simpler buttons

* rebase fixes

add some comments

* rebase fixes

add some comments

* simplify enum caveman logic

* reduce code duplication and db round trips

* Fix pull payment date format

* fix issue with payouts to send page not working correctly

* try fix some style issue

* fix bip21parse
This commit is contained in:
Andrew Camilleri
2021-04-13 10:36:49 +02:00
committed by GitHub
parent 98eee27b93
commit 2e12befb8b
26 changed files with 936 additions and 645 deletions

View File

@@ -8,7 +8,6 @@ using BTCPayServer.Abstractions.Constants;
using BTCPayServer.Abstractions.Extensions;
using BTCPayServer.Abstractions.Models;
using BTCPayServer.Client;
using BTCPayServer.Client.Models;
using BTCPayServer.Data;
using BTCPayServer.HostedServices;
using BTCPayServer.ModelBinders;
@@ -16,7 +15,6 @@ using BTCPayServer.Models;
using BTCPayServer.Models.StoreViewModels;
using BTCPayServer.Models.WalletViewModels;
using BTCPayServer.Payments;
using BTCPayServer.Security;
using BTCPayServer.Services;
using BTCPayServer.Services.Labels;
using BTCPayServer.Services.Rates;
@@ -62,6 +60,7 @@ namespace BTCPayServer.Controllers
private readonly ApplicationDbContextFactory _dbContextFactory;
private readonly BTCPayNetworkJsonSerializerSettings _jsonSerializerSettings;
private readonly PullPaymentHostedService _pullPaymentService;
private readonly IEnumerable<IPayoutHandler> _payoutHandlers;
public RateFetcher RateFetcher { get; }
@@ -86,7 +85,8 @@ namespace BTCPayServer.Controllers
LabelFactory labelFactory,
ApplicationDbContextFactory dbContextFactory,
BTCPayNetworkJsonSerializerSettings jsonSerializerSettings,
HostedServices.PullPaymentHostedService pullPaymentService)
HostedServices.PullPaymentHostedService pullPaymentService,
IEnumerable<IPayoutHandler> payoutHandlers)
{
_currencyTable = currencyTable;
Repository = repo;
@@ -109,6 +109,7 @@ namespace BTCPayServer.Controllers
_dbContextFactory = dbContextFactory;
_jsonSerializerSettings = jsonSerializerSettings;
_pullPaymentService = pullPaymentService;
_payoutHandlers = payoutHandlers;
}
// Borrowed from https://github.com/ManageIQ/guides/blob/master/labels.md
@@ -426,7 +427,7 @@ namespace BTCPayServer.Controllers
[Route("{walletId}/send")]
public async Task<IActionResult> WalletSend(
[ModelBinder(typeof(WalletIdModelBinder))]
WalletId walletId, string defaultDestination = null, string defaultAmount = null, string bip21 = null)
WalletId walletId, string defaultDestination = null, string defaultAmount = null, string[] bip21 = null)
{
if (walletId?.StoreId == null)
return NotFound();
@@ -444,19 +445,29 @@ namespace BTCPayServer.Controllers
double.TryParse(defaultAmount, out var amount);
var model = new WalletSendModel()
{
Outputs = new List<WalletSendModel.TransactionOutput>()
CryptoCode = walletId.CryptoCode
};
if (bip21?.Any() is true)
{
foreach (var link in bip21)
{
if (!string.IsNullOrEmpty(link))
{
LoadFromBIP21(model, link, network);
}
}
}
if (!(model.Outputs?.Any() is true))
{
model.Outputs = new List<WalletSendModel.TransactionOutput>()
{
new WalletSendModel.TransactionOutput()
{
Amount = Convert.ToDecimal(amount),
DestinationAddress = defaultDestination
Amount = Convert.ToDecimal(amount), DestinationAddress = defaultDestination
}
},
CryptoCode = walletId.CryptoCode
};
if (!string.IsNullOrEmpty(bip21))
{
LoadFromBIP21(model, bip21, network);
};
}
var feeProvider = _feeRateProvider.CreateFeeProvider(network);
var recommendedFees =
@@ -540,6 +551,7 @@ namespace BTCPayServer.Controllers
vm.NBXSeedAvailable = await GetSeed(walletId, network) != null;
if (!string.IsNullOrEmpty(bip21))
{
vm.Outputs?.Clear();
LoadFromBIP21(vm, bip21, network);
}
@@ -577,6 +589,10 @@ namespace BTCPayServer.Controllers
if (!string.IsNullOrEmpty(bip21))
{
if (!vm.Outputs.Any())
{
vm.Outputs.Add(new WalletSendModel.TransactionOutput());
}
return View(vm);
}
if (command == "add-output")
@@ -720,6 +736,7 @@ namespace BTCPayServer.Controllers
private void LoadFromBIP21(WalletSendModel vm, string bip21, BTCPayNetwork network)
{
vm.Outputs ??= new List<WalletSendModel.TransactionOutput>();
try
{
if (bip21.StartsWith(network.UriScheme, StringComparison.InvariantCultureIgnoreCase))
@@ -728,15 +745,13 @@ namespace BTCPayServer.Controllers
}
var uriBuilder = new NBitcoin.Payment.BitcoinUrlBuilder(bip21, network.NBitcoinNetwork);
vm.Outputs = new List<WalletSendModel.TransactionOutput>()
vm.Outputs.Add(new WalletSendModel.TransactionOutput()
{
new WalletSendModel.TransactionOutput()
{
Amount = uriBuilder.Amount?.ToDecimal(MoneyUnit.BTC),
DestinationAddress = uriBuilder.Address.ToString(),
SubtractFeesFromOutput = false
}
};
Amount = uriBuilder.Amount?.ToDecimal(MoneyUnit.BTC),
DestinationAddress = uriBuilder.Address.ToString(),
SubtractFeesFromOutput = false
});
if (!string.IsNullOrEmpty(uriBuilder.Label) || !string.IsNullOrEmpty(uriBuilder.Message))
{
TempData.SetStatusMessageModel(new StatusMessageModel()
@@ -754,13 +769,11 @@ namespace BTCPayServer.Controllers
{
try
{
vm.Outputs = new List<WalletSendModel.TransactionOutput>()
{
new WalletSendModel.TransactionOutput()
vm.Outputs.Add(new WalletSendModel.TransactionOutput()
{
DestinationAddress = BitcoinAddress.Create(bip21, network.NBitcoinNetwork).ToString()
}
};
);
}
catch
{