Compare commits

...

6 Commits

12 changed files with 72 additions and 58 deletions

View File

@ -466,7 +466,7 @@ namespace BTCPayServer.Tests
}
[Fact]
public void CanSendLightningPayment2()
public void CanSendLightningPaymentCLightning()
{
using (var tester = ServerTester.Create())
{
@ -498,7 +498,7 @@ namespace BTCPayServer.Tests
}
[Fact]
public void CanSendLightningPayment()
public void CanSendLightningPaymentCharge()
{
using (var tester = ServerTester.Create())

View File

@ -89,7 +89,7 @@ services:
- "bitcoin_datadir:/data"
customer_lightningd:
image: nicolasdorier/clightning:0.0.0.21-dev
image: nicolasdorier/clightning:v0.6-dev
environment:
EXPOSE_TCP: "true"
LIGHTNINGD_OPT: |
@ -112,7 +112,7 @@ services:
- bitcoind
lightning-charged:
image: shesek/lightning-charge:0.3.12
image: shesek/lightning-charge:0.3.15
environment:
NETWORK: regtest
API_TOKEN: foiewnccewuify
@ -131,7 +131,7 @@ services:
- merchant_lightningd
merchant_lightningd:
image: nicolasdorier/clightning:0.0.0.21-dev
image: nicolasdorier/clightning:v0.6-dev
environment:
EXPOSE_TCP: "true"
LIGHTNINGD_OPT: |

View File

@ -2,7 +2,7 @@
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.1</TargetFramework>
<Version>1.0.2.36</Version>
<Version>1.0.2.38</Version>
<NoWarn>NU1701,CA1816,CA1308,CA1810,CA2208</NoWarn>
</PropertyGroup>
<ItemGroup>
@ -40,10 +40,10 @@
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="2.1.0" />
<PackageReference Include="Microsoft.Extensions.Logging.Filter" Version="1.1.2" />
<PackageReference Include="Microsoft.NetCore.Analyzers" Version="2.6.0" />
<PackageReference Include="NBitcoin" Version="4.1.1.18" />
<PackageReference Include="NBitcoin" Version="4.1.1.20" />
<PackageReference Include="NBitpayClient" Version="1.0.0.29" />
<PackageReference Include="DBreeze" Version="1.87.0" />
<PackageReference Include="NBXplorer.Client" Version="1.0.2.11" />
<PackageReference Include="NBXplorer.Client" Version="1.0.2.12" />
<PackageReference Include="NicolasDorier.CommandLine" Version="1.0.0.2" />
<PackageReference Include="NicolasDorier.CommandLine.Configuration" Version="1.0.0.3" />
<PackageReference Include="NicolasDorier.StandardConfiguration" Version="1.0.0.14" />

View File

@ -144,32 +144,26 @@ namespace BTCPayServer.Controllers
PaymentMethod: CreatePaymentMethodAsync(fetchingByCurrencyPair, o.Handler, o.SupportedPaymentMethod, o.Network, entity, store)))
.ToList();
List<string> paymentMethodErrors = new List<string>();
List<string> invoiceLogs = new List<string>();
List<ISupportedPaymentMethod> supported = new List<ISupportedPaymentMethod>();
var paymentMethods = new PaymentMethodDictionary();
foreach(var pair in fetchingByCurrencyPair)
foreach (var pair in fetchingByCurrencyPair)
{
var rateResult = await pair.Value;
bool hasError = false;
if(rateResult.Errors.Count != 0)
invoiceLogs.Add($"{pair.Key}: The rating rule is {rateResult.Rule}");
invoiceLogs.Add($"{pair.Key}: The evaluated rating rule is {rateResult.EvaluatedRule}");
if (rateResult.Errors.Count != 0)
{
var allRateRuleErrors = string.Join(", ", rateResult.Errors.ToArray());
paymentMethodErrors.Add($"{pair.Key}: Rate rule error ({allRateRuleErrors})");
hasError = true;
invoiceLogs.Add($"{pair.Key}: Rate rule error ({allRateRuleErrors})");
}
if(rateResult.ExchangeExceptions.Count != 0)
if (rateResult.ExchangeExceptions.Count != 0)
{
foreach(var ex in rateResult.ExchangeExceptions)
foreach (var ex in rateResult.ExchangeExceptions)
{
paymentMethodErrors.Add($"{pair.Key}: Exception reaching exchange {ex.ExchangeName} ({ex.Exception.Message})");
invoiceLogs.Add($"{pair.Key}: Exception reaching exchange {ex.ExchangeName} ({ex.Exception.Message})");
}
hasError = true;
}
if(hasError)
{
paymentMethodErrors.Add($"{pair.Key}: The rule is {rateResult.Rule}");
paymentMethodErrors.Add($"{pair.Key}: Evaluated rule is {rateResult.EvaluatedRule}");
}
}
@ -185,11 +179,11 @@ namespace BTCPayServer.Controllers
}
catch (PaymentMethodUnavailableException ex)
{
paymentMethodErrors.Add($"{o.SupportedPaymentMethod.PaymentId.CryptoCode} ({o.SupportedPaymentMethod.PaymentId.PaymentType}): Payment method unavailable ({ex.Message})");
invoiceLogs.Add($"{o.SupportedPaymentMethod.PaymentId.CryptoCode} ({o.SupportedPaymentMethod.PaymentId.PaymentType}): Payment method unavailable ({ex.Message})");
}
catch (Exception ex)
{
paymentMethodErrors.Add($"{o.SupportedPaymentMethod.PaymentId.CryptoCode} ({o.SupportedPaymentMethod.PaymentId.PaymentType}): Unexpected exception ({ex.ToString()})");
invoiceLogs.Add($"{o.SupportedPaymentMethod.PaymentId.CryptoCode} ({o.SupportedPaymentMethod.PaymentId.PaymentType}): Unexpected exception ({ex.ToString()})");
}
}
@ -197,7 +191,7 @@ namespace BTCPayServer.Controllers
{
StringBuilder errors = new StringBuilder();
errors.AppendLine("No payment method available for this store");
foreach (var error in paymentMethodErrors)
foreach (var error in invoiceLogs)
{
errors.AppendLine(error);
}
@ -207,7 +201,7 @@ namespace BTCPayServer.Controllers
entity.SetSupportedPaymentMethods(supported);
entity.SetPaymentMethods(paymentMethods);
entity.PosData = invoice.PosData;
entity = await _InvoiceRepository.CreateInvoiceAsync(store.Id, entity, paymentMethodErrors, _NetworkProvider);
entity = await _InvoiceRepository.CreateInvoiceAsync(store.Id, entity, invoiceLogs, _NetworkProvider);
_EventAggregator.Publish(new Events.InvoiceEvent(entity.EntityToDTO(_NetworkProvider), 1001, "invoice_created"));
var resp = entity.EntityToDTO(_NetworkProvider);

View File

@ -288,7 +288,7 @@ namespace BTCPayServer.Controllers
var unspentCoins = await wallet.GetUnspentCoins(strategyBase);
var changeAddress = await change;
var send = new[] { (
destination: destinationAddress as IDestination,
destination: destinationAddress as IDestination,
amount: amountBTC,
substractFees: subsctractFeesValue) };
@ -335,15 +335,15 @@ namespace BTCPayServer.Controllers
Dictionary<uint256, Transaction> parentTransactions = new Dictionary<uint256, Transaction>();
if(!strategy.Segwit)
if (!strategy.Segwit)
{
var parentHashes = usedCoins.Select(c => c.Outpoint.Hash).ToHashSet();
var explorer = _ExplorerProvider.GetExplorerClient(network);
var getTransactionAsyncs = parentHashes.Select(h => (Op: explorer.GetTransactionAsync(h), Hash: h)).ToList();
foreach(var getTransactionAsync in getTransactionAsyncs)
foreach (var getTransactionAsync in getTransactionAsyncs)
{
var tx = (await getTransactionAsync.Op);
if(tx == null)
if (tx == null)
throw new Exception($"Parent transaction {getTransactionAsync.Hash} not found");
parentTransactions.Add(tx.Transaction.GetHash(), tx.Transaction);
}
@ -356,7 +356,7 @@ namespace BTCPayServer.Controllers
KeyPath = foundKeyPath.Derive(keypaths[c.TxOut.ScriptPubKey]),
PubKey = strategy.Root.Derive(keypaths[c.TxOut.ScriptPubKey]).PubKey
}).ToArray(), unsigned, hasChange ? foundKeyPath.Derive(changeAddress.Item2) : null);
try
{
var broadcastResult = await wallet.BroadcastTransactionsAsync(new List<Transaction>() { transaction });
@ -377,7 +377,7 @@ namespace BTCPayServer.Controllers
{ result = new LedgerTestResult() { Success = false, Error = "Timeout" }; }
catch (Exception ex)
{ result = new LedgerTestResult() { Success = false, Error = ex.Message }; }
finally { hw.Dispose(); }
try
{
if (result != null)

View File

@ -313,7 +313,7 @@ namespace BTCPayServer.Controllers
Action = "Continue",
Title = "Rate rule scripting",
Description = scripting ?
"This action will mofify your current rate sources. Are you sure to turn on rate rules scripting? (Advanced users)"
"This action will modify your current rate sources. Are you sure to turn on rate rules scripting? (Advanced users)"
: "This action will delete your rate script. Are you sure to turn off rate rules scripting?",
ButtonClass = "btn-primary"
});

