btcpayserver/BTCPayServer/Services/Altcoins/Monero/Payments/MoneroLikePaymentMethodHandler.cs

134 lines
5.8 KiB
C#
Raw Normal View History

#if ALTCOINS
2019-09-30 10:32:43 +02:00
using System;
using System.Collections.Generic;
2019-11-02 08:41:48 +01:00
using System.Globalization;
2019-09-30 10:32:43 +02:00
using System.Linq;
using System.Threading.Tasks;
using AngleSharp.Dom;
using BTCPayServer.Abstractions.Extensions;
using BTCPayServer.BIP78.Sender;
2019-09-30 10:32:43 +02:00
using BTCPayServer.Data;
2020-03-30 00:28:22 +09:00
using BTCPayServer.Logging;
2019-09-30 10:32:43 +02:00
using BTCPayServer.Models;
using BTCPayServer.Models.InvoicingModels;
2020-06-28 17:55:27 +09:00
using BTCPayServer.Payments;
using BTCPayServer.Plugins.Altcoins;
2020-06-28 17:55:27 +09:00
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.Altcoins.Zcash.Payments;
2019-09-30 10:32:43 +02:00
using BTCPayServer.Services.Invoices;
using BTCPayServer.Services.Rates;
using NBitcoin;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
2019-09-30 10:32:43 +02:00
namespace BTCPayServer.Services.Altcoins.Monero.Payments
2019-09-30 10:32:43 +02:00
{
public class MoneroLikePaymentMethodHandler : IPaymentMethodHandler
2019-09-30 10:32:43 +02:00
{
internal static PaymentType MoneroLike => MoneroPaymentType.Instance;
private readonly MoneroLikeSpecificBtcPayNetwork _network;
public MoneroLikeSpecificBtcPayNetwork Network => _network;
public JsonSerializer Serializer { get; }
2019-09-30 10:32:43 +02:00
private readonly MoneroRPCProvider _moneroRpcProvider;
public PaymentMethodId PaymentMethodId { get; }
public MoneroLikePaymentMethodHandler(MoneroLikeSpecificBtcPayNetwork network, MoneroRPCProvider moneroRpcProvider)
2019-09-30 10:32:43 +02:00
{
PaymentMethodId = MoneroLike.GetPaymentMethodId(network.CryptoCode);
_network = network;
Serializer = BlobSerializer.CreateSerializer().Serializer;
2019-09-30 10:32:43 +02:00
_moneroRpcProvider = moneroRpcProvider;
}
public Task BeforeFetchingRates(PaymentMethodContext context)
2019-09-30 10:32:43 +02:00
{
context.Prompt.Currency = _network.CryptoCode;
context.Prompt.Divisibility = _network.Divisibility;
if (context.Prompt.Activated)
{
var supportedPaymentMethod = ParsePaymentMethodConfig(context.PaymentMethodConfig);
var walletClient = _moneroRpcProvider.WalletRpcClients[_network.CryptoCode];
var daemonClient = _moneroRpcProvider.DaemonRpcClients[_network.CryptoCode];
context.State = new Prepare()
{
GetFeeRate = daemonClient.SendCommandAsync<GetFeeEstimateRequest, GetFeeEstimateResponse>("get_fee_estimate", new GetFeeEstimateRequest()),
ReserveAddress = s => walletClient.SendCommandAsync<CreateAddressRequest, CreateAddressResponse>("create_address", new CreateAddressRequest() { Label = $"btcpay invoice #{s}", AccountIndex = supportedPaymentMethod.AccountIndex }),
AccountIndex = supportedPaymentMethod.AccountIndex
};
}
return Task.CompletedTask;
}
2020-06-28 17:55:27 +09:00
public async Task ConfigurePrompt(PaymentMethodContext context)
{
if (!_moneroRpcProvider.IsAvailable(_network.CryptoCode))
2019-09-30 10:32:43 +02:00
throw new PaymentMethodUnavailableException($"Node or wallet not available");
var invoice = context.InvoiceEntity;
Prepare moneroPrepare = (Prepare)context.State;
2019-09-30 10:32:43 +02:00
var feeRatePerKb = await moneroPrepare.GetFeeRate;
var address = await moneroPrepare.ReserveAddress(invoice.Id);
var feeRatePerByte = feeRatePerKb.Fee / 1024;
var details = new MoneroLikeOnChainPaymentMethodDetails()
2019-09-30 10:32:43 +02:00
{
AccountIndex = moneroPrepare.AccountIndex,
2019-09-30 10:32:43 +02:00
AddressIndex = address.AddressIndex,
InvoiceSettledConfirmationThreshold = ParsePaymentMethodConfig(context.PaymentMethodConfig).InvoiceSettledConfirmationThreshold
2019-09-30 10:32:43 +02:00
};
context.Prompt.Destination = address.Address;
context.Prompt.PaymentMethodFee = MoneroMoney.Convert(feeRatePerByte * 100);
context.Prompt.Details = JObject.FromObject(details, Serializer);
2019-09-30 10:32:43 +02:00
}
private MoneroPaymentPromptDetails ParsePaymentMethodConfig(JToken config)
2019-09-30 10:32:43 +02:00
{
return config.ToObject<MoneroPaymentPromptDetails>(Serializer) ?? throw new FormatException($"Invalid {nameof(MoneroLikePaymentMethodHandler)}");
}
object IPaymentMethodHandler.ParsePaymentMethodConfig(JToken config)
{
return ParsePaymentMethodConfig(config);
2019-09-30 10:32:43 +02:00
}
2020-06-28 17:55:27 +09:00
2019-09-30 10:32:43 +02:00
class Prepare
{
public Task<GetFeeEstimateResponse> GetFeeRate;
public Func<string, Task<CreateAddressResponse>> ReserveAddress;
public long AccountIndex { get; internal set; }
2019-09-30 10:32:43 +02:00
}
public MoneroLikeOnChainPaymentMethodDetails ParsePaymentPromptDetails(Newtonsoft.Json.Linq.JToken details)
2019-09-30 10:32:43 +02:00
{
return ParsePaymentPromptDetails(details);
2019-09-30 10:32:43 +02:00
}
object IPaymentMethodHandler.ParsePaymentPromptDetails(Newtonsoft.Json.Linq.JToken details)
2019-09-30 10:32:43 +02:00
{
return details.ToObject<MoneroLikeOnChainPaymentMethodDetails>(Serializer);
2019-09-30 10:32:43 +02:00
}
public CheckoutUIPaymentMethodSettings GetCheckoutUISettings()
2019-09-30 10:32:43 +02:00
{
return new CheckoutUIPaymentMethodSettings()
{
ExtensionPartial = "Bitcoin/BitcoinLikeMethodCheckout",
CheckoutBodyVueComponentName = "BitcoinLikeMethodCheckout",
CheckoutHeaderVueComponentName = "BitcoinLikeMethodCheckoutHeader",
NoScriptPartialName = "Bitcoin/BitcoinLikeMethodCheckoutNoScript"
};
2019-09-30 10:32:43 +02:00
}
public MoneroLikePaymentData ParsePaymentDetails(JToken details)
2019-09-30 10:32:43 +02:00
{
return details.ToObject<MoneroLikePaymentData>(Serializer) ?? throw new FormatException($"Invalid {nameof(MoneroLikePaymentMethodHandler)}");
2019-09-30 10:32:43 +02:00
}
object IPaymentMethodHandler.ParsePaymentDetails(JToken details)
2019-09-30 10:32:43 +02:00
{
return ParsePaymentDetails(details);
2019-09-30 10:32:43 +02:00
}
}
}
2020-07-28 22:48:51 +02:00
#endif