#if ALTCOINS using System; using System.Collections.Generic; using System.Globalization; using System.Linq; using System.Threading.Tasks; using BTCPayServer.Data; using BTCPayServer.Logging; using BTCPayServer.Models; using BTCPayServer.Models.InvoicingModels; using BTCPayServer.Payments; using BTCPayServer.Rating; using BTCPayServer.Services.Altcoins.Monero.RPC.Models; using BTCPayServer.Services.Altcoins.Monero.Services; using BTCPayServer.Services.Altcoins.Monero.Utils; using BTCPayServer.Services.Invoices; using BTCPayServer.Services.Rates; using NBitcoin; namespace BTCPayServer.Services.Altcoins.Monero.Payments { public class MoneroLikePaymentMethodHandler : PaymentMethodHandlerBase { private readonly BTCPayNetworkProvider _networkProvider; private readonly MoneroRPCProvider _moneroRpcProvider; public MoneroLikePaymentMethodHandler(BTCPayNetworkProvider networkProvider, MoneroRPCProvider moneroRpcProvider) { _networkProvider = networkProvider; _moneroRpcProvider = moneroRpcProvider; } public override PaymentType PaymentType => MoneroPaymentType.Instance; public override async Task CreatePaymentMethodDetails(InvoiceLogs logs, MoneroSupportedPaymentMethod supportedPaymentMethod, PaymentMethod paymentMethod, StoreData store, MoneroLikeSpecificBtcPayNetwork network, object preparePaymentObject) { if (!_moneroRpcProvider.IsAvailable(network.CryptoCode)) throw new PaymentMethodUnavailableException($"Node or wallet not available"); var invoice = paymentMethod.ParentEntity; if (!(preparePaymentObject is Prepare moneroPrepare)) throw new ArgumentException(); var feeRatePerKb = await moneroPrepare.GetFeeRate; var address = await moneroPrepare.ReserveAddress(invoice.Id); var feeRatePerByte = feeRatePerKb.Fee / 1024; return new MoneroLikeOnChainPaymentMethodDetails() { NextNetworkFee = MoneroMoney.Convert(feeRatePerByte * 100), AccountIndex = supportedPaymentMethod.AccountIndex, AddressIndex = address.AddressIndex, DepositAddress = address.Address }; } public override object PreparePayment(MoneroSupportedPaymentMethod supportedPaymentMethod, StoreData store, BTCPayNetworkBase network) { var walletClient = _moneroRpcProvider.WalletRpcClients[supportedPaymentMethod.CryptoCode]; var daemonClient = _moneroRpcProvider.DaemonRpcClients[supportedPaymentMethod.CryptoCode]; return new Prepare() { GetFeeRate = daemonClient.SendCommandAsync("get_fee_estimate", new GetFeeEstimateRequest()), ReserveAddress = s => walletClient.SendCommandAsync("create_address", new CreateAddressRequest() { Label = $"btcpay invoice #{s}", AccountIndex = supportedPaymentMethod.AccountIndex }) }; } class Prepare { public Task GetFeeRate; public Func> ReserveAddress; } public override void PreparePaymentModel(PaymentModel model, InvoiceResponse invoiceResponse, StoreBlob storeBlob, IPaymentMethod paymentMethod) { var paymentMethodId = paymentMethod.GetId(); var cryptoInfo = invoiceResponse.CryptoInfo.First(o => o.GetpaymentMethodId() == paymentMethodId); var network = _networkProvider.GetNetwork(model.CryptoCode); model.PaymentMethodName = GetPaymentMethodName(network); model.CryptoImage = GetCryptoImage(network); model.InvoiceBitcoinUrl = MoneroPaymentType.Instance.GetPaymentLink(network, new MoneroLikeOnChainPaymentMethodDetails() { DepositAddress = cryptoInfo.Address }, cryptoInfo.Due, null); model.InvoiceBitcoinUrlQR = model.InvoiceBitcoinUrl; } public override string GetCryptoImage(PaymentMethodId paymentMethodId) { var network = _networkProvider.GetNetwork(paymentMethodId.CryptoCode); return GetCryptoImage(network); } public override string GetPaymentMethodName(PaymentMethodId paymentMethodId) { var network = _networkProvider.GetNetwork(paymentMethodId.CryptoCode); return GetPaymentMethodName(network); } public override IEnumerable GetSupportedPaymentMethods() { return _networkProvider.GetAll() .Where(network => network is MoneroLikeSpecificBtcPayNetwork) .Select(network => new PaymentMethodId(network.CryptoCode, PaymentType)); } private string GetCryptoImage(MoneroLikeSpecificBtcPayNetwork network) { return network.CryptoImagePath; } private string GetPaymentMethodName(MoneroLikeSpecificBtcPayNetwork network) { return $"{network.DisplayName}"; } } } #endif