accounts/abi: fix mobile interface (#19180)

This commit is contained in:
Daniel Liu 2024-12-12 16:28:30 +08:00
parent b711dc811d
commit 91570dce8a
2 changed files with 30 additions and 126 deletions

View file

@ -161,139 +161,43 @@ var bindType = map[Lang]func(kind abi.Type) string{
LangGo: bindTypeGo, LangGo: bindTypeGo,
} }
// Helper function for the binding generators. // bindBasicTypeGo converts basic solidity types(except array, slice and tuple) to Go one.
// It reads the unmatched characters after the inner type-match, func bindBasicTypeGo(kind abi.Type) string {
// switch kind.T {
// (since the inner type is a prefix of the total type declaration), case abi.AddressTy:
// looks for valid arrays (possibly a dynamic one) wrapping the inner type, return "common.Address"
// and returns the sizes of these arrays. case abi.IntTy, abi.UintTy:
// parts := regexp.MustCompile(`(u)?int([0-9]*)`).FindStringSubmatch(kind.String())
// Returned array sizes are in the same order as solidity signatures; inner array size first.
// Array sizes may also be "", indicating a dynamic array.
func wrapArray(stringKind string, innerLen int, innerMapping string) (string, []string) {
remainder := stringKind[innerLen:]
//find all the sizes
matches := regexp.MustCompile(`\[(\d*)\]`).FindAllStringSubmatch(remainder, -1)
parts := make([]string, 0, len(matches))
for _, match := range matches {
//get group 1 from the regex match
parts = append(parts, match[1])
}
return innerMapping, parts
}
// Translates the array sizes to a Go-lang declaration of a (nested) array of the inner type.
// Simply returns the inner type if arraySizes is empty.
func arrayBindingGo(inner string, arraySizes []string) string {
out := ""
//prepend all array sizes, from outer (end arraySizes) to inner (start arraySizes)
for i := len(arraySizes) - 1; i >= 0; i-- {
out += "[" + arraySizes[i] + "]"
}
out += inner
return out
}
// bindTypeGo 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
// mapped will use an upscaled type (e.g. *big.Int).
func bindTypeGo(kind abi.Type) string {
stringKind := kind.String()
innerLen, innerMapping := bindUnnestedTypeGo(stringKind)
return arrayBindingGo(wrapArray(stringKind, innerLen, innerMapping))
}
// The inner function of bindTypeGo, this finds the inner type of stringKind.
// (Or just the type itself if it is not an array or slice)
// The length of the matched part is returned, with the the translated type.
func bindUnnestedTypeGo(stringKind string) (int, string) {
switch {
case strings.HasPrefix(stringKind, "address"):
return len("address"), "common.Address"
case strings.HasPrefix(stringKind, "bytes"):
parts := regexp.MustCompile(`bytes([0-9]*)`).FindStringSubmatch(stringKind)
return len(parts[0]), fmt.Sprintf("[%s]byte", parts[1])
case strings.HasPrefix(stringKind, "int") || strings.HasPrefix(stringKind, "uint"):
parts := regexp.MustCompile(`(u)?int([0-9]*)`).FindStringSubmatch(stringKind)
switch parts[2] { switch parts[2] {
case "8", "16", "32", "64": case "8", "16", "32", "64":
return len(parts[0]), fmt.Sprintf("%sint%s", parts[1], parts[2]) return fmt.Sprintf("%sint%s", parts[1], parts[2])
} }
return len(parts[0]), "*big.Int" return "*big.Int"
case abi.FixedBytesTy:
case strings.HasPrefix(stringKind, "bool"): return fmt.Sprintf("[%d]byte", kind.Size)
return len("bool"), "bool" case abi.BytesTy:
return "[]byte"
case strings.HasPrefix(stringKind, "string"): case abi.FunctionTy:
return len("string"), "string" // todo(rjl493456442)
return ""
default: default:
return len(stringKind), stringKind // string, bool types
return kind.String()
} }
} }
// Translates the array sizes to a Java declaration of a (nested) array of the inner type. // bindTypeGo converts solidity types to Go ones. Since there is no clear mapping
// Simply returns the inner type if arraySizes is empty. // from all Solidity types to Go ones (e.g. uint17), those that cannot be exactly
func arrayBindingJava(inner string, arraySizes []string) string { // mapped will use an upscaled type (e.g. BigDecimal).
// Java array type declarations do not include the length. func bindTypeGo(kind abi.Type) string {
return inner + strings.Repeat("[]", len(arraySizes)) // todo(rjl493456442) tuple
} switch kind.T {
case abi.ArrayTy:
// The inner function of bindTypeJava, this finds the inner type of stringKind. return fmt.Sprintf("[%d]", kind.Size) + bindTypeGo(*kind.Elem)
// (Or just the type itself if it is not an array or slice) case abi.SliceTy:
// The length of the matched part is returned, with the the translated type. return "[]" + bindTypeGo(*kind.Elem)
func bindUnnestedTypeJava(stringKind string) (int, string) {
switch {
case strings.HasPrefix(stringKind, "address"):
parts := regexp.MustCompile(`address(\[[0-9]*\])?`).FindStringSubmatch(stringKind)
if len(parts) != 2 {
return len(stringKind), stringKind
}
if parts[1] == "" {
return len("address"), "Address"
}
return len(parts[0]), "Addresses"
case strings.HasPrefix(stringKind, "bytes"):
parts := regexp.MustCompile(`bytes([0-9]*)`).FindStringSubmatch(stringKind)
if len(parts) != 2 {
return len(stringKind), stringKind
}
return len(parts[0]), "byte[]"
case strings.HasPrefix(stringKind, "int") || strings.HasPrefix(stringKind, "uint"):
//Note that uint and int (without digits) are also matched,
// these are size 256, and will translate to BigInt (the default).
parts := regexp.MustCompile(`(u)?int([0-9]*)`).FindStringSubmatch(stringKind)
if len(parts) != 3 {
return len(stringKind), stringKind
}
namedSize := map[string]string{
"8": "byte",
"16": "short",
"32": "int",
"64": "long",
}[parts[2]]
//default to BigInt
if namedSize == "" {
namedSize = "BigInt"
}
return len(parts[0]), namedSize
case strings.HasPrefix(stringKind, "bool"):
return len("bool"), "boolean"
case strings.HasPrefix(stringKind, "string"):
return len("string"), "String"
default: default:
return len(stringKind), stringKind return bindBasicTypeGo(kind)
} }
} }

View file

@ -936,7 +936,7 @@ var bindTests = []struct {
// Tests that packages generated by the binder can be successfully compiled and // Tests that packages generated by the binder can be successfully compiled and
// the requested tester run against it. // the requested tester run against it.
func TestBindings(t *testing.T) { func TestGolangBindings(t *testing.T) {
// Skip the test if no Go command can be found // Skip the test if no Go command can be found
gocmd := runtime.GOROOT() + "/bin/go" gocmd := runtime.GOROOT() + "/bin/go"
if !common.FileExist(gocmd) { if !common.FileExist(gocmd) {