예제 #1
0
        public ExplorerClient GetExplorerClient(string cryptoCode)
        {
            var network = _NetworkProviders.GetNetwork <BTCPayNetwork>(cryptoCode);

            if (network == null)
            {
                return(null);
            }
            _Clients.TryGetValue(network.NBXplorerNetwork.CryptoCode, out ExplorerClient client);
            return(client);
        }
예제 #2
0
        public ExplorerClient GetExplorerClient(string cryptoCode)
        {
            var network = _NetworkProviders.GetNetwork(cryptoCode);

            if (network == null)
            {
                return(null);
            }
            if (_Options.ExplorerFactories.TryGetValue(network.CryptoCode, out Func <BTCPayNetwork, ExplorerClient> factory))
            {
                return(factory(network));
            }
            return(null);
        }
        public ExplorerClientProvider(
            IHttpClientFactory httpClientFactory,
            BTCPayNetworkProvider networkProviders,
            IOptions <NBXplorerOptions> nbXplorerOptions,
            NBXplorerDashboard dashboard)
        {
            _Dashboard        = dashboard;
            _NetworkProviders = networkProviders;

            foreach (var setting in nbXplorerOptions.Value.NBXplorerConnectionSettings)
            {
                var cookieFile = setting.CookieFile;
                if (cookieFile.Trim() == "0" || string.IsNullOrEmpty(cookieFile.Trim()))
                {
                    cookieFile = null;
                }
                Logs.Configuration.LogInformation($"{setting.CryptoCode}: Explorer url is {(setting.ExplorerUri.AbsoluteUri)}");
                Logs.Configuration.LogInformation($"{setting.CryptoCode}: Cookie file is {(setting.CookieFile ?? "not set")}");
                if (setting.ExplorerUri != null)
                {
                    _Clients.TryAdd(setting.CryptoCode.ToUpperInvariant(),
                                    CreateExplorerClient(httpClientFactory.CreateClient(nameof(ExplorerClientProvider)),
                                                         _NetworkProviders.GetNetwork <BTCPayNetwork>(setting.CryptoCode), setting.ExplorerUri,
                                                         setting.CookieFile));
                }
            }
        }
        public ExplorerClientProvider(BTCPayNetworkProvider networkProviders, BTCPayServerOptions options, NBXplorerDashboard dashboard)
        {
            _Dashboard        = dashboard;
            _NetworkProviders = networkProviders;
            _Options          = options;

            foreach (var setting in options.NBXplorerConnectionSettings)
            {
                var cookieFile = setting.CookieFile;
                if (cookieFile.Trim() == "0" || string.IsNullOrEmpty(cookieFile.Trim()))
                {
                    cookieFile = null;
                }
                Logs.Configuration.LogInformation($"{setting.CryptoCode}: Explorer url is {(setting.ExplorerUri.AbsoluteUri ?? "not set")}");
                Logs.Configuration.LogInformation($"{setting.CryptoCode}: Cookie file is {(setting.CookieFile ?? "not set")}");
                if (setting.ExplorerUri != null)
                {
                    _Clients.TryAdd(setting.CryptoCode, CreateExplorerClient(_NetworkProviders.GetNetwork(setting.CryptoCode), setting.ExplorerUri, setting.CookieFile));
                }
            }
        }
예제 #5
0
        public static PaymentEntity GetBlob(this Data.PaymentData paymentData, BTCPayNetworkProvider networks)
        {
            var unziped    = ZipUtils.Unzip(paymentData.Blob);
            var cryptoCode = "BTC";

            if (JObject.Parse(unziped).TryGetValue("cryptoCode", out var v) && v.Type == JTokenType.String)
            {
                cryptoCode = v.Value <string>();
            }
            var           network       = networks.GetNetwork <BTCPayNetworkBase>(cryptoCode);
            PaymentEntity paymentEntity = null;

            if (network == null)
            {
                paymentEntity = NBitcoin.JsonConverters.Serializer.ToObject <PaymentEntity>(unziped, null);
            }
            else
            {
                paymentEntity = network.ToObject <PaymentEntity>(unziped);
            }
            paymentEntity.Network   = network;
            paymentEntity.Accounted = paymentData.Accounted;
            return(paymentEntity);
        }
