Skip to main content

eth-listener

eth-listener is a tiny helper library that wraps Ethereum JSON-RPC websocket subscriptions with a synchronous, callback-based interface. Under the hood it drives a lean asyncio websocket client (built on top of websockets) and keeps your callbacks running on dedicated worker threads, letting you interact with Ethereum events using a simple .on(event, callback) pattern that feels familiar to JavaScript developers.

Features

  • Connect to any Ethereum node that exposes a websocket JSON-RPC endpoint
  • Strongly typed callback payloads for common subscriptions such as newHeads and newPendingTransactions
  • Automatic reconnection with stored subscription state
  • Callbacks run in a dedicated worker pool so they never block the websocket
  • Simple synchronous API: no need to manage event loops yourself
  • Works with any JSON-RPC node that speaks standard websocket subscriptions

Installation

pip install eth-listener

Python 3.9 or newer is required.

Quickstart

import argparse
import json
import logging
import time

from eth_listener import EthListener, NewHeadEvent

# Replace with your node's websocket endpoint
WS_URL = "wss://mainnet.infura.io/ws/v3/<your-project-id>"

def main() -> None:
    parser = argparse.ArgumentParser()
    parser.add_argument("--dump-raw", action="store_true")
    parser.add_argument("--dump-messages", action="store_true")
    parser.add_argument("--transport-debug", action="store_true")
    parser.add_argument("--debug", action="store_true")
    args = parser.parse_args()

    logging.basicConfig(level=logging.INFO, format="[%(levelname)s] %(message)s")
    logging.getLogger("websockets").setLevel(
        logging.DEBUG if args.transport_debug else logging.WARNING
    )
    if args.debug or args.dump_messages:
        logging.getLogger("eth_listener").setLevel(logging.DEBUG)

    listener = EthListener(WS_URL, start_timeout=0)

    def handle_new_head(event: NewHeadEvent) -> None:
        print(f"New block {event.number} with hash {event.hash}")
        if args.dump_raw:
            print(json.dumps(event.raw, indent=2))

    def print_message(raw: str) -> None:
        try:
            parsed = json.loads(raw)
        except json.JSONDecodeError:
            print(raw)
        else:
            print(json.dumps(parsed, indent=2))

    if args.dump_messages:
        listener.add_raw_message_listener(print_message)

    with listener:
        listener.start(timeout=0)
        listener.on("newHeads", handle_new_head)

        # Keep your application alive while callbacks run on background threads
        try:
            while True:
                time.sleep(1)
        except KeyboardInterrupt:
            pass
        finally:
            if args.dump_messages:
                listener.remove_raw_message_listener(print_message)


if __name__ == "__main__":
    main()

Unsubscribing

Every call to :meth:EthListener.on returns a :class:~eth_listener.SubscriptionHandle. Use it to stop listening when you no longer need the events:

handle = listener.on("newHeads", handle_new_head)
...
handle.unsubscribe()  # Removes the callback and issues eth_unsubscribe

Stopping the listener (via :meth:stop, the context manager, or object finalisation) also unsubscribes from any remaining topics.

Event payloads

The library ships with typed payloads for common subscriptions:

  • :class:~eth_listener.NewHeadEvent for newHeads
  • :class:~eth_listener.NewPendingTransactionEvent for newPendingTransactions

Each payload preserves the original JSON data in the raw attribute while also exposing more convenient Pythonic fields (for example block numbers are converted to integers).

Unknown subscriptions are delivered as the base :class:~eth_listener.BaseEthereumEvent, letting you inspect the raw payload and build your own helper classes when needed.

Development

pip install -e .[dev]
pytest

Pull requests and issues are very welcome!

Metadata

Release files for eth-listener 0.1.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for eth-listener 0.1.1
File Size Uploaded
eth_listener-0.1.1.tar.gz 9.4 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for eth-listener 0.1.1
File Interpreter ABI Platform
eth_listener-0.1.1-py3-none-any.whl Python 3 none any Details

Total release size: 20.4 kB

Release files / eth_listener-0.1.1.tar.gz

Download URL eth_listener-0.1.1.tar.gz
Size 9.4 kB
Tags Source
SHA-256 checksum
How to use checksums
e2b56937da449adfd80a8ff933f7fb1f4bc5ff021243cb6bf2b8aa45da986eb4
BLAKE2b-256 checksum
How to use checksums
b01f5374293fdf0248df196ee78cab3b59000901f81f77f8952be92b10f465f3
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.13.2

Release files / eth_listener-0.1.1-py3-none-any.whl

Download URL eth_listener-0.1.1-py3-none-any.whl
Size 11.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
d83ace45ca293a5b28b53474e352a4b26a7824b9636576ecf9aeedf2bc32a87b
BLAKE2b-256 checksum
How to use checksums
ece030a430d24648aa9383c65ba05282616f7df03f8968676b360aa43fea2450
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.13.2

Release history Release notifications | RSS feed

This release

0.1.1 This release

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page