public Task <decimal> GetRateAsync(string currency) { return(_MemoryCache.GetOrCreateAsync("CURR_" + currency, (ICacheEntry entry) => { entry.AbsoluteExpiration = DateTimeOffset.UtcNow + CacheSpan; return _Inner.GetRateAsync(currency); })); }
internal async Task <DataWrapper <InvoiceResponse> > CreateInvoiceCore(Invoice invoice, StoreData store, string serverUrl, double expiryMinutes = 15) { //TODO: expiryMinutes (time before a new invoice can become paid) and monitoringMinutes (time before a paid invoice becomes invalid) should be configurable at store level var derivationStrategy = store.DerivationStrategy; var entity = new InvoiceEntity { InvoiceTime = DateTimeOffset.UtcNow, DerivationStrategy = derivationStrategy ?? throw new BitpayHttpException(400, "This store has not configured the derivation strategy") }; var storeBlob = store.GetStoreBlob(_Network); Uri notificationUri = Uri.IsWellFormedUriString(invoice.NotificationURL, UriKind.Absolute) ? new Uri(invoice.NotificationURL, UriKind.Absolute) : null; if (notificationUri == null || (notificationUri.Scheme != "http" && notificationUri.Scheme != "https")) //TODO: Filer non routable addresses ? { notificationUri = null; } EmailAddressAttribute emailValidator = new EmailAddressAttribute(); entity.ExpirationTime = entity.InvoiceTime.AddMinutes(expiryMinutes); entity.MonitoringExpiration = entity.ExpirationTime + TimeSpan.FromMinutes(storeBlob.MonitoringExpiration); entity.OrderId = invoice.OrderId; entity.ServerUrl = serverUrl; entity.FullNotifications = invoice.FullNotifications; entity.NotificationURL = notificationUri?.AbsoluteUri; entity.BuyerInformation = Map <Invoice, BuyerInformation>(invoice); //Another way of passing buyer info to support FillBuyerInfo(invoice.Buyer, entity.BuyerInformation); if (entity?.BuyerInformation?.BuyerEmail != null) { if (!EmailValidator.IsEmail(entity.BuyerInformation.BuyerEmail)) { throw new BitpayHttpException(400, "Invalid email"); } entity.RefundMail = entity.BuyerInformation.BuyerEmail; } entity.ProductInformation = Map <Invoice, ProductInformation>(invoice); entity.RedirectURL = invoice.RedirectURL ?? store.StoreWebsite; entity.Status = "new"; entity.SpeedPolicy = ParseSpeedPolicy(invoice.TransactionSpeed, store.SpeedPolicy); var getFeeRate = _FeeProvider.GetFeeRateAsync(); var getRate = _RateProvider.GetRateAsync(invoice.Currency); var getAddress = _Wallet.ReserveAddressAsync(ParseDerivationStrategy(derivationStrategy)); entity.TxFee = storeBlob.NetworkFeeDisabled ? Money.Zero : (await getFeeRate).GetFee(100); // assume price for 100 bytes entity.Rate = (double)await getRate; entity.PosData = invoice.PosData; entity.DepositAddress = await getAddress; entity = await _InvoiceRepository.CreateInvoiceAsync(store.Id, entity); _Watcher.Watch(entity.Id); var resp = entity.EntityToDTO(); return(new DataWrapper <InvoiceResponse>(resp) { Facade = "pos/invoice" }); }
public async Task <decimal> GetRateAsync(string currency) { var rate = await rateProvider.GetRateAsync(currency); foreach (var rule in rateRules) { rate = rule.Apply(network, rate); } return(rate); }
internal async Task <DataWrapper <InvoiceResponse> > CreateInvoiceCore(Invoice invoice, StoreData store, string serverUrl) { var derivationStrategy = store.DerivationStrategy; var entity = new InvoiceEntity { InvoiceTime = DateTimeOffset.UtcNow, DerivationStrategy = derivationStrategy ?? throw new BitpayHttpException(400, "This store has not configured the derivation strategy") }; Uri notificationUri = Uri.IsWellFormedUriString(invoice.NotificationURL, UriKind.Absolute) ? new Uri(invoice.NotificationURL, UriKind.Absolute) : null; if (notificationUri == null || (notificationUri.Scheme != "http" && notificationUri.Scheme != "https")) //TODO: Filer non routable addresses ? { notificationUri = null; } EmailAddressAttribute emailValidator = new EmailAddressAttribute(); entity.ExpirationTime = entity.InvoiceTime + TimeSpan.FromMinutes(15.0); entity.ServerUrl = serverUrl; entity.FullNotifications = invoice.FullNotifications; entity.NotificationURL = notificationUri?.AbsoluteUri; entity.BuyerInformation = Map <Invoice, BuyerInformation>(invoice); //Another way of passing buyer info to support FillBuyerInfo(invoice.Buyer, entity.BuyerInformation); if (entity?.BuyerInformation?.BuyerEmail != null) { if (!EmailValidator.IsEmail(entity.BuyerInformation.BuyerEmail)) { throw new BitpayHttpException(400, "Invalid email"); } entity.RefundMail = entity.BuyerInformation.BuyerEmail; } entity.ProductInformation = Map <Invoice, ProductInformation>(invoice); entity.RedirectURL = invoice.RedirectURL ?? store.StoreWebsite; entity.Status = "new"; entity.SpeedPolicy = store.SpeedPolicy; entity.TxFee = (await _FeeProvider.GetFeeRateAsync()).GetFee(100); // assume price for 100 bytes entity.Rate = (double)await _RateProvider.GetRateAsync(invoice.Currency); entity.PosData = invoice.PosData; entity.DepositAddress = await _Wallet.ReserveAddressAsync(ParseDerivationStrategy(derivationStrategy)); entity = await _InvoiceRepository.CreateInvoiceAsync(store.Id, entity); await _Wallet.MapAsync(entity.DepositAddress.ScriptPubKey, entity.Id); await _Watcher.WatchAsync(entity.Id); var resp = entity.EntityToDTO(); return(new DataWrapper <InvoiceResponse>(resp) { Facade = "pos/invoice" }); }
internal async Task <DataWrapper <InvoiceResponse> > CreateInvoiceCore(Invoice invoice, StoreData store, string serverUrl, double expiryMinutes = 15) { var derivationStrategy = store.DerivationStrategy; var entity = new InvoiceEntity { InvoiceTime = DateTimeOffset.UtcNow, DerivationStrategy = derivationStrategy ?? throw new BitpayHttpException(400, "This store has not configured the derivation strategy") }; var storeBlob = store.GetStoreBlob(); Uri notificationUri = Uri.IsWellFormedUriString(invoice.NotificationURL, UriKind.Absolute) ? new Uri(invoice.NotificationURL, UriKind.Absolute) : null; if (notificationUri == null || (notificationUri.Scheme != "http" && notificationUri.Scheme != "https")) //TODO: Filer non routable addresses ? { notificationUri = null; } EmailAddressAttribute emailValidator = new EmailAddressAttribute(); entity.ExpirationTime = entity.InvoiceTime.AddMinutes(expiryMinutes); entity.MonitoringExpiration = entity.ExpirationTime + TimeSpan.FromMinutes(storeBlob.MonitoringExpiration); entity.OrderId = invoice.OrderId; entity.ServerUrl = serverUrl; entity.FullNotifications = invoice.FullNotifications; entity.NotificationURL = notificationUri?.AbsoluteUri; entity.BuyerInformation = Map <Invoice, BuyerInformation>(invoice); //Another way of passing buyer info to support FillBuyerInfo(invoice.Buyer, entity.BuyerInformation); if (entity?.BuyerInformation?.BuyerEmail != null) { if (!EmailValidator.IsEmail(entity.BuyerInformation.BuyerEmail)) { throw new BitpayHttpException(400, "Invalid email"); } entity.RefundMail = entity.BuyerInformation.BuyerEmail; } entity.ProductInformation = Map <Invoice, ProductInformation>(invoice); entity.RedirectURL = invoice.RedirectURL ?? store.StoreWebsite; entity.Status = "new"; entity.SpeedPolicy = ParseSpeedPolicy(invoice.TransactionSpeed, store.SpeedPolicy); var queries = storeBlob.GetSupportedCryptoCurrencies() .Select(n => _NetworkProvider.GetNetwork(n)) .Where(n => n != null) .Select(network => { return(new { network = network, getFeeRate = _FeeProviderFactory.CreateFeeProvider(network).GetFeeRateAsync(), getRate = _RateProvider.GetRateAsync(invoice.Currency), getAddress = _Wallet.ReserveAddressAsync(ParseDerivationStrategy(derivationStrategy, network)) }); }); var cryptoDatas = new Dictionary <string, CryptoData>(); foreach (var q in queries) { CryptoData cryptoData = new CryptoData(); cryptoData.CryptoCode = q.network.CryptoCode; cryptoData.FeeRate = (await q.getFeeRate); cryptoData.TxFee = storeBlob.NetworkFeeDisabled ? Money.Zero : cryptoData.FeeRate.GetFee(100); // assume price for 100 bytes cryptoData.Rate = await q.getRate; cryptoData.DepositAddress = (await q.getAddress).ToString(); #pragma warning disable CS0618 if (q.network.CryptoCode == "BTC") { entity.TxFee = cryptoData.TxFee; entity.Rate = cryptoData.Rate; entity.DepositAddress = cryptoData.DepositAddress; } #pragma warning restore CS0618 cryptoDatas.Add(cryptoData.CryptoCode, cryptoData); } entity.SetCryptoData(cryptoDatas); entity.PosData = invoice.PosData; entity = await _InvoiceRepository.CreateInvoiceAsync(store.Id, entity, _NetworkProvider); _Watcher.Watch(entity.Id); var resp = entity.EntityToDTO(_NetworkProvider); return(new DataWrapper <InvoiceResponse>(resp) { Facade = "pos/invoice" }); }