Пример #1
0
        public override object PreparePayment(DerivationSchemeSettings supportedPaymentMethod, StoreData store,
                                              BTCPayNetworkBase network)
        {
            var storeBlob = store.GetStoreBlob();

            return(new Prepare()
            {
                GetFeeRate = _FeeRateProviderFactory.CreateFeeProvider(network).GetFeeRateAsync(storeBlob.RecommendedFeeBlockTarget),
                GetNetworkFeeRate = storeBlob.NetworkFeeMode == NetworkFeeMode.Never ? null
                                    : _FeeRateProviderFactory.CreateFeeProvider(network).GetFeeRateAsync(),
                ReserveAddress = _WalletProvider.GetWallet(network)
                                 .ReserveAddressAsync(supportedPaymentMethod.AccountDerivation)
            });
        }
 public override object PreparePayment(DerivationSchemeSettings supportedPaymentMethod, StoreData store, BTCPayNetwork network)
 {
     return(new Prepare()
     {
         GetFeeRate = _FeeRateProviderFactory.CreateFeeProvider(network).GetFeeRateAsync(),
         ReserveAddress = _WalletProvider.GetWallet(network).ReserveAddressAsync(supportedPaymentMethod.AccountDerivation)
     });
 }
        public override async Task <IPaymentMethodDetails> CreatePaymentMethodDetails(DerivationStrategy supportedPaymentMethod, PaymentMethod paymentMethod, BTCPayNetwork network)
        {
            var getFeeRate = _FeeRateProviderFactory.CreateFeeProvider(network).GetFeeRateAsync();
            var getAddress = _WalletProvider.GetWallet(network).ReserveAddressAsync(supportedPaymentMethod.DerivationStrategyBase);

            Payments.Bitcoin.BitcoinLikeOnChainPaymentMethod onchainMethod = new Payments.Bitcoin.BitcoinLikeOnChainPaymentMethod();
            onchainMethod.FeeRate        = await getFeeRate;
            onchainMethod.TxFee          = onchainMethod.FeeRate.GetFee(100); // assume price for 100 bytes
            onchainMethod.DepositAddress = (await getAddress).ToString();
            return(onchainMethod);
        }
Пример #4
0
        public override async Task <IPaymentMethodDetails> CreatePaymentMethodDetails(DerivationStrategy supportedPaymentMethod, PaymentMethod paymentMethod, StoreData store, BTCPayNetwork network)
        {
            if (!_ExplorerProvider.IsAvailable(network))
            {
                throw new PaymentMethodUnavailableException($"Full node not available");
            }
            var getFeeRate = _FeeRateProviderFactory.CreateFeeProvider(network).GetFeeRateAsync();
            var getAddress = _WalletProvider.GetWallet(network).ReserveAddressAsync(supportedPaymentMethod.DerivationStrategyBase);

            Payments.Bitcoin.BitcoinLikeOnChainPaymentMethod onchainMethod = new Payments.Bitcoin.BitcoinLikeOnChainPaymentMethod();
            onchainMethod.FeeRate        = await getFeeRate;
            onchainMethod.TxFee          = onchainMethod.FeeRate.GetFee(100); // assume price for 100 bytes
            onchainMethod.DepositAddress = (await getAddress).ToString();
            return(onchainMethod);
        }
        public async Task <IActionResult> GetOnChainFeeRate(string storeId, string cryptoCode, int?blockTarget = null)
        {
            if (IsInvalidWalletRequest(cryptoCode, out var network,
                                       out var derivationScheme, out var actionResult))
            {
                return(actionResult);
            }

            var feeRateTarget = blockTarget ?? Store.GetStoreBlob().RecommendedFeeBlockTarget;

            return(Ok(new OnChainWalletFeeRateData()
            {
                FeeRate = await _feeProviderFactory.CreateFeeProvider(network)
                          .GetFeeRateAsync(feeRateTarget),
            }));
        }
