def createFilter( self, *, # PEP 3102 argument_filters=None, fromBlock=None, toBlock="latest", address=None, topics=None): """ Create filter object that tracks logs emitted by this contract event. :param filter_params: other parameters to limit the events """ if fromBlock is None: raise TypeError("Missing mandatory keyword argument to createFilter: fromBlock") if argument_filters is None: argument_filters = dict() _filters = dict(**argument_filters) event_abi = self._get_event_abi() check_for_forbidden_api_filter_arguments(event_abi, _filters) _, event_filter_params = construct_event_filter_params( self._get_event_abi(), contract_address=self.address, argument_filters=_filters, fromBlock=fromBlock, toBlock=toBlock, address=address, topics=topics, ) filter_builder = EventFilterBuilder(event_abi) filter_builder.address = event_filter_params.get('address') filter_builder.fromBlock = event_filter_params.get('fromBlock') filter_builder.toBlock = event_filter_params.get('toBlock') match_any_vals = { arg: value for arg, value in _filters.items() if not is_array_type(filter_builder.args[arg].arg_type) and is_list_like(value) } for arg, value in match_any_vals.items(): filter_builder.args[arg].match_any(*value) match_single_vals = { arg: value for arg, value in _filters.items() if not is_array_type(filter_builder.args[arg].arg_type) and not is_list_like(value) } for arg, value in match_single_vals.items(): filter_builder.args[arg].match_single(value) log_filter = filter_builder.deploy(self.web3) log_filter.log_entry_formatter = get_event_data(self._get_event_abi()) log_filter.builder = filter_builder return log_filter
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: "Web3") -> None: 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 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_filter_params(event_abi, contract_address=None, argument_filters=None, topics=None, fromBlock=None, toBlock=None, address=None): filter_params = {} if topics is None: topic_set = construct_event_topic_set(event_abi, argument_filters) else: topic_set = [topics] + construct_event_topic_set( event_abi, argument_filters) 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 providers(self, value): if not is_list_like(value): providers = [value] else: providers = value self._providers = providers self._generate_request_functions()
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(force_bytes(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 normalize_filter_params(from_block, to_block, address, topics): yield from_block yield to_block if address is None: yield address elif is_address(address): yield to_canonical_address(address) elif is_list_like(address): yield tuple(to_canonical_address(item) for item in address) else: raise TypeError( "Address is not in a recognized format: {0}".format(address)) if topics is None: yield topics elif is_flat_topic_array(topics): yield tuple(decode_hex(item) for item in topics) elif all(is_flat_topic_array(item) for item in topics): yield tuple( tuple(decode_hex(sub_item) for sub_item in item) for item in topics) else: raise TypeError( "Topics are not in a recognized format: {0}".format(address))
def bytes_repr(value): if is_bytes(value): yield value elif is_text(value): yield to_bytes(text=value) elif is_list_like(value): yield b''.join(( b'(', b','.join(bytes_repr(item) for item in value), b')', )) elif is_dict(value): yield b''.join(( b'{', b','.join(( b":".join((bytes_repr(key), bytes_repr(item))) for key, item in value.items() )), b'}', )) elif is_integer(value): yield to_bytes(value) elif is_null(value): yield 'None@{}'.format(id(value)) else: raise TypeError("Unsupported type for bytes_repr: {}".format(type(value)))
def get_netting_channel_closed_events( chain: BlockChainService, token_network_address: Address, netting_channel_identifier: ChannelID, contract_manager: ContractManager, from_block: BlockSpecification = 0, to_block: BlockSpecification = 'latest', ) -> List[Dict]: closed_event_abi = contract_manager.get_event_abi( CONTRACT_TOKEN_NETWORK, ChannelEvent.CLOSED, ) topic_set = construct_event_topic_set( event_abi=closed_event_abi, arguments={'channel_identifier': netting_channel_identifier}, ) if len(topic_set) == 1 and is_list_like(topic_set[0]): topics = topic_set[0] else: topics = topic_set return get_contract_events( chain=chain, abi=contract_manager.get_contract_abi(CONTRACT_TOKEN_NETWORK), contract_address=token_network_address, topics=topics, from_block=from_block, to_block=to_block, )
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 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 _decode_auth(encoded_packet: bytes) -> Tuple[Union[AuthHeader, Nonce], int]: try: decoded_auth, _, message_start_index = rlp.codec.consume_item(encoded_packet, TAG_SIZE) except DecodingError as error: raise ValidationError("Packet authentication section is not proper RLP") from error if is_bytes(decoded_auth): validate_nonce(decoded_auth) return Nonce(decoded_auth), message_start_index elif is_list_like(decoded_auth): validate_length(decoded_auth, 5, "auth header") for index, element in enumerate(decoded_auth): if not is_bytes(element): raise ValidationError(f"Element {index} in auth header is not bytes: {element}") auth_header = AuthHeader( auth_tag=decoded_auth[0], id_nonce=decoded_auth[1], auth_scheme_name=decoded_auth[2], ephemeral_public_key=decoded_auth[3], encrypted_auth_response=decoded_auth[4], ) validate_auth_header(auth_header) return auth_header, message_start_index else: raise Exception("unreachable: RLP can only encode bytes and lists")
def is_encodable(_type, value): if not isinstance(_type, str): raise ValueError("is_encodable only accepts type strings") 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(collapse_type(*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 stringify(value): if is_bytes(value): yield value elif is_text(value): yield force_bytes(value) elif is_list_like(value): yield b''.join(( b'(', b','.join((stringify(item) for item in value)), b')', )) elif is_dict(value): yield b''.join(( b'{', b','.join((b":".join((stringify(key), stringify(item))) for key, item in value.items())), b'}', )) elif is_integer(value): yield force_bytes(str(value)) elif is_null(value): yield 'None@{0}'.format(id(value)) else: raise TypeError("Unsupported type for stringification: {0}".format( type(value)))
def get_netting_channel_deposit_events( chain: BlockChainService, token_network_address: Address, netting_channel_identifier: ChannelID, contract_manager: ContractManager, from_block: BlockSpecification = GENESIS_BLOCK_NUMBER, to_block: BlockSpecification = 'latest', ) -> List[Dict]: deposit_event_abi = contract_manager.get_event_abi( CONTRACT_TOKEN_NETWORK, ChannelEvent.DEPOSIT, ) topic_set = construct_event_topic_set( event_abi=deposit_event_abi, arguments={'channel_identifier': netting_channel_identifier}, ) if len(topic_set) == 1 and is_list_like(topic_set[0]): topics = topic_set[0] else: topics = topic_set return get_contract_events( chain, contract_manager.get_contract_abi(CONTRACT_TOKEN_NETWORK), token_network_address, topics, from_block, to_block, )
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 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 get_netting_channel_settled_events( chain: BlockChainService, token_network_address: Address, netting_channel_identifier: ChannelID, from_block: BlockSpecification = 0, to_block: BlockSpecification = 'latest', ) -> List[Dict]: settled_event_abi = CONTRACT_MANAGER.get_event_abi( CONTRACT_TOKEN_NETWORK, ChannelEvent.SETTLED, ) topic_set = construct_event_topic_set( event_abi=settled_event_abi, arguments={'channel_identifier': netting_channel_identifier}, ) if len(topic_set) == 1 and is_list_like(topic_set[0]): topics = topic_set[0] else: topics = topic_set return get_contract_events( chain, CONTRACT_MANAGER.get_contract_abi(CONTRACT_TOKEN_NETWORK), token_network_address, topics, from_block, to_block, )
def test_auth_header_preparation_without_enr(tag, auth_tag, id_nonce, initiator_key, auth_response_key, ephemeral_public_key): message = PingMessage( request_id=5, enr_seq=1, ) id_nonce_signature = b"\x00" * 32 packet = AuthHeaderPacket.prepare( tag=tag, auth_tag=auth_tag, id_nonce=id_nonce, message=message, initiator_key=initiator_key, id_nonce_signature=id_nonce_signature, auth_response_key=auth_response_key, enr=None, ephemeral_public_key=ephemeral_public_key ) decrypted_auth_response = aesgcm_decrypt( key=auth_response_key, nonce=ZERO_NONCE, cipher_text=packet.auth_header.encrypted_auth_response, authenticated_data=b"", ) decoded_auth_response = rlp.decode(decrypted_auth_response) assert is_list_like(decoded_auth_response) and len(decoded_auth_response) == 3 assert decoded_auth_response[0] == int_to_big_endian(AUTH_RESPONSE_VERSION) assert decoded_auth_response[1] == id_nonce_signature assert decoded_auth_response[2] == []
def get_netting_channel_deposit_events( proxy_manager: ProxyManager, token_network_address: TokenNetworkAddress, netting_channel_identifier: ChannelID, contract_manager: ContractManager, from_block: BlockSpecification = GENESIS_BLOCK_NUMBER, to_block: BlockSpecification = "latest", ) -> List[Dict]: deposit_event_abi = contract_manager.get_event_abi(CONTRACT_TOKEN_NETWORK, ChannelEvent.DEPOSIT) topic_set = construct_event_topic_set( event_abi=deposit_event_abi, arguments={"channel_identifier": netting_channel_identifier}) if len(topic_set) == 1 and is_list_like(topic_set[0]): topics = topic_set[0] else: topics = topic_set return get_contract_events( proxy_manager, contract_manager.get_contract_abi(CONTRACT_TOKEN_NETWORK), Address(token_network_address), topics, from_block, to_block, )
def decrypt_auth_response( self, auth_response_key: AES128Key) -> Tuple[bytes, Optional[ENR]]: """Extract id nonce signature and optional ENR from auth header packet.""" plain_text = aesgcm_decrypt( key=auth_response_key, nonce=ZERO_NONCE, cipher_text=self.auth_header.encrypted_auth_response, authenticated_data=self.tag, ) try: decoded_rlp = rlp.decode(plain_text) except DecodingError as error: raise ValidationError( f"Auth response does not contain valid RLP: {encode_hex(plain_text)}" ) if not is_list_like(decoded_rlp): raise ValidationError( f"Auth response contains bytes instead of list: {encode_hex(decoded_rlp)}" ) if len(decoded_rlp) != 2: raise ValidationError( f"Auth response is a list of {len(decoded_rlp)} instead of two elements" ) id_nonce_signature, serialized_enr = decoded_rlp if not is_bytes(id_nonce_signature): raise ValidationError( f"Id nonce signature is a list instead of bytes: {id_nonce_signature}" ) if not is_list_like(serialized_enr): raise ValidationError( f"ENR is bytes instead of list: {encode_hex(serialized_enr)}") if len(serialized_enr) == 0: enr = None else: try: enr = ENR.deserialize(serialized_enr) except DeserializationError as error: raise ValidationError( "ENR in auth response is not properly encoded") from error return id_nonce_signature, enr
def wrapper(*args, **kwargs): value = fn(*args, **kwargs) if is_string(value): return os.path.relpath(value) elif is_list_like(value): return type(value)([os.path.relpath(path) for path in value]) else: raise TypeError("Unsupported type: {0}".format(type(value)))
def test_personal_list_wallets(self, web3: "Web3") -> None: wallets = web3.geth.personal.list_wallets() assert is_list_like(wallets) assert len(wallets) > 0 assert is_checksum_address(wallets[0]['accounts'][0]['address']) assert is_string(wallets[0]['accounts'][0]['url']) assert is_string(wallets[0]['status']) assert is_string(wallets[0]['url'])
def topic_to_name(param): if is_list_like(param): return [topic_to_name(t) for t in param] if isinstance(param, bytes): topic_int = big_endian_to_int(param) return chr(topic_int + 65) else: return param
def encode_elements(cls, 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), )) encoded_elements = b''.join((cls.item_encoder(item) for item in value)) return encoded_elements
def test_auth_header_preparation(tag, auth_tag, id_nonce, initiator_key, auth_response_key, ephemeral_public_key): enr = ENR( sequence_number=1, signature=b"", kv_pairs={ b"id": b"v4", b"secp256k1": b"\x02" * 33, } ) message = PingMessage( request_id=5, enr_seq=enr.sequence_number, ) id_nonce_signature = b"\x00" * 32 packet = AuthHeaderPacket.prepare( tag=tag, auth_tag=auth_tag, id_nonce=id_nonce, message=message, initiator_key=initiator_key, id_nonce_signature=id_nonce_signature, auth_response_key=auth_response_key, enr=enr, ephemeral_public_key=ephemeral_public_key ) assert packet.tag == tag assert packet.auth_header.auth_tag == auth_tag assert packet.auth_header.id_nonce == id_nonce assert packet.auth_header.auth_scheme_name == AUTH_SCHEME_NAME assert packet.auth_header.ephemeral_public_key == ephemeral_public_key decrypted_auth_response = aesgcm_decrypt( key=auth_response_key, nonce=ZERO_NONCE, cipher_text=packet.auth_header.encrypted_auth_response, authenticated_data=b"", ) decoded_auth_response = rlp.decode(decrypted_auth_response) assert is_list_like(decoded_auth_response) and len(decoded_auth_response) == 3 assert decoded_auth_response[0] == int_to_big_endian(AUTH_RESPONSE_VERSION) assert decoded_auth_response[1] == id_nonce_signature assert ENR.deserialize(decoded_auth_response[2]) == enr decrypted_message = aesgcm_decrypt( key=initiator_key, nonce=auth_tag, cipher_text=packet.encrypted_message, authenticated_data=tag, ) assert decrypted_message[0] == message.message_type assert rlp.decode(decrypted_message[1:], PingMessage) == message
def test_personal_listAccounts(self, webu): accounts = webu.personal.listAccounts assert is_list_like(accounts) assert len(accounts) > 0 assert all(( is_checksum_address(item) for item in accounts ))
def validate_value(self, value): if not is_list_like(value): self.invalidate_value( value, msg="must be list-like such as array or tuple", ) for item in value: self.item_encoder.validate_value(item)
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 == 'bool': return is_boolean(value) elif base == 'uint': if not is_integer(value): return False exp = int(sub) if value < 0 or value >= 2**exp: return False return True elif base == 'int': if not is_integer(value): return False exp = int(sub) if value <= -1 * 2**(exp - 1) or value >= 2**(exp - 1): return False return True elif base == 'string': if not is_string(value): return False return True elif base == 'bytes': if not is_string(value): return False if not sub: return True max_length = int(sub) if isinstance(value, str): decodable = is_hex(value) and len(value) % 2 == 0 return decodable and len(decode_hex(value)) <= max_length elif isinstance(value, bytes): return len(value) <= max_length else: False elif base == 'address': if is_ens_name(value): return True elif is_address(value): return True else: return False else: raise ValueError("Unsupported type")
def test_personal_list_accounts(self, web3: "Web3") -> None: accounts = web3.geth.personal.list_accounts() assert is_list_like(accounts) assert len(accounts) > 0 assert all(( is_checksum_address(item) for item in accounts ))
def validate_abi(abi): """ Helper function for validating an ABI """ if not is_list_like(abi): raise TypeError("'abi' is not a list") for e in abi: if not is_dict(e): raise TypeError("The elements of 'abi' are not all dictionaries")
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_abi(abi): """ Helper function for validating an ABI """ if not is_list_like(abi): raise ValueError("'abi' is not a list") for e in abi: if not is_dict(e): raise ValueError("The elements of 'abi' are not all dictionaries")
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 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 == 'bool': return is_boolean(value) elif base == 'uint': if not is_integer(value): return False exp = int(sub) if value < 0 or value >= 2**exp: return False return True elif base == 'int': if not is_integer(value): return False exp = int(sub) if value <= -1 * 2**(exp - 1) or value >= 2**(exp - 1): return False return True elif base == 'string': if not is_string(value): return False return True elif base == 'bytes': if not is_string(value): return False if not sub: return True max_length = int(sub) if isinstance(value, str): decodable = is_hex(value) and len(value) % 2 == 0 return decodable and len(decode_hex(value)) <= max_length elif isinstance(value, bytes): return len(value) <= max_length else: return False elif base == 'address': if is_ens_name(value): return True elif is_address(value): return True else: return False else: raise ValueError("Unsupported type")
def match(filename, pattern): if is_list_like(pattern): return any([fnmatch.fnmatch(filename, p) for p in pattern]) elif is_string(pattern): return fnmatch.fnmatch(filename, pattern) else: raise TypeError( "Pattern must either be a string pattern or a list of patterns." + " Got {0}".format(pattern) )
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_vns_accounts(self, web3): accounts = web3.vns.accounts assert is_list_like(accounts) assert len(accounts) != 0 assert all(( is_checksum_address(account) for account in accounts )) assert web3.vns.coinbase in accounts
def test_eth_accounts(self, web3): accounts = web3.eth.accounts assert is_list_like(accounts) assert len(accounts) != 0 assert all(( is_address(account) for account in accounts )) assert web3.eth.coinbase in accounts
def wrapper(*args, **kwargs): value = fn(*args, **kwargs) if is_string(value): return os.path.relpath(value) elif is_list_like(value): return type(value)([ os.path.relpath(path) for path in value ]) else: raise TypeError("Unsupported type: {0}".format(type(value)))
def construct_event_filter_params(event_abi, contract_address=None, argument_filters=None, topics=None, fromBlock=None, toBlock=None, address=None): filter_params = {} if topics is None: topic_set = construct_event_topic_set(event_abi, argument_filters) else: topic_set = [topics] + construct_event_topic_set(event_abi, argument_filters) 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 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 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 sys.version_info.major >= 3 and 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 check_for_forbidden_api_filter_arguments(event_abi, _filters): name_indexed_inputs = {_input['name']: _input for _input in event_abi['inputs']} for filter_name, filter_value in _filters.items(): _input = name_indexed_inputs[filter_name] if is_array_type(_input['type']): raise TypeError( "createFilter no longer supports array type filter arguments. " "see the build_filter method for filtering array type filters.") if is_list_like(filter_value) and is_dynamic_sized_type(_input['type']): raise TypeError( "createFilter no longer supports setting filter argument options for dynamic sized " "types. See the build_filter method for setting filters with the match_any " "method.")
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 inputPostFormatter(post): """ Formats the input of a whisper post and converts all values to HEX """ post["ttl"] = from_decimal(post["ttl"]) post["workToProve"] = from_decimal(post.get("workToProve", 0)) post["priority"] = from_decimal(post["priority"]) if not is_list_like(post.get("topics")): post["topics"] = [post["topics"]] if post.get("topics") else [] post["topics"] = [topic if is_0x_prefixed(topic) else encode_hex(topic) for topic in post["topics"]] return post
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 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 ] topics = [ list(permutation) if any(value is not None for value in permutation) else [] for permutation in itertools.product(*encoded_args) ] return topics
def validate_value(self, value): if not is_list_like(value): self.invalidate_value( value, msg="must be list-like object such as array or tuple", ) if len(value) != len(self.encoders): self.invalidate_value( value, exc=ValueOutOfBounds, msg="value has {} items when {} were expected".format( len(value), len(self.encoders), ), ) for item, encoder in zip(value, self.encoders): try: encoder.validate_value(item) except AttributeError: encoder(item)
def providers(self, value): if not is_list_like(value): providers = [value] else: providers = value self._providers = providers
def __init__(self, *args, **kwargs): """Create a new smart contract proxy object. :param address: Contract address as 0x hex string """ code = kwargs.pop('code', empty) code_runtime = kwargs.pop('code_runtime', empty) source = kwargs.pop('source', empty) abi = kwargs.pop('abi', empty) address = kwargs.pop('address', empty) if self.web3 is None: raise AttributeError( 'The `Contract` class has not been initialized. Please use the ' '`web3.contract` interface to create your contract class.' ) arg_0, arg_1, arg_2, arg_3, arg_4 = tuple(itertools.chain( args, itertools.repeat(empty, 5), ))[:5] if is_list_like(arg_0): if abi: raise TypeError("The 'abi' argument was found twice") abi = arg_0 elif is_address(arg_0): if address: raise TypeError("The 'address' argument was found twice") address = arg_0 if is_address(arg_1): if address: raise TypeError("The 'address' argument was found twice") address = arg_1 if arg_2 is not empty: if code: raise TypeError("The 'code' argument was found twice") code = arg_2 if arg_3 is not empty: if code_runtime: raise TypeError("The 'code_runtime' argument was found twice") code_runtime = arg_3 if arg_4 is not empty: if source: raise TypeError("The 'source' argument was found twice") source = arg_4 if any((abi, code, code_runtime, source)): warnings.warn(DeprecationWarning( "The arguments abi, code, code_runtime, and source have been " "deprecated and will be removed from the Contract class " "constructor in future releases. Update your code to use the " "Contract.factory method." )) if abi is not empty: self.abi = abi if code is not empty: self.bytecode = code if code_runtime is not empty: self.bytecode_runtime = code_runtime if source is not empty: self._source = source if address is not empty: self.address = address else: warnings.warn(DeprecationWarning( "The address argument is now required for contract class " "instantiation. Please update your code to reflect this change" ))
def is_array_of_dicts(value): if not is_list_like(value): return False return all((is_dict(item) for item in value))
def upgrade_v4_to_v5(v4_config): """ Upgrade a v4 config file to a v5 config file. """ errors = get_validation_errors(v4_config, version=V4) if errors: raise ValueError( "Cannot upgrade invalid config. Please ensure that your current " "configuration file is valid:\n\n{0}".format( format_errors(errors), ) ) v4_default_config = load_default_config(version=V4) v5_default_config = load_default_config(version=V5) if v4_config == v4_default_config: return v5_default_config upgraded_v4_config = copy.deepcopy(v4_config) # new configuration values whos keys were not present in the previous # configuration. for key_path in NEW_V5_PATHS: if has_nested_key(upgraded_v4_config, key_path): continue set_nested_key( upgraded_v4_config, key_path, get_nested_key(v5_default_config, key_path), ) # keys in the new configuration that were relocated. for old_path, new_path in MOVED_V4_PATHS.items(): default_value = get_nested_key(v5_default_config, new_path) if has_nested_key(upgraded_v4_config, old_path): existing_value = pop_nested_key(upgraded_v4_config, old_path) if is_dict(default_value) and is_dict(existing_value): merged_value = deep_merge_dicts(default_value, existing_value) elif is_list_like(default_value) and is_list_like(existing_value): merged_value = list(set(itertools.chain(default_value, existing_value))) else: raise ValueError( "Unable to merge {0} with {1}".format( type(default_value), type(existing_value), ) ) set_nested_key( upgraded_v4_config, new_path, merged_value, ) else: set_nested_key( upgraded_v4_config, new_path, default_value, ) # keys from the previous configuration that were changed. for key_path in MODIFIED_V4_PATHS: new_default = get_nested_key(v5_default_config, key_path) if key_path not in upgraded_v4_config: set_nested_key( upgraded_v4_config, key_path, new_default, ) else: current_value = get_nested_key(upgraded_v4_config, key_path) old_default = get_nested_key(v4_default_config, key_path) if current_value == old_default: set_nested_key( upgraded_v4_config, key_path, new_default, ) # bump the version set_nested_key(upgraded_v4_config, 'version', V5) errors = get_validation_errors(upgraded_v4_config, version=V5) if errors: raise ValueError( "Upgraded configuration did not pass validation:\n\n" "\n=============Original-Configuration============\n" "{0}" "\n=============Upgraded-Configuration============\n" "{1}" "\n=============Validation-Errors============\n" "{2}".format( pprint.pformat(dict(v4_config)), pprint.pformat(dict(upgraded_v4_config)), format_errors(errors), ) ) return upgraded_v4_config
def upgrade_v3_to_v4(v3_config): """ Upgrade a v3 config file to a v4 config file. """ errors = get_validation_errors(v3_config, version=V3) if errors: raise ValueError( "Cannot upgrade invalid config. Please ensure that your current " "configuration file is valid:\n\n{0}".format( format_errors(errors), ) ) v3_default_config = load_default_config(version=V3) v4_default_config = load_default_config(version=V4) if v3_config == v3_default_config: return v4_default_config upgraded_v3_config = copy.deepcopy(v3_config) for key_path in NEW_V4_PATHS: if has_nested_key(upgraded_v3_config, key_path): continue set_nested_key( upgraded_v3_config, key_path, get_nested_key(v4_default_config, key_path), ) for old_path, new_path in MOVED_V3_PATHS.items(): default_value = get_nested_key(v4_default_config, new_path) if has_nested_key(upgraded_v3_config, old_path): existing_value = pop_nested_key(upgraded_v3_config, old_path) if is_dict(default_value) and is_dict(existing_value): merged_value = deep_merge_dicts(default_value, existing_value) elif is_list_like(default_value) and is_list_like(existing_value): merged_value = list(set(itertools.chain(default_value, existing_value))) else: raise ValueError( "Unable to merge {0} with {1}".format( type(default_value), type(existing_value), ) ) set_nested_key( upgraded_v3_config, new_path, merged_value, ) else: set_nested_key( upgraded_v3_config, new_path, default_value, ) # bump the version set_nested_key(upgraded_v3_config, 'version', V4) errors = get_validation_errors(upgraded_v3_config, version=V4) if errors: raise ValueError( "Upgraded configuration did not pass validation:\n\n" "\n=============Original-Configuration============\n" "{0}" "\n=============Upgraded-Configuration============\n" "{1}" "\n=============Validation-Errors============\n" "{2}".format( pprint.pformat(dict(v3_config)), pprint.pformat(dict(upgraded_v3_config)), format_errors(errors), ) ) return upgraded_v3_config
def is_array_of_strings(value): if not is_list_like(value): return False return all((is_string(item) for item in value))
def pop_singlets(seq): yield from (i[0] if is_list_like(i) and len(i) == 1 else i for i in seq)