2022-06-14 07:36:22 +02:00
|
|
|
using System;
|
2024-11-05 13:40:37 +01:00
|
|
|
using System.Threading;
|
2022-06-14 07:36:22 +02:00
|
|
|
using System.Threading.Tasks;
|
2024-01-06 08:46:19 +01:00
|
|
|
using BTCPayServer.Client;
|
2024-11-05 13:40:37 +01:00
|
|
|
using BTCPayServer.Client.Models;
|
2022-06-14 07:36:22 +02:00
|
|
|
using BTCPayServer.Configuration;
|
|
|
|
using BTCPayServer.Data;
|
|
|
|
using BTCPayServer.Lightning;
|
|
|
|
using BTCPayServer.Payments;
|
|
|
|
using BTCPayServer.Payments.Lightning;
|
2024-01-06 08:46:19 +01:00
|
|
|
using BTCPayServer.Security;
|
2022-06-14 07:36:22 +02:00
|
|
|
using BTCPayServer.Services;
|
2024-04-04 09:31:04 +02:00
|
|
|
using BTCPayServer.Services.Invoices;
|
2022-07-04 04:03:16 +02:00
|
|
|
using BTCPayServer.Services.Rates;
|
2022-06-14 07:36:22 +02:00
|
|
|
using BTCPayServer.Services.Stores;
|
2024-01-06 08:46:19 +01:00
|
|
|
using Microsoft.AspNetCore.Authorization;
|
2022-06-14 07:36:22 +02:00
|
|
|
using Microsoft.AspNetCore.Mvc;
|
|
|
|
using Microsoft.Extensions.Options;
|
2024-11-05 13:40:37 +01:00
|
|
|
using StoreData = BTCPayServer.Data.StoreData;
|
2022-06-14 07:36:22 +02:00
|
|
|
|
|
|
|
namespace BTCPayServer.Components.StoreLightningBalance;
|
|
|
|
|
|
|
|
public class StoreLightningBalance : ViewComponent
|
|
|
|
{
|
2024-11-05 13:40:37 +01:00
|
|
|
private const HistogramType DefaultType = HistogramType.Week;
|
|
|
|
|
2022-06-14 07:36:22 +02:00
|
|
|
private readonly StoreRepository _storeRepo;
|
2022-07-04 04:03:16 +02:00
|
|
|
private readonly CurrencyNameTable _currencies;
|
2022-06-14 07:36:22 +02:00
|
|
|
private readonly BTCPayServerOptions _btcpayServerOptions;
|
|
|
|
private readonly BTCPayNetworkProvider _networkProvider;
|
|
|
|
private readonly LightningClientFactoryService _lightningClientFactory;
|
|
|
|
private readonly IOptions<LightningNetworkOptions> _lightningNetworkOptions;
|
|
|
|
private readonly IOptions<ExternalServicesOptions> _externalServiceOptions;
|
2024-01-06 08:46:19 +01:00
|
|
|
private readonly IAuthorizationService _authorizationService;
|
2024-04-04 09:31:04 +02:00
|
|
|
private readonly PaymentMethodHandlerDictionary _handlers;
|
2024-11-05 13:40:37 +01:00
|
|
|
private readonly LightningHistogramService _lnHistogramService;
|
2022-06-14 07:36:22 +02:00
|
|
|
|
|
|
|
public StoreLightningBalance(
|
|
|
|
StoreRepository storeRepo,
|
2022-07-04 04:03:16 +02:00
|
|
|
CurrencyNameTable currencies,
|
2022-06-14 07:36:22 +02:00
|
|
|
BTCPayNetworkProvider networkProvider,
|
|
|
|
BTCPayServerOptions btcpayServerOptions,
|
|
|
|
LightningClientFactoryService lightningClientFactory,
|
|
|
|
IOptions<LightningNetworkOptions> lightningNetworkOptions,
|
2024-04-04 09:31:04 +02:00
|
|
|
IOptions<ExternalServicesOptions> externalServiceOptions,
|
|
|
|
IAuthorizationService authorizationService,
|
2024-11-05 13:40:37 +01:00
|
|
|
PaymentMethodHandlerDictionary handlers,
|
|
|
|
LightningHistogramService lnHistogramService)
|
2022-06-14 07:36:22 +02:00
|
|
|
{
|
|
|
|
_storeRepo = storeRepo;
|
2022-07-04 04:03:16 +02:00
|
|
|
_currencies = currencies;
|
2022-06-14 07:36:22 +02:00
|
|
|
_networkProvider = networkProvider;
|
|
|
|
_btcpayServerOptions = btcpayServerOptions;
|
|
|
|
_externalServiceOptions = externalServiceOptions;
|
2024-01-06 08:46:19 +01:00
|
|
|
_authorizationService = authorizationService;
|
2024-04-04 09:31:04 +02:00
|
|
|
_handlers = handlers;
|
2022-06-14 07:36:22 +02:00
|
|
|
_lightningClientFactory = lightningClientFactory;
|
|
|
|
_lightningNetworkOptions = lightningNetworkOptions;
|
2024-11-05 13:40:37 +01:00
|
|
|
_lnHistogramService = lnHistogramService;
|
2022-06-14 07:36:22 +02:00
|
|
|
}
|
|
|
|
|
2024-11-05 13:40:37 +01:00
|
|
|
public async Task<IViewComponentResult> InvokeAsync(StoreData store, string cryptoCode, bool initialRendering)
|
2022-06-14 07:36:22 +02:00
|
|
|
{
|
2024-11-05 13:40:37 +01:00
|
|
|
var defaultCurrency = store.GetStoreBlob().DefaultCurrency;
|
|
|
|
var vm = new StoreLightningBalanceViewModel
|
|
|
|
{
|
|
|
|
StoreId = store.Id,
|
|
|
|
CryptoCode = cryptoCode,
|
|
|
|
InitialRendering = initialRendering,
|
|
|
|
DefaultCurrency = defaultCurrency,
|
|
|
|
CurrencyData = _currencies.GetCurrencyData(defaultCurrency, true),
|
|
|
|
DataUrl = Url.Action("LightningBalanceDashboard", "UIStores", new { storeId = store.Id, cryptoCode })
|
|
|
|
};
|
2023-01-06 14:18:07 +01:00
|
|
|
|
2024-11-05 13:40:37 +01:00
|
|
|
if (vm.InitialRendering)
|
|
|
|
return View(vm);
|
2024-01-06 08:46:19 +01:00
|
|
|
|
2022-07-04 04:03:16 +02:00
|
|
|
try
|
2022-06-14 07:36:22 +02:00
|
|
|
{
|
2024-11-05 13:40:37 +01:00
|
|
|
var lightningClient = await GetLightningClient(store, vm.CryptoCode);
|
2024-01-06 08:46:19 +01:00
|
|
|
|
2024-11-05 13:40:37 +01:00
|
|
|
// balance
|
|
|
|
using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(10));
|
|
|
|
var balance = await lightningClient.GetBalance(cts.Token);
|
2022-07-04 04:03:16 +02:00
|
|
|
vm.Balance = balance;
|
|
|
|
vm.TotalOnchain = balance.OnchainBalance != null
|
2023-01-06 14:18:07 +01:00
|
|
|
? (balance.OnchainBalance.Confirmed ?? 0L) + (balance.OnchainBalance.Reserved ?? 0L) +
|
2022-07-08 03:55:26 +02:00
|
|
|
(balance.OnchainBalance.Unconfirmed ?? 0L)
|
2022-07-04 04:03:16 +02:00
|
|
|
: null;
|
|
|
|
vm.TotalOffchain = balance.OffchainBalance != null
|
2023-01-06 14:18:07 +01:00
|
|
|
? (balance.OffchainBalance.Opening ?? 0) + (balance.OffchainBalance.Local ?? 0) +
|
|
|
|
(balance.OffchainBalance.Closing ?? 0)
|
2022-07-04 04:03:16 +02:00
|
|
|
: null;
|
2024-11-05 13:40:37 +01:00
|
|
|
|
|
|
|
// histogram
|
|
|
|
var data = await _lnHistogramService.GetHistogram(lightningClient, DefaultType, cts.Token);
|
|
|
|
if (data != null)
|
|
|
|
{
|
|
|
|
vm.Type = data.Type;
|
|
|
|
vm.Series = data.Series;
|
|
|
|
vm.Labels = data.Labels;
|
|
|
|
}
|
2022-06-14 07:36:22 +02:00
|
|
|
}
|
2024-01-06 08:46:19 +01:00
|
|
|
catch (Exception ex) when (ex is NotImplementedException or NotSupportedException)
|
2022-06-14 07:36:22 +02:00
|
|
|
{
|
2022-07-04 04:03:16 +02:00
|
|
|
// not all implementations support balance fetching
|
|
|
|
vm.ProblemDescription = "Your node does not support balance fetching.";
|
|
|
|
}
|
|
|
|
catch
|
|
|
|
{
|
|
|
|
// general error
|
|
|
|
vm.ProblemDescription = "Could not fetch Lightning balance.";
|
2022-06-14 07:36:22 +02:00
|
|
|
}
|
|
|
|
return View(vm);
|
|
|
|
}
|
2023-01-06 14:18:07 +01:00
|
|
|
|
2024-11-05 13:40:37 +01:00
|
|
|
private async Task<ILightningClient> GetLightningClient(StoreData store, string cryptoCode)
|
2022-06-14 07:36:22 +02:00
|
|
|
{
|
2022-07-06 05:40:16 +02:00
|
|
|
var network = _networkProvider.GetNetwork<BTCPayNetwork>(cryptoCode);
|
2024-04-04 09:31:04 +02:00
|
|
|
var id = PaymentTypes.LN.GetPaymentMethodId(cryptoCode);
|
|
|
|
var existing = store.GetPaymentMethodConfig<LightningPaymentMethodConfig>(id, _handlers);
|
2023-01-06 14:18:07 +01:00
|
|
|
if (existing == null)
|
|
|
|
return null;
|
|
|
|
|
|
|
|
if (existing.GetExternalLightningUrl() is { } connectionString)
|
2022-06-14 07:36:22 +02:00
|
|
|
{
|
|
|
|
return _lightningClientFactory.Create(connectionString, network);
|
|
|
|
}
|
2022-07-06 05:40:16 +02:00
|
|
|
if (existing.IsInternalNode && _lightningNetworkOptions.Value.InternalLightningByCryptoCode.TryGetValue(cryptoCode, out var internalLightningNode))
|
2022-06-14 07:36:22 +02:00
|
|
|
{
|
2024-01-06 08:46:19 +01:00
|
|
|
var result = await _authorizationService.AuthorizeAsync(HttpContext.User, null,
|
|
|
|
new PolicyRequirement(Policies.CanUseInternalLightningNode));
|
|
|
|
return result.Succeeded ? internalLightningNode : null;
|
2022-06-14 07:36:22 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
}
|