Fix monero payments

This commit is contained in:
nicolas.dorier 2024-10-16 23:15:27 +09:00
parent d7fd90c4c3
commit b7affb1d34
No known key found for this signature in database
GPG Key ID: 6618763EF09186FE
5 changed files with 106 additions and 146 deletions

View File

@ -727,5 +727,39 @@
}, },
"version": 2 "version": 2
} }
},
{
"type": "payment",
"input": {
"output": null,
"version": 1,
"outpoint": null,
"accounted": true,
"cryptoCode": "XMR",
"networkFee": 0.0000000019,
"receivedTimeMs": 1705500405468,
"cryptoPaymentData": "{\"Amount\":62700000000,\"Address\":\"85CjjvQyW7PjNmiFRKZuEHKzZjiB3rjSu6n8zPzji4PtQxw1CyEY5H5FBge6GRUMJqR7FqsgBHU7H1FpEppvZXS6HGpFF6t\",\"SubaddressIndex\":23,\"SubaccountIndex\":0,\"BlockHeight\":3063946,\"ConfirmationCount\":10,\"TransactionId\":\"cc2e9ef03864c6af5e0d6f1c730ba142144f6588c50035b2996a59a6f3771b06\",\"LockTime\":0}",
"cryptoPaymentDataType": "MoneroLike"
},
"expected": {
"divisibility": 12,
"destination": "85CjjvQyW7PjNmiFRKZuEHKzZjiB3rjSu6n8zPzji4PtQxw1CyEY5H5FBge6GRUMJqR7FqsgBHU7H1FpEppvZXS6HGpFF6t",
"details": {
"blockHeight": 3063946,
"confirmationCount": 10,
"lockTime": 0,
"subaccountIndex": 0,
"subaddressIndex": 23,
"transactionId": "cc2e9ef03864c6af5e0d6f1c730ba142144f6588c50035b2996a59a6f3771b06"
},
"version": 2
},
"expectedProperties": {
"Amount": "0.0627",
"PaymentMethodId": "XMR-CHAIN",
"Currency": "XMR",
"Status": "Settled",
"Accounted": null
}
} }
] ]

View File

