Esempio n. 1
0
        public async Task <IActionResult> SparkServices(string cryptoCode, int index, bool showQR = false)
        {
            if (!_dashBoard.IsFullySynched(cryptoCode, out var unusud))
            {
                StatusMessage = $"Error: {cryptoCode} is not fully synched";
                return(RedirectToAction(nameof(Services)));
            }
            var spark = _Options.ExternalServicesByCryptoCode.GetServices <ExternalSpark>(cryptoCode).Skip(index).Select(c => c.ConnectionString).FirstOrDefault();

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

            SparkServicesViewModel vm = new SparkServicesViewModel();

            vm.ShowQR = showQR;
            try
            {
                var cookie = (spark.CookeFile == "fake"
                            ? "fake:fake:fake" // If we are testing, it should not crash
                            : await System.IO.File.ReadAllTextAsync(spark.CookeFile)).Split(':');
                if (cookie.Length >= 3)
                {
                    vm.SparkLink = $"{spark.Server.AbsoluteUri}?access-key={cookie[2]}";
                }
            }
            catch (Exception ex)
            {
                StatusMessage = $"Error: {ex.Message}";
                return(RedirectToAction(nameof(Services)));
            }
            return(View(vm));
        }
        public async Task <IActionResult> SparkServices(string cryptoCode, int index)
        {
            if (!_dashBoard.IsFullySynched(cryptoCode, out var unusud))
            {
                StatusMessage = $"Error: {cryptoCode} is not fully synched";
                return(RedirectToAction(nameof(Services)));
            }
            var spark = _Options.ExternalServicesByCryptoCode.GetServices <ExternalSpark>(cryptoCode).Skip(index).Select(c => c.ConnectionString).FirstOrDefault();

            if (spark == null)
            {
                return(NotFound());
            }
            try
            {
                var cookie = System.IO.File.ReadAllText(spark.CookeFile).Split(':');
                if (cookie.Length >= 3)
                {
                    var client   = HttpClientFactory.CreateClient();
                    var response = await client.GetAsync($"{spark.Server.AbsoluteUri}?access-key={cookie[2]}");

                    HttpContext.Response.SetHeader("Set-Cookie", response.Headers.GetValues("Set-Cookie").First());
                    return(Redirect($"{spark.Server.AbsoluteUri}"));
                }
            }
            catch (Exception ex)
            {
                StatusMessage = $"Error: {ex.Message}";
                return(RedirectToAction(nameof(Services)));
            }
            return(NotFound());
        }
Esempio n. 3
0
        public async Task <IActionResult> Service(string serviceName, string cryptoCode, bool showQR = false, uint?nonce = null)
        {
            if (!_dashBoard.IsFullySynched(cryptoCode, out var unusud))
            {
                StatusMessage = $"Error: {cryptoCode} is not fully synched";
                return(RedirectToAction(nameof(Services)));
            }
            var service = GetService(serviceName, cryptoCode);

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

            try
            {
                if (service.Type == ExternalServiceTypes.P2P)
                {
                    return(View("P2PService", new LightningWalletServices()
                    {
                        ShowQR = showQR,
                        WalletName = service.ServiceName,
                        ServiceLink = service.ConnectionString.Server.AbsoluteUri.WithoutEndingSlash()
                    }));
                }
                var connectionString = await service.ConnectionString.Expand(this.Request.GetAbsoluteUriNoPathBase(), service.Type, _Options.NetworkType);

                switch (service.Type)
                {
                case ExternalServiceTypes.Charge:
                    return(LightningChargeServices(service, connectionString, showQR));

                case ExternalServiceTypes.RTL:
                case ExternalServiceTypes.Spark:
                    if (connectionString.AccessKey == null)
                    {
                        StatusMessage = $"Error: The access key of the service is not set";
                        return(RedirectToAction(nameof(Services)));
                    }
                    LightningWalletServices vm = new LightningWalletServices();
                    vm.ShowQR      = showQR;
                    vm.WalletName  = service.DisplayName;
                    vm.ServiceLink = $"{connectionString.Server}?access-key={connectionString.AccessKey}";
                    return(View("LightningWalletServices", vm));

                case ExternalServiceTypes.LNDGRPC:
                case ExternalServiceTypes.LNDRest:
                    return(LndServices(service, connectionString, nonce));

                default:
                    throw new NotSupportedException(service.Type.ToString());
                }
            }
            catch (Exception ex)
            {
                StatusMessage = $"Error: {ex.Message}";
                return(RedirectToAction(nameof(Services)));
            }
        }
