Skip to content

WS Provider

The Ws provider establishes an WebSocket connection with a node, allowing you to send JSON-RPC requests to the node to fetch data, simulate calls, send transactions and much more. The Ws provider can be used with any Ethereum node that supports WebSocket connections. This allows programs to interact with the network in real-time without the need for HTTP polling for things like new block headers and filter logs.

Initializing a Ws Provider

The recommended way of initializing a Ws provider is by using the connect_ws method on the ProviderBuilder with a WsConnect configuration.

//! Example of creating an WS provider using the `connect_ws` method on the `ProviderBuilder`.
 
use alloy::providers::{Provider, ProviderBuilder, WsConnect};
use std::error::Error;
 
#[tokio::main]
async fn main() -> eyre::Result<(), Box<dyn Error>> {
    // Set up the WS transport which is consumed by the RPC client.
    let rpc_url = "wss://eth-mainnet.g.alchemy.com/v2/your-api-key";
 
    // Create the provider.
    let ws = WsConnect::new(rpc_url);
    let provider = ProviderBuilder::new().connect_ws(ws).await?;
 
    Ok(())
}

Ws with Authorization

Similar to the other providers, you can also establish an authorized connection with a node via websockets.

//! Example of using the WS provider with auth to subscribe to new blocks.
 
use alloy::{
    providers::{Provider, ProviderBuilder, WsConnect},
    transports::Authorization,
};
use eyre::Result;
use futures_util::StreamExt;
 
#[tokio::main]
async fn main() -> Result<()> {
    // Create authorization methods.
    let auth = Authorization::basic("username", "password");
    let auth_bearer = Authorization::bearer("bearer-token");
 
    // Create the WS connection object with authentication.
    let rpc_url = "wss://your-ws-endpoint.com/";
    let ws_basic = WsConnect::new(rpc_url).with_auth(auth);
    let ws_bearer = WsConnect::new(rpc_url).with_auth(auth_bearer);
 
    // Create the provider.
    let provider_basic = ProviderBuilder::new().on_ws(ws_basic).await?;
    let provider_bearer = ProviderBuilder::new().on_ws(ws_bearer).await?;
 
    // Subscribe to new block headers.
    let sub_basic = provider_basic.subscribe_blocks();
    let sub_bearer = provider_bearer.subscribe_blocks();
 
    // Wait and take the next 4 block headers
    let mut stream_basic = sub_basic.await?.into_stream().take(4);
    let mut stream_bearer = sub_bearer.await?.into_stream().take(4);
 
    println!("Awaiting block headers...");
 
    // Take the basic stream and print the block number upon receiving a new block header.
    let basic_handle = tokio::spawn(async move {
        while let Some(header) = stream_basic.next().await {
            println!("Latest block number (basic): {}", header.number);
        }
    });
 
    // Take the bearer stream and print the block number upon receiving a new block header.
    let bearer_handle = tokio::spawn(async move {
        while let Some(header) = stream_bearer.next().await {
            println!("Latest block number (bearer): {}", header.number);
        }
    });
 
    // Wait for both tasks to complete.
    let _ = tokio::try_join!(basic_handle, bearer_handle)?;
 
    Ok(())
}