Skip to content

Commit 1956d58

Browse files
authored
feat: update hermes to support publisher stake caps (#1866)
* go * go * works * go * add this file too * rename * cleanup * udno dependency update * fix: use v2 routes * fix: move response struct * fix: some renames * fix: get_price_feed_ids * bump: hermes
1 parent a9659a2 commit 1956d58

File tree

11 files changed

+197
-12
lines changed

11 files changed

+197
-12
lines changed

apps/hermes/server/Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

apps/hermes/server/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "hermes"
3-
version = "0.5.17"
3+
version = "0.6.0"
44
description = "Hermes is an agent that provides Verified Prices from the Pythnet Pyth Oracle."
55
edition = "2021"
66

apps/hermes/server/src/api.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ where
111111
rest::latest_vaas,
112112
rest::price_feed_ids,
113113
rest::latest_price_updates,
114+
rest::latest_publisher_stake_caps,
114115
rest::timestamp_price_updates,
115116
rest::price_feeds_metadata,
116117
rest::price_stream_sse_handler,
@@ -127,7 +128,7 @@ where
127128
types::RpcPriceIdentifier,
128129
types::EncodingType,
129130
types::PriceUpdate,
130-
types::BinaryPriceUpdate,
131+
types::BinaryUpdate,
131132
types::ParsedPriceUpdate,
132133
types::RpcPriceFeedMetadataV2,
133134
types::PriceFeedMetadata,
@@ -158,6 +159,10 @@ where
158159
get(rest::price_stream_sse_handler),
159160
)
160161
.route("/v2/updates/price/latest", get(rest::latest_price_updates))
162+
.route(
163+
"/v2/updates/publisher_stake_caps/latest",
164+
get(rest::latest_publisher_stake_caps),
165+
)
161166
.route(
162167
"/v2/updates/price/:publish_time",
163168
get(rest::timestamp_price_updates),

apps/hermes/server/src/api/rest.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ pub use {
3535
ready::*,
3636
v2::{
3737
latest_price_updates::*,
38+
latest_publisher_stake_caps::*,
3839
price_feeds_metadata::*,
3940
sse::*,
4041
timestamp_price_updates::*,

apps/hermes/server/src/api/rest/v2/latest_price_updates.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use {
66
RestError,
77
},
88
types::{
9-
BinaryPriceUpdate,
9+
BinaryUpdate,
1010
EncodingType,
1111
ParsedPriceUpdate,
1212
PriceIdInput,
@@ -108,7 +108,7 @@ where
108108
EncodingType::Hex => hex::encode(data),
109109
})
110110
.collect();
111-
let binary_price_update = BinaryPriceUpdate {
111+
let binary_price_update = BinaryUpdate {
112112
encoding: params.encoding,
113113
data: encoded_data,
114114
};
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
use {
2+
crate::{
3+
api::{
4+
rest::RestError,
5+
types::{
6+
BinaryUpdate,
7+
EncodingType,
8+
ParsedPublisherStakeCapsUpdate,
9+
},
10+
ApiState,
11+
},
12+
state::Aggregates,
13+
},
14+
anyhow::Result,
15+
axum::{
16+
extract::State,
17+
Json,
18+
},
19+
base64::{
20+
engine::general_purpose::STANDARD as base64_standard_engine,
21+
Engine as _,
22+
},
23+
serde::{
24+
Deserialize,
25+
Serialize,
26+
},
27+
serde_qs::axum::QsQuery,
28+
utoipa::{
29+
IntoParams,
30+
ToSchema,
31+
},
32+
};
33+
34+
35+
#[derive(Debug, Deserialize, IntoParams)]
36+
#[into_params(parameter_in=Query)]
37+
pub struct LatestPublisherStakeCapsUpdateData {
38+
/// Get the most recent publisher stake caps update data.
39+
40+
/// Optional encoding type. If true, return the message in the encoding specified by the encoding parameter. Default is `hex`.
41+
#[serde(default)]
42+
encoding: EncodingType,
43+
44+
/// If true, include the parsed update in the `parsed` field of each returned feed. Default is `true`.
45+
#[serde(default = "default_true")]
46+
parsed: bool,
47+
}
48+
49+
fn default_true() -> bool {
50+
true
51+
}
52+
53+
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
54+
pub struct LatestPublisherStakeCapsUpdateDataResponse {
55+
pub binary: BinaryUpdate,
56+
#[serde(skip_serializing_if = "Option::is_none")]
57+
pub parsed: Option<Vec<ParsedPublisherStakeCapsUpdate>>,
58+
}
59+
60+
/// Get the most recent publisher stake caps update data.
61+
#[utoipa::path(
62+
get,
63+
path = "/v2/updates/publisher_stake_caps/latest",
64+
responses(
65+
(status = 200, description = "Publisher stake caps update data retrieved succesfully", body = Vec<PriceFeedMetadata>)
66+
),
67+
params(
68+
LatestPublisherStakeCapsUpdateData
69+
)
70+
)]
71+
pub async fn latest_publisher_stake_caps<S>(
72+
State(state): State<ApiState<S>>,
73+
QsQuery(params): QsQuery<LatestPublisherStakeCapsUpdateData>,
74+
) -> Result<Json<LatestPublisherStakeCapsUpdateDataResponse>, RestError>
75+
where
76+
S: Aggregates,
77+
{
78+
let state = &*state.state;
79+
let publisher_stake_caps_with_update_data =
80+
Aggregates::get_latest_publisher_stake_caps_with_update_data(state)
81+
.await
82+
.map_err(|e| {
83+
tracing::warn!(
84+
"Error getting publisher stake caps with update data: {:?}",
85+
e
86+
);
87+
RestError::UpdateDataNotFound
88+
})?;
89+
90+
let encoded_data: Vec<String> = publisher_stake_caps_with_update_data
91+
.update_data
92+
.into_iter()
93+
.map(|data| match params.encoding {
94+
EncodingType::Base64 => base64_standard_engine.encode(data),
95+
EncodingType::Hex => hex::encode(data),
96+
})
97+
.collect();
98+
99+
let binary = BinaryUpdate {
100+
encoding: params.encoding,
101+
data: encoded_data,
102+
};
103+
104+
let parsed: Option<Vec<ParsedPublisherStakeCapsUpdate>> = if params.parsed {
105+
Some(publisher_stake_caps_with_update_data.publisher_stake_caps)
106+
} else {
107+
None
108+
};
109+
110+
Ok(Json(LatestPublisherStakeCapsUpdateDataResponse {
111+
binary,
112+
parsed,
113+
}))
114+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
pub mod latest_price_updates;
2+
pub mod latest_publisher_stake_caps;
23
pub mod price_feeds_metadata;
34
pub mod sse;
45
pub mod timestamp_price_updates;

apps/hermes/server/src/api/rest/v2/sse.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use {
66
RestError,
77
},
88
types::{
9-
BinaryPriceUpdate,
9+
BinaryUpdate,
1010
EncodingType,
1111
ParsedPriceUpdate,
1212
PriceIdInput,
@@ -211,7 +211,7 @@ where
211211
.into_iter()
212212
.map(|data| encoding.encode_str(&data))
213213
.collect();
214-
let binary_price_update = BinaryPriceUpdate {
214+
let binary_price_update = BinaryUpdate {
215215
encoding,
216216
data: encoded_data,
217217
};

apps/hermes/server/src/api/rest/v2/timestamp_price_updates.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use {
77
RestError,
88
},
99
types::{
10-
BinaryPriceUpdate,
10+
BinaryUpdate,
1111
EncodingType,
1212
ParsedPriceUpdate,
1313
PriceIdInput,
@@ -123,7 +123,7 @@ where
123123
.into_iter()
124124
.map(|data| query_params.encoding.encode_str(&data))
125125
.collect();
126-
let binary_price_update = BinaryPriceUpdate {
126+
let binary_price_update = BinaryUpdate {
127127
encoding: query_params.encoding,
128128
data: encoded_data,
129129
};

apps/hermes/server/src/api/types.rs

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ use {
2828
Deserialize,
2929
Serialize,
3030
},
31+
solana_sdk::pubkey::Pubkey,
3132
std::{
3233
collections::BTreeMap,
3334
fmt::{
@@ -40,6 +41,7 @@ use {
4041
wormhole_sdk::Chain,
4142
};
4243

44+
4345
/// A price id is a 32-byte hex string, optionally prefixed with "0x".
4446
/// Price ids are case insensitive.
4547
///
@@ -231,7 +233,7 @@ impl EncodingType {
231233
}
232234

233235
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
234-
pub struct BinaryPriceUpdate {
236+
pub struct BinaryUpdate {
235237
pub encoding: EncodingType,
236238
pub data: Vec<String>,
237239
}
@@ -271,9 +273,21 @@ impl From<PriceFeedUpdate> for ParsedPriceUpdate {
271273
}
272274
}
273275

276+
#[derive(Debug, PartialEq, serde::Serialize, serde::Deserialize, Clone)]
277+
pub struct ParsedPublisherStakeCapsUpdate {
278+
pub publisher_stake_caps: Vec<ParsedPublisherStakeCap>,
279+
}
280+
281+
#[derive(Debug, PartialEq, serde::Serialize, serde::Deserialize, Clone)]
282+
pub struct ParsedPublisherStakeCap {
283+
#[serde(with = "pyth_sdk::utils::as_string")]
284+
pub publisher: Pubkey,
285+
pub cap: u64,
286+
}
287+
274288
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
275289
pub struct PriceUpdate {
276-
pub binary: BinaryPriceUpdate,
290+
pub binary: BinaryUpdate,
277291
#[serde(skip_serializing_if = "Option::is_none")]
278292
pub parsed: Option<Vec<ParsedPriceUpdate>>,
279293
}

0 commit comments

Comments
 (0)