-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdaily_block_window.rs
More file actions
103 lines (90 loc) · 3.57 KB
/
daily_block_window.rs
File metadata and controls
103 lines (90 loc) · 3.57 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
// SPDX-FileCopyrightText: 2025 Semiotic AI, Inc.
//
// SPDX-License-Identifier: Apache-2.0
use alloy_chains::NamedChain;
/// Example demonstrating how to calculate daily block windows for blockchain queries
///
/// This example shows how to:
/// 1. Create a BlockWindowCalculator for a specific chain
/// 2. Calculate the block range for a specific UTC day
/// 3. Use the cached results for repeated queries
/// 4. Integrate with existing semioscan tools like CombinedCalculator
///
/// Run with:
/// ```bash
/// CHAIN_ID=42161 \
/// RPC_URL=https://arb1.arbitrum.io/rpc/ \
/// API_KEY=your_api_key \
/// DAY=2025-10-10 \
/// CACHE_PATH=block_windows.json \
/// cargo run --package semioscan --example daily_block_window
/// ```
///
/// Note: CHAIN_ID must be provided as config because some chains (e.g., Avalanche)
/// don't support the get_chain_id() RPC method.
use alloy_provider::ProviderBuilder;
use anyhow::{Context, Result};
use chrono::NaiveDate;
use semioscan::BlockWindowCalculator;
use std::env;
use tracing::{info, Level};
use tracing_subscriber::FmtSubscriber;
#[tokio::main]
async fn main() -> Result<()> {
// Initialize tracing
let subscriber = FmtSubscriber::builder()
.with_max_level(Level::INFO)
.finish();
tracing::subscriber::set_global_default(subscriber)
.context("Failed to set tracing subscriber")?;
dotenvy::dotenv().ok();
// Read configuration from environment
let rpc_url = env::var("RPC_URL").context("RPC_URL environment variable not set")?;
let api_key = env::var("API_KEY").context("API_KEY environment variable not set")?;
let day_str = env::var("DAY").unwrap_or_else(|_| "2025-10-16".to_string());
let cache_path = env::var("CACHE_PATH").unwrap_or_else(|_| "block_windows.json".to_string());
// Combine RPC URL with API key (trailing slash is important for Pinax endpoint)
let full_rpc_url = format!("{rpc_url}{api_key}/");
info!(day_str, cache_path, "Starting daily block window example");
// Parse the date
let date = NaiveDate::parse_from_str(&day_str, "%Y-%m-%d")
.context("Failed to parse DAY (expected format: YYYY-MM-DD)")?;
// Create provider
let provider = ProviderBuilder::new().connect_http(full_rpc_url.parse()?);
// Create calculator with disk cache
let calculator = BlockWindowCalculator::with_disk_cache(provider.clone(), cache_path)?;
// Calculate daily window
// Note: Chain ID is injected from config rather than queried from provider
// because some chains (e.g., Avalanche) don't support get_chain_id()
info!(chain = ?NamedChain::Arbitrum, date = %date, "Calculating daily block window");
let window = calculator
.get_daily_window(NamedChain::Arbitrum, date)
.await?;
info!(
date = %date,
start_block = window.start_block,
end_block = window.end_block,
block_count = window.block_count().as_u64(),
start_ts = %window.start_ts,
end_ts_exclusive = %window.end_ts_exclusive,
"Daily block window calculated"
);
println!("\n=== Daily Block Window ===");
println!("Date: {date}");
println!(
"Block range: [{}, {}] (inclusive)",
window.start_block, window.end_block
);
println!("Block count: {}", window.block_count());
println!(
"UTC start: {} ({})",
window.start_ts,
chrono::DateTime::from_timestamp(window.start_ts.0, 0).unwrap()
);
println!(
"UTC end (exclusive): {} ({})",
window.end_ts_exclusive,
chrono::DateTime::from_timestamp(window.end_ts_exclusive.0, 0).unwrap()
);
Ok(())
}