View File

@ -20,9 +20,9 @@ namespace BTCPayServer.Services
public HardwareWalletException(string message) : base(message) { }
public HardwareWalletException(string message, Exception inner) : base(message, inner) { }
}
public class HardwareWalletService
public class HardwareWalletService : IDisposable
{
class WebSocketTransport : LedgerWallet.Transports.ILedgerTransport
class WebSocketTransport : LedgerWallet.Transports.ILedgerTransport, IDisposable
{
private readonly WebSocket webSocket;
@ -33,26 +33,40 @@ namespace BTCPayServer.Services
this.webSocket = webSocket;
}
SemaphoreSlim _Semaphore = new SemaphoreSlim(1, 1);
public TimeSpan Timeout { get; set; } = TimeSpan.FromSeconds(10);
public async Task<byte[][]> Exchange(byte[][] apdus)
{
await _Semaphore.WaitAsync();
List<byte[]> responses = new List<byte[]>();
using (CancellationTokenSource cts = new CancellationTokenSource(Timeout))
try
{
foreach (var apdu in apdus)
using (CancellationTokenSource cts = new CancellationTokenSource(Timeout))
{
await this.webSocket.SendAsync(new ArraySegment<byte>(apdu), WebSocketMessageType.Binary, true, cts.Token);
}
foreach (var apdu in apdus)
{
byte[] response = new byte[300];
var result = await this.webSocket.ReceiveAsync(new ArraySegment<byte>(response), cts.Token);
Array.Resize(ref response, result.Count);
responses.Add(response);
foreach (var apdu in apdus)
{
await this.webSocket.SendAsync(new ArraySegment<byte>(apdu), WebSocketMessageType.Binary, true, cts.Token);
}
foreach (var apdu in apdus)
{
byte[] response = new byte[300];
var result = await this.webSocket.ReceiveAsync(new ArraySegment<byte>(response), cts.Token);
Array.Resize(ref response, result.Count);
responses.Add(response);
}
}
}
finally
{
_Semaphore.Release();
}
return responses.ToArray();
}
public void Dispose()
{
_Semaphore.Dispose();
}
}
private readonly LedgerClient _Ledger;
@ -121,7 +135,7 @@ namespace BTCPayServer.Services
public async Task<KeyPath> GetKeyPath(BTCPayNetwork network, DirectDerivationStrategy directStrategy)
{
List<KeyPath> derivations = new List<KeyPath>();
if(network.NBitcoinNetwork.Consensus.SupportSegwit)
if (network.NBitcoinNetwork.Consensus.SupportSegwit)
derivations.Add(new KeyPath("49'"));
derivations.Add(new KeyPath("44'"));
KeyPath foundKeyPath = null;
@ -155,6 +169,12 @@ namespace BTCPayServer.Services
_Transport.Timeout = TimeSpan.FromMinutes(5);
return await Ledger.SignTransactionAsync(signatureRequests, unsigned, changeKeyPath);
}
public void Dispose()
{
if(_Transport != null)
_Transport.Dispose();
}
}
public class LedgerTestResult

