btcpayserver/BTCPayServer/Services/Wallets/WalletHistogramService.cs
d11n d5d0be5824
Code formatting updates (#4502)
* Editorconfig: Add space_before_self_closing setting

This was a difference between the way dotnet-format and Rider format code. See https://www.jetbrains.com/help/rider/EditorConfig_Index.html

* Editorconfig: Keep 4 spaces indentation for Swagger JSON files

They are all formatted that way, let's keep it like that.

* Apply dotnet-format, mostly white-space related changes
2023-01-06 22:18:07 +09:00

93 lines
3.4 KiB
C#

using System;
using System.Collections.Generic;
using System.Globalization;
using System.Threading.Tasks;
using BTCPayServer.Client.JsonConverters;
using BTCPayServer.Data;
using Dapper;
namespace BTCPayServer.Services.Wallets;
public enum WalletHistogramType
{
Week,
Month,
Year
}
public class WalletHistogramService
{
private readonly BTCPayNetworkProvider _networkProvider;
private readonly NBXplorerConnectionFactory _connectionFactory;
public WalletHistogramService(
BTCPayNetworkProvider networkProvider,
NBXplorerConnectionFactory connectionFactory)
{
_networkProvider = networkProvider;
_connectionFactory = connectionFactory;
}
public async Task<WalletHistogramData> GetHistogram(StoreData store, WalletId walletId, WalletHistogramType type)
{
// https://github.com/dgarage/NBXplorer/blob/master/docs/Postgres-Schema.md
if (_connectionFactory.Available)
{
var derivationSettings = store.GetDerivationSchemeSettings(_networkProvider, walletId.CryptoCode);
if (derivationSettings != null)
{
var wallet_id = derivationSettings.GetNBXWalletId();
await using var conn = await _connectionFactory.OpenConnection();
var code = walletId.CryptoCode;
var to = DateTimeOffset.UtcNow;
var labelCount = 6;
(var days, var pointCount) = type switch
{
WalletHistogramType.Week => (7, 30),
WalletHistogramType.Month => (30, 30),
WalletHistogramType.Year => (365, 30),
_ => throw new ArgumentException($"WalletHistogramType {type} does not exist.")
};
var from = to - TimeSpan.FromDays(days);
var interval = TimeSpan.FromTicks((to - from).Ticks / pointCount);
var balance = await conn.ExecuteScalarAsync<decimal>(
"SELECT to_btc(available_balance) FROM wallets_balances WHERE wallet_id=@wallet_id AND code=@code AND asset_id=''",
new { code, wallet_id });
var rows = await conn.QueryAsync("SELECT date, to_btc(balance) balance FROM get_wallets_histogram(@wallet_id, @code, '', @from, @to, @interval)",
new { code, wallet_id, from, to, interval });
var data = rows.AsList();
var series = new List<decimal>(pointCount);
var labels = new List<string>(labelCount);
var labelEvery = pointCount / labelCount;
for (int i = 0; i < data.Count; i++)
{
var r = data[i];
series.Add((decimal)r.balance);
labels.Add((i % labelEvery == 0)
? ((DateTime)r.date).ToString("MMM dd", CultureInfo.InvariantCulture)
: null);
}
series[^1] = balance;
return new WalletHistogramData
{
Series = series,
Labels = labels,
Balance = balance,
Type = type
};
}
}
return null;
}
}
public class WalletHistogramData
{
public WalletHistogramType Type { get; set; }
public List<decimal> Series { get; set; }
public List<string> Labels { get; set; }
public decimal Balance { get; set; }
}