Beispiel #1
0
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)
Beispiel #2
0
    def __init__(
            self,
            private_key: str = None,
            key_password_path: str = None,
            channel_manager_address: str = None,
            web3: Web3 = None
    ) -> None:
        is_hex_key = is_hex(private_key) and len(remove_0x_prefix(private_key)) == 64
        is_path = os.path.exists(private_key)
        assert is_hex_key or is_path, 'Private key must either be a hex key or a file path.'

        # Load private key from file if none is specified on command line.
        if is_path:
            private_key = get_private_key(private_key, key_password_path)
            assert private_key is not None, 'Could not load private key from file.'

        self.channels = []  # type: List[Channel]

        # Create web3 context if none is provided, either by using the proxies' context or creating
        # a new one.
        if not web3:
            web3 = Web3(HTTPProvider(WEB3_PROVIDER_DEFAULT))

        channel_manager_address = to_checksum_address(
            channel_manager_address or NETWORK_CFG.CHANNEL_MANAGER_ADDRESS
        )

        self.context = Context(private_key, web3, channel_manager_address)

        self.sync_channels()
Beispiel #3
0
def is_by_hash(at_block):
    if is_string(at_block) and is_hex(at_block) and len(at_block) == 66:
        return True
    elif is_integer(at_block) or at_block in ('latest', 'earliest', 'pending'):
        return False
    else:
        raise ValueError("Unrecognized 'at_block' value: %r" % at_block)
Beispiel #4
0
def faucet_private_key(request, faucet_password_path: str) -> str:
    private_key = request.config.getoption('faucet_private_key')
    if is_hex(private_key):
        assert len(remove_0x_prefix(private_key)) == 64
        return private_key
    else:
        private_key = get_private_key(private_key, faucet_password_path)
        assert private_key is not None, 'Error loading faucet private key from file.'
        return private_key
Beispiel #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 == '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")
Beispiel #6
0
def is_ens_name(value):
    if not isinstance(value, str):
        return False
    elif is_hex_address(value):
        return False
    elif is_0x_prefixed(value) and is_hex(value):
        return False
    else:
        return ENS.is_valid_name(value)
Beispiel #7
0
def test_hexstr_if_str_on_invalid_hex(val):
    try:
        is_hexstr = (is_hex(val) or val == '')
    except ValueError:
        is_hexstr = False

    if not is_hexstr:
        with pytest.raises(ValueError):
            hexstr_if_str(Mock(), val)
Beispiel #8
0
def hexstr_if_str(to_type, hexstr_or_primitive):
    '''
    Convert to a type, assuming that strings can be only hexstr (not unicode text)

    @param to_type is a function that takes the arguments (primitive, hexstr=hexstr, text=text),
        eg~ to_bytes, to_text, to_hex, to_int, etc
    @param text_or_primitive in bytes, str, or int.
    '''
    if isinstance(hexstr_or_primitive, str):
        (primitive, hexstr) = (None, hexstr_or_primitive)
        if remove_0x_prefix(hexstr) and not is_hex(hexstr):
            raise ValueError(
                "when sending a str, it must be a hex string. Got: {0!r}".format(
                    hexstr_or_primitive,
                )
            )
    else:
        (primitive, hexstr) = (hexstr_or_primitive, None)
    return to_type(primitive, hexstr=hexstr)
def hexstr_if_str(to_type, hexstr_or_primitive):
    """
    Convert to a type, assuming that strings can be only hexstr (not unicode text)

    @param to_type is a function that takes the arguments (primitive, hexstr=hexstr, text=text),
        eg~ to_bytes, to_text, to_hex, to_int, etc
    @param text_or_primitive in bytes, str, or int.
    """
    if isinstance(hexstr_or_primitive, str):
        (primitive, hexstr) = (None, hexstr_or_primitive)
        if remove_0x_prefix(hexstr) and not is_hex(hexstr):
            raise ValueError(
                "when sending a str, it must be a hex string. Got: {0!r}".format(
                    hexstr_or_primitive,
                )
            )
    else:
        (primitive, hexstr) = (hexstr_or_primitive, None)
    return to_type(primitive, hexstr=hexstr)
