Compare commits

..

11 Commits

10 changed files with 106 additions and 36 deletions

View File

@ -37,7 +37,7 @@ services:
- postgres
nbxplorer:
image: nicolasdorier/nbxplorer:1.0.0.56
image: nicolasdorier/nbxplorer:1.0.0.64
ports:
- "32838:32838"
expose:

View File

@ -2,7 +2,7 @@
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.0</TargetFramework>
<Version>1.0.0.70</Version>
<Version>1.0.0.77</Version>
</PropertyGroup>
<ItemGroup>
<Compile Remove="Build\dockerfiles\**" />
@ -24,7 +24,7 @@
<PackageReference Include="NBitcoin" Version="4.0.0.51" />
<PackageReference Include="NBitpayClient" Version="1.0.0.16" />
<PackageReference Include="DBreeze" Version="1.87.0" />
<PackageReference Include="NBXplorer.Client" Version="1.0.0.31" />
<PackageReference Include="NBXplorer.Client" Version="1.0.0.33" />
<PackageReference Include="NicolasDorier.CommandLine" Version="1.0.0.1" />
<PackageReference Include="NicolasDorier.CommandLine.Configuration" Version="1.0.0.2" />
<PackageReference Include="NicolasDorier.StandardConfiguration" Version="1.0.0.13" />

View File

@ -19,7 +19,7 @@ namespace BTCPayServer.Configuration
protected override CommandLineApplication CreateCommandLineApplicationCore()
{
var provider = new BTCPayNetworkProvider(ChainType.Main);
var chains = string.Join(",", provider.GetAll().Select(n=>n.CryptoCode.ToLowerInvariant()).ToArray());
var chains = string.Join(",", provider.GetAll().Select(n => n.CryptoCode.ToLowerInvariant()).ToArray());
CommandLineApplication app = new CommandLineApplication(true)
{
FullName = "BTCPay\r\nOpen source, self-hosted payment processor.",
@ -72,9 +72,13 @@ namespace BTCPayServer.Configuration
if (network != null)
{
var n = Network.GetNetwork(network);
if (n == null)
{
throw new ConfigException($"Invalid network parameter '{network}'");
}
return n.ToChainType();
}
var net = conf.GetOrDefault<bool>("regtest", false) ? ChainType.Regtest:
var net = conf.GetOrDefault<bool>("regtest", false) ? ChainType.Regtest :
conf.GetOrDefault<bool>("testnet", false) ? ChainType.Test : ChainType.Main;
return net;

View File

@ -6,6 +6,21 @@ using BTCPayServer.HostedServices;
namespace BTCPayServer.Events
{
public class NBXplorerErrorEvent
{
public NBXplorerErrorEvent(BTCPayNetwork network, string errorMessage)
{
Message = errorMessage;
Network = network;
}
public string Message { get; set; }
public BTCPayNetwork Network { get; set; }
public override string ToString()
{
return $"{Network.CryptoCode}: NBXplorer error `{Message}`";
}
}
public class NBXplorerStateChangedEvent
{
public NBXplorerStateChangedEvent(BTCPayNetwork network, NBXplorerState old, NBXplorerState newState)

View File

@ -27,11 +27,12 @@ namespace BTCPayServer.HostedServices
public BTCPayNetwork Network { get; set; }
public NBXplorerState State { get; set; }
public StatusResult Status { get; set; }
public string Error { get; set; }
}
ConcurrentDictionary<string, NBXplorerSummary> _Summaries = new ConcurrentDictionary<string, NBXplorerSummary>();
public void Publish(BTCPayNetwork network, NBXplorerState state, StatusResult status)
public void Publish(BTCPayNetwork network, NBXplorerState state, StatusResult status, string error)
{
var summary = new NBXplorerSummary() { Network = network, State = state, Status = status };
var summary = new NBXplorerSummary() { Network = network, State = state, Status = status, Error = error };
_Summaries.AddOrUpdate(network.CryptoCode, summary, (k, v) => summary);
}
@ -120,6 +121,7 @@ namespace BTCPayServer.HostedServices
private async Task<bool> StepAsync(CancellationToken cancellation)
{
var oldState = State;
string error = null;
StatusResult status = null;
try
{
@ -164,15 +166,28 @@ namespace BTCPayServer.HostedServices
}
}
catch when (cancellation.IsCancellationRequested)
catch (Exception ex) when (!cancellation.IsCancellationRequested)
{
error = ex.Message;
}
catch (Exception ex)
if(status == null && error == null)
error = $"{_Network.CryptoCode}: NBXplorer does not support this cryptocurrency";
if(status != null && error == null)
{
if(status.ChainType != _Network.NBXplorerNetwork.DefaultSettings.ChainType)
error = $"{_Network.CryptoCode}: NBXplorer is on a different ChainType (actual: {status.ChainType}, expected: {_Network.NBXplorerNetwork.DefaultSettings.ChainType})";
}
if (error != null)
{
State = NBXplorerState.NotConnected;
Logs.PayServer.LogError(ex, $"Error while trying to connect to NBXplorer ({_Network.CryptoCode})");
status = null;
_Aggregator.Publish(new NBXplorerErrorEvent(_Network, error));
}
if (oldState != State)
{
if (State == NBXplorerState.Synching)
@ -185,7 +200,7 @@ namespace BTCPayServer.HostedServices
}
_Aggregator.Publish(new NBXplorerStateChangedEvent(_Network, oldState, State));
}
_Dashboard.Publish(_Network, State, status);
_Dashboard.Publish(_Network, State, status, error);
return oldState != State;
}

View File

@ -9,20 +9,21 @@
},
"profiles": {
"Default": {
"commandName": "Project"
"commandName": "Project",
"commandLineArgs": "--network testnet --chains ltc --ltcexplorerurl http://127.0.0.1:2727/"
},
"Docker-Regtest": {
"commandName": "Project",
"launchBrowser": true,
"environmentVariables": {
"BTCPAY_NETWORK": "regtest",
"BTCPAY_CHAINS": "btc,ltc",
"BTCPAY_LTCEXPLORERURL": "http://127.0.0.1:32838/",
"BTCPAY_BTCEXPLORERURL": "http://127.0.0.1:32838/",
"ASPNETCORE_ENVIRONMENT": "Development",
"BTCPAY_POSTGRES": "User ID=postgres;Host=127.0.0.1;Port=39372;Database=btcpayserver"
},
"environmentVariables": {
"BTCPAY_NETWORK": "regtest",
"BTCPAY_LTCEXPLORERURL": "http://127.0.0.1:32838/",
"BTCPAY_BTCEXPLORERURL": "http://127.0.0.1:32838/",
"ASPNETCORE_ENVIRONMENT": "Development",
"BTCPAY_CHAINS": "btc,ltc",
"BTCPAY_POSTGRES": "User ID=postgres;Host=127.0.0.1;Port=39372;Database=btcpayserver"
},
"applicationUrl": "http://localhost:14142/"
}
}
}
}

