github.com/ethereumproject/go-ethereum@v5.5.2+incompatible/cmd/abigen/main.go (about)

     1  // Copyright 2016 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/ethereumproject/go-ethereum/accounts/abi/bind"
    28  	"github.com/ethereumproject/go-ethereum/common/compiler"
    29  )
    30  
    31  // Version is the application revision identifier. It can be set with the linker
    32  // as in: go build -ldflags "-X main.Version="`git describe --tags`
    33  var Version = "unknown"
    34  
    35  var (
    36  	abiFlag = flag.String("abi", "", "Path to the Ethereum contract ABI json to bind")
    37  	binFlag = flag.String("bin", "", "Path to the Ethereum contract bytecode (generate deploy method)")
    38  	typFlag = flag.String("type", "", "Go struct name for the binding (default = package name)")
    39  
    40  	solFlag  = flag.String("sol", "", "Path to the Ethereum contract Solidity source to build and bind")
    41  	solcFlag = flag.String("solc", "solc", "Solidity compiler to use if source builds are requested")
    42  	excFlag  = flag.String("exc", "", "Comma separated types to exclude from binding")
    43  
    44  	pkgFlag     = flag.String("pkg", "", "Go package name to generate the binding into")
    45  	outFlag     = flag.String("out", "", "Output file for the generated binding (default = stdout)")
    46  	versionFlag = flag.Bool("version", false, "Prints the revision identifier and exit immediatily.")
    47  )
    48  
    49  func main() {
    50  	// Parse and ensure all needed inputs are specified
    51  	flag.Parse()
    52  
    53  	if *versionFlag {
    54  		fmt.Println("abigen version", Version)
    55  		os.Exit(0)
    56  	}
    57  
    58  	if *abiFlag == "" && *solFlag == "" {
    59  		fmt.Printf("No contract ABI (--abi) or Solidity source (--sol) specified\n")
    60  		os.Exit(-1)
    61  	} else if (*abiFlag != "" || *binFlag != "" || *typFlag != "") && *solFlag != "" {
    62  		fmt.Printf("Contract ABI (--abi), bytecode (--bin) and type (--type) flags are mutually exclusive with the Solidity source (--sol) flag\n")
    63  		os.Exit(-1)
    64  	}
    65  	if *pkgFlag == "" {
    66  		fmt.Printf("No destination Go package specified (--pkg)\n")
    67  		os.Exit(-1)
    68  	}
    69  	// If the entire solidity code was specified, build and bind based on that
    70  	var (
    71  		abis  []string
    72  		bins  []string
    73  		types []string
    74  	)
    75  	if *solFlag != "" {
    76  		// Generate the list of types to exclude from binding
    77  		exclude := make(map[string]bool)
    78  		for _, kind := range strings.Split(*excFlag, ",") {
    79  			exclude[strings.ToLower(kind)] = true
    80  		}
    81  		// Build the Solidity source into bindable components
    82  		solc, err := compiler.New(*solcFlag)
    83  		if err != nil {
    84  			fmt.Printf("Failed to locate Solidity compiler: %v\n", err)
    85  			os.Exit(-1)
    86  		}
    87  		source, err := ioutil.ReadFile(*solFlag)
    88  		if err != nil {
    89  			fmt.Printf("Failed to read Soldity source code: %v\n", err)
    90  			os.Exit(-1)
    91  		}
    92  		contracts, err := solc.Compile(string(source))
    93  		if err != nil {
    94  			fmt.Printf("Failed to build Solidity contract: %v\n", err)
    95  			os.Exit(-1)
    96  		}
    97  		// Gather all non-excluded contract for binding
    98  		for name, contract := range contracts {
    99  			if exclude[strings.ToLower(name)] {
   100  				continue
   101  			}
   102  			abi, _ := json.Marshal(contract.Info.AbiDefinition) // Flatten the compiler parse
   103  			abis = append(abis, string(abi))
   104  			bins = append(bins, contract.Code)
   105  			types = append(types, name)
   106  		}
   107  	} else {
   108  		// Otherwise load up the ABI, optional bytecode and type name from the parameters
   109  		abi, err := ioutil.ReadFile(*abiFlag)
   110  		if err != nil {
   111  			fmt.Printf("Failed to read input ABI: %v\n", err)
   112  			os.Exit(-1)
   113  		}
   114  		abis = append(abis, string(abi))
   115  
   116  		bin := []byte{}
   117  		if *binFlag != "" {
   118  			if bin, err = ioutil.ReadFile(*binFlag); err != nil {
   119  				fmt.Printf("Failed to read input bytecode: %v\n", err)
   120  				os.Exit(-1)
   121  			}
   122  		}
   123  		bins = append(bins, string(bin))
   124  
   125  		kind := *typFlag
   126  		if kind == "" {
   127  			kind = *pkgFlag
   128  		}
   129  		types = append(types, kind)
   130  	}
   131  	// Generate the contract binding
   132  	code, err := bind.Bind(types, abis, bins, *pkgFlag)
   133  	if err != nil {
   134  		fmt.Printf("Failed to generate ABI binding: %v\n", err)
   135  		os.Exit(-1)
   136  	}
   137  	// Either flush it out to a file or display on the standard output
   138  	if *outFlag == "" {
   139  		fmt.Printf("%s\n", code)
   140  		return
   141  	}
   142  	if err := ioutil.WriteFile(*outFlag, []byte(code), 0600); err != nil {
   143  		fmt.Printf("Failed to write ABI binding: %v\n", err)
   144  		os.Exit(-1)
   145  	}
   146  }