Refactor invoice entity to not have to inject the NetworkProvider (#858)

This commit is contained in:
Nicolas Dorier 2019-05-24 22:22:38 +09:00 committed by GitHub
parent 15dc0d60db
commit 512ee16620
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 59 additions and 51 deletions

View File

@ -201,7 +201,7 @@ namespace BTCPayServer.Tests
entity.SetPaymentMethod(new PaymentMethod() { CryptoCode = "BTC", Rate = 5000, NextNetworkFee = Money.Coins(0.1m) });
entity.ProductInformation = new ProductInformation() { Price = 5000 };
var paymentMethod = entity.GetPaymentMethods(null).TryGet("BTC", PaymentTypes.BTCLike);
var paymentMethod = entity.GetPaymentMethods().TryGet("BTC", PaymentTypes.BTCLike);
var accounting = paymentMethod.Calculate();
Assert.Equal(Money.Coins(1.1m), accounting.Due);
Assert.Equal(Money.Coins(1.1m), accounting.TotalDue);
@ -364,7 +364,7 @@ namespace BTCPayServer.Tests
entity.PaymentTolerance = 0;
var paymentMethod = entity.GetPaymentMethods(null).TryGet("BTC", PaymentTypes.BTCLike);
var paymentMethod = entity.GetPaymentMethods().TryGet("BTC", PaymentTypes.BTCLike);
var accounting = paymentMethod.Calculate();
Assert.Equal(Money.Coins(1.1m), accounting.Due);
Assert.Equal(Money.Coins(1.1m), accounting.TotalDue);

View File

@ -51,7 +51,7 @@ namespace BTCPayServer.Controllers
})).FirstOrDefault();
if (invoice == null)
throw new BitpayHttpException(404, "Object not found");
var resp = invoice.EntityToDTO(_NetworkProvider);
var resp = invoice.EntityToDTO();
return new DataWrapper<InvoiceResponse>(resp);
}
[HttpGet]
@ -82,7 +82,7 @@ namespace BTCPayServer.Controllers
};
var entities = (await _InvoiceRepository.GetInvoices(query))
.Select((o) => o.EntityToDTO(_NetworkProvider)).ToArray();
.Select((o) => o.EntityToDTO()).ToArray();
return DataWrapper.Create(entities);
}

View File

@ -96,7 +96,7 @@ namespace BTCPayServer.Controllers
{
var model = new InvoiceDetailsModel();
foreach (var data in invoice.GetPaymentMethods(null))
foreach (var data in invoice.GetPaymentMethods())
{
var accounting = data.Calculate();
var paymentMethodId = data.GetId();
@ -248,18 +248,18 @@ namespace BTCPayServer.Controllers
{
if (!isDefaultPaymentId)
return null;
var paymentMethodTemp = invoice.GetPaymentMethods(_NetworkProvider)
var paymentMethodTemp = invoice.GetPaymentMethods()
.Where(c => paymentMethodId.CryptoCode == c.GetId().CryptoCode)
.FirstOrDefault();
if (paymentMethodTemp == null)
paymentMethodTemp = invoice.GetPaymentMethods(_NetworkProvider).First();
paymentMethodTemp = invoice.GetPaymentMethods().First();
network = paymentMethodTemp.Network;
paymentMethodId = paymentMethodTemp.GetId();
}
var paymentMethod = invoice.GetPaymentMethod(paymentMethodId, _NetworkProvider);
var paymentMethodDetails = paymentMethod.GetPaymentMethodDetails();
var dto = invoice.EntityToDTO(_NetworkProvider);
var dto = invoice.EntityToDTO();
var cryptoInfo = dto.CryptoInfo.First(o => o.GetpaymentMethodId() == paymentMethodId);
var storeBlob = store.GetStoreBlob();
var currency = invoice.ProductInformation.Currency;
@ -332,7 +332,7 @@ namespace BTCPayServer.Controllers
CoinSwitchMerchantId = coinswitch?.MerchantId,
CoinSwitchMode = coinswitch?.Mode,
StoreId = store.Id,
AvailableCryptos = invoice.GetPaymentMethods(_NetworkProvider)
AvailableCryptos = invoice.GetPaymentMethods()
.Where(i => i.Network != null)
.Select(kv => new PaymentModel.AvailableCrypto()
{

View File

@ -75,7 +75,8 @@ namespace BTCPayServer.Controllers
var entity = new InvoiceEntity
{
Version = InvoiceEntity.Lastest_Version,
InvoiceTime = DateTimeOffset.UtcNow
InvoiceTime = DateTimeOffset.UtcNow,
Networks = _NetworkProvider
};
var getAppsTaggingStore = _InvoiceRepository.GetAppsTaggingStore(store.Id);
@ -208,7 +209,7 @@ namespace BTCPayServer.Controllers
using (logs.Measure("Saving invoice"))
{
entity = await _InvoiceRepository.CreateInvoiceAsync(store.Id, entity, _NetworkProvider);
entity = await _InvoiceRepository.CreateInvoiceAsync(store.Id, entity);
}
_ = Task.Run(async () =>
{
@ -223,7 +224,7 @@ namespace BTCPayServer.Controllers
await _InvoiceRepository.AddInvoiceLogs(entity.Id, logs);
});
_EventAggregator.Publish(new Events.InvoiceEvent(entity, 1001, InvoiceEvent.Created));
var resp = entity.EntityToDTO(_NetworkProvider);
var resp = entity.EntityToDTO();
return new DataWrapper<InvoiceResponse>(resp) { Facade = "pos/invoice" };
}

View File

@ -64,7 +64,7 @@ namespace BTCPayServer.HostedServices
void Notify(InvoiceEntity invoice, InvoiceEvent invoiceEvent, bool extendedNotification)
{
var dto = invoice.EntityToDTO(_NetworkProvider);
var dto = invoice.EntityToDTO();
var notification = new InvoicePaymentNotificationEventWrapper()
{
Data = new InvoicePaymentNotification()

View File

@ -74,7 +74,7 @@ namespace BTCPayServer.HostedServices
}
var payments = invoice.GetPayments().Where(p => p.Accounted).ToArray();
var allPaymentMethods = invoice.GetPaymentMethods(_NetworkProvider);
var allPaymentMethods = invoice.GetPaymentMethods();
var paymentMethod = GetNearestClearedPayment(allPaymentMethods, out var accounting, _NetworkProvider);
if (paymentMethod == null)
return;

View File

@ -74,7 +74,7 @@ namespace BTCPayServer.Hosting
var dbpath = Path.Combine(opts.DataDir, "InvoiceDB");
if (!Directory.Exists(dbpath))
Directory.CreateDirectory(dbpath);
return new InvoiceRepository(dbContext, dbpath);
return new InvoiceRepository(dbContext, dbpath, o.GetRequiredService<BTCPayNetworkProvider>());
});
services.AddSingleton<BTCPayServerEnvironment>();
services.TryAddSingleton<TokenRepository>();

View File

@ -345,7 +345,7 @@ namespace BTCPayServer.Payments.Bitcoin
private DerivationStrategyBase GetDerivationStrategy(InvoiceEntity invoice, BTCPayNetwork network)
{
return invoice.GetSupportedPaymentMethod<DerivationSchemeSettings>(new PaymentMethodId(network.CryptoCode, PaymentTypes.BTCLike), _ExplorerClients.NetworkProviders)
return invoice.GetSupportedPaymentMethod<DerivationSchemeSettings>(new PaymentMethodId(network.CryptoCode, PaymentTypes.BTCLike))
.Select(d => d.AccountDerivation)
.FirstOrDefault();
}

View File

@ -95,13 +95,13 @@ namespace BTCPayServer.Payments.Lightning
{
var listenedInvoices = new List<ListenedInvoice>();
var invoice = await _InvoiceRepository.GetInvoice(invoiceId);
foreach (var paymentMethod in invoice.GetPaymentMethods(_NetworkProvider)
foreach (var paymentMethod in invoice.GetPaymentMethods()
.Where(c => c.GetId().PaymentType == PaymentTypes.LightningLike))
{
var lightningMethod = paymentMethod.GetPaymentMethodDetails() as LightningLikePaymentMethodDetails;
if (lightningMethod == null)
continue;
var lightningSupportedMethod = invoice.GetSupportedPaymentMethod<LightningSupportedPaymentMethod>(_NetworkProvider)
var lightningSupportedMethod = invoice.GetSupportedPaymentMethod<LightningSupportedPaymentMethod>()
.FirstOrDefault(c => c.CryptoCode == paymentMethod.GetId().CryptoCode);
if (lightningSupportedMethod == null)
continue;

View File

@ -113,6 +113,8 @@ namespace BTCPayServer.Services.Invoices
}
public class InvoiceEntity
{
[JsonIgnore]
public BTCPayNetworkProvider Networks { get; set; }
public const int InternalTagSupport_Version = 1;
public const int Lastest_Version = 1;
public int Version { get; set; }
@ -190,18 +192,18 @@ namespace BTCPayServer.Services.Invoices
get;
set;
}
public IEnumerable<T> GetSupportedPaymentMethod<T>(PaymentMethodId paymentMethodId, BTCPayNetworkProvider networks) where T : ISupportedPaymentMethod
public IEnumerable<T> GetSupportedPaymentMethod<T>(PaymentMethodId paymentMethodId) where T : ISupportedPaymentMethod
{
return
GetSupportedPaymentMethod(networks)
GetSupportedPaymentMethod()
.Where(p => paymentMethodId == null || p.PaymentId == paymentMethodId)
.OfType<T>();
}
public IEnumerable<T> GetSupportedPaymentMethod<T>(BTCPayNetworkProvider networks) where T : ISupportedPaymentMethod
public IEnumerable<T> GetSupportedPaymentMethod<T>() where T : ISupportedPaymentMethod
{
return GetSupportedPaymentMethod<T>(null, networks);
return GetSupportedPaymentMethod<T>(null);
}
public IEnumerable<ISupportedPaymentMethod> GetSupportedPaymentMethod(BTCPayNetworkProvider networks)
public IEnumerable<ISupportedPaymentMethod> GetSupportedPaymentMethod()
{
#pragma warning disable CS0618
bool btcReturned = false;
@ -211,10 +213,10 @@ namespace BTCPayServer.Services.Invoices
foreach (var strat in strategies.Properties())
{
var paymentMethodId = PaymentMethodId.Parse(strat.Name);
var network = networks.GetNetwork(paymentMethodId.CryptoCode);
var network = Networks.GetNetwork(paymentMethodId.CryptoCode);
if (network != null)
{
if (network == networks.BTC && paymentMethodId.PaymentType == PaymentTypes.BTCLike)
if (network == Networks.BTC && paymentMethodId.PaymentType == PaymentTypes.BTCLike)
btcReturned = true;
yield return PaymentMethodExtensions.Deserialize(paymentMethodId, strat.Value, network);
}
@ -223,9 +225,9 @@ namespace BTCPayServer.Services.Invoices
if (!btcReturned && !string.IsNullOrEmpty(DerivationStrategy))
{
if (networks.BTC != null)
if (Networks.BTC != null)
{
yield return BTCPayServer.DerivationSchemeSettings.Parse(DerivationStrategy, networks.BTC);
yield return BTCPayServer.DerivationSchemeSettings.Parse(DerivationStrategy, Networks.BTC);
}
}
#pragma warning restore CS0618
@ -362,7 +364,7 @@ namespace BTCPayServer.Services.Invoices
return DateTimeOffset.UtcNow > ExpirationTime;
}
public InvoiceResponse EntityToDTO(BTCPayNetworkProvider networkProvider)
public InvoiceResponse EntityToDTO()
{
ServerUrl = ServerUrl ?? "";
InvoiceResponse dto = new InvoiceResponse
@ -391,7 +393,7 @@ namespace BTCPayServer.Services.Invoices
dto.Url = ServerUrl.WithTrailingSlash() + $"invoice?id=" + Id;
dto.CryptoInfo = new List<NBitpayClient.InvoiceCryptoInfo>();
dto.MinerFees = new Dictionary<string, MinerFeeInfo>();
foreach (var info in this.GetPaymentMethods(networkProvider))
foreach (var info in this.GetPaymentMethods())
{
var accounting = info.Calculate();
var cryptoInfo = new NBitpayClient.InvoiceCryptoInfo();
@ -510,13 +512,13 @@ namespace BTCPayServer.Services.Invoices
internal bool Support(PaymentMethodId paymentMethodId)
{
var rates = GetPaymentMethods(null);
var rates = GetPaymentMethods();
return rates.TryGet(paymentMethodId) != null;
}
public PaymentMethod GetPaymentMethod(PaymentMethodId paymentMethodId, BTCPayNetworkProvider networkProvider)
{
GetPaymentMethods(networkProvider).TryGetValue(paymentMethodId, out var data);
GetPaymentMethods().TryGetValue(paymentMethodId, out var data);
return data;
}
public PaymentMethod GetPaymentMethod(BTCPayNetwork network, PaymentTypes paymentType, BTCPayNetworkProvider networkProvider)
@ -524,7 +526,7 @@ namespace BTCPayServer.Services.Invoices
return GetPaymentMethod(new PaymentMethodId(network.CryptoCode, paymentType), networkProvider);
}
public PaymentMethodDictionary GetPaymentMethods(BTCPayNetworkProvider networkProvider)
public PaymentMethodDictionary GetPaymentMethods()
{
PaymentMethodDictionary paymentMethods = new PaymentMethodDictionary();
var serializer = new Serializer(Dummy);
@ -538,8 +540,8 @@ namespace BTCPayServer.Services.Invoices
r.CryptoCode = paymentMethodId.CryptoCode;
r.PaymentType = paymentMethodId.PaymentType.ToString();
r.ParentEntity = this;
r.Network = networkProvider?.GetNetwork(r.CryptoCode);
if (r.Network != null || networkProvider == null)
r.Network = Networks?.GetNetwork(r.CryptoCode);
if (r.Network != null || Networks == null)
paymentMethods.Add(r);
}
}
@ -551,7 +553,7 @@ namespace BTCPayServer.Services.Invoices
public void SetPaymentMethod(PaymentMethod paymentMethod)
{
var dict = GetPaymentMethods(null);
var dict = GetPaymentMethods();
dict.AddOrReplace(paymentMethod);
SetPaymentMethods(dict);
}
@ -830,7 +832,7 @@ namespace BTCPayServer.Services.Invoices
public PaymentMethodAccounting Calculate(Func<PaymentEntity, bool> paymentPredicate = null)
{
paymentPredicate = paymentPredicate ?? new Func<PaymentEntity, bool>((p) => true);
var paymentMethods = ParentEntity.GetPaymentMethods(null);
var paymentMethods = ParentEntity.GetPaymentMethods();
var totalDue = ParentEntity.ProductInformation.Price / Rate;
var paid = 0m;

View File

@ -37,8 +37,9 @@ namespace BTCPayServer.Services.Invoices
}
private ApplicationDbContextFactory _ContextFactory;
private readonly BTCPayNetworkProvider _Networks;
private CustomThreadPool _IndexerThread;
public InvoiceRepository(ApplicationDbContextFactory contextFactory, string dbreezePath)
public InvoiceRepository(ApplicationDbContextFactory contextFactory, string dbreezePath, BTCPayNetworkProvider networks)
{
int retryCount = 0;
retry:
@ -49,6 +50,7 @@ retry:
catch when (retryCount++ < 5) { goto retry; }
_IndexerThread = new CustomThreadPool(1, "Invoice Indexer");
_ContextFactory = contextFactory;
_Networks = networks;
}
public async Task<bool> RemovePendingInvoice(string invoiceId)
@ -118,10 +120,11 @@ retry:
}
}
public async Task<InvoiceEntity> CreateInvoiceAsync(string storeId, InvoiceEntity invoice, BTCPayNetworkProvider networkProvider)
public async Task<InvoiceEntity> CreateInvoiceAsync(string storeId, InvoiceEntity invoice)
{
List<string> textSearch = new List<string>();
invoice = Clone(invoice, null);
invoice = NBitcoin.JsonConverters.Serializer.ToObject<InvoiceEntity>(ToString(invoice, null), null);
invoice.Networks = _Networks;
invoice.Id = Encoders.Base58.EncodeData(RandomUtils.GetBytes(16));
#pragma warning disable CS0618
invoice.Payments = new List<PaymentEntity>();
@ -143,7 +146,7 @@ retry:
CustomerEmail = invoice.RefundMail
});
foreach (var paymentMethod in invoice.GetPaymentMethods(networkProvider))
foreach (var paymentMethod in invoice.GetPaymentMethods())
{
if (paymentMethod.Network == null)
throw new InvalidOperationException("CryptoCode unsupported");
@ -217,7 +220,7 @@ retry:
if (invoice == null)
return false;
var invoiceEntity = ToObject<InvoiceEntity>(invoice.Blob, network.NBitcoinNetwork);
var invoiceEntity = ToObject(invoice.Blob);
var currencyData = invoiceEntity.GetPaymentMethod(network, paymentMethod.GetPaymentType(), null);
if (currencyData == null)
return false;
@ -278,7 +281,7 @@ retry:
private static void MarkUnassigned(string invoiceId, InvoiceEntity entity, ApplicationDbContext context, PaymentMethodId paymentMethodId)
{
foreach (var address in entity.GetPaymentMethods(null))
foreach (var address in entity.GetPaymentMethods())
{
if (paymentMethodId != null && paymentMethodId != address.GetId())
continue;
@ -298,7 +301,7 @@ retry:
var invoiceData = await context.FindAsync<Data.InvoiceData>(invoiceId).ConfigureAwait(false);
if (invoiceData == null)
return;
var invoiceEntity = ToObject<InvoiceEntity>(invoiceData.Blob, null);
var invoiceEntity = ToObject(invoiceData.Blob);
MarkUnassigned(invoiceId, invoiceEntity, context, null);
try
{
@ -393,7 +396,7 @@ retry:
private InvoiceEntity ToEntity(Data.InvoiceData invoice)
{
var entity = ToObject<InvoiceEntity>(invoice.Blob, null);
var entity = ToObject(invoice.Blob);
PaymentMethodDictionary paymentMethods = null;
#pragma warning disable CS0618
entity.Payments = invoice.Payments.Select(p =>
@ -406,7 +409,7 @@ retry:
if (paymentEntity.Version == 0)
{
if (paymentMethods == null)
paymentMethods = entity.GetPaymentMethods(null);
paymentMethods = entity.GetPaymentMethods();
var paymentMethodDetails = paymentMethods.TryGet(paymentEntity.GetPaymentMethodId())?.GetPaymentMethodDetails();
if (paymentMethodDetails != null) // == null should never happen, but we never know.
paymentEntity.NetworkFee = paymentMethodDetails.GetNextNetworkFee();
@ -604,7 +607,7 @@ retry:
var invoice = context.Invoices.Find(invoiceId);
if (invoice == null)
return null;
InvoiceEntity invoiceEntity = ToObject<InvoiceEntity>(invoice.Blob, network.NBitcoinNetwork);
InvoiceEntity invoiceEntity = ToObject(invoice.Blob);
PaymentMethod paymentMethod = invoiceEntity.GetPaymentMethod(new PaymentMethodId(network.CryptoCode, paymentData.GetPaymentType()), null);
IPaymentMethodDetails paymentMethodDetails = paymentMethod.GetPaymentMethodDetails();
PaymentEntity entity = new PaymentEntity
@ -669,21 +672,23 @@ retry:
}
}
private InvoiceEntity ToObject(byte[] value)
{
var entity = NBitcoin.JsonConverters.Serializer.ToObject<InvoiceEntity>(ZipUtils.Unzip(value), null);
entity.Networks = _Networks;
return entity;
}
private T ToObject<T>(byte[] value, Network network)
{
return NBitcoin.JsonConverters.Serializer.ToObject<T>(ZipUtils.Unzip(value), network);
}
private byte[] ToBytes<T>(T obj, Network network)
{
return ZipUtils.Zip(NBitcoin.JsonConverters.Serializer.ToString(obj, network));
}
private T Clone<T>(T invoice, Network network)
{
return NBitcoin.JsonConverters.Serializer.ToObject<T>(ToString(invoice, network), network);
}
private string ToString<T>(T data, Network network)
{
return NBitcoin.JsonConverters.Serializer.ToString(data, network);