Пример #6
0
        public async Task <IActionResult> ShowOnChainWalletOverview(string storeId, string cryptoCode)
        {
            if (IsInvalidWalletRequest(cryptoCode, out BTCPayNetwork network,
                                       out DerivationSchemeSettings derivationScheme, out IActionResult actionResult))
            {
                return(actionResult);
            }

            var wallet        = _btcPayWalletProvider.GetWallet(network);
            var feeRateTarget = Store.GetStoreBlob().RecommendedFeeBlockTarget;

            return(Ok(new OnChainWalletOverviewData()
            {
                Balance = await wallet.GetBalance(derivationScheme.AccountDerivation),
                FeeRate = await _feeProviderFactory.CreateFeeProvider(network)
                          .GetFeeRateAsync(feeRateTarget),
            }));
        }
        public async Task <IActionResult> LedgerConnection(
            string command,
            // getinfo
            string cryptoCode = null,
            // getxpub
            [ModelBinder(typeof(ModelBinders.DerivationSchemeModelBinder))]
            DerivationStrategyBase derivationScheme = null,
            int account = 0,
            // sendtoaddress
            string destination = null, string amount = null, string feeRate = null, string substractFees = null
            )
        {
            if (!HttpContext.WebSockets.IsWebSocketRequest)
            {
                return(NotFound());
            }
            var webSocket = await HttpContext.WebSockets.AcceptWebSocketAsync();

            using (var normalOperationTimeout = new CancellationTokenSource())
                using (var signTimeout = new CancellationTokenSource())
                {
                    normalOperationTimeout.CancelAfter(TimeSpan.FromMinutes(30));
                    var    hw     = new HardwareWalletService(webSocket);
                    object result = null;
                    try
                    {
                        BTCPayNetwork network = null;
                        if (cryptoCode != null)
                        {
                            network = _NetworkProvider.GetNetwork(cryptoCode);
                            if (network == null)
                            {
                                throw new FormatException("Invalid value for crypto code");
                            }
                        }

                        BitcoinAddress destinationAddress = null;
                        if (destination != null)
                        {
                            try
                            {
                                destinationAddress = BitcoinAddress.Create(destination, network.NBitcoinNetwork);
                            }
                            catch { }
                            if (destinationAddress == null)
                            {
                                throw new FormatException("Invalid value for destination");
                            }
                        }

                        FeeRate feeRateValue = null;
                        if (feeRate != null)
                        {
                            try
                            {
                                feeRateValue = new FeeRate(Money.Satoshis(int.Parse(feeRate, CultureInfo.InvariantCulture)), 1);
                            }
                            catch { }
                            if (feeRateValue == null || feeRateValue.FeePerK <= Money.Zero)
                            {
                                throw new FormatException("Invalid value for fee rate");
                            }
                        }

                        Money amountBTC = null;
                        if (amount != null)
                        {
                            try
                            {
                                amountBTC = Money.Parse(amount);
                            }
                            catch { }
                            if (amountBTC == null || amountBTC <= Money.Zero)
                            {
                                throw new FormatException("Invalid value for amount");
                            }
                        }

                        bool subsctractFeesValue = false;
                        if (substractFees != null)
                        {
                            try
                            {
                                subsctractFeesValue = bool.Parse(substractFees);
                            }
                            catch { throw new FormatException("Invalid value for subtract fees"); }
                        }
                        if (command == "test")
                        {
                            result = await hw.Test(normalOperationTimeout.Token);
                        }
                        if (command == "getxpub")
                        {
                            var getxpubResult = await hw.GetExtPubKey(network, account, normalOperationTimeout.Token);

                            result = getxpubResult;
                        }
                        if (command == "getinfo")
                        {
                            var strategy = GetDirectDerivationStrategy(derivationScheme);
                            if (strategy == null || await hw.GetKeyPath(network, strategy, normalOperationTimeout.Token) == null)
                            {
                                throw new Exception($"This store is not configured to use this ledger");
                            }

                            var feeProvider     = _feeRateProvider.CreateFeeProvider(network);
                            var recommendedFees = feeProvider.GetFeeRateAsync();
                            var balance         = _walletProvider.GetWallet(network).GetBalance(derivationScheme);
                            result = new GetInfoResult()
                            {
                                Balance = (double)(await balance).ToDecimal(MoneyUnit.BTC), RecommendedSatoshiPerByte = (int)(await recommendedFees).GetFee(1).Satoshi
                            };
                        }

                        if (command == "sendtoaddress")
                        {
                            if (!_dashboard.IsFullySynched(network.CryptoCode, out var summary))
                            {
                                throw new Exception($"{network.CryptoCode}: not started or fully synched");
                            }
                            var strategy = GetDirectDerivationStrategy(derivationScheme);
                            var wallet   = _walletProvider.GetWallet(network);
                            var change   = wallet.GetChangeAddressAsync(derivationScheme);

                            var unspentCoins = await wallet.GetUnspentCoins(derivationScheme);

                            var changeAddress = await change;
                            var send          = new[] { (
Пример #8
0
        public async Task <IActionResult> WalletSend(
            [ModelBinder(typeof(WalletIdModelBinder))]
            WalletId walletId, string defaultDestination = null, string defaultAmount = null)
        {
            if (walletId?.StoreId == null)
            {
                return(NotFound());
            }
            var store = await Repository.FindStore(walletId.StoreId, GetUserId());

            DerivationSchemeSettings paymentMethod = GetDerivationSchemeSettings(walletId);

            if (paymentMethod == null)
            {
                return(NotFound());
            }
            var network = this.NetworkProvider.GetNetwork <BTCPayNetwork>(walletId?.CryptoCode);

            if (network == null || network.ReadonlyWallet)
            {
                return(NotFound());
            }
            var storeData = store.GetStoreBlob();
            var rateRules = store.GetStoreBlob().GetRateRules(NetworkProvider);

            rateRules.Spread = 0.0m;
            var currencyPair = new Rating.CurrencyPair(paymentMethod.PaymentId.CryptoCode, GetCurrencyCode(storeData.DefaultLang) ?? "USD");

            double.TryParse(defaultAmount, out var amount);
            var model = new WalletSendModel()
            {
                Outputs = new List <WalletSendModel.TransactionOutput>()
                {
                    new WalletSendModel.TransactionOutput()
                    {
                        Amount             = Convert.ToDecimal(amount),
                        DestinationAddress = defaultDestination
                    }
                },
                CryptoCode = walletId.CryptoCode
            };


            var feeProvider     = _feeRateProvider.CreateFeeProvider(network);
            var recommendedFees = feeProvider.GetFeeRateAsync();
            var balance         = _walletProvider.GetWallet(network).GetBalance(paymentMethod.AccountDerivation);

            model.CurrentBalance            = await balance;
            model.RecommendedSatoshiPerByte = (int)(await recommendedFees).GetFee(1).Satoshi;
            model.FeeSatoshiPerByte         = model.RecommendedSatoshiPerByte;
            model.SupportRBF = network.SupportRBF;
            using (CancellationTokenSource cts = new CancellationTokenSource())
            {
                try
                {
                    cts.CancelAfter(TimeSpan.FromSeconds(5));
                    var result = await RateFetcher.FetchRate(currencyPair, rateRules, cts.Token).WithCancellation(cts.Token);

                    if (result.BidAsk != null)
                    {
                        model.Rate         = result.BidAsk.Center;
                        model.Divisibility = _currencyTable.GetNumberFormatInfo(currencyPair.Right, true).CurrencyDecimalDigits;
                        model.Fiat         = currencyPair.Right;
                    }
                    else
                    {
                        model.RateError = $"{result.EvaluatedRule} ({string.Join(", ", result.Errors.OfType<object>().ToArray())})";
                    }
                }
                catch (Exception ex) { model.RateError = ex.Message; }
            }
            return(View(model));
        }
Пример #9
0
        public async Task <IActionResult> LedgerConnection(
            string storeId,
            string command,
            // getinfo
            string cryptoCode = null,
            // sendtoaddress
            string destination = null, string amount = null, string feeRate = null, string substractFees = null
            )
        {
            if (!HttpContext.WebSockets.IsWebSocketRequest)
            {
                return(NotFound());
            }
            var store = await _Repo.FindStore(storeId, GetUserId());

            if (store == null)
            {
                return(NotFound());
            }

            var webSocket = await HttpContext.WebSockets.AcceptWebSocketAsync();

            var    hw     = new HardwareWalletService(webSocket);
            object result = null;

            try
            {
                BTCPayNetwork network = null;
                if (cryptoCode != null)
                {
                    network = _NetworkProvider.GetNetwork(cryptoCode);
                    if (network == null)
                    {
                        throw new FormatException("Invalid value for crypto code");
                    }
                }

                BitcoinAddress destinationAddress = null;
                if (destination != null)
                {
                    try
                    {
                        destinationAddress = BitcoinAddress.Create(destination);
                    }
                    catch { }
                    if (destinationAddress == null)
                    {
                        throw new FormatException("Invalid value for destination");
                    }
                }

                FeeRate feeRateValue = null;
                if (feeRate != null)
                {
                    try
                    {
                        feeRateValue = new FeeRate(Money.Satoshis(int.Parse(feeRate)), 1);
                    }
                    catch { }
                    if (feeRateValue == null || feeRateValue.FeePerK <= Money.Zero)
                    {
                        throw new FormatException("Invalid value for fee rate");
                    }
                }

                Money amountBTC = null;
                if (amount != null)
                {
                    try
                    {
                        amountBTC = Money.Parse(amount);
                    }
                    catch { }
                    if (amountBTC == null || amountBTC <= Money.Zero)
                    {
                        throw new FormatException("Invalid value for amount");
                    }
                }

                bool subsctractFeesValue = false;
                if (substractFees != null)
                {
                    try
                    {
                        subsctractFeesValue = bool.Parse(substractFees);
                    }
                    catch { throw new FormatException("Invalid value for substract fees"); }
                }
                if (command == "test")
                {
                    result = await hw.Test();
                }
                if (command == "getxpub")
                {
                    result = await hw.GetExtPubKey(network);
                }
                if (command == "getinfo")
                {
                    var strategy     = GetDirectDerivationStrategy(store, network);
                    var strategyBase = GetDerivationStrategy(store, network);
                    if (!await hw.SupportDerivation(network, strategy))
                    {
                        throw new Exception($"This store is not configured to use this ledger");
                    }

                    var feeProvider     = _FeeRateProvider.CreateFeeProvider(network);
                    var recommendedFees = feeProvider.GetFeeRateAsync();
                    var balance         = _WalletProvider.GetWallet(network).GetBalance(strategyBase);
                    result = new GetInfoResult()
                    {
                        Balance = (double)(await balance).ToDecimal(MoneyUnit.BTC), RecommendedSatoshiPerByte = (int)(await recommendedFees).GetFee(1).Satoshi
                    };
                }

                if (command == "sendtoaddress")
                {
                    var strategy     = GetDirectDerivationStrategy(store, network);
                    var strategyBase = GetDerivationStrategy(store, network);
                    var wallet       = _WalletProvider.GetWallet(network);
                    var change       = wallet.GetChangeAddressAsync(strategyBase);
                    var unspentCoins = await wallet.GetUnspentCoins(strategyBase);

                    var changeAddress = await change;
                    unspentCoins.Item2.TryAdd(changeAddress.Item1.ScriptPubKey, changeAddress.Item2);
                    var transaction = await hw.SendToAddress(strategy, unspentCoins.Item1, network,
                                                             new[] { (destinationAddress as IDestination, amountBTC, subsctractFeesValue) },
Пример #10
0
        internal async Task <DataWrapper <InvoiceResponse> > CreateInvoiceCore(Invoice invoice, StoreData store, string serverUrl)
        {
            var derivationStrategies = store.GetDerivationStrategies(_NetworkProvider).Where(c => _ExplorerClients.IsAvailable(c.Network.CryptoCode)).ToList();

            if (derivationStrategies.Count == 0)
            {
                throw new BitpayHttpException(400, "No derivation strategy are available now for this store");
            }
            var entity = new InvoiceEntity
            {
                InvoiceTime = DateTimeOffset.UtcNow
            };

            entity.SetDerivationStrategies(derivationStrategies);

            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(storeBlob.InvoiceExpiration);
            entity.MonitoringExpiration = entity.ExpirationTime + TimeSpan.FromMinutes(storeBlob.MonitoringExpiration);
            entity.OrderId               = invoice.OrderId;
            entity.ServerUrl             = serverUrl;
            entity.FullNotifications     = invoice.FullNotifications || invoice.ExtendedNotifications;
            entity.ExtendedNotifications = invoice.ExtendedNotifications;
            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 = derivationStrategies
                          .Select(derivationStrategy => (Wallet: _WalletProvider.GetWallet(derivationStrategy.Network),
                                                         DerivationStrategy: derivationStrategy.DerivationStrategyBase,
                                                         Network: derivationStrategy.Network,
                                                         RateProvider: _RateProviders.GetRateProvider(derivationStrategy.Network, false),
                                                         FeeRateProvider: _FeeProviderFactory.CreateFeeProvider(derivationStrategy.Network)))
                          .Where(_ => _.Wallet != null &&
                                 _.FeeRateProvider != null &&
                                 _.RateProvider != null)
                          .Select(_ =>
            {
                return(new
                {
                    network = _.Network,
                    getFeeRate = _.FeeRateProvider.GetFeeRateAsync(),
                    getRate = storeBlob.ApplyRateRules(_.Network, _.RateProvider).GetRateAsync(invoice.Currency),
                    getAddress = _.Wallet.ReserveAddressAsync(_.DerivationStrategy)
                });
            });

            bool legacyBTCisSet = false;
            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          = GetTxFee(storeBlob, cryptoData.FeeRate); // assume price for 100 bytes
                cryptoData.Rate           = await q.getRate;
                cryptoData.DepositAddress = (await q.getAddress).ToString();

#pragma warning disable CS0618
                if (q.network.IsBTC)
                {
                    legacyBTCisSet        = true;
                    entity.TxFee          = cryptoData.TxFee;
                    entity.Rate           = cryptoData.Rate;
                    entity.DepositAddress = cryptoData.DepositAddress;
                }
#pragma warning restore CS0618
                cryptoDatas.Add(cryptoData.CryptoCode, cryptoData);
            }

            if (!legacyBTCisSet)
            {
                // Legacy Bitpay clients expect information for BTC information, even if the store do not support it
#pragma warning disable CS0618
                var btc          = _NetworkProvider.BTC;
                var feeProvider  = _FeeProviderFactory.CreateFeeProvider(btc);
                var rateProvider = storeBlob.ApplyRateRules(btc, _RateProviders.GetRateProvider(btc, false));
                if (feeProvider != null && rateProvider != null)
                {
                    var gettingFee  = feeProvider.GetFeeRateAsync();
                    var gettingRate = rateProvider.GetRateAsync(invoice.Currency);
                    entity.TxFee = GetTxFee(storeBlob, await gettingFee);
                    entity.Rate  = await gettingRate;
                }
#pragma warning restore CS0618
            }

            entity.SetCryptoData(cryptoDatas);
            entity.PosData = invoice.PosData;
            entity         = await _InvoiceRepository.CreateInvoiceAsync(store.Id, entity, _NetworkProvider);

            _EventAggregator.Publish(new Events.InvoiceEvent(entity, 1001, "invoice_created"));
            var resp = entity.EntityToDTO(_NetworkProvider);
            return(new DataWrapper <InvoiceResponse>(resp)
            {
                Facade = "pos/invoice"
            });
        }
Пример #11
0
        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"
            });
        }
Пример #12
0
        public async Task <IActionResult> WalletSend(
            [ModelBinder(typeof(WalletIdModelBinder))]
            WalletId walletId, string defaultDestination = null, string defaultAmount = null, bool advancedMode = false)
        {
            if (walletId?.StoreId == null)
            {
                return(NotFound());
            }
            var store = await Repository.FindStore(walletId.StoreId, GetUserId());

            DerivationStrategy paymentMethod = GetPaymentMethod(walletId, store);

            if (paymentMethod == null)
            {
                return(NotFound());
            }
            var network = this.NetworkProvider.GetNetwork(walletId?.CryptoCode);

            if (network == null)
            {
                return(NotFound());
            }
            var storeData = store.GetStoreBlob();
            var rateRules = store.GetStoreBlob().GetRateRules(NetworkProvider);

            rateRules.Spread = 0.0m;
            var             currencyPair = new Rating.CurrencyPair(paymentMethod.PaymentId.CryptoCode, GetCurrencyCode(storeData.DefaultLang) ?? "USD");
            WalletSendModel model        = new WalletSendModel()
            {
                Destination = defaultDestination,
                CryptoCode  = walletId.CryptoCode
            };

            if (double.TryParse(defaultAmount, out var amount))
            {
                model.Amount = (decimal)amount;
            }

            var feeProvider     = _feeRateProvider.CreateFeeProvider(network);
            var recommendedFees = feeProvider.GetFeeRateAsync();
            var balance         = _walletProvider.GetWallet(network).GetBalance(paymentMethod.DerivationStrategyBase);

            model.CurrentBalance            = (await balance).ToDecimal(MoneyUnit.BTC);
            model.RecommendedSatoshiPerByte = (int)(await recommendedFees).GetFee(1).Satoshi;
            model.FeeSatoshiPerByte         = model.RecommendedSatoshiPerByte;

            using (CancellationTokenSource cts = new CancellationTokenSource())
            {
                try
                {
                    cts.CancelAfter(TimeSpan.FromSeconds(5));
                    var result = await RateFetcher.FetchRate(currencyPair, rateRules).WithCancellation(cts.Token);

                    if (result.BidAsk != null)
                    {
                        model.Rate         = result.BidAsk.Center;
                        model.Divisibility = _currencyTable.GetNumberFormatInfo(currencyPair.Right, true).CurrencyDecimalDigits;
                        model.Fiat         = currencyPair.Right;
                    }
                    else
                    {
                        model.RateError = $"{result.EvaluatedRule} ({string.Join(", ", result.Errors.OfType<object>().ToArray())})";
                    }
                }
                catch (Exception ex) { model.RateError = ex.Message; }
            }
            model.AdvancedMode = advancedMode;
            return(View(model));
        }