1use anyhow::Context;
2use serde::Serialize;
3
4#[derive(Default, Debug, Clone)]
5#[cfg_attr(feature = "pyo3", derive(pyo3::FromPyObject))]
6pub struct Query {
7 pub from_block: u64,
8 pub to_block: Option<u64>,
9 pub include_all_blocks: bool,
10 pub transactions: Vec<TransactionRequest>,
11 pub logs: Vec<LogRequest>,
12 pub traces: Vec<TraceRequest>,
13 pub fields: Fields,
14}
15
16#[derive(Debug, Clone, Copy)]
17pub struct Hash(pub [u8; 32]);
18
19#[derive(Debug, Clone, Copy)]
20pub struct Address(pub [u8; 20]);
21
22#[derive(Debug, Clone, Copy)]
23pub struct Sighash(pub [u8; 4]);
24
25#[derive(Debug, Clone, Copy)]
26pub struct Topic(pub [u8; 32]);
27
28#[cfg(feature = "pyo3")]
29fn extract_hex<const N: usize>(ob: &pyo3::Bound<'_, pyo3::PyAny>) -> pyo3::PyResult<[u8; N]> {
30 use pyo3::types::PyAnyMethods;
31
32 let s: &str = ob.extract()?;
33 let s = s.strip_prefix("0x").context("strip 0x prefix")?;
34 let mut out = [0; N];
35 faster_hex::hex_decode(s.as_bytes(), &mut out).context("decode hex")?;
36
37 Ok(out)
38}
39
40#[cfg(feature = "pyo3")]
41impl<'py> pyo3::FromPyObject<'py> for Hash {
42 fn extract_bound(ob: &pyo3::Bound<'py, pyo3::PyAny>) -> pyo3::PyResult<Self> {
43 let out = extract_hex(ob)?;
44 Ok(Self(out))
45 }
46}
47
48#[cfg(feature = "pyo3")]
49impl<'py> pyo3::FromPyObject<'py> for Address {
50 fn extract_bound(ob: &pyo3::Bound<'py, pyo3::PyAny>) -> pyo3::PyResult<Self> {
51 let out = extract_hex(ob)?;
52 Ok(Self(out))
53 }
54}
55
56#[cfg(feature = "pyo3")]
57impl<'py> pyo3::FromPyObject<'py> for Sighash {
58 fn extract_bound(ob: &pyo3::Bound<'py, pyo3::PyAny>) -> pyo3::PyResult<Self> {
59 let out = extract_hex(ob)?;
60 Ok(Self(out))
61 }
62}
63
64#[cfg(feature = "pyo3")]
65impl<'py> pyo3::FromPyObject<'py> for Topic {
66 fn extract_bound(ob: &pyo3::Bound<'py, pyo3::PyAny>) -> pyo3::PyResult<Self> {
67 let out = extract_hex(ob)?;
68 Ok(Self(out))
69 }
70}
71
72#[derive(Default, Debug, Clone)]
79#[cfg_attr(feature = "pyo3", derive(pyo3::FromPyObject))]
80pub struct TransactionRequest {
81 pub from_: Vec<Address>,
82 pub to: Vec<Address>,
83 pub sighash: Vec<Sighash>,
84 pub status: Vec<u8>,
85 pub type_: Vec<u8>,
86 pub contract_deployment_address: Vec<Address>,
87 pub hash: Vec<Hash>,
88 pub include_logs: bool,
89 pub include_traces: bool,
90 pub include_blocks: bool,
91}
92
93#[derive(Default, Debug, Clone)]
94#[cfg_attr(feature = "pyo3", derive(pyo3::FromPyObject))]
95pub struct LogRequest {
96 pub address: Vec<Address>,
97 pub event_signatures: Vec<String>,
98 pub topic0: Vec<Topic>,
99 pub topic1: Vec<Topic>,
100 pub topic2: Vec<Topic>,
101 pub topic3: Vec<Topic>,
102 pub include_transactions: bool,
103 pub include_transaction_logs: bool,
104 pub include_transaction_traces: bool,
105 pub include_blocks: bool,
106}
107
108#[derive(Default, Debug, Clone)]
109#[cfg_attr(feature = "pyo3", derive(pyo3::FromPyObject))]
110pub struct TraceRequest {
111 pub from_: Vec<Address>,
112 pub to: Vec<Address>,
113 pub address: Vec<Address>,
114 pub call_type: Vec<String>,
115 pub reward_type: Vec<String>,
116 pub type_: Vec<String>,
117 pub sighash: Vec<Sighash>,
118 pub author: Vec<Address>,
119 pub include_transactions: bool,
120 pub include_transaction_logs: bool,
121 pub include_transaction_traces: bool,
122 pub include_blocks: bool,
123}
124
125#[derive(Serialize, Default, Debug, Clone, Copy)]
126#[cfg_attr(feature = "pyo3", derive(pyo3::FromPyObject))]
127pub struct Fields {
128 pub block: BlockFields,
129 pub transaction: TransactionFields,
130 pub log: LogFields,
131 pub trace: TraceFields,
132}
133
134impl Fields {
135 pub fn all() -> Self {
136 Self {
137 block: BlockFields::all(),
138 transaction: TransactionFields::all(),
139 log: LogFields::all(),
140 trace: TraceFields::all(),
141 }
142 }
143}
144
145#[derive(Default, Debug, Clone, Copy, Serialize)]
146#[cfg_attr(feature = "pyo3", derive(pyo3::FromPyObject))]
147pub struct BlockFields {
148 pub number: bool,
149 pub hash: bool,
150 pub parent_hash: bool,
151 pub nonce: bool,
152 pub sha3_uncles: bool,
153 pub logs_bloom: bool,
154 pub transactions_root: bool,
155 pub state_root: bool,
156 pub receipts_root: bool,
157 pub miner: bool,
158 pub difficulty: bool,
159 pub total_difficulty: bool,
160 pub extra_data: bool,
161 pub size: bool,
162 pub gas_limit: bool,
163 pub gas_used: bool,
164 pub timestamp: bool,
165 pub uncles: bool,
166 pub base_fee_per_gas: bool,
167 pub blob_gas_used: bool,
168 pub excess_blob_gas: bool,
169 pub parent_beacon_block_root: bool,
170 pub withdrawals_root: bool,
171 pub withdrawals: bool,
172 pub l1_block_number: bool,
173 pub send_count: bool,
174 pub send_root: bool,
175 pub mix_hash: bool,
176}
177
178impl BlockFields {
179 pub fn all() -> Self {
180 BlockFields {
181 number: true,
182 hash: true,
183 parent_hash: true,
184 nonce: true,
185 sha3_uncles: true,
186 logs_bloom: true,
187 transactions_root: true,
188 state_root: true,
189 receipts_root: true,
190 miner: true,
191 difficulty: true,
192 total_difficulty: true,
193 extra_data: true,
194 size: true,
195 gas_limit: true,
196 gas_used: true,
197 timestamp: true,
198 uncles: true,
199 base_fee_per_gas: true,
200 blob_gas_used: true,
201 excess_blob_gas: true,
202 parent_beacon_block_root: true,
203 withdrawals_root: true,
204 withdrawals: true,
205 l1_block_number: true,
206 send_count: true,
207 send_root: true,
208 mix_hash: true,
209 }
210 }
211}
212
213#[derive(Default, Debug, Clone, Copy, Serialize)]
214#[cfg_attr(feature = "pyo3", derive(pyo3::FromPyObject))]
215pub struct TransactionFields {
216 pub block_hash: bool,
217 pub block_number: bool,
218 #[serde(rename = "from")]
219 pub from_: bool,
220 pub gas: bool,
221 pub gas_price: bool,
222 pub hash: bool,
223 pub input: bool,
224 pub nonce: bool,
225 pub to: bool,
226 pub transaction_index: bool,
227 pub value: bool,
228 pub v: bool,
229 pub r: bool,
230 pub s: bool,
231 pub max_priority_fee_per_gas: bool,
232 pub max_fee_per_gas: bool,
233 pub chain_id: bool,
234 pub cumulative_gas_used: bool,
235 pub effective_gas_price: bool,
236 pub gas_used: bool,
237 pub contract_address: bool,
238 pub logs_bloom: bool,
239 #[serde(rename = "type")]
240 pub type_: bool,
241 pub root: bool,
242 pub status: bool,
243 pub sighash: bool,
244 pub y_parity: bool,
245 pub access_list: bool,
246 pub l1_fee: bool,
247 pub l1_gas_price: bool,
248 pub l1_fee_scalar: bool,
249 pub gas_used_for_l1: bool,
250 pub max_fee_per_blob_gas: bool,
251 pub blob_versioned_hashes: bool,
252 pub deposit_nonce: bool,
253 pub blob_gas_price: bool,
254 pub deposit_receipt_version: bool,
255 pub blob_gas_used: bool,
256 pub l1_base_fee_scalar: bool,
257 pub l1_blob_base_fee: bool,
258 pub l1_blob_base_fee_scalar: bool,
259 pub l1_block_number: bool,
260 pub mint: bool,
261 pub source_hash: bool,
262}
263
264impl TransactionFields {
265 pub fn all() -> Self {
266 TransactionFields {
267 block_hash: true,
268 block_number: true,
269 from_: true,
270 gas: true,
271 gas_price: true,
272 hash: true,
273 input: true,
274 nonce: true,
275 to: true,
276 transaction_index: true,
277 value: true,
278 v: true,
279 r: true,
280 s: true,
281 max_priority_fee_per_gas: true,
282 max_fee_per_gas: true,
283 chain_id: true,
284 cumulative_gas_used: true,
285 effective_gas_price: true,
286 gas_used: true,
287 contract_address: true,
288 logs_bloom: true,
289 type_: true,
290 root: true,
291 status: true,
292 sighash: true,
293 y_parity: true,
294 access_list: true,
295 l1_fee: true,
296 l1_gas_price: true,
297 l1_fee_scalar: true,
298 gas_used_for_l1: true,
299 max_fee_per_blob_gas: true,
300 blob_versioned_hashes: true,
301 deposit_nonce: true,
302 blob_gas_price: true,
303 deposit_receipt_version: true,
304 blob_gas_used: true,
305 l1_base_fee_scalar: true,
306 l1_blob_base_fee: true,
307 l1_blob_base_fee_scalar: true,
308 l1_block_number: true,
309 mint: true,
310 source_hash: true,
311 }
312 }
313}
314
315#[derive(Default, Debug, Clone, Copy, Serialize)]
316#[cfg_attr(feature = "pyo3", derive(pyo3::FromPyObject))]
317pub struct LogFields {
318 pub removed: bool,
319 pub log_index: bool,
320 pub transaction_index: bool,
321 pub transaction_hash: bool,
322 pub block_hash: bool,
323 pub block_number: bool,
324 pub address: bool,
325 pub data: bool,
326 pub topic0: bool,
327 pub topic1: bool,
328 pub topic2: bool,
329 pub topic3: bool,
330}
331
332impl LogFields {
333 pub fn all() -> Self {
334 LogFields {
335 removed: true,
336 log_index: true,
337 transaction_index: true,
338 transaction_hash: true,
339 block_hash: true,
340 block_number: true,
341 address: true,
342 data: true,
343 topic0: true,
344 topic1: true,
345 topic2: true,
346 topic3: true,
347 }
348 }
349}
350
351#[derive(Default, Debug, Clone, Copy, Serialize)]
352#[cfg_attr(feature = "pyo3", derive(pyo3::FromPyObject))]
353pub struct TraceFields {
354 #[serde(rename = "from")]
355 pub from_: bool,
356 pub to: bool,
357 pub call_type: bool,
358 pub gas: bool,
359 pub input: bool,
360 pub init: bool,
361 pub value: bool,
362 pub author: bool,
363 pub reward_type: bool,
364 pub block_hash: bool,
365 pub block_number: bool,
366 pub address: bool,
367 pub code: bool,
368 pub gas_used: bool,
369 pub output: bool,
370 pub subtraces: bool,
371 pub trace_address: bool,
372 pub transaction_hash: bool,
373 pub transaction_position: bool,
374 #[serde(rename = "type")]
375 pub type_: bool,
376 pub error: bool,
377 pub sighash: bool,
378 pub action_address: bool,
379 pub balance: bool,
380 pub refund_address: bool,
381}
382
383impl TraceFields {
384 pub fn all() -> Self {
385 TraceFields {
386 from_: true,
387 to: true,
388 call_type: true,
389 gas: true,
390 input: true,
391 init: true,
392 value: true,
393 author: true,
394 reward_type: true,
395 block_hash: true,
396 block_number: true,
397 address: true,
398 code: true,
399 gas_used: true,
400 output: true,
401 subtraces: true,
402 trace_address: true,
403 transaction_hash: true,
404 transaction_position: true,
405 type_: true,
406 error: true,
407 sighash: true,
408 action_address: true,
409 balance: true,
410 refund_address: true,
411 }
412 }
413}