1414// You should have received a copy of the GNU Lesser General Public License
1515// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
1616
17- // Package bind generates Ethereum contract Go bindings.
17+ // Package abigen generates Ethereum contract Go bindings.
1818//
1919// Detailed usage document and tutorial available on the go-ethereum Wiki page:
20- // https://github.com/ ethereum/go-ethereum/wiki/Native-DApps:-Go- bindings-to-Ethereum-contracts
21- package bind
20+ // https://geth. ethereum.org/docs/developers/dapp-developer/native- bindings
21+ package abigen
2222
2323import (
2424 "bytes"
@@ -33,13 +33,6 @@ import (
3333 "github.com/ethereum/go-ethereum/log"
3434)
3535
36- // Lang is a target programming language selector to generate bindings for.
37- type Lang int
38-
39- const (
40- LangGo Lang = iota
41- )
42-
4336func isKeyWord (arg string ) bool {
4437 switch arg {
4538 case "break" :
@@ -81,7 +74,7 @@ func isKeyWord(arg string) bool {
8174// to be used as is in client code, but rather as an intermediate struct which
8275// enforces compile time type safety and naming convention as opposed to having to
8376// manually maintain hard coded strings that break on runtime.
84- func Bind (types []string , abis []string , bytecodes []string , fsigs []map [string ]string , pkg string , lang Lang , libs map [string ]string , aliases map [string ]string ) (string , error ) {
77+ func Bind (types []string , abis []string , bytecodes []string , fsigs []map [string ]string , pkg string , libs map [string ]string , aliases map [string ]string ) (string , error ) {
8578 var (
8679 // contracts is the map of each individual contract requested binding
8780 contracts = make (map [string ]* tmplContract )
@@ -125,14 +118,14 @@ func Bind(types []string, abis []string, bytecodes []string, fsigs []map[string]
125118
126119 for _ , input := range evmABI .Constructor .Inputs {
127120 if hasStruct (input .Type ) {
128- bindStructType [ lang ] (input .Type , structs )
121+ bindStructType (input .Type , structs )
129122 }
130123 }
131124
132125 for _ , original := range evmABI .Methods {
133126 // Normalize the method for capital cases and non-anonymous inputs/outputs
134127 normalized := original
135- normalizedName := methodNormalizer [ lang ] (alias (aliases , original .Name ))
128+ normalizedName := abi . ToCamelCase (alias (aliases , original .Name ))
136129 // Ensure there is no duplicated identifier
137130 var identifiers = callIdentifiers
138131 if ! original .IsConstant () {
@@ -159,17 +152,17 @@ func Bind(types []string, abis []string, bytecodes []string, fsigs []map[string]
159152 normalized .Inputs [j ].Name = fmt .Sprintf ("arg%d" , j )
160153 }
161154 if hasStruct (input .Type ) {
162- bindStructType [ lang ] (input .Type , structs )
155+ bindStructType (input .Type , structs )
163156 }
164157 }
165158 normalized .Outputs = make ([]abi.Argument , len (original .Outputs ))
166159 copy (normalized .Outputs , original .Outputs )
167160 for j , output := range normalized .Outputs {
168161 if output .Name != "" {
169- normalized .Outputs [j ].Name = capitalise (output .Name )
162+ normalized .Outputs [j ].Name = abi . ToCamelCase (output .Name )
170163 }
171164 if hasStruct (output .Type ) {
172- bindStructType [ lang ] (output .Type , structs )
165+ bindStructType (output .Type , structs )
173166 }
174167 }
175168 // Append the methods to the call or transact lists
@@ -188,7 +181,7 @@ func Bind(types []string, abis []string, bytecodes []string, fsigs []map[string]
188181 normalized := original
189182
190183 // Ensure there is no duplicated identifier
191- normalizedName := methodNormalizer [ lang ] (alias (aliases , original .Name ))
184+ normalizedName := abi . ToCamelCase (alias (aliases , original .Name ))
192185 // Name shouldn't start with a digit. It will make the generated code invalid.
193186 if len (normalizedName ) > 0 && unicode .IsDigit (rune (normalizedName [0 ])) {
194187 normalizedName = fmt .Sprintf ("E%s" , normalizedName )
@@ -213,14 +206,14 @@ func Bind(types []string, abis []string, bytecodes []string, fsigs []map[string]
213206 // Event is a bit special, we need to define event struct in binding,
214207 // ensure there is no camel-case-style name conflict.
215208 for index := 0 ; ; index ++ {
216- if ! used [capitalise (normalized .Inputs [j ].Name )] {
217- used [capitalise (normalized .Inputs [j ].Name )] = true
209+ if ! used [abi . ToCamelCase (normalized .Inputs [j ].Name )] {
210+ used [abi . ToCamelCase (normalized .Inputs [j ].Name )] = true
218211 break
219212 }
220213 normalized .Inputs [j ].Name = fmt .Sprintf ("%s%d" , normalized .Inputs [j ].Name , index )
221214 }
222215 if hasStruct (input .Type ) {
223- bindStructType [ lang ] (input .Type , structs )
216+ bindStructType (input .Type , structs )
224217 }
225218 }
226219 // Append the event to the accumulator list
@@ -233,8 +226,9 @@ func Bind(types []string, abis []string, bytecodes []string, fsigs []map[string]
233226 if evmABI .HasReceive () {
234227 receive = & tmplMethod {Original : evmABI .Receive }
235228 }
229+
236230 contracts [types [i ]] = & tmplContract {
237- Type : capitalise (types [i ]),
231+ Type : abi . ToCamelCase (types [i ]),
238232 InputABI : strings .ReplaceAll (strippedABI , "\" " , "\\ \" " ),
239233 InputBin : strings .TrimPrefix (strings .TrimSpace (bytecodes [i ]), "0x" ),
240234 Constructor : evmABI .Constructor ,
@@ -245,6 +239,7 @@ func Bind(types []string, abis []string, bytecodes []string, fsigs []map[string]
245239 Events : events ,
246240 Libraries : make (map [string ]string ),
247241 }
242+
248243 // Function 4-byte signatures are stored in the same sequence
249244 // as types, if available.
250245 if len (fsigs ) > i {
@@ -270,6 +265,7 @@ func Bind(types []string, abis []string, bytecodes []string, fsigs []map[string]
270265 _ , ok := isLib [types [i ]]
271266 contracts [types [i ]].Library = ok
272267 }
268+
273269 // Generate the contract template data content and render it
274270 data := & tmplData {
275271 Package : pkg ,
@@ -280,36 +276,25 @@ func Bind(types []string, abis []string, bytecodes []string, fsigs []map[string]
280276 buffer := new (bytes.Buffer )
281277
282278 funcs := map [string ]interface {}{
283- "bindtype" : bindType [lang ],
284- "bindtopictype" : bindTopicType [lang ],
285- "namedtype" : namedType [lang ],
286- "capitalise" : capitalise ,
279+ "bindtype" : bindType ,
280+ "bindtopictype" : bindTopicType ,
281+ "capitalise" : abi .ToCamelCase ,
287282 "decapitalise" : decapitalise ,
288283 }
289- tmpl := template .Must (template .New ("" ).Funcs (funcs ).Parse (tmplSource [ lang ] ))
284+ tmpl := template .Must (template .New ("" ).Funcs (funcs ).Parse (tmplSource ))
290285 if err := tmpl .Execute (buffer , data ); err != nil {
291286 return "" , err
292287 }
293- // For Go bindings pass the code through gofmt to clean it up
294- if lang == LangGo {
295- code , err := format .Source (buffer .Bytes ())
296- if err != nil {
297- return "" , fmt .Errorf ("%v\n %s" , err , buffer )
298- }
299- return string (code ), nil
288+ // Pass the code through gofmt to clean it up
289+ code , err := format .Source (buffer .Bytes ())
290+ if err != nil {
291+ return "" , fmt .Errorf ("%v\n %s" , err , buffer )
300292 }
301- // For all others just return as is for now
302- return buffer .String (), nil
303- }
304-
305- // bindType is a set of type binders that convert Solidity types to some supported
306- // programming language types.
307- var bindType = map [Lang ]func (kind abi.Type , structs map [string ]* tmplStruct ) string {
308- LangGo : bindTypeGo ,
293+ return string (code ), nil
309294}
310295
311- // bindBasicTypeGo converts basic solidity types(except array, slice and tuple) to Go ones.
312- func bindBasicTypeGo (kind abi.Type ) string {
296+ // bindBasicType converts basic solidity types(except array, slice and tuple) to Go ones.
297+ func bindBasicType (kind abi.Type ) string {
313298 switch kind .T {
314299 case abi .AddressTy :
315300 return "common.Address"
@@ -332,32 +317,26 @@ func bindBasicTypeGo(kind abi.Type) string {
332317 }
333318}
334319
335- // bindTypeGo converts solidity types to Go ones. Since there is no clear mapping
320+ // bindType converts solidity types to Go ones. Since there is no clear mapping
336321// from all Solidity types to Go ones (e.g. uint17), those that cannot be exactly
337322// mapped will use an upscaled type (e.g. BigDecimal).
338- func bindTypeGo (kind abi.Type , structs map [string ]* tmplStruct ) string {
323+ func bindType (kind abi.Type , structs map [string ]* tmplStruct ) string {
339324 switch kind .T {
340325 case abi .TupleTy :
341326 return structs [kind .TupleRawName + kind .String ()].Name
342327 case abi .ArrayTy :
343- return fmt .Sprintf ("[%d]" , kind .Size ) + bindTypeGo (* kind .Elem , structs )
328+ return fmt .Sprintf ("[%d]" , kind .Size ) + bindType (* kind .Elem , structs )
344329 case abi .SliceTy :
345- return "[]" + bindTypeGo (* kind .Elem , structs )
330+ return "[]" + bindType (* kind .Elem , structs )
346331 default :
347- return bindBasicTypeGo (kind )
332+ return bindBasicType (kind )
348333 }
349334}
350335
351- // bindTopicType is a set of type binders that convert Solidity types to some
352- // supported programming language topic types.
353- var bindTopicType = map [Lang ]func (kind abi.Type , structs map [string ]* tmplStruct ) string {
354- LangGo : bindTopicTypeGo ,
355- }
356-
357- // bindTopicTypeGo converts a Solidity topic type to a Go one. It is almost the same
336+ // bindTopicType converts a Solidity topic type to a Go one. It is almost the same
358337// functionality as for simple types, but dynamic types get converted to hashes.
359- func bindTopicTypeGo (kind abi.Type , structs map [string ]* tmplStruct ) string {
360- bound := bindTypeGo (kind , structs )
338+ func bindTopicType (kind abi.Type , structs map [string ]* tmplStruct ) string {
339+ bound := bindType (kind , structs )
361340
362341 // todo(rjl493456442) according solidity documentation, indexed event
363342 // parameters that are not value types i.e. arrays and structs are not
@@ -371,16 +350,10 @@ func bindTopicTypeGo(kind abi.Type, structs map[string]*tmplStruct) string {
371350 return bound
372351}
373352
374- // bindStructType is a set of type binders that convert Solidity tuple types to some supported
375- // programming language struct definition.
376- var bindStructType = map [Lang ]func (kind abi.Type , structs map [string ]* tmplStruct ) string {
377- LangGo : bindStructTypeGo ,
378- }
379-
380- // bindStructTypeGo converts a Solidity tuple type to a Go one and records the mapping
381- // in the given map.
382- // Notably, this function will resolve and record nested struct recursively.
383- func bindStructTypeGo (kind abi.Type , structs map [string ]* tmplStruct ) string {
353+ // bindStructType converts a Solidity tuple type to a Go one and records the mapping
354+ // in the given map. Notably, this function will resolve and record nested struct
355+ // recursively.
356+ func bindStructType (kind abi.Type , structs map [string ]* tmplStruct ) string {
384357 switch kind .T {
385358 case abi .TupleTy :
386359 // We compose a raw struct name and a canonical parameter expression
@@ -398,37 +371,35 @@ func bindStructTypeGo(kind abi.Type, structs map[string]*tmplStruct) string {
398371 fields []* tmplField
399372 )
400373 for i , elem := range kind .TupleElems {
401- name := capitalise (kind .TupleRawNames [i ])
374+ name := abi . ToCamelCase (kind .TupleRawNames [i ])
402375 name = abi .ResolveNameConflict (name , func (s string ) bool { return names [s ] })
403376 names [name ] = true
404- fields = append (fields , & tmplField {Type : bindStructTypeGo (* elem , structs ), Name : name , SolKind : * elem })
377+ fields = append (fields , & tmplField {
378+ Type : bindStructType (* elem , structs ),
379+ Name : name ,
380+ SolKind : * elem ,
381+ })
405382 }
406383 name := kind .TupleRawName
407384 if name == "" {
408385 name = fmt .Sprintf ("Struct%d" , len (structs ))
409386 }
410- name = capitalise (name )
387+ name = abi . ToCamelCase (name )
411388
412389 structs [id ] = & tmplStruct {
413390 Name : name ,
414391 Fields : fields ,
415392 }
416393 return name
417394 case abi .ArrayTy :
418- return fmt .Sprintf ("[%d]" , kind .Size ) + bindStructTypeGo (* kind .Elem , structs )
395+ return fmt .Sprintf ("[%d]" , kind .Size ) + bindStructType (* kind .Elem , structs )
419396 case abi .SliceTy :
420- return "[]" + bindStructTypeGo (* kind .Elem , structs )
397+ return "[]" + bindStructType (* kind .Elem , structs )
421398 default :
422- return bindBasicTypeGo (kind )
399+ return bindBasicType (kind )
423400 }
424401}
425402
426- // namedType is a set of functions that transform language specific types to
427- // named versions that may be used inside method names.
428- var namedType = map [Lang ]func (string , abi.Type ) string {
429- LangGo : func (string , abi.Type ) string { panic ("this shouldn't be needed" ) },
430- }
431-
432403// alias returns an alias of the given string based on the aliasing rules
433404// or returns itself if no rule is matched.
434405func alias (aliases map [string ]string , n string ) string {
@@ -438,21 +409,11 @@ func alias(aliases map[string]string, n string) string {
438409 return n
439410}
440411
441- // methodNormalizer is a name transformer that modifies Solidity method names to
442- // conform to target language naming conventions.
443- var methodNormalizer = map [Lang ]func (string ) string {
444- LangGo : abi .ToCamelCase ,
445- }
446-
447- // capitalise makes a camel-case string which starts with an upper case character.
448- var capitalise = abi .ToCamelCase
449-
450412// decapitalise makes a camel-case string which starts with a lower case character.
451413func decapitalise (input string ) string {
452414 if len (input ) == 0 {
453415 return input
454416 }
455-
456417 goForm := abi .ToCamelCase (input )
457418 return strings .ToLower (goForm [:1 ]) + goForm [1 :]
458419}
@@ -471,7 +432,7 @@ func structured(args abi.Arguments) bool {
471432 }
472433 // If the field name is empty when normalized or collides (var, Var, _var, _Var),
473434 // we can't organize into a struct
474- field := capitalise (out .Name )
435+ field := abi . ToCamelCase (out .Name )
475436 if field == "" || exists [field ] {
476437 return false
477438 }
0 commit comments