def normalize_int(value: IntConvertible) -> int:
    """
    Robust to integer conversion, handling hex values, string representations,
    and special cases like `0x`.
    """
    if is_integer(value):
        return cast(int, value)
    elif is_bytes(value):
        return big_endian_to_int(cast(bytes, value))
    elif is_hex(value) and is_0x_prefixed(value):
        value = cast(str, value)
        if len(value) == 2:
            return 0
        else:
            return int(value, 16)
    elif is_string(value):
        return int(value)
    else:
        raise TypeError(f"Unsupported type: Got `{type(value)}`")
Beispiel #11
0
def get_private_key(pk_file, pw_file=None):
    """Open a JSON-encoded private key and return it

    If a password file is provided, uses it to decrypt the key. If not, the
    password is asked interactively. Raw hex-encoded private keys are supported,
    but deprecated."""

    is_hex_key = is_hex(pk_file) and len(remove_0x_prefix(pk_file)) == 64
    is_path = os.path.exists(pk_file)
    assert is_hex_key or is_path, 'Private key must either be a hex key or a file path.'

    # Load private key from file if none is specified on command line.
    if is_path:
        private_key = load_pk(pk_file, pw_file)
        assert private_key is not None, 'Could not load private key from file.'
        return private_key
    else:
        # TODO make sure '0x'
        return pk_file
Beispiel #12
0
def get_private_key(key_path, password_path=None):
    """Open a JSON-encoded private key and return it

    If a password file is provided, uses it to decrypt the key. If not, the
    password is asked interactively. Raw hex-encoded private keys are supported,
    but deprecated."""

    assert key_path, key_path
    if not os.path.exists(key_path):
        log.fatal("%s: no such file", key_path)
        return None

    if not check_permission_safety(key_path):
        log.fatal("Private key file %s must be readable only by its owner.", key_path)
        return None

    if password_path and not check_permission_safety(password_path):
        log.fatal("Password file %s must be readable only by its owner.", password_path)
        return None

    with open(key_path) as keyfile:
        private_key = keyfile.readline().strip()

        if is_hex(private_key) and len(decode_hex(private_key)) == 32:
            log.warning("Private key in raw format. Consider switching to JSON-encoded")
        else:
            keyfile.seek(0)
            try:
                json_data = json.load(keyfile)
                if password_path:
                    with open(password_path) as password_file:
                        password = password_file.readline().strip()
                else:
                    password = getpass.getpass("Enter the private key password: "******"crypto"]["kdf"] == "pbkdf2":
                    password = password.encode()
                private_key = encode_hex(decode_keyfile_json(json_data, password))
            except ValueError:
                log.fatal("Invalid private key format or password!")
                return None

    return private_key
Beispiel #13
0
def to_hexbytes(num_bytes, val):
    if isinstance(val, str):
        result = HexBytes(val)
    elif isinstance(val, bytes):
        if len(val) == num_bytes:
            result = HexBytes(val)
        else:
            # some providers return values with hex as bytes, like b'0xEFFF' :(
            hexstr = val.decode('utf-8')
            if not is_hex(hexstr):
                raise ValueError("Cannot convert %r into a %d byte argument" %
                                 (hexstr, num_bytes))
            result = HexBytes(hexstr)
    else:
        raise TypeError("Cannot convert %r to HexBytes" % val)

    if len(result) != num_bytes:
        raise ValueError("The value %r is %d bytes, but should be %d" %
                         (result, len(result), num_bytes))
    return result
    def time_based_gas_price_strategy(web3, transaction_params):
        avg_block_time = _get_avg_block_time(web3, sample_size=sample_size)
        wait_blocks = int(math.ceil(max_wait_seconds / avg_block_time))

        raw_miner_data = _get_raw_miner_data(web3, sample_size=sample_size)
        miner_data = _aggregate_miner_data(raw_miner_data)

        probabilities = _compute_probabilities(
            miner_data,
            wait_blocks=wait_blocks,
            sample_size=sample_size,
        )
        latest = web3.eth.getBlock('latest')
        latest_block_gas_price = latest.minimumGasPrice
        if is_hex(latest_block_gas_price):
            latest_block_gas_price = int(latest_block_gas_price, 16)
        else:
            latest_block_gas_price = int(latest_block_gas_price)
        gas_price = _compute_gas_price(probabilities, probability / 100)
        max_gas = max(gas_price, latest_block_gas_price)
        return max_gas
