public async Task <LightningInvoice> GetInvoice(string invoiceId, CancellationToken cancellation = default(CancellationToken)) { InvoiceResponse result = null; try { result = await _eclairClient.GetInvoice(invoiceId, cancellation); } catch (EclairClient.EclairApiException ex) when(ex.Error.Error == "Not found" || ex.Error.Error.Contains("Invalid hexadecimal", StringComparison.OrdinalIgnoreCase)) { return(null); } GetReceivedInfoResponse info = null; try { info = await _eclairClient.GetReceivedInfo(invoiceId, null, cancellation); } catch (EclairClient.EclairApiException) { } var parsed = BOLT11PaymentRequest.Parse(result.Serialized, _network); var lnInvoice = new LightningInvoice() { Id = result.PaymentHash, Amount = parsed.MinimumAmount, ExpiresAt = parsed.ExpiryDate, BOLT11 = result.Serialized }; if (DateTimeOffset.UtcNow >= parsed.ExpiryDate) { lnInvoice.Status = LightningInvoiceStatus.Expired; } if (info != null && info.Status.Type == "received") { lnInvoice.AmountReceived = info.Status.Amount; lnInvoice.Status = info.Status.Amount >= parsed.MinimumAmount ? LightningInvoiceStatus.Paid : LightningInvoiceStatus.Unpaid; lnInvoice.PaidAt = info.Status.ReceivedAt; } return(lnInvoice); }
public async Task CanCreateInvoiceWithDescriptionHash() { var hashToUse = new uint256(new SHA256Managed().ComputeHash(Encoding.UTF8.GetBytes("CanCreateInvoiceWithDescriptionHash"))); async Task <LightningInvoice> CreateWithHash(ILightningClient lightningClient) { return(await lightningClient.CreateInvoice(new CreateInvoiceParams(10000, hashToUse, TimeSpan.FromMinutes(5)))); } await WaitServersAreUp(); foreach (var client in Tester.GetLightningClients()) { switch (client.Client) { case CLightningClient _: case LndClient _: Logs.Tester.LogInformation($"{client.Name}: {nameof(CanCreateInvoiceWithDescriptionHash)}"); var createdInvoice = await CreateWithHash(client.Client); var retrievedInvoice = await client.Client.GetInvoice(createdInvoice.Id); Logs.Tester.LogInformation(JObject.FromObject(createdInvoice).ToString()); Logs.Tester.LogInformation(JObject.FromObject(retrievedInvoice).ToString()); AssertUnpaid(createdInvoice); AssertUnpaid(retrievedInvoice); var createdInvoiceBOLT = BOLT11PaymentRequest.Parse(createdInvoice.BOLT11, Network.RegTest); var retrievedInvoiceeBOLT = BOLT11PaymentRequest.Parse(retrievedInvoice.BOLT11, Network.RegTest); Assert.Equal(createdInvoiceBOLT.PaymentHash, retrievedInvoiceeBOLT.PaymentHash); Assert.Equal(hashToUse, createdInvoiceBOLT.DescriptionHash); break; default: await Assert.ThrowsAsync <NotSupportedException>(async() => { await CreateWithHash(client.Client); }); break; } } }
public async Task <LightningInvoice> CreateInvoice(LightMoney amount, string description, TimeSpan expiry, CancellationToken cancellation = default(CancellationToken)) { var result = await _eclairClient.CreateInvoice( description, amount.MilliSatoshi, Convert.ToInt32(expiry.TotalSeconds), null, cancellation); var parsed = BOLT11PaymentRequest.Parse(result.Serialized, _network); var invoice = new LightningInvoice() { BOLT11 = result.Serialized, Amount = amount, Id = result.PaymentHash, Status = LightningInvoiceStatus.Unpaid, ExpiresAt = parsed.ExpiryDate }; return(invoice); }
internal LightningInvoice GetLightningInvoiceObject(ListInvoiceResultResponse invoice, Network network) { var parsed = BOLT11PaymentRequest.Parse(invoice.Bolt11, network); var lightningInvoice = new LightningInvoice() { Id = invoice.Hash, Amount = invoice.AmountMsat, AmountReceived = invoice.AmountMsat, BOLT11 = invoice.Bolt11, Status = ToStatus(invoice.State), PaidAt = null, ExpiresAt = parsed.ExpiryDate }; if (invoice.State == "used") { lightningInvoice.PaidAt = parsed.ExpiryDate; } return(lightningInvoice); }
public async Task <LightningInvoice> GetInvoice(string invoiceId, CancellationToken cancellation = default(CancellationToken)) { var result = await _eclairClient.GetInvoice(invoiceId, cancellation); GetReceivedInfoResponse info; try { info = await _eclairClient.GetReceivedInfo(invoiceId, null, cancellation); } catch (EclairClient.EclairApiException) { info = new GetReceivedInfoResponse() { AmountMsat = 0, ReceivedAt = 0, PaymentHash = invoiceId }; } var parsed = BOLT11PaymentRequest.Parse(result.Serialized, _network); return(new LightningInvoice() { Id = result.PaymentHash, Amount = parsed.MinimumAmount, ExpiresAt = parsed.ExpiryDate, BOLT11 = result.Serialized, AmountReceived = info.AmountMsat, Status = info.AmountMsat >= parsed.MinimumAmount ? LightningInvoiceStatus.Paid : DateTime.Now >= parsed.ExpiryDate ? LightningInvoiceStatus.Expired : LightningInvoiceStatus.Unpaid, PaidAt = info.ReceivedAt == 0 ? (DateTimeOffset?)null : DateTimeOffset.FromUnixTimeMilliseconds(info.ReceivedAt) }); }
public async Task <LightningInvoice> GetInvoice(string invoiceId, CancellationToken cancellation = default(CancellationToken)) { var result = await _eclairClient.GetInvoice(invoiceId, cancellation); GetReceivedInfoResponse info = null; try { info = await _eclairClient.GetReceivedInfo(invoiceId, null, cancellation); } catch (EclairClient.EclairApiException) { } var parsed = BOLT11PaymentRequest.Parse(result.Serialized, _network); var lnInvoice = new LightningInvoice() { Id = result.PaymentHash, Amount = parsed.MinimumAmount, ExpiresAt = parsed.ExpiryDate, BOLT11 = result.Serialized }; if (DateTimeOffset.UtcNow >= parsed.ExpiryDate) { lnInvoice.Status = LightningInvoiceStatus.Expired; } if (info != null && info.Status.Type == "received") { lnInvoice.AmountReceived = info.Status.Amount; lnInvoice.Status = info.Status.Amount >= parsed.MinimumAmount ? LightningInvoiceStatus.Paid : LightningInvoiceStatus.Unpaid; lnInvoice.PaidAt = info.Status.ReceivedAt; } return(lnInvoice); }
public uint256 GetPaymentHash(Network network) { return(PaymentHash ?? BOLT11PaymentRequest.Parse(BOLT11, network).PaymentHash); }
public override async Task <IPaymentMethodDetails> CreatePaymentMethodDetails( InvoiceLogs logs, LightningSupportedPaymentMethod supportedPaymentMethod, PaymentMethod paymentMethod, Data.StoreData store, BTCPayNetwork network, object preparePaymentObject) { if (paymentMethod.ParentEntity.Type == InvoiceType.TopUp) { throw new PaymentMethodUnavailableException("Lightning Network payment method is not available for top-up invoices"); } if (preparePaymentObject is null) { return(new LightningLikePaymentMethodDetails() { Activated = false }); } //direct casting to (BTCPayNetwork) is fixed in other pull requests with better generic interfacing for handlers var storeBlob = store.GetStoreBlob(); var test = GetNodeInfo(supportedPaymentMethod, network, paymentMethod.PreferOnion); var invoice = paymentMethod.ParentEntity; decimal due = Extensions.RoundUp(invoice.Price / paymentMethod.Rate, network.Divisibility); try { due = paymentMethod.Calculate().Due.ToDecimal(MoneyUnit.BTC); } catch (Exception) { // ignored } var client = supportedPaymentMethod.CreateLightningClient(network, Options.Value, _lightningClientFactory); var expiry = invoice.ExpirationTime - DateTimeOffset.UtcNow; if (expiry < TimeSpan.Zero) { expiry = TimeSpan.FromSeconds(1); } LightningInvoice?lightningInvoice = null; string description = storeBlob.LightningDescriptionTemplate; description = description.Replace("{StoreName}", store.StoreName ?? "", StringComparison.OrdinalIgnoreCase) .Replace("{ItemDescription}", invoice.Metadata.ItemDesc ?? "", StringComparison.OrdinalIgnoreCase) .Replace("{OrderId}", invoice.Metadata.OrderId ?? "", StringComparison.OrdinalIgnoreCase); using (var cts = new CancellationTokenSource(LIGHTNING_TIMEOUT)) { try { var request = new CreateInvoiceParams(new LightMoney(due, LightMoneyUnit.BTC), description, expiry); request.PrivateRouteHints = storeBlob.LightningPrivateRouteHints; lightningInvoice = await client.CreateInvoice(request, 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($"Impossible to create lightning invoice ({ex.Message})", ex); } } var nodeInfo = await test; return(new LightningLikePaymentMethodDetails { Activated = true, BOLT11 = lightningInvoice.BOLT11, PaymentHash = BOLT11PaymentRequest.Parse(lightningInvoice.BOLT11, network.NBitcoinNetwork).PaymentHash, InvoiceId = lightningInvoice.Id, NodeInfo = nodeInfo.First().ToString() }); }
public BoltInvoiceClaimDestination(string bolt11, Network network) { _bolt11 = bolt11 ?? throw new ArgumentNullException(nameof(bolt11)); _amount = BOLT11PaymentRequest.Parse(bolt11, network).MinimumAmount.ToDecimal(LightMoneyUnit.BTC); }
public BOLT11PaymentRequest ParsePaymentRequest(string payReq) { return(BOLT11PaymentRequest.Parse(payReq, _network)); }