Crate sof
Expand description
SOF observer engine and plugin framework.
External users should usually start from crate::runtime and crate::framework.
§Start The Packaged Runtime
use sof::runtime::ObserverRuntime;
#[tokio::main]
async fn main() -> Result<(), sof::runtime::RuntimeError> {
ObserverRuntime::new().run_until_termination_signal().await
}§Attach One Plugin
use async_trait::async_trait;
use sof::{
event::TxKind,
framework::{ObserverPlugin, PluginConfig, PluginHost, TransactionEvent, TxCommitmentStatus},
runtime::ObserverRuntime,
};
#[derive(Clone, Copy, Debug, Default)]
struct NonVoteLogger;
#[async_trait]
impl ObserverPlugin for NonVoteLogger {
fn config(&self) -> PluginConfig {
PluginConfig::new()
.with_transaction()
.at_commitment(TxCommitmentStatus::Confirmed)
}
async fn on_transaction(&self, event: &TransactionEvent) {
if event.kind == TxKind::VoteOnly {
return;
}
tracing::info!(slot = event.slot, kind = ?event.kind, "transaction observed");
}
}
#[tokio::main]
async fn main() -> Result<(), sof::runtime::RuntimeError> {
let host = PluginHost::builder().add_plugin(NonVoteLogger).build();
ObserverRuntime::new()
.with_plugin_host(host)
.run_until_termination_signal()
.await
}§Request Explicit Inline Transaction Delivery
use async_trait::async_trait;
use sof::{
event::TxKind,
framework::{
ObserverPlugin, PluginConfig, PluginHost, TransactionDispatchMode, TransactionEvent,
TxCommitmentStatus,
},
runtime::ObserverRuntime,
};
#[derive(Clone, Copy, Debug, Default)]
struct InlineTxLogger;
#[async_trait]
impl ObserverPlugin for InlineTxLogger {
fn config(&self) -> PluginConfig {
PluginConfig::new()
.with_transaction_mode(TransactionDispatchMode::Inline)
.at_commitment(TxCommitmentStatus::Processed)
}
async fn on_transaction(&self, event: &TransactionEvent) {
if event.kind == TxKind::VoteOnly {
return;
}
tracing::info!(slot = event.slot, kind = ?event.kind, "inline transaction observed");
}
}
#[tokio::main]
async fn main() -> Result<(), sof::runtime::RuntimeError> {
let host = PluginHost::builder().add_plugin(InlineTxLogger).build();
ObserverRuntime::new()
.with_plugin_host(host)
.run_until_termination_signal()
.await
}crate::framework::TransactionDispatchMode::Inline is an explicit delivery contract for
on_transaction. SOF dispatches that hook as soon as one full serialized transaction is ready
on the anchored contiguous inline path, and falls back to the completed-dataset point only when
the early path is not yet reconstructable.
§Prefer Compiled Transaction Prefilters
use async_trait::async_trait;
use solana_pubkey::Pubkey;
use sof::{
framework::{
ObserverPlugin, PluginConfig, PluginHost, TransactionDispatchMode,
TransactionInterest, TransactionPrefilter,
},
runtime::ObserverRuntime,
};
#[derive(Clone, Debug)]
struct RaydiumPoolWatcher {
filter: TransactionPrefilter,
}
impl Default for RaydiumPoolWatcher {
fn default() -> Self {
let pool = Pubkey::new_unique();
let program = Pubkey::new_unique();
Self {
filter: TransactionPrefilter::new(TransactionInterest::Critical)
.with_account_required([pool, program]),
}
}
}
#[async_trait]
impl ObserverPlugin for RaydiumPoolWatcher {
fn config(&self) -> PluginConfig {
PluginConfig::new().with_transaction_mode(TransactionDispatchMode::Inline)
}
fn transaction_prefilter(&self) -> Option<&TransactionPrefilter> {
Some(&self.filter)
}
}
#[tokio::main]
async fn main() -> Result<(), sof::runtime::RuntimeError> {
let host = PluginHost::builder()
.add_plugin(RaydiumPoolWatcher::default())
.build();
ObserverRuntime::new()
.with_plugin_host(host)
.run_until_termination_signal()
.await
}Prefer crate::framework::TransactionPrefilter when your plugin only
matches exact signatures or account-key presence. On the inline path, SOF can
use that compiled matcher on a sanitized transaction view and skip full owned
transaction decode for misses.
More user-facing examples live in crates/sof-observer/README.md and the published example
programs under crates/sof-observer/examples/.
Modules§
- event
- Runtime transaction event types. Runtime event classifications shared by runtime and plugin surfaces.
- framework
- Plugin framework for attaching custom runtime hooks. Public plugin framework surface for embedding custom observers into SOF runtime.
- provider_
stream - Processed provider-stream ingress types and adapters. Processed provider-stream ingress surfaces for SOF.
- runtime
- Packaged runtime entrypoints for embedding SOF.
- runtime_
metrics - Runtime-stage counters for ingress, dataset reconstruction, and tx delivery.