-
Notifications
You must be signed in to change notification settings - Fork 245
/
Copy pathinspect.rs
110 lines (106 loc) · 4.07 KB
/
inspect.rs
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
104
105
106
107
108
109
110
use {
crate::{
chain::ethereum::{PythContract, Request},
config::{Config, EthereumConfig, InspectOptions},
},
anyhow::Result,
ethers::{
contract::Multicall,
middleware::Middleware,
prelude::{Http, Provider},
},
};
pub async fn inspect(opts: &InspectOptions) -> Result<()> {
match opts.chain_id.clone() {
Some(chain_id) => {
let chain_config = &Config::load(&opts.config.config)?.get_chain_config(&chain_id)?;
inspect_chain(chain_config, opts.num_requests, opts.multicall_batch_size).await?;
}
None => {
let config = Config::load(&opts.config.config)?;
for (chain_id, chain_config) in config.chains.iter() {
println!("Inspecting chain: {}", chain_id);
inspect_chain(chain_config, opts.num_requests, opts.multicall_batch_size).await?;
}
}
}
Ok(())
}
async fn inspect_chain(
chain_config: &EthereumConfig,
num_requests: u64,
multicall_batch_size: u64,
) -> Result<()> {
let rpc_provider = if !chain_config.geth_rpc_addrs.is_empty() {
crate::eth_utils::utils::create_failover_provider(&chain_config.geth_rpc_addrs)?
} else {
Provider::<Http>::try_from(chain_config.geth_rpc_addr.as_str())?
};
let multicall_exists = rpc_provider
.get_code(ethers::contract::MULTICALL_ADDRESS, None)
.await
.expect("Failed to get code")
.len()
> 0;
let contract = PythContract::from_config_basic(chain_config)?;
let entropy_provider = contract.get_default_provider().call().await?;
let provider_info = contract.get_provider_info(entropy_provider).call().await?;
let mut current_request_number = provider_info.sequence_number;
println!("Initial request number: {}", current_request_number);
let last_request_number = current_request_number.saturating_sub(num_requests);
if multicall_exists {
println!("Using multicall");
let mut multicall = Multicall::new(
rpc_provider.clone(),
Some(ethers::contract::MULTICALL_ADDRESS),
)
.await?;
while current_request_number > last_request_number {
multicall.clear_calls();
for _ in 0..multicall_batch_size {
if current_request_number == 0 {
break;
}
multicall.add_call(
contract.get_request(entropy_provider, current_request_number),
false,
);
current_request_number -= 1;
}
let return_data: Vec<Request> = multicall.call_array().await?;
for request in return_data {
process_request(rpc_provider.clone(), request).await?;
}
println!("Current request number: {}", current_request_number);
}
} else {
println!("Multicall not deployed in this chain, fetching requests one by one");
while current_request_number > last_request_number {
let request = contract
.get_request(entropy_provider, current_request_number)
.call()
.await?;
process_request(rpc_provider.clone(), request).await?;
current_request_number -= 1;
if current_request_number % 100 == 0 {
println!("Current request number: {}", current_request_number);
}
}
}
Ok(())
}
async fn process_request(rpc_provider: Provider<Http>, request: Request) -> Result<()> {
if request.sequence_number != 0 && request.is_request_with_callback {
let block = rpc_provider
.get_block(request.block_number)
.await?
.expect("Block not found");
let datetime = chrono::DateTime::from_timestamp(block.timestamp.as_u64() as i64, 0)
.expect("Invalid timestamp");
println!(
"{} sequence_number:{} block_number:{} requester:{}",
datetime, request.sequence_number, request.block_number, request.requester
);
}
Ok(())
}