Preconfs
Pre-shred serialized VersionedTransaction bytes from connected leaders
Preconfs delivers already-included Solana transactions from connected leaders before raw shreds are emitted.
It uses the same gRPC service and serialized VersionedTransaction payload as Binary, with a dedicated shreder_preconf.proto. The proto adds a preconf source selector to each subscription filter and a preconf source marker to each update.
Set preconf: true to receive only transactions from the preconf ingest path. This does not merge preconfs with shred-derived Binary updates: false or an unset value selects only transactions reconstructed from shreds.
Highlights
- Pre-shred delivery from connected leaders
- Serialized
VersionedTransactionbytes - Transport: gRPC
SubscribeBinaryTransactions(shreder_preconfproto) - Filters:
account_includeandaccount_required - Explicit source selection and reporting with
preconf - Deserialization in Rust with
bincode
Proto changes
The preconf proto keeps the shreder_binary package and ShrederBinaryService names, so the gRPC method remains ShrederBinaryService.SubscribeBinaryTransactions.
It extends the Binary contract with two fields:
message SubscribeUpdateBinaryTransaction {
BinaryTransaction transaction = 1;
uint64 slot = 2;
bool preconf = 3;
}
message SubscribeRequestFilterBinaryTransactions {
repeated string account_include = 3;
repeated string account_exclude = 4;
repeated string account_required = 6;
bool preconf = 7;
}Use shreder_preconf.proto when generating the client. In a standalone project, the generated module can still be loaded with tonic::include_proto!("shreder_binary").
Filters
| Filter | Behavior |
|---|---|
account_include | Allows only transactions involving any of these accounts |
account_required | Allows only transactions involving all of these accounts |
account_exclude | Not allowed when preconf is true |
preconf | true: preconf ingest only; false or unset: shred-reconstructed transactions only |
The server reports the actual source in SubscribeUpdateBinaryTransaction.preconf.
Usage example (Rust)
Connect, subscribe with a preconf-only filter, and deserialize each binary_transaction payload.
git clone https://github.com/shrederxyz/shreder-rust-example.git
cd shreder-rust-example
# set the endpoint in src/examples/preconf/main.rs
cargo run --example preconfFull example: src/examples/preconf
Subscribe
use futures::{channel::mpsc::unbounded, sink::SinkExt};
use shreder_binary::{
shreder_binary_service_client::ShrederBinaryServiceClient,
SubscribeBinaryTransactionsRequest, SubscribeRequestFilterBinaryTransactions,
};
let entrypoint = "http://fra-allnodes.binary.shreder.xyz:9991";
let mut client = ShrederBinaryServiceClient::connect(entrypoint)
.await
.unwrap();
let request = SubscribeBinaryTransactionsRequest {
transactions: maplit::hashmap! {
"pumpfun".to_owned() => SubscribeRequestFilterBinaryTransactions {
account_include: vec![],
account_exclude: vec![],
account_required: vec![
"6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P".to_owned()
],
preconf: true,
}
},
};
let (mut subscribe_tx, subscribe_rx) = unbounded();
let response = client
.subscribe_binary_transactions(subscribe_rx)
.await
.unwrap();
let mut stream = response.into_inner();
let _ = subscribe_tx.send(request).await;Deserialize updates
use solana_transaction::versioned::VersionedTransaction;
while let Some(response) = stream.message().await.unwrap() {
let update = response.transaction.expect("transaction must be present");
let tx = update.transaction.expect("transaction must be present");
let versioned_tx = match bincode::deserialize::<VersionedTransaction>(&tx.binary_transaction) {
Ok(vt) => vt,
Err(e) => {
println!("Failed to deserialize VersionedTransaction: {e}");
continue;
}
};
println!(
"filters: {:?}, slot: {}, preconf: {}, signatures: {}, instructions: {}",
response.filters,
update.slot,
update.preconf,
tx.signatures.len(),
versioned_tx.message.instructions().len(),
);
}Replace the entrypoint with the Binary gRPC endpoint provided by the Shreder team. If you subscribe to both source types, the same logical transaction can arrive once as preconf and once as non-preconf. Use update.preconf to distinguish them, or deduplicate across sources if you need a single event.
When to use it
- You need transaction delivery before shred emission from connected leaders
- Your hot path already consumes serialized
VersionedTransactionbytes - You want to process the preconf and shred-reconstructed sources explicitly
Preconf coverage depends on whether the current leader is connected to the preconf ingest path.
Related
- Product: Preconfs
- Rust example: main.rs
- Proto: shreder_preconf.proto
- Parent format docs: Binary
- Article: Preconfs — faster than raw shreds