Skip to content

Commit 1d4d875

Browse files
fernandodeluretkespinolariprsa
authored
Type Source Config, Subscribe to Slots, Fumarole Source, Separate Stream Crate (#111)
--------- Co-authored-by: Kyle Espinola <[email protected]> Co-authored-by: riprsa <[email protected]>
1 parent d094882 commit 1d4d875

File tree

40 files changed

+2827
-1850
lines changed

40 files changed

+2827
-1850
lines changed

Cargo.lock

Lines changed: 1796 additions & 1309 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,10 @@ exclude = ["examples/streams-ts/"]
44
resolver = "2"
55

66
[workspace.dependencies]
7-
yellowstone-grpc-client = { version = "6.1.0" }
8-
yellowstone-grpc-proto = { version = "6.1.0", default-features = false }
7+
yellowstone-grpc-client = { version = "9" }
8+
yellowstone-grpc-proto = { version = "9", default-features = false }
99
yellowstone-vixen = { path = "crates/runtime", version = "0.4.0" }
10+
yellowstone-vixen-stream = { path = "crates/stream", version = "0.0.0" }
1011
yellowstone-vixen-core = { path = "crates/core", version = "0.4.0" }
1112
yellowstone-vixen-mock = { path = "crates/mock", version = "0.4.0" }
1213
yellowstone-vixen-parser = { path = "crates/parser", version = "0.4.0" }
@@ -33,6 +34,8 @@ yellowstone-vixen-virtuals-parser = { path = "crates/virtuals-parser", version =
3334
# Sources
3435
yellowstone-vixen-solana-rpc-source = { path = "crates/solana-rpc-source", version = "0.2.0" }
3536
yellowstone-vixen-yellowstone-grpc-source = { path = "crates/yellowstone-grpc-source", version = "0.2.0" }
37+
yellowstone-vixen-yellowstone-fumarole-source = { path = "crates/yellowstone-fumarole-source", version = "0.2.0" }
38+
yellowstone-vixen-solana-snapshot-source = { path = "crates/solana-snapshot-source", version = "0.2.0" }
3639

3740

3841
# helps resolving zeroize dependency conflicts betweeen solana creates depending on curve25519-dalek and yellowstone-grpc

Vixen.example.toml

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
# This is an example TOML configuration file for Yellowstone Vixen.
22
# Copy to Vixen.toml and them modify as needed.
33

4-
[yellowstone]
4+
# Only needed if you are using the Yellowstone gRPC as a source.
5+
[source]
56
# The endpoint of the dragon's mouth stream.
67
# This is the URL where the stream can be accessed.
78
endpoint = "https://index.rpcpool.com"
@@ -14,6 +15,12 @@ x-token = "<X-TOKEN>"
1415
# This defines how long to wait for a connection before timing out.
1516
timeout = 60
1617

18+
# # Only needed if you are using Fumarole as a source.
19+
# [source]
20+
# endpoint = "https://index.rpcpool.com"
21+
# x-token = "<X-TOKEN>"
22+
# subscriber-name = "my_subscribe_group"
23+
1724
# Metrics configuration section.
1825
# Uncomment the following lines if you are running Prometheus
1926

crates/core/Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ bs58 = "0.5.1"
1313
thiserror = "1.0.64"
1414
yellowstone-grpc-proto = { workspace = true }
1515
yellowstone-vixen-proto = { workspace = true, optional = true }
16+
serde = { version = "1.0.198", features = ["derive"] }
17+
clap = { version = "4.5.4", features = ["derive", "cargo", "wrap_help"] }
1618

1719
[features]
1820
proto = ["dep:yellowstone-vixen-proto"]

crates/core/src/instruction.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,7 @@ impl InstructionUpdate {
200200
return_data: _,
201201
return_data_none: _,
202202
compute_units_consumed,
203+
cost_units: _,
203204
} = meta.ok_or(Missing::TransactionMeta)?;
204205
let Message {
205206
header,

crates/core/src/lib.rs

Lines changed: 75 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,11 @@ use std::{
2424
sync::Arc,
2525
};
2626

27+
use serde::Deserialize;
2728
use yellowstone_grpc_proto::geyser::{
28-
CommitmentLevel, SubscribeRequest, SubscribeRequestFilterAccounts,
29-
SubscribeRequestFilterBlocksMeta, SubscribeRequestFilterTransactions, SubscribeUpdateAccount,
30-
SubscribeUpdateBlockMeta, SubscribeUpdateTransaction,
29+
self, SubscribeRequest, SubscribeRequestFilterAccounts, SubscribeRequestFilterBlocksMeta,
30+
SubscribeRequestFilterSlots, SubscribeRequestFilterTransactions, SubscribeUpdateAccount,
31+
SubscribeUpdateBlockMeta, SubscribeUpdateSlot, SubscribeUpdateTransaction,
3132
};
3233

3334
pub extern crate bs58;
@@ -65,6 +66,8 @@ pub type AccountUpdate = SubscribeUpdateAccount;
6566
pub type TransactionUpdate = SubscribeUpdateTransaction;
6667
/// A block meta update from Yellowstone.
6768
pub type BlockMetaUpdate = SubscribeUpdateBlockMeta;
69+
/// A slot update from Yellowstone.
70+
pub type SlotUpdate = SubscribeUpdateSlot;
6871

6972
/// Generic output type for instruction parsers that wraps shared data for all instructions
7073
/// in the given transaction.
@@ -154,7 +157,9 @@ pub struct Prefilter {
154157
/// Filters for transaction updates.
155158
pub transaction: Option<TransactionPrefilter>,
156159
/// Filters for block meta updates.
157-
pub(crate) block_meta: Option<BlockMetaPrefilter>,
160+
pub block_meta: Option<BlockMetaPrefilter>,
161+
/// Filters for slot updates.
162+
pub slot: Option<SlotPrefilter>,
158163
}
159164

160165
fn merge_opt<T, F: FnOnce(&mut T, T)>(lhs: &mut Option<T>, rhs: Option<T>, f: F) {
@@ -177,10 +182,12 @@ impl Prefilter {
177182
account,
178183
transaction,
179184
block_meta,
185+
slot,
180186
} = self;
181187
merge_opt(account, other.account, AccountPrefilter::merge);
182188
merge_opt(transaction, other.transaction, TransactionPrefilter::merge);
183189
merge_opt(block_meta, other.block_meta, BlockMetaPrefilter::merge);
190+
merge_opt(slot, other.slot, SlotPrefilter::merge);
184191
}
185192
}
186193

@@ -242,10 +249,23 @@ impl TransactionPrefilter {
242249
}
243250
}
244251

245-
#[derive(Debug, Default, Clone, PartialEq)]
246-
pub(crate) struct BlockMetaPrefilter {}
252+
/// A prefilter for matching block metadata updates.
253+
#[derive(Debug, Default, Clone, PartialEq, Copy)]
254+
pub struct BlockMetaPrefilter {}
247255

248256
impl BlockMetaPrefilter {
257+
/// Merge another block metadata prefilter into this one.
258+
/// This function currently does nothing as the struct has no fields.
259+
pub fn merge(_lhs: &mut Self, _rhs: Self) {}
260+
}
261+
262+
/// A prefilter for matching slot updates updates.
263+
#[derive(Debug, Default, Clone, PartialEq, Copy)]
264+
pub struct SlotPrefilter {}
265+
266+
impl SlotPrefilter {
267+
/// Merge another slot prefilter into this one.
268+
/// This function currently does nothing as the struct has no fields.
249269
pub fn merge(_lhs: &mut Self, _rhs: Self) {}
250270
}
251271

@@ -445,6 +465,8 @@ pub enum PrefilterError {
445465
#[must_use = "Consider calling .build() on this builder"]
446466
pub struct PrefilterBuilder {
447467
error: Option<PrefilterError>,
468+
slots: bool,
469+
block_metas: bool,
448470
accounts: Option<HashSet<Pubkey>>,
449471
account_owners: Option<HashSet<Pubkey>>,
450472
/// Matching [`TransactionPrefilter::accounts_include`]
@@ -484,6 +506,8 @@ impl PrefilterBuilder {
484506
error,
485507
accounts,
486508
account_owners,
509+
slots,
510+
block_metas,
487511
transaction_accounts_include,
488512
transaction_accounts_required,
489513
} = self;
@@ -503,10 +527,13 @@ impl PrefilterBuilder {
503527

504528
let block_meta = BlockMetaPrefilter {};
505529

530+
let slot = SlotPrefilter {};
531+
506532
Ok(Prefilter {
507533
account: (account != AccountPrefilter::default()).then_some(account),
508534
transaction: (transaction != TransactionPrefilter::default()).then_some(transaction),
509-
block_meta: (block_meta != BlockMetaPrefilter::default()).then_some(block_meta),
535+
block_meta: block_metas.then_some(block_meta),
536+
slot: slots.then_some(slot),
510537
})
511538
}
512539

@@ -518,6 +545,14 @@ impl PrefilterBuilder {
518545
self
519546
}
520547

548+
/// Set prefilter will request slot updates.
549+
pub fn slots(self) -> Self {
550+
self.mutate(|this| {
551+
this.slots = true;
552+
Ok(())
553+
})
554+
}
555+
521556
/// Set the accounts that this prefilter will match.
522557
pub fn accounts<I: IntoIterator>(self, it: I) -> Self
523558
where I::Item: AsRef<[u8]> {
@@ -573,17 +608,6 @@ impl PrefilterBuilder {
573608
pub struct Filters {
574609
/// Filters for each parser.
575610
pub parsers_filters: HashMap<String, Prefilter>,
576-
/// Global filters for the subscription.
577-
pub global_filters: GlobalFilters,
578-
}
579-
580-
/// A collection of global filters shared by all parsers for a Vixen subscription.
581-
#[derive(Debug, Clone, Default, Copy)]
582-
pub struct GlobalFilters {
583-
/// The commitment level for the subscription.
584-
pub commitment: Option<CommitmentLevel>,
585-
/// The from slot filter for the subscription.
586-
pub from_slot: Option<u64>,
587611
}
588612

589613
impl Filters {
@@ -593,26 +617,30 @@ impl Filters {
593617
pub fn new(filters: HashMap<String, Prefilter>) -> Self {
594618
Self {
595619
parsers_filters: filters,
596-
global_filters: GlobalFilters::default(),
597620
}
598621
}
622+
}
599623

600-
/// Set the commitment level filter.
601-
#[inline]
602-
#[must_use]
603-
pub fn commitment(mut self, commitment: Option<CommitmentLevel>) -> Self {
604-
self.global_filters.commitment = commitment;
605-
606-
self
607-
}
608-
609-
/// Set the from slot filter.
610-
#[inline]
611-
#[must_use]
612-
pub fn from_slot(mut self, from_slot: Option<u64>) -> Self {
613-
self.global_filters.from_slot = from_slot;
614-
615-
self
624+
/// Type mirroring the `CommitmentLevel` enum in the `geyser` crate but serializable.
625+
/// Used to avoid need for custom deserialization logic.
626+
#[derive(Debug, Clone, Copy, Deserialize, clap::ValueEnum)]
627+
#[serde(rename_all = "lowercase")]
628+
pub enum CommitmentLevel {
629+
/// Processed
630+
Processed,
631+
/// Confirmed
632+
Confirmed,
633+
/// Finalized
634+
Finalized,
635+
}
636+
637+
impl From<geyser::CommitmentLevel> for CommitmentLevel {
638+
fn from(value: geyser::CommitmentLevel) -> Self {
639+
match value {
640+
geyser::CommitmentLevel::Processed => Self::Processed,
641+
geyser::CommitmentLevel::Confirmed => Self::Confirmed,
642+
geyser::CommitmentLevel::Finalized => Self::Finalized,
643+
}
616644
}
617645
}
618646

@@ -635,7 +663,16 @@ impl From<Filters> for SubscribeRequest {
635663
}))
636664
})
637665
.collect(),
638-
slots: [].into_iter().collect(),
666+
slots: value
667+
.parsers_filters
668+
.keys()
669+
.map(|k| {
670+
(k.clone(), SubscribeRequestFilterSlots {
671+
filter_by_commitment: Some(true),
672+
interslot_updates: None,
673+
})
674+
})
675+
.collect(),
639676
transactions: value
640677
.parsers_filters
641678
.iter()
@@ -669,13 +706,10 @@ impl From<Filters> for SubscribeRequest {
669706
.map(|k| (k.clone(), SubscribeRequestFilterBlocksMeta {}))
670707
.collect(),
671708
entry: [].into_iter().collect(),
672-
commitment: value
673-
.global_filters
674-
.commitment
675-
.map(|commitment| commitment as i32),
709+
commitment: None,
676710
accounts_data_slice: vec![],
677711
ping: None,
678-
from_slot: value.global_filters.from_slot,
712+
from_slot: None,
679713
}
680714
}
681715
}

crates/parser/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ tokio = "1.39.2"
3434
[features]
3535
default = []
3636
block-meta = []
37+
slot = []
3738
proto = [
3839
"dep:yellowstone-vixen-proto",
3940
"yellowstone-vixen-core/proto",

crates/parser/src/lib.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ mod helpers;
1818
#[cfg(feature = "block-meta")]
1919
pub mod block_meta;
2020

21+
#[cfg(feature = "slot")]
22+
pub mod slot;
23+
2124
#[cfg(feature = "token-extensions")]
2225
pub mod token_extension_program;
2326
#[cfg(feature = "token-program")]

crates/parser/src/slot.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
use std::borrow::Cow;
2+
3+
use yellowstone_vixen_core::{ParseResult, Parser, Prefilter, ProgramParser, Pubkey, SlotUpdate};
4+
5+
#[derive(Debug, Clone, Copy)]
6+
pub struct SlotParser;
7+
8+
impl Parser for SlotParser {
9+
type Input = SlotUpdate;
10+
type Output = SlotUpdate;
11+
12+
fn id(&self) -> Cow<str> { "yellowstone::SlotParser".into() }
13+
14+
fn prefilter(&self) -> Prefilter { Prefilter::builder().slots().build().unwrap() }
15+
16+
async fn parse(&self, slot: &SlotUpdate) -> ParseResult<Self::Output> { Ok(slot.to_owned()) }
17+
}
18+
19+
impl ProgramParser for SlotParser {
20+
/// "S111111111111111111111111111111111111111112"
21+
#[inline]
22+
fn program_id(&self) -> Pubkey {
23+
Pubkey::new([
24+
83, 144, 207, 224, 10, 18, 54, 164, 34, 33, 252, 0, 121, 244, 178, 50, 161, 204, 101,
25+
119, 224, 0, 123, 66, 92, 89, 105, 1, 1, 1, 1, 2,
26+
])
27+
}
28+
}

crates/runtime/Cargo.toml

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ clap = { version = "4.5.4", default-features = false, features = [
1818
futures-channel = { version = "0.3.30", features = ["sink"] }
1919
futures-util = { version = "0.3.30", features = ["sink"] }
2020
opentelemetry = { version = "0.24.0", features = ["metrics"], optional = true }
21-
pin-project-lite = { version = "0.2.14", optional = true }
2221
prometheus = { version = "0.14.0", features = ["push"], optional = true }
22+
toml = "0.8.12"
2323
serde = { version = "1.0.198", features = ["derive"] }
2424
smallvec = "1.13.2"
2525
thiserror = "1.0.64"
@@ -29,13 +29,7 @@ tracing = "0.1.40"
2929
yellowstone-grpc-client = { workspace = true }
3030
yellowstone-grpc-proto = { workspace = true }
3131
yellowstone-vixen-core = { workspace = true }
32-
yellowstone-vixen-proto = { workspace = true, optional = true }
3332

3433
[features]
3534
opentelemetry = ["dep:opentelemetry"]
3635
prometheus = ["dep:prometheus"]
37-
stream = [
38-
"dep:pin-project-lite",
39-
"dep:yellowstone-vixen-proto",
40-
"yellowstone-vixen-proto/stream",
41-
]

0 commit comments

Comments
 (0)