use jsonrpsee_types::error::Error; use jsonrpsee_types::v2::{traits::RpcMethod, RpcError, RpcParams}; use jsonrpsee_utils::server::{send_response, Methods}; use serde::Serialize; use std::sync::Arc; #[derive(Default)] pub struct RpcModule { methods: Methods, } impl RpcModule { /// Instantiate a new `RpcModule`. pub fn new() -> Self { RpcModule { methods: Methods::default() } } /// Add context for this module, turning it into an `RpcContextModule`. pub fn with_context(self, ctx: Context) -> RpcContextModule { RpcContextModule { ctx: Arc::new(ctx), module: self } } fn verify_method_name(&mut self, name: &str) -> Result<(), Error> { if self.methods.get(name).is_some() { return Err(Error::MethodAlreadyRegistered(name.into())); } Ok(()) } /// Register a new RPC method, which responds with a given callback. pub fn register_method(&mut self, method_name: &'static str, callback: F) -> Result<(), Error> where R: Serialize, F: RpcMethod, { self.verify_method_name(method_name)?; self.methods.insert( method_name, Box::new(move |id, params, tx, _| { let result = callback(params)?; send_response(id, tx, result); Ok(()) }), ); Ok(()) } pub(crate) fn into_methods(self) -> Methods { self.methods } pub(crate) fn merge(&mut self, other: RpcModule) -> Result<(), Error> { for name in other.methods.keys() { self.verify_method_name(name)?; } for (name, callback) in other.methods { self.methods.insert(name, callback); } Ok(()) } } pub struct RpcContextModule { ctx: Arc, module: RpcModule, } impl RpcContextModule { /// Create a new module with a given shared `Context`. pub fn new(ctx: Context) -> Self { RpcContextModule { ctx: Arc::new(ctx), module: RpcModule::new() } } /// Register a new RPC method, which responds with a given callback. pub fn register_method(&mut self, method_name: &'static str, callback: F) -> Result<(), Error> where Context: Send + Sync + 'static, R: Serialize, F: Fn(RpcParams, &Context) -> Result + Send + Sync + 'static, { self.module.verify_method_name(method_name)?; let ctx = self.ctx.clone(); self.module.methods.insert( method_name, Box::new(move |id, params, tx, _| { let result = callback(params, &*ctx)?; send_response(id, tx, result); Ok(()) }), ); Ok(()) } /// Convert this `RpcContextModule` into a regular `RpcModule` that can be registered on the `Server`. pub fn into_module(self) -> RpcModule { self.module } }