status-im/status-go

View on GitHub
cmd/status-cli/util.go

Summary

Maintainability
A
0 mins
Test Coverage
package main

import (
    "context"
    "errors"
    "fmt"
    "os"
    "strings"
    "time"

    "go.uber.org/zap"

    "github.com/status-im/status-go/api"
    "github.com/status-im/status-go/logutils"
    "github.com/status-im/status-go/multiaccounts"
    "github.com/status-im/status-go/protocol/requests"
    "github.com/status-im/status-go/services/wakuv2ext"
    "github.com/status-im/status-go/telemetry"

    "github.com/urfave/cli/v2"
)

func setupLogger(file string) *zap.Logger {
    logFile := fmt.Sprintf("%s.log", strings.ToLower(file))
    logSettings := logutils.LogSettings{
        Enabled:         true,
        MobileSystem:    false,
        Level:           "DEBUG",
        File:            logFile,
        MaxSize:         100,
        MaxBackups:      3,
        CompressRotated: true,
    }
    if err := logutils.OverrideRootLogWithConfig(logSettings, false); err != nil {
        zap.S().Fatalf("Error initializing logger: %v", err)
    }
    return logutils.ZapLogger()
}

func start(name string, port int, apiModules string, telemetryUrl string, keyUID string, logger *zap.SugaredLogger) (*StatusCLI, error) {
    var (
        rootDataDir = fmt.Sprintf("./test-%s", strings.ToLower(name))
        password    = "some-password"
    )
    setupLogger(name)
    logger.Info("starting messenger")

    backend := api.NewGethStatusBackend()
    if keyUID != "" {
        if err := getAccountAndLogin(backend, name, rootDataDir, password, keyUID); err != nil {
            return nil, err
        }
        logger.Infof("existing account, key UID: %v", keyUID)
    } else {
        acc, err := createAccountAndLogin(backend, name, rootDataDir, password, apiModules, telemetryUrl, port)
        if err != nil {
            return nil, err
        }
        logger.Infof("account created, key UID: %v", acc.KeyUID)
    }

    wakuService := backend.StatusNode().WakuV2ExtService()
    if wakuService == nil {
        return nil, errors.New("waku service is not available")
    }

    if telemetryUrl != "" {
        telemetryLogger, err := getLogger(true)
        if err != nil {
            return nil, err
        }
        telemetryClient := telemetry.NewClient(telemetryLogger, telemetryUrl, backend.SelectedAccountKeyID(), name, "cli")
        go telemetryClient.Start(context.Background())
        backend.StatusNode().WakuV2Service().SetStatusTelemetryClient(telemetryClient)
    }
    wakuAPI := wakuv2ext.NewPublicAPI(wakuService)

    messenger := wakuAPI.Messenger()
    if _, err := wakuAPI.StartMessenger(); err != nil {
        return nil, err
    }

    logger.Info("messenger started, public key: ", messenger.IdentityPublicKeyString())
    time.Sleep(WaitingInterval)

    data := StatusCLI{
        name:      name,
        messenger: messenger,
        backend:   backend,
        logger:    logger,
    }

    return &data, nil
}

func getAccountAndLogin(b *api.GethStatusBackend, name, rootDataDir, password string, keyUID string) error {
    b.UpdateRootDataDir(rootDataDir)
    if err := b.OpenAccounts(); err != nil {
        return fmt.Errorf("name '%v' might not have an account: trying to find: %v: %w", name, rootDataDir, err)
    }
    accs, err := b.GetAccounts()
    if err != nil {
        return err
    }
    if len(accs) == 0 {
        return errors.New("no accounts found")
    }

    var acc multiaccounts.Account
    found := false
    for _, a := range accs {
        if a.KeyUID == keyUID {
            acc = a
            found = true
            break
        }
    }
    if !found {
        return fmt.Errorf("account not found for keyUID: %v", keyUID)
    }

    return b.LoginAccount(&requests.Login{
        Password: password,
        KeyUID:   acc.KeyUID,
    })
}

func createAccountAndLogin(b *api.GethStatusBackend, name, rootDataDir, password, apiModules, telemetryUrl string, port int) (*multiaccounts.Account, error) {
    if err := os.MkdirAll(rootDataDir, os.ModePerm); err != nil {
        return nil, err
    }

    req := &requests.CreateAccount{
        DisplayName:        name,
        CustomizationColor: "#ffffff",
        Emoji:              "some",
        Password:           password,
        RootDataDir:        rootDataDir,
        LogFilePath:        "log",
        APIConfig: &requests.APIConfig{
            APIModules:  apiModules,
            HTTPEnabled: true,
            HTTPHost:    "127.0.0.1",
            HTTPPort:    port,
        },
        TelemetryServerURL: telemetryUrl,
    }
    return b.CreateAccountAndLogin(req)
}

func (cli *StatusCLI) stop() {
    err := cli.backend.StopNode()
    if err != nil {
        cli.logger.Error(err)
    }
}

func getLogger(debug bool) (*zap.Logger, error) {
    at := zap.NewAtomicLevel()
    if debug {
        at.SetLevel(zap.DebugLevel)
    } else {
        at.SetLevel(zap.InfoLevel)
    }
    config := zap.NewDevelopmentConfig()
    config.Level = at
    rawLogger, err := config.Build()
    if err != nil {
        return nil, fmt.Errorf("initializing logger: %v", err)
    }
    return rawLogger, nil
}

func getSLogger(debug bool) (*zap.SugaredLogger, error) {
    l, err := getLogger(debug)
    if err != nil {
        return nil, err
    }
    return l.Sugar(), nil
}

func flagsUsed(cCtx *cli.Context) string {
    var sb strings.Builder
    for _, flag := range cCtx.Command.Flags {
        if flag != nil && len(flag.Names()) > 0 {
            fName := flag.Names()[0]
            fmt.Fprintf(&sb, "\t-%s %v\n", fName, cCtx.Value(fName))
        }
    }
    return sb.String()
}