public override CryptoPaymentData GetCryptoPaymentData(PaymentEntity paymentEntity) { #pragma warning disable CS0618 BitcoinLikePaymentData paymentData; if (string.IsNullOrEmpty(paymentEntity.CryptoPaymentDataType)) { // For invoices created when CryptoPaymentDataType was not existing, we just consider that it is a RBFed payment for safety paymentData = new BitcoinLikePaymentData(); paymentData.Outpoint = paymentEntity.Outpoint; paymentData.Output = paymentEntity.Output; paymentData.RBF = true; paymentData.ConfirmationCount = 0; paymentData.Legacy = true; return(paymentData); } paymentData = JsonConvert.DeserializeObject <BitcoinLikePaymentData>(paymentEntity.CryptoPaymentData); // legacy paymentData.Output = paymentEntity.Output; paymentData.Outpoint = paymentEntity.Outpoint; #pragma warning restore CS0618 return(paymentData); }
private async Task Listen(BTCPayWallet wallet) { var network = wallet.Network; bool cleanup = false; try { if (_SessionsByCryptoCode.ContainsKey(network.CryptoCode)) { return; } var client = _ExplorerClients.GetExplorerClient(network); if (client == null) { return; } if (_Cts.IsCancellationRequested) { return; } var session = await client.CreateWebsocketNotificationSessionAsync(_Cts.Token).ConfigureAwait(false); if (!_SessionsByCryptoCode.TryAdd(network.CryptoCode, session)) { await session.DisposeAsync(); return; } cleanup = true; using (session) { await session.ListenNewBlockAsync(_Cts.Token).ConfigureAwait(false); await session.ListenAllTrackedSourceAsync(cancellation : _Cts.Token).ConfigureAwait(false); Logs.PayServer.LogInformation($"{network.CryptoCode}: Checking if any pending invoice got paid while offline..."); int paymentCount = await FindPaymentViaPolling(wallet, network); Logs.PayServer.LogInformation($"{network.CryptoCode}: {paymentCount} payments happened while offline"); Logs.PayServer.LogInformation($"Connected to WebSocket of NBXplorer ({network.CryptoCode})"); while (!_Cts.IsCancellationRequested) { var newEvent = await session.NextEventAsync(_Cts.Token).ConfigureAwait(false); switch (newEvent) { case NBXplorer.Models.NewBlockEvent evt: await UpdatePaymentStates(wallet, await _InvoiceRepository.GetPendingInvoices()); _Aggregator.Publish(new Events.NewBlockEvent() { CryptoCode = evt.CryptoCode }); break; case NBXplorer.Models.NewTransactionEvent evt: if (evt.DerivationStrategy != null) { wallet.InvalidateCache(evt.DerivationStrategy); var validOutputs = network.GetValidOutputs(evt).ToList(); if (!validOutputs.Any()) { break; } foreach (var output in validOutputs) { var key = output.Item1.ScriptPubKey.Hash + "#" + network.CryptoCode.ToUpperInvariant(); var invoice = (await _InvoiceRepository.GetInvoicesFromAddresses(new[] { key })) .FirstOrDefault(); if (invoice != null) { var address = network.NBXplorerNetwork.CreateAddress(evt.DerivationStrategy, output.Item1.KeyPath, output.Item1.ScriptPubKey); var paymentData = new BitcoinLikePaymentData(address, output.matchedOutput.Value, output.outPoint, evt.TransactionData.Transaction.RBF, output.matchedOutput.KeyPath); var alreadyExist = invoice .GetAllBitcoinPaymentData(false).Any(c => c.GetPaymentId() == paymentData.GetPaymentId()); if (!alreadyExist) { var payment = await _paymentService.AddPayment(invoice.Id, DateTimeOffset.UtcNow, paymentData, network); if (payment != null) { await ReceivedPayment(wallet, invoice, payment, evt.DerivationStrategy); } } else { await UpdatePaymentStates(wallet, invoice.Id); } } } } _Aggregator.Publish(new NewOnChainTransactionEvent() { CryptoCode = wallet.Network.CryptoCode, NewTransactionEvent = evt }); break; default: Logs.PayServer.LogWarning("Received unknown message from NBXplorer"); break; } } } } catch when(_Cts.IsCancellationRequested) { }
private async Task Listen(BTCPayWallet wallet) { var network = wallet.Network; bool cleanup = false; try { if (_SessionsByCryptoCode.ContainsKey(network.CryptoCode)) { return; } var client = _ExplorerClients.GetExplorerClient(network); if (client == null) { return; } if (_Cts.IsCancellationRequested) { return; } var session = await client.CreateNotificationSessionAsync(_Cts.Token).ConfigureAwait(false); if (!_SessionsByCryptoCode.TryAdd(network.CryptoCode, session)) { await session.DisposeAsync(); return; } cleanup = true; using (session) { await session.ListenNewBlockAsync(_Cts.Token).ConfigureAwait(false); await session.ListenAllDerivationSchemesAsync(cancellation : _Cts.Token).ConfigureAwait(false); Logs.PayServer.LogInformation($"{network.CryptoCode}: Checking if any pending invoice got paid while offline..."); int paymentCount = await FindPaymentViaPolling(wallet, network); Logs.PayServer.LogInformation($"{network.CryptoCode}: {paymentCount} payments happened while offline"); Logs.PayServer.LogInformation($"Connected to WebSocket of NBXplorer ({network.CryptoCode})"); while (!_Cts.IsCancellationRequested) { var newEvent = await session.NextEventAsync(_Cts.Token).ConfigureAwait(false); switch (newEvent) { case NBXplorer.Models.NewBlockEvent evt: await Task.WhenAll((await _InvoiceRepository.GetPendingInvoices()) .Select(invoiceId => UpdatePaymentStates(wallet, invoiceId)) .ToArray()); _Aggregator.Publish(new Events.NewBlockEvent() { CryptoCode = evt.CryptoCode }); break; case NBXplorer.Models.NewTransactionEvent evt: wallet.InvalidateCache(evt.DerivationStrategy); foreach (var output in evt.Outputs) { foreach (var txCoin in evt.TransactionData.Transaction.Outputs.AsCoins() .Where(o => o.ScriptPubKey == output.ScriptPubKey) .Select(o => output.Redeem == null ? o : o.ToScriptCoin(output.Redeem))) { var invoice = await _InvoiceRepository.GetInvoiceFromScriptPubKey(output.ScriptPubKey, network.CryptoCode); if (invoice != null) { var paymentData = new BitcoinLikePaymentData(txCoin, evt.TransactionData.Transaction.RBF); var alreadyExist = GetAllBitcoinPaymentData(invoice).Where(c => c.GetPaymentId() == paymentData.GetPaymentId()).Any(); if (!alreadyExist) { var payment = await _InvoiceRepository.AddPayment(invoice.Id, DateTimeOffset.UtcNow, paymentData, network.CryptoCode); await ReceivedPayment(wallet, invoice.Id, payment, evt.DerivationStrategy); } else { await UpdatePaymentStates(wallet, invoice.Id); } } } } break; default: Logs.PayServer.LogWarning("Received unknown message from NBXplorer"); break; } } } } catch when(_Cts.IsCancellationRequested) { }