Esempio n. 4
0
        public async Task <IActionResult> WalletRescan(
            [ModelBinder(typeof(WalletIdModelBinder))]
            WalletId walletId)
        {
            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 vm = new RescanWalletModel();

            vm.IsFullySync = _dashboard.IsFullySynched(walletId.CryptoCode, out var unused);
            // We need to ensure it is segwit,
            // because hardware wallet support need the parent transactions to sign, which NBXplorer don't have. (Nor does a pruned node)
            vm.IsSegwit              = paymentMethod.DerivationStrategyBase.IsSegwit();
            vm.IsServerAdmin         = User.Claims.Any(c => c.Type == Policies.CanModifyServerSettings.Key && c.Value == "true");
            vm.IsSupportedByCurrency = _dashboard.Get(walletId.CryptoCode)?.Status?.BitcoinStatus?.Capabilities?.CanScanTxoutSet == true;
            var explorer     = ExplorerClientProvider.GetExplorerClient(walletId.CryptoCode);
            var scanProgress = await explorer.GetScanUTXOSetInformationAsync(paymentMethod.DerivationStrategyBase);

            if (scanProgress != null)
            {
                vm.PreviousError = scanProgress.Error;
                if (scanProgress.Status == ScanUTXOStatus.Queued || scanProgress.Status == ScanUTXOStatus.Pending)
                {
                    if (scanProgress.Progress == null)
                    {
                        vm.Progress = 0;
                    }
                    else
                    {
                        vm.Progress      = scanProgress.Progress.OverallProgress;
                        vm.RemainingTime = TimeSpan.FromSeconds(scanProgress.Progress.RemainingSeconds).PrettyPrint();
                    }
                }
                if (scanProgress.Status == ScanUTXOStatus.Complete)
                {
                    vm.LastSuccess = scanProgress.Progress;
                    vm.TimeOfScan  = (scanProgress.Progress.CompletedAt.Value - scanProgress.Progress.StartedAt).PrettyPrint();
                }
            }
            return(View(vm));
        }
Esempio n. 5
0
        public async Task <IActionResult> WalletRescan(
            [ModelBinder(typeof(WalletIdModelBinder))]
            WalletId walletId)
        {
            if (walletId?.StoreId == null)
            {
                return(NotFound());
            }
            DerivationSchemeSettings paymentMethod = GetDerivationSchemeSettings(walletId);

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

            var vm = new RescanWalletModel();

            vm.IsFullySync           = _dashboard.IsFullySynched(walletId.CryptoCode, out var unused);
            vm.IsServerAdmin         = (await _authorizationService.AuthorizeAsync(User, Policies.CanModifyServerSettings.Key)).Succeeded;
            vm.IsSupportedByCurrency = _dashboard.Get(walletId.CryptoCode)?.Status?.BitcoinStatus?.Capabilities?.CanScanTxoutSet == true;
            var explorer     = ExplorerClientProvider.GetExplorerClient(walletId.CryptoCode);
            var scanProgress = await explorer.GetScanUTXOSetInformationAsync(paymentMethod.AccountDerivation);

            if (scanProgress != null)
            {
                vm.PreviousError = scanProgress.Error;
                if (scanProgress.Status == ScanUTXOStatus.Queued || scanProgress.Status == ScanUTXOStatus.Pending)
                {
                    if (scanProgress.Progress == null)
                    {
                        vm.Progress = 0;
                    }
                    else
                    {
                        vm.Progress      = scanProgress.Progress.OverallProgress;
                        vm.RemainingTime = TimeSpan.FromSeconds(scanProgress.Progress.RemainingSeconds).PrettyPrint();
                    }
                }
                if (scanProgress.Status == ScanUTXOStatus.Complete)
                {
                    vm.LastSuccess = scanProgress.Progress;
                    vm.TimeOfScan  = (scanProgress.Progress.CompletedAt.Value - scanProgress.Progress.StartedAt).PrettyPrint();
                }
            }
            return(View(vm));
        }
