mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-26 06:36:43 +00:00
abigen: adding support for configurable template file for generating bindings
This commit is contained in:
parent
b135da2eac
commit
ec72537db5
5 changed files with 45 additions and 11 deletions
|
|
@ -294,7 +294,7 @@ func iterSorted[V any](inp map[string]V, onItem func(string, V) error) error {
|
||||||
// to be used as is in client code, but rather as an intermediate struct which
|
// to be used as is in client code, but rather as an intermediate struct which
|
||||||
// enforces compile time type safety and naming convention as opposed to having to
|
// enforces compile time type safety and naming convention as opposed to having to
|
||||||
// manually maintain hard coded strings that break on runtime.
|
// manually maintain hard coded strings that break on runtime.
|
||||||
func BindV2(types []string, abis []string, bytecodes []string, pkg string, libs map[string]string, aliases map[string]string) (string, error) {
|
func BindV2(types []string, abis []string, bytecodes []string, pkg string, libs map[string]string, aliases map[string]string, templateContent string) (string, error) {
|
||||||
b := binder{
|
b := binder{
|
||||||
contracts: make(map[string]*tmplContractV2),
|
contracts: make(map[string]*tmplContractV2),
|
||||||
structs: make(map[string]*tmplStruct),
|
structs: make(map[string]*tmplStruct),
|
||||||
|
|
@ -360,7 +360,7 @@ func BindV2(types []string, abis []string, bytecodes []string, pkg string, libs
|
||||||
"ispointertype": isPointerType,
|
"ispointertype": isPointerType,
|
||||||
"underlyingbindtype": underlyingBindType,
|
"underlyingbindtype": underlyingBindType,
|
||||||
}
|
}
|
||||||
tmpl := template.Must(template.New("").Funcs(funcs).Parse(tmplSourceV2))
|
tmpl := template.Must(template.New("").Funcs(funcs).Parse(templateContent))
|
||||||
if err := tmpl.Execute(buffer, data); err != nil {
|
if err := tmpl.Execute(buffer, data); err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -58,7 +58,7 @@ func bindCombinedJSON(test *bindV2Test) (string, error) {
|
||||||
if test.aliases == nil {
|
if test.aliases == nil {
|
||||||
test.aliases = make(map[string]string)
|
test.aliases = make(map[string]string)
|
||||||
}
|
}
|
||||||
code, err := BindV2(types, abis, bins, "bindtests", libs, test.aliases)
|
code, err := BindV2(types, abis, bins, "bindtests", libs, test.aliases, TmplSourceV2)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", fmt.Errorf("error creating bindings: %v", err)
|
return "", fmt.Errorf("error creating bindings: %v", err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -133,4 +133,4 @@ var tmplSource string
|
||||||
// for abigen v2 is based on.
|
// for abigen v2 is based on.
|
||||||
//
|
//
|
||||||
//go:embed source2.go.tpl
|
//go:embed source2.go.tpl
|
||||||
var tmplSourceV2 string
|
var TmplSourceV2 string
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,26 @@ import (
|
||||||
// TestBindingGeneration tests that re-running generation of bindings does not result in
|
// TestBindingGeneration tests that re-running generation of bindings does not result in
|
||||||
// mutations to the binding code.
|
// mutations to the binding code.
|
||||||
func TestBindingGeneration(t *testing.T) {
|
func TestBindingGeneration(t *testing.T) {
|
||||||
|
BindGenerationWithExpectedOutput(t, abigen.TmplSourceV2, getCodeFromBindingsDotGo)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBindingGenerationWithDifferentTemplate(t *testing.T) {
|
||||||
|
BindGenerationWithExpectedOutput(t, "package {{.Package}} //test template", getHarcodedCodeFromBindingsDotGo)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getHarcodedCodeFromBindingsDotGo(t *testing.T, basePath string) string {
|
||||||
|
return "package " + strings.Replace(basePath, "internal/contracts/", "", -1) + " //test template\n"
|
||||||
|
}
|
||||||
|
|
||||||
|
func getCodeFromBindingsDotGo(t *testing.T, basePath string) string {
|
||||||
|
existingBindings, err := os.ReadFile(filepath.Join(basePath, "bindings.go"))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("ReadFile returned error: %v", err)
|
||||||
|
}
|
||||||
|
return string(existingBindings)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BindGenerationWithExpectedOutput(t *testing.T, templateContent string, getExpectedCodeFunc func(t *testing.T, basePath string) string) {
|
||||||
matches, _ := filepath.Glob("internal/contracts/*")
|
matches, _ := filepath.Glob("internal/contracts/*")
|
||||||
var dirs []string
|
var dirs []string
|
||||||
for _, match := range matches {
|
for _, match := range matches {
|
||||||
|
|
@ -86,16 +106,13 @@ func TestBindingGeneration(t *testing.T) {
|
||||||
libPattern := crypto.Keccak256Hash([]byte(name)).String()[2:36] // the first 2 chars are 0x
|
libPattern := crypto.Keccak256Hash([]byte(name)).String()[2:36] // the first 2 chars are 0x
|
||||||
libs[libPattern] = typeName
|
libs[libPattern] = typeName
|
||||||
}
|
}
|
||||||
code, err := abigen.BindV2(types, abis, bins, dir, libs, make(map[string]string))
|
code, err := abigen.BindV2(types, abis, bins, dir, libs, make(map[string]string), templateContent)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("error creating bindings for package %s: %v", dir, err)
|
t.Fatalf("error creating bindings for package %s: %v", dir, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
existingBindings, err := os.ReadFile(filepath.Join(basePath, "bindings.go"))
|
expectedCode := getExpectedCodeFunc(t, basePath)
|
||||||
if err != nil {
|
if code != expectedCode {
|
||||||
t.Fatalf("ReadFile returned error: %v", err)
|
|
||||||
}
|
|
||||||
if code != string(existingBindings) {
|
|
||||||
t.Fatalf("code mismatch for %s", dir)
|
t.Fatalf("code mismatch for %s", dir)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -67,6 +67,10 @@ var (
|
||||||
Name: "alias",
|
Name: "alias",
|
||||||
Usage: "Comma separated aliases for function and event renaming. If --v2 is set, errors are aliased as well. e.g. original1=alias1, original2=alias2",
|
Usage: "Comma separated aliases for function and event renaming. If --v2 is set, errors are aliased as well. e.g. original1=alias1, original2=alias2",
|
||||||
}
|
}
|
||||||
|
templateFlag = &cli.StringFlag{
|
||||||
|
Name: "template",
|
||||||
|
Usage: "Input file to use as template for generating bindings",
|
||||||
|
}
|
||||||
v2Flag = &cli.BoolFlag{
|
v2Flag = &cli.BoolFlag{
|
||||||
Name: "v2",
|
Name: "v2",
|
||||||
Usage: "Generates v2 bindings",
|
Usage: "Generates v2 bindings",
|
||||||
|
|
@ -86,6 +90,7 @@ func init() {
|
||||||
pkgFlag,
|
pkgFlag,
|
||||||
outFlag,
|
outFlag,
|
||||||
aliasFlag,
|
aliasFlag,
|
||||||
|
templateFlag,
|
||||||
v2Flag,
|
v2Flag,
|
||||||
}
|
}
|
||||||
app.Action = generate
|
app.Action = generate
|
||||||
|
|
@ -100,6 +105,9 @@ func generate(c *cli.Context) error {
|
||||||
if c.String(abiFlag.Name) == "" && c.String(jsonFlag.Name) == "" {
|
if c.String(abiFlag.Name) == "" && c.String(jsonFlag.Name) == "" {
|
||||||
utils.Fatalf("Either contract ABI source (--abi) or combined-json (--combined-json) are required")
|
utils.Fatalf("Either contract ABI source (--abi) or combined-json (--combined-json) are required")
|
||||||
}
|
}
|
||||||
|
if !c.Bool(v2Flag.Name) && c.IsSet(templateFlag.Name) {
|
||||||
|
utils.Fatalf("Template configurabion only works with abigen v2")
|
||||||
|
}
|
||||||
// If the entire solidity code was specified, build and bind based on that
|
// If the entire solidity code was specified, build and bind based on that
|
||||||
var (
|
var (
|
||||||
abis []string
|
abis []string
|
||||||
|
|
@ -216,7 +224,16 @@ func generate(c *cli.Context) error {
|
||||||
err error
|
err error
|
||||||
)
|
)
|
||||||
if c.IsSet(v2Flag.Name) {
|
if c.IsSet(v2Flag.Name) {
|
||||||
code, err = abigen.BindV2(types, abis, bins, c.String(pkgFlag.Name), libs, aliases)
|
template := abigen.TmplSourceV2
|
||||||
|
if c.IsSet(templateFlag.Name) {
|
||||||
|
templateLoc := c.String(templateFlag.Name)
|
||||||
|
templateData, err := os.ReadFile(templateLoc)
|
||||||
|
if err != nil {
|
||||||
|
utils.Fatalf("Error reading template file: %s, error: %", templateLoc, err)
|
||||||
|
}
|
||||||
|
template = string(templateData)
|
||||||
|
}
|
||||||
|
code, err = abigen.BindV2(types, abis, bins, c.String(pkgFlag.Name), libs, aliases, template)
|
||||||
} else {
|
} else {
|
||||||
code, err = abigen.Bind(types, abis, bins, sigs, c.String(pkgFlag.Name), libs, aliases)
|
code, err = abigen.Bind(types, abis, bins, sigs, c.String(pkgFlag.Name), libs, aliases)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue