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()); }
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))); } }
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)); }
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)); }
public ActionResult GetHealth(NBXplorerDashboard dashBoard) { ApiHealthData model = new ApiHealthData() { Synchronized = dashBoard.IsFullySynched() }; return(Ok(model)); }
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)); }
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>()); }
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})"); } }
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); } }
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[] { (
public bool IsAvailable(string bitcoinCode) { bitcoinCode = bitcoinCode.ToUpperInvariant(); return(_Clients.ContainsKey(bitcoinCode) && _Dashboard.IsFullySynched(bitcoinCode, out var unused)); }
public bool IsAvailable(string cryptoCode) { return(_Clients.ContainsKey(cryptoCode) && _Dashboard.IsFullySynched(cryptoCode)); }
public bool IsAvailable(string cryptoCode) { cryptoCode = cryptoCode.ToUpperInvariant(); return(_Clients.ContainsKey(cryptoCode) && _Dashboard.IsFullySynched(cryptoCode, out var unused)); }
public bool AllAvailable() { return(_nbXplorerDashboard.IsFullySynched()); }