def construct_event_filter_params(event_abi, contract_address=None, argument_filters=None, topics=None, fromBlock=None, toBlock=None, address=None): filter_params = {} topic_set = construct_event_topic_set(event_abi, argument_filters) if topics is not None: if len(topic_set) > 1: raise TypeError( "Merging the topics argument with topics generated " "from argument_filters is not supported.") topic_set = topics if len(topic_set) == 1 and is_list_like(topic_set[0]): filter_params['topics'] = topic_set[0] else: filter_params['topics'] = topic_set if address and contract_address: if is_list_like(address): filter_params['address'] = address + [contract_address] elif is_string(address): filter_params['address'] = [address, contract_address] else: raise ValueError( "Unsupported type for `address` parameter: {0}".format( type(address))) elif address: filter_params['address'] = address elif contract_address: filter_params['address'] = contract_address if 'address' not in filter_params: pass elif is_list_like(filter_params['address']): for addr in filter_params['address']: validate_address(addr) else: validate_address(filter_params['address']) if fromBlock is not None: filter_params['fromBlock'] = fromBlock if toBlock is not None: filter_params['toBlock'] = toBlock data_filters_set = construct_event_data_set(event_abi, argument_filters) return data_filters_set, filter_params
def test_eth_newFilter(self, web3): filter = web3.eth.filter({}) changes = web3.eth.getFilterChanges(filter.filter_id) assert is_list_like(changes) assert not changes logs = web3.eth.getFilterLogs(filter.filter_id) assert is_list_like(logs) assert not logs result = web3.eth.uninstallFilter(filter.filter_id) assert result is True
def construct_event_data_set(event_abi, arguments=None): if arguments is None: arguments = {} if isinstance(arguments, (list, tuple)): if len(arguments) != len(event_abi['inputs']): raise ValueError( "When passing an argument list, the number of arguments must " "match the event constructor.") arguments = { arg['name']: [arg_value] for arg, arg_value in zip(event_abi['inputs'], arguments) } normalized_args = { key: value if is_list_like(value) else [value] for key, value in arguments.items() } non_indexed_args = exclude_indexed_event_inputs(event_abi) zipped_abi_and_args = [(arg, normalized_args.get(arg['name'], [None])) for arg in non_indexed_args] encoded_args = [[ None if option is None else encode_hex( encode_single(arg['type'], option)) for option in arg_options ] for arg, arg_options in zipped_abi_and_args] data = [ list(permutation) if any(value is not None for value in permutation) else [] for permutation in itertools.product(*encoded_args) ] return data
def construct_event_topic_set(event_abi, arguments=None): if arguments is None: arguments = {} if isinstance(arguments, (list, tuple)): if len(arguments) != len(event_abi['inputs']): raise ValueError( "When passing an argument list, the number of arguments must " "match the event constructor.") arguments = { arg['name']: [arg_value] for arg, arg_value in zip(event_abi['inputs'], arguments) } normalized_args = { key: value if is_list_like(value) else [value] for key, value in arguments.items() } event_topic = encode_hex(event_abi_to_log_topic(event_abi)) indexed_args = get_indexed_event_inputs(event_abi) zipped_abi_and_args = [(arg, normalized_args.get(arg['name'], [None])) for arg in indexed_args] encoded_args = [[ None if option is None else encode_hex( encode_single(arg['type'], option)) for option in arg_options ] for arg, arg_options in zipped_abi_and_args] topics = list(normalize_topic_list([event_topic] + encoded_args)) return topics
def is_encodable(_type, value): try: base, sub, arrlist = _type except ValueError: base, sub, arrlist = process_type(_type) if arrlist: if not is_list_like(value): return False if arrlist[-1] and len(value) != arrlist[-1][0]: return False sub_type = (base, sub, arrlist[:-1]) return all(is_encodable(sub_type, sub_value) for sub_value in value) elif base == 'address' and is_ens_name(value): # ENS names can be used anywhere an address is needed # Web3.py will resolve the name to an address before encoding it return True elif base == 'bytes' and isinstance(value, str): # Hex-encoded bytes values can be used anywhere a bytes value is needed if is_hex(value) and len(value) % 2 == 0: # Require hex-encoding of full bytes (even length) bytes_val = to_bytes(hexstr=value) return eth_abi_is_encodable(_type, bytes_val) else: return False elif base == 'string' and isinstance(value, bytes): # bytes that were encoded with utf-8 can be used anywhere a string is needed try: string_val = to_text(value) except UnicodeDecodeError: return False else: return eth_abi_is_encodable(_type, string_val) else: return eth_abi_is_encodable(_type, value)
def generate_cache_key(value): """ Generates a cache key for the *args and **kwargs """ if is_bytes(value): return hashlib.md5(value).hexdigest() elif is_text(value): return generate_cache_key(to_bytes(text=value)) elif is_boolean(value) or is_null(value) or is_number(value): return generate_cache_key(repr(value)) elif is_dict(value): return generate_cache_key(( (key, value[key]) for key in sorted(value.keys()) )) elif is_list_like(value) or isinstance(value, Generator): return generate_cache_key("".join(( generate_cache_key(item) for item in value ))) else: raise TypeError("Cannot generate cache key for value {0} of type {1}".format( value, type(value), ))
def validate_value(self, value): if not is_list_like(value): raise EncodingTypeError( "Cannot encode value of type {0} using array encoder. Must be " "a list-like object such as an array or tuple".format( type(value), )) for item in value: self.item_encoder.validate_value(item)
def validate_value(self, value): if not is_list_like(value): raise EncodingTypeError( "Cannot encode value of type {0} using tuple encoder. Must be " "a list-like object such as an array or tuple".format( type(value), )) if len(value) != len(self.encoders): raise ValueOutOfBounds( "Expected value with length {0}. Provided value has {1} " "elements".format(len(self.encoders), len(value))) for item, encoder in zip(value, self.encoders): encoder.validate_value(item)
def validate_abi_value(abi_type, value): """ Helper function for validating a value against the expected abi_type Note: abi_type 'bytes' must either be python3 'bytes' object or '' """ if is_array_type(abi_type) and is_list_like(value): # validate length specified_length = length_of_array_type(abi_type) if specified_length is not None: if specified_length < 1: raise TypeError( "Invalid abi-type: {abi_type}. Length of fixed sized arrays" "must be greater than 0.".format(abi_type=abi_type)) if specified_length != len(value): raise TypeError( "The following array length does not the length specified" "by the abi-type, {abi_type}: {value}".format( abi_type=abi_type, value=value)) # validate sub_types sub_type = sub_type_of_array_type(abi_type) for v in value: validate_abi_value(sub_type, v) return elif is_bool_type(abi_type) and is_boolean(value): return elif is_uint_type(abi_type) and is_integer(value) and value >= 0: return elif is_int_type(abi_type) and is_integer(value): return elif is_address_type(abi_type): validate_address(value) return elif is_bytes_type(abi_type): if is_bytes(value): return elif is_string(value): if is_0x_prefixed(value): return else: raise TypeError( "ABI values of abi-type 'bytes' must be either" "a python3 'bytes' object or an '0x' prefixed string.") elif is_string_type(abi_type) and is_string(value): return raise TypeError( "The following abi value is not a '{abi_type}': {value}".format( abi_type=abi_type, value=value))
def test_eth_newPendingTransactionFilter(self, web3): filter = web3.eth.filter('pending') assert is_string(filter.filter_id) changes = web3.eth.getFilterChanges(filter.filter_id) assert is_list_like(changes) assert not changes # TODO: figure out why this fails in go-ethereum # logs = web3.eth.getFilterLogs(filter.filter_id) # assert is_list_like(logs) # assert not logs result = web3.eth.uninstallFilter(filter.filter_id) assert result is True
def _friendly_json_encode(self, obj): try: encoded = json.dumps(obj) return encoded except TypeError as full_exception: if hasattr(obj, 'items'): item_errors = '; '.join(self._json_mapping_errors(obj)) raise TypeError( "dict had unencodable value at keys: {{{}}}".format( item_errors)) elif is_list_like(obj): element_errors = '; '.join(self._json_list_errors(obj)) raise TypeError( "list had unencodable value at index: [{}]".format( element_errors)) else: raise full_exception
def validate_abi(abi): """ Helper function for validating an ABI """ if not is_list_like(abi): raise ValueError("'abi' is not a list") if not all(is_dict(e) for e in abi): raise ValueError("'abi' is not a list of dictionaries") functions = filter_by_type('function', abi) selectors = groupby(compose(encode_hex, function_abi_to_4byte_selector), functions) duplicates = valfilter(lambda funcs: len(funcs) > 1, selectors) if duplicates: raise ValueError('Abi contains functions with colliding selectors. ' 'Functions {0}'.format( _prepare_selector_collision_msg(duplicates)))
def providers(self, value): if not is_list_like(value): providers = [value] else: providers = value self._providers = providers
def is_array_of_dicts(value): if not is_list_like(value): return False return all((is_dict(item) for item in value))
def is_array_of_strings(value): if not is_list_like(value): return False return all((is_string(item) for item in value))
def test_eth_accounts(self, web3): accounts = web3.eth.accounts assert is_list_like(accounts) assert len(accounts) != 0 assert all((is_checksum_address(account) for account in accounts)) assert web3.eth.coinbase in accounts
def test_personal_listAccounts(self, web3): accounts = web3.personal.listAccounts assert is_list_like(accounts) assert len(accounts) > 0 assert all((is_checksum_address(item) for item in accounts))
def pop_singlets(seq): yield from (i[0] if is_list_like(i) and len(i) == 1 else i for i in seq)