View File

@ -369,8 +369,8 @@ namespace BTCPayServer.Services.Invoices
dto.PaymentUrls = cryptoInfo.PaymentUrls;
}
#pragma warning restore CS0618
dto.CryptoInfo.Add(cryptoInfo);
if(!info.IsPhantomBTC)
dto.CryptoInfo.Add(cryptoInfo);
}
Populate(ProductInformation, dto);
@ -410,22 +410,22 @@ namespace BTCPayServer.Services.Invoices
public Dictionary<string, CryptoData> GetCryptoData(BTCPayNetworkProvider networkProvider, bool alwaysIncludeBTC = false)
{
Dictionary<string, CryptoData> rates = new Dictionary<string, CryptoData>();
bool btcAdded = false;
var serializer = new Serializer(Dummy);
CryptoData phantom = null;
#pragma warning disable CS0618
// Legacy
if (alwaysIncludeBTC)
{
var btcNetwork = networkProvider?.GetNetwork("BTC");
rates.Add("BTC", new CryptoData() { ParentEntity = this, Rate = Rate, CryptoCode = "BTC", TxFee = TxFee, FeeRate = new FeeRate(TxFee, 100), DepositAddress = DepositAddress, Network = btcNetwork });
btcAdded = true;
phantom = new CryptoData() { ParentEntity = this, IsPhantomBTC = true, Rate = Rate, CryptoCode = "BTC", TxFee = TxFee, FeeRate = new FeeRate(TxFee, 100), DepositAddress = DepositAddress, Network = btcNetwork };
rates.Add("BTC", phantom);
}
if (CryptoData != null)
{
foreach (var prop in CryptoData.Properties())
{
if (prop.Name == "BTC" && btcAdded)
continue;
if (prop.Name == "BTC" && phantom != null)
rates.Remove("BTC");
var r = serializer.ToObject<CryptoData>(prop.Value.ToString());
r.CryptoCode = prop.Name;
r.ParentEntity = this;
@ -511,9 +511,12 @@ namespace BTCPayServer.Services.Invoices
[JsonProperty(PropertyName = "depositAddress")]
public string DepositAddress { get; set; }
[JsonIgnore]
public bool IsPhantomBTC { get; set; }
public CryptoDataAccounting Calculate()
{
var cryptoData = ParentEntity.GetCryptoData(null);
var cryptoData = ParentEntity.GetCryptoData(null, IsPhantomBTC);
var totalDue = Money.Coins(ParentEntity.ProductInformation.Price / Rate);
var paid = Money.Zero;
var cryptoPaid = Money.Zero;

View File

@ -196,7 +196,7 @@ namespace BTCPayServer.Services.Invoices
continue;
var historical = new HistoricalAddressInvoiceData();
historical.InvoiceDataId = invoiceId;
historical.SetAddress(address.Value.DepositAddress, cryptoCode);
historical.SetAddress(address.Value.DepositAddress, address.Value.CryptoCode);
historical.UnAssigned = DateTimeOffset.UtcNow;
context.Attach(historical);
context.Entry(historical).Property(o => o.UnAssigned).IsModified = true;

View File

@ -57,7 +57,15 @@ namespace BTCPayServer.Services.Wallets
public async Task<BitcoinAddress> ReserveAddressAsync(DerivationStrategyBase derivationStrategy)
{
if (derivationStrategy == null)
throw new ArgumentNullException(nameof(derivationStrategy));
var pathInfo = await _Client.GetUnusedAsync(derivationStrategy, DerivationFeature.Deposit, 0, true).ConfigureAwait(false);
// Might happen on some broken install
if (pathInfo == null)
{
await _Client.TrackAsync(derivationStrategy).ConfigureAwait(false);
pathInfo = await _Client.GetUnusedAsync(derivationStrategy, DerivationFeature.Deposit, 0, true).ConfigureAwait(false);
}
return pathInfo.ScriptPubKey.GetDestinationAddress(Network.NBitcoinNetwork);
}
@ -100,9 +108,17 @@ namespace BTCPayServer.Services.Wallets
public async Task<Money> GetBalance(DerivationStrategyBase derivationStrategy)
{
var result = await _Client.SyncAsync(derivationStrategy, null, true);
return result.Confirmed.UTXOs.Select(u => u.Value)
.Concat(result.Unconfirmed.UTXOs.Select(u => u.Value))
.Sum();
Dictionary<OutPoint, UTXO> received = new Dictionary<OutPoint, UTXO>();
foreach(var utxo in result.Confirmed.UTXOs.Concat(result.Unconfirmed.UTXOs))
{
received.TryAdd(utxo.Outpoint, utxo);
}
foreach (var utxo in result.Confirmed.SpentOutpoints.Concat(result.Unconfirmed.SpentOutpoints))
{
received.Remove(utxo);
}
return received.Values.Select(c => c.Value).Sum();
}
}
}

View File

@ -103,7 +103,13 @@
<h4>@line.Network.CryptoCode</h4>
@if(line.Status == null)
{
<p>NBXplorer is offline</p>
<ul>
<li>The node is offline</li>
@if(line.Error != null)
{
<li>Last error: @line.Error</li>
}
</ul>
}
else
{
@ -118,11 +124,21 @@
else
{
<li>The node is offline</li>
@if(line.Error != null)
{
<li>Last error: @line.Error</li>
}
}
}
else if(line.Status.BitcoinStatus.IsSynched)
{
<li>The node is synched</li>
<li>The node is synched (Height: @line.Status.BitcoinStatus.Headers)</li>
@if(line.Status.BitcoinStatus.IsSynched &&
line.Status.SyncHeight.HasValue &&
line.Status.SyncHeight.Value < line.Status.BitcoinStatus.Headers)
{
<li>NBXplorer is synching... (Height: @line.Status.SyncHeight.Value)</li>
}
}
else
{