Esempio n. 6
0
        public ActionResult GetHealth(NBXplorerDashboard dashBoard)
        {
            ApiHealthData model = new ApiHealthData()
            {
                Synchronized = dashBoard.IsFullySynched()
            };

            return(Ok(model));
        }
Esempio n. 7
0
        public async Task <IActionResult> LightningChargeServices(string cryptoCode, int index, bool showQR = false)
        {
            if (!_dashBoard.IsFullySynched(cryptoCode, out var unusud))
            {
                StatusMessage = $"Error: {cryptoCode} is not fully synched";
                return(RedirectToAction(nameof(Services)));
            }
            var lightningCharge = _Options.ExternalServicesByCryptoCode.GetServices <ExternalCharge>(cryptoCode).Select(c => c.ConnectionString).FirstOrDefault();

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

            ChargeServiceViewModel vm = new ChargeServiceViewModel();

            vm.Uri      = lightningCharge.ToUri(false).AbsoluteUri;
            vm.APIToken = lightningCharge.Password;
            try
            {
                if (string.IsNullOrEmpty(vm.APIToken) && lightningCharge.CookieFilePath != null)
                {
                    if (lightningCharge.CookieFilePath != "fake")
                    {
                        vm.APIToken = await System.IO.File.ReadAllTextAsync(lightningCharge.CookieFilePath);
                    }
                    else
                    {
                        vm.APIToken = "fake";
                    }
                }
                var builder = new UriBuilder(lightningCharge.ToUri(false));
                builder.UserName    = "******";
                builder.Password    = vm.APIToken;
                vm.AuthenticatedUri = builder.ToString();
            }
            catch (Exception ex)
            {
                StatusMessage = $"Error: {ex.Message}";
                return(RedirectToAction(nameof(Services)));
            }
            return(View(vm));
        }
