Skip to content

Commit 9bf868e

Browse files
authored
Merge pull request #107 from jstol/add-invoice-desc-hash
Include invoice description hash when adding invoice via RPC client
2 parents 66974d0 + 3e85cec commit 9bf868e

File tree

2 files changed

+178
-5
lines changed

2 files changed

+178
-5
lines changed

lightning_client.go

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1364,11 +1364,12 @@ func (s *lightningClient) AddInvoice(ctx context.Context,
13641364
defer cancel()
13651365

13661366
rpcIn := &lnrpc.Invoice{
1367-
Memo: in.Memo,
1368-
ValueMsat: int64(in.Value),
1369-
Expiry: in.Expiry,
1370-
CltvExpiry: in.CltvExpiry,
1371-
Private: true,
1367+
Memo: in.Memo,
1368+
ValueMsat: int64(in.Value),
1369+
DescriptionHash: in.DescriptionHash,
1370+
Expiry: in.Expiry,
1371+
CltvExpiry: in.CltvExpiry,
1372+
Private: true,
13721373
}
13731374

13741375
if in.Preimage != nil {

lightning_client_test.go

Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
package lndclient
2+
3+
import (
4+
"context"
5+
"errors"
6+
"testing"
7+
8+
"github.com/lightningnetwork/lnd/lnrpc"
9+
"github.com/lightningnetwork/lnd/lnrpc/invoicesrpc"
10+
"github.com/lightningnetwork/lnd/lntypes"
11+
"github.com/lightningnetwork/lnd/lnwire"
12+
"github.com/stretchr/testify/require"
13+
"google.golang.org/grpc"
14+
)
15+
16+
// addInvoiceArg records the args used in a call to mockRPCClient.AddInvoice.
17+
type addInvoiceArg struct {
18+
in *lnrpc.Invoice
19+
opts []grpc.CallOption
20+
}
21+
22+
// mockRPCClient implements lnrpc.LightningClient with dynamic method
23+
// implementations and call spying.
24+
type mockRPCClient struct {
25+
lnrpc.LightningClient
26+
27+
addInvoice func(in *lnrpc.Invoice, opts ...grpc.CallOption) (
28+
*lnrpc.AddInvoiceResponse, error)
29+
addInvoiceArgs []addInvoiceArg
30+
}
31+
32+
func (m *mockRPCClient) AddInvoice(ctx context.Context, in *lnrpc.Invoice,
33+
opts ...grpc.CallOption) (*lnrpc.AddInvoiceResponse, error) {
34+
35+
m.addInvoiceArgs = append(m.addInvoiceArgs, addInvoiceArg{
36+
in: in,
37+
opts: opts,
38+
})
39+
40+
return m.addInvoice(in, opts...)
41+
}
42+
43+
// TestLightningClientAddInvoice ensures that adding an invoice via
44+
// lightningClient is completed as expected.
45+
func TestLightningClientAddInvoice(t *testing.T) {
46+
// Define constants / fixtures.
47+
var validPreimage lntypes.Preimage
48+
copy(validPreimage[:], "valid preimage")
49+
var validRHash lntypes.Hash
50+
copy(validRHash[:], "valid hash")
51+
validAddInvoiceData := &invoicesrpc.AddInvoiceData{
52+
Memo: "fake memo",
53+
Preimage: &validPreimage,
54+
Hash: &validRHash,
55+
Value: lnwire.MilliSatoshi(500000),
56+
DescriptionHash: []byte("fake 32 byte hash"),
57+
Expiry: 123,
58+
CltvExpiry: 456,
59+
}
60+
61+
validInvoice := &lnrpc.Invoice{
62+
Memo: validAddInvoiceData.Memo,
63+
RPreimage: validAddInvoiceData.Preimage[:],
64+
RHash: validAddInvoiceData.Hash[:],
65+
ValueMsat: int64(validAddInvoiceData.Value),
66+
DescriptionHash: validAddInvoiceData.DescriptionHash,
67+
Expiry: validAddInvoiceData.Expiry,
68+
CltvExpiry: validAddInvoiceData.CltvExpiry,
69+
Private: true,
70+
}
71+
72+
validPayReq := "a valid pay req"
73+
validResp := &lnrpc.AddInvoiceResponse{
74+
RHash: validRHash[:],
75+
PaymentRequest: validPayReq,
76+
}
77+
78+
validAddInvoiceArgs := []addInvoiceArg{
79+
{in: validInvoice},
80+
}
81+
82+
validAddInvoice := func(in *lnrpc.Invoice, opts ...grpc.CallOption) (
83+
*lnrpc.AddInvoiceResponse, error) {
84+
return validResp, nil
85+
}
86+
87+
errorAddInvoice := func(in *lnrpc.Invoice, opts ...grpc.CallOption) (
88+
*lnrpc.AddInvoiceResponse, error) {
89+
return nil, errors.New("error")
90+
}
91+
92+
// Set up the test structure.
93+
type expect struct {
94+
addInvoiceArgs []addInvoiceArg
95+
hash lntypes.Hash
96+
payRequest string
97+
wantErr bool
98+
}
99+
100+
type testCase struct {
101+
name string
102+
client mockRPCClient
103+
invoice *invoicesrpc.AddInvoiceData
104+
expect expect
105+
}
106+
107+
// Run through the test cases.
108+
tests := []testCase{
109+
{
110+
name: "happy path",
111+
client: mockRPCClient{
112+
addInvoice: validAddInvoice,
113+
},
114+
invoice: validAddInvoiceData,
115+
expect: expect{
116+
addInvoiceArgs: validAddInvoiceArgs,
117+
hash: validRHash,
118+
payRequest: validPayReq,
119+
},
120+
}, {
121+
name: "rpc client error",
122+
client: mockRPCClient{
123+
addInvoice: errorAddInvoice,
124+
},
125+
invoice: validAddInvoiceData,
126+
expect: expect{
127+
addInvoiceArgs: validAddInvoiceArgs,
128+
wantErr: true,
129+
},
130+
},
131+
}
132+
133+
for _, test := range tests {
134+
test := test
135+
t.Run(test.name, func(t *testing.T) {
136+
ln := lightningClient{
137+
client: &test.client,
138+
}
139+
140+
hash, payRequest, err := ln.AddInvoice(
141+
context.Background(), test.invoice,
142+
)
143+
144+
// Check if an error (or no error) was received as
145+
// expected.
146+
if test.expect.wantErr {
147+
require.Error(t, err)
148+
} else {
149+
require.NoError(t, err)
150+
}
151+
152+
// Check if the expected hash was returned.
153+
require.Equal(
154+
t, hash, test.expect.hash,
155+
"received unexpected hash",
156+
)
157+
158+
// Check if the expected invoice was returned.
159+
require.Equal(
160+
t, payRequest, test.expect.payRequest,
161+
"received unexpected payment request",
162+
)
163+
164+
// Check if the expected args were passed to the RPC
165+
// client call.
166+
require.Equal(t, test.client.addInvoiceArgs,
167+
test.expect.addInvoiceArgs,
168+
"rpc client call was not made as expected",
169+
)
170+
})
171+
}
172+
}

0 commit comments

Comments
 (0)