finished LND implementation

This commit is contained in:
michael1011 2018-03-24 23:03:55 +01:00
parent cc124317ea
commit f7e60168b4
No known key found for this signature in database
GPG Key ID: 84D249BA71685D46
3 changed files with 188 additions and 8 deletions

View File

@ -3,10 +3,13 @@ package backends
import (
"context"
"encoding/hex"
"errors"
"fmt"
"github.com/lightningnetwork/lnd/lnrpc"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials"
"google.golang.org/grpc/metadata"
"io"
"io/ioutil"
)
@ -76,3 +79,41 @@ func (lnd *LND) GetInvoice(description string, value int64, expiry int64) (invoi
return response.PaymentRequest, err
}
func (lnd *LND) SubscribeInvoices() error {
stream, err := lnd.client.SubscribeInvoices(lnd.ctx, &lnrpc.InvoiceSubscription{})
if err != nil {
return err
}
wait := make(chan struct{})
go func() {
for {
in, streamErr := stream.Recv()
if streamErr == io.EOF {
err = errors.New("lost connection to LND gRPC")
close(wait)
return
}
if streamErr != nil {
err = streamErr
close(wait)
return
}
fmt.Println(in)
}
}()
<-wait
return err
}

View File

@ -10,12 +10,20 @@ import (
"strings"
)
// TODO: add option to show URI of Lightning node
const (
defaultConfigFile = "lightningTip.conf"
defaultLogFile = "lightningTip.log"
defaultLogLevel = "debug"
defaultRESTHost = "localhost:8081"
defaultTipMessage = "A generous tip"
defaultTipExpiry = 3600
defaultTipValue = 100
defaultLndRPCHost = "localhost:10009"
defaultLndCertFile = "tls.cert"
defaultMacaroonFile = "admin.macaroon"
@ -27,13 +35,18 @@ type config struct {
LogFile string `long:"logfile" Description:"Log file location"`
LogLevel string `long:"loglevel" Description:"Log level: debug, info, warning, error"`
RESTHost string `long:"resthost" Description:"Host for the rest interface of LightningTip"`
TipMessage string `long:"tipmessage" Description:"Message embedded in the payment request"`
TipExpiry int64 `long:"tipexpiry" Description:"Expiry time in seconds"`
DefaultTipValue int64 `long:"defaulttipvalue" Description:"The default value of a tip in satoshis"`
LND *backends.LND `group:"LND" namespace:"lnd"`
}
var cfg config
var backend backends.Backend
var backendName string
func initConfig() {
lndDir := getDefaultLndDir()
@ -44,6 +57,12 @@ func initConfig() {
LogFile: defaultLogFile,
LogLevel: defaultLogLevel,
RESTHost: defaultRESTHost,
TipMessage: defaultTipMessage,
TipExpiry: defaultTipExpiry,
DefaultTipValue: defaultTipValue,
LND: &backends.LND{
RPCHost: defaultLndRPCHost,
CertFile: path.Join(lndDir, defaultLndCertFile),
@ -82,9 +101,8 @@ func initConfig() {
log.Infof("Failed to parse config file: %v", errFile)
}
// TODO: add more backend options like for example c-lighting
// TODO: add more backend options like for example c-lighting and eclair
backend = cfg.LND
backendName = "LND"
}
func getDefaultLndDir() (dir string) {

View File

@ -1,6 +1,31 @@
package main
import "fmt"
import (
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"os"
"strconv"
)
type getInvoiceRequest struct {
Value int64
Message string
}
type invoiceResponse struct {
Invoice string
Error string
}
type tipValueResponse struct {
TipValue int64
}
type errorResponse struct {
Error string
}
func main() {
initLog()
@ -10,12 +35,108 @@ func main() {
err := backend.Connect()
if err == nil {
log.Info("Successfully connected to " + backendName)
http.HandleFunc("/", notFoundHandler)
http.HandleFunc("/getinvoice", getInvoiceHandler)
http.HandleFunc("/defaulttipvalue", defaultTipValueHandler)
invoice, err := backend.GetInvoice("Just a test", 1, 3600)
log.Info("Subscribing to invoices")
go func() {
err = cfg.LND.SubscribeInvoices()
if err != nil {
log.Error("Failed to subscribe to invoices: " + fmt.Sprint(err))
os.Exit(1)
}
}()
log.Info("Starting HTTP server")
go func() {
err = http.ListenAndServe(cfg.RESTHost, nil)
if err != nil {
log.Error("Failed to start HTTP server: " + fmt.Sprint(err))
os.Exit(1)
}
}()
select {}
log.Info("Got invoice " + invoice)
log.Info(fmt.Sprint(err))
}
}
func getInvoiceHandler(writer http.ResponseWriter, request *http.Request) {
var errorMessage string
tipValue := cfg.DefaultTipValue
tipMessage := cfg.TipMessage
if request.Method == http.MethodPost {
var body getInvoiceRequest
data, _ := ioutil.ReadAll(request.Body)
err := json.Unmarshal(data, &body)
if err == nil {
if body.Value != 0 {
tipValue = body.Value
}
if body.Message != "" {
tipMessage = body.Message
}
} else {
errorMessage = "Could not parse values from request"
log.Warning(errorMessage)
}
}
invoice, err := backend.GetInvoice(tipMessage, tipValue, cfg.TipExpiry)
if err == nil {
log.Info("Created invoice with value of " + strconv.FormatInt(tipValue, 10) + " satoshis")
writer.Write(marshalJson(invoiceResponse{
Invoice: invoice,
Error: errorMessage,
}))
} else {
errorMessage := "Failed to create invoice"
log.Error(errorMessage + ": " + fmt.Sprint(err))
writer.Write(marshalJson(errorResponse{
Error: errorMessage,
}))
}
}
func defaultTipValueHandler(writer http.ResponseWriter, request *http.Request) {
writer.Write(marshalJson(tipValueResponse{
TipValue: cfg.DefaultTipValue,
}))
}
func notFoundHandler(writer http.ResponseWriter, request *http.Request) {
writer.Write(marshalJson(errorResponse{
Error: "Not found",
}))
}
func marshalJson(data interface{}) []byte {
response, _ := json.MarshalIndent(data, "", " ")
return response
}