pyth_lazer_protocol/
lib.rs

1//! Lazer type definitions and utilities.
2
3/// Types describing Lazer HTTP and WebSocket APIs.
4pub mod api;
5/// Binary delivery format for WebSocket.
6pub mod binary_update;
7mod dynamic_value;
8mod feed_kind;
9/// Lazer Agent JSON-RPC API.
10pub mod jrpc;
11/// Types describing Lazer's verifiable messages containing signature and payload.
12pub mod message;
13/// Types describing Lazer's message payload.
14pub mod payload;
15mod price;
16/// Legacy Websocket API for publishers.
17pub mod publisher;
18mod rate;
19mod serde_price_as_i64;
20mod serde_str;
21mod symbol_state;
22/// Lazer's types for time representation.
23pub mod time;
24
25use derive_more::derive::{From, Into};
26use serde::{Deserialize, Serialize};
27
28pub use crate::{
29    dynamic_value::DynamicValue,
30    feed_kind::FeedKind,
31    price::{Price, PriceError},
32    rate::{Rate, RateError},
33    symbol_state::SymbolState,
34};
35
36#[derive(
37    Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize, From, Into,
38)]
39pub struct PublisherId(pub u16);
40
41#[derive(
42    Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize, From, Into,
43)]
44pub struct PriceFeedId(pub u32);
45
46#[derive(
47    Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize, From, Into,
48)]
49pub struct ChannelId(pub u8);
50
51impl ChannelId {
52    pub const REAL_TIME: ChannelId = ChannelId(1);
53    pub const FIXED_RATE_50: ChannelId = ChannelId(2);
54    pub const FIXED_RATE_200: ChannelId = ChannelId(3);
55}
56
57#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
58#[serde(rename_all = "camelCase")]
59pub enum PriceFeedProperty {
60    Price,
61    BestBidPrice,
62    BestAskPrice,
63    PublisherCount,
64    Exponent,
65    Confidence,
66    FundingRate,
67    FundingTimestamp,
68    FundingRateInterval,
69    // More fields may be added later.
70}
71
72// Operation and coefficient for converting value to mantissa.
73enum ExponentFactor {
74    // mantissa = value * factor
75    Mul(i64),
76    // mantissa = value / factor
77    Div(i64),
78}
79
80impl ExponentFactor {
81    fn get(exponent: i16) -> Option<Self> {
82        if exponent >= 0 {
83            let exponent: u32 = exponent.try_into().ok()?;
84            Some(ExponentFactor::Div(10_i64.checked_pow(exponent)?))
85        } else {
86            let minus_exponent: u32 = exponent.checked_neg()?.try_into().ok()?;
87            Some(ExponentFactor::Mul(10_i64.checked_pow(minus_exponent)?))
88        }
89    }
90}
91
92#[test]
93fn magics_in_big_endian() {
94    use crate::{
95        binary_update::BINARY_UPDATE_FORMAT_MAGIC,
96        message::format_magics_le::{
97            EVM_FORMAT_MAGIC, JSON_FORMAT_MAGIC, LE_ECDSA_FORMAT_MAGIC, LE_UNSIGNED_FORMAT_MAGIC,
98            SOLANA_FORMAT_MAGIC,
99        },
100        payload::PAYLOAD_FORMAT_MAGIC,
101    };
102
103    // The values listed in this test can be used when reading the magic headers in BE format
104    // (e.g., on EVM).
105
106    assert_eq!(u32::swap_bytes(BINARY_UPDATE_FORMAT_MAGIC), 1937213467);
107    assert_eq!(u32::swap_bytes(PAYLOAD_FORMAT_MAGIC), 1976813459);
108
109    assert_eq!(u32::swap_bytes(SOLANA_FORMAT_MAGIC), 3103857282);
110    assert_eq!(u32::swap_bytes(JSON_FORMAT_MAGIC), 2584795844);
111    assert_eq!(u32::swap_bytes(EVM_FORMAT_MAGIC), 706910618);
112    assert_eq!(u32::swap_bytes(LE_ECDSA_FORMAT_MAGIC), 3837609805);
113    assert_eq!(u32::swap_bytes(LE_UNSIGNED_FORMAT_MAGIC), 206398297);
114
115    for magic in [
116        BINARY_UPDATE_FORMAT_MAGIC,
117        PAYLOAD_FORMAT_MAGIC,
118        SOLANA_FORMAT_MAGIC,
119        JSON_FORMAT_MAGIC,
120        EVM_FORMAT_MAGIC,
121        LE_ECDSA_FORMAT_MAGIC,
122        LE_UNSIGNED_FORMAT_MAGIC,
123    ] {
124        // Required to distinguish between byte orders.
125        assert_ne!(u32::swap_bytes(magic), magic);
126    }
127}