Skip to main content

pyth_lazer_publisher_sdk/
lib.rs

1use crate::publisher_update::feed_update::Update;
2use crate::publisher_update::{FeedUpdate, FundingRateUpdate, PriceUpdate};
3use crate::state::FeedState;
4use ::protobuf::{EnumOrUnknown, MessageField};
5use pyth_lazer_protocol::jrpc::{FeedUpdateParams, UpdateParams};
6use pyth_lazer_protocol::{
7    ExchangeAssetClass, ExchangeAssetSector, ExchangeAssetSubclass, FeedKind, SymbolState,
8};
9
10pub mod transaction_envelope {
11    pub use crate::protobuf::transaction_envelope::*;
12}
13
14pub mod transaction {
15    pub use crate::protobuf::pyth_lazer_transaction::*;
16}
17
18pub mod publisher_update {
19    pub use crate::protobuf::publisher_update::*;
20}
21
22pub mod governance_instruction {
23    pub use crate::protobuf::governance_instruction::*;
24}
25
26pub mod state {
27    pub use crate::protobuf::state::*;
28}
29
30pub mod dynamic_value {
31    pub use crate::protobuf::dynamic_value::*;
32}
33
34#[allow(rustdoc::broken_intra_doc_links)]
35mod protobuf;
36
37mod convert_dynamic_value;
38
39impl From<FeedUpdateParams> for FeedUpdate {
40    fn from(value: FeedUpdateParams) -> Self {
41        FeedUpdate {
42            feed_id: Some(value.feed_id.0),
43            source_timestamp: value.source_timestamp.into(),
44            update: Some(value.update.into()),
45            special_fields: Default::default(),
46        }
47    }
48}
49
50impl From<UpdateParams> for Update {
51    fn from(value: UpdateParams) -> Self {
52        match value {
53            UpdateParams::PriceUpdate {
54                price,
55                best_bid_price,
56                best_ask_price,
57                trading_status,
58                market_session,
59            } => Update::PriceUpdate(PriceUpdate {
60                price: price.map(|p| p.mantissa_i64()),
61                best_bid_price: best_bid_price.map(|p| p.mantissa_i64()),
62                best_ask_price: best_ask_price.map(|p| p.mantissa_i64()),
63                trading_status: trading_status
64                    .map(|ts| EnumOrUnknown::from(state::TradingStatus::from(ts))),
65                market_session: market_session
66                    .map(|ms| EnumOrUnknown::from(state::MarketSession::from(ms))),
67                special_fields: Default::default(),
68            }),
69            UpdateParams::FundingRateUpdate {
70                price,
71                rate,
72                funding_rate_interval,
73            } => Update::FundingRateUpdate(FundingRateUpdate {
74                price: price.map(|p| p.mantissa_i64()),
75                rate: Some(rate.mantissa()),
76                funding_rate_interval: MessageField::from_option(
77                    funding_rate_interval.map(|i| i.into()),
78                ),
79                special_fields: Default::default(),
80            }),
81        }
82    }
83}
84
85impl From<FeedState> for SymbolState {
86    fn from(value: FeedState) -> Self {
87        match value {
88            FeedState::COMING_SOON => SymbolState::ComingSoon,
89            FeedState::STABLE => SymbolState::Stable,
90            FeedState::INACTIVE => SymbolState::Inactive,
91            FeedState::BETA => SymbolState::Beta,
92        }
93    }
94}
95
96impl From<SymbolState> for FeedState {
97    fn from(value: SymbolState) -> Self {
98        match value {
99            SymbolState::ComingSoon => FeedState::COMING_SOON,
100            SymbolState::Stable => FeedState::STABLE,
101            SymbolState::Inactive => FeedState::INACTIVE,
102            SymbolState::Beta => FeedState::BETA,
103        }
104    }
105}
106
107impl From<FeedKind> for state::FeedKind {
108    fn from(value: FeedKind) -> Self {
109        match value {
110            FeedKind::Price => state::FeedKind::PRICE,
111            FeedKind::FundingRate => state::FeedKind::FUNDING_RATE,
112        }
113    }
114}
115
116impl From<state::FeedKind> for FeedKind {
117    fn from(value: state::FeedKind) -> Self {
118        match value {
119            state::FeedKind::PRICE => FeedKind::Price,
120            state::FeedKind::FUNDING_RATE => FeedKind::FundingRate,
121        }
122    }
123}
124
125impl TryFrom<state::Channel> for pyth_lazer_protocol::api::Channel {
126    type Error = anyhow::Error;
127
128    fn try_from(value: state::Channel) -> Result<Self, Self::Error> {
129        Ok(match value.kind {
130            Some(kind) => match kind {
131                state::channel::Kind::Rate(rate) => {
132                    pyth_lazer_protocol::api::Channel::FixedRate(rate.try_into()?)
133                }
134                state::channel::Kind::RealTime(_) => pyth_lazer_protocol::api::Channel::RealTime,
135            },
136            None => pyth_lazer_protocol::api::Channel::FixedRate(
137                pyth_lazer_protocol::time::FixedRate::MIN,
138            ),
139        })
140    }
141}
142
143impl From<pyth_lazer_protocol::api::Channel> for state::Channel {
144    fn from(value: pyth_lazer_protocol::api::Channel) -> Self {
145        let mut result = state::Channel::new();
146        match value {
147            pyth_lazer_protocol::api::Channel::FixedRate(rate) => {
148                result.set_rate(rate.into());
149            }
150            pyth_lazer_protocol::api::Channel::RealTime => {
151                result.set_real_time(::protobuf::well_known_types::empty::Empty::new());
152            }
153        };
154        result
155    }
156}
157
158impl From<pyth_lazer_protocol::api::MarketSession> for state::MarketSession {
159    fn from(value: pyth_lazer_protocol::api::MarketSession) -> Self {
160        match value {
161            pyth_lazer_protocol::api::MarketSession::Regular => state::MarketSession::REGULAR,
162            pyth_lazer_protocol::api::MarketSession::PreMarket => state::MarketSession::PRE_MARKET,
163            pyth_lazer_protocol::api::MarketSession::PostMarket => {
164                state::MarketSession::POST_MARKET
165            }
166            pyth_lazer_protocol::api::MarketSession::OverNight => state::MarketSession::OVER_NIGHT,
167            pyth_lazer_protocol::api::MarketSession::Closed => state::MarketSession::CLOSED,
168        }
169    }
170}
171
172impl From<state::MarketSession> for pyth_lazer_protocol::api::MarketSession {
173    fn from(value: state::MarketSession) -> Self {
174        match value {
175            state::MarketSession::REGULAR => pyth_lazer_protocol::api::MarketSession::Regular,
176            state::MarketSession::PRE_MARKET => pyth_lazer_protocol::api::MarketSession::PreMarket,
177            state::MarketSession::POST_MARKET => {
178                pyth_lazer_protocol::api::MarketSession::PostMarket
179            }
180            state::MarketSession::OVER_NIGHT => pyth_lazer_protocol::api::MarketSession::OverNight,
181            state::MarketSession::CLOSED => pyth_lazer_protocol::api::MarketSession::Closed,
182        }
183    }
184}
185
186impl From<pyth_lazer_protocol::api::TradingStatus> for state::TradingStatus {
187    fn from(value: pyth_lazer_protocol::api::TradingStatus) -> Self {
188        match value {
189            pyth_lazer_protocol::api::TradingStatus::Open => {
190                state::TradingStatus::TRADING_STATUS_OPEN
191            }
192            pyth_lazer_protocol::api::TradingStatus::Closed => {
193                state::TradingStatus::TRADING_STATUS_CLOSED
194            }
195            pyth_lazer_protocol::api::TradingStatus::Halted => {
196                state::TradingStatus::TRADING_STATUS_HALTED
197            }
198            pyth_lazer_protocol::api::TradingStatus::CorpAction => {
199                state::TradingStatus::TRADING_STATUS_CORP_ACTION
200            }
201        }
202    }
203}
204
205impl From<state::TradingStatus> for pyth_lazer_protocol::api::TradingStatus {
206    fn from(value: state::TradingStatus) -> Self {
207        match value {
208            state::TradingStatus::TRADING_STATUS_OPEN => {
209                pyth_lazer_protocol::api::TradingStatus::Open
210            }
211            state::TradingStatus::TRADING_STATUS_CLOSED => {
212                pyth_lazer_protocol::api::TradingStatus::Closed
213            }
214            state::TradingStatus::TRADING_STATUS_HALTED => {
215                pyth_lazer_protocol::api::TradingStatus::Halted
216            }
217            state::TradingStatus::TRADING_STATUS_CORP_ACTION => {
218                pyth_lazer_protocol::api::TradingStatus::CorpAction
219            }
220        }
221    }
222}
223
224impl From<state::ExchangeAssetClass> for ExchangeAssetClass {
225    fn from(value: state::ExchangeAssetClass) -> Self {
226        match value {
227            state::ExchangeAssetClass::EXCHANGE_ASSET_CLASS_UNSPECIFIED => {
228                ExchangeAssetClass::Unspecified
229            }
230            state::ExchangeAssetClass::EXCHANGE_ASSET_CLASS_EQUITY => ExchangeAssetClass::Equity,
231            state::ExchangeAssetClass::EXCHANGE_ASSET_CLASS_FUTURE => ExchangeAssetClass::Future,
232        }
233    }
234}
235
236impl From<ExchangeAssetClass> for state::ExchangeAssetClass {
237    fn from(value: ExchangeAssetClass) -> Self {
238        match value {
239            ExchangeAssetClass::Unspecified => {
240                state::ExchangeAssetClass::EXCHANGE_ASSET_CLASS_UNSPECIFIED
241            }
242            ExchangeAssetClass::Equity => state::ExchangeAssetClass::EXCHANGE_ASSET_CLASS_EQUITY,
243            ExchangeAssetClass::Future => state::ExchangeAssetClass::EXCHANGE_ASSET_CLASS_FUTURE,
244        }
245    }
246}
247
248impl From<state::ExchangeAssetSubclass> for ExchangeAssetSubclass {
249    fn from(value: state::ExchangeAssetSubclass) -> Self {
250        match value {
251            state::ExchangeAssetSubclass::EXCHANGE_ASSET_SUBCLASS_UNSPECIFIED => {
252                ExchangeAssetSubclass::Unspecified
253            }
254            state::ExchangeAssetSubclass::EXCHANGE_ASSET_SUBCLASS_COMMON_STOCK => {
255                ExchangeAssetSubclass::CommonStock
256            }
257            state::ExchangeAssetSubclass::EXCHANGE_ASSET_SUBCLASS_ETF => ExchangeAssetSubclass::Etf,
258            state::ExchangeAssetSubclass::EXCHANGE_ASSET_SUBCLASS_ENERGY => {
259                ExchangeAssetSubclass::Energy
260            }
261            state::ExchangeAssetSubclass::EXCHANGE_ASSET_SUBCLASS_METALS => {
262                ExchangeAssetSubclass::Metals
263            }
264            state::ExchangeAssetSubclass::EXCHANGE_ASSET_SUBCLASS_EQUITY => {
265                ExchangeAssetSubclass::Equity
266            }
267            state::ExchangeAssetSubclass::EXCHANGE_ASSET_SUBCLASS_FIXED_INCOME => {
268                ExchangeAssetSubclass::FixedIncome
269            }
270            state::ExchangeAssetSubclass::EXCHANGE_ASSET_SUBCLASS_FX => ExchangeAssetSubclass::Fx,
271            state::ExchangeAssetSubclass::EXCHANGE_ASSET_SUBCLASS_AGRICULTURAL => {
272                ExchangeAssetSubclass::Agricultural
273            }
274        }
275    }
276}
277
278impl From<ExchangeAssetSubclass> for state::ExchangeAssetSubclass {
279    fn from(value: ExchangeAssetSubclass) -> Self {
280        match value {
281            ExchangeAssetSubclass::Unspecified => {
282                state::ExchangeAssetSubclass::EXCHANGE_ASSET_SUBCLASS_UNSPECIFIED
283            }
284            ExchangeAssetSubclass::CommonStock => {
285                state::ExchangeAssetSubclass::EXCHANGE_ASSET_SUBCLASS_COMMON_STOCK
286            }
287            ExchangeAssetSubclass::Etf => state::ExchangeAssetSubclass::EXCHANGE_ASSET_SUBCLASS_ETF,
288            ExchangeAssetSubclass::Energy => {
289                state::ExchangeAssetSubclass::EXCHANGE_ASSET_SUBCLASS_ENERGY
290            }
291            ExchangeAssetSubclass::Metals => {
292                state::ExchangeAssetSubclass::EXCHANGE_ASSET_SUBCLASS_METALS
293            }
294            ExchangeAssetSubclass::Equity => {
295                state::ExchangeAssetSubclass::EXCHANGE_ASSET_SUBCLASS_EQUITY
296            }
297            ExchangeAssetSubclass::FixedIncome => {
298                state::ExchangeAssetSubclass::EXCHANGE_ASSET_SUBCLASS_FIXED_INCOME
299            }
300            ExchangeAssetSubclass::Fx => state::ExchangeAssetSubclass::EXCHANGE_ASSET_SUBCLASS_FX,
301            ExchangeAssetSubclass::Agricultural => {
302                state::ExchangeAssetSubclass::EXCHANGE_ASSET_SUBCLASS_AGRICULTURAL
303            }
304        }
305    }
306}
307
308impl From<state::ExchangeAssetSector> for ExchangeAssetSector {
309    fn from(value: state::ExchangeAssetSector) -> Self {
310        match value {
311            state::ExchangeAssetSector::EXCHANGE_ASSET_SECTOR_UNSPECIFIED => {
312                ExchangeAssetSector::Unspecified
313            }
314            state::ExchangeAssetSector::EXCHANGE_ASSET_SECTOR_TECHNOLOGY => {
315                ExchangeAssetSector::Technology
316            }
317            state::ExchangeAssetSector::EXCHANGE_ASSET_SECTOR_FINANCIALS => {
318                ExchangeAssetSector::Financials
319            }
320            state::ExchangeAssetSector::EXCHANGE_ASSET_SECTOR_BROAD_MARKET => {
321                ExchangeAssetSector::BroadMarket
322            }
323            state::ExchangeAssetSector::EXCHANGE_ASSET_SECTOR_OIL => ExchangeAssetSector::Oil,
324            state::ExchangeAssetSector::EXCHANGE_ASSET_SECTOR_METALS => ExchangeAssetSector::Metals,
325            state::ExchangeAssetSector::EXCHANGE_ASSET_SECTOR_INDEX => ExchangeAssetSector::Index,
326            state::ExchangeAssetSector::EXCHANGE_ASSET_SECTOR_RATES => ExchangeAssetSector::Rates,
327            state::ExchangeAssetSector::EXCHANGE_ASSET_SECTOR_FX => ExchangeAssetSector::Fx,
328            state::ExchangeAssetSector::EXCHANGE_ASSET_SECTOR_AGRICULTURAL => {
329                ExchangeAssetSector::Agricultural
330            }
331        }
332    }
333}
334
335impl From<ExchangeAssetSector> for state::ExchangeAssetSector {
336    fn from(value: ExchangeAssetSector) -> Self {
337        match value {
338            ExchangeAssetSector::Unspecified => {
339                state::ExchangeAssetSector::EXCHANGE_ASSET_SECTOR_UNSPECIFIED
340            }
341            ExchangeAssetSector::Technology => {
342                state::ExchangeAssetSector::EXCHANGE_ASSET_SECTOR_TECHNOLOGY
343            }
344            ExchangeAssetSector::Financials => {
345                state::ExchangeAssetSector::EXCHANGE_ASSET_SECTOR_FINANCIALS
346            }
347            ExchangeAssetSector::BroadMarket => {
348                state::ExchangeAssetSector::EXCHANGE_ASSET_SECTOR_BROAD_MARKET
349            }
350            ExchangeAssetSector::Oil => state::ExchangeAssetSector::EXCHANGE_ASSET_SECTOR_OIL,
351            ExchangeAssetSector::Metals => state::ExchangeAssetSector::EXCHANGE_ASSET_SECTOR_METALS,
352            ExchangeAssetSector::Index => state::ExchangeAssetSector::EXCHANGE_ASSET_SECTOR_INDEX,
353            ExchangeAssetSector::Rates => state::ExchangeAssetSector::EXCHANGE_ASSET_SECTOR_RATES,
354            ExchangeAssetSector::Fx => state::ExchangeAssetSector::EXCHANGE_ASSET_SECTOR_FX,
355            ExchangeAssetSector::Agricultural => {
356                state::ExchangeAssetSector::EXCHANGE_ASSET_SECTOR_AGRICULTURAL
357            }
358        }
359    }
360}