Live video on the AT Protocol
79
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v0.8.7 132 lines 2.9 kB view raw
1package schema 2 3import ( 4 "encoding/json" 5 "fmt" 6 "reflect" 7 8 "github.com/ethereum/go-ethereum/signer/core/apitypes" 9) 10 11type Schema interface { 12 EIP712() (*EIP712SchemaStruct, error) 13} 14 15type SchemaStruct struct { 16 name string 17 version string 18 schema any 19} 20 21func MakeSchema(name, version string, schema any) (Schema, error) { 22 return &SchemaStruct{ 23 name: name, 24 version: version, 25 schema: schema, 26 }, nil 27} 28 29type EIP712SchemaStruct struct { 30 Types apitypes.Types `json:"types"` 31 Domain *apitypes.TypedDataDomain `json:"domain"` 32 TypeToName map[reflect.Type]string 33 NameToType map[string]reflect.Type 34} 35 36func (schema *SchemaStruct) EIP712() (*EIP712SchemaStruct, error) { 37 var eip712Types = apitypes.Types{ 38 "EIP712Domain": { 39 { 40 Name: "name", 41 Type: "string", 42 }, 43 { 44 Name: "version", 45 Type: "string", 46 }, 47 }, 48 } 49 50 stype := reflect.TypeOf(schema.schema) 51 if stype.Kind() != reflect.Struct { 52 return nil, fmt.Errorf("schema parameter of MakeEIP712Signer is not a struct") 53 } 54 fields := reflect.VisibleFields(stype) 55 typeToName := map[reflect.Type]string{} 56 nameToType := map[string]reflect.Type{} 57 for _, field := range fields { 58 name := field.Name 59 eip712TypeName := fmt.Sprintf("%sData", name) 60 if field.Type.Kind() != reflect.Struct { 61 return nil, fmt.Errorf("field '%s' in provided schema is not a struct", name) 62 } 63 typeToName[field.Type] = name 64 nameToType[name] = field.Type 65 parentType := []apitypes.Type{ 66 { 67 Name: "signer", 68 Type: "address", 69 }, 70 { 71 Name: "time", 72 Type: "int64", 73 }, 74 { 75 Name: "data", 76 Type: eip712TypeName, 77 }, 78 } 79 typeSlice := []apitypes.Type{} 80 81 subfields := reflect.VisibleFields(field.Type) 82 for _, subfield := range subfields { 83 eipType, err := goToEIP712(subfield) 84 if err != nil { 85 return nil, fmt.Errorf("error handling type %s: %w", name, err) 86 } 87 typeSlice = append(typeSlice, eipType) 88 } 89 eip712Types[name] = parentType 90 eip712Types[eip712TypeName] = typeSlice 91 } 92 return &EIP712SchemaStruct{ 93 Types: eip712Types, 94 Domain: &apitypes.TypedDataDomain{ 95 Version: schema.version, 96 Name: schema.name, 97 }, 98 TypeToName: typeToName, 99 NameToType: nameToType, 100 }, nil 101} 102 103func (eip *EIP712SchemaStruct) JSON() ([]byte, error) { 104 out := map[string]any{ 105 "domain": eip.Domain, 106 "types": eip.Types, 107 } 108 bs, err := json.MarshalIndent(out, "", " ") 109 if err != nil { 110 return []byte{}, err 111 } 112 return bs, nil 113} 114 115// turns a go type into an eip712 type 116func goToEIP712(field reflect.StructField) (apitypes.Type, error) { 117 var typ string 118 kind := field.Type.Kind() 119 if kind == reflect.String { 120 typ = "string" 121 } else if kind == reflect.Int64 { 122 typ = "int64" 123 } 124 jsonTag := field.Tag.Get("json") 125 if jsonTag == "" { 126 return apitypes.Type{}, fmt.Errorf("could not find field name for %s", field.Name) 127 } 128 return apitypes.Type{ 129 Name: jsonTag, 130 Type: typ, 131 }, nil 132}