Skip to content

feat: add hermes client #2931

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

Merged
merged 1 commit into from
Aug 7, 2025
Merged

feat: add hermes client #2931

merged 1 commit into from
Aug 7, 2025

Conversation

keyvankhademi
Copy link
Contributor

Summary

This PR adds a resilient hermes client that will be published to cargo

Rationale

We use hermes in multiple services, including hermes publisher and circuit breaker in lazer. This crate allows us to easily get data from hermes while having resiliency.

How has this been tested?

  • Current tests cover my changes
  • Added new tests
  • Manually tested the code

Manually ran the code.

@keyvankhademi keyvankhademi requested a review from a team as a code owner August 7, 2025 00:15
Copy link

vercel bot commented Aug 7, 2025

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
api-reference ✅ Ready (Inspect) Visit Preview 💬 Add feedback Aug 7, 2025 0:20am
component-library ✅ Ready (Inspect) Visit Preview 💬 Add feedback Aug 7, 2025 0:20am
developer-hub ✅ Ready (Inspect) Visit Preview 💬 Add feedback Aug 7, 2025 0:20am
entropy-debugger ✅ Ready (Inspect) Visit Preview 💬 Add feedback Aug 7, 2025 0:20am
entropy-explorer ✅ Ready (Inspect) Visit Preview 💬 Add feedback Aug 7, 2025 0:20am
insights ✅ Ready (Inspect) Visit Preview 💬 Add feedback Aug 7, 2025 0:20am
proposals ✅ Ready (Inspect) Visit Preview 💬 Add feedback Aug 7, 2025 0:20am
staking ✅ Ready (Inspect) Visit Preview 💬 Add feedback Aug 7, 2025 0:20am

Copy link
Contributor

@tejasbadadare tejasbadadare left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like this client is focused specifically on the websockets endpoint. Should we rename it to pyth-hermes-websockets-client instead of pyth-hermes-client which implies that it's a client that implements the Hermes OpenAPI spec?

Also, i believe we want to push the public to use the SSE endpoint, not WS. If we release a client for the (undocumented) WS endpoint it could be confusing for end users. Maybe we keep it privately published?

Sidenote, I actually had Devin generate a rust client a while ago from the OpenAPI spec plus SSE support but never got around to merging and publishing it.

@keyvankhademi
Copy link
Contributor Author

Looks like this client is focused specifically on the websockets endpoint. Should we rename it to pyth-hermes-websockets-client instead of pyth-hermes-client which implies that it's a client that implements the Hermes OpenAPI spec?

Also, i believe we want to push the public to use the SSE endpoint, not WS. If we release a client for the (undocumented) WS endpoint it could be confusing for end users. Maybe we keep it privately published?

Sidenote, I actually had Devin generate a rust client a while ago from the OpenAPI spec plus SSE support but never got around to merging and publishing it.

We might add more features to it in future depending on our/clients needs. I don't think we should deprecate the WS anymore as we have seen it has benefits over SSE; that's why we have changed it to ws in circuit breaker.

Copy link
Contributor

@darunrs darunrs left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice!

license = "Apache-2.0"

[dependencies]
pyth-sdk = { version = "0.8.0" }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we instead read the hermes structs since it seems it defines things (metadata) that isn't in pyth-sdk?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i tried that, it doesn't work out of the box and require changes to the hermes server, which I don't think is worth doing.

/// This struct encapsulates the parameters needed to configure exponential backoff
/// behavior and can be converted into the backoff crate's [`ExponentialBackoff`] type.
#[derive(Debug)]
pub struct HermesExponentialBackoff {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the value add of defining a wrapper struct around expo backoff? I don't seem to see any additional features or behavior?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is a feature that we don't support max_elapsed_time iirc.

timeout: Duration,
channel_capacity: usize,
) -> Result<Self> {
if endpoints.is_empty() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should add a check to ensure num_connections is also zero.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this causes panic. num connections being 0 i think doesn't panic.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It could cause strange invisible behavior such as the client running but doing nothing. Given this is a customer facing function, I figure it's good to communicate to them any behavior we don't expect.

}

#[derive(Deserialize, Serialize, Debug, Clone, Hash)]
pub struct HermesPrice {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you provide doc comments there explaining that price and publish time can be 0 if the feed is disabled, and that the publish time can also be when a market closes, and doesn't change? It's useful behavior to document since it changes how the data can be handled.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a hermes behavior and I think should be documented in hermes api docs.

@keyvankhademi keyvankhademi merged commit 6c7165e into main Aug 7, 2025
10 checks passed
@keyvankhademi keyvankhademi deleted the hermes-client branch August 7, 2025 18:19
@tejasbadadare
Copy link
Contributor

Looks like this client is focused specifically on the websockets endpoint. Should we rename it to pyth-hermes-websockets-client instead of pyth-hermes-client which implies that it's a client that implements the Hermes OpenAPI spec?
Also, i believe we want to push the public to use the SSE endpoint, not WS. If we release a client for the (undocumented) WS endpoint it could be confusing for end users. Maybe we keep it privately published?
Sidenote, I actually had Devin generate a rust client a while ago from the OpenAPI spec plus SSE support but never got around to merging and publishing it.

We might add more features to it in future depending on our/clients needs. I don't think we should deprecate the WS anymore as we have seen it has benefits over SSE; that's why we have changed it to ws in circuit breaker.

Yeah true if we are relying on it for Lazer, we should undeprecate it. I'd wanna understand why we initially hid it from public use though and pushed people to use SSE. cc @ali-behjati

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 this pull request may close these issues.

3 participants