Esempio n. 8
0
        public IActionResult LndServices(string cryptoCode, int index, uint?nonce)
        {
            if (!_dashBoard.IsFullySynched(cryptoCode, out var unusud))
            {
                StatusMessage = $"Error: {cryptoCode} is not fully synched";
                return(RedirectToAction(nameof(Services)));
            }
            var external = GetExternalLndConnectionString(cryptoCode, index);

            if (external == null)
            {
                return(NotFound());
            }
            var model = new LndGrpcServicesViewModel();

            if (external.ConnectionType == LightningConnectionType.LndGRPC)
            {
                model.Host           = $"{external.BaseUri.DnsSafeHost}:{external.BaseUri.Port}";
                model.SSL            = external.BaseUri.Scheme == "https";
                model.ConnectionType = "GRPC";
            }
            else if (external.ConnectionType == LightningConnectionType.LndREST)
            {
                model.Uri            = external.BaseUri.AbsoluteUri;
                model.ConnectionType = "REST";
            }

            if (external.CertificateThumbprint != null)
            {
                model.CertificateThumbprint = Encoders.Hex.EncodeData(external.CertificateThumbprint);
            }
            if (external.Macaroon != null)
            {
                model.Macaroon = Encoders.Hex.EncodeData(external.Macaroon);
            }
            if (external.RestrictedMacaroon != null)
            {
                model.RestrictedMacaroon = Encoders.Hex.EncodeData(external.RestrictedMacaroon);
            }

            if (nonce != null)
            {
                var configKey = GetConfigKey("lnd", cryptoCode, index, nonce.Value);
                var lnConfig  = _LnConfigProvider.GetConfig(configKey);
                if (lnConfig != null)
                {
                    model.QRCodeLink = $"{this.Request.GetAbsoluteRoot().WithTrailingSlash()}lnd-config/{configKey}/lnd.config";
                    model.QRCode     = $"config={model.QRCodeLink}";
                }
            }

            return(View(model));
        }
        public async Task <NodeInfo[]> GetNodeInfo(LightningSupportedPaymentMethod supportedPaymentMethod, BTCPayNetwork network, InvoiceLogs invoiceLogs, bool?preferOnion = null, bool throws = false)
        {
            if (!_Dashboard.IsFullySynched(network.CryptoCode, out var summary))
            {
                throw new PaymentMethodUnavailableException("Full node not available");
            }

            try
            {
                using var cts = new CancellationTokenSource(LIGHTNING_TIMEOUT);
                var client = CreateLightningClient(supportedPaymentMethod, network);
                LightningNodeInformation info;
                try
                {
                    info = await client.GetInfo(cts.Token);
                }
                catch (OperationCanceledException) when(cts.IsCancellationRequested)
                {
                    throw new PaymentMethodUnavailableException("The lightning node did not reply in a timely manner");
                }
                catch (Exception ex)
                {
                    throw new PaymentMethodUnavailableException($"Error while connecting to the API: {ex.Message}" +
                                                                (!string.IsNullOrEmpty(ex.InnerException?.Message) ? $" ({ex.InnerException.Message})" : ""));
                }

                var nodeInfo = preferOnion != null && info.NodeInfoList.Any(i => i.IsTor == preferOnion)
                    ? info.NodeInfoList.Where(i => i.IsTor == preferOnion.Value).ToArray()
                    : info.NodeInfoList.Select(i => i).ToArray();

                // Maybe the user does not have an  easily accessible ln node. Node info should be optional. The UI also supports this.
                // if (!nodeInfo.Any())
                // {
                //     throw new PaymentMethodUnavailableException("No lightning node public address has been configured");
                // }

                var blocksGap = summary.Status.ChainHeight - info.BlockHeight;
                if (blocksGap > 10)
                {
                    throw new PaymentMethodUnavailableException($"The lightning node is not synched ({blocksGap} blocks left)");
                }

                return(nodeInfo);
            }
            catch (Exception e) when(!throws)
            {
                invoiceLogs.Write($"NodeInfo failed to be fetched: {e.Message}", InvoiceEventData.EventSeverity.Error);
            }

            return(Array.Empty <NodeInfo>());
        }
