mirror of
https://github.com/btcpayserver/btcpayserver.git
synced 2025-02-22 14:22:40 +01:00
Greenfield: Add lightning histogram
This commit is contained in:
parent
380f9d5ec5
commit
e6afc487df
13 changed files with 176 additions and 37 deletions
|
@ -21,6 +21,13 @@ public partial class BTCPayServerClient
|
||||||
return await SendHttpRequest<LightningNodeBalanceData>($"api/v1/server/lightning/{cryptoCode}/balance", null, HttpMethod.Get, token);
|
return await SendHttpRequest<LightningNodeBalanceData>($"api/v1/server/lightning/{cryptoCode}/balance", null, HttpMethod.Get, token);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public virtual async Task<HistogramData> GetLightningNodeHistogram(string cryptoCode, HistogramType? type = null,
|
||||||
|
CancellationToken token = default)
|
||||||
|
{
|
||||||
|
var queryPayload = type == null ? null : new Dictionary<string, string> { ["type"] = type.ToString() };
|
||||||
|
return await SendHttpRequest<HistogramData>($"api/v1/server/lightning/{cryptoCode}/histogram", queryPayload, HttpMethod.Get, token);
|
||||||
|
}
|
||||||
|
|
||||||
public virtual async Task ConnectToLightningNode(string cryptoCode, ConnectToNodeRequest request,
|
public virtual async Task ConnectToLightningNode(string cryptoCode, ConnectToNodeRequest request,
|
||||||
CancellationToken token = default)
|
CancellationToken token = default)
|
||||||
{
|
{
|
||||||
|
|
|
@ -21,6 +21,13 @@ public partial class BTCPayServerClient
|
||||||
return await SendHttpRequest<LightningNodeBalanceData>($"api/v1/stores/{storeId}/lightning/{cryptoCode}/balance", null, HttpMethod.Get, token);
|
return await SendHttpRequest<LightningNodeBalanceData>($"api/v1/stores/{storeId}/lightning/{cryptoCode}/balance", null, HttpMethod.Get, token);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public virtual async Task<HistogramData> GetLightningNodeHistogram(string storeId, string cryptoCode, HistogramType? type = null,
|
||||||
|
CancellationToken token = default)
|
||||||
|
{
|
||||||
|
var queryPayload = type == null ? null : new Dictionary<string, string> { ["type"] = type.ToString() };
|
||||||
|
return await SendHttpRequest<HistogramData>($"api/v1/stores/{storeId}/lightning/{cryptoCode}/histogram", queryPayload, HttpMethod.Get, token);
|
||||||
|
}
|
||||||
|
|
||||||
public virtual async Task ConnectToLightningNode(string storeId, string cryptoCode, ConnectToNodeRequest request,
|
public virtual async Task ConnectToLightningNode(string storeId, string cryptoCode, ConnectToNodeRequest request,
|
||||||
CancellationToken token = default)
|
CancellationToken token = default)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using NBitcoin;
|
using BTCPayServer.JsonConverters;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Converters;
|
using Newtonsoft.Json.Converters;
|
||||||
|
|
||||||
|
@ -19,6 +19,6 @@ public class HistogramData
|
||||||
public HistogramType Type { get; set; }
|
public HistogramType Type { get; set; }
|
||||||
public List<decimal> Series { get; set; }
|
public List<decimal> Series { get; set; }
|
||||||
public List<DateTimeOffset> Labels { get; set; }
|
public List<DateTimeOffset> Labels { get; set; }
|
||||||
[JsonConverter(typeof(JsonConverters.MoneyJsonConverter))]
|
[JsonConverter(typeof(NumericStringJsonConverter))]
|
||||||
public Money Balance { get; set; }
|
public decimal Balance { get; set; }
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,23 +1,13 @@
|
||||||
#nullable enable
|
#nullable enable
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Data.Common;
|
|
||||||
using System.Globalization;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using BTCPayServer.Data;
|
using BTCPayServer.Data;
|
||||||
using BTCPayServer.Services;
|
|
||||||
using BTCPayServer.Services.Invoices;
|
using BTCPayServer.Services.Invoices;
|
||||||
using BTCPayServer.Services.Rates;
|
using BTCPayServer.Services.Rates;
|
||||||
using BTCPayServer.Services.Stores;
|
using BTCPayServer.Services.Stores;
|
||||||
using BTCPayServer.Services.Wallets;
|
using BTCPayServer.Services.Wallets;
|
||||||
using Dapper;
|
|
||||||
using Microsoft.AspNetCore.Identity;
|
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using NBitcoin;
|
|
||||||
using NBXplorer;
|
|
||||||
using NBXplorer.Client;
|
|
||||||
|
|
||||||
namespace BTCPayServer.Components.StoreWalletBalance;
|
namespace BTCPayServer.Components.StoreWalletBalance;
|
||||||
|
|
||||||
|
|
|
@ -1,14 +1,10 @@
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using BTCPayApp.CommonServer;
|
using BTCPayApp.CommonServer;
|
||||||
using BTCPayServer.Abstractions.Constants;
|
|
||||||
using BTCPayServer.Abstractions.Contracts;
|
|
||||||
using BTCPayServer.Client;
|
using BTCPayServer.Client;
|
||||||
using BTCPayServer.Client.Models;
|
using BTCPayServer.Client.Models;
|
||||||
using BTCPayServer.Configuration;
|
using BTCPayServer.Configuration;
|
||||||
using BTCPayServer.HostedServices;
|
|
||||||
using BTCPayServer.Lightning;
|
using BTCPayServer.Lightning;
|
||||||
using BTCPayServer.Security;
|
|
||||||
using BTCPayServer.Services;
|
using BTCPayServer.Services;
|
||||||
using BTCPayServer.Services.Invoices;
|
using BTCPayServer.Services.Invoices;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
|
@ -32,8 +28,9 @@ namespace BTCPayServer.Controllers.Greenfield
|
||||||
PoliciesSettings policiesSettings, LightningClientFactoryService lightningClientFactory,
|
PoliciesSettings policiesSettings, LightningClientFactoryService lightningClientFactory,
|
||||||
IOptions<LightningNetworkOptions> lightningNetworkOptions,
|
IOptions<LightningNetworkOptions> lightningNetworkOptions,
|
||||||
IAuthorizationService authorizationService,
|
IAuthorizationService authorizationService,
|
||||||
PaymentMethodHandlerDictionary handlers
|
PaymentMethodHandlerDictionary handlers,
|
||||||
) : base(policiesSettings, authorizationService, handlers)
|
LightningHistogramService lnHistogramService
|
||||||
|
) : base(policiesSettings, authorizationService, handlers, lnHistogramService)
|
||||||
{
|
{
|
||||||
_lightningClientFactory = lightningClientFactory;
|
_lightningClientFactory = lightningClientFactory;
|
||||||
_lightningNetworkOptions = lightningNetworkOptions;
|
_lightningNetworkOptions = lightningNetworkOptions;
|
||||||
|
@ -56,6 +53,14 @@ namespace BTCPayServer.Controllers.Greenfield
|
||||||
return base.GetBalance(cryptoCode, cancellationToken);
|
return base.GetBalance(cryptoCode, cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Authorize(Policy = Policies.CanUseInternalLightningNode,
|
||||||
|
AuthenticationSchemes = AuthenticationSchemes.Greenfield)]
|
||||||
|
[HttpGet("~/api/v1/server/lightning/{cryptoCode}/histogram")]
|
||||||
|
public override Task<IActionResult> GetHistogram(string cryptoCode, [FromQuery] HistogramType? type = null, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
return base.GetHistogram(cryptoCode, type, cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
[Authorize(Policy = Policies.CanUseInternalLightningNode,
|
[Authorize(Policy = Policies.CanUseInternalLightningNode,
|
||||||
AuthenticationSchemes = AuthenticationSchemes.Greenfield)]
|
AuthenticationSchemes = AuthenticationSchemes.Greenfield)]
|
||||||
[HttpPost("~/api/v1/server/lightning/{cryptoCode}/connect")]
|
[HttpPost("~/api/v1/server/lightning/{cryptoCode}/connect")]
|
||||||
|
|
|
@ -1,9 +1,6 @@
|
||||||
using System.Linq;
|
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using BTCPayApp.CommonServer;
|
using BTCPayApp.CommonServer;
|
||||||
using BTCPayServer.Abstractions.Constants;
|
|
||||||
using BTCPayServer.Abstractions.Contracts;
|
|
||||||
using BTCPayServer.Abstractions.Extensions;
|
using BTCPayServer.Abstractions.Extensions;
|
||||||
using BTCPayServer.Client;
|
using BTCPayServer.Client;
|
||||||
using BTCPayServer.Client.Models;
|
using BTCPayServer.Client.Models;
|
||||||
|
@ -35,7 +32,8 @@ namespace BTCPayServer.Controllers.Greenfield
|
||||||
IOptions<LightningNetworkOptions> lightningNetworkOptions,
|
IOptions<LightningNetworkOptions> lightningNetworkOptions,
|
||||||
LightningClientFactoryService lightningClientFactory, PaymentMethodHandlerDictionary handlers,
|
LightningClientFactoryService lightningClientFactory, PaymentMethodHandlerDictionary handlers,
|
||||||
PoliciesSettings policiesSettings,
|
PoliciesSettings policiesSettings,
|
||||||
IAuthorizationService authorizationService) : base(policiesSettings, authorizationService, handlers)
|
IAuthorizationService authorizationService,
|
||||||
|
LightningHistogramService lnHistogramService) : base(policiesSettings, authorizationService, handlers, lnHistogramService)
|
||||||
{
|
{
|
||||||
_lightningNetworkOptions = lightningNetworkOptions;
|
_lightningNetworkOptions = lightningNetworkOptions;
|
||||||
_lightningClientFactory = lightningClientFactory;
|
_lightningClientFactory = lightningClientFactory;
|
||||||
|
@ -58,6 +56,13 @@ namespace BTCPayServer.Controllers.Greenfield
|
||||||
return base.GetBalance(cryptoCode, cancellationToken);
|
return base.GetBalance(cryptoCode, cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Authorize(Policy = Policies.CanUseLightningNodeInStore, AuthenticationSchemes = AuthenticationSchemes.Greenfield)]
|
||||||
|
[HttpGet("~/api/v1/stores/{storeId}/lightning/{cryptoCode}/histogram")]
|
||||||
|
public override Task<IActionResult> GetHistogram(string cryptoCode, [FromQuery] HistogramType? type = null, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
return base.GetHistogram(cryptoCode, type, cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
[Authorize(Policy = Policies.CanUseLightningNodeInStore,
|
[Authorize(Policy = Policies.CanUseLightningNodeInStore,
|
||||||
AuthenticationSchemes = AuthenticationSchemes.Greenfield)]
|
AuthenticationSchemes = AuthenticationSchemes.Greenfield)]
|
||||||
[HttpPost("~/api/v1/stores/{storeId}/lightning/{cryptoCode}/connect")]
|
[HttpPost("~/api/v1/stores/{storeId}/lightning/{cryptoCode}/connect")]
|
||||||
|
@ -65,6 +70,7 @@ namespace BTCPayServer.Controllers.Greenfield
|
||||||
{
|
{
|
||||||
return base.ConnectToNode(cryptoCode, request, cancellationToken);
|
return base.ConnectToNode(cryptoCode, request, cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Authorize(Policy = Policies.CanUseLightningNodeInStore,
|
[Authorize(Policy = Policies.CanUseLightningNodeInStore,
|
||||||
AuthenticationSchemes = AuthenticationSchemes.Greenfield)]
|
AuthenticationSchemes = AuthenticationSchemes.Greenfield)]
|
||||||
[HttpGet("~/api/v1/stores/{storeId}/lightning/{cryptoCode}/channels")]
|
[HttpGet("~/api/v1/stores/{storeId}/lightning/{cryptoCode}/channels")]
|
||||||
|
@ -72,6 +78,7 @@ namespace BTCPayServer.Controllers.Greenfield
|
||||||
{
|
{
|
||||||
return base.GetChannels(cryptoCode, cancellationToken);
|
return base.GetChannels(cryptoCode, cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Authorize(Policy = Policies.CanUseLightningNodeInStore,
|
[Authorize(Policy = Policies.CanUseLightningNodeInStore,
|
||||||
AuthenticationSchemes = AuthenticationSchemes.Greenfield)]
|
AuthenticationSchemes = AuthenticationSchemes.Greenfield)]
|
||||||
[HttpPost("~/api/v1/stores/{storeId}/lightning/{cryptoCode}/channels")]
|
[HttpPost("~/api/v1/stores/{storeId}/lightning/{cryptoCode}/channels")]
|
||||||
|
|
|
@ -9,12 +9,13 @@ using BTCPayServer.Client.Models;
|
||||||
using BTCPayServer.Lightning;
|
using BTCPayServer.Lightning;
|
||||||
using BTCPayServer.Payments;
|
using BTCPayServer.Payments;
|
||||||
using BTCPayServer.Payments.Bitcoin;
|
using BTCPayServer.Payments.Bitcoin;
|
||||||
using BTCPayServer.Security;
|
|
||||||
using BTCPayServer.Services;
|
using BTCPayServer.Services;
|
||||||
using BTCPayServer.Services.Invoices;
|
using BTCPayServer.Services.Invoices;
|
||||||
|
using BTCPayServer.Services.Wallets;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.AspNetCore.Mvc.Filters;
|
using Microsoft.AspNetCore.Mvc.Filters;
|
||||||
|
using NBitcoin;
|
||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
|
|
||||||
namespace BTCPayServer.Controllers.Greenfield
|
namespace BTCPayServer.Controllers.Greenfield
|
||||||
|
@ -33,15 +34,18 @@ namespace BTCPayServer.Controllers.Greenfield
|
||||||
private readonly PoliciesSettings _policiesSettings;
|
private readonly PoliciesSettings _policiesSettings;
|
||||||
private readonly IAuthorizationService _authorizationService;
|
private readonly IAuthorizationService _authorizationService;
|
||||||
private readonly PaymentMethodHandlerDictionary _handlers;
|
private readonly PaymentMethodHandlerDictionary _handlers;
|
||||||
|
private readonly LightningHistogramService _lnHistogramService;
|
||||||
|
|
||||||
protected GreenfieldLightningNodeApiController(
|
protected GreenfieldLightningNodeApiController(
|
||||||
PoliciesSettings policiesSettings,
|
PoliciesSettings policiesSettings,
|
||||||
IAuthorizationService authorizationService,
|
IAuthorizationService authorizationService,
|
||||||
PaymentMethodHandlerDictionary handlers)
|
PaymentMethodHandlerDictionary handlers,
|
||||||
|
LightningHistogramService lnHistogramService)
|
||||||
{
|
{
|
||||||
_policiesSettings = policiesSettings;
|
_policiesSettings = policiesSettings;
|
||||||
_authorizationService = authorizationService;
|
_authorizationService = authorizationService;
|
||||||
_handlers = handlers;
|
_handlers = handlers;
|
||||||
|
_lnHistogramService = lnHistogramService;
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual async Task<IActionResult> GetInfo(string cryptoCode, CancellationToken cancellationToken = default)
|
public virtual async Task<IActionResult> GetInfo(string cryptoCode, CancellationToken cancellationToken = default)
|
||||||
|
@ -88,6 +92,22 @@ namespace BTCPayServer.Controllers.Greenfield
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public virtual async Task<IActionResult> GetHistogram(string cryptoCode, HistogramType? type = null, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
Enum.TryParse<WalletHistogramType>(type.ToString(), true, out var histType);
|
||||||
|
var lightningClient = await GetLightningClient(cryptoCode, true);
|
||||||
|
var data = await _lnHistogramService.GetHistogram(lightningClient, histType, cancellationToken);
|
||||||
|
if (data == null) return this.CreateAPIError(404, "histogram-not-found", "The lightning histogram was not found.");
|
||||||
|
|
||||||
|
return Ok(new HistogramData
|
||||||
|
{
|
||||||
|
Type = Enum.Parse<HistogramType>(data.Type.ToString(), true),
|
||||||
|
Balance = data.Balance,
|
||||||
|
Series = data.Series,
|
||||||
|
Labels = data.Labels
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
public virtual async Task<IActionResult> ConnectToNode(string cryptoCode, ConnectToNodeRequest request, CancellationToken cancellationToken = default)
|
public virtual async Task<IActionResult> ConnectToNode(string cryptoCode, ConnectToNodeRequest request, CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
var lightningClient = await GetLightningClient(cryptoCode, true);
|
var lightningClient = await GetLightningClient(cryptoCode, true);
|
||||||
|
|
|
@ -116,7 +116,7 @@ namespace BTCPayServer.Controllers.Greenfield
|
||||||
|
|
||||||
[Authorize(Policy = Policies.CanModifyStoreSettings, AuthenticationSchemes = AuthenticationSchemes.Greenfield)]
|
[Authorize(Policy = Policies.CanModifyStoreSettings, AuthenticationSchemes = AuthenticationSchemes.Greenfield)]
|
||||||
[HttpGet("~/api/v1/stores/{storeId}/payment-methods/onchain/{cryptoCode}/histogram")]
|
[HttpGet("~/api/v1/stores/{storeId}/payment-methods/onchain/{cryptoCode}/histogram")]
|
||||||
public async Task<IActionResult> GetOnChainWalletHistogram(string storeId, string cryptoCode, [FromQuery] string type)
|
public async Task<IActionResult> GetOnChainWalletHistogram(string storeId, string cryptoCode, [FromQuery] string? type = null)
|
||||||
{
|
{
|
||||||
if (IsInvalidWalletRequest(cryptoCode, out _, out _, out var actionResult))
|
if (IsInvalidWalletRequest(cryptoCode, out _, out _, out var actionResult))
|
||||||
return actionResult;
|
return actionResult;
|
||||||
|
@ -124,8 +124,15 @@ namespace BTCPayServer.Controllers.Greenfield
|
||||||
var walletId = new WalletId(storeId, cryptoCode);
|
var walletId = new WalletId(storeId, cryptoCode);
|
||||||
Enum.TryParse<WalletHistogramType>(type, true, out var histType);
|
Enum.TryParse<WalletHistogramType>(type, true, out var histType);
|
||||||
var data = await _walletHistogramService.GetHistogram(Store, walletId, histType);
|
var data = await _walletHistogramService.GetHistogram(Store, walletId, histType);
|
||||||
|
if (data == null) return this.CreateAPIError(404, "histogram-not-found", "The wallet histogram was not found.");
|
||||||
|
|
||||||
return Ok(data);
|
return Ok(new HistogramData
|
||||||
|
{
|
||||||
|
Type = Enum.Parse<HistogramType>(data.Type.ToString(), true),
|
||||||
|
Balance = data.Balance,
|
||||||
|
Series = data.Series,
|
||||||
|
Labels = data.Labels
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
[Authorize(Policy = Policies.CanViewStoreSettings, AuthenticationSchemes = AuthenticationSchemes.Greenfield)]
|
[Authorize(Policy = Policies.CanViewStoreSettings, AuthenticationSchemes = AuthenticationSchemes.Greenfield)]
|
||||||
|
|
|
@ -13,7 +13,6 @@ using BTCPayServer.Client;
|
||||||
using BTCPayServer.Client.Models;
|
using BTCPayServer.Client.Models;
|
||||||
using BTCPayServer.Controllers.GreenField;
|
using BTCPayServer.Controllers.GreenField;
|
||||||
using BTCPayServer.Data;
|
using BTCPayServer.Data;
|
||||||
using BTCPayServer.Security;
|
|
||||||
using BTCPayServer.Security.Greenfield;
|
using BTCPayServer.Security.Greenfield;
|
||||||
using BTCPayServer.Services.Mails;
|
using BTCPayServer.Services.Mails;
|
||||||
using BTCPayServer.Services.Stores;
|
using BTCPayServer.Services.Stores;
|
||||||
|
@ -21,7 +20,6 @@ using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.AspNetCore.Identity;
|
using Microsoft.AspNetCore.Identity;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.AspNetCore.StaticFiles;
|
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Microsoft.Extensions.Options;
|
using Microsoft.Extensions.Options;
|
||||||
using NBitcoin;
|
using NBitcoin;
|
||||||
|
@ -385,6 +383,13 @@ namespace BTCPayServer.Controllers.Greenfield
|
||||||
await GetController<GreenfieldStoreLightningNodeApiController>().GetBalance(cryptoCode, token));
|
await GetController<GreenfieldStoreLightningNodeApiController>().GetBalance(cryptoCode, token));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override async Task<HistogramData> GetLightningNodeHistogram(string storeId, string cryptoCode, HistogramType? type = null,
|
||||||
|
CancellationToken token = default)
|
||||||
|
{
|
||||||
|
return GetFromActionResult<HistogramData>(
|
||||||
|
await GetController<GreenfieldStoreLightningNodeApiController>().GetHistogram(cryptoCode, type, token));
|
||||||
|
}
|
||||||
|
|
||||||
public override async Task ConnectToLightningNode(string storeId, string cryptoCode,
|
public override async Task ConnectToLightningNode(string storeId, string cryptoCode,
|
||||||
ConnectToNodeRequest request, CancellationToken token = default)
|
ConnectToNodeRequest request, CancellationToken token = default)
|
||||||
{
|
{
|
||||||
|
@ -461,6 +466,13 @@ namespace BTCPayServer.Controllers.Greenfield
|
||||||
await GetController<GreenfieldInternalLightningNodeApiController>().GetBalance(cryptoCode));
|
await GetController<GreenfieldInternalLightningNodeApiController>().GetBalance(cryptoCode));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override async Task<HistogramData> GetLightningNodeHistogram(string cryptoCode, HistogramType? type = null,
|
||||||
|
CancellationToken token = default)
|
||||||
|
{
|
||||||
|
return GetFromActionResult<HistogramData>(
|
||||||
|
await GetController<GreenfieldInternalLightningNodeApiController>().GetHistogram(cryptoCode, type, token));
|
||||||
|
}
|
||||||
|
|
||||||
public override async Task ConnectToLightningNode(string cryptoCode, ConnectToNodeRequest request,
|
public override async Task ConnectToLightningNode(string cryptoCode, ConnectToNodeRequest request,
|
||||||
CancellationToken token = default)
|
CancellationToken token = default)
|
||||||
{
|
{
|
||||||
|
@ -703,10 +715,10 @@ namespace BTCPayServer.Controllers.Greenfield
|
||||||
await GetController<GreenfieldStoreOnChainWalletsController>().ShowOnChainWalletOverview(storeId, cryptoCode));
|
await GetController<GreenfieldStoreOnChainWalletsController>().ShowOnChainWalletOverview(storeId, cryptoCode));
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async Task<HistogramData> GetOnChainWalletHistogram(string storeId, string cryptoCode, string type, CancellationToken token = default)
|
public override async Task<HistogramData> GetOnChainWalletHistogram(string storeId, string cryptoCode, HistogramType? type = null, CancellationToken token = default)
|
||||||
{
|
{
|
||||||
return GetFromActionResult<HistogramData>(
|
return GetFromActionResult<HistogramData>(
|
||||||
await GetController<GreenfieldStoreOnChainWalletsController>().GetOnChainWalletHistogram(storeId, cryptoCode, type));
|
await GetController<GreenfieldStoreOnChainWalletsController>().GetOnChainWalletHistogram(storeId, cryptoCode, type?.ToString()));
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async Task<OnChainWalletAddressData> GetOnChainWalletReceiveAddress(string storeId,
|
public override async Task<OnChainWalletAddressData> GetOnChainWalletReceiveAddress(string storeId,
|
||||||
|
|
|
@ -46,6 +46,7 @@ using NBXplorer.Models;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
using StoreData = BTCPayServer.Data.StoreData;
|
using StoreData = BTCPayServer.Data.StoreData;
|
||||||
|
using WalletHistogramType = BTCPayServer.Services.Wallets.WalletHistogramType;
|
||||||
|
|
||||||
namespace BTCPayServer.Controllers
|
namespace BTCPayServer.Controllers
|
||||||
{
|
{
|
||||||
|
@ -314,10 +315,6 @@ namespace BTCPayServer.Controllers
|
||||||
var data = await _walletHistogramService.GetHistogram(store, walletId, type);
|
var data = await _walletHistogramService.GetHistogram(store, walletId, type);
|
||||||
if (data == null) return NotFound();
|
if (data == null) return NotFound();
|
||||||
|
|
||||||
const int labelCount = 6;
|
|
||||||
var pointCount = data.Series.Count;
|
|
||||||
var labelEvery = pointCount / labelCount;
|
|
||||||
|
|
||||||
return Json(data);
|
return Json(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -182,6 +182,7 @@ namespace BTCPayServer.Hosting
|
||||||
services.TryAddSingleton<UserService>();
|
services.TryAddSingleton<UserService>();
|
||||||
services.TryAddSingleton<UriResolver>();
|
services.TryAddSingleton<UriResolver>();
|
||||||
services.TryAddSingleton<WalletHistogramService>();
|
services.TryAddSingleton<WalletHistogramService>();
|
||||||
|
services.TryAddSingleton<LightningHistogramService>();
|
||||||
services.AddSingleton<ApplicationDbContextFactory>();
|
services.AddSingleton<ApplicationDbContextFactory>();
|
||||||
services.AddOptions<BTCPayServerOptions>().Configure(
|
services.AddOptions<BTCPayServerOptions>().Configure(
|
||||||
(options) =>
|
(options) =>
|
||||||
|
|
88
BTCPayServer/Services/LightningHistogramService.cs
Normal file
88
BTCPayServer/Services/LightningHistogramService.cs
Normal file
|
@ -0,0 +1,88 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using BTCPayServer.Lightning;
|
||||||
|
using BTCPayServer.Services.Wallets;
|
||||||
|
|
||||||
|
namespace BTCPayServer.Services;
|
||||||
|
|
||||||
|
public class LightningHistogramService
|
||||||
|
{
|
||||||
|
public async Task<WalletHistogramData> GetHistogram(ILightningClient lightningClient, WalletHistogramType type, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
var (days, pointCount) = type switch
|
||||||
|
{
|
||||||
|
WalletHistogramType.Week => (7, 30),
|
||||||
|
WalletHistogramType.Month => (30, 30),
|
||||||
|
WalletHistogramType.Year => (365, 30),
|
||||||
|
_ => throw new ArgumentException($"WalletHistogramType {type} does not exist.")
|
||||||
|
};
|
||||||
|
var to = DateTimeOffset.UtcNow;
|
||||||
|
var from = to - TimeSpan.FromDays(days);
|
||||||
|
var ticks = (to - from).Ticks;
|
||||||
|
var interval = TimeSpan.FromTicks(ticks / pointCount);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// general balance
|
||||||
|
var lnBalance = await lightningClient.GetBalance(cancellationToken);
|
||||||
|
/*var totalOnchain = lnBalance.OnchainBalance != null
|
||||||
|
? (lnBalance.OnchainBalance.Confirmed ?? 0L) + (lnBalance.OnchainBalance.Reserved ?? 0L) +
|
||||||
|
(lnBalance.OnchainBalance.Unconfirmed ?? 0L)
|
||||||
|
: new Money(0L);
|
||||||
|
var totalOffchain = lnBalance.OffchainBalance != null
|
||||||
|
? (lnBalance.OffchainBalance.Opening ?? 0) + (lnBalance.OffchainBalance.Local ?? 0) +
|
||||||
|
(lnBalance.OffchainBalance.Closing ?? 0)
|
||||||
|
: null;*/
|
||||||
|
var total = lnBalance.OffchainBalance.Local;//(totalOnchain + new Money(totalOffchain?.ToDecimal(LightMoneyUnit.Satoshi) ?? 0, MoneyUnit.Satoshi)).ToDecimal(MoneyUnit.Satoshi);
|
||||||
|
var totalBtc = total.ToDecimal(LightMoneyUnit.BTC);
|
||||||
|
// prepare transaction data
|
||||||
|
var lnInvoices = await lightningClient.ListInvoices(cancellationToken);
|
||||||
|
var lnPayments = await lightningClient.ListPayments(cancellationToken);
|
||||||
|
var lnTransactions = lnInvoices
|
||||||
|
.Where(inv => inv.Status == LightningInvoiceStatus.Paid && inv.PaidAt >= from)
|
||||||
|
.Select(inv => new LnTx { Amount = inv.Amount.ToDecimal(LightMoneyUnit.BTC), Settled = inv.PaidAt.GetValueOrDefault() })
|
||||||
|
.Concat(lnPayments
|
||||||
|
.Where(pay => pay.Status == LightningPaymentStatus.Complete && pay.CreatedAt >= from)
|
||||||
|
.Select(pay => new LnTx { Amount = pay.Amount.ToDecimal(LightMoneyUnit.BTC) * -1, Settled = pay.CreatedAt.GetValueOrDefault() }))
|
||||||
|
.OrderByDescending(tx => tx.Settled)
|
||||||
|
.ToList();
|
||||||
|
// assemble graph data going backwards
|
||||||
|
var series = new List<decimal>(pointCount);
|
||||||
|
var labels = new List<DateTimeOffset>(pointCount);
|
||||||
|
var balance = totalBtc;
|
||||||
|
for (var i = pointCount; i > 0; i--)
|
||||||
|
{
|
||||||
|
var txs = lnTransactions.Where(t =>
|
||||||
|
t.Settled.Ticks >= from.Ticks + interval.Ticks * i &&
|
||||||
|
t.Settled.Ticks < from.Ticks + interval.Ticks * (i + 1));
|
||||||
|
var sum = txs.Sum(tx => tx.Amount);
|
||||||
|
balance -= sum;
|
||||||
|
series.Add(balance);
|
||||||
|
labels.Add(from + interval * i);
|
||||||
|
}
|
||||||
|
// reverse the lists
|
||||||
|
series.Reverse();
|
||||||
|
labels.Reverse();
|
||||||
|
return new WalletHistogramData
|
||||||
|
{
|
||||||
|
Type = type,
|
||||||
|
Balance = totalBtc,
|
||||||
|
Series = series,
|
||||||
|
Labels = labels
|
||||||
|
};
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class LnTx
|
||||||
|
{
|
||||||
|
public DateTimeOffset Settled { get; set; }
|
||||||
|
public decimal Amount { get; set; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,8 +1,6 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Globalization;
|
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using BTCPayServer.Client.JsonConverters;
|
|
||||||
using BTCPayServer.Data;
|
using BTCPayServer.Data;
|
||||||
using BTCPayServer.Services.Invoices;
|
using BTCPayServer.Services.Invoices;
|
||||||
using Dapper;
|
using Dapper;
|
||||||
|
|
Loading…
Add table
Reference in a new issue