npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

decoded-shredstream

v0.1.1

Published

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

Readme

Decoded ShredStream — TypeScript / Node client

TypeScript 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.

npm install decoded-shredstream
import { DecodedShredStream, FilterAll } from "decoded-shredstream";

const client = await DecodedShredStream.grpc({ endpoint, token, filters: { all: FilterAll } });

for await (const tx of client.transactions()) {
  console.log(tx.slot, tx.signature.toBase58());
}

Requirements — Node.js 20 or later, and a Decoded ShredStream subscription on ShredStream.com.

🔑 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

import { DecodedShredStream, FilterAll } from "decoded-shredstream";

const client = await DecodedShredStream.grpc({
  endpoint: "your-endpoint.shredstream.com:PORT",
  token: process.env.DECODED_SHREDSTREAM_TOKEN!,
  filters: { all: FilterAll },
});

for await (const tx of client.transactions()) {
  console.log(`slot=${tx.slot} sig=${tx.signature.toBase58()} ${tx.bytes.length} bytes`);
}

DecodedShredStream.grpc() opens the stream and subscribes before it resolves.

📡 Quickstart — UDP

import { DecodedShredStream } from "decoded-shredstream";

const client = await DecodedShredStream.udp({ port: 8002 });
console.log(`listening on ${client.localAddr}`);

client.on("transaction", (tx) => {
  console.log(`slot=${tx.slot} sig=${tx.signature.toBase58()} ${tx.bytes.length} bytes`);
});

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

🔍 Transaction parsing

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

tx.signature.toBase58();                // fee payer signature
tx.signatures.map((s) => s.toBase58()); // every signature

Everything else is available through parse():

client.on("transaction", (tx) => {
  const { message } = tx.parse();

  message.version;              // 0, or "legacy"
  message.staticAccounts;       // Pubkey[]
  message.lifetimeToken;        // recent blockhash, or a durable nonce
  message.instructions;         // { programAddressIndex, accountIndices, data }
  message.addressTableLookups;  // versioned messages only

  for (const ix of message.instructions) {
    const program = message.staticAccounts[ix.programAddressIndex]!;
    console.log(program.toBase58(), ix.data.length, "bytes of payload");
  }
});

🎯 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 filter has three optional lists of base58 account addresses, combined with a logical AND:

| list | semantics | |---|---| | include | the transaction touches at least one of these accounts | | exclude | the transaction touches none of these accounts | | required | the transaction touches all of these accounts |

Matching uses the account keys carried in the transaction, signers included. Addresses resolved through a lookup table cannot be filtered on.

An omitted or empty list is not a constraint, so a filter with no list at all matches every transaction. FilterAll is exactly that filter:

import { DecodedShredStream, FilterAll } from "decoded-shredstream";

const client = await DecodedShredStream.grpc({
  endpoint,
  token,
  filters: {
    "watched-wallet": { include: [wallet] },
    "amm-only": { required: [ammProgram], exclude: [blockedAccount] },
    everything: FilterAll,
  },
});

Every update reports which filters matched it, and a transaction matching several named filters is delivered once:

client.on("transaction", (tx) => {
  if (tx.filters.includes("watched-wallet")) { /* … */ }
});

The whole map is replaced on a live stream, atomically and without a gap in the data:

await client.updateFilters({ "watched-wallet": { include: [wallet] } });

The new map is also the one re-sent by any later reconnection.

🔄 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, once, through error:

client.on("error", (err) => {
  console.error(`${err.name}: ${err.message}`);
});

Every error class, 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 holds runnable programs. Run them with tsx:

DECODED_SHREDSTREAM_UDP_PORT=8002 npx tsx examples/udp_quickstart.ts
DECODED_SHREDSTREAM_ENDPOINT=your-endpoint.shredstream.com:PORT DECODED_SHREDSTREAM_TOKEN=... npx tsx examples/grpc_quickstart.ts

| example | shows | |---|---| | udp_quickstart | binding the port and printing transactions | | grpc_quickstart | connecting, subscribing to everything, iterating | | grpc_filters | named filters and replacing the map on a live stream | | parse_transaction | cheap accessors first, then parse() for the message | | raw_bytes_pipeline | forwarding raw bytes as NDJSON without decoding | | low_latency | synchronous handlers and receive buffer sizing |

⚖️ License

Apache-2.0. See LICENSE.