* Add dashboard and chart basics

* More widgets

* Make widgets responsive

* Layout dashboard

* Prepare ExplorerClient

* Switch to Chartist

* Dynamic data for store numbers and recent transactions tiles

* Dynamic data for recent invoices tile

* Improvements

* Plug NBXPlorer DB

* Properly filter by code

* Reorder cheat mode button

* AJAX update for graph data

* Fix create invoice button

* Retry connection on transient issues

* App Top Items stats

* Design updates

* App Sales stats

* Add points for weekly histogram, set last point to current balance

Co-authored-by: nicolas.dorier <nicolas.dorier@gmail.com>
This commit is contained in:
d11n
2022-04-12 09:55:10 +02:00
committed by GitHub
parent d58803a058
commit 7ec978fcdb
41 changed files with 2037 additions and 115 deletions

View File

@@ -22,11 +22,14 @@ using BTCPayServer.Services.Labels;
using BTCPayServer.Services.Rates;
using BTCPayServer.Services.Stores;
using BTCPayServer.Services.Wallets;
using Dapper;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.DependencyInjection;
using NBitcoin;
using NBXplorer;
using NBXplorer.Client;
using NBXplorer.DerivationStrategy;
using NBXplorer.Models;
using Newtonsoft.Json;
@@ -43,7 +46,7 @@ namespace BTCPayServer.Controllers
private WalletRepository WalletRepository { get; }
private BTCPayNetworkProvider NetworkProvider { get; }
private ExplorerClientProvider ExplorerClientProvider { get; }
public IServiceProvider ServiceProvider { get; }
public RateFetcher RateFetcher { get; }
private readonly UserManager<ApplicationUser> _userManager;
@@ -62,6 +65,8 @@ namespace BTCPayServer.Controllers
private readonly BTCPayNetworkJsonSerializerSettings _jsonSerializerSettings;
private readonly PullPaymentHostedService _pullPaymentService;
private readonly IEnumerable<IPayoutHandler> _payoutHandlers;
private readonly NBXplorerConnectionFactory _connectionFactory;
private readonly WalletHistogramService _walletHistogramService;
readonly CurrencyNameTable _currencyTable;
public UIWalletsController(StoreRepository repo,
@@ -71,6 +76,8 @@ namespace BTCPayServer.Controllers
UserManager<ApplicationUser> userManager,
MvcNewtonsoftJsonOptions mvcJsonOptions,
NBXplorerDashboard dashboard,
WalletHistogramService walletHistogramService,
NBXplorerConnectionFactory connectionFactory,
RateFetcher rateProvider,
IAuthorizationService authorizationService,
ExplorerClientProvider explorerProvider,
@@ -85,7 +92,8 @@ namespace BTCPayServer.Controllers
ApplicationDbContextFactory dbContextFactory,
BTCPayNetworkJsonSerializerSettings jsonSerializerSettings,
PullPaymentHostedService pullPaymentService,
IEnumerable<IPayoutHandler> payoutHandlers)
IEnumerable<IPayoutHandler> payoutHandlers,
IServiceProvider serviceProvider)
{
_currencyTable = currencyTable;
Repository = repo;
@@ -109,6 +117,9 @@ namespace BTCPayServer.Controllers
_jsonSerializerSettings = jsonSerializerSettings;
_pullPaymentService = pullPaymentService;
_payoutHandlers = payoutHandlers;
ServiceProvider = serviceProvider;
_connectionFactory = connectionFactory;
_walletHistogramService = walletHistogramService;
}
// Borrowed from https://github.com/ManageIQ/guides/blob/master/labels.md
@@ -351,6 +362,19 @@ namespace BTCPayServer.Controllers
return View(model);
}
[HttpGet("{walletId}/histogram/{type}")]
public async Task<IActionResult> WalletHistogram(
[ModelBinder(typeof(WalletIdModelBinder))]
WalletId walletId, WalletHistogramType type)
{
var store = GetCurrentStore();
var data = await _walletHistogramService.GetHistogram(store, walletId, type);
return data == null
? NotFound()
: Json(data);
}
private static string GetLabelTarget(WalletId walletId, uint256 txId)
{
@@ -416,10 +440,48 @@ namespace BTCPayServer.Controllers
case "generate-new-address":
await _walletReceiveService.GetOrGenerate(walletId, true);
break;
case "fill-wallet":
var cheater = ServiceProvider.GetService<Cheater>();
if (cheater != null)
await SendFreeMoney(cheater, walletId, paymentMethod);
break;
}
return RedirectToAction(nameof(WalletReceive), new { walletId });
}
private async Task SendFreeMoney(Cheater cheater, WalletId walletId, DerivationSchemeSettings paymentMethod)
{
var c = this.ExplorerClientProvider.GetExplorerClient(walletId.CryptoCode);
var addresses = Enumerable.Range(0, 200).Select(_ => c.GetUnusedAsync(paymentMethod.AccountDerivation, DerivationFeature.Deposit, reserve: true)).ToArray();
await Task.WhenAll(addresses);
await cheater.CashCow.GenerateAsync(addresses.Length / 8);
var b = cheater.CashCow.PrepareBatch();
Random r = new Random();
List<Task<uint256>> sending = new List<Task<uint256>>();
foreach (var a in addresses)
{
sending.Add(b.SendToAddressAsync((await a).Address, Money.Coins(0.1m) + Money.Satoshis(r.Next(0, 90_000_000))));
}
await b.SendBatchAsync();
await cheater.CashCow.GenerateAsync(1);
var factory = ServiceProvider.GetService<NBXplorerConnectionFactory>();
// Wait it sync...
await Task.Delay(1000);
await ExplorerClientProvider.GetExplorerClient(walletId.CryptoCode).WaitServerStartedAsync();
await Task.Delay(1000);
await using var conn = await factory.OpenConnection();
var wallet_id = paymentMethod.GetNBXWalletId();
var txIds = sending.Select(s => s.Result.ToString()).ToArray();
await conn.ExecuteAsync(
"UPDATE txs t SET seen_at=(NOW() - (random() * (interval '90 days'))) " +
"FROM unnest(@txIds) AS r (tx_id) WHERE r.tx_id=t.tx_id;", new { txIds });
await Task.Delay(1000);
await conn.ExecuteAsync("REFRESH MATERIALIZED VIEW wallets_history;");
}
private async Task<bool> CanUseHotWallet()
{
var policies = await _settingsRepository.GetSettingAsync<PoliciesSettings>();