Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add store object #33

Merged
merged 18 commits into from
Feb 26, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 29 additions & 2 deletions relayer/log.go → cmd/log.go
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
package relayer
package cmd

import (
"fmt"
"os"
"time"

zaplogfmt "github.com/jsternberg/zap-logfmt"
"github.com/spf13/viper"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
)

func newRootLogger(format string, logLevel string) (*zap.Logger, error) {
// newLogger creates a new root logger with the given log format and log level.
func newLogger(format string, logLevel string) (*zap.Logger, error) {
config := zap.NewProductionEncoderConfig()
config.EncodeTime = func(ts time.Time, encoder zapcore.PrimitiveArrayEncoder) {
encoder.AppendString(ts.UTC().Format("2006-01-02T15:04:05.000000Z07:00"))
Expand Down Expand Up @@ -51,3 +53,28 @@ func newRootLogger(format string, logLevel string) (*zap.Logger, error) {

return logger, nil
}

// initLogger initializes the logger with the given default log level.
func initLogger(defaultLogLevel string) (log *zap.Logger, err error) {
logFormat := viper.GetString("log-format")

logLevel := viper.GetString("log-level")
if viper.GetBool("debug") {
logLevel = "debug"
}
if logLevel == "" && defaultLogLevel != "" {
logLevel = defaultLogLevel
}

// initialize logger only if user run command "start" or log level is "debug"
if os.Args[1] == "start" || logLevel == "debug" {
log, err = newLogger(logFormat, logLevel)
if err != nil {
return nil, err
}
} else {
log = zap.NewNop()
}

return log, nil
}
36 changes: 28 additions & 8 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,22 @@ import (
"go.uber.org/zap"

falcon "github.com/bandprotocol/falcon/relayer"
"github.com/bandprotocol/falcon/relayer/store"
)

const (
appName = "falcon"
defaultCoinType = 60

PassphraseEnvKey = "PASSPHRASE"
)

var defaultHome = filepath.Join(os.Getenv("HOME"), ".falcon")

// NewRootCmd returns the root command for falcon.
func NewRootCmd(log *zap.Logger) *cobra.Command {
app := falcon.NewApp(log, defaultHome, false, nil)
passphrase := os.Getenv(PassphraseEnvKey)
app := falcon.NewApp(log, defaultHome, false, nil, passphrase, nil)

// RootCmd represents the base command when called without any subcommands
rootCmd := &cobra.Command{
Expand All @@ -44,16 +48,32 @@ func NewRootCmd(log *zap.Logger) *cobra.Command {
(i.e. 'falcon tx', 'falcon q', etc...)`),
}

rootCmd.PersistentPreRunE = func(cmd *cobra.Command, _ []string) error {
// retrieve log level from viper
logLevelViper := viper.GetString("log-level")
if viper.GetBool("debug") {
logLevelViper = "debug"
rootCmd.PersistentPreRunE = func(cmd *cobra.Command, _ []string) (err error) {
// set up store
app.Store, err = store.NewFileSystem(app.HomePath)
if err != nil {
return err
}

// load configuration
app.Config, err = app.Store.GetConfig()
if err != nil {
return err
}

logFormat := viper.GetString("log-format")
// retrieve log level from config
configLogLevel := ""
if app.Config != nil {
configLogLevel = app.Config.Global.LogLevel
}

// init log object
app.Log, err = initLogger(configLogLevel)
if err != nil {
return err
}

return app.Init(rootCmd.Context(), logLevelViper, logFormat)
return app.Init(rootCmd.Context())
}

rootCmd.PersistentPostRun = func(cmd *cobra.Command, _ []string) {
Expand Down
66 changes: 66 additions & 0 deletions internal/os/os.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package os

import (
"os"
"path"
)

// CheckAndCreateFolder checks if the folder exists and creates it if it doesn't.
func CheckAndCreateFolder(path string) error {
if exist, err := IsPathExist(path); err != nil {
return err
} else if !exist {
return os.Mkdir(path, os.ModePerm)
}

return nil
}

// IsPathExist checks if the path exists.
func IsPathExist(path string) (bool, error) {
if _, err := os.Stat(path); os.IsNotExist(err) {
return false, nil
} else if err != nil {
return false, err
}

return true, nil
}

// ReadFileIfExist reads file from the given path. It returns empty data with no error,
// if the file doesn't exist. Otherwise, it returns an error.
func ReadFileIfExist(path string) ([]byte, error) {
if exist, err := IsPathExist(path); err != nil {
return nil, err
} else if !exist {
return nil, nil
}

return os.ReadFile(path)
}

// Write writes the given data to the file at the given path. It also creates the folders if they don't exist.
func Write(data []byte, paths []string) error {
// Create folders if they don't exist
folderPath := ""
for _, p := range paths[:len(paths)-1] {
folderPath = path.Join(folderPath, p)
if err := CheckAndCreateFolder(folderPath); err != nil {
return err
}
}

// Write the data to the file
filePath := path.Join(folderPath, paths[len(paths)-1])
f, err := os.Create(filePath)
if err != nil {
return err
}
defer f.Close()

if _, err = f.Write(data); err != nil {
return err
}

return nil
}
97 changes: 97 additions & 0 deletions internal/os/os_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
package os_test

import (
"os"
"path"
"testing"

"github.com/stretchr/testify/require"

internal_os "github.com/bandprotocol/falcon/internal/os"
)

func TestCheckAndCreateFolder(t *testing.T) {
tmpDir := path.Join(t.TempDir(), "test")

// create a folder
err := internal_os.CheckAndCreateFolder(tmpDir)
require.NoError(t, err)

_, err = os.Stat(tmpDir)
require.NoError(t, err)

// create a folder again; shouldn't cause any error
err = internal_os.CheckAndCreateFolder(tmpDir)
require.NoError(t, err)
}

func TestIsPathExist(t *testing.T) {
tmpDir := path.Join(t.TempDir(), "test")

// check if a folder exists, should return false
exist, err := internal_os.IsPathExist(tmpDir)
require.NoError(t, err)
require.False(t, exist)

err = internal_os.CheckAndCreateFolder(tmpDir)
require.NoError(t, err)

exist, err = internal_os.IsPathExist(tmpDir)
require.NoError(t, err)
require.True(t, exist)
}

func TestWrite(t *testing.T) {
tmpDir := path.Join(t.TempDir(), "test")

// write a file
err := internal_os.Write([]byte("test"), []string{tmpDir, "test.txt"})
require.NoError(t, err)

// check if the file exists
exist, err := internal_os.IsPathExist(path.Join(tmpDir, "test.txt"))
require.NoError(t, err)
require.True(t, exist)

// check if the file contains the correct data
data, err := os.ReadFile(path.Join(tmpDir, "test.txt"))
require.NoError(t, err)
require.Equal(t, "test", string(data))

// write a file again; shouldn't cause any error
err = internal_os.Write([]byte("new test"), []string{tmpDir, "test.txt"})
require.NoError(t, err)

// check if the file contains the correct data
data, err = os.ReadFile(path.Join(tmpDir, "test.txt"))
require.NoError(t, err)
require.Equal(t, "new test", string(data))
}

func TestReadFileIfExist(t *testing.T) {
tmpDir := path.Join(t.TempDir(), "test")

// check if a file exists, should return nil
data, err := internal_os.ReadFileIfExist(path.Join(tmpDir, "test.txt"))
require.NoError(t, err)
require.Nil(t, data)

// write a file
err = internal_os.Write([]byte("test"), []string{tmpDir, "test.txt"})
require.NoError(t, err)

// check if the file exists
exist, err := internal_os.IsPathExist(path.Join(tmpDir, "test.txt"))
require.NoError(t, err)
require.True(t, exist)

// check if the file contains the correct data
data, err = internal_os.ReadFileIfExist(path.Join(tmpDir, "test.txt"))
require.NoError(t, err)
require.Equal(t, "test", string(data))

// check if a file doesn't exist, should return nil
data, err = internal_os.ReadFileIfExist(path.Join(tmpDir, "non-exist.txt"))
require.NoError(t, err)
require.Nil(t, data)
}
8 changes: 4 additions & 4 deletions internal/relayertest/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ import (
_ "embed"
"time"

falcon "github.com/bandprotocol/falcon/relayer"
"github.com/bandprotocol/falcon/relayer/band"
"github.com/bandprotocol/falcon/relayer/chains"
"github.com/bandprotocol/falcon/relayer/chains/evm"
"github.com/bandprotocol/falcon/relayer/config"
)

//go:embed testdata/default_config.toml
Expand All @@ -19,8 +19,8 @@ var CustomCfgText string
//go:embed testdata/custom_config_with_time_str.toml
var CustomCfgTextWithTimeStr string

var CustomCfg = falcon.Config{
Global: falcon.GlobalConfig{
var CustomCfg = config.Config{
Global: config.GlobalConfig{
CheckingPacketInterval: 1 * time.Minute,
SyncTunnelsInterval: 5 * time.Minute,
PenaltySkipRounds: 3,
Expand All @@ -31,7 +31,7 @@ var CustomCfg = falcon.Config{
Timeout: 3 * time.Second,
LivelinessCheckingInterval: 5 * time.Minute,
},
TargetChains: chains.ChainProviderConfigs{
TargetChains: config.ChainProviderConfigs{
"testnet": &evm.EVMChainProviderConfig{
BaseChainProviderConfig: chains.BaseChainProviderConfig{
Endpoints: []string{"http://localhost:8545"},
Expand Down
Loading
Loading