Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Subscriptions just returns None (no error) - manual tokio_tungstenite works fine #1142

Open
chikko80 opened this issue Jun 16, 2023 · 4 comments

Comments

@chikko80
Copy link

I am trying to connect to a jsonrpc websocket with your library but it doesn't work.
The strange thing is that every other library including manual implementation with tokio-tokio_tungstenite works absolutely fine.
Even a simple wscat via terminal works without any problems.

from stream.next().await i always get just a None - there is no error.
Seems like the connection gets successfully established but then there is just nothing to receive. Even if I loop the stream.next().await for 1 minute i never receive anything.
Super confused cause its just with jsonrpsee which would totally fit for my use case.

Is anyone familiar with that problem or has an idea how to solve that?

    #[tokio::test]
    async fn test_jsonrpsee() {
        let mut headers = HeaderMap::new();
        let bx_auth_header = "<bloxroute-auth-token>";
        headers.insert("Authorization", bx_auth_header.parse().unwrap());

        let ws_client = WsClientBuilder::default().set_headers(headers);

        let client = ws_client
            .build("wss://api.blxrbdn.com:443/ws")
            .await
            .unwrap();
        dbg!(&client);

        // let bx_params = BxParams::default();
        // dbg!(bx_params.clone().to_rpc_params());
        let params = rpc_params!["newTxs", doc! {"include": vec!["tx_hash"]}];

        let mut stream: Subscription<String> = client
            .subscribe("subscribe", params, "unsubscribe")
            .await
            .unwrap();

        tokio::time::sleep(Duration::from_secs(1)).await;

        dbg!(&stream);
        dbg!(stream.next().await);
    }

    #[tokio::test]
    async fn test_manual_impl() {
        let request_text = r#"{
            "jsonrpc": "2.0",
            "id": 0,
            "method": "subscribe",
            "params": ["newTxs", {"include": ["tx_hash"]}]
        }"#;

        // Generate a random Sec-WebSocket-Key
        let key = base64::encode("secret-key");

        let request = Request::get("wss://api.blxrbdn.com:443/ws")
            .header("Host", "api.blxrbdn.com:443")
            .header("Authorization", "<bloxroute-auth-token>")
            .header("Sec-WebSocket-Key", key)
            .header("Connection", "Upgrade")
            .header("Upgrade", "websocket")
            .header("Sec-WebSocket-Version", "13")
            .body(())
            .unwrap();

        let (mut ws_stream, _) = connect_async(request).await.expect("Failed to connect");

        ws_stream
            .send(Message::Text(request_text.to_string()))
            .await
            .expect("Failed to send a message");

        dbg!(ws_stream.next().await);
    }
@niklasad1
Copy link
Member

Hey @chikko80

It's bit hard to understand what the issue is from my side of things, if you could instantiate a tracing subscriber and use RUST_LOG=jsonrpsee=trace and paste the logs that would be a big help.

Do you know the format of subscription notifications as the server sends out?

Maybe it's interpreted as a close notification or something....

@chikko80
Copy link
Author

chikko80 commented Jun 16, 2023

@niklasad1
thanks for your fast support - yeah tracing subscriber makes sense seems like there is a parsing error:

2023-06-16T22:58:40.306221Z TRACE subscription{method="subscribe"}: /home/dex/.cargo/registry/src/github.com-1ecc6299db9ec823/jsonrpsee-core-0.18.2/src/tracing.rs:8: send="{\"jsonrpc\":\"2.0\",\"id\":0,\"method\":\"subscribe\",\"params\":[\"newTxs\",{\"include\":[\"tx_hash\"]}]}"
2023-06-16T22:58:40.306325Z TRACE /home/dex/.cargo/registry/src/github.com-1ecc6299db9ec823/jsonrpsee-client-transport-0.18.2/src/ws/mod.rs:227: send: {"jsonrpc":"2.0","id":0,"method":"subscribe","params":["newTxs",{"include":["tx_hash"]}]}
2023-06-16T22:58:40.419312Z TRACE subscription{method="subscribe"}: /home/dex/.cargo/registry/src/github.com-1ecc6299db9ec823/jsonrpsee-core-0.18.2/src/tracing.rs:34: recv="{\"jsonrpc\":\"2.0\",\"result\":\"9e0b132e-46dd-4d6e-b92b-cab2b6f8a92b\",\"id\":1}"
2023-06-16T22:58:40.519506Z ERROR /home/dex/.cargo/registry/src/github.com-1ecc6299db9ec823/jsonrpsee-core-0.18.2/src/client/async_client/mod.rs:770: [backend]: Custom error: Unparseable message: {"id":0,"method":"subscribe","params":{"subscription":"9e0b132e-46dd-4d6e-b92b-cab2b6f8a92b","result":{"txHash":"0xfef682e838b1a255ec58d87ec0e6dfc42de490a0f6bef59669ad1bb5efd78f78"}}}

Seems like the lib can't parse that format:

{"id":0,"method":"subscribe","params":{"subscription":"9e0b132e-46dd-4d6e-b92b-cab2b6f8a92b","result":{"txHash":"0xfef682e838b1a255ec58d87ec0e6dfc42de490a0f6bef59669ad1bb5efd78f78"}}}

Update:

/// JSON-RPC notification (a request object without a request ID) as defined in the
/// [spec](https://www.jsonrpc.org/specification#request-object).
#[derive(Serialize, Deserialize, Debug)]
pub struct Notification<'a, T> {
	/// JSON-RPC version.
	pub jsonrpc: TwoPointZero,
	/// Name of the method to be invoked.
	#[serde(borrow)]
	pub method: Cow<'a, str>,
	/// Parameter values of the request.
	pub params: T,
}

Seems like the missing "jsonrpc":"2.0" in the response is the problem right?
This is obviously a problem of the endpoint itself cause the protocol is basically jsonrpc.
Is there any way to make this work with that library?

@niklasad1
Copy link
Member

Ok, I see.

Previously, we made the interpretation that jsonrpc field must exist but recently #1045 explained to me that it could be interpreted as optional.

So, it's fine to change this as well to

/// JSON-RPC notification (a request object without a request ID) as defined in the
/// [spec](https://www.jsonrpc.org/specification#request-object).
#[derive(Serialize, Deserialize, Debug)]
pub struct Notification<'a, T> {
	/// JSON-RPC version.
	pub jsonrpc: Option<TwoPointZero>,
	/// Name of the method to be invoked.
	#[serde(borrow)]
	pub method: Cow<'a, str>,
	/// Parameter values of the request.
	pub params: T,
}

Are you down to make a PR?

@chikko80
Copy link
Author

@niklasad1
Please checkout the change on my branch. I just made the jsonrpc of the Notification optional.
I guess it makes sense to keep the jsonrpc required for the Request struct?
I wasn't sure about the NotificationSer struct. Don't really understand the usecase of that one.
Let me know what you think about / if i should change anything else

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants