-
Notifications
You must be signed in to change notification settings - Fork 297
feat(lazer-protocol): add Metadata V3 response types #3111
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
base: main
Are you sure you want to change the base?
Conversation
The latest updates on your projects. Learn more about Vercel for GitHub.
|
/// Commodity | ||
Commodity, | ||
/// Funding rate | ||
FundingRate, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is this really an asset class?
/// High-level asset class. | ||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)] | ||
#[serde(rename_all = "kebab-case")] | ||
pub enum AssetClass { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One of the reasons for opting in a dynamic metadata was to not go through a code change when new asset classes are added to the system. I know that users (on both sides) rely on these, and that's probably why you opted for explicit definition here. But if that's the case, you might actually remove any dynamic field and make everything very explicit. Being in the middle (some explicit metadata, some implicit dynamic) is probably worse.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should stick with our decision and use fully dynamic metadata in the protocols. In Rust that would be BTreeMap<String, serde_value::Value>
. We can revisit it later if we feel like the metadata structure is very stable and future-proof, but I doubt that it will happen soon.
/// Rates | ||
Rates, | ||
/// Net Asset Value | ||
Nav, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This also doesn't seem to be an asset class, it's a feed/instrument type.
/// Unique human-readable identifier for a feed. | ||
/// Format: `source.instrument_type.base/quote` | ||
/// Examples: `"pyth.spot.btc/usd"`, `"pyth.redemptionrate.alp/usd"`, `"binance.fundingrate.btc/usdt"`, `"pyth.future.emz5/usd"` | ||
pub symbol: String, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i recommend opting for a specific type with validation here to ensure it's correct.
q: what if the asset has no quote asset? (such as rates)
/// CoinMarketCap asset identifier. | ||
/// Example: `"123"` | ||
#[serde(skip_serializing_if = "Option::is_none")] | ||
pub cmc_id: Option<String>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i wonder whether you considered @jayantk suggestion on having a nested struct as "external mappings". It's probably more difficult on the DB layer.
pub feed_expiry: Option<String>, | ||
/// The nature of the data produced by the feed. | ||
/// Examples: `"price"`, `"fundingRate"` | ||
pub feed_kind: FeedKind, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmmm so we do have a feedkind and an instrument type. I wonder whether we can merge them.
/// ISO datetime after which the feed will no longer produce prices because the underlying market has expired. | ||
/// Example: `"2025-10-03T11:08:10.089998603Z"` | ||
#[serde(skip_serializing_if = "Option::is_none")] | ||
pub feed_expiry: Option<String>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use a datetime type or an integer based timestamp (i bet we should have something similar in our code)
/// Example: `"stablecoin"` | ||
#[serde(skip_serializing_if = "Option::is_none")] | ||
pub subclass: Option<String>, | ||
/// Primary or canonical listing exchange, when applicable. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmmm, what if there are multiple?
i suggest renaming the field to primary_exchange
or something similar here. not sure listing_exchange
is clear.
Summary
Add types for output representations of the Metadata v3 API.
FeedResponseV3
: Returned by the/v3/feeds
APIsAssetResponseV3
: Returned by the/v3/assets
APIs/v1/symbols
API will continue to return thehistory_service::api::SymbolResponse
from Lazer internals for the time being. In the future, this type should be unified with the duplicated one in the protocol crate (pyth_lazer_protocol::jrpc::SymbolMetadata
, used by History client).How has this been tested?