View File

@ -10,8 +10,8 @@
</div>
<div class="modal-body">
<p>
Some of your nodes are still synching...<br />
BTCPay Server will not work correctly until it is over.
Some of your nodes are still synchronizing...<br />
BTCPay Server will not create invoices with those cryptocurrencies.
</p>
@foreach (var line in dashboard.GetAll())
{
@ -47,12 +47,12 @@
}
else if (line.Status.BitcoinStatus.IsSynched)
{
<li>The node is synched (Height: @line.Status.BitcoinStatus.Headers)</li>
<li>The node is synchronized (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>
<li>NBXplorer is synchronizing... (Height: @line.Status.SyncHeight.Value)</li>
}
}
else

View File

@ -17,7 +17,7 @@
If your Ledger wallet is not detected:
</p>
<ul>
<li>Make sure you are running the Ledger Bitcoin or Litecoin app with version superior or equal to 1.2.4</li>
<li>Make sure you are running the Ledger app with version superior or equal to 1.2.4</li>
<li>Use a browser supporting the <a href="https://www.yubico.com/support/knowledge-base/categories/articles/browsers-support-u2f/">U2F protocol</a></li>
</ul>
<p id="hw-loading"><span class="fa fa-question-circle" style="color:orange"></span> <span>Detecting hardware wallet...</span></p>

View File

