Skip to content

Repository files navigation

electrum-client

Async Python client for the Electrum protocol (JSON-RPC 2.0 over TCP/SSL, newline-delimited), plus higher-level helpers for tracking onchain addresses, transactions, and blocks.

  • Request/response correlation by id, subscription dispatch, automatic keepalive pings
  • server.version handshake sent automatically on connect, as required by the spec
  • Response payloads parsed into typed pydantic models
  • Raw transaction / block header parsing (via embit)
  • Reconnecting trackers for address balances/history, single transactions, and new blocks

Install

pip install electrum-client

Usage

import asyncio
from electrum_client import ElectrumClient

async def main():
    async with ElectrumClient("ssl://electrum.blockstream.info:50002") as client:
        print(await client.get_height())
        print(await client.server_banner())

asyncio.run(main())

Scripthashes and balances

from electrum_client import ElectrumClient, scripthash_from_address

async with ElectrumClient("ssl://electrum.blockstream.info:50002") as client:
    scripthash = scripthash_from_address("bc1q...")
    balance = await client.get_balance(scripthash)
    history = await client.get_history(scripthash)
    utxos = await client.listunspent(scripthash)

Subscriptions

def on_change(params):
    print("scripthash status changed:", params)

async with ElectrumClient("ssl://electrum.blockstream.info:50002") as client:
    await client.subscribe_scripthash(scripthash, callback=on_change)
    await asyncio.sleep(60)  # keep the connection open to receive notifications

Trackers

AddressTracker, TransactionTracker, and BlockTracker wrap a reconnecting ElectrumClient connection and dispatch typed events (OnchainAddressEvent, OnchainTxEvent, BlockInfo) to an async callback — useful for driving websockets or other push-based consumers.

from electrum_client import AddressTracker

tracker = AddressTracker("ssl://electrum.blockstream.info:50002")
tracker.add("bc1q...")

async def on_event(event):
    print(event.address, event.confirmed, event.unconfirmed)

await tracker.run(callback=on_event, is_active=lambda: True)

Parsing helpers

from electrum_client import parse_raw_tx, parse_block_header

tx = parse_raw_tx(raw_tx_hex)
header = parse_block_header(header_hex, height)

Development

Requires uv.

uv sync
make format   # black + ruff --fix
make check    # black --check, ruff check, mypy
make test     # unit tests

Regtest integration tests

The regtest suite runs the client against bitcoind in Docker, indexed by two independent Electrum servers so the client is exercised against more than one implementation:

  • electrs (electrs-esplora) — fast, but doesn't implement server.features or blockchain.scripthash.get_mempool
  • fulcrum — fully spec-compliant, used to cover the protocol paths electrs can't (see tests/regtest/test_fulcrum.py)
make regtest-up
uv run pytest tests/regtest
make regtest-down

License

MIT

About

Python Electrum API compatible client

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Contributors

Languages