github.com/iotexproject/iotex-core@v1.14.1-rc1/ioctl/cmd/contract/contractcompile.go (about) 1 // Copyright (c) 2022 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 contract 7 8 import ( 9 "encoding/json" 10 "fmt" 11 "os" 12 "strings" 13 14 "github.com/spf13/cobra" 15 16 "github.com/iotexproject/iotex-core/ioctl/config" 17 "github.com/iotexproject/iotex-core/ioctl/output" 18 ) 19 20 var ( 21 _abiOut string 22 _binOut string 23 ) 24 25 // Multi-language support 26 var ( 27 _contractCompileCmdUses = map[config.Language]string{ 28 config.English: "compile CONTRACT_NAME [CODE_FILES...] [--abi-out ABI_PATH] [--bin-out BIN_PATH]", 29 config.Chinese: "compile 合约名 [代码文件...] [--abi-out ABI路径] [--bin-out BIN路径]", 30 } 31 _contractCompileCmdShorts = map[config.Language]string{ 32 config.English: "Compile smart contract of IoTeX blockchain from source code file(s).", 33 config.Chinese: "编译IoTeX区块链的智能合约代码,支持多文件编译", 34 } 35 _flagAbiOutUsage = map[config.Language]string{ 36 config.English: "set abi file output path", 37 config.Chinese: "设置abi文件输出路径", 38 } 39 _flagBinOutUsage = map[config.Language]string{ 40 config.English: "set bin file output path", 41 config.Chinese: "设置bin文件输出路径", 42 } 43 ) 44 45 // ContractCompileCmd represents the contract compile command 46 var ContractCompileCmd = &cobra.Command{ 47 Use: config.TranslateInLang(_contractCompileCmdUses, config.UILanguage), 48 Short: config.TranslateInLang(_contractCompileCmdShorts, config.UILanguage), 49 Args: cobra.MinimumNArgs(1), 50 RunE: func(cmd *cobra.Command, args []string) error { 51 cmd.SilenceUsage = true 52 err := compile(args) 53 return output.PrintError(err) 54 }, 55 } 56 57 func init() { 58 ContractCompileCmd.Flags().StringVar(&_abiOut, "abi-out", "", 59 config.TranslateInLang(_flagAbiOutUsage, config.UILanguage)) 60 61 ContractCompileCmd.Flags().StringVar(&_binOut, "bin-out", "", 62 config.TranslateInLang(_flagBinOutUsage, config.UILanguage)) 63 } 64 65 func compile(args []string) error { 66 contractName := args[0] 67 68 files := args[1:] 69 if len(files) == 0 { 70 dirInfo, err := os.ReadDir("./") 71 if err != nil { 72 return output.NewError(output.ReadFileError, "failed to get current directory", err) 73 } 74 75 for _, fileInfo := range dirInfo { 76 if !fileInfo.IsDir() && strings.HasSuffix(fileInfo.Name(), ".sol") { 77 files = append(files, fileInfo.Name()) 78 } 79 } 80 81 if len(files) == 0 { 82 return output.NewError(output.InputError, "failed to get source file(s)", nil) 83 } 84 } 85 86 contracts, err := Compile(files...) 87 if err != nil { 88 return output.NewError(0, "failed to compile", err) 89 } 90 91 for name := range contracts { 92 if name == contractName { 93 break 94 } 95 nameSplit := strings.Split(name, ":") 96 if nameSplit[len(nameSplit)-1] == contractName { 97 contractName = name 98 break 99 } 100 } 101 102 contract, ok := contracts[contractName] 103 if !ok { 104 return output.NewError(output.CompilerError, fmt.Sprintf("failed to find out contract %s", contractName), nil) 105 } 106 107 abiByte, err := json.Marshal(contract.Info.AbiDefinition) 108 if err != nil { 109 return output.NewError(output.SerializationError, "failed to marshal abi", err) 110 } 111 112 result := []string{ 113 fmt.Sprintf("======= %s =======", contractName), 114 fmt.Sprintf("Binary:\n%s", contract.Code), 115 fmt.Sprintf("Contract JSON ABI\n%s", string(abiByte)), 116 } 117 output.PrintResult(strings.Join(result, "\n")) 118 119 if _binOut != "" { 120 // bin file starts with "0x" prefix 121 if err := os.WriteFile(_binOut, []byte(contract.Code), 0600); err != nil { 122 return output.NewError(output.WriteFileError, "failed to write bin file", err) 123 } 124 } 125 126 if _abiOut != "" { 127 if err := os.WriteFile(_abiOut, abiByte, 0600); err != nil { 128 return output.NewError(output.WriteFileError, "failed to write abi file", err) 129 } 130 } 131 132 return nil 133 }