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