Beispiel #15
0
def hexstr_if_str(to_type, hexstr_or_primitive):
    '''
    Convert to a type, assuming that strings can be only hexstr (not unicode text)

    @param to_type is a function that takes the arguments (primitive, hexstr=hexstr, text=text),
        eg~ to_bytes, to_text, to_hex, to_int, etc
    @param text_or_primitive in bytes, str, or int. (or unicode in py2)
        In Python 2, a bytes, unicode or str object will be interpreted as hexstr
        In Python 3, only a str object will be interpreted as hexstr
    '''
    if isinstance(hexstr_or_primitive, str) or (
            sys.version_info.major < 3 and isinstance(hexstr_or_primitive, unicode)  # noqa: F821
        ):
        (primitive, hexstr) = (None, hexstr_or_primitive)
        if remove_0x_prefix(hexstr) and not is_hex(hexstr):
            raise ValueError(
                "when sending this str, it must be a hex string. Got: %r" % hexstr_or_primitive
            )
    else:
        (primitive, hexstr) = (hexstr_or_primitive, None)
    return to_type(primitive, hexstr=hexstr)
Beispiel #16
0
def get_private_key(key_path, password_path=None):
    """Open a JSON-encoded private key and return it

    If a password file is provided, uses it to decrypt the key. If not, the
    password is asked interactively. Raw hex-encoded private keys are supported,
    but deprecated."""

    assert key_path, key_path
    if not os.path.exists(key_path):
        log.fatal("%s: no such file", key_path)
        return None

    if not check_permission_safety(key_path):
        log.fatal("Private key file %s must be readable only by its owner.", key_path)
        return None

    if password_path and not check_permission_safety(password_path):
        log.fatal("Password file %s must be readable only by its owner.", password_path)
        return None

    with open(key_path) as keyfile:
        private_key = keyfile.readline().strip()

        if is_hex(private_key) and len(decode_hex(private_key)) == 32:
            log.warning("Private key in raw format. Consider switching to JSON-encoded")
        else:
            keyfile.seek(0)
            try:
                json_data = json.load(keyfile)
                if password_path:
                    with open(password_path) as password_file:
                        password = password_file.readline().strip()
                else:
                    password = getpass.getpass("Enter the private key password: "******"Invalid private key format or password!")
                return None

    return private_key
Beispiel #17
0
    def iou_side_effect(*args, **kwargs):
        if args[0].endswith("/info"):
            return mocked_json_response({
                "price_info":
                5,
                "network_info": {
                    "chain_id":
                    42,
                    "token_network_registry_address":
                    to_checksum_address(
                        factories.make_token_network_registry_address()),
                    "user_deposit_address":
                    to_checksum_address(factories.make_address()),
                    "confirmed_block": {
                        "number": 11
                    },
                },
                "version":
                "0.0.3",
                "operator":
                "John Doe",
                "message":
                "This is your favorite pathfinding service",
                "payment_address":
                to_checksum_address(factories.make_address()),
                "matrix_server":
                "http://matrix.example.com",
            })
        else:
            assert "params" in kwargs
            body = kwargs["params"]

            assert is_hex_address(body["sender"])
            assert is_hex_address(body["receiver"])
            assert "timestamp" in body
            assert is_hex(body["signature"])
            assert len(body["signature"]
                       ) == 65 * 2 + 2  # 65 hex encoded bytes with 0x prefix

            return mocked_json_response(response_data=iou_json_data)
