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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
//! Solana plugin trait and PluginFuture type alias.
//!
//! Implement the [`Plugin`] trait to observe Solana block and transaction events.
//! Register plugins with [`CascadeRunner::with_plugin()`](crate::CascadeRunner::with_plugin).
//!
//! Two approaches:
//! - **Custom extraction**: implement [`on_raw`](Plugin::on_raw) and parse the raw JSON yourself.
//! Use [`extract_block()`](super::extract_block) as a utility if you want structured data too.
//! - **Built-in extraction**: implement [`on_block`](Plugin::on_block),
//! [`on_transaction`](Plugin::on_transaction), etc. and let the framework extract for you.
//!
//! Both can be combined — `on_raw` fires first, then the structured hooks.
use Future;
use Pin;
use ;
/// The return type for all plugin hooks. A boxed async future that returns
/// `Result<(), Box<dyn Error>>`. Use `Box::pin(async move { ... })` to create one.
pub type PluginFuture<'a> =
;
/// Observe Solana block and transaction events.
///
/// Two approaches to consuming data:
///
/// **1. Custom extraction** — implement [`on_raw`](Self::on_raw) and parse the raw
/// JSON-RPC response yourself. Use [`extract_block()`](super::extract_block)
/// as an optional utility.
///
/// **2. Built-in extraction** — implement [`on_block`](Self::on_block),
/// [`on_transaction`](Self::on_transaction), etc. The framework extracts structured data
/// and calls your hooks.
///
/// Both can be combined: `on_raw` fires first with the raw JSON, then the framework
/// extracts and calls the structured hooks.
///
/// # Example: Custom extraction
///
/// ```rust,no_run
/// use quicknode_cascade::solana::{Plugin, PluginFuture};
///
/// struct RawProcessor;
///
/// impl Plugin for RawProcessor {
/// fn name(&self) -> &'static str { "raw" }
///
/// fn on_raw<'a>(&'a self, slot: u64, raw: &'a serde_json::Value) -> PluginFuture<'a> {
/// Box::pin(async move {
/// let txs = raw.get("transactions").and_then(|v| v.as_array());
/// println!("slot {} has {} txs", slot, txs.map_or(0, |t| t.len()));
/// Ok(())
/// })
/// }
/// }
/// ```
///
/// # Example: Built-in extraction
///
/// ```rust,no_run
/// use quicknode_cascade::solana::{Plugin, PluginFuture, BlockData, TransactionData};
///
/// struct MyIndexer;
///
/// impl Plugin for MyIndexer {
/// fn name(&self) -> &'static str { "my-indexer" }
///
/// fn on_block<'a>(&'a self, block: &'a BlockData) -> PluginFuture<'a> {
/// Box::pin(async move {
/// println!("slot {} — {} txs", block.slot, block.transaction_count);
/// Ok(())
/// })
/// }
///
/// fn on_transaction<'a>(&'a self, tx: &'a TransactionData) -> PluginFuture<'a> {
/// Box::pin(async move {
/// if !tx.is_vote {
/// println!(" tx {}", tx.signature);
/// }
/// Ok(())
/// })
/// }
/// }
/// ```