2222 pipe ,
2323)
2424
25+ DYNAMIC_TYPES = ['bytes' , 'string' ]
2526
26- def filter_by_argument_count (num_arguments , contract_abi ):
27- return [
28- abi
29- for abi
30- in contract_abi
31- if len (abi ['inputs' ]) == num_arguments
32- ]
27+ INT_SIZES = range (8 , 257 , 8 )
28+ BYTES_SIZES = range (1 , 33 )
29+ UINT_TYPES = ['uint{0}' .format (i ) for i in INT_SIZES ]
30+ INT_TYPES = ['int{0}' .format (i ) for i in INT_SIZES ]
31+ BYTES_TYPES = ['bytes{0}' .format (i ) for i in BYTES_SIZES ] + ['bytes32.byte' ]
32+
33+ STATIC_TYPES = list (itertools .chain (
34+ ['address' , 'bool' ],
35+ UINT_TYPES ,
36+ INT_TYPES ,
37+ BYTES_TYPES ,
38+ ))
39+
40+ BASE_TYPE_REGEX = '|' .join ((
41+ _type + '(?![a-z0-9])'
42+ for _type
43+ in itertools .chain (STATIC_TYPES , DYNAMIC_TYPES )
44+ ))
45+
46+ SUB_TYPE_REGEX = (
47+ r'\['
48+ '[0-9]*'
49+ r'\]'
50+ )
51+
52+ TYPE_REGEX = (
53+ '^'
54+ '(?:{base_type})'
55+ '(?:(?:{sub_type})*)?'
56+ '$'
57+ ).format (
58+ base_type = BASE_TYPE_REGEX ,
59+ sub_type = SUB_TYPE_REGEX ,
60+ )
61+
62+ NAME_REGEX = (
63+ '[a-zA-Z_]'
64+ '[a-zA-Z0-9_]*'
65+ )
66+
67+ ENUM_REGEX = (
68+ '^'
69+ '{lib_name}'
70+ r'\.'
71+ '{enum_name}'
72+ '$'
73+ ).format (lib_name = NAME_REGEX , enum_name = NAME_REGEX )
74+
75+ END_BRACKETS_OF_ARRAY_TYPE_REGEX = r"\[[^]]*\]$"
76+
77+ NAME_REGEX = (
78+ '[a-zA-Z_]'
79+ '[a-zA-Z0-9_]*'
80+ )
3381
82+ ARRAY_REGEX = (
83+ "^"
84+ "[a-zA-Z0-9_]+"
85+ "({sub_type})+"
86+ "$"
87+ ).format (sub_type = SUB_TYPE_REGEX )
3488
3589def filter_by_argument_name (argument_names , contract_abi ):
3690 return [
@@ -95,56 +149,6 @@ def process_type(type_str):
95149 def collapse_type (base , sub , arrlist ):
96150 return base + str (sub ) + '' .join (map (repr , arrlist ))
97151
98- DYNAMIC_TYPES = ['bytes' , 'string' ]
99-
100- INT_SIZES = range (8 , 257 , 8 )
101- BYTES_SIZES = range (1 , 33 )
102- UINT_TYPES = ['uint{0}' .format (i ) for i in INT_SIZES ]
103- INT_TYPES = ['int{0}' .format (i ) for i in INT_SIZES ]
104- BYTES_TYPES = ['bytes{0}' .format (i ) for i in BYTES_SIZES ] + ['bytes32.byte' ]
105-
106- STATIC_TYPES = list (itertools .chain (
107- ['address' , 'bool' ],
108- UINT_TYPES ,
109- INT_TYPES ,
110- BYTES_TYPES ,
111- ))
112-
113- BASE_TYPE_REGEX = '|' .join ((
114- _type + '(?![a-z0-9])'
115- for _type
116- in itertools .chain (STATIC_TYPES , DYNAMIC_TYPES )
117- ))
118-
119- SUB_TYPE_REGEX = (
120- r'\['
121- '[0-9]*'
122- r'\]'
123- )
124-
125- TYPE_REGEX = (
126- '^'
127- '(?:{base_type})'
128- '(?:(?:{sub_type})*)?'
129- '$'
130- ).format (
131- base_type = BASE_TYPE_REGEX ,
132- sub_type = SUB_TYPE_REGEX ,
133- )
134-
135- NAME_REGEX = (
136- '[a-zA-Z_]'
137- '[a-zA-Z0-9_]*'
138- )
139-
140- ENUM_REGEX = (
141- '^'
142- '{lib_name}'
143- r'\.'
144- '{enum_name}'
145- '$'
146- ).format (lib_name = NAME_REGEX , enum_name = NAME_REGEX )
147-
148152
149153def filter_by_type (_type , contract_abi ):
150154 return [abi for abi in contract_abi if abi ['type' ] == _type ]
@@ -162,10 +166,6 @@ def filter_by_name(name, contract_abi):
162166 ]
163167
164168
165- def is_recognized_type (abi_type ):
166- return bool (re .match (TYPE_REGEX , abi_type ))
167-
168-
169169def get_abi_input_types (abi ):
170170 if 'inputs' not in abi and abi ['type' ] == 'fallback' :
171171 return []
@@ -211,6 +211,69 @@ def get_constructor_abi(contract_abi):
211211 raise ValueError ("Found multiple constructors." )
212212
213213
214+ def is_recognized_type (abi_type ):
215+ return bool (re .match (TYPE_REGEX , abi_type ))
216+
217+
218+ def is_bool_type (abi_type ):
219+ return abi_type == 'bool'
220+
221+
222+ def is_uint_type (abi_type ):
223+ return abi_type in UINT_TYPES
224+
225+
226+ def is_int_type (abi_type ):
227+ return abi_type in INT_TYPES
228+
229+
230+ def is_address_type (abi_type ):
231+ return abi_type == 'address'
232+
233+
234+ def is_bytes_type (abi_type ):
235+ return abi_type in BYTES_TYPES + ['bytes' ]
236+
237+
238+ def is_string_type (abi_type ):
239+ return abi_type == 'string'
240+
241+
242+ @curry
243+ def is_length (target_length , value ):
244+ return len (value ) == target_length
245+
246+
247+ def size_of_type (abi_type ):
248+ """
249+ Returns size in bits of abi_type
250+ """
251+ if 'string' in abi_type :
252+ return None
253+ if 'byte' in abi_type :
254+ return None
255+ if '[' in abi_type :
256+ return None
257+ if abi_type == 'bool' :
258+ return 8
259+ if abi_type == 'address' :
260+ return 160
261+ return int (re .sub (r"\D" , "" , abi_type ))
262+
263+
264+ def is_array_type (abi_type ):
265+ return bool (re .match (ARRAY_REGEX , abi_type ))
266+
267+
268+ def sub_type_of_array_type (abi_type ):
269+ if not is_array_type (abi_type ):
270+ raise ValueError (
271+ "Cannot parse subtype of nonarray abi-type: {0}" .format (abi_type )
272+ )
273+
274+ return re .sub (END_BRACKETS_OF_ARRAY_TYPE_REGEX , '' , abi_type , 1 )
275+
276+
214277def is_probably_enum (abi_type ):
215278 return bool (re .match (ENUM_REGEX , abi_type ))
216279
@@ -353,8 +416,8 @@ def abi_sub_tree(data_type, data_value):
353416
354417@curry
355418def map_abi_data (normalizers , types , data ):
356- '''
357- This function will apply normalizers to your data, in the
419+ """
420+ This function will apply normalizers to your data, in the
358421 context of the relevant types. Each normalizer is in the format:
359422
360423 def normalizer(datatype, data):
@@ -374,7 +437,7 @@ def normalizer(datatype, data):
374437 1. Decorating the data tree with types
375438 2. Recursively mapping each of the normalizers to the data
376439 3. Stripping the types back out of the tree
377- '''
440+ """
378441 pipeline = itertools .chain (
379442 [abi_data_tree (types )],
380443 map (data_tree_map , normalizers ),
@@ -385,7 +448,7 @@ def normalizer(datatype, data):
385448
386449
387450@curry
388- def abi_data_tree (types , data ):
451+ def abi_data_tree (types , data = None ):
389452 """Decorate the data tree with pairs of (type, data). The pair tuple is actually an
390453 ABITypedData, but can be accessed as a tuple.
391454
0 commit comments