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    pub const FIXED_RATE_1000: ChannelId = ChannelId(4);
56}
57
58#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
59#[serde(rename_all = "camelCase")]
60pub enum PriceFeedProperty {
61    Price,
62    BestBidPrice,
63    BestAskPrice,
64    PublisherCount,
65    Exponent,
66    Confidence,
67    FundingRate,
68    FundingTimestamp,
69    FundingRateInterval,
70    // More fields may be added later.
71}
72
73// Operation and coefficient for converting value to mantissa.
74enum ExponentFactor {
75    // mantissa = value * factor
76    Mul(i64),
77    // mantissa = value / factor
78    Div(i64),
79}
80
81impl ExponentFactor {
82    fn get(exponent: i16) -> Option<Self> {
83        if exponent >= 0 {
84            let exponent: u32 = exponent.try_into().ok()?;
85            Some(ExponentFactor::Div(10_i64.checked_pow(exponent)?))
86        } else {
87            let minus_exponent: u32 = exponent.checked_neg()?.try_into().ok()?;
88            Some(ExponentFactor::Mul(10_i64.checked_pow(minus_exponent)?))
89        }
90    }
91}
92
93#[test]
94fn magics_in_big_endian() {
95    use crate::{
96        binary_update::BINARY_UPDATE_FORMAT_MAGIC,
97        message::format_magics_le::{
98            EVM_FORMAT_MAGIC, JSON_FORMAT_MAGIC, LE_ECDSA_FORMAT_MAGIC, LE_UNSIGNED_FORMAT_MAGIC,
99            SOLANA_FORMAT_MAGIC,
100        },
101        payload::PAYLOAD_FORMAT_MAGIC,
102    };
103
104    // The values listed in this test can be used when reading the magic headers in BE format
105    // (e.g., on EVM).
106
107    assert_eq!(u32::swap_bytes(BINARY_UPDATE_FORMAT_MAGIC), 1937213467);
108    assert_eq!(u32::swap_bytes(PAYLOAD_FORMAT_MAGIC), 1976813459);
109
110    assert_eq!(u32::swap_bytes(SOLANA_FORMAT_MAGIC), 3103857282);
111    assert_eq!(u32::swap_bytes(JSON_FORMAT_MAGIC), 2584795844);
112    assert_eq!(u32::swap_bytes(EVM_FORMAT_MAGIC), 706910618);
113    assert_eq!(u32::swap_bytes(LE_ECDSA_FORMAT_MAGIC), 3837609805);
114    assert_eq!(u32::swap_bytes(LE_UNSIGNED_FORMAT_MAGIC), 206398297);
115
116    for magic in [
117        BINARY_UPDATE_FORMAT_MAGIC,
118        PAYLOAD_FORMAT_MAGIC,
119        SOLANA_FORMAT_MAGIC,
120        JSON_FORMAT_MAGIC,
121        EVM_FORMAT_MAGIC,
122        LE_ECDSA_FORMAT_MAGIC,
123        LE_UNSIGNED_FORMAT_MAGIC,
124    ] {
125        // Required to distinguish between byte orders.
126        assert_ne!(u32::swap_bytes(magic), magic);
127    }
128}