### Configure and Start JSON-RPC Server Source: https://context7.com/paritytech/jsonrpsee/llms.txt Demonstrates how to initialize a JSON-RPC server using Server::builder, configure custom settings, and register RPC modules. The server supports both HTTP and WebSocket protocols on a single port. ```rust use std::net::SocketAddr; use jsonrpsee::server::{Server, RpcModule, ServerConfig}; use jsonrpsee::core::middleware::RpcServiceBuilder; #[tokio::main] async fn main() -> anyhow::Result<()> { let config = ServerConfig::builder() .set_message_buffer_capacity(5) .build(); let rpc_middleware = RpcServiceBuilder::new().rpc_logger(1024); let server = Server::builder() .set_config(config) .set_rpc_middleware(rpc_middleware) .build("127.0.0.1:9944".parse::()?) .await?; let mut module = RpcModule::new(()); module.register_method("say_hello", |_, _, _| "Hello, World!")?; let addr = server.local_addr()?; let handle = server.start(module); println!("Server running at {}", addr); handle.stopped().await; Ok(()) } ``` -------------------------------- ### Generate Client and Server Traits with #[rpc] Proc Macro in Rust Source: https://context7.com/paritytech/jsonrpsee/llms.txt Illustrates the use of the `#[rpc]` proc macro in jsonrpsee to generate type-safe client and server traits from a single interface definition. This example defines a `StateApi` with methods for getting keys and subscribing to storage changes, and shows how to implement the server and use the generated client. ```rust use jsonrpsee::proc_macros::rpc; use jsonrpsee::core::{async_trait, SubscriptionResult, client::Subscription}; use jsonrpsee::server::{Server, PendingSubscriptionSink}; use jsonrpsee::types::ErrorObjectOwned; use jsonrpsee::ws_client::WsClientBuilder; // Define RPC interface with namespace "state" #[rpc(server, client, namespace = "state")] pub trait StateApi { /// Async method returning storage keys #[method(name = "getKeys")] async fn get_keys(&self, prefix: Vec, at: Option) -> Result>, ErrorObjectOwned>; /// Subscription for storage changes #[subscription(name = "subscribeStorage" => "storage", item = Vec)] async fn subscribe_storage(&self, keys: Option>>) -> SubscriptionResult; } // Implement server-side pub struct StateApiImpl; #[async_trait] impl StateApiServer<[u8; 32]> for StateApiImpl { async fn get_keys(&self, prefix: Vec, _at: Option<[u8; 32]>) -> Result>, ErrorObjectOwned> { Ok(vec![prefix]) } async fn subscribe_storage( &self, pending: PendingSubscriptionSink, _keys: Option>>, ) -> SubscriptionResult { let sink = pending.accept().await?; let msg = serde_json::value::to_raw_value(&vec![[0u8; 32]])?; sink.send(msg).await?; Ok(()) } } #[tokio::main] async fn main() -> anyhow::Result<()> { // Start server let server = Server::builder().build("127.0.0.1:0").await?; let addr = server.local_addr()?; let handle = server.start(StateApiImpl.into_rpc()); tokio::spawn(handle.stopped()); // Use generated client trait let client = WsClientBuilder::default().build(&format!("ws://{}", addr)).await?; // Type-safe method call using generated client let keys = StateApiClient::<[u8; 32]>::get_keys(&client, vec![1, 2, 3], None).await?; assert_eq!(keys, vec![vec![1, 2, 3]]); // Type-safe subscription using generated client let mut sub: Subscription> = StateApiClient::<[u8; 32]>::subscribe_storage(&client, None).await?; if let Some(Ok(data)) = sub.next().await { println!("Received storage update: {:?}", data); } Ok(()) } ``` -------------------------------- ### Execute Benchmarks with Cargo Source: https://github.com/paritytech/jsonrpsee/blob/master/benches/README.md Commands to run the full benchmark suite, specific individual benchmarks, or benchmarks with additional feature flags. ```sh cargo bench cargo bench --bench bench jsonrpsee_types_v2_array_ref cargo bench --features jsonpc-crate ``` -------------------------------- ### Monitor Benchmarks with Tokio Console Source: https://github.com/paritytech/jsonrpsee/blob/master/benches/README.md Enables tokio-console support to monitor asynchronous tasks during benchmark execution. ```sh cargo install --locked tokio-console && tokio-console RUSTFLAGS="--cfg tokio_unstable" cargo bench ``` -------------------------------- ### Profile Benchmarks with Flamegraphs Source: https://github.com/paritytech/jsonrpsee/blob/master/benches/README.md Generates CPU flamegraphs for performance analysis by running benchmarks with a specified profiling duration. ```sh cargo bench --bench bench -- --profile-time=60 cargo bench --bench bench -- --profile-time=60 sync/http_concurrent_conn_calls/1024 ``` -------------------------------- ### Configure System Limits for Benchmarking Source: https://github.com/paritytech/jsonrpsee/blob/master/benches/README.md Adjusts macOS system limits to handle high volumes of concurrent connections and file descriptors required for stress testing. ```sh sudo sysctl -w kern.maxfiles=100000 sudo sysctl -w kern.maxfilesperproc=100000 ulimit -n 100000 sudo sysctl -w kern.ipc.somaxconn=100000 sudo sysctl -w kern.ipc.maxsockbuf=16777216 ``` -------------------------------- ### Configure WsClient with Custom Headers in Rust Source: https://context7.com/paritytech/jsonrpsee/llms.txt Demonstrates how to configure a WebSocket client with custom headers, such as 'Authorization' and 'X-Custom-Header', using jsonrpsee. This is useful for authentication or passing additional metadata to the server. The client is built with a specified URL and maximum concurrent requests. ```rust use jsonrpsee::ws_client::{WsClientBuilder, HeaderMap, HeaderValue}; #[tokio::main] async fn main() -> anyhow::Result<()> { let mut headers = HeaderMap::new(); headers.insert("Authorization", HeaderValue::from_static("Bearer my-token")); headers.insert("X-Custom-Header", HeaderValue::from_static("custom-value")); let client = WsClientBuilder::new() .set_headers(headers) .max_concurrent_requests(256) .build("wss://secure-server.example.com:443") .await?; // Use client with authenticated connection let result: String = client.request("protected_method", rpc_params![]).await?; println!("Result: {}", result); Ok(()) } ``` -------------------------------- ### Register Asynchronous RPC Methods Source: https://context7.com/paritytech/jsonrpsee/llms.txt Illustrates how to register asynchronous methods using register_async_method. This is essential for operations involving I/O, such as database access or external network calls. ```rust use std::sync::Arc; use jsonrpsee::server::RpcModule; use jsonrpsee::types::ErrorObjectOwned; struct AppState { db_pool: String, } let state = AppState { db_pool: "connected".into() }; let mut module = RpcModule::new(state); module.register_async_method("fetch_user", |params, ctx, _ext| async move { let user_id: u64 = params.one()?; tokio::time::sleep(std::time::Duration::from_millis(10)).await; Ok::<_, ErrorObjectOwned>(format!("User {} from {}", user_id, ctx.db_pool)) })?; module.register_async_method("slow_operation", |params, _ctx, _ext| async move { let delay_ms: u64 = params.one()?; tokio::time::sleep(std::time::Duration::from_millis(delay_ms)).await; Ok::<_, ErrorObjectOwned>("completed") })?; ``` -------------------------------- ### Register Synchronous RPC Methods Source: https://context7.com/paritytech/jsonrpsee/llms.txt Shows how to register synchronous methods to an RpcModule. These methods handle incoming parameters and return results immediately without blocking the async runtime. ```rust use jsonrpsee::server::RpcModule; use jsonrpsee::types::ErrorObjectOwned; let mut module = RpcModule::new(42_u64); module.register_method("greet", |params, ctx, _ext| { let name: String = params.one()?; Ok::<_, ErrorObjectOwned>(format!("Hello {}, context value is {}", name, ctx)) })?; module.register_method("add", |params, _ctx, _ext| { let (a, b): (i32, i32) = params.parse()?; Ok::<_, ErrorObjectOwned>(a + b) })?; let result: String = module.call("greet", ["Alice"]).await?; assert_eq!(result, "Hello Alice, context value is 42"); let sum: i32 = module.call("add", [10, 20]).await?; assert_eq!(sum, 30); ``` -------------------------------- ### Implement Custom JSON-RPC Middleware with RpcServiceT Source: https://context7.com/paritytech/jsonrpsee/llms.txt Demonstrates how to create a custom middleware struct implementing RpcServiceT to intercept and count RPC calls. This pattern allows for global logging, metrics collection, or request modification before passing the request to the underlying service. ```rust use std::sync::Arc; use std::sync::atomic::{AtomicUsize, Ordering}; use jsonrpsee::core::middleware::{Batch, Notification, RpcServiceBuilder, RpcServiceT}; use jsonrpsee::types::Request; use jsonrpsee::server::{Server, RpcModule}; #[derive(Clone)] pub struct CallCounter { service: S, count: Arc, } impl RpcServiceT for CallCounter where S: RpcServiceT + Send + Sync + Clone + 'static, { type MethodResponse = S::MethodResponse; type NotificationResponse = S::NotificationResponse; type BatchResponse = S::BatchResponse; fn call<'a>(&self, req: Request<'a>) -> impl std::future::Future + Send + 'a { let count = self.count.clone(); let service = self.service.clone(); async move { let method = req.method.to_string(); let response = service.call(req).await; let current = count.fetch_add(1, Ordering::SeqCst) + 1; println!("Method '{}' called. Total calls: {}", method, current); response } } fn batch<'a>(&self, batch: Batch<'a>) -> impl std::future::Future + Send + 'a { let len = batch.len(); self.count.fetch_add(len, Ordering::SeqCst); self.service.batch(batch) } fn notification<'a>(&self, n: Notification<'a>) -> impl std::future::Future + Send + 'a { self.service.notification(n) } } #[tokio::main] async fn main() -> anyhow::Result<()> { let call_count = Arc::new(AtomicUsize::new(0)); let rpc_middleware = RpcServiceBuilder::new() .layer_fn(move |service| CallCounter { service, count: call_count.clone(), }); let server = Server::builder() .set_rpc_middleware(rpc_middleware) .build("127.0.0.1:9944") .await?; let mut module = RpcModule::new(()); module.register_method("ping", |_, _, _| "pong")?; let handle = server.start(module); handle.stopped().await; Ok(()) } ``` -------------------------------- ### Test RPC Methods Directly Without a Server Source: https://context7.com/paritytech/jsonrpsee/llms.txt Shows how to invoke registered RPC methods directly on an RpcModule instance for unit testing purposes. This bypasses network transport layers, allowing for fast verification of method logic and raw JSON request handling. ```rust use jsonrpsee::server::RpcModule; use jsonrpsee::types::ErrorObjectOwned; #[tokio::main] async fn main() -> anyhow::Result<()> { let mut module = RpcModule::new(()); module.register_method("echo", |params, _, _| { let msg: String = params.one()?; Ok::<_, ErrorObjectOwned>(msg) })?; module.register_method("multiply", |params, _, _| { let (a, b): (i32, i32) = params.parse()?; Ok::<_, ErrorObjectOwned>(a * b) })?; let echo_result: String = module.call("echo", ["Hello"]).await?; assert_eq!(echo_result, "Hello"); let multiply_result: i32 = module.call("multiply", [6, 7]).await?; assert_eq!(multiply_result, 42); let (response, _rx) = module .raw_json_request(r#"{"jsonrpc":"2.0","method":"multiply","params":[3,4],"id":1}"#, 1) .await?; println!("Raw response: {}", response); Ok(()) } ``` -------------------------------- ### Tag and Push Release Source: https://github.com/paritytech/jsonrpsee/blob/master/RELEASE-CHECKLIST.md Commands to sign and push a version tag to the repository after a successful publication. This marks the specific commit on the master branch as the official release version. ```bash git tag -s v0.15.0 git push --tags ``` -------------------------------- ### HTTP JSON-RPC Client with jsonrpsee Source: https://context7.com/paritytech/jsonrpsee/llms.txt Implements an HTTP client for making JSON-RPC requests. It supports configurable timeouts, request sizes, and allows for both single and batched requests. ```rust use jsonrpsee::http_client::HttpClient; use jsonrpsee::core::client::ClientT; use jsonrpsee::rpc_params; #[tokio::main] async fn main() -> anyhow::Result<()> { // Build HTTP client with custom configuration let client = HttpClient::builder() .request_timeout(std::time::Duration::from_secs(30)) .max_request_size(10 * 1024 * 1024) // 10 MB .build("http://127.0.0.1:9944")?; // Make a simple request let response: String = client.request("say_hello", rpc_params![]).await?; println!("Response: {}", response); // Request with parameters let sum: i32 = client.request("add", rpc_params![10, 20]).await?; println!("Sum: {}", sum); // Batch requests for efficiency let mut batch = client.batch_request(); batch.insert("say_hello", rpc_params![])?; batch.insert("add", rpc_params![1, 2])?; let responses = batch.send().await?; for response in responses { println!("Batch response: {:?}", response); } Ok(()) } ``` -------------------------------- ### Register Pub/Sub Subscription with jsonrpsee Source: https://context7.com/paritytech/jsonrpsee/llms.txt Registers a subscription method for Pub/Sub following the Ethereum specification. It automatically generates the unsubscribe handler and streams events to connected clients via a broadcast channel. ```rust use jsonrpsee::server::{RpcModule, PendingSubscriptionSink}; use jsonrpsee::core::SubscriptionResult; use tokio::sync::broadcast; use tokio_stream::wrappers::BroadcastStream; use futures::StreamExt; let (tx, _rx) = broadcast::channel::(16); let mut module = RpcModule::new(tx); module.register_subscription( "subscribe_events", // subscribe method name "event_notification", // notification method name "unsubscribe_events", // unsubscribe method name |params, pending, tx, _ext| async move { // Parse optional filter parameter let filter: Option = params.optional_next()?; // Accept the subscription - this responds to the RPC call let sink = pending.accept().await?; // Subscribe to broadcast channel let rx = tx.subscribe(); let mut stream = BroadcastStream::new(rx); // Stream events until client disconnects loop { tokio::select! { _ = sink.closed() => break, Some(Ok(item)) = stream.next() => { let msg = serde_json::value::to_raw_value(&item)?; if sink.send(msg).await.is_err() { break; } } } } Ok(()) } )?; ``` -------------------------------- ### Publish Crates Script Source: https://github.com/paritytech/jsonrpsee/blob/master/RELEASE-CHECKLIST.md Executes the shell script to publish all workspace crates to crates.io in the correct dependency order. This should be performed after the release branch has been merged into master. ```bash ./scripts/publish.sh ``` -------------------------------- ### Generate Changelog Script Source: https://github.com/paritytech/jsonrpsee/blob/master/RELEASE-CHECKLIST.md Executes the shell script to identify and list merged pull requests between the current state and the last published release tag. This facilitates the manual organization of changelog entries into categories like Fixed, Added, and Changed. ```bash ./scripts/generate_changelog.sh ``` -------------------------------- ### WebSocket JSON-RPC Client with jsonrpsee Source: https://context7.com/paritytech/jsonrpsee/llms.txt Provides a WebSocket client for JSON-RPC, supporting both regular requests and subscriptions. It includes features like automatic reconnection and configurable timeouts. ```rust use jsonrpsee::ws_client::{WsClientBuilder, WsClient}; use jsonrpsee::core::client::{ClientT, SubscriptionClientT, Subscription}; use jsonrpsee::rpc_params; use futures::StreamExt; #[tokio::main] async fn main() -> anyhow::Result<()> { // Build WebSocket client let client: WsClient = WsClientBuilder::default() .request_timeout(std::time::Duration::from_secs(60)) .connection_timeout(std::time::Duration::from_secs(10)) .max_buffer_capacity_per_subscription(1024) .build("ws://127.0.0.1:9944") .await?; // Make regular RPC request let response: String = client.request("say_hello", rpc_params![]).await?; println!("Response: {}", response); // Subscribe to events let mut subscription: Subscription = client .subscribe("subscribe_events", rpc_params![], "unsubscribe_events") .await?; // Receive subscription notifications while let Some(result) = subscription.next().await { match result { Ok(value) => println!("Received: {}", value), Err(e) => eprintln!("Subscription error: {}", e), } } Ok(()) } ``` -------------------------------- ### Configure Server CORS Middleware with jsonrpsee Source: https://context7.com/paritytech/jsonrpsee/llms.txt Configures Cross-Origin Resource Sharing (CORS) for a JSON-RPC server using tower-http middleware. This allows requests from different origins, typically from web browsers. ```rust use std::net::SocketAddr; use hyper::Method; use jsonrpsee::server::{RpcModule, Server}; use tower_http::cors::{Any, CorsLayer}; #[tokio::main] async fn main() -> anyhow::Result<()> { // Configure CORS to allow requests from any origin let cors = CorsLayer::new() .allow_methods([Method::POST]) .allow_origin(Any) .allow_headers([hyper::header::CONTENT_TYPE]); let middleware = tower::ServiceBuilder::new().layer(cors); let server = Server::builder() .set_http_middleware(middleware) .build("127.0.0.1:9944".parse::()?) .await?; let mut module = RpcModule::new(()); module.register_method("ping", |_, _, _| "pong")?; let handle = server.start(module); handle.stopped().await; Ok(()) } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.