Beispiel #18
0
 def __init__(
     self,
     w3: "Web3",
     from_block: Optional[Union[BlockNumber, LatestBlockParam]] = None,
     to_block: Optional[Union[BlockNumber, LatestBlockParam]] = None,
     address: Optional[Union[Address, ChecksumAddress,
                             List[Union[Address, ChecksumAddress]]]] = None,
     topics: Optional[List[Optional[Union[_Hash32, List[_Hash32]]]]] = None
 ) -> None:
     self.address = address
     self.topics = topics
     self.w3 = w3
     if from_block is None or from_block == "latest":
         self._from_block = BlockNumber(w3.eth.block_number + 1)
     elif is_string(from_block) and is_hex(from_block):
         self._from_block = BlockNumber(
             hex_to_integer(from_block))  # type: ignore
     else:
         # cast b/c LatestBlockParam is handled above
         self._from_block = cast(BlockNumber, from_block)
     self._to_block = to_block
     self.filter_changes = self._get_filter_changes()
Beispiel #19
0
    def push(self, input_data: Union[bytes, str, int]) -> "Contract":
        """
        Opcode push1(0x60) to push32(0x7f), the length of data determines which opcode to use
        """
        data: bytes
        if isinstance(input_data, bytes):
            data = input_data
        elif isinstance(input_data, int):
            data = to_big_endian(input_data)
        elif is_hex(input_data):
            data = decode_hex(input_data)
        else:
            raise TypeError(f"Unsupported input_data type: {type(input_data)}")

        len_data = len(data)
        if len_data == 0 or len_data > 32:
            raise ValueError(f"Invalid data length: {len_data}")

        # If the data has length 5, the opcode for push5 is 0x5F + 5
        self.code.append(0x5F + len_data)
        self.code.extend([d for d in data])
        return self
Beispiel #20
0
def ipfs_get_json(ipfs_conn: ipfsapi.client.Client,
                  file_hash: str,
                  tmpdir: Optional[PS] = None) -> Dict[str, Any]:
    """ Perform an ipfs.get and return the json object as a Python dict """

    if isinstance(file_hash, bytes):
        file_hash = to_b58_string(
            from_hex_string('1220' + remove_0x_prefix(file_hash.hex())))
    elif is_0x_prefixed(file_hash):
        file_hash = to_b58_string(
            from_hex_string('1220' + remove_0x_prefix(file_hash)))
    elif is_hex(file_hash):
        file_hash = to_b58_string(from_hex_string('1220' + file_hash))
    elif file_hash.startswith('Qm'):
        pass
    else:
        raise ValueError("Invalid file_hash")

    with tempfile.TemporaryDirectory(dir=tmpdir) as _workdir:
        workdir = Path(_workdir)
        orig_dir = Path.cwd()
        assert orig_dir is not None
        os.chdir(workdir)

        ipfs_conn.get(file_hash)

        downloaded: Path = workdir.joinpath(file_hash)
        if not downloaded.exists() or not downloaded.is_file():
            raise ScatterError("Download filed.  File not found.")

        contents = ''
        with downloaded.open() as _userfile:
            userfile_text = _userfile.read()
            print("Downloaded... {}".format(userfile_text))
            contents = json.loads(userfile_text)

        os.chdir(orig_dir)
        downloaded.unlink()
        return contents
Beispiel #21
0
def etherscan_url(item, network: str, is_token=False) -> str:
    if network is None or network is UNKNOWN_DEVELOPMENT_CHAIN_ID:
        raise ValueError("A network must be provided")
    elif network == 'mainnet':
        domain = "https://etherscan.io"
    else:
        network = network.lower()
        testnets_supported_by_etherscan = ('ropsten', 'goerli', 'rinkeby', 'kovan')
        if network in testnets_supported_by_etherscan:
            domain = f"https://{network}.etherscan.io"
        else:
            raise ValueError(f"'{network}' network not supported by Etherscan")

    if is_address(item):
        item_type = 'address' if not is_token else 'token'
        item = to_checksum_address(item)
    elif is_hex(item) and len(item) == 2 + 32*2:  # If it's a hash...
        item_type = 'tx'
    else:
        raise ValueError(f"Cannot construct etherscan URL for {item}")

    url = f"{domain}/{item_type}/{item}"
    return url