예제 #6
0
        public async Task <IActionResult> GetLNURLForApp(string cryptoCode, string appId, string itemCode = null)
        {
            var network = _btcPayNetworkProvider.GetNetwork <BTCPayNetwork>(cryptoCode);

            if (network is null || !network.SupportLightning)
            {
                return(NotFound());
            }

            var app = await _appService.GetApp(appId, null, true);

            if (app is null)
            {
                return(NotFound());
            }

            var store = app.StoreData;

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

            if (string.IsNullOrEmpty(itemCode))
            {
                return(NotFound());
            }

            var pmi         = new PaymentMethodId(cryptoCode, PaymentTypes.LNURLPay);
            var lnpmi       = new PaymentMethodId(cryptoCode, PaymentTypes.LightningLike);
            var methods     = store.GetSupportedPaymentMethods(_btcPayNetworkProvider);
            var lnUrlMethod =
                methods.FirstOrDefault(method => method.PaymentId == pmi) as LNURLPaySupportedPaymentMethod;
            var lnMethod = methods.FirstOrDefault(method => method.PaymentId == lnpmi);

            if (lnUrlMethod is null || lnMethod is null)
            {
                return(NotFound());
            }

            ViewPointOfSaleViewModel.Item[] items = null;
            string currencyCode = null;

            switch (app.AppType)
            {
            case nameof(AppType.Crowdfund):
                var cfS = app.GetSettings <CrowdfundSettings>();
                currencyCode = cfS.TargetCurrency;
                items        = _appService.Parse(cfS.PerksTemplate, cfS.TargetCurrency);
                break;

            case nameof(AppType.PointOfSale):
                var posS = app.GetSettings <UIAppsController.PointOfSaleSettings>();
                currencyCode = posS.Currency;
                items        = _appService.Parse(posS.Template, posS.Currency);
                break;
            }

            var item = items.FirstOrDefault(item1 =>
                                            item1.Id.Equals(itemCode, StringComparison.InvariantCultureIgnoreCase));

            if (item is null ||
                item.Inventory <= 0 ||
                (item.PaymentMethods?.Any() is true &&
                 item.PaymentMethods?.Any(s => PaymentMethodId.Parse(s) == pmi) is false))
            {
                return(NotFound());
            }

            return(await GetLNURL(cryptoCode, app.StoreDataId, currencyCode, null, null,
                                  () => (null, app, item, new List <string> {
                AppService.GetAppInternalTag(appId)
            }, item.Price.Value, true)));
        }
