Skip to content

Commit 82b3f07

Browse files
authored
Merge pull request #285 from starius/fix-DecodePaymentRequest
lndclient: fix decoded payment request expiry
2 parents c255827 + 1a9544b commit 82b3f07

2 files changed

Lines changed: 56 additions & 3 deletions

File tree

lightning_client.go

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2908,8 +2908,8 @@ type PaymentRequest struct {
29082908
// Timestamp of the payment request.
29092909
Timestamp time.Time
29102910

2911-
// Expiry is the time at which the payment request expires.
2912-
Expiry time.Time
2911+
// ExpiresAt is the time at which the payment request expires.
2912+
ExpiresAt time.Time
29132913

29142914
// Description is a description attached to the payment request.
29152915
Description string
@@ -2961,7 +2961,11 @@ func (s *lightningClient) DecodePaymentRequest(ctx context.Context,
29612961
}
29622962

29632963
if resp.Expiry != 0 {
2964-
paymentReq.Expiry = time.Unix(resp.Expiry, 0)
2964+
// LND reports expiry as a duration from the invoice timestamp.
2965+
invoiceTimestamp := time.Unix(resp.Timestamp, 0)
2966+
paymentReq.ExpiresAt = invoiceTimestamp.Add(
2967+
time.Duration(resp.Expiry) * time.Second,
2968+
)
29652969
}
29662970

29672971
return paymentReq, nil

lightning_client_test.go

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,13 @@ import (
44
"context"
55
"errors"
66
"testing"
7+
"time"
78

89
"github.com/lightningnetwork/lnd/lnrpc"
910
"github.com/lightningnetwork/lnd/lnrpc/invoicesrpc"
1011
"github.com/lightningnetwork/lnd/lntypes"
1112
"github.com/lightningnetwork/lnd/lnwire"
13+
"github.com/lightningnetwork/lnd/routing/route"
1214
"github.com/stretchr/testify/require"
1315
"google.golang.org/grpc"
1416
)
@@ -19,6 +21,53 @@ type addInvoiceArg struct {
1921
opts []grpc.CallOption
2022
}
2123

24+
type mockDecodePayReqRPCClient struct {
25+
lnrpc.LightningClient
26+
27+
request *lnrpc.PayReqString
28+
response *lnrpc.PayReq
29+
}
30+
31+
func (m *mockDecodePayReqRPCClient) DecodePayReq(_ context.Context,
32+
request *lnrpc.PayReqString, _ ...grpc.CallOption) (*lnrpc.PayReq,
33+
error) {
34+
35+
m.request = request
36+
37+
return m.response, nil
38+
}
39+
40+
// TestLightningClientDecodePaymentRequestExpiresAt ensures that the relative
41+
// expiry returned by lnd is converted to an absolute expiration time.
42+
func TestLightningClientDecodePaymentRequestExpiresAt(t *testing.T) {
43+
t.Parallel()
44+
45+
timestamp := time.Unix(1_700_000_000, 0)
46+
expiry := 90 * time.Minute
47+
paymentHash := lntypes.Hash{1, 2, 3}
48+
destination := route.Vertex{2}
49+
encoded := "test invoice"
50+
51+
mock := &mockDecodePayReqRPCClient{
52+
response: &lnrpc.PayReq{
53+
Destination: destination.String(),
54+
PaymentHash: paymentHash.String(),
55+
Timestamp: timestamp.Unix(),
56+
Expiry: int64(expiry.Seconds()),
57+
},
58+
}
59+
client := &lightningClient{
60+
client: mock,
61+
timeout: time.Second,
62+
}
63+
64+
request, err := client.DecodePaymentRequest(t.Context(), encoded)
65+
require.NoError(t, err)
66+
require.Equal(t, encoded, mock.request.PayReq)
67+
require.Equal(t, timestamp, request.Timestamp)
68+
require.Equal(t, timestamp.Add(expiry), request.ExpiresAt)
69+
}
70+
2271
// mockRPCClient implements lnrpc.LightningClient with dynamic method
2372
// implementations and call spying.
2473
type mockRPCClient struct {

0 commit comments

Comments
 (0)