aboutsummaryrefslogtreecommitdiffstats
path: root/accounts/abi/event.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/event.go
parente9295163aa25479e817efee4aac23eaeb7554bba (diff)
downloaddexon-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.go91
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
+}