@ -35,8 +35,8 @@ const locales_de = {
"What happened?": "Was ist passiert?",
"InvoiceExpired_Body_1": "Diese Rechnung ist abgelaufen. Eine Rechnung ist nur für {{maxTimeMinutes}} Minuten gültig. \
Sie können zu {{storeName}} zurückkehren, wenn Sie Ihre Zahlung erneut senden möchten.",
"InvoiceExpired_Body_2": "Wenn Sie versucht haben, eine Zahlung zu senden, wurde sie vom Bitcoin-Netzwerk noch nicht akzeptiert. Wir haben Ihre Gelder noch nicht erhalten.",
"InvoiceExpired_Body_3": "Wenn die Transaktion vom Bitcoin-Netzwerk nicht akzeptiert wird, ist das Geld wieder in Ihrer Wallet verfügbar. Abhängig von Ihrer Wallet, kann dies 48-72 Stunden dauern.",
"InvoiceExpired_Body_2": "Wenn Sie versucht haben, eine Zahlung zu senden, wurde sie vom Netzwerk noch nicht akzeptiert. Wir haben Ihre Gelder noch nicht erhalten.",
"InvoiceExpired_Body_3": "Wenn die Transaktion vom Netzwerk nicht akzeptiert wird, ist das Geld wieder in Ihrer Wallet verfügbar. Abhängig von Ihrer Wallet, kann dies 48-72 Stunden dauern.",
"Invoice ID": "Rechnungs ID",
"Order ID": "Auftrag ID",
"Return to StoreName": "Zurück zu {{storeName}}",

View File

@ -35,8 +35,8 @@ const locales_en = {
"What happened?": "What happened?",
"InvoiceExpired_Body_1": "This invoice has expired. An invoice is only valid for {{maxTimeMinutes}} minutes. \
You can return to {{storeName}} if you would like to submit your payment again.",
"InvoiceExpired_Body_2": "If you tried to send a payment, it has not yet been accepted by the Bitcoin network. We have not yet received your funds.",
"InvoiceExpired_Body_3": "If the transaction is not accepted by the Bitcoin network, the funds will be spendable again in your wallet. Depending on your wallet, this may take 48-72 hours.",
"InvoiceExpired_Body_2": "If you tried to send a payment, it has not yet been accepted by the network. We have not yet received your funds.",
"InvoiceExpired_Body_3": "If the transaction is not accepted by the network, the funds will be spendable again in your wallet. Depending on your wallet, this may take 48-72 hours.",
"Invoice ID": "Invoice ID",
"Order ID": "Order ID",
"Return to StoreName": "Return to {{storeName}}",

View File

@ -26,7 +26,7 @@ const locales_is = {
"Copied": "Afritað",
// Conversion tab
"ConversionTab_BodyTop": "Þú getur borgað {{btcDue}} {{cryptoCode}} með altcoins.",
"ConversionTab_BodyDesc": "Þessi þjónusta er veitt af þriðja aðila. Mundu að við höfum ekki stjórn á því hvað þeir gera við peningana. Reikningurinn verður aðeins móttekinn þegar {{cryptoCode}} greiðslan hefur verið staðfest á Bitcoin netinu.",
"ConversionTab_BodyDesc": "Þessi þjónusta er veitt af þriðja aðila. Mundu að við höfum ekki stjórn á því hvað þeir gera við peningana. Reikningurinn verður aðeins móttekinn þegar {{cryptoCode}} greiðslan hefur verið staðfest á netinu.",
"Shapeshift_Button_Text": "Borga með Altcoins",
"ConversionTab_Lightning": "Engir viðskiptaveitendur eru í boði fyrir Lightning Network greiðslur.",
// Invoice expired
@ -36,7 +36,7 @@ const locales_is = {
"InvoiceExpired_Body_1": "Þessi reikningur er útrunnin. Reikningurinn er aðeins gildur í {{maxTimeMinutes}} mínútur. \
Þú getur farið aftur á {{storeName}} ef þú vilt reyna aftur.",
"InvoiceExpired_Body_2": "Ef þú reyndir að senda greiðslu, þá hefur hún ekki verið samþykkt.",
"InvoiceExpired_Body_3": "Ef viðskiptin eru ekki samþykkt af Bitcoin netinu verða fjármunirnir aðgengilegar aftur í veskinu þínu. Það fer eftir veskinu þínu og getur tekið 48-72 klukkustundir.",
"InvoiceExpired_Body_3": "Ef viðskiptin eru ekki samþykkt af netinu verða fjármunirnir aðgengilegar aftur í veskinu þínu. Það fer eftir veskinu þínu og getur tekið 48-72 klukkustundir.",
"Invoice ID": "Innheimtu ID",
"Order ID": "Pöntun ID",
"Return to StoreName": "Fara aftur á {{storeName}}",