pub struct SurfpoolWsRpc {
pub uid: AtomicUsize,
pub signature_subscription_map: Arc<RwLock<HashMap<SubscriptionId, Sink<Response<RpcSignatureResult>>>>>,
pub account_subscription_map: Arc<RwLock<HashMap<SubscriptionId, Sink<Response<UiAccount>>>>>,
pub slot_subscription_map: Arc<RwLock<HashMap<SubscriptionId, Sink<SlotInfo>>>>,
pub logs_subscription_map: Arc<RwLock<HashMap<SubscriptionId, Sink<Response<RpcLogsResponse>>>>>,
pub tokio_handle: Handle,
}Expand description
WebSocket RPC server implementation for Surfpool.
This struct manages WebSocket subscriptions for both signature status updates and account change notifications in the Surfpool environment. It provides a complete WebSocket RPC interface that allows clients to subscribe to real-time updates from the Solana Virtual Machine (SVM) and handles the lifecycle of WebSocket connections.
§Fields
uid: Atomic counter for generating unique subscription IDs across all subscription types.signature_subscription_map: Thread-safe HashMap containing active signature subscriptions, mapping subscription IDs to their notification sinks.account_subscription_map: Thread-safe HashMap containing active account subscriptions, mapping subscription IDs to their notification sinks.slot_subscription_map: Thread-safe HashMap containing active slot subscriptions, mapping subscription IDs to their notification sinks.tokio_handle: Runtime handle for spawning asynchronous subscription monitoring tasks.
§Features
- Concurrent Subscriptions: Supports multiple simultaneous subscriptions without blocking.
- Thread Safety: All subscription management operations are thread-safe using RwLock.
- Automatic Cleanup: Subscriptions are automatically cleaned up when completed or unsubscribed.
- Efficient Monitoring: Each subscription runs in its own async task for optimal performance.
- Real-time Updates: Provides immediate notifications when monitored conditions are met.
§Usage
This struct implements the Rpc trait and is typically used as part of a larger
WebSocket server infrastructure to provide real-time blockchain data to clients.
§Notes
- Each subscription is assigned a unique numeric ID for tracking and management.
- The struct maintains separate maps for different subscription types to optimize performance.
- All async operations are managed through the provided Tokio runtime handle.
§See Also
Rpc: The trait interface this struct implementsRpcAccountSubscribeConfig: Configuration options for account subscriptions
Fields§
§uid: AtomicUsize§signature_subscription_map: Arc<RwLock<HashMap<SubscriptionId, Sink<Response<RpcSignatureResult>>>>>§account_subscription_map: Arc<RwLock<HashMap<SubscriptionId, Sink<Response<UiAccount>>>>>§slot_subscription_map: Arc<RwLock<HashMap<SubscriptionId, Sink<SlotInfo>>>>§logs_subscription_map: Arc<RwLock<HashMap<SubscriptionId, Sink<Response<RpcLogsResponse>>>>>§tokio_handle: HandleTrait Implementations§
Source§impl Rpc for SurfpoolWsRpc
impl Rpc for SurfpoolWsRpc
Source§fn signature_subscribe(
&self,
meta: Self::Metadata,
subscriber: Subscriber<RpcResponse<RpcSignatureResult>>,
signature_str: String,
config: Option<RpcSignatureSubscribeConfig>,
)
fn signature_subscribe( &self, meta: Self::Metadata, subscriber: Subscriber<RpcResponse<RpcSignatureResult>>, signature_str: String, config: Option<RpcSignatureSubscribeConfig>, )
Implementation of signature subscription for WebSocket clients.
This method handles the complete lifecycle of signature subscriptions:
- Validates the provided signature string format
- Determines the subscription type (received vs commitment-based)
- Checks if the transaction already exists in the desired state
- If found and confirmed, immediately notifies the subscriber
- Otherwise, sets up a continuous monitoring loop
- Spawns an async task to handle ongoing subscription management
§Error Handling
- Rejects subscription with
InvalidParamsfor malformed signatures - Handles RPC context retrieval failures
- Manages subscription cleanup on completion or failure
§Concurrency
Each subscription runs in its own async task, allowing multiple concurrent subscriptions without blocking each other.
Source§fn signature_unsubscribe(
&self,
_meta: Option<Self::Metadata>,
subscription: SubscriptionId,
) -> Result<bool>
fn signature_unsubscribe( &self, _meta: Option<Self::Metadata>, subscription: SubscriptionId, ) -> Result<bool>
Implementation of signature unsubscription for WebSocket clients.
This method removes an active signature subscription from the internal tracking maps, effectively stopping further notifications for that subscription.
§Implementation Details
- Attempts to remove the subscription from the active subscriptions map
- Returns success if the subscription existed and was removed
- Returns an error if the subscription ID was not found
§Thread Safety
Uses write locks to ensure thread-safe removal from the subscription map.
Source§fn account_subscribe(
&self,
meta: Self::Metadata,
subscriber: Subscriber<RpcResponse<UiAccount>>,
pubkey_str: String,
config: Option<RpcAccountSubscribeConfig>,
)
fn account_subscribe( &self, meta: Self::Metadata, subscriber: Subscriber<RpcResponse<UiAccount>>, pubkey_str: String, config: Option<RpcAccountSubscribeConfig>, )
Implementation of account subscription for WebSocket clients.
This method handles the complete lifecycle of account subscriptions:
- Validates the provided public key string format
- Parses the subscription configuration (commitment and encoding)
- Generates a unique subscription ID and assigns it to the subscriber
- Spawns an async task to continuously monitor account changes
- Sends notifications whenever the account state changes
§Monitoring Loop
The spawned task runs a continuous loop that:
- Checks if the subscription is still active (not unsubscribed)
- Polls for account updates from the SVM
- Sends notifications to the subscriber when changes occur
- Automatically terminates when the subscription is removed
§Error Handling
- Rejects subscription with
InvalidParamsfor malformed public keys - Handles encoding configuration for account data serialization
- Manages subscription cleanup through the monitoring loop
§Performance
Uses efficient polling with minimal CPU overhead and automatic cleanup when subscriptions are no longer needed.
Source§fn account_unsubscribe(
&self,
_meta: Option<Self::Metadata>,
subscription: SubscriptionId,
) -> Result<bool>
fn account_unsubscribe( &self, _meta: Option<Self::Metadata>, subscription: SubscriptionId, ) -> Result<bool>
Implementation of account unsubscription for WebSocket clients.
This method removes an active account subscription from the internal tracking maps, effectively stopping further notifications for that subscription. The monitoring loop in the corresponding subscription task will detect this removal and automatically terminate.
§Implementation Details
- Attempts to remove the subscription from the account subscriptions map
- Returns success if the subscription existed and was removed
- Returns an error if the subscription ID was not found
- The removal triggers automatic cleanup of the monitoring task
§Thread Safety
Uses write locks to ensure thread-safe removal from the subscription map. The monitoring task uses read locks to check subscription status, creating a clean synchronization pattern.
type Metadata = Option<SurfpoolWebsocketMeta>
Source§fn slot_subscribe(&self, meta: Self::Metadata, subscriber: Subscriber<SlotInfo>)
fn slot_subscribe(&self, meta: Self::Metadata, subscriber: Subscriber<SlotInfo>)
Source§fn slot_unsubscribe(
&self,
_meta: Option<Self::Metadata>,
subscription: SubscriptionId,
) -> Result<bool>
fn slot_unsubscribe( &self, _meta: Option<Self::Metadata>, subscription: SubscriptionId, ) -> Result<bool>
Source§fn logs_subscribe(
&self,
meta: Self::Metadata,
subscriber: Subscriber<RpcResponse<RpcLogsResponse>>,
mentions: Option<RpcTransactionLogsFilter>,
commitment: Option<CommitmentLevel>,
)
fn logs_subscribe( &self, meta: Self::Metadata, subscriber: Subscriber<RpcResponse<RpcLogsResponse>>, mentions: Option<RpcTransactionLogsFilter>, commitment: Option<CommitmentLevel>, )
Source§fn logs_unsubscribe(
&self,
_meta: Option<Self::Metadata>,
subscription: SubscriptionId,
) -> Result<bool>
fn logs_unsubscribe( &self, _meta: Option<Self::Metadata>, subscription: SubscriptionId, ) -> Result<bool>
Source§fn to_delegate(self) -> IoDelegate<Self, Self::Metadata>
fn to_delegate(self) -> IoDelegate<Self, Self::Metadata>
IoDelegate, wiring rpc calls to the trait methods.Auto Trait Implementations§
impl !Freeze for SurfpoolWsRpc
impl RefUnwindSafe for SurfpoolWsRpc
impl Send for SurfpoolWsRpc
impl Sync for SurfpoolWsRpc
impl Unpin for SurfpoolWsRpc
impl UnwindSafe for SurfpoolWsRpc
Blanket Implementations§
Source§impl<'a, T, E> AsTaggedExplicit<'a, E> for Twhere
T: 'a,
impl<'a, T, E> AsTaggedExplicit<'a, E> for Twhere
T: 'a,
Source§impl<'a, T, E> AsTaggedImplicit<'a, E> for Twhere
T: 'a,
impl<'a, T, E> AsTaggedImplicit<'a, E> for Twhere
T: 'a,
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more