Beispiel #22
0
def hexstr_if_str(to_type, hexstr_or_primitive):
    '''
    Convert to a type, assuming that strings can be only hexstr (not unicode text)

    @param to_type is a function that takes the arguments (primitive, hexstr=hexstr, text=text),
        eg~ to_bytes, to_text, to_hex, to_int, etc
    @param text_or_primitive in bytes, str, or int. (or unicode in py2)
        In Python 2, a bytes, unicode or str object will be interpreted as hexstr
        In Python 3, only a str object will be interpreted as hexstr
    '''
    if isinstance(hexstr_or_primitive, str) or (
            sys.version_info.major < 3 and isinstance(hexstr_or_primitive, unicode)  # noqa: F821
        ):
        (primitive, hexstr) = (None, hexstr_or_primitive)
        if remove_0x_prefix(hexstr) and not is_hex(hexstr):
            raise ValueError(
                "when sending a str, it must be a hex string. Got: {0!r}".format(
                    hexstr_or_primitive,
                )
            )
    else:
        (primitive, hexstr) = (hexstr_or_primitive, None)
    return to_type(primitive, hexstr=hexstr)
Beispiel #23
0
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)
Beispiel #24
0
    def __init__(self,
                 private_key: str = None,
                 key_password_path: str = None,
                 channel_manager_address: str = None,
                 web3: Web3 = None) -> None:
        """

        Args:
            private_key:
            key_password_path:
            channel_manager_address:
            web3:
        """
        is_hex_key = is_hex(private_key) and len(
            remove_0x_prefix(private_key)) == 64
        is_path = os.path.exists(private_key)
        assert is_hex_key or is_path, 'Private key must either be a hex key or a file path.'

        # Load private key from file if none is specified on command line.
        if is_path:
            private_key = get_private_key(private_key, key_password_path)
            assert private_key is not None, 'Could not load private key from file.'

        self.channels = []  # type: List[Channel]

        # Create web3 context if none is provided, either by using the proxies' context or creating
        # a new one.
        if not web3:
            web3 = Web3(HTTPProvider(WEB3_PROVIDER_DEFAULT))

        channel_manager_address = to_checksum_address(
            channel_manager_address or NETWORK_CFG.CHANNEL_MANAGER_ADDRESS)

        self.context = Context(private_key, web3, channel_manager_address)

        self.sync_channels()
Beispiel #25
0
def is_encoded_hash32(value: str) -> bool:
    return is_hex(value) and len(value) == 2 + 2 * 32
Beispiel #26
0
def is_hexstr(value):
    return is_string(value) and is_hex(value)
Beispiel #27
0
 def is_convertible(self, value: str) -> bool:
     return is_hex(value)
Beispiel #28
0
def is_hex_node_id(value: Any) -> bool:
    return (isinstance(value, str) and is_hex(value)
            and len(remove_0x_prefix(HexStr(value))) == 64)
def validate_signature(ctx, param, value):
    if is_hex(value) and is_0x_prefixed(value) and len(value) == 132:
        return decode_hex(value)
    else:
        raise click.BadParameter(
            f"A signature parameter seems to be not well structured: {value}")
Beispiel #30
0
def _hex_compare(a: Any, b: Any) -> bool:
    b = str(b)
    if not b.startswith("0x") or not eth_utils.is_hex(b):
        raise TypeError(f"Invalid type for comparison: '{b}' is not a valid hex string")
    return a.lstrip("0x").lower() == b.lstrip("0x").lower()
Beispiel #31
0
def validate_raw_transaction(raw_transaction):
    if not is_text(raw_transaction) or not is_hex(raw_transaction):
        raise ValidationError(
            "Raw Transaction must be a hexidecimal encoded string.  Got: "
            "{0}".format(raw_transaction))
Beispiel #32
0
def is_hexstr(value):
    return is_string(value) and is_hex(value)
Beispiel #33
0
def is_32byte_hex_string(value):
    return is_text(value) and is_hex(value) and len(
        remove_0x_prefix(value)) == 64
