Skip to content

Commit

Permalink
Add custom TLV records to invoice (#98)
Browse files Browse the repository at this point in the history
* Add custom TLV records to invoice

Custom [TLV records](https://github.com/satoshisstream/satoshis.stream/blob/main/TLV_registry.md) only work for LND right now, Core Lightning support might come, see ElementsProject/lightning#4470

* Format files
  • Loading branch information
dennisreimann authored Sep 26, 2022
1 parent 2e865d1 commit 265fcf5
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 27 deletions.
23 changes: 12 additions & 11 deletions src/BTCPayServer.Lightning.Common/LightningInvoice.cs
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
using System;
using System.Collections.Generic;

namespace BTCPayServer.Lightning
namespace BTCPayServer.Lightning;

public class LightningInvoice
{
public class LightningInvoice
{
public string Id { get; set; }
public LightningInvoiceStatus Status { get; set; }
public string BOLT11 { get; set; }
public DateTimeOffset? PaidAt { get; set; }
public DateTimeOffset ExpiresAt { get; set; }
public LightMoney Amount { get; set; }
public LightMoney AmountReceived { get; set; }
}
public string Id { get; set; }
public LightningInvoiceStatus Status { get; set; }
public string BOLT11 { get; set; }
public DateTimeOffset? PaidAt { get; set; }
public DateTimeOffset ExpiresAt { get; set; }
public LightMoney Amount { get; set; }
public LightMoney AmountReceived { get; set; }
public Dictionary<ulong, string> CustomRecords { get; set; }
}
25 changes: 12 additions & 13 deletions src/BTCPayServer.Lightning.Common/PayInvoiceParams.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,17 @@
using System.Collections.Generic;
using NBitcoin;

namespace BTCPayServer.Lightning
namespace BTCPayServer.Lightning;

public class PayInvoiceParams
{
public class PayInvoiceParams
{
public double? MaxFeePercent { get; set; }
public Money? MaxFeeFlat { get; set; }
public LightMoney? Amount { get; set; }

public PubKey Destination { get; set; }

public uint256 PaymentHash { get; set; }

public Dictionary<ulong,string> CustomRecords { get; set; }
}
public double? MaxFeePercent { get; set; }
public Money? MaxFeeFlat { get; set; }
public LightMoney? Amount { get; set; }

public PubKey? Destination { get; set; }

public uint256? PaymentHash { get; set; }

public Dictionary<ulong, string>? CustomRecords { get; set; }
}
8 changes: 8 additions & 0 deletions src/BTCPayServer.Lightning.LND/LndClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -506,6 +506,14 @@ private static LightningInvoice ConvertLndInvoice(LnrpcInvoice resp)
Status = LightningInvoiceStatus.Unpaid,
ExpiresAt = DateTimeOffset.FromUnixTimeSeconds(ConvertInv.ToInt64(resp.Creation_date) + ConvertInv.ToInt64(resp.Expiry))
};

if (resp.Htlcs != null && resp.Htlcs.Any())
{
invoice.CustomRecords = resp.Htlcs
.SelectMany(htlc => htlc.CustomRecords)
.ToDictionary(x => x.Key, y => y.Value);
}

if (resp.Settled == true)
{
invoice.PaidAt = DateTimeOffset.FromUnixTimeSeconds(ConvertInv.ToInt64(resp.Settle_date));
Expand Down
22 changes: 19 additions & 3 deletions tests/CommonTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -383,11 +383,14 @@ public async Task CanHandleKeysend()
var paymentHash = new uint256(Hashes.SHA256(preimage));

// https://github.com/satoshisstream/satoshis.stream/blob/main/TLV_registry.md
var val5482373484 = Encoders.Base64.EncodeData(preimage);
var val696969 = Encoders.Base64.EncodeData(Encoding.Default.GetBytes("123456"));
var val112111100 = Encoders.Base64.EncodeData(Encoding.Default.GetBytes("wal_hrDHs0RBEM576"));
var tlvData = new Dictionary<ulong,string>
{
{ 5482373484, Encoders.Base64.EncodeData(preimage) },
{ 696969, Encoders.Base64.EncodeData(Encoding.Default.GetBytes("123456")) },
{ 112111100, Encoders.Base64.EncodeData(Encoding.Default.GetBytes("wal_hrDHs0RBEM576")) }
{ 696969, val696969 },
{ 112111100, val112111100 },
{ 5482373484, val5482373484 }
};
var param = new PayInvoiceParams
{
Expand Down Expand Up @@ -421,6 +424,19 @@ await Assert.ThrowsAsync<NotSupportedException>(async () =>
});
break;
}

// Check the custom records are present in the invoice
// Only works for LND right now, Core Lightning support might come, see:
// https://github.com/ElementsProject/lightning/issues/4470#issuecomment-873599548
if (src is LndClient)
{
var invoiceId = Encoders.Hex.EncodeData(paymentHash.ToBytes());
var invoice = await dest.GetInvoice(invoiceId);
Assert.NotNull(invoice.CustomRecords);
Assert.Contains(invoice.CustomRecords, pair => pair.Key == 696969 && pair.Value == val696969);
Assert.Contains(invoice.CustomRecords, pair => pair.Key == 112111100 && pair.Value == val112111100);
Assert.Contains(invoice.CustomRecords, pair => pair.Key == 5482373484 && pair.Value == val5482373484);
}
}
}

Expand Down

0 comments on commit 265fcf5

Please sign in to comment.