accounts/abi/bind, cmd/abigen: move around packages a bit

This commit is contained in:
Péter Szilágyi 2016-03-16 13:51:25 +02:00
parent 5ca063fe71
commit 512d25c794
4 changed files with 35 additions and 30 deletions

View file

@ -14,7 +14,7 @@
// You should have received a copy of the GNU Lesser General Public License // You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package abi package bind
import ( import (
"errors" "errors"
@ -22,6 +22,7 @@ import (
"math/big" "math/big"
"github.com/barakmich/glog" "github.com/barakmich/glog"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/state"
@ -74,7 +75,7 @@ type AuthOpts struct {
// higher level contract bindings to operate. // higher level contract bindings to operate.
type BoundContract struct { type BoundContract struct {
address common.Address // Deployment address of the contract on the Ethereum blockchain address common.Address // Deployment address of the contract on the Ethereum blockchain
abi ABI // Reflect based ABI to access the correct Ethereum methods abi abi.ABI // Reflect based ABI to access the correct Ethereum methods
blockchain *core.BlockChain // Ethereum blockchain to use for state retrieval blockchain *core.BlockChain // Ethereum blockchain to use for state retrieval
options *ContractOpts // Options fine tuning contract behaviour options *ContractOpts // Options fine tuning contract behaviour
@ -83,7 +84,7 @@ type BoundContract struct {
// NewBoundContract initialises a new ABI and returns the contract. It does not // NewBoundContract initialises a new ABI and returns the contract. It does not
// deploy the contract, hence the name. // deploy the contract, hence the name.
func NewBoundContract(address common.Address, abi ABI, blockchain *core.BlockChain, opts ContractOpts) *BoundContract { func NewBoundContract(address common.Address, abi abi.ABI, blockchain *core.BlockChain, opts ContractOpts) *BoundContract {
// Initialize any needed values for the contract options // Initialize any needed values for the contract options
if opts.EventMux == nil { if opts.EventMux == nil {
opts.EventMux = new(event.TypeMux) opts.EventMux = new(event.TypeMux)

View file

@ -14,7 +14,8 @@
// You should have received a copy of the GNU Lesser General Public License // You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package abi // Package bind generates Ethereum contract Go bindings.
package bind
import ( import (
"bytes" "bytes"
@ -22,6 +23,7 @@ import (
"sort" "sort"
"strings" "strings"
"github.com/ethereum/go-ethereum/accounts/abi"
"golang.org/x/tools/imports" "golang.org/x/tools/imports"
) )
@ -31,7 +33,7 @@ import (
// manually maintain hard coded strings that break on runtime. // manually maintain hard coded strings that break on runtime.
func Bind(jsonABI string, pkg string, kind string) (string, error) { func Bind(jsonABI string, pkg string, kind string) (string, error) {
// Parse the actual ABI to generate the binding for // Parse the actual ABI to generate the binding for
abi, err := JSON(strings.NewReader(jsonABI)) abi, err := abi.JSON(strings.NewReader(jsonABI))
if err != nil { if err != nil {
return "", err return "", err
} }
@ -75,18 +77,18 @@ func bindContract(kind string, abi string) string {
// Generate the Go struct with all the maintenance fields // Generate the Go struct with all the maintenance fields
code += fmt.Sprintf("// %s is an auto generated Go binding around an Ethereum contract.\n", kind) code += fmt.Sprintf("// %s is an auto generated Go binding around an Ethereum contract.\n", kind)
code += fmt.Sprintf("type %s struct {\n", kind) code += fmt.Sprintf("type %s struct {\n", kind)
code += fmt.Sprintf("contract *abi.BoundContract // Generic contract wrapper for the low level calls\n") code += fmt.Sprintf("contract *bind.BoundContract // Generic contract wrapper for the low level calls\n")
code += fmt.Sprintf("}\n\n") code += fmt.Sprintf("}\n\n")
// Generate the constructor to create a bound contract // Generate the constructor to create a bound contract
code += fmt.Sprintf("// New%s creates a new instance of %s, bound to a specific deployed contract.\n", kind, kind) code += fmt.Sprintf("// New%s creates a new instance of %s, bound to a specific deployed contract.\n", kind, kind)
code += fmt.Sprintf("func New%s(address common.Address, blockchain *core.BlockChain, opts abi.ContractOpts) (*%s, error) {\n", kind, kind) code += fmt.Sprintf("func New%s(address common.Address, blockchain *core.BlockChain, opts bind.ContractOpts) (*%s, error) {\n", kind, kind)
code += fmt.Sprintf(" parsed, err := abi.JSON(strings.NewReader(%sABI))\n", kind) code += fmt.Sprintf(" parsed, err := abi.JSON(strings.NewReader(%sABI))\n", kind)
code += fmt.Sprintf(" if err != nil {\n") code += fmt.Sprintf(" if err != nil {\n")
code += fmt.Sprintf(" return nil, err\n") code += fmt.Sprintf(" return nil, err\n")
code += fmt.Sprintf(" }\n") code += fmt.Sprintf(" }\n")
code += fmt.Sprintf(" return &%s{\n", kind) code += fmt.Sprintf(" return &%s{\n", kind)
code += fmt.Sprintf(" contract: abi.NewBoundContract(address, parsed, blockchain, opts),\n") code += fmt.Sprintf(" contract: bind.NewBoundContract(address, parsed, blockchain, opts),\n")
code += fmt.Sprintf(" }, nil\n") code += fmt.Sprintf(" }, nil\n")
code += fmt.Sprintf("}") code += fmt.Sprintf("}")
@ -94,7 +96,7 @@ func bindContract(kind string, abi string) string {
} }
// bindMethod // bindMethod
func bindMethod(kind string, method Method) string { func bindMethod(kind string, method abi.Method) string {
var ( var (
name = strings.ToUpper(method.Name[:1]) + method.Name[1:] name = strings.ToUpper(method.Name[:1]) + method.Name[1:]
prologue = new(bytes.Buffer) prologue = new(bytes.Buffer)
@ -123,7 +125,7 @@ func bindMethod(kind string, method Method) string {
if method.Const { if method.Const {
return fmt.Sprintf("%s\n%s\nfunc (_%s *%s) %s(%s) (%s) {\n%s\n}\n", prologue, docs, kind, kind, name, strings.Join(args, ","), strings.Join(returns, ","), bindCallBody(kind, method.Name, args, returns)) return fmt.Sprintf("%s\n%s\nfunc (_%s *%s) %s(%s) (%s) {\n%s\n}\n", prologue, docs, kind, kind, name, strings.Join(args, ","), strings.Join(returns, ","), bindCallBody(kind, method.Name, args, returns))
} else { } else {
args = append([]string{"auth *abi.AuthOpts"}, args...) args = append([]string{"auth *bind.AuthOpts"}, args...)
return fmt.Sprintf("%s\n%s\nfunc (_%s *%s) %s(%s) (*types.Transaction, error) {\n%s\n}\n", prologue, docs, kind, kind, name, strings.Join(args, ","), bindTransactionBody(kind, method.Name, args)) return fmt.Sprintf("%s\n%s\nfunc (_%s *%s) %s(%s) (*types.Transaction, error) {\n%s\n}\n", prologue, docs, kind, kind, name, strings.Join(args, ","), bindTransactionBody(kind, method.Name, args))
} }
} }
@ -131,43 +133,45 @@ func bindMethod(kind string, method Method) string {
// bindType converts a Solidity type to a Go one. Since there is no clear mapping // bindType converts a Solidity type to a Go one. Since there is no clear mapping
// from all Solidity types to Go ones (e.g. uint17), those that cannot be exactly // from all Solidity types to Go ones (e.g. uint17), those that cannot be exactly
// mapped will use an upscaled type (e.g. *big.Int). // mapped will use an upscaled type (e.g. *big.Int).
func bindType(kind Type) string { func bindType(kind abi.Type) string {
stringKind := kind.String()
switch { switch {
case kind.stringKind == "address": case stringKind == "address":
return "common.Address" return "common.Address"
case kind.stringKind == "hash": case stringKind == "hash":
return "common.Hash" return "common.Hash"
case strings.HasPrefix(kind.stringKind, "bytes"): case strings.HasPrefix(stringKind, "bytes"):
if kind.stringKind == "bytes" { if stringKind == "bytes" {
return "[]byte" return "[]byte"
} }
return fmt.Sprintf("[%s]byte", kind.stringKind[5:]) return fmt.Sprintf("[%s]byte", stringKind[5:])
case strings.HasPrefix(kind.stringKind, "int"): case strings.HasPrefix(stringKind, "int"):
switch kind.stringKind[:3] { switch stringKind[:3] {
case "8", "16", "32", "64": case "8", "16", "32", "64":
return kind.stringKind return stringKind
} }
return "*big.Int" return "*big.Int"
case strings.HasPrefix(kind.stringKind, "uint"): case strings.HasPrefix(stringKind, "uint"):
switch kind.stringKind[:4] { switch stringKind[:4] {
case "8", "16", "32", "64": case "8", "16", "32", "64":
return kind.stringKind return stringKind
} }
return "*big.Int" return "*big.Int"
default: default:
return kind.stringKind return stringKind
} }
} }
// bindReturn creates the list of return parameters for a method invocation. If // bindReturn creates the list of return parameters for a method invocation. If
// all the fields of the return type are named, and there is more than one value // all the fields of the return type are named, and there is more than one value
// being returned, the returns are wrapped in a result struct. // being returned, the returns are wrapped in a result struct.
func bindReturn(prologue *bytes.Buffer, method string, outputs []Argument) ([]string, string) { func bindReturn(prologue *bytes.Buffer, method string, outputs []abi.Argument) ([]string, string) {
// Generate the anonymous return list for when a struct is not needed/possible // Generate the anonymous return list for when a struct is not needed/possible
var ( var (
returns = make([]string, 0, len(outputs)+1) returns = make([]string, 0, len(outputs)+1)
@ -191,7 +195,7 @@ func bindReturn(prologue *bytes.Buffer, method string, outputs []Argument) ([]st
// bindReturnStruct creates a Go structure with the specified fields to be used // bindReturnStruct creates a Go structure with the specified fields to be used
// as the return type from a method call. // as the return type from a method call.
func bindReturnStruct(method string, returns []Argument) (string, string) { func bindReturnStruct(method string, returns []abi.Argument) (string, string) {
fields := make([]string, 0, len(returns)) fields := make([]string, 0, len(returns))
for _, ret := range returns { for _, ret := range returns {
fields = append(fields, fmt.Sprintf("%s %s", strings.ToUpper(ret.Name[:1])+ret.Name[1:], bindType(ret.Type))) fields = append(fields, fmt.Sprintf("%s %s", strings.ToUpper(ret.Name[:1])+ret.Name[1:], bindType(ret.Type)))

View file

@ -14,7 +14,7 @@
// You should have received a copy of the GNU Lesser General Public License // You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package abi package bind
/* /*
// Tests that packages generated by the binder can be successfully compiled. // Tests that packages generated by the binder can be successfully compiled.

View file

@ -22,7 +22,7 @@ import (
"io/ioutil" "io/ioutil"
"os" "os"
"github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/accounts/abi/bind"
) )
var ( var (
@ -54,17 +54,17 @@ func main() {
if kind == "" { if kind == "" {
kind = *pkgFlag kind = *pkgFlag
} }
bind, err := abi.Bind(string(in), *pkgFlag, kind) code, err := bind.Bind(string(in), *pkgFlag, kind)
if err != nil { if err != nil {
fmt.Printf("Failed to generate ABI binding: %v\n", err) fmt.Printf("Failed to generate ABI binding: %v\n", err)
os.Exit(-1) os.Exit(-1)
} }
// Either flush it out to a file or display on the standard output // Either flush it out to a file or display on the standard output
if *outFlag == "" { if *outFlag == "" {
fmt.Printf("%s\n", bind) fmt.Printf("%s\n", code)
return return
} }
if err := ioutil.WriteFile(*outFlag, []byte(bind), 0600); err != nil { if err := ioutil.WriteFile(*outFlag, []byte(code), 0600); err != nil {
fmt.Printf("Failed to write ABI binding: %v\n", err) fmt.Printf("Failed to write ABI binding: %v\n", err)
os.Exit(-1) os.Exit(-1)
} }