|
|
1 ماه پیش | |
|---|---|---|
| .. | ||
| examples | 2 ماه پیش | |
| src | 1 ماه پیش | |
| Cargo.toml | 1 ماه پیش | |
| README.md | 1 ماه پیش | |
A high-performance Rust client for connecting to Pyth Lazer real-time data streams. This client provides reliable, low-latency access to Pyth's oracle price feeds with built-in redundancy and automatic failover.
Add the following to your Cargo.toml:
[dependencies]
pyth-lazer-client = "8.2.2"
pyth-lazer-protocol = "0.16.0"
tokio = { version = "1", features = ["full"] }
To use the Pyth Lazer client, you need an access token. Set your access token via the LAZER_ACCESS_TOKEN environment variable:
export LAZER_ACCESS_TOKEN="your_access_token_here"
Or provide it directly in your code:
use pyth_lazer_client::stream_client::PythLazerStreamClientBuilder;
let access_token = std::env::var("LAZER_ACCESS_TOKEN")
.expect("LAZER_ACCESS_TOKEN not set");
let client = PythLazerStreamClientBuilder::new(access_token)
.build()?;
Here's a minimal example to get started with streaming price feeds:
use pyth_lazer_client::stream_client::PythLazerStreamClientBuilder;
use pyth_lazer_protocol::api::{SubscribeRequest, SubscriptionParams, SubscriptionParamsRepr, Channel};
use pyth_lazer_protocol::{PriceFeedId, PriceFeedProperty};
use pyth_lazer_protocol::time::FixedRate;
#[tokio::main]
async fn main() -> anyhow::Result<()> {
// Create and start the client
let mut client = PythLazerStreamClientBuilder::new(
std::env::var("LAZER_ACCESS_TOKEN")?
).build()?;
let mut receiver = client.start().await?;
// Subscribe to price feeds
let subscribe_request = SubscribeRequest {
subscription_id: pyth_lazer_protocol::api::SubscriptionId(1),
params: SubscriptionParams::new(SubscriptionParamsRepr {
price_feed_ids: Some(vec![PriceFeedId(1), PriceFeedId(2)]),
symbols: None,
properties: vec![PriceFeedProperty::Price, PriceFeedProperty::Exponent],
formats: vec![pyth_lazer_protocol::api::Format::Solana],
delivery_format: pyth_lazer_protocol::api::DeliveryFormat::Json,
json_binary_encoding: pyth_lazer_protocol::api::JsonBinaryEncoding::Base64,
parsed: true,
channel: Channel::FixedRate(FixedRate::RATE_200_MS),
ignore_invalid_feeds: false,
})?,
};
client.subscribe(subscribe_request).await?;
// Process incoming messages
while let Some(response) = receiver.recv().await {
println!("Received update: {:?}", response);
}
Ok(())
}
The PythLazerStreamClientBuilder provides several configuration options:
Override the default production endpoints:
let client = PythLazerStreamClientBuilder::new(access_token)
.with_endpoints(vec![
"wss://pyth-lazer-0.dourolabs.app/v1/stream".parse()?,
"wss://pyth-lazer-1.dourolabs.app/v1/stream".parse()?,
])
.build()?;
Set the number of concurrent WebSocket connections (default: 4):
let client = PythLazerStreamClientBuilder::new(access_token)
.with_num_connections(2)
.build()?;
Configure the timeout for WebSocket operations (default: 5 seconds):
use std::time::Duration;
let client = PythLazerStreamClientBuilder::new(access_token)
.with_timeout(Duration::from_secs(10))
.build()?;
Customize the reconnection backoff strategy:
use pyth_lazer_client::backoff::PythLazerExponentialBackoffBuilder;
let backoff = PythLazerExponentialBackoffBuilder::default()
.build();
let client = PythLazerStreamClientBuilder::new(access_token)
.with_backoff(backoff)
.build()?;
Set the internal message buffer size (default: 1000):
let client = PythLazerStreamClientBuilder::new(access_token)
.with_channel_capacity(5000)
.build()?;
Choose the update frequency for your price feeds:
Channel::RealTime - Receive updates as soon as they're availableChannel::FixedRate(FixedRate::RATE_50_MS) - Updates every 50msChannel::FixedRate(FixedRate::RATE_200_MS) - Updates every 200ms (recommended for most use cases)Channel::FixedRate(FixedRate::RATE_1000_MS) - Updates every 1000ms
use pyth_lazer_protocol::api::Channel;
use pyth_lazer_protocol::time::FixedRate;
// Real-time updates
let channel = Channel::RealTime;
// Fixed rate updates
let channel = Channel::FixedRate(FixedRate::RATE_200_MS);
Specify the signature format for the price data:
Format::Evm - EVM-compatible format with secp256k1 signaturesFormat::Solana - Solana-compatible format with Ed25519 signaturesFormat::LeEcdsa - Little-endian ECDSA formatFormat::LeUnsigned - Little-endian unsigned format
use pyth_lazer_protocol::api::Format;
let formats = vec![Format::Evm, Format::Solana];
Choose how messages are delivered:
DeliveryFormat::Json - Receive updates as JSON text messages (default)DeliveryFormat::Binary - Receive updates as binary messages (more efficient)
use pyth_lazer_protocol::api::DeliveryFormat;
let delivery_format = DeliveryFormat::Binary;
Select which price feed properties to receive:
PriceFeedProperty::Price - Current pricePriceFeedProperty::BestBidPrice - Best bid pricePriceFeedProperty::BestAskPrice - Best ask pricePriceFeedProperty::PublisherCount - Number of contributing publishersPriceFeedProperty::Exponent - Price exponentPriceFeedProperty::Confidence - Confidence intervalPriceFeedProperty::FundingRate - Funding rate (for perpetual markets)PriceFeedProperty::FundingTimestamp - Funding rate timestampPriceFeedProperty::FundingRateInterval - Funding rate update interval
use pyth_lazer_protocol::PriceFeedProperty;
let properties = vec![
PriceFeedProperty::Price,
PriceFeedProperty::Exponent,
PriceFeedProperty::Confidence,
];
Subscribe to feeds using either price feed IDs or symbols:
// By price feed ID
let params = SubscriptionParamsRepr {
price_feed_ids: Some(vec![PriceFeedId(1), PriceFeedId(2)]),
symbols: None,
// ... other fields
};
// By symbol
let params = SubscriptionParamsRepr {
price_feed_ids: None,
symbols: Some(vec![
"Crypto.BTC/USD".to_string(),
"Crypto.ETH/USD".to_string(),
]),
// ... other fields
};
See examples/subscribe_price_feeds.rs for a complete example demonstrating:
Run the example:
cargo run --example subscribe_price_feeds
Fetch symbol metadata using the history client:
use pyth_lazer_client::history_client::{PythLazerHistoryClient, PythLazerHistoryClientConfig};
let client = PythLazerHistoryClient::new(
PythLazerHistoryClientConfig::default()
);
// Get all symbol metadata
let symbols = client.all_symbols_metadata().await?;
// Or get an auto-updating handle
let handle = client.all_symbols_metadata_handle().await?;
let symbols = handle.symbols();
See examples/symbols.rs and examples/symbols_stream.rs for complete examples.
The PythLazerHistoryClient provides access to symbol metadata and historical price information:
use pyth_lazer_client::history_client::{PythLazerHistoryClient, PythLazerHistoryClientConfig};
use std::time::Duration;
let config = PythLazerHistoryClientConfig {
urls: vec!["https://history.pyth-lazer.dourolabs.app/".parse()?],
update_interval: Duration::from_secs(30),
request_timeout: Duration::from_secs(15),
cache_dir: Some("/tmp/pyth-lazer-cache".into()),
channel_capacity: 1000,
};
let client = PythLazerHistoryClient::new(config);
// Fetch symbol metadata once
let symbols = client.all_symbols_metadata().await?;
// Or get an auto-updating handle that refreshes in the background
let handle = client.all_symbols_metadata_handle().await?;
// Or get a stream of updates
let mut stream = client.all_symbols_metadata_stream().await?;
while let Some(symbols) = stream.recv().await {
println!("Updated symbols: {} feeds", symbols.len());
}
The history client supports:
all_symbols_metadata()all_symbols_metadata_handle()all_symbols_metadata_stream()PythLazerStreamClient - The main client for streaming price updatesPythLazerStreamClientBuilder - Builder for configuring the stream clientPythLazerHistoryClient - Client for fetching symbol metadataSubscribeRequest - Subscription configurationSubscriptionParams - Subscription parameters wrapperAnyResponse - Enum for JSON or binary responsesstart() -> Result<Receiver<AnyResponse>> - Start the client and return message receiversubscribe(request: SubscribeRequest) -> Result<()> - Subscribe to price feedsunsubscribe(id: SubscriptionId) -> Result<()> - Unsubscribe from a feedall_symbols_metadata() -> Result<Vec<SymbolMetadata>> - Fetch all symbols onceall_symbols_metadata_handle() -> Result<SymbolMetadataHandle> - Get auto-updating handleall_symbols_metadata_stream() -> Result<Receiver<Vec<SymbolMetadata>>> - Get update streamFor complete API documentation, visit docs.rs/pyth-lazer-client.
This project is licensed under the Apache-2.0 License. See the LICENSE file for details.