aboutsummaryrefslogtreecommitdiffstats
path: root/accounts/abi/method.go
diff options
context:
space:
mode:
authorRJ Catalano <catalanor0220@gmail.com>2017-10-17 19:07:08 +0800
committerFelix Lange <fjl@users.noreply.github.com>2017-10-17 19:07:08 +0800
commitdec8bba9d4c5fcb3dd7e51f0f794b3e895c7f52d (patch)
tree7e4713ca276ac1a2cef7cd2dd19dcf8c6fd1f6c4 /accounts/abi/method.go
parente9295163aa25479e817efee4aac23eaeb7554bba (diff)
downloaddexon-dec8bba9d4c5fcb3dd7e51f0f794b3e895c7f52d.tar
dexon-dec8bba9d4c5fcb3dd7e51f0f794b3e895c7f52d.tar.gz
dexon-dec8bba9d4c5fcb3dd7e51f0f794b3e895c7f52d.tar.bz2
dexon-dec8bba9d4c5fcb3dd7e51f0f794b3e895c7f52d.tar.lz
dexon-dec8bba9d4c5fcb3dd7e51f0f794b3e895c7f52d.tar.xz
dexon-dec8bba9d4c5fcb3dd7e51f0f794b3e895c7f52d.tar.zst
dexon-dec8bba9d4c5fcb3dd7e51f0f794b3e895c7f52d.zip
accounts/abi: improve type handling, add event support (#14743)
Diffstat (limited to 'accounts/abi/method.go')
-rw-r--r--accounts/abi/method.go79
1 files changed, 79 insertions, 0 deletions
diff --git a/accounts/abi/method.go b/accounts/abi/method.go
index 62b3d2957..d8838e9ed 100644
--- a/accounts/abi/method.go
+++ b/accounts/abi/method.go
@@ -77,6 +77,85 @@ func (method Method) pack(args ...interface{}) ([]byte, error) {
return ret, nil
}
+// unpacks a method return tuple into a struct of corresponding go types
+//
+// Unpacking can be done into a struct or a slice/array.
+func (method Method) tupleUnpack(v interface{}, output []byte) error {
+ // make sure the passed value is a pointer
+ valueOf := reflect.ValueOf(v)
+ if reflect.Ptr != valueOf.Kind() {
+ return fmt.Errorf("abi: Unpack(non-pointer %T)", v)
+ }
+
+ var (
+ value = valueOf.Elem()
+ typ = value.Type()
+ )
+
+ j := 0
+ for i := 0; i < len(method.Outputs); i++ {
+ toUnpack := method.Outputs[i]
+ if toUnpack.Type.T == ArrayTy {
+ // need to move this up because they read sequentially
+ j += toUnpack.Type.Size
+ }
+ marshalledValue, err := toGoType((i+j)*32, toUnpack.Type, output)
+ if err != nil {
+ return err
+ }
+ reflectValue := reflect.ValueOf(marshalledValue)
+
+ switch value.Kind() {
+ case reflect.Struct:
+ for j := 0; j < typ.NumField(); j++ {
+ field := typ.Field(j)
+ // TODO read tags: `abi:"fieldName"`
+ if field.Name == strings.ToUpper(method.Outputs[i].Name[:1])+method.Outputs[i].Name[1:] {
+ if err := set(value.Field(j), reflectValue, method.Outputs[i]); err != nil {
+ return err
+ }
+ }
+ }
+ case reflect.Slice, reflect.Array:
+ if value.Len() < i {
+ return fmt.Errorf("abi: insufficient number of arguments for unpack, want %d, got %d", len(method.Outputs), value.Len())
+ }
+ v := value.Index(i)
+ if v.Kind() != reflect.Ptr && v.Kind() != reflect.Interface {
+ return fmt.Errorf("abi: cannot unmarshal %v in to %v", v.Type(), reflectValue.Type())
+ }
+ reflectValue := reflect.ValueOf(marshalledValue)
+ if err := set(v.Elem(), reflectValue, method.Outputs[i]); err != nil {
+ return err
+ }
+ default:
+ return fmt.Errorf("abi: cannot unmarshal tuple in to %v", typ)
+ }
+ }
+ return nil
+}
+
+func (method Method) isTupleReturn() bool { return len(method.Outputs) > 1 }
+
+func (method Method) singleUnpack(v interface{}, output []byte) error {
+ // make sure the passed value is a pointer
+ valueOf := reflect.ValueOf(v)
+ if reflect.Ptr != valueOf.Kind() {
+ return fmt.Errorf("abi: Unpack(non-pointer %T)", v)
+ }
+
+ value := valueOf.Elem()
+
+ marshalledValue, err := toGoType(0, method.Outputs[0].Type, output)
+ if err != nil {
+ return err
+ }
+ if err := set(value, reflect.ValueOf(marshalledValue), method.Outputs[0]); err != nil {
+ return err
+ }
+ return nil
+}
+
// Sig returns the methods string signature according to the ABI spec.
//
// Example