Skip to content

Latest commit

 

History

2 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

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.

About

Official Python client for Decoded ShredStream by ShredStream.com — pre-execution Solana transactions decoded from shreds, over UDP push or gRPC.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages