Skip to main content

Decoded ShredStream — Python client

Python client for the Decoded ShredStream of ShredStream.com: pre-execution Solana transactions, decoded from shreds — the serialized VersionedTransaction, its signatures and its slot, delivered over gRPC or UDP push the moment they propagate.

Before execution — transactions carry no status, logs, balance changes or inner instructions, and some will fail on-chain. Use a post-execution source to confirm.

The client is synchronous and blocking: iterating it returns one transaction at a time on the calling thread.

pip install decoded-shredstream
from decoded_shredstream import Client, Filter, GrpcConfig

with Client.grpc(GrpcConfig(endpoint=endpoint, token=token,
                            filters={"all": Filter()})) as client:
    for update in client:
        print(update.slot, update.signature)

Requirements — Python 3.10 or later, and a Decoded ShredStream subscription on ShredStream.com. Extras: solana for parse(), fast for a Rust base58.

With the extras:

pip install "decoded-shredstream[solana,fast]"

🔑 Access

Decoded ShredStream is a subscription product, available from ShredStream.com. One subscription covers both transports, and you can move from one to the other whenever you need to.

  • gRPC — you receive an endpoint and an access token. Use the endpoint exactly as issued.
  • UDP — you register your server's IP and port; datagrams are pushed to it.

Choosing a transport

Both carry the same data; they differ on what the protocol guarantees.

gRPC UDP
Latency higher lowest
Delivery ordered, retransmitted best-effort, no retransmission
Server-side filters yes no — you receive the full stream

⚡ Quickstart — gRPC

from decoded_shredstream import Client, Filter, GrpcConfig

with Client.grpc(
    GrpcConfig(
        endpoint="your-endpoint.shredstream.com:PORT",
        token="YOUR_TOKEN",
        filters={"all": Filter()},
    )
) as client:
    for update in client:
        print(update.slot, len(update.data), list(update.filters))

Client.grpc connects and subscribes before returning.

📡 Quickstart — UDP

from decoded_shredstream import Client, UdpConfig

with Client.udp(UdpConfig(port=8002)) as client:
    print("listening on", client.local_addr)
    for update in client:
        print(update.slot, len(update.data), update.signature.hex())

8002 is only an example: bind whichever port you registered in your account.

🔍 Transaction parsing

Every transaction exposes update.data, in the standard Solana wire format, and its signatures without any decoding:

import base58

update.signature                              # first signature, raw 64 bytes
update.signatures                             # every signature
base58.b58encode(update.signature).decode()   # to display one

Everything else is available through parse(), which returns a solders.transaction.VersionedTransaction and requires the solana extra:

for update in client:
    message = update.parse().message
    keys = message.account_keys
    programs = {str(keys[ix.program_id_index]) for ix in message.instructions}
    print(update.slot, keys[0], len(message.instructions), sorted(programs))

Without the solana extra, parse() raises ImportError.

🎯 Filters

Filters exist on the gRPC transport only. They are evaluated by the server; the client never filters locally. UDP delivers the full stream.

A subscription carries a map of named filters. Each response is tagged with the names that matched it, exposed as update.filters.

from decoded_shredstream import Client, Filter, GrpcConfig

client = Client.grpc(
    GrpcConfig(
        endpoint=endpoint,
        token=token,
        filters={
            "watched": Filter(include=[account]),
            "everything": Filter(),
        },
    )
)

Semantics

A Filter holds three lists of base58 account keys, matched against the accounts a transaction touches. The three conditions are ANDed, and an empty list adds no constraint — Filter() matches every transaction.

List Matches when the transaction
include touches at least one of the accounts
exclude touches none of the accounts
required touches all of the accounts

Matching uses the account keys carried in the transaction, signers included. Addresses resolved through an Address Lookup Table cannot be filtered on. A transaction matching several filters is delivered once.

Replacing filters mid-stream

update_filters replaces the whole map atomically. The server applies it without a reconnect and without a gap in the data, and the new map is the one any later reconnection re-sends.

client.update_filters({"watched": Filter(include=[account])})

🔄 Errors & reconnection

Recoverable interruptions never reach you: the client reconnects on its own and re-sends the current filter map. Only a refused token, a session closed by the server and a rejected filter map end the stream, raised once by the iteration:

from decoded_shredstream import StreamError

try:
    for update in client:
        ...
except StreamError as e:
    print("stream ended:", e)

Every exception, the backoff policy and the telemetry notices are in docs/errors.md.

📖 Documentation

This README is what you need to receive transactions. The rest lives beside it:

Document Contents
docs/api.md Every type and method: clients, configuration, filters, updates, UDP codec, performance notes and counters
docs/errors.md Error types, reconnection policy, telemetry notices

💡 Examples

The examples/ directory contains runnable programs; each reads its configuration from the environment.

File Shows
udp_quickstart.py binding the registered port and printing transactions
grpc_quickstart.py connecting, subscribing to everything, printing transactions
grpc_filters.py named filters and replacing the map mid-stream
parse_transaction.py full parsing with solders
raw_bytes_pipeline.py forwarding update.data without parsing
low_latency.py the shape of a minimal consumption loop
DECODED_SHREDSTREAM_UDP_PORT=8002 python examples/udp_quickstart.py
DECODED_SHREDSTREAM_ENDPOINT=your-endpoint.shredstream.com:PORT DECODED_SHREDSTREAM_TOKEN=... python examples/grpc_quickstart.py
DECODED_SHREDSTREAM_ENDPOINT=your-endpoint.shredstream.com:PORT DECODED_SHREDSTREAM_TOKEN=... ACCOUNT=<base58> python examples/grpc_filters.py

⚖️ License

Apache-2.0. See LICENSE.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

decoded_shredstream-0.1.0.tar.gz (26.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

decoded_shredstream-0.1.0-py3-none-any.whl (28.0 kB view details)

Uploaded Python 3

File details

Details for the file decoded_shredstream-0.1.0.tar.gz.

File metadata

  • Download URL: decoded_shredstream-0.1.0.tar.gz
  • Upload date:
  • Size: 26.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.13.9

File hashes

Hashes for decoded_shredstream-0.1.0.tar.gz
Algorithm Hash digest
SHA256 f5b980f0135060b48445b58b542e5babeba5f857404fe37ccf509ccf95c55402
MD5 62cd69bc1a84817c95b2f70e05204105
BLAKE2b-256 0e14bf2e5acdfb3c875d411580199e607b073c2d01e17d516d864bf1fe341b22

See more details on using hashes here.

File details

Details for the file decoded_shredstream-0.1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for decoded_shredstream-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 92e8d7cd6d285282ededdb0e78a30a7acd0b14e9765643ff8f030293c191500b
MD5 138fe4aae23c235454268ac6becf4e07
BLAKE2b-256 06c0ea397496ca56244d064e939e5f13706ccd091089e3b0a98b81b398c814dc

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 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