ETH_UTILS(1)

NAME
eth_utils - Ethereum Utilities Documentation

Common utility functions for python code that interacts with Ethereum

INSTALLATION

    python -m pip install eth-utils

  Overview

eth-utils provides common utility functions for codebases which interact with ethereum.

•   This library and repository was previously located at <https://github.com/pipermerriam/ethereum-utils>. It was transferred to the Ethereum foundation github in November 2017 and renamed to eth-utils. The PyPi package was also renamed from ethereum-utils to `eth-utils`.

  Installation

    python -m pip install eth-utils

  Development

Clone the repository and then run:

    python -m pip install -e ".[dev]"

  Documentation

Building Sphinx docs locally:

    python -m pip install -e ".[docs]"
    cd docs
    make html

Docs are written in reStructuredText <http://docutils.sourceforge.net/rst.html> and built using the Sphinx <http://www.sphinx-doc.org/> documentation generator.

  Running the tests

You can run the tests with:

    pytest tests

Or you can install tox to run the full test suite.

  Releasing

To release a new version:

    make release bump=$$VERSION_PART_TO_BUMP$$

  How to bumpversion

The version format for this repo is {major}.{minor}.{patch} for stable, and {major}.{minor}.{patch}-{stage}.{devnum} for unstable (stage can be alpha or beta).

To issue the next version in line, specify which part to bump, like make release bump=minor or make release bump=devnum.

If you are in a beta version, make release bump=stage will switch to a stable.

To issue an unstable version when the current version is stable, specify the new version explicitly, like make release bump="--new-version 4.0.0-alpha.1 devnum"

  Utilities

All functions can be imported directly from the eth_utils module

Alternatively, you can get the curried version of the functions by importing them through the curried module like so:

    >>> from eth_utils.curried import hexstr_if_str

  ABI Utilities

The Application Binary Interface (ABI) may be used for encoding or decoding transactional data. Components of an ABI may include a descriptor of each Function or Event in the contract. The following utilities provide convenient methods for parsing components of an ABI and encoding function parameters for use in transactions.

For more information about the ABI spec, see the Solidity Contract ABI specification <https://docs.soliditylang.org/en/v0.8.25/abi-spec.html>.

  Applicators

Applicators help you apply “formatters” in various ways, most notably:

•   apply formatters to values by key

•   apply formatters to lists by index

•   conditionally applying a formatter

•   conditionally applying one of several formatters.

    Here we define a “formatter” as any callable that may be called with a single positional argument. It returns the “formatted” result. For example int() could be used as a formatter.

    Defining your own formatter is easy:

        def i_put_my_thing_down_flip_it_and_reverse_it(lyric):
            return ''.join(reversed(lyric))

    These tools often work nicely when curried. Import them from the curried module to get that capability built in, like from eth_utils.curried import apply_formatter_if.

  apply_formatter_if(condition, formatter, value) -> new_value

This function will apply the formatter only if bool(condition()) is True.

    >>> from eth_utils.curried import apply_formatter_if, is_string
    >>> bool_if_string = apply_formatter_if(is_string, bool)
    >>> bool_if_string(1)
    1
    >>> bool_if_string('1')
    True
    >>> bool_if_string('')
    False

  apply_one_of_formatters(condition_formatter_pairs, value) -> new_value

