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 }