github.com/iotexproject/iotex-core@v1.14.1-rc1/ioctl/config/config.go (about)

     1  // Copyright (c) 2019 IoTeX Foundation
     2  // This source code is provided 'as is' and no warranties are given as to title or non-infringement, merchantability
     3  // or fitness for purpose and, to the extent permitted by law, all liability for your use of the code is disclaimed.
     4  // This source code is governed by Apache License 2.0 that can be found in the LICENSE file.
     5  
     6  package config
     7  
     8  import (
     9  	"fmt"
    10  	"os"
    11  	"path/filepath"
    12  
    13  	"github.com/spf13/cobra"
    14  	"gopkg.in/yaml.v2"
    15  
    16  	"github.com/iotexproject/iotex-core/blockchain/genesis"
    17  	"github.com/iotexproject/iotex-core/ioctl/output"
    18  	"github.com/iotexproject/iotex-core/pkg/log"
    19  )
    20  
    21  // Directories
    22  var (
    23  	// ConfigDir is the directory to store config file
    24  	ConfigDir string
    25  	// DefaultConfigFile is the default config file name
    26  	DefaultConfigFile string
    27  )
    28  
    29  // Error strings
    30  var (
    31  	// ErrConfigNotMatch indicates error for no config matches
    32  	ErrConfigNotMatch = fmt.Errorf("no matching config")
    33  	// ErrEmptyEndpoint indicates error for empty endpoint
    34  	ErrEmptyEndpoint = fmt.Errorf("no endpoint has been set")
    35  	// ErrConfigDefaultAccountNotSet indicates an error for the default account not being set
    36  	ErrConfigDefaultAccountNotSet = fmt.Errorf("default account not set")
    37  )
    38  
    39  // Language type used to enumerate supported language of ioctl
    40  type Language int
    41  
    42  // Multi-language support
    43  const (
    44  	English Language = iota
    45  	Chinese
    46  )
    47  
    48  // ConfigCmd represents the config command
    49  var ConfigCmd = &cobra.Command{
    50  	Use:   "config",
    51  	Short: "Get, set, or reset configuration for ioctl",
    52  }
    53  
    54  // Context represents the current context
    55  type Context struct {
    56  	AddressOrAlias string `json:"addressOrAlias" yaml:"addressOrAlias"`
    57  }
    58  
    59  // Config defines the config schema
    60  type Config struct {
    61  	Wallet           string            `json:"wallet" yaml:"wallet"`
    62  	Endpoint         string            `json:"endpoint" yaml:"endpoint"`
    63  	SecureConnect    bool              `json:"secureConnect" yaml:"secureConnect"`
    64  	Aliases          map[string]string `json:"aliases" yaml:"aliases"`
    65  	DefaultAccount   Context           `json:"defaultAccount" yaml:"defaultAccount"`
    66  	Explorer         string            `json:"explorer" yaml:"explorer"`
    67  	Language         string            `json:"language" yaml:"language"`
    68  	Nsv2height       uint64            `json:"nsv2height" yaml:"nsv2height"`
    69  	AnalyserEndpoint string            `json:"analyserEndpoint" yaml:"analyserEndpoint"`
    70  	// WsEndpoint w3bstream endpoint
    71  	WsEndpoint string `json:"wsEndpoint" yaml:"wsEndpoint"`
    72  	// IPFSEndpoint ipfs endpoint for uploading
    73  	IPFSEndpoint string `json:"ipfsEndpoint" yaml:"ipfsEndpoint"`
    74  	// IPFSGateway ipfs gateway for resource fetching (with scheme)
    75  	IPFSGateway string `json:"ipfsGateway" yaml:"ipfsGateway"`
    76  	// WsRegisterContract w3bstream project register contract address
    77  	WsRegisterContract string `json:"wsRegisterContract" yaml:"wsRegisterContract"`
    78  }
    79  
    80  var (
    81  	// ReadConfig represents the current config read from local
    82  	ReadConfig Config
    83  	// Insecure represents the insecure connect option of grpc dial, default is false
    84  	Insecure = false
    85  	// UILanguage represents the language of ioctl user interface, default is 0 representing English
    86  	UILanguage Language
    87  )
    88  
    89  func init() {
    90  	ConfigDir = os.Getenv("HOME") + "/.config/ioctl/default"
    91  	// Create path to config directory
    92  	if err := os.MkdirAll(ConfigDir, 0700); err != nil {
    93  		log.L().Panic(err.Error())
    94  	}
    95  	// Path to config file
    96  	DefaultConfigFile = ConfigDir + "/config.default"
    97  	// Load or reset config file
    98  	var err error
    99  	ReadConfig, err = LoadConfig()
   100  	if err != nil {
   101  		if os.IsNotExist(err) {
   102  			err = reset() // Config file doesn't exist
   103  		}
   104  		if err != nil {
   105  			log.L().Panic(err.Error())
   106  		}
   107  	}
   108  	// Check completeness of config file
   109  	completeness := true
   110  	if ReadConfig.Wallet == "" {
   111  		ReadConfig.Wallet = ConfigDir
   112  		completeness = false
   113  	}
   114  	if ReadConfig.Language == "" {
   115  		ReadConfig.Language = _supportedLanguage[0]
   116  		completeness = false
   117  	}
   118  	if ReadConfig.Nsv2height == 0 {
   119  		ReadConfig.Nsv2height = genesis.Default.FairbankBlockHeight
   120  		completeness = false
   121  	}
   122  	if ReadConfig.Endpoint == "" {
   123  		ReadConfig.Endpoint = _defaultEndpoint
   124  		ReadConfig.SecureConnect = true
   125  		completeness = false
   126  	}
   127  	if ReadConfig.AnalyserEndpoint == "" {
   128  		ReadConfig.AnalyserEndpoint = _defaultAnalyserEndpoint
   129  		completeness = false
   130  	}
   131  	if ReadConfig.WsEndpoint == "" {
   132  		ReadConfig.WsEndpoint = _defaultWsEndpoint
   133  		completeness = false
   134  	}
   135  	if ReadConfig.IPFSEndpoint == "" {
   136  		ReadConfig.IPFSEndpoint = _defaultIPFSEndpoint
   137  		completeness = false
   138  	}
   139  	if ReadConfig.IPFSGateway == "" {
   140  		ReadConfig.IPFSGateway = _defaultIPFSGateway
   141  		completeness = false
   142  	}
   143  	if ReadConfig.WsRegisterContract == "" {
   144  		ReadConfig.WsRegisterContract = _defaultWsRegisterContract
   145  		completeness = false
   146  	}
   147  	if !completeness {
   148  		err := writeConfig()
   149  		if err != nil {
   150  			log.L().Panic(err.Error())
   151  		}
   152  	}
   153  	// Set language for ioctl
   154  	UILanguage = isSupportedLanguage(ReadConfig.Language)
   155  	if UILanguage == -1 {
   156  		UILanguage = 0
   157  		message := output.StringMessage(fmt.Sprintf("Language %s is not supported, English instead.",
   158  			ReadConfig.Language))
   159  		fmt.Println(message.Warn())
   160  	}
   161  	// Init subcommands
   162  	ConfigCmd.AddCommand(_configGetCmd)
   163  	ConfigCmd.AddCommand(_configSetCmd)
   164  	ConfigCmd.AddCommand(_configResetCmd)
   165  }
   166  
   167  // LoadConfig loads config file in yaml format
   168  func LoadConfig() (Config, error) {
   169  	ReadConfig := Config{
   170  		Aliases: make(map[string]string),
   171  	}
   172  	in, err := os.ReadFile(filepath.Clean(DefaultConfigFile))
   173  	if err == nil {
   174  		if err := yaml.Unmarshal(in, &ReadConfig); err != nil {
   175  			return ReadConfig, err
   176  		}
   177  	}
   178  	return ReadConfig, err
   179  }
   180  
   181  // TranslateInLang returns translation in selected language
   182  func TranslateInLang(translations map[Language]string, lang Language) string {
   183  	if tsl, ok := translations[lang]; ok {
   184  		return tsl
   185  	}
   186  
   187  	// Assumption: English should always be provided
   188  	return translations[English]
   189  }
   190  
   191  // Lang returns the selected language, default is English
   192  func (c *Config) Lang() Language {
   193  	switch c.Language {
   194  	case "中文":
   195  		return Chinese
   196  	default:
   197  		return English
   198  	}
   199  }