Skip to content

Commit bdd1880

Browse files
committed
Finalizing initial creation of project.
- Bugfixes - Renamed struct_to_dict to struct_to_message (more accurate to purpose) - README updated with extra useful info
1 parent 5f67156 commit bdd1880

File tree

4 files changed

+55
-19
lines changed

4 files changed

+55
-19
lines changed

README.md

Lines changed: 42 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ struct Message {
2525

2626
Python representation:
2727
```python
28-
from eip712_structs import EIP712Struct, Address, String, make_domain, struct_to_dict
28+
from eip712_structs import EIP712Struct, Address, String, make_domain, struct_to_message
2929

3030
class Message(EIP712Struct):
3131
to = Address()
@@ -37,7 +37,16 @@ msg = Message(to='0xdead...beef', contents='hello world')
3737
msg.encode_data() # The struct's data in encoded form
3838

3939
domain = make_domain(name='example')
40-
msg_body, msg_hash = struct_to_dict(msg, domain)
40+
msg_body, signable_bytes = struct_to_message(msg, domain)
41+
42+
# msg_body is a standardized dict with keys primaryType, types, domain, and message
43+
# suitable for converting to JSON for making requests
44+
45+
# `signable bytes` is a deterministic bytes representation of the struct
46+
# Suitable for hashing or signing
47+
# bytes 0-1: b'\x19\x01'
48+
# bytes 2-33: domain separator (hash of domain type and data)
49+
# bytes 34-65: hash of struct type and data
4150
```
4251

4352
#### Dynamic construction
@@ -52,22 +61,29 @@ Message.to = Address()
5261
setattr(Message, 'from', Address())
5362
```
5463

55-
#### Creating Messages and Hashing
64+
#### The domain separator
5665
Messages also require a domain struct. A helper method exists for this purpose.
66+
All values to the `make_domain()`
67+
function are optional - but at least one must be defined. If omitted, the resulting
68+
domain struct's definition leaves out the parameter entirely.
69+
70+
The full signature: <br/>
71+
`make_domain(name: string, version: string, chainId: uint256, verifyingContract: address, salt: bytes32)`
5772

5873
```python
59-
from eip712_structs import EIP712Struct, String, make_domain, struct_to_dict
74+
from eip712_structs import EIP712Struct, String, make_domain, struct_to_message
6075

61-
domain = make_domain(name='my_domain') # Also accepts kwargs: version, chainId, verifyingContract, salt
76+
domain = make_domain(name='my_domain')
6277

6378
class Foo(EIP712Struct):
6479
bar = String()
6580

6681
foo = Foo(bar='baz')
6782

68-
message_dict, message_hash = struct_to_dict(foo, domain)
83+
message_dict, message_hash = struct_to_message(foo, domain)
6984
```
7085

86+
7187
## Member Types
7288

7389
### Basic types
@@ -111,6 +127,23 @@ Dog.encode_type() # Dog(string name,string breed)
111127
Person.encode_type() # Person(string name,Dog dog)Dog(string name,string breed)
112128
```
113129

130+
Instantiating the structs with nested values may be done like:
131+
132+
```python
133+
# Method one: set it to a struct
134+
dog = Dog(name='Mochi', breed='Corgi')
135+
person = Person(name='Ed', dog=dog)
136+
137+
# Method two: set it to a dict - the underlying struct is built for you
138+
person = Person(
139+
name='Ed',
140+
dog={
141+
'name': 'Mochi',
142+
'breed': 'Corgi',
143+
}
144+
)
145+
```
146+
114147
### Arrays
115148
Arrays are also supported for the standard.
116149

@@ -123,8 +156,9 @@ array_member = Array(<item_type>[, <optional_length>])
123156

124157
For example:
125158
```python
126-
dynamic_array = Array(X()) # X[] dynamic_array
127-
static_array = Array(X(), 10) # X[10] static_array
159+
dynamic_array = Array(String()) # String[] dynamic_array
160+
static_array = Array(String(), 10) # String[10] static_array
161+
struct_array = Array(MyStruct, 10) # MyStruct[10] - again, don't instantiate structs like the basic types
128162
```
129163

130164
## Development

eip712_structs/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from eip712_structs.domain_separator import make_domain
2-
from eip712_structs.struct import EIP712Struct, struct_to_dict, struct_from_dict
2+
from eip712_structs.struct import EIP712Struct, struct_from_message, struct_to_message
33
from eip712_structs.types import Address, Array, Boolean, Bytes, Int, String, Uint
44

55
name = 'eip712-structs'
6-
version = '0.1.2'
6+
version = '0.1.3'

eip712_structs/struct.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ def hash_struct(self):
120120
121121
hash_struct => keccak(type_hash || encode_data)
122122
"""
123-
return keccak(b''.join([self.type_hash(), self.encode_data()]))
123+
return keccak(b''.join([self.type_hash(), self.encode_value()]))
124124

125125
@classmethod
126126
def get_members(cls) -> List[Tuple[str, EIP712Type]]:
@@ -133,7 +133,7 @@ def get_members(cls) -> List[Tuple[str, EIP712Type]]:
133133
return members
134134

135135

136-
def struct_to_dict(primary_struct: EIP712Struct, domain: EIP712Struct):
136+
def struct_to_message(primary_struct: EIP712Struct, domain: EIP712Struct):
137137
"""Convert a struct into a dictionary suitable for messaging.
138138
139139
Dictionary is of the form:
@@ -168,12 +168,12 @@ def struct_to_dict(primary_struct: EIP712Struct, domain: EIP712Struct):
168168
'message': primary_struct.data_dict(),
169169
}
170170

171-
typed_data_hash = keccak(b'\x19\x01' + domain.type_hash() + primary_struct.type_hash())
171+
typed_data_hash = b'\x19\x01' + domain.type_hash() + primary_struct.type_hash()
172172

173173
return result, typed_data_hash
174174

175175

176-
def struct_from_dict(message_dict):
176+
def struct_from_message(message_dict):
177177
"""Return the EIP712Struct object of the message and domain structs.
178178
179179
:returns: A tuple in the form of: (<primary struct>, <domain struct>)

tests/test_message_json.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from eip712_structs import EIP712Struct, String, make_domain, struct_to_dict, struct_from_dict
1+
from eip712_structs import EIP712Struct, String, make_domain, struct_to_message, struct_from_message
22

33

44
def test_flat_struct_to_message():
@@ -28,11 +28,11 @@ class Foo(EIP712Struct):
2828
}
2929
}
3030

31-
message, _ = struct_to_dict(foo, domain)
31+
message, _ = struct_to_message(foo, domain)
3232
assert message == expected_result
3333

3434
# Now test in reverse...
35-
new_struct, domain = struct_from_dict(expected_result)
35+
new_struct, domain = struct_from_message(expected_result)
3636
assert new_struct.type_name == 'Foo'
3737

3838
members_list = new_struct.get_members()
@@ -88,11 +88,11 @@ class Foo(EIP712Struct):
8888
}
8989
}
9090

91-
message, _ = struct_to_dict(foo, domain)
91+
message, _ = struct_to_message(foo, domain)
9292
assert message == expected_result
9393

9494
# And test in reverse...
95-
new_struct, new_domain = struct_from_dict(expected_result)
95+
new_struct, new_domain = struct_from_message(expected_result)
9696
assert new_struct.type_name == 'Foo'
9797

9898
members = new_struct.get_members()
@@ -103,3 +103,5 @@ class Foo(EIP712Struct):
103103
bar_val = new_struct.get_data_value('bar')
104104
assert bar_val.type_name == 'Bar'
105105
assert bar_val.get_data_value('s') == 'bar'
106+
107+
assert foo.hash_struct() == new_struct.hash_struct()

0 commit comments

Comments
 (0)