示例#1
0
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
示例#2
0
    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
示例#3
0
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
示例#4
0
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
示例#5
0
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)
示例#6
0
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))
示例#10
0
    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
示例#11
0
 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)))
示例#13
0
 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))
示例#16
0
 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
示例#17
0
 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))
示例#18
0
def pop_singlets(seq):
    yield from (i[0] if is_list_like(i) and len(i) == 1 else i for i in seq)