diff --git a/BTCPayServer/BTCPayServer.csproj b/BTCPayServer/BTCPayServer.csproj
index c392836c0..d8212942d 100644
--- a/BTCPayServer/BTCPayServer.csproj
+++ b/BTCPayServer/BTCPayServer.csproj
@@ -2,7 +2,7 @@
Exe
netcoreapp2.0
- 1.0.1.27
+ 1.0.1.28
NU1701
diff --git a/BTCPayServer/Controllers/StoresController.cs b/BTCPayServer/Controllers/StoresController.cs
index 266aa470c..b9910cbf9 100644
--- a/BTCPayServer/Controllers/StoresController.cs
+++ b/BTCPayServer/Controllers/StoresController.cs
@@ -312,10 +312,10 @@ namespace BTCPayServer.Controllers
var stores = await _Repo.GetStoresByUserId(GetUserId());
var balances = stores
.Select(s => s.GetDerivationStrategies(_NetworkProvider)
- .Select(d => (Wallet: _WalletProvider.GetWallet(d.Network),
- DerivationStrategy: d.DerivationStrategyBase))
+ .Select(d => ((Wallet: _WalletProvider.GetWallet(d.Network),
+ DerivationStrategy: d.DerivationStrategyBase)))
.Where(_ => _.Wallet != null)
- .Select(async _ => (await _.Wallet.GetBalance(_.DerivationStrategy)).ToString() + " " + _.Wallet.Network.CryptoCode))
+ .Select(async _ => (await GetBalanceString(_)).ToString() + " " + _.Wallet.Network.CryptoCode))
.ToArray();
await Task.WhenAll(balances.SelectMany(_ => _));
@@ -333,6 +333,21 @@ namespace BTCPayServer.Controllers
return View(result);
}
+ private static async Task GetBalanceString((BTCPayWallet Wallet, DerivationStrategyBase DerivationStrategy) _)
+ {
+ using (CancellationTokenSource cts = new CancellationTokenSource(TimeSpan.FromSeconds(10)))
+ {
+ try
+ {
+ return (await _.Wallet.GetBalance(_.DerivationStrategy, cts.Token)).ToString();
+ }
+ catch
+ {
+ return "--";
+ }
+ }
+ }
+
[HttpGet]
[Route("{storeId}/delete")]
public async Task DeleteStore(string storeId)
diff --git a/BTCPayServer/Services/Wallets/BTCPayWallet.cs b/BTCPayServer/Services/Wallets/BTCPayWallet.cs
index 6f1e9f7a0..35f124e5a 100644
--- a/BTCPayServer/Services/Wallets/BTCPayWallet.cs
+++ b/BTCPayServer/Services/Wallets/BTCPayWallet.cs
@@ -1,4 +1,5 @@
using NBitcoin;
+using Microsoft.Extensions.Logging;
using NBXplorer;
using NBXplorer.DerivationStrategy;
using System;
@@ -10,6 +11,7 @@ using BTCPayServer.Data;
using System.Threading;
using NBXplorer.Models;
using Microsoft.Extensions.Caching.Memory;
+using BTCPayServer.Logging;
namespace BTCPayServer.Services.Wallets
{
@@ -25,7 +27,6 @@ namespace BTCPayServer.Services.Wallets
public Coin Coin { get; set; }
}
public TimestampedCoin[] TimestampedCoins { get; set; }
- public KnownState State { get; set; }
public DerivationStrategyBase Strategy { get; set; }
public BTCPayWallet Wallet { get; set; }
}
@@ -102,19 +103,40 @@ namespace BTCPayServer.Services.Wallets
_MemoryCache.Remove("CACHEDCOINS_" + strategy.ToString());
}
- public Task GetCoins(DerivationStrategyBase strategy, CancellationToken cancellation = default(CancellationToken))
+ public async Task GetCoins(DerivationStrategyBase strategy, CancellationToken cancellation = default(CancellationToken))
{
- return _MemoryCache.GetOrCreateAsync("CACHEDCOINS_" + strategy.ToString(), async entry =>
+ UTXOChanges changes = await GetUTXOChanges(strategy, cancellation);
+
+ return new NetworkCoins()
{
- entry.AbsoluteExpiration = DateTimeOffset.UtcNow + CacheSpan;
- var changes = await _Client.GetUTXOsAsync(strategy, null, false, cancellation).ConfigureAwait(false);
- return new NetworkCoins()
+ TimestampedCoins = changes.Confirmed.UTXOs.Concat(changes.Unconfirmed.UTXOs).Select(c => new NetworkCoins.TimestampedCoin() { Coin = c.AsCoin(), DateTime = c.Timestamp }).ToArray(),
+ Strategy = strategy,
+ Wallet = this
+ };
+ }
+
+ private async Task GetUTXOChanges(DerivationStrategyBase strategy, CancellationToken cancellation)
+ {
+ return await _MemoryCache.GetOrCreateAsync("CACHEDCOINS_" + strategy.ToString(), async entry =>
+ {
+ var now = DateTimeOffset.UtcNow;
+ UTXOChanges result = null;
+ try
{
- TimestampedCoins = changes.Confirmed.UTXOs.Concat(changes.Unconfirmed.UTXOs).Select(c => new NetworkCoins.TimestampedCoin() { Coin = c.AsCoin(), DateTime = c.Timestamp }).ToArray(),
- State = new KnownState() { PreviousCall = changes },
- Strategy = strategy,
- Wallet = this
- };
+ result = await _Client.GetUTXOsAsync(strategy, null, false, cancellation).ConfigureAwait(false);
+ }
+ catch
+ {
+ Logs.PayServer.LogError("Call to NBXplorer GetUTXOsAsync timed out, this should never happen, please report this issue to NBXplorer developers");
+ throw;
+ }
+ var spentTime = DateTimeOffset.UtcNow - now;
+ if (spentTime.TotalSeconds > 30)
+ {
+ Logs.PayServer.LogWarning($"NBXplorer took {(int)spentTime.TotalSeconds} seconds to reply, there is something wrong, please report this issue to NBXplorer developers");
+ }
+ entry.AbsoluteExpiration = DateTimeOffset.UtcNow + CacheSpan;
+ return result;
});
}
@@ -128,7 +150,7 @@ namespace BTCPayServer.Services.Wallets
public async Task<(Coin[], Dictionary