Esempio n. 10
0
        public async Task <NodeInfo> Test(LightningSupportedPaymentMethod supportedPaymentMethod, BTCPayNetwork network)
        {
            if (!_Dashboard.IsFullySynched(network.CryptoCode, out var summary))
            {
                throw new Exception($"Full node not available");
            }

            var cts    = new CancellationTokenSource(5000);
            var client = _LightningClientFactory.CreateClient(supportedPaymentMethod, network);
            LightningNodeInformation info = null;

            try
            {
                info = await client.GetInfo(cts.Token);
            }
            catch (OperationCanceledException) when(cts.IsCancellationRequested)
            {
                throw new Exception($"The lightning node did not replied in a timely maner");
            }
            catch (Exception ex)
            {
                throw new Exception($"Error while connecting to the API ({ex.Message})");
            }

            if (info.Address == null)
            {
                throw new Exception($"No lightning node public address has been configured");
            }

            var blocksGap = Math.Abs(info.BlockHeight - summary.Status.ChainHeight);

            if (blocksGap > 10)
            {
                throw new Exception($"The lightning is not synched ({blocksGap} blocks)");
            }

            try
            {
                if (!SkipP2PTest)
                {
                    await TestConnection(info.Address, info.P2PPort, cts.Token);
                }
            }
            catch (Exception ex)
            {
                throw new Exception($"Error while connecting to the lightning node via {info.Address}:{info.P2PPort} ({ex.Message})");
            }
            return(new NodeInfo(info.NodeId, info.Address, info.P2PPort));
        }
        public async Task Test(LightningSupportedPaymentMethod supportedPaymentMethod, BTCPayNetwork network)
        {
            if (!_Dashboard.IsFullySynched(network.CryptoCode, out var summary))
            {
                throw new Exception($"Full node not available");
            }


            var             cts    = new CancellationTokenSource(5000);
            var             client = GetClient(supportedPaymentMethod, network);
            GetInfoResponse info   = null;

            try
            {
                info = await client.GetInfoAsync(cts.Token);
            }
            catch (Exception ex)
            {
                throw new Exception($"Error while connecting to the lightning charge {client.Uri} ({ex.Message})");
            }
            var address = info.Address.Select(a => a.Address).FirstOrDefault();
            var port    = info.Port;

            address = address ?? client.Uri.DnsSafeHost;

            if (info.Network != network.CLightningNetworkName)
            {
                throw new Exception($"Lightning node network {info.Network}, but expected is {network.CLightningNetworkName}");
            }

            var blocksGap = Math.Abs(info.BlockHeight - summary.Status.ChainHeight);

            if (blocksGap > 10)
            {
                throw new Exception($"The lightning is not synched ({blocksGap} blocks)");
            }

            try
            {
                await TestConnection(address, port, cts.Token);
            }
            catch (Exception ex)
            {
                throw new Exception($"Error while connecting to the lightning node via {address}:{port} ({ex.Message})");
            }
        }
