- Feeds — subscribe to MoQT feed tracks with the raw MoQT client,
@clutchcall/sdk/moqt(MoqtClient). - Transactions — deliver a signed tx to the BDN over the HTTP/3 submit
API (
/bdn/submitand/tpu), callable from any HTTP/3 client.
A typed
Crypto class that wraps both surfaces is a Preview — see
Preview: the typed Crypto surface at the
bottom. Don’t build against it as a shipping API.Subscribe to feeds with the MoQT client
A feed is an ordinary MoQT frame track, so you subscribe with the sameMoqtClient the rest of the platform uses. Import it from the moqt subpath.
- TypeScript
- Python
connect returns immediately and dials in the background. The client
auto-reconnects with capped backoff and replays every subscription on
reconnect, so a feed consumer survives a relay flap without re-subscribing.
MoqtClient.connect
The feed relay, e.g.
quic://feeds.clutchcall.dev. The QUIC port is discovered
from the host’s DNS HTTPS record.Bearer token for the feed scope. Required for private (
sol/feed/<orgId>/…)
tracks; the public mainnet feed may be open.Lifecycle callback.
ConnectionState is one of Connecting, Connected,
Reconnecting, Closed, Failed.{ token?, serverCertificateHash?, webTransport? }. Pass
serverCertificateHash when pinning a self-signed dev cert.Promise<MoqtClient> — resolves once the first session is up.
client.subscribeFrame(ns, name, onFrame)
Subscribe to a feed track. The namespace and name together address the track
(sol/feed/mainnet + slots).
Track namespace, e.g.
sol/feed/mainnet (public) or sol/feed/<orgId>
(private).Track name within the namespace:
slots, blockhash, or priorityFee.Called for every object the relay fans out.
data is the raw frame payload —
decode it as the feed’s JSON or binary schema.Optional MoQT filter — defaults to “largest object” (live tail). Pass a
start/end window to replay from a point in the durable origin.
FrameSubscription. Call .close() to unsubscribe.
- TypeScript
- Python
Other MoqtClient members you’ll use here
| Member | Purpose |
|---|---|
subscribeFrame(ns, name, onFrame) / subscribe_frame(...) | Subscribe to a feed track (above). |
subscribeObject(ns, name, onObject) / subscribe_object(...) | Subscribe to a raw object track (verbatim payload, no frame header) — for a custom binary feed. |
close() | Tear down the session and every subscription. |
publishFrame exists on MoqtClient too, but you don’t publish feed tracks
— the BDN ingest does. Your ingest endpoint (public RPC or your own
gossip/Geyser) is configured server-side; you only ever subscribe.Deliver a transaction (HTTP/3 submit API)
There is no typed submit method yet — deliver the signed tx over HTTP/3 with the raw bytes as the body. Both routes acceptapplication/octet-stream.
Fan-out. Query
leader=auto (resolve schedule) or leader=<host>:<port>.
Ingests once, dedups on the 64-byte signature, fans across all edges; each edge
lands on its nearby leaders. Returns the signature on success.Direct. Query
host=auto or host=<validator-host>&port=<quic-port>. Sends
straight to the current + next leader TPU from this node, no fan-out.Submit query parameters
auto resolves the leader schedule; or <host>:<port> to pin a validator TPU.auto resolves the leader schedule; or an explicit validator host. Pair with
port=<quic-port> when explicit.ALPN solana-tpu) with an ephemeral ed25519 client identity per connection.
Events & lifecycle
The feed surface is event-driven through the MoQT callbacks:| Source | Event | When |
|---|---|---|
onState | Connecting / Connected / Reconnecting / Closed / Failed | Session lifecycle; tracks re-subscribe automatically on Connected. |
onFrame | per feed object | Every slot / blockhash / fee update the relay fans out. |
FrameSubscription.close() | — | Unsubscribe a single feed track. |
MoqtClient.close() | — | Tear down everything. |
Preview: the typed Crypto surface
A typedCrypto client would wrap feed subscription and tx delivery behind one
handle, so you don’t hand-roll subscribeFrame calls or fetch bodies:

