1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
//! Yellowstone Block Machine
//!
//! Sans-IO state machine utilities for reconstructing Solana blocks from Yellowstone Geyser events.
//!
//! The crate provides:
//! - deterministic per-slot reconstruction from replay + consensus signals,
//! - fork and dead-slot detection,
//! - commitment-level progression updates.
//!
//! # Why this crate exists
//!
//! Raw Geyser streams can arrive in surprising orders. For example, lifecycle and commitment updates
//! may not always line up with block metadata arrival timing. This crate centralizes those rules so
//! downstream consumers can process reconstructed blocks through a stable API.
//!
//! # Core model
//!
//! The state machine consumes:
//! 1. slot lifecycle updates,
//! 2. block entries,
//! 3. block metadata (summary),
//! 4. commitment updates.
//!
//! It emits `BlockStateMachineOutput` values, including frozen blocks, slot status updates, and
//! fork/dead-slot signals.
//!
//! # Wire-format independence
//!
//! [`stream::BlockStream`] and [`wrapper::BlocksStateMachineWrapper`] are generic over any
//! [`event::GeyserEventAdapter`] — they do not depend on any specific version of
//! `yellowstone-grpc-proto`. This crate ships an implementation of [`event::GeyserEventAdapter`] for
//! `yellowstone_grpc_proto::geyser::SubscribeUpdate` behind the `dragonsmouth-thin` feature; if your
//! project is pinned to a different major version of `yellowstone-grpc-proto` (or another Geyser
//! wire format entirely), implement [`event::GeyserEventAdapter`] on your own (possibly zero-sized)
//! marker type instead of enabling that feature — the implementing type doesn't have to be the
//! event type itself, which keeps this legal under Rust's orphan rules even when neither the trait
//! nor the event type is local to your crate — and reuse the reconstruction machinery unchanged.
//!
//! # Dragonsmouth integration
//!
//! With the Dragonsmouth integration enabled, you can consume a typed stream of:
//! - `BlockStreamEvent::FrozenBlock`,
//! - `BlockStreamEvent::SlotCommitmentUpdate`,
//! - `BlockStreamEvent::ForkDetected`,
//! - `BlockStreamEvent::DeadBlockDetected`.
//!
//! High-level example:
//!
//! ```no_run
//! use futures_util::StreamExt;
//! use yellowstone_block_machine::{
//! dragonsmouth::client_ext::{BlockStreamEvent, GeyserGrpcExt},
//! stream::BlockEventStore,
//! };
//! use yellowstone_grpc_client::GeyserGrpcBuilder;
//! use yellowstone_grpc_proto::geyser::{CommitmentLevel, SubscribeRequest};
//!
//! async fn run(mut client: yellowstone_grpc_client::GeyserGrpcClient) {
//! let request = SubscribeRequest {
//! commitment: Some(CommitmentLevel::Confirmed as i32),
//! ..Default::default()
//! };
//! let mut stream = client.subscribe_block(request).await.expect("subscribe_block");
//!
//! while let Some(item) = stream.next().await {
//! match item.expect("stream item") {
//! BlockStreamEvent::FrozenBlock(block) => {
//! let _ = (
//! block.slot(),
//! block.transaction_len(),
//! block.account_len(),
//! block.entry_len(),
//! );
//! }
//! BlockStreamEvent::SlotCommitmentUpdate(update) => {
//! let _ = (update.slot, update.commitment);
//! }
//! BlockStreamEvent::ForkDetected(fork) => {
//! let _ = fork.slot;
//! }
//! BlockStreamEvent::DeadBlockDetected(dead) => {
//! let _ = dead.slot;
//! }
//! }
//! }
//! }
//! ```
//!
//! # Feature flags
//!
//! - `dragonsmouth-thin`: Enables the bundled [`event::GeyserEventAdapter`] impl for
//! `yellowstone_grpc_proto::geyser::SubscribeUpdate` and re-exports `yellowstone_grpc_proto`.
//! Not required if you implement [`event::GeyserEventAdapter`] yourself.
//! - `dragonsmouth`: Enables `client_ext` helpers on top of `dragonsmouth-thin`, including
//! `GeyserGrpcExt::subscribe_block`, and re-exports `yellowstone_grpc_client`.
//!
//! If you are integrating with Yellowstone gRPC directly, `dragonsmouth` is the easiest starting point.
pub use yellowstone_grpc_client;
pub use yellowstone_grpc_proto;