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