Tip Floor Stream
Stream real-time tip floor data from NextBlock to optimize your transaction tips dynamically.
Streaming Tip Floor Data
use tokio_stream::StreamExt;
use std::time::Duration;
use serde::{Deserialize, Serialize};
// Tip floor response structure
#[derive(Debug, Deserialize, Serialize)]
pub struct TipFloorData {
pub time: String,
pub landed_tips_25th_percentile: f64,
pub landed_tips_50th_percentile: f64,
pub landed_tips_75th_percentile: f64,
pub landed_tips_95th_percentile: f64,
pub landed_tips_99th_percentile: f64,
pub ema_landed_tips_50th_percentile: f64,
}
// Stream tip floor updates
async fn stream_tip_floor(
// nextblock_client: &mut YourGeneratedApiClient,
update_frequency: String,
) -> Result<(), Box<dyn std::error::Error>> {
println!("Starting tip floor stream with frequency: {}", update_frequency);
// Create streaming request
/* Uncomment when you have the generated API client
let request = tonic::Request::new(TipFloorStreamRequest {
update_frequency,
});
let mut stream = nextblock_client
.stream_tip_floor(request)
.await?
.into_inner();
println!("Streaming tip floor data:");
while let Some(tip_floor_response) = stream.next().await {
match tip_floor_response {
Ok(tip_floor) => {
println!("Received tip floor update:");
println!(" Time: {}", tip_floor.time);
println!(" 25th percentile: {:.6} SOL", tip_floor.landed_tips_25th_percentile);
println!(" 50th percentile: {:.6} SOL", tip_floor.landed_tips_50th_percentile);
println!(" 75th percentile: {:.6} SOL", tip_floor.landed_tips_75th_percentile);
println!(" 95th percentile: {:.6} SOL", tip_floor.landed_tips_95th_percentile);
println!(" 99th percentile: {:.6} SOL", tip_floor.landed_tips_99th_percentile);
println!(" EMA 50th percentile: {:.6} SOL", tip_floor.ema_landed_tips_50th_percentile);
println!(" ---");
// Process the tip floor data
process_tip_floor_update(&tip_floor).await?;
}
Err(e) => {
eprintln!("Stream error: {}", e);
// Implement reconnection logic here
break;
}
}
}
*/
// Mock streaming for demonstration
println!("Mock tip floor streaming started...");
let mut interval = tokio::time::interval(Duration::from_secs(60));
loop {
interval.tick().await;
let mock_tip_floor = TipFloorData {
time: chrono::Utc::now().to_rfc3339(),
landed_tips_25th_percentile: 0.0011,
landed_tips_50th_percentile: 0.005000001,
landed_tips_75th_percentile: 0.01555,
landed_tips_95th_percentile: 0.09339195639999975,
landed_tips_99th_percentile: 0.4846427910400001,
ema_landed_tips_50th_percentile: 0.005989477267191758,
};
println!("Mock tip floor update: {:#?}", mock_tip_floor);
process_tip_floor_update(&mock_tip_floor).await?;
}
}
// Process tip floor updates
async fn process_tip_floor_update(
tip_floor: &TipFloorData,
) -> Result<(), Box<dyn std::error::Error>> {
// Update global tip strategy
update_tip_strategy(tip_floor).await?;
// Optionally store historical data
store_tip_floor_data(tip_floor).await?;
// Trigger any pending transactions with updated tips
trigger_pending_transactions().await?;
Ok(())
}Dynamic Tip Calculation
Advanced Tip Management
Store Historical Data
Usage Example
Best Practices
Update frequency: Use 1-5 minute intervals for most applications
Trend analysis: Consider tip trends when calculating optimal amounts
Fallback values: Always have default tip values in case streaming fails
Historical data: Store tip floor data for analysis and optimization
Priority levels: Use different tip strategies for different transaction types
Error handling: Implement reconnection logic for stream interruptions
Resource management: Limit historical data storage to prevent memory issues
Last updated