diff --git a/main.go b/cmd/server/main.go similarity index 94% rename from main.go rename to cmd/server/main.go index bf00b9d..fb53731 100644 --- a/main.go +++ b/cmd/server/main.go @@ -1,4 +1,4 @@ -package main +package server import ( "context" @@ -11,6 +11,7 @@ import ( "sync" "time" + "github.com/getAlby/lndhub.go/lnd" "github.com/getAlby/lndhub.go/rabbitmq" ddEcho "gopkg.in/DataDog/dd-trace-go.v1/contrib/labstack/echo.v4" "gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer" @@ -99,12 +100,16 @@ func main() { } } // Init new LND client - lndClient, err := InitLNClient(c, logger, startupCtx) + lnCfg, err := lnd.LoadConfig() if err != nil { - logger.Fatalf("Error initializing the %s connection: %v", c.LNClientType, err) + logger.Fatalf("Error loading LN config: %v", err) + } + lndClient, err := lnd.InitLNClient(lnCfg, logger, startupCtx) + if err != nil { + logger.Fatalf("Error initializing the %s connection: %v", lnCfg.LNClientType, err) } - logger.Infof("Connected to %s: %s", c.LNClientType, lndClient.GetMainPubkey()) + logger.Infof("Connected to %s: %s", lnCfg.LNClientType, lndClient.GetMainPubkey()) // If no RABBITMQ_URI was provided we will not attempt to create a client // No rabbitmq features will be available in this case. diff --git a/lib/service/config.go b/lib/service/config.go index ee1f998..6ddb0cf 100644 --- a/lib/service/config.go +++ b/lib/service/config.go @@ -5,12 +5,6 @@ import ( "strings" ) -const ( - LND_CLIENT_TYPE = "lnd" - LND_CLUSTER_CLIENT_TYPE = "lnd_cluster" - ECLAIR_CLIENT_TYPE = "eclair" -) - type Config struct { DatabaseUri string `envconfig:"DATABASE_URI" required:"true"` DatabaseMaxConns int `envconfig:"DATABASE_MAX_CONNS" default:"10"` @@ -25,14 +19,6 @@ type Config struct { AdminToken string `envconfig:"ADMIN_TOKEN"` JWTRefreshTokenExpiry int `envconfig:"JWT_REFRESH_EXPIRY" default:"604800"` // in seconds, default 7 days JWTAccessTokenExpiry int `envconfig:"JWT_ACCESS_EXPIRY" default:"172800"` // in seconds, default 2 days - LNClientType string `envconfig:"LN_CLIENT_TYPE" default:"lnd"` //lnd, lnd_cluster, eclair - LNDAddress string `envconfig:"LND_ADDRESS" required:"true"` - LNDMacaroonFile string `envconfig:"LND_MACAROON_FILE"` - LNDCertFile string `envconfig:"LND_CERT_FILE"` - LNDMacaroonHex string `envconfig:"LND_MACAROON_HEX"` - LNDCertHex string `envconfig:"LND_CERT_HEX"` - LNDClusterLivenessPeriod int `envconfig:"LND_CLUSTER_LIVENESS_PERIOD" default:"10"` - LNDClusterActiveChannelRatio float64 `envconfig:"LND_CLUSTER_ACTIVE_CHANNEL_RATIO" default:"0.5"` CustomName string `envconfig:"CUSTOM_NAME"` Host string `envconfig:"HOST" default:"localhost:3000"` Port int `envconfig:"PORT" default:"3000"` diff --git a/lnd/config.go b/lnd/config.go new file mode 100644 index 0000000..381ba36 --- /dev/null +++ b/lnd/config.go @@ -0,0 +1,31 @@ +package lnd + +import ( + "github.com/kelseyhightower/envconfig" +) + +const ( + LND_CLIENT_TYPE = "lnd" + LND_CLUSTER_CLIENT_TYPE = "lnd_cluster" + ECLAIR_CLIENT_TYPE = "eclair" +) + +type Config struct { + LNClientType string `envconfig:"LN_CLIENT_TYPE" default:"lnd"` //lnd, lnd_cluster, eclair + LNDAddress string `envconfig:"LND_ADDRESS" required:"true"` + LNDMacaroonFile string `envconfig:"LND_MACAROON_FILE"` + LNDCertFile string `envconfig:"LND_CERT_FILE"` + LNDMacaroonHex string `envconfig:"LND_MACAROON_HEX"` + LNDCertHex string `envconfig:"LND_CERT_HEX"` + LNDClusterLivenessPeriod int `envconfig:"LND_CLUSTER_LIVENESS_PERIOD" default:"10"` + LNDClusterActiveChannelRatio float64 `envconfig:"LND_CLUSTER_ACTIVE_CHANNEL_RATIO" default:"0.5"` +} + +func LoadConfig() (c *Config, err error) { + c = &Config{} + err = envconfig.Process("", c) + if err != nil { + return nil, err + } + return c, nil +} diff --git a/lnd/interface.go b/lnd/interface.go deleted file mode 100644 index 15fdf5a..0000000 --- a/lnd/interface.go +++ /dev/null @@ -1,28 +0,0 @@ -package lnd - -import ( - "context" - - "github.com/lightningnetwork/lnd/lnrpc" - "github.com/lightningnetwork/lnd/lnrpc/routerrpc" - "google.golang.org/grpc" -) - -type LightningClientWrapper interface { - ListChannels(ctx context.Context, req *lnrpc.ListChannelsRequest, options ...grpc.CallOption) (*lnrpc.ListChannelsResponse, error) - SendPaymentSync(ctx context.Context, req *lnrpc.SendRequest, options ...grpc.CallOption) (*lnrpc.SendResponse, error) - AddInvoice(ctx context.Context, req *lnrpc.Invoice, options ...grpc.CallOption) (*lnrpc.AddInvoiceResponse, error) - SubscribeInvoices(ctx context.Context, req *lnrpc.InvoiceSubscription, options ...grpc.CallOption) (SubscribeInvoicesWrapper, error) - SubscribePayment(ctx context.Context, req *routerrpc.TrackPaymentRequest, options ...grpc.CallOption) (SubscribePaymentWrapper, error) - GetInfo(ctx context.Context, req *lnrpc.GetInfoRequest, options ...grpc.CallOption) (*lnrpc.GetInfoResponse, error) - DecodeBolt11(ctx context.Context, bolt11 string, options ...grpc.CallOption) (*lnrpc.PayReq, error) - IsIdentityPubkey(pubkey string) (isOurPubkey bool) - GetMainPubkey() (pubkey string) -} - -type SubscribeInvoicesWrapper interface { - Recv() (*lnrpc.Invoice, error) -} -type SubscribePaymentWrapper interface { - Recv() (*lnrpc.Payment, error) -} diff --git a/init_lnd.go b/lnd/ln_client.go similarity index 51% rename from init_lnd.go rename to lnd/ln_client.go index 44d6440..41b3853 100644 --- a/init_lnd.go +++ b/lnd/ln_client.go @@ -1,29 +1,48 @@ -package main +package lnd import ( "context" "fmt" "strings" - "github.com/getAlby/lndhub.go/lib/service" - "github.com/getAlby/lndhub.go/lnd" "github.com/lightningnetwork/lnd/lnrpc" + "github.com/lightningnetwork/lnd/lnrpc/routerrpc" "github.com/ziflex/lecho/v3" + "google.golang.org/grpc" ) -func InitLNClient(c *service.Config, logger *lecho.Logger, ctx context.Context) (result lnd.LightningClientWrapper, err error) { +type LightningClientWrapper interface { + ListChannels(ctx context.Context, req *lnrpc.ListChannelsRequest, options ...grpc.CallOption) (*lnrpc.ListChannelsResponse, error) + SendPaymentSync(ctx context.Context, req *lnrpc.SendRequest, options ...grpc.CallOption) (*lnrpc.SendResponse, error) + AddInvoice(ctx context.Context, req *lnrpc.Invoice, options ...grpc.CallOption) (*lnrpc.AddInvoiceResponse, error) + SubscribeInvoices(ctx context.Context, req *lnrpc.InvoiceSubscription, options ...grpc.CallOption) (SubscribeInvoicesWrapper, error) + SubscribePayment(ctx context.Context, req *routerrpc.TrackPaymentRequest, options ...grpc.CallOption) (SubscribePaymentWrapper, error) + GetInfo(ctx context.Context, req *lnrpc.GetInfoRequest, options ...grpc.CallOption) (*lnrpc.GetInfoResponse, error) + DecodeBolt11(ctx context.Context, bolt11 string, options ...grpc.CallOption) (*lnrpc.PayReq, error) + IsIdentityPubkey(pubkey string) (isOurPubkey bool) + GetMainPubkey() (pubkey string) +} + +type SubscribeInvoicesWrapper interface { + Recv() (*lnrpc.Invoice, error) +} +type SubscribePaymentWrapper interface { + Recv() (*lnrpc.Payment, error) +} + +func InitLNClient(c *Config, logger *lecho.Logger, ctx context.Context) (result LightningClientWrapper, err error) { switch c.LNClientType { - case service.LND_CLIENT_TYPE: + case LND_CLIENT_TYPE: return InitSingleLNDClient(c, ctx) - case service.LND_CLUSTER_CLIENT_TYPE: + case LND_CLUSTER_CLIENT_TYPE: return InitLNDCluster(c, logger, ctx) default: return nil, fmt.Errorf("Did not recognize LN client type %s", c.LNClientType) } } -func InitSingleLNDClient(c *service.Config, ctx context.Context) (result lnd.LightningClientWrapper, err error) { - client, err := lnd.NewLNDclient(lnd.LNDoptions{ +func InitSingleLNDClient(c *Config, ctx context.Context) (result LightningClientWrapper, err error) { + client, err := NewLNDclient(LNDoptions{ Address: c.LNDAddress, MacaroonFile: c.LNDMacaroonFile, MacaroonHex: c.LNDMacaroonHex, @@ -40,8 +59,8 @@ func InitSingleLNDClient(c *service.Config, ctx context.Context) (result lnd.Lig client.IdentityPubkey = getInfo.IdentityPubkey return client, nil } -func InitLNDCluster(c *service.Config, logger *lecho.Logger, ctx context.Context) (result lnd.LightningClientWrapper, err error) { - nodes := []lnd.LightningClientWrapper{} +func InitLNDCluster(c *Config, logger *lecho.Logger, ctx context.Context) (result LightningClientWrapper, err error) { + nodes := []LightningClientWrapper{} //interpret lnd address, macaroon file & cert file as comma seperated values addresses := strings.Split(c.LNDAddress, ",") macaroons := strings.Split(c.LNDMacaroonFile, ",") @@ -50,7 +69,7 @@ func InitLNDCluster(c *service.Config, logger *lecho.Logger, ctx context.Context return nil, fmt.Errorf("Error parsing LND cluster config: addresses, macaroons or certs array length mismatch") } for i := 0; i < len(addresses); i++ { - n, err := lnd.NewLNDclient(lnd.LNDoptions{ + n, err := NewLNDclient(LNDoptions{ Address: addresses[i], MacaroonFile: macaroons[i], CertFile: certs[i], @@ -66,7 +85,7 @@ func InitLNDCluster(c *service.Config, logger *lecho.Logger, ctx context.Context nodes = append(nodes, n) } logger.Infof("Initialized LND cluster with %d nodes", len(nodes)) - cluster := &lnd.LNDCluster{ + cluster := &LNDCluster{ Nodes: nodes, ActiveChannelRatio: c.LNDClusterActiveChannelRatio, ActiveNode: nodes[0],