mirror of
https://github.com/btcpayserver/btcpayserver.git
synced 2025-02-22 14:22:40 +01:00
commit
9a54445785
6 changed files with 48 additions and 52 deletions
|
@ -14,7 +14,6 @@ namespace BTCPayServer.Services.Altcoins.Monero.RPC.Models
|
|||
[JsonProperty("amount")] public long Amount { get; set; }
|
||||
[JsonProperty("confirmations")] public long Confirmations { get; set; }
|
||||
[JsonProperty("double_spend_seen")] public bool DoubleSpendSeen { get; set; }
|
||||
[JsonProperty("fee")] public long Fee { get; set; }
|
||||
[JsonProperty("height")] public long Height { get; set; }
|
||||
[JsonProperty("note")] public string Note { get; set; }
|
||||
[JsonProperty("payment_id")] public string PaymentId { get; set; }
|
||||
|
|
|
@ -18,7 +18,6 @@ namespace BTCPayServer.Services.Altcoins.Monero.RPC.Models
|
|||
[JsonProperty("amount")] public long Amount { get; set; }
|
||||
[JsonProperty("confirmations")] public long Confirmations { get; set; }
|
||||
[JsonProperty("double_spend_seen")] public bool DoubleSpendSeen { get; set; }
|
||||
[JsonProperty("fee")] public long Fee { get; set; }
|
||||
[JsonProperty("height")] public long Height { get; set; }
|
||||
[JsonProperty("note")] public string Note { get; set; }
|
||||
[JsonProperty("payment_id")] public string PaymentId { get; set; }
|
||||
|
|
|
@ -3,26 +3,26 @@ version: "3"
|
|||
services:
|
||||
|
||||
monerod:
|
||||
image: kukks/docker-monero:test
|
||||
image: btcpayserver/monero:0.15.0.1-amd64
|
||||
restart: unless-stopped
|
||||
container_name: xmr_monerod
|
||||
entrypoint: monerod --fixed-difficulty 100 --rpc-bind-ip=0.0.0.0 --confirm-external-bind --rpc-bind-port=18081 --non-interactive --block-notify="/scripts/notifier.sh https://127.0.0.1:14142/monerolikedaemoncallback/block?cryptoCode=xmr&hash=%s" --testnet --no-igd --hide-my-port --no-sync --offline
|
||||
entrypoint: sleep 999999
|
||||
# entrypoint: monerod --fixed-difficulty 200 --rpc-bind-ip=0.0.0.0 --confirm-external-bind --rpc-bind-port=18081 --block-notify="/bin/sh ./scripts/notifier.sh -k -X GET https://host.docker.internal:14142/monerolikedaemoncallback/block?cryptoCode=xmr&hash=%s" --testnet --no-igd --hide-my-port --offline
|
||||
volumes:
|
||||
- "monero_data:/home/monero/.bitmonero"
|
||||
ports:
|
||||
- "18081:18081"
|
||||
monero_wallet:
|
||||
image: kukks/docker-monero:test
|
||||
image: btcpayserver/monero:0.15.0.1-amd64
|
||||
restart: unless-stopped
|
||||
container_name: xmr_wallet_rpc
|
||||
entrypoint: monero-wallet-rpc --testnet --rpc-bind-ip=0.0.0.0 --disable-rpc-login --confirm-external-bind --rpc-bind-port=18082 --non-interactive --trusted-daemon --daemon-address=127.0.0.1:18081 --wallet-file=/wallet/wallet.keys --tx-notify="/scripts/notifier.sh https://127.0.0.1:14142/monerolikedaemoncallback/tx?cryptoCode=xmr&hash=%s"
|
||||
entrypoint: monero-wallet-rpc --testnet --rpc-bind-ip=0.0.0.0 --disable-rpc-login --confirm-external-bind --rpc-bind-port=18082 --non-interactive --trusted-daemon --daemon-address=monerod:18081 --wallet-file=/wallet/wallet.keys --password-file=/wallet/password --tx-notify="/bin/sh ./scripts/notifier.sh -k -X GET https://host.docker.internal:14142/monerolikedaemoncallback/tx?cryptoCode=xmr&hash=%s"
|
||||
ports:
|
||||
- "18082:18082"
|
||||
volumes:
|
||||
- "monero_wallet:/wallet"
|
||||
- "./monero_wallet:/wallet"
|
||||
depends_on:
|
||||
- monerod
|
||||
|
||||
volumes:
|
||||
monero_data:
|
||||
monero_wallet:
|
||||
|
|
|
@ -4,7 +4,6 @@ using System.Collections.Generic;
|
|||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using BTCPayServer.Data;
|
||||
using BTCPayServer.Events;
|
||||
using BTCPayServer.Services.Altcoins.Monero.Configuration;
|
||||
using BTCPayServer.Services.Altcoins.Monero.Payments;
|
||||
|
@ -28,8 +27,7 @@ namespace BTCPayServer.Services.Altcoins.Monero.Services
|
|||
private readonly BTCPayNetworkProvider _networkProvider;
|
||||
private readonly ILogger<MoneroListener> _logger;
|
||||
private CompositeDisposable leases = new CompositeDisposable();
|
||||
|
||||
|
||||
private Queue<Func<CancellationToken, Task>> taskQueue = new Queue<Func<CancellationToken, Task>>();
|
||||
private CancellationTokenSource _Cts;
|
||||
|
||||
public MoneroListener(InvoiceRepository invoiceRepository,
|
||||
|
@ -68,10 +66,34 @@ namespace BTCPayServer.Services.Altcoins.Monero.Services
|
|||
_logger.LogInformation($"{e.CryptoCode} just became unavailable");
|
||||
}
|
||||
}));
|
||||
|
||||
_ = WorkThroughQueue(_Cts.Token);
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
private async Task WorkThroughQueue(CancellationToken token)
|
||||
{
|
||||
while (!token.IsCancellationRequested)
|
||||
{
|
||||
if (taskQueue.TryDequeue(out var t))
|
||||
{
|
||||
try
|
||||
{
|
||||
|
||||
await t.Invoke(token);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
||||
_logger.LogError($"error with queue item",e);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
await Task.Delay(TimeSpan.FromSeconds(1), token);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void OnMoneroEvent(MoneroEvent obj)
|
||||
{
|
||||
if (!_moneroRpcProvider.IsAvailable(obj.CryptoCode))
|
||||
|
@ -81,12 +103,12 @@ namespace BTCPayServer.Services.Altcoins.Monero.Services
|
|||
|
||||
if (!string.IsNullOrEmpty(obj.BlockHash))
|
||||
{
|
||||
OnNewBlock(obj.CryptoCode);
|
||||
taskQueue.Enqueue(token => OnNewBlock(obj.CryptoCode));
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(obj.TransactionHash))
|
||||
{
|
||||
_ = OnTransactionUpdated(obj.CryptoCode, obj.TransactionHash);
|
||||
taskQueue.Enqueue(token => OnTransactionUpdated(obj.CryptoCode, obj.TransactionHash));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -209,7 +231,7 @@ namespace BTCPayServer.Services.Altcoins.Monero.Services
|
|||
}
|
||||
|
||||
|
||||
return HandlePaymnetData(cryptoCode, transfer.Address, transfer.Amount, transfer.SubaddrIndex.Major,
|
||||
return HandlePaymentData(cryptoCode, transfer.Address, transfer.Amount, transfer.SubaddrIndex.Major,
|
||||
transfer.SubaddrIndex.Minor, transfer.Txid, transfer.Confirmations, transfer.Height, invoice,
|
||||
updatedPaymentEntities);
|
||||
}));
|
||||
|
@ -235,9 +257,9 @@ namespace BTCPayServer.Services.Altcoins.Monero.Services
|
|||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
private void OnNewBlock(string cryptoCode)
|
||||
private async Task OnNewBlock(string cryptoCode)
|
||||
{
|
||||
_ = UpdateAnyPendingMoneroLikePayment(cryptoCode);
|
||||
await UpdateAnyPendingMoneroLikePayment(cryptoCode);
|
||||
_eventAggregator.Publish(new NewBlockEvent() {CryptoCode = cryptoCode});
|
||||
}
|
||||
|
||||
|
@ -250,8 +272,7 @@ namespace BTCPayServer.Services.Altcoins.Monero.Services
|
|||
new GetTransferByTransactionIdRequest() {TransactionId = transactionHash});
|
||||
|
||||
var paymentsToUpdate = new BlockingCollection<(PaymentEntity Payment, InvoiceEntity invoice)>();
|
||||
|
||||
|
||||
|
||||
//group all destinations of the tx together and loop through the sets
|
||||
foreach (var destination in transfer.Transfers.GroupBy(destination => destination.Address))
|
||||
{
|
||||
|
@ -265,7 +286,7 @@ namespace BTCPayServer.Services.Altcoins.Monero.Services
|
|||
|
||||
var index = destination.First().SubaddrIndex;
|
||||
|
||||
await HandlePaymnetData(cryptoCode,
|
||||
await HandlePaymentData(cryptoCode,
|
||||
destination.Key,
|
||||
destination.Sum(destination1 => destination1.Amount),
|
||||
index.Major,
|
||||
|
@ -289,7 +310,7 @@ namespace BTCPayServer.Services.Altcoins.Monero.Services
|
|||
}
|
||||
}
|
||||
|
||||
private async Task HandlePaymnetData(string cryptoCode, string address, long totalAmount, long subaccountIndex,
|
||||
private async Task HandlePaymentData(string cryptoCode, string address, long totalAmount, long subaccountIndex,
|
||||
long subaddressIndex,
|
||||
string txId, long confirmations, long blockHeight, InvoiceEntity invoice,
|
||||
BlockingCollection<(PaymentEntity Payment, InvoiceEntity invoice)> paymentsToUpdate)
|
||||
|
@ -331,26 +352,18 @@ namespace BTCPayServer.Services.Altcoins.Monero.Services
|
|||
|
||||
private async Task UpdateAnyPendingMoneroLikePayment(string cryptoCode)
|
||||
{
|
||||
var invoiceIds =
|
||||
await GetPendingInvoicesWithPaymentMethodOption(new PaymentMethodId(cryptoCode,
|
||||
MoneroPaymentType.Instance));
|
||||
var invoiceIds =await _invoiceRepository.GetPendingInvoices();
|
||||
if (!invoiceIds.Any())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var invoices = await _invoiceRepository.GetInvoices(new InvoiceQuery() {InvoiceId = invoiceIds});
|
||||
invoices = invoices.Where(entity => entity.GetPaymentMethod(new PaymentMethodId(cryptoCode, MoneroPaymentType.Instance)) != null).ToArray();
|
||||
_logger.LogInformation($"Updating pending payments for {cryptoCode} in {string.Join(',', invoiceIds)}");
|
||||
await UpdatePaymentStates(cryptoCode, invoices);
|
||||
}
|
||||
|
||||
private async Task<string[]> GetPendingInvoicesWithPaymentMethodOption(PaymentMethodId paymentMethodId)
|
||||
{
|
||||
return await _invoiceRepository.GetPendingInvoices(pendingInvoice =>
|
||||
pendingInvoice.Where(data => data.InvoiceData.AddressInvoices.Any(invoiceData =>
|
||||
invoiceData.GetpaymentMethodId() != null && invoiceData.GetpaymentMethodId() == paymentMethodId)));
|
||||
}
|
||||
|
||||
private IEnumerable<PaymentEntity> GetAllMoneroLikePayments(InvoiceEntity invoice, string cryptoCode)
|
||||
{
|
||||
return invoice.GetPayments()
|
||||
|
|
|
@ -14,6 +14,7 @@ namespace BTCPayServer.Services.Altcoins.Monero.Services
|
|||
{
|
||||
private readonly MoneroLikeConfiguration _moneroLikeConfiguration;
|
||||
private readonly EventAggregator _eventAggregator;
|
||||
private readonly BTCPayServerEnvironment _btcPayServerEnvironment;
|
||||
public ImmutableDictionary<string, JsonRpcClient> DaemonRpcClients;
|
||||
public ImmutableDictionary<string, JsonRpcClient> WalletRpcClients;
|
||||
|
||||
|
@ -22,10 +23,11 @@ namespace BTCPayServer.Services.Altcoins.Monero.Services
|
|||
|
||||
public ConcurrentDictionary<string, MoneroLikeSummary> Summaries => _summaries;
|
||||
|
||||
public MoneroRPCProvider(MoneroLikeConfiguration moneroLikeConfiguration, EventAggregator eventAggregator, IHttpClientFactory httpClientFactory)
|
||||
public MoneroRPCProvider(MoneroLikeConfiguration moneroLikeConfiguration, EventAggregator eventAggregator, IHttpClientFactory httpClientFactory, BTCPayServerEnvironment btcPayServerEnvironment)
|
||||
{
|
||||
_moneroLikeConfiguration = moneroLikeConfiguration;
|
||||
_eventAggregator = eventAggregator;
|
||||
_btcPayServerEnvironment = btcPayServerEnvironment;
|
||||
DaemonRpcClients =
|
||||
_moneroLikeConfiguration.MoneroLikeConfigurationItems.ToImmutableDictionary(pair => pair.Key,
|
||||
pair => new JsonRpcClient(pair.Value.DaemonRpcUri, "", "", httpClientFactory.CreateClient()));
|
||||
|
@ -61,8 +63,7 @@ namespace BTCPayServer.Services.Altcoins.Monero.Services
|
|||
await daemonRpcClient.SendCommandAsync<JsonRpcClient.NoRequestModel, SyncInfoResponse>("sync_info",
|
||||
JsonRpcClient.NoRequestModel.Instance);
|
||||
summary.TargetHeight = daemonResult.TargetHeight ?? daemonResult.Height;
|
||||
summary.Synced = !daemonResult.TargetHeight.HasValue ||
|
||||
(daemonResult.Height >= daemonResult.TargetHeight && daemonResult.TargetHeight > 0);
|
||||
summary.Synced = daemonResult.Height >= summary.TargetHeight && (summary.TargetHeight > 0 || _btcPayServerEnvironment.IsDevelopping);
|
||||
summary.CurrentHeight = daemonResult.Height;
|
||||
summary.UpdatedAt = DateTime.Now;
|
||||
summary.DaemonAvailable = true;
|
||||
|
|
|
@ -1,27 +1,16 @@
|
|||
using DBriize;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using NBitpayClient;
|
||||
using Newtonsoft.Json;
|
||||
using System.Linq;
|
||||
using NBitcoin;
|
||||
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Query;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure.Internal;
|
||||
using BTCPayServer.Models;
|
||||
using System.Threading.Tasks;
|
||||
using BTCPayServer.Data;
|
||||
using System.Globalization;
|
||||
using BTCPayServer.Models.InvoicingModels;
|
||||
using BTCPayServer.Logging;
|
||||
using BTCPayServer.Payments;
|
||||
using System.Data.Common;
|
||||
using NBitcoin.Altcoins;
|
||||
using NBitcoin.Altcoins.Elements;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Encoders = NBitcoin.DataEncoders.Encoders;
|
||||
|
||||
|
@ -99,16 +88,11 @@ retry:
|
|||
}
|
||||
}
|
||||
|
||||
public async Task<string[]> GetPendingInvoices(Func<IQueryable<PendingInvoiceData>, IQueryable<PendingInvoiceData>> filter = null )
|
||||
public async Task<string[]> GetPendingInvoices()
|
||||
{
|
||||
using (var ctx = _ContextFactory.CreateContext())
|
||||
{
|
||||
var queryable = ctx.PendingInvoices.AsQueryable();
|
||||
if (filter != null)
|
||||
{
|
||||
queryable = filter.Invoke(queryable);
|
||||
}
|
||||
return await queryable.Select(p => p.Id).ToArrayAsync();
|
||||
return await ctx.PendingInvoices.AsQueryable().Select(data => data.Id).ToArrayAsync();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue