def map_abi_data(normalizers, types, data): ''' This function will apply normalizers to your data, in the context of the relevant types. Each normalizer is in the format: def normalizer(datatype, data): # Conditionally modify data return (datatype, data) Where datatype is a valid ABI type string, like "uint". In case of an array, like "bool[2]", normalizer will receive `data` as an iterable of typed data, like `[("bool", True), ("bool", False)]`. Internals --- This is accomplished by: 1. Decorating the data tree with types 2. Recursively mapping each of the normalizers to the data 3. Stripping the types back out of the tree ''' pipeline = itertools.chain( [abi_data_tree(types)], map(data_tree_map, normalizers), [partial(recursive_map, strip_abi_type)], ) return pipe(data, *pipeline)
def find_matching_fn_abi(abi, fn_identifier=None, args=None, kwargs=None): args = args or tuple() kwargs = kwargs or dict() filters = [] num_arguments = len(args) + len(kwargs) if fn_identifier is FallbackFn: return get_fallback_func_abi(abi) if not is_text(fn_identifier): raise TypeError("Unsupported function identifier") name_filter = functools.partial(filter_by_name, fn_identifier) arg_count_filter = functools.partial(filter_by_argument_count, num_arguments) encoding_filter = functools.partial(filter_by_encodability, args, kwargs) filters.extend([ name_filter, arg_count_filter, encoding_filter, ]) function_candidates = pipe(abi, *filters) if len(function_candidates) == 1: return function_candidates[0] else: matching_identifiers = name_filter(abi) matching_function_signatures = [ abi_to_signature(func) for func in matching_identifiers ] arg_count_matches = len(arg_count_filter(matching_identifiers)) encoding_matches = len(encoding_filter(matching_identifiers)) if arg_count_matches == 0: diagnosis = "\nFunction invocation failed due to improper number of arguments." elif encoding_matches == 0: diagnosis = "\nFunction invocation failed due to no matching argument types." elif encoding_matches > 1: diagnosis = ( "\nAmbiguous argument encoding. " "Provided arguments can be encoded to multiple functions matching this call." ) message = ( "\nCould not identify the intended function with name `{name}`, " "positional argument(s) of type `{arg_types}` and " "keyword argument(s) of type `{kwarg_types}`." "\nFound {num_candidates} function(s) with the name `{name}`: {candidates}" "{diagnosis}").format( name=fn_identifier, arg_types=tuple(map(type, args)), kwarg_types=valmap(type, kwargs), num_candidates=len(matching_identifiers), candidates=matching_function_signatures, diagnosis=diagnosis, ) raise ValidationError(message)
def middleware(method, params): # TODO send call to eth-tester without gas, and remove guess_gas entirely if method == 'eth_call': filled_transaction = pipe( params[0], fill_default_from, fill_default_gas, ) return make_request(method, [filled_transaction] + params[1:]) elif method in ( 'eth_estimateGas', 'eth_sendTransaction', ): filled_transaction = pipe( params[0], fill_default_from, ) return make_request(method, [filled_transaction] + params[1:]) else: return make_request(method, params)
def find_matching_event_abi(abi, event_name=None, argument_names=None): filters = [ functools.partial(filter_by_type, 'event'), ] if event_name is not None: filters.append(functools.partial(filter_by_name, event_name)) if argument_names is not None: filters.append( functools.partial(filter_by_argument_name, argument_names)) event_abi_candidates = pipe(abi, *filters) if len(event_abi_candidates) == 1: return event_abi_candidates[0] elif not event_abi_candidates: raise ValueError("No matching events found") else: raise ValueError("Multiple events found")