Esempio n. 12
0
        public async Task <NodeInfo[]> GetNodeInfo(LightningSupportedPaymentMethod supportedPaymentMethod, BTCPayNetwork network, bool?preferOnion = null)
        {
            if (!_Dashboard.IsFullySynched(network.CryptoCode, out var summary))
            {
                throw new PaymentMethodUnavailableException("Full node not available");
            }

            using (var cts = new CancellationTokenSource(LIGHTNING_TIMEOUT))
            {
                var client = supportedPaymentMethod.CreateLightningClient(network, Options.Value, _lightningClientFactory);
                LightningNodeInformation info;
                try
                {
                    info = await client.GetInfo(cts.Token);
                }
                catch (OperationCanceledException) when(cts.IsCancellationRequested)
                {
                    throw new PaymentMethodUnavailableException("The lightning node did not reply in a timely manner");
                }
                catch (Exception ex)
                {
                    throw new PaymentMethodUnavailableException($"Error while connecting to the API: {ex.Message}" +
                                                                (!string.IsNullOrEmpty(ex.InnerException?.Message) ? $" ({ex.InnerException.Message})" : ""));
                }

                var nodeInfo = preferOnion != null && info.NodeInfoList.Any(i => i.IsTor == preferOnion)
                    ? info.NodeInfoList.Where(i => i.IsTor == preferOnion.Value).ToArray()
                    : info.NodeInfoList.Select(i => i).ToArray();

                if (!nodeInfo.Any())
                {
                    throw new PaymentMethodUnavailableException("No lightning node public address has been configured");
                }

                var blocksGap = summary.Status.ChainHeight - info.BlockHeight;
                if (blocksGap > 10)
                {
                    throw new PaymentMethodUnavailableException($"The lightning node is not synched ({blocksGap} blocks left)");
                }

                return(nodeInfo);
            }
        }
        public async Task <NodeInfo> Test(LightningSupportedPaymentMethod supportedPaymentMethod, BTCPayNetwork network)
        {
            if (!_Dashboard.IsFullySynched(network.CryptoCode, out var summary))
            {
                throw new PaymentMethodUnavailableException($"Full node not available");
            }

            using (var cts = new CancellationTokenSource(LIGHTNING_TIMEOUT))
            {
                var client = supportedPaymentMethod.CreateClient(network);
                LightningNodeInformation info = null;
                try
                {
                    info = await client.GetInfo(cts.Token);
                }
                catch (OperationCanceledException) when(cts.IsCancellationRequested)
                {
                    throw new PaymentMethodUnavailableException($"The lightning node did not replied in a timely maner");
                }
                catch (Exception ex)
                {
                    throw new PaymentMethodUnavailableException($"Error while connecting to the API ({ex.Message})");
                }

                if (info.NodeInfo == null)
                {
                    throw new PaymentMethodUnavailableException($"No lightning node public address has been configured");
                }

                var blocksGap = Math.Abs(info.BlockHeight - summary.Status.ChainHeight);
                if (blocksGap > 10)
                {
                    throw new PaymentMethodUnavailableException($"The lightning is not synched ({blocksGap} blocks)");
                }

                return(info.NodeInfo);
            }
        }
        public async Task <NodeInfo> GetNodeInfo(bool preferOnion, LightningSupportedPaymentMethod supportedPaymentMethod, BTCPayNetwork network)
        {
            if (!_Dashboard.IsFullySynched(network.CryptoCode, out var summary))
            {
                throw new PaymentMethodUnavailableException($"Full node not available");
            }

            using (var cts = new CancellationTokenSource(LIGHTNING_TIMEOUT))
            {
                var client = _lightningClientFactory.Create(supportedPaymentMethod.GetLightningUrl(), network);
                LightningNodeInformation info = null;
                try
                {
                    info = await client.GetInfo(cts.Token);
                }
                catch (OperationCanceledException) when(cts.IsCancellationRequested)
                {
                    throw new PaymentMethodUnavailableException($"The lightning node did not reply in a timely manner");
                }
                catch (Exception ex)
                {
                    throw new PaymentMethodUnavailableException($"Error while connecting to the API ({ex.Message})");
                }
                var nodeInfo = info.NodeInfoList.FirstOrDefault(i => i.IsTor == preferOnion) ?? info.NodeInfoList.FirstOrDefault();
                if (nodeInfo == null)
                {
                    throw new PaymentMethodUnavailableException($"No lightning node public address has been configured");
                }

                var blocksGap = summary.Status.ChainHeight - info.BlockHeight;
                if (blocksGap > 10)
                {
                    throw new PaymentMethodUnavailableException($"The lightning node is not synched ({blocksGap} blocks left)");
                }

                return(nodeInfo);
            }
        }