Beispiel #34
0
def is_hex_encoded_block_hash(value):
    if not is_string(value):
        return False
    return len(remove_0x_prefix(value)) == 64 and is_hex(value)
Beispiel #35
0
def is_hex_encoded_block_hash(value: Any) -> bool:
    if not is_string(value):
        return False
    return len(remove_0x_prefix(value)) == 64 and is_hex(value)
Beispiel #36
0
def validate_private_key(value):
    if not is_text(value) or not is_hex(value) or not len(
            remove_0x_prefix(value)) == 64:
        raise ValidationError(
            "Private keys must be 32 bytes encoded as hexidecimal")
Beispiel #37
0
def is_hexstr(value: Any) -> bool:
    return is_string(value) and is_hex(value)
Beispiel #38
0
def _address_compare(a: Any, b: Any) -> bool:
    b = str(b)
    if not b.startswith("0x") or not eth_utils.is_hex(b) or len(b) != 42:
        raise TypeError(f"Invalid type for comparison: '{b}' is not a valid address")
    return a.lower() == b.lower()
Beispiel #39
0
def test_is_hex(value, expected):
    actual = is_hex(value)
    assert actual is expected
Beispiel #40
0
def validate_transaction(value, txn_type):
    if txn_type not in ALLOWED_TRANSACTION_TYPES:
        raise TypeError(
            "the `txn_type` parameter must be one of send/call/estimate")
    if not is_dict(value):
        raise ValidationError(
            "Transaction must be a dictionary.  Got: {0}".format(type(value)))

    unknown_keys = tuple(
        sorted(
            set(value.keys()).difference(TRANSACTION_TYPE_INFO[txn_type], )))
    if unknown_keys:
        raise ValidationError(
            "Only the keys '{0}' are allowed.  Got extra keys: '{1}'".format(
                "/".join(tuple(sorted(TRANSACTION_TYPE_INFO[txn_type]))),
                "/".join(unknown_keys),
            ))

    if txn_type == 'send':
        required_keys = {'from', 'gas'}
    elif txn_type == 'send_signed':
        required_keys = {'from', 'gas'} | SIGNED_TRANSACTION_KEYS
    elif txn_type in {'estimate', 'call'}:
        required_keys = set(['from'])
    else:
        raise Exception("Invariant: code path should be unreachable")

    missing_required_keys = tuple(
        sorted(required_keys.difference(value.keys())))
    if missing_required_keys:
        raise ValidationError(
            "Transaction is missing the required keys: '{0}'".format(
                "/".join(missing_required_keys), ))

    if 'from' in value:
        validate_account(value['from'])

    if 'to' in value and value['to'] != '':
        validate_account(value['to'])
    elif 'to' in value and value['to'] == '':
        validate_text(value['to'])

    if 'gas' in value:
        validate_uint256(value['gas'])

    if 'gas_price' in value:
        validate_uint256(value['gas_price'])

    if 'value' in value:
        validate_uint256(value['value'])

    if 'nonce' in value:
        validate_uint256(value['nonce'])

    if 'data' in value:
        bad_data_message = (
            "Transaction data must be a hexidecimal encoded string.  Got: "
            "{0}".format(value['data']))
        if not is_text(value['data']):
            raise ValidationError(bad_data_message)
        elif not remove_0x_prefix(value['data']):
            pass
        elif not is_hex(value['data']):
            raise ValidationError(bad_data_message)
        try:
            decode_hex(value['data'])
        except (binascii.Error, TypeError):
            # TypeError is for python2
            # binascii.Error is for python3
            raise ValidationError(bad_data_message)

    if txn_type == 'send_signed':
        validate_uint256(value['r'])
        validate_uint256(value['s'])
        validate_uint8(value['v'])
def faucet_private_key(request) -> str:
    private_key = request.config.getoption('faucet_private_key')
    if is_hex(private_key):
        assert len(remove_0x_prefix(private_key)) == 64
        return private_key
 def test_eth_chainId(self, web3):
     chain_id = web3.eth.chainId
     assert is_hex(chain_id)
     assert hex_to_integer(chain_id) is 61