diff --git a/cmd/arkd/commands.go b/cmd/arkd/commands.go index 0d7c17e44..0d62be81e 100644 --- a/cmd/arkd/commands.go +++ b/cmd/arkd/commands.go @@ -17,10 +17,15 @@ const ONE_BTC = float64(1_00_000_000) // commands var ( - startCmd = &cli.Command{ - Name: "start", - Usage: "Starts the arkd server", - Action: startAction, + // startCmdWrapper is a wrapper around the start command defined in start.go + // TODO: This should disappear when we migrate all sub-commands from urfave/cli to spf13/cobra. + startCmdWrapper = &cli.Command{ + Name: "start", + Usage: "Starts the arkd server", + SkipFlagParsing: true, + Action: func(_ *cli.Context) error { + return startCmd.Execute() + }, } walletCmd = &cli.Command{ diff --git a/cmd/arkd/main.go b/cmd/arkd/main.go index 62092e675..deacc7c9e 100755 --- a/cmd/arkd/main.go +++ b/cmd/arkd/main.go @@ -1,14 +1,8 @@ package main import ( - "fmt" "os" - "os/signal" - "syscall" - "github.com/arkade-os/arkd/internal/config" - grpcservice "github.com/arkade-os/arkd/internal/interface/grpc" - "github.com/arkade-os/arkd/internal/telemetry" log "github.com/sirupsen/logrus" "github.com/urfave/cli/v2" ) @@ -23,53 +17,6 @@ const ( tlsCertFile = "cert.pem" ) -func startAction(_ *cli.Context) error { - cfg, err := config.LoadConfig() - if err != nil { - return fmt.Errorf("invalid config: %s", err) - } - - log.SetLevel(log.Level(cfg.LogLevel)) - if cfg.OtelCollectorEndpoint != "" { - log.AddHook(telemetry.NewOTelHook()) - } - - svcConfig := grpcservice.Config{ - Datadir: cfg.Datadir, - Port: cfg.Port, - AdminPort: cfg.AdminPort, - NoTLS: cfg.NoTLS, - NoMacaroons: cfg.NoMacaroons, - TLSExtraIPs: cfg.TLSExtraIPs, - TLSExtraDomains: cfg.TLSExtraDomains, - HeartbeatInterval: cfg.HeartbeatInterval, - EnablePprof: cfg.EnablePprof, - } - - svc, err := grpcservice.NewService(Version, svcConfig, cfg) - if err != nil { - return err - } - - log.Infof("ark server config: %s", cfg) - - log.Debug("starting service...") - if err := svc.Start(); err != nil { - return err - } - - log.RegisterExitHandler(svc.Stop) - - sigChan := make(chan os.Signal, 1) - signal.Notify(sigChan, syscall.SIGTERM, syscall.SIGINT, syscall.SIGQUIT, os.Interrupt) - <-sigChan - - log.Debug("shutting down service...") - log.Exit(0) - - return nil -} - func main() { app := cli.NewApp() app.Version = Version @@ -78,7 +25,7 @@ func main() { app.UsageText = "Run the Ark Server with:\n\tarkd\nManage the Ark Server with:\n\tarkd [global options] command [command options]" app.Commands = append( app.Commands, - startCmd, + startCmdWrapper, versionCmd, walletCmd, signerCmd, @@ -93,7 +40,7 @@ func main() { convictionsCmd, ) - app.DefaultCommand = startCmd.Name + app.DefaultCommand = startCmd.Use app.Flags = append(app.Flags, urlFlag, datadirFlag, macaroonFlag) if err := app.Run(os.Args); err != nil { diff --git a/cmd/arkd/root.go b/cmd/arkd/root.go new file mode 100644 index 000000000..f82ad80e8 --- /dev/null +++ b/cmd/arkd/root.go @@ -0,0 +1,17 @@ +package main + +import ( + "strings" + + "github.com/spf13/viper" +) + +// EnvReplacer replaces `-` to `_`. +// This is used to map flag like `--my-param` to environment variables like `MY_PARAM`. +var envReplacer = strings.NewReplacer("-", "_") + +func init() { + viper.SetEnvPrefix("ARKD") + viper.AutomaticEnv() + viper.SetEnvKeyReplacer(envReplacer) +} diff --git a/cmd/arkd/start.go b/cmd/arkd/start.go new file mode 100644 index 000000000..be661299a --- /dev/null +++ b/cmd/arkd/start.go @@ -0,0 +1,94 @@ +package main + +import ( + "fmt" + "os" + "os/signal" + "strings" + "syscall" + + "github.com/arkade-os/arkd/internal/config" + grpcservice "github.com/arkade-os/arkd/internal/interface/grpc" + "github.com/arkade-os/arkd/internal/telemetry" + log "github.com/sirupsen/logrus" + "github.com/spf13/cobra" + "github.com/spf13/pflag" + "github.com/spf13/viper" + "github.com/urfave/cli/v2" +) + +var startCmd = &cobra.Command{ + Use: "start", + Short: "Start the Ark Server", + Long: `Start the Ark Server daemon to serve gRPC requests.`, + RunE: func(cmd *cobra.Command, args []string) error { + return startAction(nil) + }, +} + +// startAction is a wrapper to a cobra command that starts the arkd server. +func startAction(_ *cli.Context) error { + cfg, err := config.LoadConfig() + if err != nil { + return fmt.Errorf("invalid config: %s", err) + } + + log.SetLevel(log.Level(cfg.LogLevel)) + if cfg.OtelCollectorEndpoint != "" { + log.AddHook(telemetry.NewOTelHook()) + } + + svcConfig := grpcservice.Config{ + Datadir: cfg.Datadir, + Port: cfg.Port, + AdminPort: cfg.AdminPort, + NoTLS: cfg.NoTLS, + NoMacaroons: cfg.NoMacaroons, + TLSExtraIPs: cfg.TLSExtraIPs, + TLSExtraDomains: cfg.TLSExtraDomains, + HeartbeatInterval: cfg.HeartbeatInterval, + EnablePprof: cfg.EnablePprof, + } + + svc, err := grpcservice.NewService(Version, svcConfig, cfg) + if err != nil { + return err + } + + log.Infof("ark server config: %s", cfg) + + log.Debug("starting service...") + if err := svc.Start(); err != nil { + return err + } + + log.RegisterExitHandler(svc.Stop) + + sigChan := make(chan os.Signal, 1) + signal.Notify(sigChan, syscall.SIGTERM, syscall.SIGINT, syscall.SIGQUIT, os.Interrupt) + <-sigChan + + log.Debug("shutting down service...") + log.Exit(0) + + return nil +} + +func init() { + config.SetupFlags(startCmd) + + // TODO: Move this to the root cmd upon urfave/cli -> spf13/cobra migration. + _ = viper.BindPFlags(startCmd.Flags()) + + // Update the flag's Usage to display the corresponding env var name when --help is invoked. + startCmd.Flags().VisitAll(func(f *pflag.Flag) { + envVar := strings.ToUpper(envReplacer.Replace(f.Name)) + envUsage := fmt.Sprintf("[ARKD_%s]", envVar) + + if f.Usage == "" { + f.Usage = envUsage + } else { + f.Usage = f.Usage + " " + envUsage + } + }) +} diff --git a/go.mod b/go.mod index 8d9526c34..955ad9e53 100644 --- a/go.mod +++ b/go.mod @@ -44,6 +44,7 @@ require ( github.com/redis/go-redis/v9 v9.10.0 github.com/shopspring/decimal v1.2.0 github.com/sirupsen/logrus v1.9.3 + github.com/spf13/cobra v1.10.2 github.com/spf13/viper v1.20.1 github.com/sqlc-dev/pqtype v0.3.0 github.com/stretchr/testify v1.11.1 @@ -122,6 +123,7 @@ require ( github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect + github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/jackc/chunkreader/v2 v2.0.1 // indirect github.com/jackc/pgconn v1.14.3 // indirect github.com/jackc/pgerrcode v0.0.0-20240316143900-6e2875d9b438 // indirect @@ -256,7 +258,7 @@ require ( github.com/sourcegraph/conc v0.3.0 // indirect github.com/spf13/afero v1.12.0 // indirect github.com/spf13/cast v1.7.1 // indirect - github.com/spf13/pflag v1.0.6 // indirect + github.com/spf13/pflag v1.0.9 github.com/subosito/gotenv v1.6.0 // indirect go.uber.org/atomic v1.11.0 // indirect go.uber.org/multierr v1.11.0 // indirect diff --git a/go.sum b/go.sum index 0fb01ea6a..5dfa56704 100644 --- a/go.sum +++ b/go.sum @@ -288,6 +288,8 @@ github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyf github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= +github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/jackc/chunkreader v1.0.0/go.mod h1:RT6O25fNZIuasFJRyZ4R/Y2BbhasbmZXF9QQ7T3kePo= github.com/jackc/chunkreader/v2 v2.0.0/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk= github.com/jackc/chunkreader/v2 v2.0.1 h1:i+RDz65UE+mmpjTfyz0MoVTnzeYxroil2G82ki7MGG8= @@ -555,10 +557,12 @@ github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkU github.com/spf13/cast v1.7.1 h1:cuNEagBQEHWN1FnbGEjCXL2szYEXqfJPbP2HNUaca9Y= github.com/spf13/cast v1.7.1/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= +github.com/spf13/cobra v1.10.2 h1:DMTTonx5m65Ic0GOoRY2c16WCbHxOOw6xxezuLaBpcU= +github.com/spf13/cobra v1.10.2/go.mod h1:7C1pvHqHw5A4vrJfjNwvOdzYu0Gml16OCs2GRiTUUS4= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= -github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o= -github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/pflag v1.0.9 h1:9exaQaMOCwffKiiiYk6/BndUBv+iRViNW+4lEMi0PvY= +github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= github.com/spf13/viper v1.20.1 h1:ZMi+z/lvLyPSCoNtFCpqjy0S4kPbirhpTMwl8BkW9X4= github.com/spf13/viper v1.20.1/go.mod h1:P9Mdzt1zoHIG8m2eZQinpiBjo6kCmZSKBClNNqjJvu4= @@ -701,6 +705,7 @@ go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= go.uber.org/zap v1.18.1/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= +go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= golang.org/x/crypto v0.0.0-20170613210332-850760c427c5/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180723164146-c126467f60eb/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= diff --git a/internal/config/config.go b/internal/config/config.go index c1de51591..703fa5f07 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -25,6 +25,7 @@ import ( arklib "github.com/arkade-os/arkd/pkg/ark-lib" "github.com/redis/go-redis/v9" log "github.com/sirupsen/logrus" + "github.com/spf13/cobra" "github.com/spf13/viper" ) @@ -153,63 +154,63 @@ func (c *Config) String() string { } var ( - Datadir = "DATADIR" - WalletAddr = "WALLET_ADDR" - SignerAddr = "SIGNER_ADDR" - SessionDuration = "SESSION_DURATION" - BanDuration = "BAN_DURATION" - BanThreshold = "BAN_THRESHOLD" - Port = "PORT" - AdminPort = "ADMIN_PORT" - EventDbType = "EVENT_DB_TYPE" - DbType = "DB_TYPE" - DbUrl = "PG_DB_URL" - PostgresAutoCreateDB = "PG_DB_AUTOCREATE" - EventDbUrl = "PG_EVENT_DB_URL" - SchedulerType = "SCHEDULER_TYPE" - TxBuilderType = "TX_BUILDER_TYPE" - LiveStoreType = "LIVE_STORE_TYPE" - RedisUrl = "REDIS_URL" - RedisTxNumOfRetries = "REDIS_NUM_OF_RETRIES" - LogLevel = "LOG_LEVEL" - VtxoTreeExpiry = "VTXO_TREE_EXPIRY" - UnilateralExitDelay = "UNILATERAL_EXIT_DELAY" - PublicUnilateralExitDelay = "PUBLIC_UNILATERAL_EXIT_DELAY" - CheckpointExitDelay = "CHECKPOINT_EXIT_DELAY" - BoardingExitDelay = "BOARDING_EXIT_DELAY" - EsploraURL = "ESPLORA_URL" - AlertManagerURL = "ALERT_MANAGER_URL" - NoMacaroons = "NO_MACAROONS" - NoTLS = "NO_TLS" - TLSExtraIP = "TLS_EXTRA_IP" - TLSExtraDomain = "TLS_EXTRA_DOMAIN" - UnlockerType = "UNLOCKER_TYPE" - UnlockerFilePath = "UNLOCKER_FILE_PATH" - UnlockerPassword = "UNLOCKER_PASSWORD" - NoteUriPrefix = "NOTE_URI_PREFIX" - ScheduledSessionStartTime = "SCHEDULED_SESSION_START_TIME" - ScheduledSessionEndTime = "SCHEDULED_SESSION_END_TIME" - ScheduledSessionPeriod = "SCHEDULED_SESSION_PERIOD" - ScheduledSessionDuration = "SCHEDULED_SESSION_DURATION" - ScheduledSessionMinRoundParticipants = "SCHEDULED_SESSION_MIN_ROUND_PARTICIPANTS_COUNT" - ScheduledSessionMaxRoundParticipants = "SCHEDULED_SESSION_MAX_ROUND_PARTICIPANTS_COUNT" - OtelCollectorEndpoint = "OTEL_COLLECTOR_ENDPOINT" - OtelPushInterval = "OTEL_PUSH_INTERVAL" - PyroscopeServerURL = "PYROSCOPE_SERVER_URL" - RoundMaxParticipantsCount = "ROUND_MAX_PARTICIPANTS_COUNT" - RoundMinParticipantsCount = "ROUND_MIN_PARTICIPANTS_COUNT" - UtxoMaxAmount = "UTXO_MAX_AMOUNT" - VtxoMaxAmount = "VTXO_MAX_AMOUNT" - UtxoMinAmount = "UTXO_MIN_AMOUNT" - VtxoMinAmount = "VTXO_MIN_AMOUNT" - AllowCSVBlockType = "ALLOW_CSV_BLOCK_TYPE" - HeartbeatInterval = "HEARTBEAT_INTERVAL" - RoundReportServiceEnabled = "ROUND_REPORT_ENABLED" - SettlementMinExpiryGap = "SETTLEMENT_MIN_EXPIRY_GAP" + Datadir = "datadir" + WalletAddr = "wallet-addr" + SignerAddr = "signer-addr" + SessionDuration = "session-duration" + BanDuration = "ban-duration" + BanThreshold = "ban-threshold" + Port = "port" + AdminPort = "admin-port" + EventDbType = "event-db-type" + DbType = "db-type" + DbUrl = "pg-db-url" + PostgresAutoCreateDB = "pg-db-autocreate" + EventDbUrl = "pg-event-db-url" + SchedulerType = "scheduler-type" + TxBuilderType = "tx-builder-type" + LiveStoreType = "live-store-type" + RedisUrl = "redis-url" + RedisTxNumOfRetries = "redis-num-of-retries" + LogLevel = "log-level" + VtxoTreeExpiry = "vtxo-tree-expiry" + UnilateralExitDelay = "unilateral-exit-delay" + PublicUnilateralExitDelay = "public-unilateral-exit-delay" + CheckpointExitDelay = "checkpoint-exit-delay" + BoardingExitDelay = "boarding-exit-delay" + EsploraURL = "esplora-url" + AlertManagerURL = "alert-manager-url" + NoMacaroons = "no-macaroons" + NoTLS = "no-tls" + TLSExtraIP = "tls-extra-ip" + TLSExtraDomain = "tls-extra-domain" + UnlockerType = "unlocker-type" + UnlockerFilePath = "unlocker-file-path" + UnlockerPassword = "unlocker-password" + NoteUriPrefix = "note-uri-prefix" + ScheduledSessionStartTime = "scheduled-session-start-time" + ScheduledSessionEndTime = "scheduled-session-end-time" + ScheduledSessionPeriod = "scheduled-session-period" + ScheduledSessionDuration = "scheduled-session-duration" + ScheduledSessionMinRoundParticipants = "scheduled-session-min-round-participants-count" + ScheduledSessionMaxRoundParticipants = "scheduled-session-max-round-participants-count" + OtelCollectorEndpoint = "otel-collector-endpoint" + OtelPushInterval = "otel-push-interval" + PyroscopeServerURL = "pyroscope-server-url" + RoundMaxParticipantsCount = "round-max-participants-count" + RoundMinParticipantsCount = "round-min-participants-count" + UtxoMaxAmount = "utxo-max-amount" + VtxoMaxAmount = "vtxo-max-amount" + UtxoMinAmount = "utxo-min-amount" + VtxoMinAmount = "vtxo-min-amount" + AllowCSVBlockType = "allow-csv-block-type" + HeartbeatInterval = "heartbeat-interval" + RoundReportServiceEnabled = "round-report-enabled" + SettlementMinExpiryGap = "settlement-min-expiry-gap" // Skip CSV validation for vtxos created before this date - VtxoNoCsvValidationCutoffDate = "VTXO_NO_CSV_VALIDATION_CUTOFF_DATE" - OnchainOutputFee = "ONCHAIN_OUTPUT_FEE" - EnablePprof = "ENABLE_PPROF" + VtxoNoCsvValidationCutoffDate = "vtxo-no-csv-validation-cutoff-date" + OnchainOutputFee = "onchain-output-fee" + EnablePprof = "enable-pprof" defaultDatadir = arklib.AppDataDir("arkd", false) defaultSessionDuration = 30 @@ -248,46 +249,90 @@ var ( defaultEnablePprof = false ) -func LoadConfig() (*Config, error) { - viper.SetEnvPrefix("ARKD") - viper.AutomaticEnv() - - viper.SetDefault(Datadir, defaultDatadir) - viper.SetDefault(Port, DefaultPort) - viper.SetDefault(AdminPort, DefaultAdminPort) - viper.SetDefault(DbType, defaultDbType) - viper.SetDefault(NoTLS, defaultNoTLS) - viper.SetDefault(LogLevel, defaultLogLevel) - viper.SetDefault(SessionDuration, defaultSessionDuration) - viper.SetDefault(BanDuration, defaultBanDuration) - viper.SetDefault(BanThreshold, defaultBanThreshold) - viper.SetDefault(VtxoTreeExpiry, defaultVtxoTreeExpiry) - viper.SetDefault(SchedulerType, defaultSchedulerType) - viper.SetDefault(EventDbType, defaultEventDbType) - viper.SetDefault(TxBuilderType, defaultTxBuilderType) - viper.SetDefault(UnilateralExitDelay, defaultUnilateralExitDelay) - viper.SetDefault(PublicUnilateralExitDelay, defaultUnilateralExitDelay) - viper.SetDefault(CheckpointExitDelay, defaultCheckpointExitDelay) - viper.SetDefault(EsploraURL, defaultEsploraURL) - viper.SetDefault(NoMacaroons, defaultNoMacaroons) - viper.SetDefault(BoardingExitDelay, defaultBoardingExitDelay) - viper.SetDefault(RoundMaxParticipantsCount, defaultRoundMaxParticipantsCount) - viper.SetDefault(RoundMinParticipantsCount, defaultRoundMinParticipantsCount) - viper.SetDefault(UtxoMaxAmount, defaultUtxoMaxAmount) - viper.SetDefault(UtxoMinAmount, defaultUtxoMinAmount) - viper.SetDefault(VtxoMaxAmount, defaultVtxoMaxAmount) - viper.SetDefault(VtxoMinAmount, defaultVtxoMinAmount) - viper.SetDefault(LiveStoreType, defaultLiveStoreType) - viper.SetDefault(RedisTxNumOfRetries, defaultRedisTxNumOfRetries) - viper.SetDefault(AllowCSVBlockType, defaultAllowCSVBlockType) - viper.SetDefault(OtelPushInterval, defaultOtelPushInterval) - viper.SetDefault(HeartbeatInterval, defaultHeartbeatInterval) - viper.SetDefault(RoundReportServiceEnabled, defaultRoundReportServiceEnabled) - viper.SetDefault(SettlementMinExpiryGap, defaultSettlementMinExpiryGap) - viper.SetDefault(VtxoNoCsvValidationCutoffDate, defaultVtxoNoCsvValidationCutoffDate) - viper.SetDefault(OnchainOutputFee, defaultOnchainOutputFee) - viper.SetDefault(EnablePprof, defaultEnablePprof) +func SetupFlags(cmd *cobra.Command) { + cmd.Flags().String(Datadir, defaultDatadir, "Directory to store data") + cmd.Flags().Int(Port, DefaultPort, "Port (public) to listen on") + cmd.Flags().Int(AdminPort, DefaultAdminPort, + "Admin port (private) to listen on, fallback to service port if 0") + cmd.Flags().String(DbType, defaultDbType, "Database type (postgres, sqlite, badger)") + cmd.Flags().Bool(NoTLS, defaultNoTLS, "Disable TLS") + cmd.Flags().Int(LogLevel, defaultLogLevel, "Logging level (0-6, where 6 is trace)") + cmd.Flags().Int64(SessionDuration, int64(defaultSessionDuration), + "How long a batch session lasts (in seconds) before timing out once it started") + cmd.Flags().Int64(BanDuration, int64(defaultBanDuration), "Ban duration in seconds") + cmd.Flags().Int64(BanThreshold, int64(defaultBanThreshold), "Number of crimes to trigger a ban") + cmd.Flags().Int64(VtxoTreeExpiry, int64(defaultVtxoTreeExpiry), "VTXO tree expiry in seconds") + cmd.Flags().String(SchedulerType, defaultSchedulerType, "Scheduler type (gocron, block)") + cmd.Flags().String(EventDbType, defaultEventDbType, "Event database type (postgres, badger)") + cmd.Flags().String(TxBuilderType, defaultTxBuilderType, + "Transaction builder type (covenantless)") + cmd.Flags().Int(UnilateralExitDelay, defaultUnilateralExitDelay, + "Unilateral exit delay in seconds") + cmd.Flags().Int(PublicUnilateralExitDelay, defaultUnilateralExitDelay, + "Public unilateral exit delay in seconds") + cmd.Flags().Int(CheckpointExitDelay, defaultCheckpointExitDelay, + "Checkpoint exit delay in seconds") + cmd.Flags().String(EsploraURL, defaultEsploraURL, "Esplora API URL") + cmd.Flags().Bool(NoMacaroons, defaultNoMacaroons, "Disable macaroon authentication") + cmd.Flags().Int(BoardingExitDelay, defaultBoardingExitDelay, "Boarding exit delay in seconds") + cmd.Flags().Int(RoundMaxParticipantsCount, defaultRoundMaxParticipantsCount, + "Maximum number of participants per round") + cmd.Flags().Int(RoundMinParticipantsCount, defaultRoundMinParticipantsCount, + "Minimum number of participants per round") + cmd.Flags().Int64(UtxoMaxAmount, int64(defaultUtxoMaxAmount), + "The maximum allowed amount for boarding or collaborative exit") + cmd.Flags().Int64(UtxoMinAmount, int64(defaultUtxoMinAmount), + "The minimum allowed amount for boarding or collaborative exit") + cmd.Flags().Int64(VtxoMaxAmount, int64(defaultVtxoMaxAmount), + "The maximum allowed amount for vtxos") + cmd.Flags().Int64(VtxoMinAmount, int64(defaultVtxoMinAmount), + "The minimum allowed amount for vtxos") + cmd.Flags().String(LiveStoreType, defaultLiveStoreType, "Cache service type (redis, inmemory)") + cmd.Flags().Int(RedisTxNumOfRetries, defaultRedisTxNumOfRetries, + "Maximum number of retries for Redis write operations in case of conflicts") + cmd.Flags().Bool(AllowCSVBlockType, defaultAllowCSVBlockType, "Allow CSV block type") + cmd.Flags().Int64(HeartbeatInterval, int64(defaultHeartbeatInterval), + "Heartbeat interval in seconds") + cmd.Flags().Bool(RoundReportServiceEnabled, defaultRoundReportServiceEnabled, + "Enable round report service") + cmd.Flags().Int64(SettlementMinExpiryGap, int64(defaultSettlementMinExpiryGap), "") + cmd.Flags(). + Int64(VtxoNoCsvValidationCutoffDate, int64(defaultVtxoNoCsvValidationCutoffDate), "") + cmd.Flags().Int64(OnchainOutputFee, int64(defaultOnchainOutputFee), "") + cmd.Flags().Bool(EnablePprof, defaultEnablePprof, "") + + cmd.Flags(). + String(WalletAddr, "", "The arkd wallet address to connect to in the form host:port") + cmd.Flags().String(SignerAddr, "", "The signer address to connect to in the form host:port") + cmd.Flags().String(DbUrl, "", "Postgres connection url if ARKD_DB_TYPE is set to postgres") + cmd.Flags(). + String(EventDbUrl, "", "Event database url if ARKD_EVENT_DB_TYPE is set to postgres") + cmd.Flags().Bool(PostgresAutoCreateDB, false, + "Toggles postgres database creation when it does not exist") + cmd.Flags().String(RedisUrl, "", + "Redis db connection url if ARKD_LIVE_STORE_TYPE is set to redis") + cmd.Flags().String(AlertManagerURL, "", "") + cmd.Flags().StringSlice(TLSExtraIP, nil, "Extra IP addresses for TLS (comma-separated)") + cmd.Flags().StringSlice(TLSExtraDomain, nil, "Extra domains for TLS (comma-separated)") + cmd.Flags().String(UnlockerType, "", "Wallet unlocker type (env, file) to enable auto-unlock") + cmd.Flags().String(UnlockerFilePath, "", "Path to unlocker file") + cmd.Flags().String(UnlockerPassword, "", "Wallet unlocker password") + cmd.Flags().String(NoteUriPrefix, "", "Note URI prefix") + cmd.Flags().Int64(ScheduledSessionStartTime, 0, "Scheduled session start time (Unix timestamp)") + cmd.Flags().Int64(ScheduledSessionEndTime, 0, "Scheduled session end time (Unix timestamp)") + cmd.Flags().Int64(ScheduledSessionPeriod, 0, "Scheduled session period in minutes") + cmd.Flags().Int64(ScheduledSessionDuration, 0, "Scheduled session duration in seconds") + cmd.Flags().Int64(ScheduledSessionMinRoundParticipants, 0, + "Min participants for scheduled sessions") + cmd.Flags().Int64(ScheduledSessionMaxRoundParticipants, 0, + "Max participants for scheduled sessions") + cmd.Flags().String(OtelCollectorEndpoint, "", "OpenTelemetry collector endpoint") + cmd.Flags().Int64(OtelPushInterval, int64(defaultOtelPushInterval), + "OpenTelemetry push interval in seconds") + cmd.Flags().String(PyroscopeServerURL, "", "") +} +func LoadConfig() (*Config, error) { if err := initDatadir(); err != nil { return nil, fmt.Errorf("failed to create datadir: %s", err) }