Esempio n. 15
0
        public async Task <IActionResult> Service(string serviceName, string cryptoCode, bool showQR = false, uint?nonce = null)
        {
            var service = GetService(serviceName, cryptoCode);

            if (service == null)
            {
                return(NotFound());
            }
            if (!string.IsNullOrEmpty(cryptoCode) && !_dashBoard.IsFullySynched(cryptoCode, out _) && service.Type != ExternalServiceTypes.RPC)
            {
                TempData[WellKnownTempData.ErrorMessage] = $"{cryptoCode} is not fully synched";
                return(RedirectToAction(nameof(Services)));
            }
            try
            {
                if (service.Type == ExternalServiceTypes.P2P)
                {
                    return(View("P2PService", new LightningWalletServices()
                    {
                        ShowQR = showQR,
                        WalletName = service.ServiceName,
                        ServiceLink = service.ConnectionString.Server.AbsoluteUri.WithoutEndingSlash()
                    }));
                }
                if (service.Type == ExternalServiceTypes.LNDSeedBackup)
                {
                    var model = LndSeedBackupViewModel.Parse(service.ConnectionString.CookieFilePath);
                    if (!model.IsWalletUnlockPresent)
                    {
                        TempData.SetStatusMessageModel(new StatusMessageModel()
                        {
                            Severity = StatusMessageModel.StatusSeverity.Warning,
                            Html     = "Your LND does not seem to allow seed backup.<br />" +
                                       "It's recommended, but not required, that you migrate as instructed by <a href=\"https://blog.btcpayserver.org/btcpay-lnd-migration\">our migration blog post</a>.<br />" +
                                       "You will need to close all of your channels, and migrate your funds as <a href=\"https://blog.btcpayserver.org/btcpay-lnd-migration\">we documented</a>."
                        });
                    }
                    return(View("LndSeedBackup", model));
                }
                if (service.Type == ExternalServiceTypes.RPC)
                {
                    return(View("RPCService", new LightningWalletServices()
                    {
                        ShowQR = showQR,
                        WalletName = service.ServiceName,
                        ServiceLink = service.ConnectionString.Server.AbsoluteUri.WithoutEndingSlash()
                    }));
                }
                var connectionString = await service.ConnectionString.Expand(this.Request.GetAbsoluteUriNoPathBase(), service.Type, _Options.NetworkType);

                switch (service.Type)
                {
                case ExternalServiceTypes.Charge:
                    return(LightningChargeServices(service, connectionString, showQR));

                case ExternalServiceTypes.RTL:
                case ExternalServiceTypes.ThunderHub:
                case ExternalServiceTypes.Spark:
                    if (connectionString.AccessKey == null)
                    {
                        TempData[WellKnownTempData.ErrorMessage] = $"The access key of the service is not set";
                        return(RedirectToAction(nameof(Services)));
                    }
                    LightningWalletServices vm = new LightningWalletServices();
                    vm.ShowQR     = showQR;
                    vm.WalletName = service.DisplayName;
                    string tokenParam = "access-key";
                    if (service.Type == ExternalServiceTypes.ThunderHub)
                    {
                        tokenParam = "token";
                    }
                    vm.ServiceLink = $"{connectionString.Server}?{tokenParam}={connectionString.AccessKey}";
                    return(View("LightningWalletServices", vm));

                case ExternalServiceTypes.CLightningRest:
                    return(LndServices(service, connectionString, nonce, "CLightningRestServices"));

                case ExternalServiceTypes.LNDGRPC:
                case ExternalServiceTypes.LNDRest:
                    return(LndServices(service, connectionString, nonce));

                case ExternalServiceTypes.Configurator:
                    return(View("ConfiguratorService",
                                new LightningWalletServices()
                    {
                        ShowQR = showQR,
                        WalletName = service.ServiceName,
                        ServiceLink = $"{connectionString.Server}?password={connectionString.AccessKey}"
                    }));

                default:
                    throw new NotSupportedException(service.Type.ToString());
                }
            }
            catch (Exception ex)
            {
                TempData[WellKnownTempData.ErrorMessage] = ex.Message;
                return(RedirectToAction(nameof(Services)));
            }
        }
        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[] { (
Esempio n. 17
0
 public bool IsAvailable(string bitcoinCode)
 {
     bitcoinCode = bitcoinCode.ToUpperInvariant();
     return(_Clients.ContainsKey(bitcoinCode) && _Dashboard.IsFullySynched(bitcoinCode, out var unused));
 }
Esempio n. 18
0
 public bool IsAvailable(string cryptoCode)
 {
     return(_Clients.ContainsKey(cryptoCode) && _Dashboard.IsFullySynched(cryptoCode));
 }
Esempio n. 19
0
 public bool IsAvailable(string cryptoCode)
 {
     cryptoCode = cryptoCode.ToUpperInvariant();
     return(_Clients.ContainsKey(cryptoCode) && _Dashboard.IsFullySynched(cryptoCode, out var unused));
 }
 public bool AllAvailable()
 {
     return(_nbXplorerDashboard.IsFullySynched());
 }