openrpc/
openrpc.rs

1use std::{sync::Arc, time::Duration};
2
3use async_trait::async_trait;
4use jsonrpc_core::{MetaIoHandler, Result};
5use jsonrpc_utils::{axum_utils::jsonrpc_router, rpc, stream::StreamServerConfig};
6use schemars::JsonSchema;
7use serde::{Deserialize, Serialize};
8use tower_http::cors::CorsLayer;
9
10#[derive(Serialize, Deserialize, JsonSchema)]
11struct MyStruct0 {
12    z: String,
13}
14
15#[derive(Serialize, Deserialize, JsonSchema)]
16struct MyStruct {
17    x: u32,
18    y: Vec<u64>,
19    z: MyStruct0,
20}
21
22/// This is doc for `MyRpc`.
23#[rpc(openrpc)]
24#[async_trait]
25trait MyRpc {
26    /// Sleep ...
27    /// Hello world for mutiple lines of comments.
28    async fn sleep(&self, x: u64) -> Result<u64> {
29        tokio::time::sleep(Duration::from_secs(x)).await;
30        Ok(x)
31    }
32    /// Add some numbers.
33    async fn add(&self, (x, y): (i32, i32), z: i32) -> Result<i32> {
34        Ok(x + y + z)
35    }
36    fn echo_my_struct(&self, my_struct: MyStruct) -> Result<MyStruct> {
37        Ok(my_struct)
38    }
39    #[rpc(name = "@ping")]
40    fn ping(&self) -> Result<String> {
41        Ok("pong".into())
42    }
43}
44
45#[derive(Clone)]
46struct MyRpcImpl;
47
48#[async_trait]
49impl MyRpc for MyRpcImpl {}
50
51#[tokio::main]
52async fn main() {
53    let doc = my_rpc_doc();
54
55    let mut rpc = MetaIoHandler::with_compatibility(jsonrpc_core::Compatibility::V2);
56    add_my_rpc_methods(&mut rpc, MyRpcImpl);
57    rpc.add_method("rpc.discover", move |_| {
58        let doc = doc.clone();
59        async move { Ok(doc) }
60    });
61
62    let rpc = Arc::new(rpc);
63
64    let stream_config = StreamServerConfig::default().with_keep_alive(true);
65    let app = jsonrpc_router("/", rpc, stream_config).layer(CorsLayer::permissive());
66
67    let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap();
68    axum::serve(listener, app).await.unwrap();
69}