github.com/daeglee/go-ethereum@v0.0.0-20190504220456-cad3e8d18e9b/cmd/abigen/main.go (about) 1 // Copyright 2019 The go-ethereum Authors 2 // This file is part of go-ethereum. 3 // 4 // go-ethereum is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // go-ethereum is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with go-ethereum. If not, see <http://www.gnu.org/licenses/>. 16 17 package main 18 19 import ( 20 "encoding/json" 21 "flag" 22 "fmt" 23 "io/ioutil" 24 "os" 25 "strings" 26 27 "github.com/ethereum/go-ethereum/accounts/abi/bind" 28 "github.com/ethereum/go-ethereum/common/compiler" 29 ) 30 31 var ( 32 abiFlag = flag.String("abi", "", "Path to the Ethereum contract ABI json to bind, - for STDIN") 33 binFlag = flag.String("bin", "", "Path to the Ethereum contract bytecode (generate deploy method)") 34 typFlag = flag.String("type", "", "Struct name for the binding (default = package name)") 35 36 solFlag = flag.String("sol", "", "Path to the Ethereum contract Solidity source to build and bind") 37 solcFlag = flag.String("solc", "solc", "Solidity compiler to use if source builds are requested") 38 excFlag = flag.String("exc", "", "Comma separated types to exclude from binding") 39 40 vyFlag = flag.String("vy", "", "Path to the Ethereum contract Vyper source to build and bind") 41 vyperFlag = flag.String("vyper", "vyper", "Vyper compiler to use if source builds are requested") 42 43 pkgFlag = flag.String("pkg", "", "Package name to generate the binding into") 44 outFlag = flag.String("out", "", "Output file for the generated binding (default = stdout)") 45 langFlag = flag.String("lang", "go", "Destination language for the bindings (go, java, objc)") 46 ) 47 48 func main() { 49 // Parse and ensure all needed inputs are specified 50 flag.Parse() 51 52 if *abiFlag == "" && *solFlag == "" && *vyFlag == "" { 53 fmt.Printf("No contract ABI (--abi), Solidity source (--sol), or Vyper source (--vy) specified\n") 54 os.Exit(-1) 55 } else if (*abiFlag != "" || *binFlag != "" || *typFlag != "") && (*solFlag != "" || *vyFlag != "") { 56 fmt.Printf("Contract ABI (--abi), bytecode (--bin) and type (--type) flags are mutually exclusive with the Solidity (--sol) and Vyper (--vy) flags\n") 57 os.Exit(-1) 58 } else if *solFlag != "" && *vyFlag != "" { 59 fmt.Printf("Solidity (--sol) and Vyper (--vy) flags are mutually exclusive\n") 60 os.Exit(-1) 61 } 62 if *pkgFlag == "" { 63 fmt.Printf("No destination package specified (--pkg)\n") 64 os.Exit(-1) 65 } 66 var lang bind.Lang 67 switch *langFlag { 68 case "go": 69 lang = bind.LangGo 70 case "java": 71 lang = bind.LangJava 72 case "objc": 73 lang = bind.LangObjC 74 default: 75 fmt.Printf("Unsupported destination language \"%s\" (--lang)\n", *langFlag) 76 os.Exit(-1) 77 } 78 // If the entire solidity code was specified, build and bind based on that 79 var ( 80 abis []string 81 bins []string 82 types []string 83 ) 84 if *solFlag != "" || *vyFlag != "" || (*abiFlag == "-" && *pkgFlag == "") { 85 // Generate the list of types to exclude from binding 86 exclude := make(map[string]bool) 87 for _, kind := range strings.Split(*excFlag, ",") { 88 exclude[strings.ToLower(kind)] = true 89 } 90 91 var contracts map[string]*compiler.Contract 92 var err error 93 94 switch { 95 case *solFlag != "": 96 contracts, err = compiler.CompileSolidity(*solcFlag, *solFlag) 97 if err != nil { 98 fmt.Printf("Failed to build Solidity contract: %v\n", err) 99 os.Exit(-1) 100 } 101 case *vyFlag != "": 102 contracts, err = compiler.CompileVyper(*vyperFlag, *vyFlag) 103 if err != nil { 104 fmt.Printf("Failed to build Vyper contract: %v\n", err) 105 os.Exit(-1) 106 } 107 default: 108 contracts, err = contractsFromStdin() 109 if err != nil { 110 fmt.Printf("Failed to read input ABIs from STDIN: %v\n", err) 111 os.Exit(-1) 112 } 113 } 114 // Gather all non-excluded contract for binding 115 for name, contract := range contracts { 116 if exclude[strings.ToLower(name)] { 117 continue 118 } 119 abi, err := json.Marshal(contract.Info.AbiDefinition) // Flatten the compiler parse 120 if err != nil { 121 fmt.Printf("Failed to parse ABIs from compiler output: %v\n", err) 122 os.Exit(-1) 123 } 124 abis = append(abis, string(abi)) 125 bins = append(bins, contract.Code) 126 127 nameParts := strings.Split(name, ":") 128 types = append(types, nameParts[len(nameParts)-1]) 129 } 130 } else { 131 // Otherwise load up the ABI, optional bytecode and type name from the parameters 132 var abi []byte 133 var err error 134 if *abiFlag == "-" { 135 abi, err = ioutil.ReadAll(os.Stdin) 136 } else { 137 abi, err = ioutil.ReadFile(*abiFlag) 138 } 139 if err != nil { 140 fmt.Printf("Failed to read input ABI: %v\n", err) 141 os.Exit(-1) 142 } 143 abis = append(abis, string(abi)) 144 145 var bin []byte 146 if *binFlag != "" { 147 if bin, err = ioutil.ReadFile(*binFlag); err != nil { 148 fmt.Printf("Failed to read input bytecode: %v\n", err) 149 os.Exit(-1) 150 } 151 } 152 bins = append(bins, string(bin)) 153 154 kind := *typFlag 155 if kind == "" { 156 kind = *pkgFlag 157 } 158 types = append(types, kind) 159 } 160 // Generate the contract binding 161 code, err := bind.Bind(types, abis, bins, *pkgFlag, lang) 162 if err != nil { 163 fmt.Printf("Failed to generate ABI binding: %v\n", err) 164 os.Exit(-1) 165 } 166 // Either flush it out to a file or display on the standard output 167 if *outFlag == "" { 168 fmt.Printf("%s\n", code) 169 return 170 } 171 if err := ioutil.WriteFile(*outFlag, []byte(code), 0600); err != nil { 172 fmt.Printf("Failed to write ABI binding: %v\n", err) 173 os.Exit(-1) 174 } 175 } 176 177 func contractsFromStdin() (map[string]*compiler.Contract, error) { 178 bytes, err := ioutil.ReadAll(os.Stdin) 179 if err != nil { 180 return nil, err 181 } 182 return compiler.ParseCombinedJSON(bytes, "", "", "", "") 183 }