@ -430,7 +430,7 @@ namespace BTCPayServer.Controllers.Greenfield
try try
{ {
bip21 = new BitcoinUrlBuilder(destination.Destination, network.NBitcoinNetwork); bip21 = new BitcoinUrlBuilder(destination.Destination, network.NBitcoinNetwork);
amount ??= bip21.Amount.GetValue(network); amount ??= bip21.Amount?.GetValue(network);
if (bip21.Address is null) if (bip21.Address is null)
request.AddModelError(transactionRequest => transactionRequest.Destinations[index], request.AddModelError(transactionRequest => transactionRequest.Destinations[index],
"This BIP21 destination is missing a bitcoin address", this); "This BIP21 destination is missing a bitcoin address", this);

View File

@ -3,10 +3,12 @@ using System.Collections.Concurrent;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading; using System.Threading;
using System.Threading.Channels;
using System.Threading.Tasks; using System.Threading.Tasks;
using BTCPayServer.Client.Models; using BTCPayServer.Client.Models;
using BTCPayServer.Data; using BTCPayServer.Data;
using BTCPayServer.Events; using BTCPayServer.Events;
using BTCPayServer.HostedServices;
using BTCPayServer.Payments; using BTCPayServer.Payments;
using BTCPayServer.Plugins.Altcoins; using BTCPayServer.Plugins.Altcoins;
using BTCPayServer.Services.Altcoins.Monero.Configuration; using BTCPayServer.Services.Altcoins.Monero.Configuration;
@ -24,7 +26,7 @@ using Newtonsoft.Json.Linq;
namespace BTCPayServer.Services.Altcoins.Monero.Services namespace BTCPayServer.Services.Altcoins.Monero.Services
{ {
public class MoneroListener : IHostedService public class MoneroListener : EventHostedServiceBase
{ {
private readonly InvoiceRepository _invoiceRepository; private readonly InvoiceRepository _invoiceRepository;
private readonly EventAggregator _eventAggregator; private readonly EventAggregator _eventAggregator;
@ -35,9 +37,6 @@ namespace BTCPayServer.Services.Altcoins.Monero.Services
private readonly PaymentMethodHandlerDictionary _handlers; private readonly PaymentMethodHandlerDictionary _handlers;
private readonly InvoiceActivator _invoiceActivator; private readonly InvoiceActivator _invoiceActivator;
private readonly PaymentService _paymentService; private readonly PaymentService _paymentService;
private readonly CompositeDisposable leases = new CompositeDisposable();
private readonly Queue<Func<CancellationToken, Task>> taskQueue = new Queue<Func<CancellationToken, Task>>();
private CancellationTokenSource _Cts;
public MoneroListener(InvoiceRepository invoiceRepository, public MoneroListener(InvoiceRepository invoiceRepository,
EventAggregator eventAggregator, EventAggregator eventAggregator,
@ -47,7 +46,7 @@ namespace BTCPayServer.Services.Altcoins.Monero.Services
ILogger<MoneroListener> logger, ILogger<MoneroListener> logger,
PaymentMethodHandlerDictionary handlers, PaymentMethodHandlerDictionary handlers,
InvoiceActivator invoiceActivator, InvoiceActivator invoiceActivator,
PaymentService paymentService) PaymentService paymentService) : base(eventAggregator, logger)
{ {
_invoiceRepository = invoiceRepository; _invoiceRepository = invoiceRepository;
_eventAggregator = eventAggregator; _eventAggregator = eventAggregator;
@ -60,73 +59,43 @@ namespace BTCPayServer.Services.Altcoins.Monero.Services
_paymentService = paymentService; _paymentService = paymentService;
} }
public Task StartAsync(CancellationToken cancellationToken) protected override void SubscribeToEvents()
{ {
if (!_MoneroLikeConfiguration.MoneroLikeConfigurationItems.Any()) base.SubscribeToEvents();
{ Subscribe<MoneroEvent>();
return Task.CompletedTask; Subscribe<MoneroRPCProvider.MoneroDaemonStateChange>();
} }
_Cts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
leases.Add(_eventAggregator.Subscribe<MoneroEvent>(OnMoneroEvent)); protected override async Task ProcessEvent(object evt, CancellationToken cancellationToken)
leases.Add(_eventAggregator.Subscribe<MoneroRPCProvider.MoneroDaemonStateChange>(e => {
if (evt is MoneroRPCProvider.MoneroDaemonStateChange stateChange)
{ {
if (_moneroRpcProvider.IsAvailable(e.CryptoCode)) if (_moneroRpcProvider.IsAvailable(stateChange.CryptoCode))
{ {
_logger.LogInformation($"{e.CryptoCode} just became available"); _logger.LogInformation($"{stateChange.CryptoCode} just became available");
_ = UpdateAnyPendingMoneroLikePayment(e.CryptoCode); _ = UpdateAnyPendingMoneroLikePayment(stateChange.CryptoCode);
} }
else else
{ {
_logger.LogInformation($"{e.CryptoCode} just became unavailable"); _logger.LogInformation($"{stateChange.CryptoCode} just became unavailable");
} }
})); }
_ = WorkThroughQueue(_Cts.Token); else if (evt is MoneroEvent moneroEvent)
return Task.CompletedTask;
}
private async Task WorkThroughQueue(CancellationToken token)
{
while (!token.IsCancellationRequested)
{ {
if (taskQueue.TryDequeue(out var t)) if (!_moneroRpcProvider.IsAvailable(moneroEvent.CryptoCode))
return;
if (!string.IsNullOrEmpty(moneroEvent.BlockHash))
{ {
try await OnNewBlock(moneroEvent.CryptoCode);
{
await t.Invoke(token);
}
catch (Exception e)
{
_logger.LogError($"error with queue item", e);
}
} }
else if (!string.IsNullOrEmpty(moneroEvent.TransactionHash))
{ {
await Task.Delay(TimeSpan.FromSeconds(1), token); await OnTransactionUpdated(moneroEvent.CryptoCode, moneroEvent.TransactionHash);
} }
} }
} }
private void OnMoneroEvent(MoneroEvent obj)
{
if (!_moneroRpcProvider.IsAvailable(obj.CryptoCode))
{
return;
}
if (!string.IsNullOrEmpty(obj.BlockHash))
{
taskQueue.Enqueue(token => OnNewBlock(obj.CryptoCode));
}
if (!string.IsNullOrEmpty(obj.TransactionHash))
{
taskQueue.Enqueue(token => OnTransactionUpdated(obj.CryptoCode, obj.TransactionHash));
}
}
private async Task ReceivedPayment(InvoiceEntity invoice, PaymentEntity payment) private async Task ReceivedPayment(InvoiceEntity invoice, PaymentEntity payment)
{ {
_logger.LogInformation( _logger.LogInformation(
@ -204,7 +173,7 @@ namespace BTCPayServer.Services.Altcoins.Monero.Services
var transferProcessingTasks = new List<Task>(); var transferProcessingTasks = new List<Task>();
var updatedPaymentEntities = new BlockingCollection<(PaymentEntity Payment, InvoiceEntity invoice)>(); var updatedPaymentEntities = new List<(PaymentEntity Payment, InvoiceEntity invoice)>();
foreach (var keyValuePair in tasks) foreach (var keyValuePair in tasks)
{ {
var transfers = keyValuePair.Value.Result.In; var transfers = keyValuePair.Value.Result.In;
@ -256,14 +225,6 @@ namespace BTCPayServer.Services.Altcoins.Monero.Services
} }
} }
public Task StopAsync(CancellationToken cancellationToken)
{
leases.Dispose();
_Cts?.Cancel();
return Task.CompletedTask;
}
private async Task OnNewBlock(string cryptoCode) private async Task OnNewBlock(string cryptoCode)
{ {
await UpdateAnyPendingMoneroLikePayment(cryptoCode); await UpdateAnyPendingMoneroLikePayment(cryptoCode);
@ -278,7 +239,7 @@ namespace BTCPayServer.Services.Altcoins.Monero.Services
"get_transfer_by_txid", "get_transfer_by_txid",
new GetTransferByTransactionIdRequest() { TransactionId = transactionHash }); new GetTransferByTransactionIdRequest() { TransactionId = transactionHash });
var paymentsToUpdate = new BlockingCollection<(PaymentEntity Payment, InvoiceEntity invoice)>(); var paymentsToUpdate = new List<(PaymentEntity Payment, InvoiceEntity invoice)>();
//group all destinations of the tx together and loop through the sets //group all destinations of the tx together and loop through the sets
foreach (var destination in transfer.Transfers.GroupBy(destination => destination.Address)) foreach (var destination in transfer.Transfers.GroupBy(destination => destination.Address))
@ -317,7 +278,7 @@ namespace BTCPayServer.Services.Altcoins.Monero.Services
private async Task HandlePaymentData(string cryptoCode, string address, long totalAmount, long subaccountIndex, private async Task HandlePaymentData(string cryptoCode, string address, long totalAmount, long subaccountIndex,
long subaddressIndex, long subaddressIndex,
string txId, long confirmations, long blockHeight, long locktime, InvoiceEntity invoice, string txId, long confirmations, long blockHeight, long locktime, InvoiceEntity invoice,
BlockingCollection<(PaymentEntity Payment, InvoiceEntity invoice)> paymentsToUpdate) List<(PaymentEntity Payment, InvoiceEntity invoice)> paymentsToUpdate)
{ {
var network = _networkProvider.GetNetwork(cryptoCode); var network = _networkProvider.GetNetwork(cryptoCode);
var pmi = PaymentTypes.CHAIN.GetPaymentMethodId(network.CryptoCode); var pmi = PaymentTypes.CHAIN.GetPaymentMethodId(network.CryptoCode);
@ -333,9 +294,10 @@ namespace BTCPayServer.Services.Altcoins.Monero.Services
LockTime = locktime, LockTime = locktime,
InvoiceSettledConfirmationThreshold = promptDetails.InvoiceSettledConfirmationThreshold InvoiceSettledConfirmationThreshold = promptDetails.InvoiceSettledConfirmationThreshold
}; };
var status = GetStatus(details, invoice.SpeedPolicy) ? PaymentStatus.Settled : PaymentStatus.Processing;
var paymentData = new Data.PaymentData() var paymentData = new Data.PaymentData()
{ {
Status = GetStatus(details, invoice.SpeedPolicy) ? PaymentStatus.Settled : PaymentStatus.Processing, Status = status,
Amount = MoneroMoney.Convert(totalAmount), Amount = MoneroMoney.Convert(totalAmount),
Created = DateTimeOffset.UtcNow, Created = DateTimeOffset.UtcNow,
Id = $"{txId}#{subaccountIndex}#{subaddressIndex}", Id = $"{txId}#{subaccountIndex}#{subaddressIndex}",
@ -346,11 +308,10 @@ namespace BTCPayServer.Services.Altcoins.Monero.Services
//check if this tx exists as a payment to this invoice already //check if this tx exists as a payment to this invoice already
var alreadyExistingPaymentThatMatches = GetAllMoneroLikePayments(invoice, cryptoCode) var alreadyExistingPaymentThatMatches = GetAllMoneroLikePayments(invoice, cryptoCode)
.Select(entity => (Payment: entity, PaymentData: handler.ParsePaymentDetails(entity.Details))) .SingleOrDefault(c => c.Id == paymentData.Id && c.PaymentMethodId == pmi);
.SingleOrDefault(c => c.Payment.PaymentMethodId == pmi);
//if it doesnt, add it and assign a new monerolike address to the system if a balance is still due //if it doesnt, add it and assign a new monerolike address to the system if a balance is still due
if (alreadyExistingPaymentThatMatches.Payment == null) if (alreadyExistingPaymentThatMatches == null)
{ {
var payment = await _paymentService.AddPayment(paymentData, [txId]); var payment = await _paymentService.AddPayment(paymentData, [txId]);
if (payment != null) if (payment != null)
@ -359,9 +320,9 @@ namespace BTCPayServer.Services.Altcoins.Monero.Services
else else
{ {
//else update it with the new data //else update it with the new data
alreadyExistingPaymentThatMatches.PaymentData = details; alreadyExistingPaymentThatMatches.Status = status;
alreadyExistingPaymentThatMatches.Payment.Details = JToken.FromObject(paymentData, handler.Serializer); alreadyExistingPaymentThatMatches.Details = JToken.FromObject(details, handler.Serializer);
paymentsToUpdate.Add((alreadyExistingPaymentThatMatches.Payment, invoice)); paymentsToUpdate.Add((alreadyExistingPaymentThatMatches, invoice));
} }
} }

View File

@ -8,6 +8,7 @@ using System.Threading.Tasks;
using BTCPayServer.Client.Models; using BTCPayServer.Client.Models;
using BTCPayServer.Data; using BTCPayServer.Data;
using BTCPayServer.Events; using BTCPayServer.Events;
using BTCPayServer.HostedServices;
using BTCPayServer.Payments; using BTCPayServer.Payments;
using BTCPayServer.Plugins.Altcoins; using BTCPayServer.Plugins.Altcoins;
using BTCPayServer.Services.Altcoins.Zcash.Configuration; using BTCPayServer.Services.Altcoins.Zcash.Configuration;
@ -26,7 +27,7 @@ using static BTCPayServer.Client.Models.InvoicePaymentMethodDataModel;
namespace BTCPayServer.Services.Altcoins.Zcash.Services namespace BTCPayServer.Services.Altcoins.Zcash.Services
{ {
public class ZcashListener : IHostedService public class ZcashListener : EventHostedServiceBase
{ {
private readonly InvoiceRepository _invoiceRepository; private readonly InvoiceRepository _invoiceRepository;
private readonly EventAggregator _eventAggregator; private readonly EventAggregator _eventAggregator;
@ -37,19 +38,16 @@ namespace BTCPayServer.Services.Altcoins.Zcash.Services
private readonly PaymentService _paymentService; private readonly PaymentService _paymentService;
private readonly InvoiceActivator _invoiceActivator; private readonly InvoiceActivator _invoiceActivator;
private readonly PaymentMethodHandlerDictionary _handlers; private readonly PaymentMethodHandlerDictionary _handlers;
private readonly CompositeDisposable leases = new CompositeDisposable();
private readonly Channel<Func<Task>> _requests = Channel.CreateUnbounded<Func<Task>>();
private CancellationTokenSource _Cts;
public ZcashListener(InvoiceRepository invoiceRepository, public ZcashListener(InvoiceRepository invoiceRepository,
EventAggregator eventAggregator, EventAggregator eventAggregator,
ZcashRPCProvider ZcashRpcProvider, ZcashRPCProvider ZcashRpcProvider,
ZcashLikeConfiguration ZcashLikeConfiguration, ZcashLikeConfiguration ZcashLikeConfiguration,
BTCPayNetworkProvider networkProvider, BTCPayNetworkProvider networkProvider,
ILogger<ZcashListener> logger, ILogger<ZcashListener> logger,
PaymentService paymentService, PaymentService paymentService,
InvoiceActivator invoiceActivator, InvoiceActivator invoiceActivator,
PaymentMethodHandlerDictionary handlers) PaymentMethodHandlerDictionary handlers) : base(eventAggregator, logger)
{ {
_invoiceRepository = invoiceRepository; _invoiceRepository = invoiceRepository;
_eventAggregator = eventAggregator; _eventAggregator = eventAggregator;
@ -62,63 +60,39 @@ namespace BTCPayServer.Services.Altcoins.Zcash.Services
_handlers = handlers; _handlers = handlers;
} }
public Task StartAsync(CancellationToken cancellationToken) protected override void SubscribeToEvents()
{ {
if (!_ZcashLikeConfiguration.ZcashLikeConfigurationItems.Any()) base.SubscribeToEvents();
{ Subscribe<ZcashEvent>();
return Task.CompletedTask; Subscribe<ZcashRPCProvider.ZcashDaemonStateChange>();
} }
_Cts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
leases.Add(_eventAggregator.Subscribe<ZcashEvent>(OnZcashEvent)); protected override async Task ProcessEvent(object evt, CancellationToken cancellationToken)
leases.Add(_eventAggregator.Subscribe<ZcashRPCProvider.ZcashDaemonStateChange>(e => {
if (evt is ZcashRPCProvider.ZcashDaemonStateChange stateChanged)
{ {
if (_ZcashRpcProvider.IsAvailable(e.CryptoCode)) if (_ZcashRpcProvider.IsAvailable(stateChanged.CryptoCode))
{ {
_logger.LogInformation($"{e.CryptoCode} just became available"); _logger.LogInformation($"{stateChanged.CryptoCode} just became available");
_ = UpdateAnyPendingZcashLikePayment(e.CryptoCode); _ = UpdateAnyPendingZcashLikePayment(stateChanged.CryptoCode);
} }
else else
{ {
_logger.LogInformation($"{e.CryptoCode} just became unavailable"); _logger.LogInformation($"{stateChanged.CryptoCode} just became unavailable");
} }
})); }
_ = WorkThroughQueue(_Cts.Token); else if (evt is ZcashEvent zcashEvent)
return Task.CompletedTask; {
} if (!_ZcashRpcProvider.IsAvailable(zcashEvent.CryptoCode))
return;
private async Task WorkThroughQueue(CancellationToken token) if (!string.IsNullOrEmpty(zcashEvent.BlockHash))
{
while (await _requests.Reader.WaitToReadAsync(token) && _requests.Reader.TryRead(out var action)) {
token.ThrowIfCancellationRequested();
try {
await action.Invoke();
}
catch (Exception e)
{ {
_logger.LogError($"error with action item {e}"); await OnNewBlock(zcashEvent.CryptoCode);
} }
} if (!string.IsNullOrEmpty(zcashEvent.TransactionHash))
} {
await OnTransactionUpdated(zcashEvent.CryptoCode, zcashEvent.TransactionHash);
private void OnZcashEvent(ZcashEvent obj)
{
if (!_ZcashRpcProvider.IsAvailable(obj.CryptoCode))
{
return;
}
if (!string.IsNullOrEmpty(obj.BlockHash))
{
if (!_requests.Writer.TryWrite(() => OnNewBlock(obj.CryptoCode))) {
_logger.LogWarning($"Failed to write new block task to channel");
}
}
if (!string.IsNullOrEmpty(obj.TransactionHash))
{
if (!_requests.Writer.TryWrite(() => OnTransactionUpdated(obj.CryptoCode, obj.TransactionHash))) {
_logger.LogWarning($"Failed to write new tx task to channel");
} }
} }
} }
@ -202,7 +176,7 @@ namespace BTCPayServer.Services.Altcoins.Zcash.Services
var transferProcessingTasks = new List<Task>(); var transferProcessingTasks = new List<Task>();
var updatedPaymentEntities = new BlockingCollection<(PaymentEntity Payment, InvoiceEntity invoice)>(); var updatedPaymentEntities = new List<(PaymentEntity Payment, InvoiceEntity invoice)>();
foreach (var keyValuePair in tasks) foreach (var keyValuePair in tasks)
{ {
var transfers = keyValuePair.Value.Result.In; var transfers = keyValuePair.Value.Result.In;
@ -254,14 +228,6 @@ namespace BTCPayServer.Services.Altcoins.Zcash.Services
} }
} }
public Task StopAsync(CancellationToken cancellationToken)
{
leases.Dispose();
_Cts?.Cancel();
return Task.CompletedTask;
}
private async Task OnNewBlock(string cryptoCode) private async Task OnNewBlock(string cryptoCode)
{ {
await UpdateAnyPendingZcashLikePayment(cryptoCode); await UpdateAnyPendingZcashLikePayment(cryptoCode);
@ -276,7 +242,7 @@ namespace BTCPayServer.Services.Altcoins.Zcash.Services
"get_transfer_by_txid", "get_transfer_by_txid",
new GetTransferByTransactionIdRequest() { TransactionId = transactionHash }); new GetTransferByTransactionIdRequest() { TransactionId = transactionHash });
var paymentsToUpdate = new BlockingCollection<(PaymentEntity Payment, InvoiceEntity invoice)>(); var paymentsToUpdate = new List<(PaymentEntity Payment, InvoiceEntity invoice)>();
//group all destinations of the tx together and loop through the sets //group all destinations of the tx together and loop through the sets
foreach (var destination in transfer.Transfers.GroupBy(destination => destination.Address)) foreach (var destination in transfer.Transfers.GroupBy(destination => destination.Address))
@ -315,7 +281,7 @@ namespace BTCPayServer.Services.Altcoins.Zcash.Services
private async Task HandlePaymentData(string cryptoCode, string address, long totalAmount, long subaccountIndex, private async Task HandlePaymentData(string cryptoCode, string address, long totalAmount, long subaccountIndex,
long subaddressIndex, long subaddressIndex,
string txId, long confirmations, long blockHeight, InvoiceEntity invoice, string txId, long confirmations, long blockHeight, InvoiceEntity invoice,
BlockingCollection<(PaymentEntity Payment, InvoiceEntity invoice)> paymentsToUpdate) List<(PaymentEntity Payment, InvoiceEntity invoice)> paymentsToUpdate)
{ {
var network = _networkProvider.GetNetwork(cryptoCode); var network = _networkProvider.GetNetwork(cryptoCode);
var pmi = PaymentTypes.CHAIN.GetPaymentMethodId(network.CryptoCode); var pmi = PaymentTypes.CHAIN.GetPaymentMethodId(network.CryptoCode);
@ -329,9 +295,10 @@ namespace BTCPayServer.Services.Altcoins.Zcash.Services
ConfirmationCount = confirmations, ConfirmationCount = confirmations,
BlockHeight = blockHeight BlockHeight = blockHeight
}; };
var status = GetStatus(details, invoice.SpeedPolicy) ? PaymentStatus.Settled : PaymentStatus.Processing;
var paymentData = new Data.PaymentData() var paymentData = new Data.PaymentData()
{ {
Status = GetStatus(details, invoice.SpeedPolicy) ? PaymentStatus.Settled : PaymentStatus.Processing, Status = status,
Amount = ZcashMoney.Convert(totalAmount), Amount = ZcashMoney.Convert(totalAmount),
Created = DateTimeOffset.UtcNow, Created = DateTimeOffset.UtcNow,
Id = $"{txId}#{subaccountIndex}#{subaddressIndex}", Id = $"{txId}#{subaccountIndex}#{subaddressIndex}",
@ -340,11 +307,10 @@ namespace BTCPayServer.Services.Altcoins.Zcash.Services
var alreadyExistingPaymentThatMatches = GetAllZcashLikePayments(invoice, cryptoCode) var alreadyExistingPaymentThatMatches = GetAllZcashLikePayments(invoice, cryptoCode)
.Select(entity => (Payment: entity, PaymentData: handler.ParsePaymentDetails(entity.Details))) .SingleOrDefault(c => c.Id == paymentData.Id && c.PaymentMethodId == pmi);
.SingleOrDefault(c => c.Payment.PaymentMethodId == pmi);
//if it doesnt, add it and assign a new Zcashlike address to the system if a balance is still due //if it doesnt, add it and assign a new Zcashlike address to the system if a balance is still due
if (alreadyExistingPaymentThatMatches.Payment == null) if (alreadyExistingPaymentThatMatches == null)
{ {
var payment = await _paymentService.AddPayment(paymentData, [txId]); var payment = await _paymentService.AddPayment(paymentData, [txId]);
if (payment != null) if (payment != null)
@ -353,9 +319,9 @@ namespace BTCPayServer.Services.Altcoins.Zcash.Services
else else
{ {
//else update it with the new data //else update it with the new data
alreadyExistingPaymentThatMatches.PaymentData = details; alreadyExistingPaymentThatMatches.Status = status;
alreadyExistingPaymentThatMatches.Payment.Details = JToken.FromObject(paymentData, handler.Serializer); alreadyExistingPaymentThatMatches.Details = JToken.FromObject(details, handler.Serializer);
paymentsToUpdate.Add((alreadyExistingPaymentThatMatches.Payment, invoice)); paymentsToUpdate.Add((alreadyExistingPaymentThatMatches, invoice));
} }
} }

View File

@ -93,7 +93,6 @@ namespace BTCPayServer.Services.Invoices
{ {
var dbPayment = dbPayments[payment.Id]; var dbPayment = dbPayments[payment.Id];
var invBlob = _invoiceRepository.ToEntity(dbPayment.InvoiceData); var invBlob = _invoiceRepository.ToEntity(dbPayment.InvoiceData);
var dbPaymentEntity = dbPayment.GetBlob();
var wasConfirmed = dbPayment.Status is PaymentStatus.Settled; var wasConfirmed = dbPayment.Status is PaymentStatus.Settled;
if (!wasConfirmed && payment.Status is PaymentStatus.Settled) if (!wasConfirmed && payment.Status is PaymentStatus.Settled)
{ {