diff options
author | RJ Catalano <catalanor0220@gmail.com> | 2017-10-17 19:07:08 +0800 |
---|---|---|
committer | Felix Lange <fjl@users.noreply.github.com> | 2017-10-17 19:07:08 +0800 |
commit | dec8bba9d4c5fcb3dd7e51f0f794b3e895c7f52d (patch) | |
tree | 7e4713ca276ac1a2cef7cd2dd19dcf8c6fd1f6c4 /accounts/abi/event.go | |
parent | e9295163aa25479e817efee4aac23eaeb7554bba (diff) | |
download | dexon-dec8bba9d4c5fcb3dd7e51f0f794b3e895c7f52d.tar.gz dexon-dec8bba9d4c5fcb3dd7e51f0f794b3e895c7f52d.tar.zst dexon-dec8bba9d4c5fcb3dd7e51f0f794b3e895c7f52d.zip |
accounts/abi: improve type handling, add event support (#14743)
Diffstat (limited to 'accounts/abi/event.go')
-rw-r--r-- | accounts/abi/event.go | 91 |
1 files changed, 91 insertions, 0 deletions
diff --git a/accounts/abi/event.go b/accounts/abi/event.go index 51ab84241..44ed7b8df 100644 --- a/accounts/abi/event.go +++ b/accounts/abi/event.go @@ -18,6 +18,7 @@ package abi import ( "fmt" + "reflect" "strings" "github.com/ethereum/go-ethereum/common" @@ -44,3 +45,93 @@ func (e Event) Id() common.Hash { } return common.BytesToHash(crypto.Keccak256([]byte(fmt.Sprintf("%v(%v)", e.Name, strings.Join(types, ","))))) } + +// unpacks an event return tuple into a struct of corresponding go types +// +// Unpacking can be done into a struct or a slice/array. +func (e Event) 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() + ) + + if value.Kind() != reflect.Struct { + return fmt.Errorf("abi: cannot unmarshal tuple in to %v", typ) + } + + j := 0 + for i := 0; i < len(e.Inputs); i++ { + input := e.Inputs[i] + if input.Indexed { + // can't read, continue + continue + } else if input.Type.T == ArrayTy { + // need to move this up because they read sequentially + j += input.Type.Size + } + marshalledValue, err := toGoType((i+j)*32, input.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(e.Inputs[i].Name[:1])+e.Inputs[i].Name[1:] { + if err := set(value.Field(j), reflectValue, e.Inputs[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(e.Inputs), 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, e.Inputs[i]); err != nil { + return err + } + default: + return fmt.Errorf("abi: cannot unmarshal tuple in to %v", typ) + } + } + return nil +} + +func (e Event) isTupleReturn() bool { return len(e.Inputs) > 1 } + +func (e Event) 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) + } + + if e.Inputs[0].Indexed { + return fmt.Errorf("abi: attempting to unpack indexed variable into element.") + } + + value := valueOf.Elem() + + marshalledValue, err := toGoType(0, e.Inputs[0].Type, output) + if err != nil { + return err + } + if err := set(value, reflect.ValueOf(marshalledValue), e.Inputs[0]); err != nil { + return err + } + return nil +} |