Skip to content

Commit

Permalink
feat: config db
Browse files Browse the repository at this point in the history
  • Loading branch information
rolznz committed Jan 18, 2024
1 parent 09cc94d commit a256049
Show file tree
Hide file tree
Showing 7 changed files with 97 additions and 67 deletions.
32 changes: 14 additions & 18 deletions api.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import (
"github.com/getAlby/nostr-wallet-connect/models/db"
"github.com/nbd-wtf/go-nostr"
"gorm.io/gorm"
"gorm.io/gorm/clause"
)

// TODO: these methods should be moved to a separate object, not in Service
Expand Down Expand Up @@ -221,40 +220,37 @@ func (svc *Service) GetInfo() *api.InfoResponse {
}

func (svc *Service) Setup(setupRequest *api.SetupRequest) error {
dbConfigEntries := []db.ConfigEntry{}

dbConfigEntries = append(dbConfigEntries, db.ConfigEntry{Key: "LN_BACKEND_TYPE", Value: setupRequest.LNBackendType})

// TODO: reduce duplication
dbConfig := db.Config{}
svc.db.First(&dbConfig)

// only update non-empty values
if setupRequest.LNBackendType != "" {
dbConfig.LNBackendType = setupRequest.LNBackendType
}
if setupRequest.BreezMnemonic != "" {
dbConfigEntries = append(dbConfigEntries, db.ConfigEntry{Key: "BREEZ_MNEMONIC", Value: setupRequest.BreezMnemonic})
dbConfig.BreezMnemonic = setupRequest.BreezMnemonic
}
if setupRequest.GreenlightInviteCode != "" {
dbConfigEntries = append(dbConfigEntries, db.ConfigEntry{Key: "GREENLIGHT_INVITE_CODE", Value: setupRequest.GreenlightInviteCode})
dbConfig.GreenlightInviteCode = setupRequest.GreenlightInviteCode
}

if setupRequest.LNDAddress != "" {
dbConfigEntries = append(dbConfigEntries, db.ConfigEntry{Key: "LND_ADDRESS", Value: setupRequest.LNDAddress})
dbConfig.LNDAddress = setupRequest.LNDAddress
}
if setupRequest.LNDCertFile != "" {
dbConfigEntries = append(dbConfigEntries, db.ConfigEntry{Key: "LND_CERT_FILE", Value: setupRequest.LNDCertFile})
dbConfig.LNDCertFile = setupRequest.LNDCertFile
}
if setupRequest.LNDCertHex != "" {
dbConfigEntries = append(dbConfigEntries, db.ConfigEntry{Key: "LND_CERT_HEX", Value: setupRequest.LNDCertHex})
dbConfig.LNDCertHex = setupRequest.LNDCertHex
}
if setupRequest.LNDMacaroonFile != "" {
dbConfigEntries = append(dbConfigEntries, db.ConfigEntry{Key: "LND_MACAROON_FILE", Value: setupRequest.LNDMacaroonFile})
dbConfig.LNDMacaroonFile = setupRequest.LNDMacaroonFile
}
if setupRequest.LNDMacaroonHex != "" {
dbConfigEntries = append(dbConfigEntries, db.ConfigEntry{Key: "LND_MACAROON_HEX", Value: setupRequest.LNDMacaroonHex})
dbConfig.LNDMacaroonHex = setupRequest.LNDMacaroonHex
}

// replace existing keys with latest values
res := svc.db.Clauses(clause.OnConflict{
Columns: []clause.Column{{Name: "key"}},
DoUpdates: clause.AssignmentColumns([]string{"value"}),
}).Create(&dbConfigEntries)
res := svc.db.Save(&dbConfig)

if res.Error != nil {
svc.Logger.Errorf("Failed to update config: %v", res.Error)
Expand Down
13 changes: 5 additions & 8 deletions config.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package main

import "github.com/getAlby/nostr-wallet-connect/models/db"

const (
AlbyBackendType = "ALBY"
LNDBackendType = "LND"
Expand All @@ -11,22 +13,17 @@ const (
)

type Config struct {
// These config can be set either by .env or the database config table.
// database config always takes preference.
db.Config
NostrSecretKey string `envconfig:"NOSTR_PRIVKEY"`
CookieSecret string `envconfig:"COOKIE_SECRET" required:"true"`
CookieDomain string `envconfig:"COOKIE_DOMAIN"`
ClientPubkey string `envconfig:"CLIENT_NOSTR_PUBKEY"`
Relay string `envconfig:"RELAY" default:"wss://relay.getalby.com/v1"`
PublicRelay string `envconfig:"PUBLIC_RELAY"`
LNBackendType string `envconfig:"LN_BACKEND_TYPE"`
AppType string `envconfig:"APP_TYPE" default:"HTTP"`
LNDAddress string `envconfig:"LND_ADDRESS"`
LNDCertFile string `envconfig:"LND_CERT_FILE"`
LNDCertHex string `envconfig:"LND_CERT_HEX"`
LNDMacaroonFile string `envconfig:"LND_MACAROON_FILE"`
LNDMacaroonHex string `envconfig:"LND_MACAROON_HEX"`
BreezMnemonic string `envconfig:"BREEZ_MNEMONIC"`
BreezAPIKey string `envconfig:"BREEZ_API_KEY"`
GreenlightInviteCode string `envconfig:"GREENLIGHT_INVITE_CODE"`
BreezWorkdir string `envconfig:"BREEZ_WORK_DIR" default:".breez"`
BasicAuthUser string `envconfig:"BASIC_AUTH_USER"`
BasicAuthPassword string `envconfig:"BASIC_AUTH_PASSWORD"`
Expand Down
1 change: 1 addition & 0 deletions lnd.go
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,7 @@ func NewLNDService(svc *Service, lndAddress, lndCertFile, lndCertHex, lndMacaroo
MacaroonHex: lndMacaroonHex,
}, svc.ctx)
if err != nil {
svc.Logger.Errorf("Failed to create new LND client %v", err)
return nil, err
}
info, err := lndClient.GetInfo(svc.ctx, &lnrpc.GetInfoRequest{})
Expand Down
91 changes: 56 additions & 35 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,11 @@ func main() {
ctx: ctx,
}

err = svc.setupDbConfig()
if err != nil {
log.Fatalf("Failed to setup DB config: %v", err)
}

// TODO: remove Datadog etc.
if os.Getenv("DATADOG_AGENT_URL") != "" {
tracer.Start(tracer.WithService("nostr-wallet-connect"))
Expand Down Expand Up @@ -244,6 +249,42 @@ func main() {
wg.Wait()
}

func (svc *Service) setupDbConfig() error {
// setup database config from the env on first run
// after first run, changes to ENV will have no effect for these fields
// because the database values always take precedence!

var existing db.Config
res := svc.db.Limit(1).Find(&existing)

if res.Error != nil {
return res.Error
}

if res.RowsAffected > 0 {
// do not overwrite the existing entry
return nil
}

newDbConfig := db.Config{
ID: 1,
LNBackendType: svc.cfg.LNBackendType,
LNDAddress: svc.cfg.LNDAddress,
LNDCertFile: svc.cfg.LNDCertFile,
LNDCertHex: svc.cfg.LNDCertHex,
LNDMacaroonFile: svc.cfg.LNDMacaroonFile,
LNDMacaroonHex: svc.cfg.LNDMacaroonHex,
BreezMnemonic: svc.cfg.BreezMnemonic,
GreenlightInviteCode: svc.cfg.GreenlightInviteCode,
}
err := svc.db.Save(&newDbConfig).Error
if err != nil {
return err
}

return nil
}

func (svc *Service) launchLNBackend() error {
if svc.lnClient != nil {
err := svc.lnClient.Shutdown()
Expand All @@ -253,48 +294,28 @@ func (svc *Service) launchLNBackend() error {
svc.lnClient = nil
}

dbCfgEntries := []db.ConfigEntry{}
svc.db.Find(&dbCfgEntries)
dbConfig := db.Config{}
svc.db.First(&dbConfig)

mergeConfigEntry := func(defaultValue string, key string) string {
for _, v := range dbCfgEntries {
if v.Key == key {
return v.Value
}
}
return ""
if dbConfig.LNBackendType == "" {
return errors.New("No LNBackendType specified")
}

// TODO: is there a better way to do this?
lnBackendType := mergeConfigEntry(svc.cfg.LNBackendType, "LN_BACKEND_TYPE")
breezMnemonic := mergeConfigEntry(svc.cfg.BreezMnemonic, "BREEZ_MNEMONIC")
greenlightInviteCode := mergeConfigEntry(svc.cfg.GreenlightInviteCode, "GREENLIGHT_INVITE_CODE")

lndAddress := mergeConfigEntry(svc.cfg.LNDAddress, "LND_ADDRESS")
lndCertFile := mergeConfigEntry(svc.cfg.LNDCertFile, "LND_CERT_FILE")
lndCertHex := mergeConfigEntry(svc.cfg.LNDCertHex, "LND_CERT_HEX")
lndMacaroonFile := mergeConfigEntry(svc.cfg.LNDMacaroonFile, "LND_MACAROON_FILE")
lndMacaroonHex := mergeConfigEntry(svc.cfg.LNDMacaroonHex, "LND_MACAROON_HEX")

svc.Logger.Infof("Launching new LN Backend: %s", lnBackendType)
switch lnBackendType {
svc.Logger.Infof("Launching LN Backend: %s", dbConfig.LNBackendType)
var err error
var lnClient LNClient
switch dbConfig.LNBackendType {
case LNDBackendType:
lndClient, err := NewLNDService(svc, lndAddress, lndCertFile, lndCertHex, lndMacaroonFile, lndMacaroonHex)
if err != nil {
return err
}
svc.lnClient = lndClient
lnClient, err = NewLNDService(svc, dbConfig.LNDAddress, dbConfig.LNDCertFile, dbConfig.LNDCertHex, dbConfig.LNDMacaroonFile, dbConfig.LNDMacaroonHex)
case BreezBackendType:
breezSvc, err := NewBreezService(svc, breezMnemonic, svc.cfg.BreezAPIKey, greenlightInviteCode, svc.cfg.BreezWorkdir)
if err != nil {
return err
}
svc.lnClient = breezSvc
case "":
return errors.New("No LNBackendType specified")
lnClient, err = NewBreezService(svc, dbConfig.BreezMnemonic, svc.cfg.BreezAPIKey, dbConfig.GreenlightInviteCode, svc.cfg.BreezWorkdir)
default:
svc.Logger.Fatalf("Unsupported LNBackendType: %v", lnBackendType)
svc.Logger.Fatalf("Unsupported LNBackendType: %v", dbConfig.LNBackendType)
}
if err != nil {
return err
}
svc.lnClient = lnClient
return nil
}

Expand Down
13 changes: 10 additions & 3 deletions migrations/202401161432_add_config_table.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,16 @@ var _202401161432_add_config_table = &gormigrate.Migration{
ID: "202401161432_add_config_table",
Migrate: func(tx *gorm.DB) error {
return tx.Exec(`
CREATE TABLE config_entries (
key TEXT PRIMARY KEY,
value TEXT
CREATE TABLE configs (
id int NOT NULL PRIMARY KEY,
ln_backend_type TEXT,
lnd_address TEXT,
lnd_cert_file TEXT,
lnd_cert_hex TEXT,
lnd_macaroon_file TEXT,
lnd_macaroon_hex TEXT,
breez_mnemonic TEXT,
greenlight_invite_code TEXT
);`).Error
},
Rollback: func(tx *gorm.DB) error {
Expand Down
13 changes: 10 additions & 3 deletions models/db/db.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
package db

type ConfigEntry struct {
Key string
Value string
type Config struct {
ID int // primary key, always 1
LNBackendType string `envconfig:"LN_BACKEND_TYPE"`
LNDAddress string `envconfig:"LND_ADDRESS"`
LNDCertFile string `envconfig:"LND_CERT_FILE"`
LNDCertHex string `envconfig:"LND_CERT_HEX"`
LNDMacaroonFile string `envconfig:"LND_MACAROON_FILE"`
LNDMacaroonHex string `envconfig:"LND_MACAROON_HEX"`
BreezMnemonic string `envconfig:"BREEZ_MNEMONIC"`
GreenlightInviteCode string `envconfig:"GREENLIGHT_INVITE_CODE"`
}
1 change: 1 addition & 0 deletions service.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (
)

type Service struct {
// config from .env only. Fetch dynamic config from db
cfg *Config
db *gorm.DB
lnClient LNClient
Expand Down

0 comments on commit a256049

Please sign in to comment.