예제 #7
0
        public async Task <IActionResult> GetLNURLForPullPayment(string cryptoCode, string pullPaymentId, string pr)
        {
            var network = _btcPayNetworkProvider.GetNetwork <BTCPayNetwork>(cryptoCode);

            if (network is null || !network.SupportLightning)
            {
                return(NotFound());
            }

            var pmi = new PaymentMethodId(cryptoCode, PaymentTypes.LightningLike);
            var pp  = await _pullPaymentHostedService.GetPullPayment(pullPaymentId, true);

            if (!pp.IsRunning() || !pp.IsSupported(pmi))
            {
                return(NotFound());
            }

            var blob = pp.GetBlob();

            if (!blob.Currency.Equals(cryptoCode, StringComparison.InvariantCultureIgnoreCase))
            {
                return(NotFound());
            }

            var progress = _pullPaymentHostedService.CalculatePullPaymentProgress(pp, DateTimeOffset.UtcNow);

            var remaining = progress.Limit - progress.Completed - progress.Awaiting;
            var request   = new LNURLWithdrawRequest()
            {
                MaxWithdrawable = LightMoney.FromUnit(remaining, LightMoneyUnit.BTC),
                K1              = pullPaymentId,
                BalanceCheck    = new Uri(Request.GetCurrentUrl()),
                CurrentBalance  = LightMoney.FromUnit(remaining, LightMoneyUnit.BTC),
                MinWithdrawable =
                    LightMoney.FromUnit(
                        Math.Min(await _lightningLikePayoutHandler.GetMinimumPayoutAmount(pmi, null), remaining),
                        LightMoneyUnit.BTC),
                Tag      = "withdrawRequest",
                Callback = new Uri(Request.GetCurrentUrl()),
            };

            if (pr is null)
            {
                return(Ok(request));
            }

            if (!BOLT11PaymentRequest.TryParse(pr, out var result, network.NBitcoinNetwork) || result is null)
            {
                return(BadRequest(new LNUrlStatusResponse {
                    Status = "ERROR", Reason = "Pr was not a valid BOLT11"
                }));
            }

            if (result.MinimumAmount < request.MinWithdrawable || result.MinimumAmount > request.MaxWithdrawable)
            {
                return(BadRequest(new LNUrlStatusResponse {
                    Status = "ERROR", Reason = "Pr was not within bounds"
                }));
            }
            var store = await _storeRepository.FindStore(pp.StoreId);

            var pm = store !.GetSupportedPaymentMethods(_btcPayNetworkProvider)
                     .OfType <LightningSupportedPaymentMethod>()
                     .FirstOrDefault(method => method.PaymentId == pmi);

            if (pm is null)
            {
                return(NotFound());
            }

            var claimResponse = await _pullPaymentHostedService.Claim(new ClaimRequest()
            {
                Destination     = new BoltInvoiceClaimDestination(pr, result),
                PaymentMethodId = pmi,
                PullPaymentId   = pullPaymentId,
                StoreId         = pp.StoreId,
                Value           = result.MinimumAmount.ToDecimal(LightMoneyUnit.BTC)
            });

            if (claimResponse.Result != ClaimRequest.ClaimResult.Ok)
            {
                return(BadRequest(new LNUrlStatusResponse {
                    Status = "ERROR", Reason = "Pr could not be paid"
                }));
            }
            switch (claimResponse.PayoutData.State)
            {
            case PayoutState.AwaitingPayment:
            {
                var client =
                    _lightningLikePaymentHandler.CreateLightningClient(pm, network);
                PayResponse payResult;
                try
                {
                    payResult = await client.Pay(pr);
                }
                catch (Exception e)
                {
                    payResult = new PayResponse(PayResult.Error, e.Message);
                }

                switch (payResult.Result)
                {
                case PayResult.Ok:
                    await _pullPaymentHostedService.MarkPaid(new PayoutPaidRequest()
                        {
                            PayoutId = claimResponse.PayoutData.Id, Proof = new ManualPayoutProof {
                            }
                        });

                    return(Ok(new LNUrlStatusResponse {
                            Status = "OK"
                        }));

                default:
                    await _pullPaymentHostedService.Cancel(
                        new PullPaymentHostedService.CancelRequest(new string[]
                        {
                            claimResponse.PayoutData.Id
                        }));

                    return(Ok(new LNUrlStatusResponse
                        {
                            Status = "ERROR",
                            Reason = $"Pr could not be paid because {payResult.ErrorDetail}"
                        }));
                }
            }

            case PayoutState.AwaitingApproval:
                return(Ok(new LNUrlStatusResponse
                {
                    Status = "OK",
                    Reason =
                        "The payment request has been recorded, but still needs to be approved before execution."
                }));

            case PayoutState.InProgress:
            case PayoutState.Completed:
                return(Ok(new LNUrlStatusResponse {
                    Status = "OK"
                }));

            case PayoutState.Cancelled:
                return(BadRequest(new LNUrlStatusResponse {
                    Status = "ERROR", Reason = "Pr could not be paid"
                }));
            }

            return(Ok(request));
        }