This function will iterate through condition_formatter_pairs, and apply the first formatter which has a truthy condition. One of the formatters must match, or this function will raise a ValueError.

    >>> from eth_utils.curried import apply_one_of_formatters, is_string, is_list_like
    >>> multi_formatter = apply_one_of_formatters((
        (is_list_like, tuple),
        (is_string, i_put_my_thing_down_flip_it_and_reverse_it),
    )
    >>> multi_formatter('my thing')
    'gniht ym'
    >>> multi_formatter([1, 2])
    (1, 2)
    >>> multi_formatter(54)
    ValueError("The provided value did not satisfy any of the formatter conditions")

  apply_formatter_at_index(formatter, at_index, <list_like>) -> <new_list_like>

This function will apply the formatter to one element of list_like, at position at_index, and return a new iterable with that element replaced. The returned value will be the same type as the one passed into the third argument.

    >>> from eth_utils.curried import apply_formatter_at_index
    >>> targetted_formatter = apply_formatter_at_index(bool, 1)
    >>> targetted_formatter((1, 2, 3))
    (1, True, 3)
    >>> targetted_formatter([1, 2, 3])
    [1, True, 3]

  apply_formatter_to_array(formatter, <list_like>) -> <new_list_like>

This function will apply the formatter to each element of list_like. It returns the same type as the list_like argument

    >>> from eth_utils.curried import apply_formatter_to_array
    >>> map_int = apply_formatter_to_array(int)
    >>> map_int((1.2, 3.4, 5.6))
    (1, 3, 5)
    >>> map_int([1.2, 3.4, 5.6])
    [1, 3, 5]

  apply_formatters_to_sequence(formatters, <list_like>) -> <new_list_like>

This function will apply each formatter at to the list-like value, at the position it was supplied. It returns the same time as the list_like argument. For example:

    >>> from eth_utils.curried import apply_formatters_to_sequence
    >>> list_formatter = apply_formatters_to_sequence([bool, int, str])
    >>> list_formatter([1.2, 3.4, 5.6])
    [True, 3, '5.6']
    >>> list_formatter((1.2, 3.4, 5.6))
    (True, 3, '5.6')
    # Formatters and list-like value must be the same length
    >>> list_formatter((1.2, 3.4, 5.6, 7.8))
    Traceback (most recent call last):
    IndexError: Too few formatters for sequence: 3 formatters for (1.2, 3.4, 5.6, 7.8)
    >>> list_formatter((1.2, 3.4))
    Traceback (most recent call last):
    IndexError: Too many formatters for sequence: 3 formatters for (1.2, 3.4)

  combine_argument_formatters(*formatters) -> lambda <list_like>: <new_list_like>

DEPRECATED

You can replace all current versions of:

    >>> from eth_utils import combine_argument_formatters
    >>> list_formatter = combine_argument_formatters(bool, int, str)

With the newer, preferred:

    >>> from eth_utils.curried import apply_formatters_to_sequence
    >>> list_formatter = apply_formatters_to_sequence((bool, int, str))

The old usage works like:

Combine several formatters to be applied to a list-like value, each formatter at the position it was supplied. The new formatter will return the same type as it was supplied. For example:

    >>> from eth_utils import combine_argument_formatters
    >>> list_formatter = combine_argument_formatters(bool, int, str)
    >>> list_formatter([1.2, 3.4, 5.6])
    [True, 3, '5.6']
    >>> list_formatter((1.2, 3.4, 5.6))
    (True, 3, '5.6')
    # it will pass through items longer than the number of formatters supplied
    >>> list_formatter((1.2, 3.4, 5.6, 7.8))
    (True, 3, '5.6', 7.8)

  apply_formatters_to_dict(formatter_dict, <dict_like>, unaliased=False) -> dict

This function will apply the formatter to the element with the matching key in dict_like, passing through values with keys that have no matching formatter.

    >>> from eth_utils.curried import apply_formatters_to_dict
    >>> dict_formatter = apply_formatters_to_dict({
    ...    'should_be_int': int,
    ...    'should_be_bool': bool,
    ... })
    >>> result = dict_formatter({
    ...    'should_be_int': 1.2,
    ...    'should_be_bool': 3.4,
    ...    'pass_through': 5.6,
    ... })
    >>> result == {'should_be_int': 1, 'should_be_bool': True, 'pass_through': 5.6}
    True

The CamelModel pydantic model is included in expected dict-like types. If the dict-like object is an instance of a CamelModel, the unaliased argument can be set to True to pre-serialize the object as "non-aliased", according to pydantic. By default, it will be pre-serialized as "aliased", which CamelModel interprets as camelCase keys.

    >>> from eth_utils.curried import apply_formatters_to_dict
    >>> from eth_utils import CamelModel, to_bytes, to_int
    >>> from pydantic import Field
    >>> class PydanticModel(CamelModel):
    ...     to_bytes_from_int: int = 1
    ...     to_int_from_bytes: bytes = b"\x02"
    ...     # class fields excluded from serialization
    ...     excluded_field: int = Field(default=3, exclude=True)
    ...     excluded_field_two: str = Field(default="4", exclude=True)
    >>> dict_formatter = apply_formatters_to_dict({
    ...     "toBytesFromInt": to_bytes,
    ...     "toIntFromBytes": to_int
    ... })
    >>> dict_formatter(PydanticModel())
    {'toBytesFromInt': b'\x01', 'toIntFromBytes': 2}

  apply_key_map(formatter_dict, <dict_like>) -> dict

This function will rename keys from using the lookups provided in formatter_dict. It will pass through any unspecified keys.

    >>> from eth_utils.curried import apply_key_map
    >>> dict_key_map = apply_key_map({
    ...    'black': 'orange',
    ...    'Internet': 'Ethereum',
    ... })
    >>> result = dict_key_map({
    ...    'black': 1.2,
    ...    'Internet': 3.4,
    ...    'pass_through': 5.6,
    ... })
    >>> result == {'orange': 1.2, 'Ethereum': 3.4, 'pass_through': 5.6}
    True

  Address Utils

  is_address(value) -> bool

Returns True if the value is one of the following accepted address formats.

•

20 byte hexadecimal, upper/lower/mixed case, with or without 0x
    prefix:

•   'd3cda913deb6f67967b99d67acdfa1712c293601'

•   '0xd3cda913deb6f67967b99d67acdfa1712c293601'

•   '0xD3CDA913DEB6F67967B99D67ACDFA1712C293601'

•   '0xd3CdA913deB6f67967B99D67aCDFa1712C293601'

•

20 byte hexadecimal padded to 32 bytes with null bytes,
    upper/lower/mixed case, with or without 0x prefix:

•   '000000000000000000000000d3cda913deb6f67967b99d67acdfa1712c293601'

•   '000000000000000000000000d3cda913deb6f67967b99d67acdfa1712c293601'

•   '0x000000000000000000000000d3cda913deb6f67967b99d67acdfa1712c293601'

•   '0x000000000000000000000000D3CDA913DEB6F67967B99D67ACDFA1712C293601'

•   '0x000000000000000000000000d3CdA913deB6f67967B99D67aCDFa1712C293601'

•   20 text or bytes string:

•   '\xd3\xcd\xa9\x13\xde\xb6\xf6yg\xb9\x9dg\xac\xdf\xa1q,)6\x01'

    This function has two special cases when it will return False:

•   a 20-byte hex string that has mixed case, with an invalid checksum

•   a 32-byte value that is all null bytes

        >>> from eth_utils import is_address
        >>> is_address('d3cda913deb6f67967b99d67acdfa1712c293601')
        True
        >>> is_address('0xd3cda913deb6f67967b99d67acdfa1712c293601')
        True
        >>> is_address('0xD3CDA913DEB6F67967B99D67ACDFA1712C293601')
        True
        >>> is_address('0xd3CdA913deB6f67967B99D67aCDFa1712C293601')
        True
        >>> is_address('000000000000000000000000d3cda913deb6f67967b99d67acdfa1712c293601')
        False
        >>> is_address('000000000000000000000000d3cda913deb6f67967b99d67acdfa1712c293601')
        False
        >>> is_address('0x000000000000000000000000d3cda913deb6f67967b99d67acdfa1712c293601')
        False
        >>> is_address('0x000000000000000000000000D3CDA913DEB6F67967B99D67ACDFA1712C293601')
        False
        >>> is_address('0x000000000000000000000000d3CdA913deB6f67967B99D67aCDFa1712C293601')
        False
        >>> is_address(b'\xd3\xcd\xa9\x13\xde\xb6\xf6yg\xb9\x9dg\xac\xdf\xa1q,)6\x01')
        True
        >>> is_address('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xd3\xcd\xa9\x13\xde\xb6\xf6yg\xb9\x9dg\xac\xdf\xa1q,)6\x01')
        False
        >>> is_address('0x0000000000000000000000000000000000000000000000000000000000000000')
        False
        >>> is_address('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
        False

  is_hex_address(value) -> bool

Return True if the value is a 20 byte hexadecimal encoded string in any of upper/lower/mixed casing, with or without the 0x prefix. Otherwise return False

•   'd3cda913deb6f67967b99d67acdfa1712c293601'

•   '0xd3cda913deb6f67967b99d67acdfa1712c293601'

•   '0xD3CDA913DEB6F67967B99D67ACDFA1712C293601'

•   '0xd3CdA913deB6f67967B99D67aCDFa1712C293601'

        >>> from eth_utils import is_hex_address
        >>> is_hex_address('d3cda913deb6f67967b99d67acdfa1712c293601')
        True
        >>> is_hex_address('0xd3cda913deb6f67967b99d67acdfa1712c293601')
        True
        >>> is_hex_address('0xD3CDA913DEB6F67967B99D67ACDFA1712C293601')
        True
        >>> is_hex_address('0xd3CdA913deB6f67967B99D67aCDFa1712C293601')
        True
        >>> is_hex_address('000000000000000000000000d3cda913deb6f67967b99d67acdfa1712c293601')
        False
        >>> is_hex_address('000000000000000000000000d3cda913deb6f67967b99d67acdfa1712c293601')
        False
        >>> is_hex_address('0x000000000000000000000000d3cda913deb6f67967b99d67acdfa1712c293601')
        False
        >>> is_hex_address('0x000000000000000000000000D3CDA913DEB6F67967B99D67ACDFA1712C293601')
        False
        >>> is_hex_address('0x000000000000000000000000d3CdA913deB6f67967B99D67aCDFa1712C293601')
        False
        >>> is_hex_address('\xd3\xcd\xa9\x13\xde\xb6\xf6yg\xb9\x9dg\xac\xdf\xa1q,)6\x01')
        False
        >>> is_hex_address('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xd3\xcd\xa9\x13\xde\xb6\xf6yg\xb9\x9dg\xac\xdf\xa1q,)6\x01')
        False
        >>> is_hex_address('0x0000000000000000000000000000000000000000000000000000000000000000')
        False
        >>> is_hex_address('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
        False

  is_binary_address(value) -> bool

Return True if the value is a 20 byte string.

    >>> from eth_utils import is_binary_address
    >>> is_binary_address('d3cda913deb6f67967b99d67acdfa1712c293601')
    False
    >>> is_binary_address('0xd3cda913deb6f67967b99d67acdfa1712c293601')
    False
    >>> is_binary_address('0xD3CDA913DEB6F67967B99D67ACDFA1712C293601')
    False
    >>> is_binary_address('0xd3CdA913deB6f67967B99D67aCDFa1712C293601')
    False
    >>> is_binary_address('000000000000000000000000d3cda913deb6f67967b99d67acdfa1712c293601')
    False
    >>> is_binary_address('000000000000000000000000d3cda913deb6f67967b99d67acdfa1712c293601')
    False
    >>> is_binary_address('0x000000000000000000000000d3cda913deb6f67967b99d67acdfa1712c293601')
    False
    >>> is_binary_address('0x000000000000000000000000D3CDA913DEB6F67967B99D67ACDFA1712C293601')
    False
    >>> is_binary_address('0x000000000000000000000000d3CdA913deB6f67967B99D67aCDFa1712C293601')
    False
    >>> is_binary_address(b'\xd3\xcd\xa9\x13\xde\xb6\xf6yg\xb9\x9dg\xac\xdf\xa1q,)6\x01')
    True
    >>> is_binary_address('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xd3\xcd\xa9\x13\xde\xb6\xf6yg\xb9\x9dg\xac\xdf\xa1q,)6\x01')
    False
    >>> is_binary_address('0x0000000000000000000000000000000000000000000000000000000000000000')
    False
    >>> is_binary_address('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
    False

  is_canonical_address(value) -> bool

Returns True if the value is an address in its canonical form.

The canonical representation of an address according to eth_utils is a 20 byte long string of bytes, eg: b'\xd3\xcd\xa9\x13\xde\xb6\xf6yg\xb9\x9dg\xac\xdf\xa1q,)6\x01'

    >>> from eth_utils import is_canonical_address
    >>> is_canonical_address('0xd3cda913deb6f67967b99d67acdfa1712c293601')
    False
    >>> is_canonical_address(b'\xd3\xcd\xa9\x13\xde\xb6\xf6yg\xb9\x9dg\xac\xdf\xa1q,)6\x01')
    True
    >>> is_canonical_address('\xd3\xcd\xa9\x13\xde\xb6\xf6yg\xb9\x9dg\xac\xdf\xa1q,)6\x01xd')
    False

  is_checksum_address(value) -> bool

Returns True if the value is a checksummed address as specified by ERC55 <https://github.com/ethereum/EIPs/issues/55>

    >>> from eth_utils import is_checksum_address
    >>> is_checksum_address('0xd3CdA913deB6f67967B99D67aCDFa1712C293601')
    True
    >>> is_checksum_address('0xd3cda913deb6f67967b99d67acdfa1712c293601')
    False
    >>> is_checksum_address('0xD3CDA913DEB6F67967B99D67ACDFA1712C293601')
    False
    >>> is_checksum_address('0x52908400098527886E0F7030069857D2E4169EE7')
    True
    >>> is_checksum_address('0xde709f2102306220921060314715629080e2fb77')
    True

  is_checksum_formatted_address(value) -> bool

Returns True if the value is formatted as an ERC55 <https://github.com/ethereum/EIPs/issues/55> checksum address.

    >>> from eth_utils import is_checksum_formatted_address
    >>> is_checksum_formatted_address('0xd3CdA913deB6f67967B99D67aCDFa1712C293601')
    True
    >>> is_checksum_formatted_address('0xd3cda913deb6f67967b99d67acdfa1712c293601')
    False
    >>> is_checksum_formatted_address('0xD3CDA913DEB6F67967B99D67ACDFA1712C293601')
    False
    >>> is_checksum_formatted_address('0x52908400098527886E0F7030069857D2E4169EE7')
    False
    >>> is_checksum_formatted_address('0xde709f2102306220921060314715629080e2fb77')
    False

  is_normalized_address(value) -> bool

Returns True if the value is an address in its normalized form.

The normalized representation of an address is the lowercased 20 byte hexadecimal format.

    >>> from eth_utils import is_normalized_address
    >>> is_normalized_address('0xd3CdA913deB6f67967B99D67aCDFa1712C293601')
    False
    >>> is_normalized_address('0xd3cda913deb6f67967b99d67acdfa1712c293601')
    True
    >>> is_normalized_address('0xD3CDA913DEB6F67967B99D67ACDFA1712C293601')
    False
    >>> is_normalized_address('0x52908400098527886E0F7030069857D2E4169EE7')
    False
    >>> is_normalized_address('0xde709f2102306220921060314715629080e2fb77')
    True

  is_same_address(a, b) -> bool

Returns True if both a and b are valid addresses according to the is_address function and that they are both representations of the same address.

    >>> from eth_utils import is_same_address
    >>> is_same_address('0xd3cda913deb6f67967b99d67acdfa1712c293601', '0xD3CDA913DEB6F67967B99D67ACDFA1712C293601')
    True
    >>> is_same_address('0xd3cda913deb6f67967b99d67acdfa1712c293601', '0xd3CdA913deB6f67967B99D67aCDFa1712C293601')
    True
    >>> is_same_address('0xd3cda913deb6f67967b99d67acdfa1712c293601', b'\xd3\xcd\xa9\x13\xde\xb6\xf6yg\xb9\x9dg\xac\xdf\xa1q,)6\x01')
    True

  to_canonical_address(value) -> Address <https://eth-typing.readthedocs.io/en/latest/types.html#address>

Given any valid representation of an address return its canonical form.

    >>> from eth_utils import to_canonical_address
    >>> to_canonical_address('0xd3cda913deb6f67967b99d67acdfa1712c293601')
    b'\xd3\xcd\xa9\x13\xde\xb6\xf6yg\xb9\x9dg\xac\xdf\xa1q,)6\x01'
    >>> to_canonical_address('0xD3CDA913DEB6F67967B99D67ACDFA1712C293601')
    b'\xd3\xcd\xa9\x13\xde\xb6\xf6yg\xb9\x9dg\xac\xdf\xa1q,)6\x01'
    >>> to_canonical_address('0xd3CdA913deB6f67967B99D67aCDFa1712C293601')
    b'\xd3\xcd\xa9\x13\xde\xb6\xf6yg\xb9\x9dg\xac\xdf\xa1q,)6\x01'
    >>> to_canonical_address(b'\xd3\xcd\xa9\x13\xde\xb6\xf6yg\xb9\x9dg\xac\xdf\xa1q,)6\x01')
    b'\xd3\xcd\xa9\x13\xde\xb6\xf6yg\xb9\x9dg\xac\xdf\xa1q,)6\x01'

  to_checksum_address(value) -> ChecksumAddress <https://eth-typing.readthedocs.io/en/latest/types.html#checksumaddress>

Given any valid representation of an address return the checksummed representation.

    >>> from eth_utils import to_checksum_address
    >>> to_checksum_address('0xd3cda913deb6f67967b99d67acdfa1712c293601')
    '0xd3CdA913deB6f67967B99D67aCDFa1712C293601'
    >>> to_checksum_address('0xD3CDA913DEB6F67967B99D67ACDFA1712C293601')
    '0xd3CdA913deB6f67967B99D67aCDFa1712C293601'
    >>> to_checksum_address('0xd3CdA913deB6f67967B99D67aCDFa1712C293601')
    '0xd3CdA913deB6f67967B99D67aCDFa1712C293601'
    >>> to_checksum_address(b'\xd3\xcd\xa9\x13\xde\xb6\xf6yg\xb9\x9dg\xac\xdf\xa1q,)6\x01')
    '0xd3CdA913deB6f67967B99D67aCDFa1712C293601'

  to_normalized_address(value) -> HexAddress <https://eth-typing.readthedocs.io/en/latest/types.html#hexaddress>

Given any valid representation of an address return the normalized representation.

    >>> from eth_utils import to_normalized_address
    >>> to_normalized_address(b'\xd3\xcd\xa9\x13\xde\xb6\xf6yg\xb9\x9dg\xac\xdf\xa1q,)6\x01')  # raw bytes
    '0xd3cda913deb6f67967b99d67acdfa1712c293601'
    >>> to_normalized_address('c6d9d2cd449a754c494264e1809c50e34d64562b')  # hex encoded
    '0xc6d9d2cd449a754c494264e1809c50e34d64562b'
    >>> to_normalized_address('0xc6d9d2cd449a754c494264e1809c50e34d64562b')  # hex encoded
    '0xc6d9d2cd449a754c494264e1809c50e34d64562b'
    >>> to_normalized_address('0XC6D9D2CD449A754C494264E1809C50E34D64562B')  # cap-cased
    '0xc6d9d2cd449a754c494264e1809c50e34d64562b'

  Conversion Utils

These methods convert values using standard practices in the Ethereum ecosystem. For example, strings are encoded to binary using UTF-8.

Because there is no reliable way to distinguish between text and a hex-encoded bytestring, you must explicitly specify which of the two is being supplied when passing in a str.

Only supply one of the arguments:

  to_bytes(<bytes/int/bool/bytearray/memoryview>, text=<str>, hexstr=<str>) -> bytes

Takes a variety of inputs and returns its bytes equivalent. Text gets encoded as UTF-8.

    >>> from eth_utils import to_bytes
    >>> to_bytes(0)
    b'\x00'
    >>> to_bytes(0x000F)
    b'\x0f'
    >>> to_bytes(b'')
    b''
    >>> to_bytes(b'\x00\x0F')
    b'\x00\x0f'
    >>> to_bytes(False)
    b'\x00'
    >>> to_bytes(True)
    b'\x01'
    >>> to_bytes(hexstr='0x000F')
    b'\x00\x0f'
    >>> to_bytes(hexstr='000F')
    b'\x00\x0f'
    >>> to_bytes(text='')
    b''
    >>> to_bytes(text='cowmö')
    b'cowm\xc3\xb6'

  to_hex(<bytes/int/bool/bytearray/memoryview>, text=<str>, hexstr=<str>) -> HexStr <https://eth-typing.readthedocs.io/en/latest/types.html#hexstr>

Takes a variety of inputs and returns it in its hexadecimal representation. It follows the rules for converting to hex in the JSON-RPC spec. Roughly, it leaves leading 0s on bytes input, and trims leading zeros on int input.

    >>> from eth_utils import to_hex
    >>> to_hex(0)
    '0x0'
    >>> to_hex(1)
    '0x1'
    >>> to_hex(0x0)
    '0x0'
    >>> to_hex(0x000F)
    '0xf'
    >>> to_hex(b'')
    '0x'
    >>> to_hex(b'\x00\x0F')
    '0x000f'
    >>> to_hex(False)
    '0x0'
    >>> to_hex(True)
    '0x1'
    >>> to_hex(hexstr='0x000F')
    '0x000f'
    >>> to_hex(hexstr='000F')
    '0x000f'
    >>> to_hex(text='')
    '0x'
    >>> to_hex(text='cowmö')
    '0x636f776dc3b6'

  to_int(<bytes/int/bool/bytearray/memoryview>, text=<str>, hexstr=<str>) -> int

Takes a variety of inputs and returns its integer equivalent.

    >>> from eth_utils import to_int
    >>> to_int(0)
    0
    >>> to_int(0x000F)
    15
    >>> to_int(b'\x00\x0F')
    15
    >>> to_int(False)
    0
    >>> to_int(True)
    1
    >>> to_int(hexstr='0x000F')
    15
    >>> to_int(hexstr='000F')
    15

  to_text(<bytes/int/bool/bytearray/memoryview>, text=<str>, hexstr=<str>) -> str

Takes a variety of inputs and returns its string equivalent. Text gets decoded as UTF-8.

    >>> from eth_utils import to_text
    >>> to_text(0x636f776dc3b6)
    'cowmö'
    >>> to_text(b'cowm\xc3\xb6')
    'cowmö'
    >>> to_text(hexstr='0x636f776dc3b6')
    'cowmö'
    >>> to_text(hexstr='636f776dc3b6')
    'cowmö'
    >>> to_text(text='cowmö')
    'cowmö'

  text_if_str(to_type, text_or_primitive) -> T

Convert text_or_primitive with the provided to_type function. Assumes the input string or primitive will be unicode text.

Return type T is the same as the return type of the provided to_type function.

    >>> from eth_utils import text_if_str, to_bytes
    >>> text_if_str(to_bytes, 0)
    b'\x00'
    >>> text_if_str(to_hex, 0)
    '0x0'
    >>> text_if_str(to_int, 0)
    0
    >>> text_if_str(to_text, 0)
    '\x00'

  hexstr_if_str(to_type, text_or_primitive) -> T

Convert text_or_primitive with the provided to_type function. Assumes the input string or primitive will be hexstr.

Return type T is the same as the return type of the provided to_type function.

    >>> from eth_utils import hexstr_if_str, to_bytes
    >>> hexstr_if_str(to_bytes, '0x000F')
    b'\x00\x0f'
    >>> hexstr_if_str(to_hex, '0x000F')
    '0x000f'
    >>> hexstr_if_str(to_int, '0x000F')
    15
    >>> hexstr_if_str(to_text, '0x000F')
    '\x00\x0f'

  Crypto Utils

Because there is no reliable way to distinguish between text and a hex-encoded bytestring, you must explicitly specify which of the two is being supplied when passing in a str.

Only supply one of the arguments:

  keccak(<bytes/int/bool>, text=<str>, hexstr=<str>) -> bytes

    >>> from eth_utils import keccak
    >>> keccak(text='')
    b"\xc5\xd2F\x01\x86\xf7#<\x92~}\xb2\xdc\xc7\x03\xc0\xe5\x00\xb6S\xca\x82';{\xfa\xd8\x04]\x85\xa4p"
    # A series of equivalent hash inputs:
    >>> keccak(text='☢')
    b'\x85\xe8\x07"\xeb\x93\r\xe9;\xcc\xa8{\xa5\xdf\xda\x89\n\xa12\x95\xae\xad.\xec\xc9\x0b\xb2\xd9z\x14\x93\x16'
    >>> keccak(0xe298a2)
    b'\x85\xe8\x07"\xeb\x93\r\xe9;\xcc\xa8{\xa5\xdf\xda\x89\n\xa12\x95\xae\xad.\xec\xc9\x0b\xb2\xd9z\x14\x93\x16'
    >>> keccak(b'\xe2\x98\xa2')
    b'\x85\xe8\x07"\xeb\x93\r\xe9;\xcc\xa8{\xa5\xdf\xda\x89\n\xa12\x95\xae\xad.\xec\xc9\x0b\xb2\xd9z\x14\x93\x16'
    >>> keccak(hexstr='0xe298a2')
    b'\x85\xe8\x07"\xeb\x93\r\xe9;\xcc\xa8{\xa5\xdf\xda\x89\n\xa12\x95\xae\xad.\xec\xc9\x0b\xb2\xd9z\x14\x93\x16'

Please Note - When using Python’s native hex literals, python converts the hex to an int, so leading 0 bytes are truncated. But all other formats maintain zeros on the left. Hex literals are only padded until a whole number of bytes are provided to keccak. For example:

    >>> keccak(0xe298a2)
    b'\x85\xe8\x07"\xeb\x93\r\xe9;\xcc\xa8{\xa5\xdf\xda\x89\n\xa12\x95\xae\xad.\xec\xc9\x0b\xb2\xd9z\x14\x93\x16'
    >>> keccak(0x0e298a2)
    b'\x85\xe8\x07"\xeb\x93\r\xe9;\xcc\xa8{\xa5\xdf\xda\x89\n\xa12\x95\xae\xad.\xec\xc9\x0b\xb2\xd9z\x14\x93\x16'
    >>> keccak(0x00e298a2)
    b'\x85\xe8\x07"\xeb\x93\r\xe9;\xcc\xa8{\xa5\xdf\xda\x89\n\xa12\x95\xae\xad.\xec\xc9\x0b\xb2\xd9z\x14\x93\x16'
    >>> keccak(0x000e298a2)
    b'\x85\xe8\x07"\xeb\x93\r\xe9;\xcc\xa8{\xa5\xdf\xda\x89\n\xa12\x95\xae\xad.\xec\xc9\x0b\xb2\xd9z\x14\x93\x16'
    >>> keccak(hexstr='0x0e298a2')
    b'i\x0f$\xbd\xbe\xf7c\xbb\xb9M\xd9\x12H"\x9f\x1f\x87\\E\xa36\xc2\xea,\x8f.\r\xf5\x95\xdc\x19\x9b'
    >>> keccak(hexstr='0x00e298a2')
    b'i\x0f$\xbd\xbe\xf7c\xbb\xb9M\xd9\x12H"\x9f\x1f\x87\\E\xa36\xc2\xea,\x8f.\r\xf5\x95\xdc\x19\x9b'
    >>> keccak(hexstr='0x000e298a2')
    b'!$Ezy\xdeU<\xec\x1f\xd1\x10\x05\xff\x11\xfc=J\xcf\xd5H\x0f\xb3c\xcc\xb5\xae\xb1\x1eA\x8b\xd3'

  Currency Utils

  denoms

Object with property access to all of the various denominations for ether. Available denominations are:
denomination | amount in wei
wei | 1
kwei | 1000
babbage | 1000
femtoether | 1000
mwei | 1000000
lovelace | 1000000
picoether | 1000000
gwei | 1000000000
shannon | 1000000000
nanoether | 1000000000
nano | 1000000000
szabo | 1000000000000
microether | 1000000000000
micro | 1000000000000
finney | 1000000000000000
milliether | 1000000000000000
milli | 1000000000000000
ether | 1000000000000000000
kether | 1000000000000000000000
grand | 1000000000000000000000
mether | 1000000000000000000000000
gether | 1000000000000000000000000000
tether | 1000000000000000000000000000000

    >>> from eth_utils import denoms
    >>> denoms.wei
    1
    >>> denoms.finney
    1000000000000000
    >>> denoms.ether
    1000000000000000000

  to_wei(value, denomination) -> integer

Converts value in the given denomination to its equivalent in the wei denomination.

    >>> from eth_utils import to_wei
    >>> to_wei(1, 'ether')
    1000000000000000000

  to_wei_decimals(value, decimals) -> integer

Converts value in the given denomination to its equivalent in the wei denomination.

    >>> from eth_utils import to_wei_decimals
    >>> to_wei_decimals(1, 18)
    1000000000000000000

  from_wei(value, denomination) -> decimal.Decimal

Converts the value in the wei denomination to its equivalent in the given denomination. Return value is a decimal.Decimal with the appropriate precision to be a lossless conversion.

    >>> from eth_utils import from_wei
    >>> from_wei(1000000000000000000, 'ether')
    Decimal('1')
    >>> from_wei(123456789, 'ether')
    Decimal('1.23456789E-10')

  from_wei_decimals(value, decimals) -> decimal.Decimal

Converts the value in the wei denomination to the number of specified decimals. Return value is a decimal.Decimal with the appropriate precision to be a lossless conversion.

    >>> from eth_utils import from_wei_decimals
    >>> from_wei_decimals(100, 3)
    Decimal('0.1')
    >>> from_wei_decimals(123456789, 18)
    Decimal('1.23456789E-10')

  Debug Utils

  Generate environment info

At the shell:

    $ python -m eth_utils
    Python version:
    3.5.3 (default, Nov 23 2017, 11:34:05)
    [GCC 6.3.0 20170406]
    Operating System: Linux-4.10.0-42-generic-x86_64-with-Ubuntu-17.04-zesty
    pip freeze result:
    bumpversion==0.5.3
    cytoolz==0.9.0
    flake8==3.4.1
    ipython==6.2.1
    pytest==3.3.2
    virtualenv==15.1.0
    ... etc

  Decorators

  @combomethod

Decorates methods in a class that can be called as both an instance method or a @classmethod.

Use the decorator like so:

    >>> from eth_utils import combomethod
    >>> class Storage:
    ...    val = 1
    ...
    ...    @combomethod
    ...    def get(combo):
    ...        if isinstance(combo, type):
    ...            print("classmethod call")
    ...        elif isinstance(combo, Storage):
    ...            print("instance method call")
    ...        else:
    ...            raise TypeError("Unreachable, unless you really monkey around")
    ...        return combo.val
    ...

As usual, instances create their own copy on assignment.

    >>> store = Storage()
    >>> store.val = 2
    >>> store.get()
    instance method call
    2
    >>> Storage.get()
    classmethod call
    1

  @replace_exceptions

Replaces Old exceptions in a method with New exceptions. Accepts a Dict, with Old exceptions pointing to New exceptions.

    >>> from eth_utils import replace_exceptions
    >>> @replace_exceptions({TypeError: AttributeError})
    ... def thing(self):
    ...     if True:
    ...         raise TypeError
    >>> thing()
    Traceback (most recent call last):
       ...
    AttributeError

Calling thing() will raise an AttributeError

  Encoding Utils

  big_endian_to_int(value) -> integer

Returns value converted to an integer (from a big endian representation).

    >>> from eth_utils import big_endian_to_int
    >>> big_endian_to_int(b'\x00')
    0
    >>> big_endian_to_int(b'\x01')
    1
    >>> big_endian_to_int(b'\x01\x00')
    256

  int_to_big_endian(value) -> bytes

Returns value converted to the big endian representation.

    >>> from eth_utils import int_to_big_endian
    >>> int_to_big_endian(0)
    b'\x00'
    >>> int_to_big_endian(1)
    b'\x01'
    >>> int_to_big_endian(256)
    b'\x01\x00'

  Exceptions

  ValidationError

An exception that is raised when something does not pass a validation check.

  Functional Utils

  compose(*callables) -> callable
DEPRECATED in 0.3.0.

Returns a single function which is the composition of the given callables.

    >>> def f(v):
    ...     return v * 3
    ...
    >>> def g(v):
    ...     return v + 2
    ...
    >>> def h(v):
    ...     return v % 5
    ...
    >>> compose(f, g, h)(1)
    0
    >>> h(g(f(1)))
    0
    >>> compose(f, g, h)(2)
    3
    >>> h(g(f(1)))
    3
    >>> compose(f, g, h)(3)
    1
    >>> h(g(f(1)))
    1
    >>> compose(f, g, h)(4)
    4
    >>> h(g(f(1)))
    4

  flatten_return(callable) -> callable() -> tuple

Decorator which performs a non-recursive flattening of the return value from the given callable.

    >>> flatten_return(lambda: [[1, 2, 3], [4, 5], [6]])
    (1, 2, 3, 4, 5, 6)

  sort_return(callable) => callable() -> tuple

Decorator which sorts the return value from the given callable.

    >>> flatten_return(lambda: [[1, 2, 3], [4, 5], [6]])
    (1, 2, 3, 4, 5, 6)

  reversed_return(callable) => callable() -> tuple

Decorator which reverses the return value from the given callable.

    >>> reversed_return(lambda: [1, 5, 2, 4, 3])
    (3, 4, 2, 5, 1)

  to_dict(callable) => callable() -> dict

Decorator which casts the return value from the given callable to a dictionary.

    >>> from eth_utils import to_dict
    >>> @to_dict
    ... def build_thing():
    ...     yield 'a', 1
    ...     yield 'b', 2
    ...     yield 'c', 3
    ...
    >>> build_thing() == {'a': 1, 'b': 2, 'c': 3}
    True

  to_list(callable) => callable() -> list

Decorator which casts the return value from the given callable to a list.

    >>> from eth_utils import to_list
    >>> @to_list
    ... def build_thing():
    ...     yield 'a'
    ...     yield 'b'
    ...     yield 'c'
    ...
    >>> build_thing()
    ['a', 'b', 'c']

  to_ordered_dict(callable) => callable() -> collections.OrderedDict

Decorator which casts the return value from the given callable to an ordered dictionary of type collections.OrderedDict.

    >>> from eth_utils import to_ordered_dict
    >>> @to_ordered_dict
    ... def build_thing():
    ...     yield 'd', 4
    ...     yield 'a', 1
    ...     yield 'b', 2
    ...     yield 'c', 3
    ...
    >>> build_thing()
    OrderedDict([('d', 4), ('a', 1), ('b', 2), ('c', 3)])

  to_tuple(callable) => callable() -> tuple

Decorator which casts the return value from the given callable to a tuple.

    >>> from eth_utils import to_tuple
    >>> @to_tuple
    ... def build_thing():
    ...     yield 'a'
    ...     yield 'b'
    ...     yield 'c'
    ...
    >>> build_thing()
    ('a', 'b', 'c')

  to_set(callable) => callable() -> set

Decorator which casts the return value from the given callable to a set.

    >>> from eth_utils import to_set
    >>> @to_set
    ... def build_thing():
    ...     yield 'a'
    ...     yield 'b'
    ...     yield 'a'  # duplicate
    ...     yield 'c'
    ...
    >>> build_thing() == {'c', 'b', 'a'}
    True

  apply_to_return_value(callable) => decorator_fn

This function takes a single callable and returns a decorator. The returned decorator, when applied to a function, will incercept the function’s return value, pass it to the callable, and return the value returned by the callable.

    >>> from eth_utils import apply_to_return_value
    >>> double = apply_to_return_value(lambda v: v * 2)
    >>> @double
    ... def f(v):
    ...     return v
    ...
    >>> f(2)
    4
    >>> f(3)
    6

  Hexadecimal Utils

  add_0x_prefix(value: HexStr) -> HexStr <https://eth-typing.readthedocs.io/en/latest/types.html#hexstr>

Returns value with a 0x prefix. If the value is already prefixed it is returned as-is. Value must be a HexStr <https://eth-typing.readthedocs.io/en/latest/types.html#hexstr>.

    >>> from eth_utils import add_0x_prefix
    >>> from eth_typing import HexStr
    >>> add_0x_prefix(HexStr('12345'))
    '0x12345'
    >>> add_0x_prefix(HexStr('0x12345'))
    '0x12345'

  decode_hex(value) -> bytes

Returns value decoded into a byte string. Accepts any string with or without the 0x prefix.

    >>> from eth_utils import decode_hex
    >>> decode_hex('0x123456')
    b'\x124V'
    >>> decode_hex('123456')
    b'\x124V'

  encode_hex(value) -> string

Returns value encoded into a hexadecimal representation with a 0x prefix

    >>> from eth_utils import encode_hex
    >>> encode_hex(b'\x01\x02\x03')
    '0x010203'

  is_0x_prefixed(value) -> bool

Returns True if value has a 0x prefix. Value must be a string literal.

    >>> from eth_utils import is_0x_prefixed
    >>> is_0x_prefixed('12345')
    False
    >>> is_0x_prefixed('0x12345')
    True

  is_hex(value) -> bool

Returns True if value is a hexadecimal encoded string of text type.

    >>> from eth_utils import is_hex
    >>> is_hex('')
    False
    >>> is_hex('0x')
    True
    >>> is_hex('0X')
    True
    >>> is_hex('1234567890abcdef')
    True
    >>> is_hex('0x1234567890abcdef')
    True
    >>> is_hex('0x1234567890ABCDEF')
    True
    >>> is_hex('0x1234567890AbCdEf')
    True
    >>> is_hex('12345')  # odd length is ok
    True
    >>> is_hex('0x12345')  # odd length is ok
    True
    >>> is_hex('123456__abcdef')  # non hex characters
    False
    # invalid, will raise TypeError:
    >>> is_hex(b'')
    Traceback (most recent call last):
    TypeError: is_hex requires text typed arguments.
    >>> is_hex(b'0x')
    Traceback (most recent call last):
    TypeError: is_hex requires text typed arguments.
    >>> is_hex(b'0X')
    Traceback (most recent call last):
    TypeError: is_hex requires text typed arguments.

  is_hexstr(value) -> bool

Returns True if value is a hexadecimal encoded string of text type.

Note: This function differs from is_hex(value: Any) in that it will return False on all non-text type arguments, while is_hex will raise a TypeError for all non-text type arguments.

    >>> from eth_utils import is_hexstr
    >>> is_hexstr('')
    False
    >>> is_hexstr('0x')
    True
    >>> is_hexstr('0X')
    True
    >>> is_hexstr('1234567890abcdef')
    True
    >>> is_hexstr('0x1234567890abcdef')
    True
    >>> is_hexstr('0x1234567890ABCDEF')
    True
    >>> is_hexstr('0x1234567890AbCdEf')
    True
    >>> is_hexstr('12345')  # odd length is ok
    True
    >>> is_hexstr('0x12345')  # odd length is ok
    True
    >>> is_hexstr('123456__abcdef')  # non hex characters
    False
    >>> is_hexstr(b'') # any non-string returns False
    False
    >>> is_hexstr(b'0x') # any non-string returns False
    False

  remove_0x_prefix(value: HexStr) -> HexStr <https://eth-typing.readthedocs.io/en/latest/types.html#hexstr>

Returns value with the 0x prefix stripped. If the value does not have a 0x prefix it is returned as-is. Value must be a HexStr <https://eth-typing.readthedocs.io/en/latest/types.html#hexstr>.

    >>> from eth_utils import remove_0x_prefix
    >>> from eth_typing import HexStr
    >>> remove_0x_prefix(HexStr('12345'))
    '12345'
    >>> remove_0x_prefix(HexStr('0x12345'))
    '12345'

  Humanize Utils

  humanize_seconds(seconds) -> string

Returns the provide number of seconds as a shorthand string.

    >>> from eth_utils import humanize_seconds
    >>> humanize_seconds(0)
    '0s'
    >>> humanize_seconds(1)
    '1s'
    >>> humanize_seconds(60)
    '1m'
    >>> humanize_seconds(61)
    '1m1s'

  humanize_bytes(bytes) -> string

Returns the provided byte string in a human readable format.

If the value is 5 bytes or less it is returned in full in its hexadecimal representation (without a 0x prefix)

If the value is longer that 5 bytes it is returned in its hexadecimal representation (without a 0x prefix) with the middle segment replaced by an ellipsis, only showing the first and last four hexadecimal nibbles.

    >>> from eth_utils import humanize_bytes
    >>> humanize_bytes(bytes(range(3)))
     '000102'
    >>> humanize_bytes(bytes(range(5)))
     '0001020304'
    >>> humanize_bytes(bytes(range(32)))
     '0001..1e1f'

  humanize_hexstr(str) -> string

Returns the provided hex string in a human readable format.

If the value is 4 bytes or less it is returned in full in its hexadecimal representation (with a 0x prefix)

If the value is longer than 4 bytes it is returned in its hexadecimal representation with the middle segment replaced by an ellipsis, only showing the first and last four hexadecimal nibbles.

    >>> from eth_utils import humanize_hexstr
    >>> humanize_hexstr('0x1234')
     '0x1234'
    >>> humanize_hexstr('0x12345678')
     '0x12345678'
    >>> humanize_hexstr('0x10203040506070')
     '0x1020..6070'

  humanize_hash(bytes) -> string

A loose wrapper around humanize_bytes that is typed specifically for the eth_typing.Hash32 type.

    >>> from eth_utils import humanize_hash
    >>> humanize_hash(bytes(range(32)))
     '0001..1e1f'

  humanize_integer_sequence(values) -> string

Returns a concise representation of the provided sequence of integer values.

    >>> from eth_utils import humanize_integer_sequence
    >>> humanize_integer_sequence((1, 2, 3, 4))
    '1-4'
    >>> humanize_integer_sequence((1, 2, 3, 4, 6, 8, 9, 10))
    '1-4|6|8-10'

  humanize_ipfs_uri(string) -> string

Returns the provided IPFS uri, with the middle segment of the hash replaced by an ellipsis, only showing the first and last four characters of the hash.

    >>> from eth_utils import humanize_ipfs_uri
    >>> humanize_ipfs_uri('ipfs://QmTKB75Y73zhNbD3Y73xeXGjYrZHmaXXNxoZqGCagu7r8u')
     'ipfs://QmTK..7r8u'

  humanize_wei(int) -> string

Returns a human-friendly form of units given an amount of wei.

    >>> from eth_utils import humanize_wei
    >>> humanize_wei(0)
    '0 wei'
    >>> humanize_wei(1000000000000000000000)
    '1000 ether'
    >>> humanize_wei(9876543)
    '0.009876543 gwei'

  Logging Utils

  get_logger(string, [, logger_class]) -> logger

This API is similar to the standard library logging.getLogger however, the logger it returns will be an instance of the provided logger_class. If logger_class is not provided this returns an instance of whatever the current default logger class is set on the logging.

    >>> import logging
    >>> from eth_utils import get_logger
    >>> logger = get_logger('my_application')
    >>> assert logger.name == 'my_application'
    >>> assert isinstance(logger, logging.getLoggerClass())

  get_extended_debug_logger(string) -> ExtendedDebugLogger

Like get_logger except that it always returns an instance of ExtendedDebugLogger

    >>> from eth_utils import get_extended_debug_logger, ExtendedDebugLogger
    >>> logger = get_extended_debug_logger('my_application')
    >>> assert logger.name == 'my_application'
    >>> assert isinstance(logger, ExtendedDebugLogger), type(logger)

  class HasLogger

Classes which inherit from this class will have an instance of a logger available on the attribute logger

    >>> from eth_utils import HasLogger
    >>> class MyClass(HasLogger):
    ...     pass
    ...
    >>> MyClass.logger.debug("This works")
    >>> instance = MyClass()
    >>> instance.logger.debug("This also works")

The name of the logger instance is derived from the __qualname__ for the class.

Warning: This class will not behave nicely with the standard library typing.Generic. If you need to create a Generic class then you'll need to assign your logging instances manually.

  class ExtendedDebugLogger

A subclass of logging.Logger which exposes a debug2 function which can be used to log a message at the DEBUG2 log level.

Note: This class works fine on its own but will produce cleaner logs if you make sure to call eth_utils.setup_DEBUG2_logging at least once before issuing any debug2 level logs.

  class HasExtendedDebugLogger

Same as the HasLogger class except the logger it exposes is an instance of ExtendedDebugLogger

  setup_DEBUG2_logging() -> None

Installs the DEBUG2 level to the standard library logging module which uses the numeric level of 8. This includes adding it to the known levels as well as providing a logging.DEBUG2 convenience property on the logging module.

This function is purely for convenience. You can use ExtendedDebugLogger without this, though your logs will be printed with the label 'Level 8'.

    >>> from eth_utils import setup_DEBUG2_logging
    >>> import logging
    >>> logging.getLevelName(8)
    'Level 8'
    >>> setup_DEBUG2_logging()
    >>> logging.getLevelName(8)
    'DEBUG2'
    >>> logging.DEBUG2
    8

Note: This function is idempotent

  class HasLoggerMeta

This is the metaclass which is responsible for adding the logger instance to the class. It exposes two additional APIs.

•   HasLoggerMeta.replace_logger_class(cls: logging.Logger)

    Returns a new metaclass which will use the provided logger class.

•   HasLoggerMeta.meta_compat(other: type)

    Returns a new metaclass that derives from both metaclasses. This is useful when working in conjunction with abc.ABC or typing.Generic.

  class HasExtendedDebugLoggerMeta

This metaclass uses the ExtendedDebugLogger class, derived from HasLoggerMeta.replace_logger_class(ExtendedDebugLogger).

  Module Loading

  import_string(dotted_path) -> Any

Import a variable/class name for a module given the dotted_path string.

Raises an ImportError if the module could not be found.

    >>> from eth_utils import import_string
    >>> import_string("eth_utils.decorators.combomethod")
    <class 'eth_utils.decorators.combomethod'>

  Networks

The Networks class provides methods to obtain network names and other metadata given a chain_id.

  network_from_chain_id(chain_id) -> Network

Returns the Network for the given chain_id int value.

    >>> from eth_utils import network
    >>> network.network_from_chain_id(1)
    Network(chain_id=1, name='Ethereum Mainnet', shortName='eth', symbol=<ChainId.ETH: 1>)
    >>> network.network_from_chain_id(2)
    Network(chain_id=2, name='Expanse Network', shortName='exp', symbol=<ChainId.EXP: 2>)
    >>> network.network_from_chain_id(100)
    Network(chain_id=100, name='Gnosis', shortName='gno', symbol=<ChainId.GNO: 100>)

  name_from_chain_id(chain_id) -> string

Returns the name of the Network with the given chain_id int value.

    >>> from eth_utils import network
    >>> network.name_from_chain_id(1)
    'Ethereum Mainnet'
    >>> network.name_from_chain_id(2)
    'Expanse Network'
    >>> network.name_from_chain_id(100)
    'Gnosis'

  short_name_from_chain_id(chain_id) -> string

Returns the short_name of the Network with the given chain_id int value.

    >>> from eth_utils import network
    >>> network.short_name_from_chain_id(1)
    'eth'
    >>> network.short_name_from_chain_id(2)
    'exp'
    >>> network.short_name_from_chain_id(100)
    'gno'

  Numeric Utils

  clamp(lower_bound, upper_bound, value) -> result

Returns value clamped within the inclusive range defined by [lower_bound, upper_bound]. The value can be any number type that supports < and > comparisons against the provided bounds.

    >>> from eth_utils import clamp
    >>> clamp(5, 7, 4)
    5
    >>> clamp(5, 7, 5)
    5
    >>> clamp(5, 7, 6)
    6
    >>> clamp(5, 7, 7)
    7
    >>> clamp(5, 7, 8)
    7

  Type Utils

  is_boolean(value) -> bool

Returns True if value is of type bool

    >>> from eth_utils import is_boolean
    >>> is_boolean(True)
    True
    >>> is_boolean(False)
    True
    >>> is_boolean(1)
    False

  is_bytes(value) -> bool

Returns True if value is a byte string or a byte array.

    >>> from eth_utils import is_bytes
    >>> is_bytes('abcd')
    False
    >>> is_bytes(b'abcd')
    True
    >>> is_bytes(bytearray((1, 2, 3)))
    True

  is_dict(value) -> bool

Returns True if value is a mapping type.

    >>> from eth_utils import is_dict
    >>> is_dict({'a': 1})
    True
    >>> is_dict([1, 2, 3])
    False

  is_integer(value) -> bool

Returns True if value is an integer

    >>> from eth_utils import is_integer
    >>> is_integer(0)
    True
    >>> is_integer(1)
    True
    >>> is_integer('1')
    False
    >>> is_integer(1.1)
    False

  is_list_like(value) -> bool

Returns True if value is a non-string sequence such as a sequence (such as a list or tuple).

    >>> from eth_utils import is_list_like
    >>> is_list_like('abcd')
    False
    >>> is_list_like([])
    True
    >>> is_list_like(tuple())
    True

  is_list(value) -> bool

Returns True if value is a non-string sequence such as a list.

    >>> from eth_utils import is_list
    >>> is_list('abcd')
    False
    >>> is_list([])
    True
    >>> is_list(tuple())
    False

  is_tuple(value) -> bool

Returns True if value is a non-string sequence such as a tuple.

    >>> from eth_utils import is_tuple
    >>> is_tuple('abcd')
    False
    >>> is_tuple([])
    False
    >>> is_tuple(tuple())
    True

  is_null(value) -> bool

Returns True if value is None

    >>> from eth_utils import is_null
    >>> is_null(None)
    True
    >>> is_null(False)
    False

  is_number(value) -> bool

Returns True if value is numeric

    >>> from eth_utils import is_number
    >>> is_number(1)
    True
    >>> is_number(1.1)
    True
    >>> is_number('1')
    False
    >>> from decimal import Decimal
    >>> is_number(Decimal('1'))
    True

  is_string(value) -> bool

Returns True if value is of any string type.

    >>> from eth_utils import is_string
    >>> is_string('abcd')
    True
    >>> is_string(b'abcd')
    True
    >>> is_string(bytearray((1, 2, 3)))
    True

  is_text(value) -> bool

Returns True if value is a text string.

    >>> from eth_utils import is_text
    >>> is_text(u'abcd')
    True
    >>> is_text(b'abcd')
    False
    >>> is_text(bytearray((1, 2, 3)))
    False

  Release Notes

Read up on all the latest improvements.

  eth-utils v5.3.1 (2025-08-27)

  Bugfixes

•   Loosen expectation in test_get_aligned_abi_inputs_raises_type_error_for_incorrect_input_types (#313 <https://github.com/ethereum/eth-utils/issues/313>)

  eth-utils v5.3.0 (2025-04-14)

  Bugfixes

•   Replace arg["name"] with arg.get("name") to correctly handle optional names. (#299 <https://github.com/ethereum/eth-utils/issues/299>)

  Features

•   Add new methods: to_wei_decimals, and from_wei_decimals which take a number instead of a string (#302 <https://github.com/ethereum/eth-utils/issues/302>)

•   Add CamelModel pydantic model for validating objects and serializing to camelCase when used with by_alias=True, with the general expectation of a well-formed JSON-RPC object. (#303 <https://github.com/ethereum/eth-utils/issues/303>)

  eth-utils v5.2.0 (2025-01-21)

  Bugfixes

•   Update types in is_same_address to accept AnyAddress, str, or bytes. (#289 <https://github.com/ethereum/eth-utils/issues/289>)

  Features

•   Add Python 3.13 support and other misc. template updates (#296 <https://github.com/ethereum/eth-utils/issues/296>)

  eth-utils v5.1.0 (2024-10-21)

  Bugfixes

•   Correct error message in from_wei and to_wei (#247 <https://github.com/ethereum/eth-utils/issues/247>)

•   Remove unused hexbytes dependency that is causing a cyclic dependency issue (#284 <https://github.com/ethereum/eth-utils/issues/284>)

  Features

•   Removed _BaseHasLogger and _BaseHasExtendedDebugLogger, and the logger attribute in the HasLogger and HasExtendedDebugLogger is type hinted directly. (#275 <https://github.com/ethereum/eth-utils/issues/275>)

•   Add new humanize_hexstr function (#285 <https://github.com/ethereum/eth-utils/issues/285>)

•   Add memoryview to accepted input type for to_hex , to_int , to_bytes , and to_text (#287 <https://github.com/ethereum/eth-utils/issues/287>)

  eth-utils v5.0.0 (2024-08-15)

  Internal Changes - for eth-utils Contributors

•   Run mypy locally via pre-commit hook, bump to mypy==1.10.0 (#282 <https://github.com/ethereum/eth-utils/issues/282>)

  eth-utils v5.0.0-beta.1 (2024-07-25)

  Breaking Changes

•   Updates to the latest eth-typing to use new ABI types for improved type checking in existing ABI utility functions. (#271 <https://github.com/ethereum/eth-utils/issues/271>)

  Features

•   Contract Application Binary Interface (ABI) utilities to obtain type and value information for functions and events. (#271 <https://github.com/ethereum/eth-utils/issues/271>)

  Internal Changes - for eth-utils Contributors

•   Merge template to use bump-my-version and update release Make commands. (#280 <https://github.com/ethereum/eth-utils/issues/280>)

  eth-utils v4.1.1 (2024-05-06)

  Features

•   Update networks for latest changes and testnets. (#276 <https://github.com/ethereum/eth-utils/issues/276>)

  Internal Changes - for eth-utils Contributors

•   Merge template updates, fixing docs CI and setting nightly CI runs for all testing (#272 <https://github.com/ethereum/eth-utils/issues/272>)

•   Updated eth_networks.json with latest networks. (#273 <https://github.com/ethereum/eth-utils/issues/273>)

•   No warning for outdated networks. (#278 <https://github.com/ethereum/eth-utils/issues/278>)

  eth-utils v4.1.0 (2024-04-01)

  Internal Changes - for eth-utils Contributors

•   Upgrades from the template with support for Python 3.12 and linting with blocklint. (#268 <https://github.com/ethereum/eth-utils/issues/268>)

•   Remove cached_property dependency, as it was only for <=py37 (#269 <https://github.com/ethereum/eth-utils/issues/269>)

  eth-utils v4.0.0 (2024-02-22)

  Breaking Changes

•   Web3.is_address now returns True for non-checksummed addresses. (#265 <https://github.com/ethereum/eth-utils/issues/265>)

  eth-utils v3.0.0 (2024-01-10)

  Breaking Changes

•   Drop python 3.7 support (#261 <https://github.com/ethereum/eth-utils/issues/261>)

  Internal Changes - for eth-utils Contributors

•   Merge updates from the project template, notably: use pre-commit for linting and change the name of the master branch to main (#261 <https://github.com/ethereum/eth-utils/issues/261>)

•   Correct booleans in pyproject.toml and add test for the presence of the eth_utils.__version__ attribute (#263 <https://github.com/ethereum/eth-utils/issues/263>)

  eth-utils v2.3.1 (2023-11-07)

  Bugfixes

•   Some users were experiencing encoding issues when parsing the networks json. Use UTF-8 explicitly. (#259 <https://github.com/ethereum/eth-utils/issues/259>)

  Internal Changes - for eth-utils Contributors

•   Fix and add new test cases for invalid Network chain_id values. (#256 <https://github.com/ethereum/eth-utils/issues/256>)

  Miscellaneous Changes

•   #259 <https://github.com/ethereum/eth-utils/issues/259>

  eth-utils v2.3.0 (2023-10-20)

  Features

•   Add Network utility methods to utilize network metadata for a given ChainId. (#253 <https://github.com/ethereum/eth-utils/issues/253>)

  eth-utils v2.2.2 (2023-10-11)

  Improved Documentation

•   Add information to docs for utilities which did not have any. (#254 <https://github.com/ethereum/eth-utils/issues/254>)

  Internal Changes - for eth-utils Contributors

•   Pull latest from template repo to fix release script, update wording in comments and docs. (#252 <https://github.com/ethereum/eth-utils/issues/252>)

  Miscellaneous Changes

•   #242 <https://github.com/ethereum/eth-utils/issues/242>

  eth-utils v2.2.1 (2023-09-13)

  Internal Changes - for eth-utils Contributors

•   Add build.os config for readthedocs (#250 <https://github.com/ethereum/eth-utils/issues/250>)

  eth-utils v2.2.0 (2023-07-10)

  Features

•   Added humanize_wei utility to convert common values to more readable units. (#194 <https://github.com/ethereum/eth-utils/issues/194>)

  eth-utils v2.1.1 (2023-06-07)

  Internal Changes - for eth-utils Contributors

•   Add currency tests with float ether inputs. (#231 <https://github.com/ethereum/eth-utils/issues/231>)

•   remove unused docs deps, bump version of remaining (#239 <https://github.com/ethereum/eth-utils/issues/239>)

•   merge updates from the python project template (#240 <https://github.com/ethereum/eth-utils/issues/240>)

  eth-utils v2.1.0 (2022-11-17)

  Features

•   Allow a wider eth-hash dependency range (#225 <https://github.com/ethereum/eth-utils/issues/225>)

  Performance improvements

•   Performance improvement of up to 65% on is_0x_prefixed (#223 <https://github.com/ethereum/eth-utils/issues/223>)

  Improved Documentation

•   Fix typo in documentation: hexidecimal -> hexadecimal (#222 <https://github.com/ethereum/eth-utils/issues/222>)

  Internal Changes - for eth-utils Contributors

•   Update use of @cached_property for debug2 logging. (#232 <https://github.com/ethereum/eth-utils/issues/232>)

  Miscellaneous changes

•   #226 <https://github.com/ethereum/eth-utils/issues/226>, #235 <https://github.com/ethereum/eth-utils/issues/235>

  Breaking changes

•   Remove support for Python 3.6, add Python 3.11, misc dev internal updates (#227 <https://github.com/ethereum/eth-utils/issues/227>)

  eth-utils v2.0.0 (2021-11-18)

  Features

•   Upgrade eth-typing to v3.0+, Add support for python 3.9 and 3.10 Remove support for python 3.5 (#215 <https://github.com/ethereum/eth-utils/issues/215>)

  eth-utils v1.10.0 (2021-01-21)

  Bugfixes

•   When a TypeError or ValueError is raised during apply_formatters_to_dict(), eth_utils appends some useful contextual information. It was trying to re-create the old exception, but that sometimes fails, like with a JSONDecodeError, which expects more arguments in the constructor. So now we raise a basic TypeError or ValueError. (#204 <https://github.com/ethereum/eth-utils/issues/204>)

•   Update the type signature of to_canonical_address(), to_checksum_address(), and to_normalized_address() to allow bytes-typed address input. (#205 <https://github.com/ethereum/eth-utils/issues/205>)

  Performance improvements

•   Significant speedup of is_hex() and is_hexstr(). (#202 <https://github.com/ethereum/eth-utils/issues/202>)

•   Significant speedup of is_address(). Running a test that abi-encodes an array of 10 addresses was about 67% faster. (#203 <https://github.com/ethereum/eth-utils/issues/203>)

  Internal Changes - for eth-utils Contributors

•   Upgrade eth-hash to v0.3.1, to use its exported type annotations instead of casting the results. (#208 <https://github.com/ethereum/eth-utils/issues/208>)

  Miscellaneous changes

•   #196 <https://github.com/ethereum/eth-utils/issues/196>

•   #207 <https://github.com/ethereum/eth-utils/issues/207>

  eth-utils v1.9.5 (2020-08-31)

  Bugfixes

•   Added a new type signature of apply_formatter_if to eth_utils curried module. Also added text_if_str and apply_formatters_to_dict. (#201 <https://github.com/ethereum/eth-utils/issues/201>)

  Misc

•   #201 <https://github.com/ethereum/eth-utils/issues/201>

  eth-utils v1.9.4 (2020-08-25)

  Bugfixes

•   Make sure all the eth_utils.curried methods are importable, plus a fix for curried typing of hexstr_if_str. (#156 <https://github.com/ethereum/eth-utils/issues/156>)

•   Pass context to new exception in replace_exceptions decorator. (#198 <https://github.com/ethereum/eth-utils/issues/198>)

•   Ensure pickling/unpickling an ExtendedDebugLogger always gives back an ExtendedDebugLogger. (#199 <https://github.com/ethereum/eth-utils/issues/199>)

  eth-utils v1.9.0 (2020-05-11)

  Features

•   Add is_hexstr as preferred method of checking if a given value is a hex string. (#137 <https://github.com/ethereum/eth-utils/issues/137>)

•   Improve performance of is_hex and is_hexstr by up to 40x (#185 <https://github.com/ethereum/eth-utils/issues/185>)

•   Add humanize_integer_sequence utility. (#188 <https://github.com/ethereum/eth-utils/issues/188>)

•   Add humanize_bytes utility. (#189 <https://github.com/ethereum/eth-utils/issues/189>)

  Bugfixes

•   Silence a deprecation error by importing from collections.abc, instead of collections. (#186 <https://github.com/ethereum/eth-utils/issues/186>)

  eth-utils 1.8.4 (2019-12-05)

  Bugfixes

•   Add missing asterisk to MANIFEST.in (#182 <https://github.com/ethereum/eth-utils/issues/182>)

  eth-utils 1.8.3 (2019-12-04)

  Misc

•   #181 <https://github.com/ethereum/eth-utils/issues/181>

  eth-utils 1.8.2 (2019-12-04)

  Misc

•   #177 <https://github.com/ethereum/eth-utils/issues/177>, #180 <https://github.com/ethereum/eth-utils/issues/180>

  eth-utils 1.8.1 (2019-11-20)

No significant changes.

  eth-utils 1.8.0-0.1 (2019-11-20)

  Misc

•   #175 <https://github.com/ethereum/eth-utils/issues/175>

  eth-utils 1.8.0 (2019-11-04)

  Features

•   Add support for python3.8 (#174 <https://github.com/ethereum/eth-utils/issues/174>)

  eth-utils 1.7.0 (2019-09-05)

  Features

•   Expose DEBUG2 log level as top level module import (#117 <https://github.com/ethereum/eth-utils/issues/117>)

•   Add get_logger and get_extended_debug_logger utils (#170 <https://github.com/ethereum/eth-utils/issues/170>)

  Improved Documentation

•   Setup towncrier to improve the quality of the release notes (#172 <https://github.com/ethereum/eth-utils/issues/172>)

  v1.6.4

Released: August 5, 2019

•   Feature

•   Caching for ExtendedDebugLogger.show_debug2 property - #167 <https://github.com/ethereum/eth-utils/pull/167>

  v1.6.3

Released: August 5, 2019

•   Feature

•   Add support for Python3.7 - #165 <https://github.com/ethereum/eth-utils/pull/165>

•   Bugfix

•   Fix HasLogger compatibility with other metaclasses. - #165 <https://github.com/ethereum/eth-utils/pull/165>

  v1.6.2

Released: July 24, 2019

•   Feature

•   Add support for Python3.7 - #165 <https://github.com/ethereum/eth-utils/pull/165>

•   Add humanize_ipfs_uri. - #162 <https://github.com/ethereum/eth-utils/pull/162>

•   Bugfix

•   Fix typing of clamp numeric utility. - #164 <https://github.com/ethereum/eth-utils/pull/164>

  v1.6.1

Released: June 11, 2019

•   Maintenance

•   Use eth-typing types instead of eth-utils types, when available - #163 <https://github.com/ethereum/eth-utils/pull/163>

  v1.6.0

Released: May 16, 2019

•   Feature

•   Add logging utilities HasLogger, ExtendedDebugLogger, HasExtendedDebugLogger and setup_DEBUG2_logging - #158 <https://github.com/ethereum/eth-utils/pull/158>

  v1.5.2

Released: April 30, 2019

•   Bugfix

•   Fix eth_utils.currency.denom to be a real class with proper type declarations. - #154 <https://github.com/ethereum/eth-utils/pull/154>

•   Fix eth_utils.functional.replace_exceptions type declarations. - #155 <https://github.com/ethereum/eth-utils/pull/155>

•   Feature

•   Add new eth_utils.clamp - #150 <https://github.com/ethereum/eth-utils/pull/150>

  v1.5.1

Released: April 17, 2019

•   Bugfix

•   Fix type declarations for eth_utils.functional.to_dict and eth_utils.funcional.to_ordered_dict - #151 <https://github.com/ethereum/eth-utils/pull/151>

  v1.5.0

Released: April 16, 2019

•   Features

•   Add new eth_utils.humanize.humanize_seconds and eth_utils.humanize.humanize_hash. - #149 <https://github.com/ethereum/eth-utils/pull/149>

•   Enable PEP561 type hints

  v1.4.1

Released: Dec 18, 2018

•   Bugfixes

•   Fixed eth_utils.abi.collapse_if_tuple not handling fixed-size tuple arrays.

  v1.4.0

Released: Dec 6, 2018

•   Features

•   Support tuples in eth_utils.abi.function_abi_to_4byte_selector and a new eth_utils.abi.collapse_if_tuple - #141 <https://github.com/ethereum/eth-utils/pull/141>

  v1.3.0

•   Misc

•   Fix linting issues

  v1.3.0-beta.0

•   Misc

•   Use eth-typing v2.0.0, which may be a breaking change for downstream packages

  v1.2.2

•   Bugfixes

•   Prevent from installing with Python 3.5.2 which has a fatal bug when ... is used in a type. - #125 <https://github.com/ethereum/eth-utils/issues/125>

•   Misc

•   Start using black for style checking. - #129 <https://github.com/ethereum/eth-utils/pulls/129>

  1.2.1

•   Move docs to RTD/Sphinx, with doctest

•   Update eth-typing dependency to 1.3.0

  1.2.0

•   Import more resources from implementation-specific "toolz" library in "toolz" wrapper module

  1.1.2

•   Update eth-typing dependency

  1.1.1

•   Add ValidationError exception

  1.1.0

•   Add abi and address type hints

•   Add typehints to more modules

•   Add replace_exceptions decorator to decorators.py

•   Add type hints to applicators module

•   Add type hints to conversions module

•   Add import_string util from django

•   Add conditional cytoolz or toolz install based on python implementation

  1.0.3

•   Reject str as a primitive in to_hex()

•   Faster int_to_big_endian implementation

  1.0.2

•   Update apply key map to catch conflicting keys

•   Add validation of 19 byte address

•   Support bytearrays in conversion functions

•   Apply formatters to sequence

  1.0.1

•   Add autouse fixture to print warnings

•   Change hexidecimal -> hexadecimal

•   Strictly accept text types for decode_hex

•   Remove remaining force_* utils

  0.8.1

•   Convert formatting from force

•   Backport pr45 into v0

•   Write validate conversion arguments decorator

•   Update hex and int conversions to work with new decorator

•   Deprecate force bytes/text & formatting utils

  0.8.0

•   Swap in eth-hash for pysha3

•   Convert keccak from force_bytes

•   Convert address utils from force text/bytes

•   Import many of the application functions from web3.py

•   Add @combomethod decorator

•   Add tool to generate environment info

•   Add type conversion helpers

•   Convert precision to localcontext

•   Remove unnecessary future imports

•   Drop support for py27

  0.7.4

•   Constrain dependencies to major version

  0.7.3

•   Support for python 3.6

  0.7.2

•   Minor fix for how __version__ is computed in the eth_utils module.

  0.7.1

•   Futzing with PyPi formatting of README info.

  0.7.0

•   Rename library on pypi to eth_utils

  0.6.0

•   Bugfix for to_wei to handle floating point inputs in a manner consistent with what users would expect.

  0.5.1

•   Bugfix for is_hex to prevent exceptions from being raised for non-hexadecimal inputs.

  0.5.0

•   is_hex now supports both empty string as 0x and odd length hexadecimal strings.

  0.4.1

•   Bugfix for currency conversions which retained too high a precision.

  0.4.0

•   is_address will now verify the checksum on any address which passes the is_checksum_formatted_address check.

  0.3.2

•   Added is_hex.

  0.3.1

•   Added big_endian_to_int and int_to_big_endian.

  0.3.0

•   Deprecate compose

•   Bugfix for is_0x_prefixed to correctly detect uppercase X as part of the prefix.

•   Added is_hex_address

•   Added is_binary_address

•   Added is_32byte_address

•   Added is_checksum_formatted_address

•   Added apply_to_return_value

•   Added to_set

•   Added is_list

•   Added is_tuple

  0.2.1

•   Strip whitespace from event signatures in event_signature_to_log_topic

  0.2.1

•   Strip whitespace from event signatures in function_signature_to_4byte_selector

  0.2.0

Initial release

  Contributing

Thank you for your interest in contributing! We welcome all contributions no matter their size. Please read along to learn how to get started. If you get stuck, feel free to ask for help in Ethereum Python Discord server <https://discord.gg/GHryRvPB84>.

  Setting the stage

To get started, fork the repository to your own github account, then clone it to your development machine:

    git clone git@github.com:your-github-username/eth-utils.git

Next, install the development dependencies. We recommend using a virtual environment, such as virtualenv <https://virtualenv.pypa.io/en/stable/>.

    cd eth-utils
    virtualenv -p python venv
    . venv/bin/activate
    python -m pip install -e ".[dev]"
    pre-commit install

  Running the tests

A great way to explore the code base is to run the tests.

We can run all tests with:

    pytest tests

  Code Style

We use pre-commit <https://pre-commit.com/> to enforce a consistent code style across the library. This tool runs automatically with every commit, but you can also run it manually with:

    make lint

If you need to make a commit that skips the pre-commit checks, you can do so with git commit --no-verify.

This library uses type hints, which are enforced by the mypy tool (part of the pre-commit checks). All new code is required to land with type hints, with the exception of code within the tests/core directory. Note that the mypy checks are also run against files within the tests/mypy directory.

  Documentation

Good documentation will lead to quicker adoption and happier users. Please check out our guide on how to create documentation for the Python Ethereum ecosystem <https://github.com/ethereum/snake-charmers-tactical-manual/blob/main/documentation.md>.

  Pull Requests

It's a good idea to make pull requests early on. A pull request represents the start of a discussion, and doesn't necessarily need to be the final, finished submission.

GitHub's documentation for working on pull requests is available here <https://docs.github.com/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/about-pull-requests>.

Once you've made a pull request, take a look at the Circle CI build status in the GitHub interface and make sure all tests are passing. In general pull requests that do not pass the CI build yet won't get reviewed unless explicitly requested.

If the pull request introduces changes that should be reflected in the release notes, please add a newsfragment file as explained here <https://github.com/ethereum/eth-utils/blob/main/newsfragments/README.md>.

If possible, the change to the release notes file should be included in the commit that introduces the feature or bugfix.

  Releasing

Releases are typically done from the main branch, except when releasing a beta (in which case the beta is released from main, and the previous stable branch is released from said branch).

  Final test before each release

Before releasing a new version, build and test the package that will be released:

    git checkout main && git pull
    make package-test

This will build the package and install it in a temporary virtual environment. Follow the instructions to activate the venv and test whatever you think is important.

You can also preview the release notes:

    towncrier --draft

  Build the release notes

Before bumping the version number, build the release notes. You must include the part of the version to bump (see below), which changes how the version number will show in the release notes.

    make notes bump=$$VERSION_PART_TO_BUMP$$

If there are any errors, be sure to re-run make notes until it works.

  Push the release to github & pypi

After confirming that the release package looks okay, release a new version:

    make release bump=$$VERSION_PART_TO_BUMP$$

This command will:

•   Bump the version number as specified in .pyproject.toml and setup.py.

•   Create a git commit and tag for the new version.

•   Build the package.

•   Push the commit and tag to github.

•   Push the new package files to pypi.

  Which version part to bump

$$VERSION_PART_TO_BUMP$$ must be one of: major, minor, patch, stage, or devnum.

The version format for this repo is {major}.{minor}.{patch} for stable, and {major}.{minor}.{patch}-{stage}.{devnum} for unstable (stage can be alpha or beta).

If you are in a beta version, make release bump=stage will switch to a stable.

To issue an unstable version when the current version is stable, specify the new version explicitly, like make release bump="--new-version 4.0.0-alpha.1"

You can see what the result of bumping any particular version part would be with bump-my-version show-bump

  Code of Conduct

  Our Pledge

In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, religion, or sexual identity and orientation.

  Our Standards

Examples of behavior that contributes to creating a positive environment include:

•   Using welcoming and inclusive language

•   Being respectful of differing viewpoints and experiences

•   Gracefully accepting constructive criticism

•   Focusing on what is best for the community

•   Showing empathy towards other community members

    Examples of unacceptable behavior by participants include:

•   The use of sexualized language or imagery and unwelcome sexual attention or advances

•   Trolling, insulting/derogatory comments, and personal or political attacks

•   Public or private harassment

•   Publishing others' private information, such as a physical or electronic address, without explicit permission

•   Other conduct which could reasonably be considered inappropriate in a professional setting

  Our Responsibilities

Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.

Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.

  Scope

This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.

  Enforcement

Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at <snakecharmers@ethereum.org>. All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.

Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.

  Attribution

This Code of Conduct is adapted from the Contributor Covenant <https://www.contributor-covenant.org>, version 1.4, available at <https://www.contributor-covenant.org/version/1/4/code-of-conduct.html>

Author
The Ethereum Foundation

Copyright
2017-2023 The Ethereum Foundation