lnd.go raw
1 package wrapper
2
3 import (
4 "context"
5 "crypto/tls"
6 "crypto/x509"
7 "encoding/hex"
8 "errors"
9
10 "github.com/lightningnetwork/lnd/lnrpc"
11 "github.com/lightningnetwork/lnd/lnrpc/invoicesrpc"
12 "github.com/lightningnetwork/lnd/lnrpc/routerrpc"
13 "github.com/lightningnetwork/lnd/macaroons"
14 "google.golang.org/grpc"
15 "google.golang.org/grpc/credentials"
16 "gopkg.in/macaroon.v2"
17 )
18
19 type SubscribeInvoicesWrapper interface {
20 Recv() (*lnrpc.Invoice, error)
21 }
22
23 type SubscribeSingleInvoiceWrapper interface {
24 Recv() (*lnrpc.Invoice, error)
25 }
26
27 type SubscribePaymentWrapper interface {
28 Recv() (*lnrpc.Payment, error)
29 }
30
31 // LNDoptions are the options for the connection to the lnd node.
32 type LNDoptions struct {
33 Address string
34 CertFile string
35 CertHex string
36 MacaroonFile string
37 MacaroonHex string
38 }
39
40 type LNDWrapper struct {
41 client lnrpc.LightningClient
42 routerClient routerrpc.RouterClient
43 stateClient lnrpc.StateClient
44 invoicesClient invoicesrpc.InvoicesClient
45 IdentityPubkey string
46 }
47
48 func NewLNDclient(lndOptions LNDoptions) (result *LNDWrapper, err error) {
49 // Get credentials either from a hex string, a file or the system's certificate store
50 var creds credentials.TransportCredentials
51 // if a hex string is provided
52 if lndOptions.CertHex != "" {
53 cp := x509.NewCertPool()
54 cert, err := hex.DecodeString(lndOptions.CertHex)
55 if err != nil {
56 return nil, err
57 }
58 if !cp.AppendCertsFromPEM(cert) {
59 return nil, errors.New("failed to append certificate")
60 }
61 creds = credentials.NewClientTLSFromCert(cp, "")
62 // if a path to a cert file is provided
63 } else {
64 creds = credentials.NewTLS(&tls.Config{InsecureSkipVerify: true})
65 }
66 opts := []grpc.DialOption{
67 grpc.WithTransportCredentials(creds),
68 }
69
70 var macaroonData []byte
71 if lndOptions.MacaroonHex != "" {
72 macBytes, err := hex.DecodeString(lndOptions.MacaroonHex)
73 if err != nil {
74 return nil, err
75 }
76 macaroonData = macBytes
77 } else {
78 return nil, errors.New("LND macaroon is missing")
79 }
80
81 mac := &macaroon.Macaroon{}
82 if err := mac.UnmarshalBinary(macaroonData); err != nil {
83 return nil, err
84 }
85 macCred, err := macaroons.NewMacaroonCredential(mac)
86 if err != nil {
87 return nil, err
88 }
89 opts = append(opts, grpc.WithPerRPCCredentials(macCred))
90
91 conn, err := grpc.NewClient(lndOptions.Address, opts...)
92 if err != nil {
93 return nil, err
94 }
95 lnClient := lnrpc.NewLightningClient(conn)
96 return &LNDWrapper{
97 client: lnClient,
98 routerClient: routerrpc.NewRouterClient(conn),
99 stateClient: lnrpc.NewStateClient(conn),
100 invoicesClient: invoicesrpc.NewInvoicesClient(conn),
101 }, nil
102 }
103
104 func (wrapper *LNDWrapper) ListChannels(ctx context.Context, req *lnrpc.ListChannelsRequest, options ...grpc.CallOption) (*lnrpc.ListChannelsResponse, error) {
105 return wrapper.client.ListChannels(ctx, req, options...)
106 }
107
108 func (wrapper *LNDWrapper) GetTransactions(ctx context.Context, req *lnrpc.GetTransactionsRequest, options ...grpc.CallOption) (*lnrpc.TransactionDetails, error) {
109 return wrapper.client.GetTransactions(ctx, req, options...)
110 }
111
112 func (wrapper *LNDWrapper) PendingChannels(ctx context.Context, req *lnrpc.PendingChannelsRequest, options ...grpc.CallOption) (*lnrpc.PendingChannelsResponse, error) {
113 return wrapper.client.PendingChannels(ctx, req, options...)
114 }
115
116 func (wrapper *LNDWrapper) SendPayment(ctx context.Context, req *routerrpc.SendPaymentRequest, options ...grpc.CallOption) (routerrpc.Router_SendPaymentV2Client, error) {
117 return wrapper.routerClient.SendPaymentV2(ctx, req, options...)
118 }
119
120 func (wrapper *LNDWrapper) AddInvoice(ctx context.Context, req *lnrpc.Invoice, options ...grpc.CallOption) (*lnrpc.AddInvoiceResponse, error) {
121 return wrapper.client.AddInvoice(ctx, req, options...)
122 }
123
124 func (wrapper *LNDWrapper) AddHoldInvoice(ctx context.Context, req *invoicesrpc.AddHoldInvoiceRequest, options ...grpc.CallOption) (*invoicesrpc.AddHoldInvoiceResp, error) {
125 return wrapper.invoicesClient.AddHoldInvoice(ctx, req, options...)
126 }
127
128 func (wrapper *LNDWrapper) SettleInvoice(ctx context.Context, req *invoicesrpc.SettleInvoiceMsg, options ...grpc.CallOption) (*invoicesrpc.SettleInvoiceResp, error) {
129 return wrapper.invoicesClient.SettleInvoice(ctx, req, options...)
130 }
131
132 func (wrapper *LNDWrapper) CancelInvoice(ctx context.Context, req *invoicesrpc.CancelInvoiceMsg, options ...grpc.CallOption) (*invoicesrpc.CancelInvoiceResp, error) {
133 return wrapper.invoicesClient.CancelInvoice(ctx, req, options...)
134 }
135
136 func (wrapper *LNDWrapper) SubscribeInvoices(ctx context.Context, req *lnrpc.InvoiceSubscription, options ...grpc.CallOption) (SubscribeInvoicesWrapper, error) {
137 return wrapper.client.SubscribeInvoices(ctx, req, options...)
138 }
139
140 func (wrapper *LNDWrapper) SubscribeSingleInvoice(ctx context.Context, req *invoicesrpc.SubscribeSingleInvoiceRequest, options ...grpc.CallOption) (SubscribeSingleInvoiceWrapper, error) {
141 return wrapper.invoicesClient.SubscribeSingleInvoice(ctx, req, options...)
142 }
143
144 func (wrapper *LNDWrapper) SubscribePayments(ctx context.Context, req *routerrpc.TrackPaymentsRequest, options ...grpc.CallOption) (routerrpc.Router_TrackPaymentsClient, error) {
145 return wrapper.routerClient.TrackPayments(ctx, req, options...)
146 }
147
148 func (wrapper *LNDWrapper) ListInvoices(ctx context.Context, req *lnrpc.ListInvoiceRequest, options ...grpc.CallOption) (*lnrpc.ListInvoiceResponse, error) {
149 return wrapper.client.ListInvoices(ctx, req, options...)
150 }
151
152 func (wrapper *LNDWrapper) LookupInvoice(ctx context.Context, req *lnrpc.PaymentHash, options ...grpc.CallOption) (*lnrpc.Invoice, error) {
153 return wrapper.client.LookupInvoice(ctx, req, options...)
154 }
155
156 func (wrapper *LNDWrapper) GetDebugInfo(ctx context.Context, req *lnrpc.GetDebugInfoRequest, options ...grpc.CallOption) (*lnrpc.GetDebugInfoResponse, error) {
157 return wrapper.client.GetDebugInfo(ctx, req, options...)
158 }
159
160 func (wrapper *LNDWrapper) GetInfo(ctx context.Context, req *lnrpc.GetInfoRequest, options ...grpc.CallOption) (*lnrpc.GetInfoResponse, error) {
161 return wrapper.client.GetInfo(ctx, req, options...)
162 }
163
164 func (wrapper *LNDWrapper) DescribeGraph(ctx context.Context, req *lnrpc.ChannelGraphRequest, options ...grpc.CallOption) (*lnrpc.ChannelGraph, error) {
165 return wrapper.client.DescribeGraph(ctx, req, options...)
166 }
167
168 func (wrapper *LNDWrapper) GetState(ctx context.Context, req *lnrpc.GetStateRequest, options ...grpc.CallOption) (*lnrpc.GetStateResponse, error) {
169 return wrapper.stateClient.GetState(ctx, req, options...)
170 }
171
172 func (wrapper *LNDWrapper) GetNodeInfo(ctx context.Context, req *lnrpc.NodeInfoRequest, options ...grpc.CallOption) (*lnrpc.NodeInfo, error) {
173 return wrapper.client.GetNodeInfo(ctx, req, options...)
174 }
175
176 func (wrapper *LNDWrapper) SignMessage(ctx context.Context, req *lnrpc.SignMessageRequest, options ...grpc.CallOption) (*lnrpc.SignMessageResponse, error) {
177 return wrapper.client.SignMessage(ctx, req, options...)
178 }
179
180 func (wrapper *LNDWrapper) ConnectPeer(ctx context.Context, req *lnrpc.ConnectPeerRequest, options ...grpc.CallOption) (*lnrpc.ConnectPeerResponse, error) {
181 return wrapper.client.ConnectPeer(ctx, req, options...)
182 }
183
184 func (wrapper *LNDWrapper) ListPeers(ctx context.Context, req *lnrpc.ListPeersRequest, options ...grpc.CallOption) (*lnrpc.ListPeersResponse, error) {
185 return wrapper.client.ListPeers(ctx, req, options...)
186 }
187
188 func (wrapper *LNDWrapper) OpenChannelSync(ctx context.Context, req *lnrpc.OpenChannelRequest, options ...grpc.CallOption) (*lnrpc.ChannelPoint, error) {
189 return wrapper.client.OpenChannelSync(ctx, req, options...)
190 }
191
192 func (wrapper *LNDWrapper) CloseChannel(ctx context.Context, req *lnrpc.CloseChannelRequest, options ...grpc.CallOption) (lnrpc.Lightning_CloseChannelClient, error) {
193 return wrapper.client.CloseChannel(ctx, req, options...)
194 }
195
196 func (wrapper *LNDWrapper) WalletBalance(ctx context.Context, req *lnrpc.WalletBalanceRequest, options ...grpc.CallOption) (*lnrpc.WalletBalanceResponse, error) {
197 return wrapper.client.WalletBalance(ctx, req, options...)
198 }
199
200 func (wrapper *LNDWrapper) SendCoins(ctx context.Context, req *lnrpc.SendCoinsRequest, options ...grpc.CallOption) (*lnrpc.SendCoinsResponse, error) {
201 return wrapper.client.SendCoins(ctx, req, options...)
202 }
203
204 func (wrapper *LNDWrapper) NewAddress(ctx context.Context, req *lnrpc.NewAddressRequest, options ...grpc.CallOption) (*lnrpc.NewAddressResponse, error) {
205 return wrapper.client.NewAddress(ctx, req, options...)
206 }
207
208 func (wrapper *LNDWrapper) GetChanInfo(ctx context.Context, req *lnrpc.ChanInfoRequest, options ...grpc.CallOption) (*lnrpc.ChannelEdge, error) {
209 return wrapper.client.GetChanInfo(ctx, req, options...)
210 }
211
212 func (wrapper *LNDWrapper) UpdateChannel(ctx context.Context, req *lnrpc.PolicyUpdateRequest, options ...grpc.CallOption) (*lnrpc.PolicyUpdateResponse, error) {
213 return wrapper.client.UpdateChannelPolicy(ctx, req, options...)
214 }
215
216 func (wrapper *LNDWrapper) DisconnectPeer(ctx context.Context, req *lnrpc.DisconnectPeerRequest, options ...grpc.CallOption) (*lnrpc.DisconnectPeerResponse, error) {
217 return wrapper.client.DisconnectPeer(ctx, req, options...)
218 }
219
220 func (wrapper *LNDWrapper) SubscribeChannelEvents(ctx context.Context, in *lnrpc.ChannelEventSubscription, options ...grpc.CallOption) (lnrpc.Lightning_SubscribeChannelEventsClient, error) {
221 return wrapper.client.SubscribeChannelEvents(ctx, in, options...)
222 }
223
224 func (wrapper *LNDWrapper) ForwardingHistory(ctx context.Context, in *lnrpc.ForwardingHistoryRequest, options ...grpc.CallOption) (*lnrpc.ForwardingHistoryResponse, error) {
225 return wrapper.client.ForwardingHistory(ctx, in, options...)
226 }
227