cherry_ingest/
evm.rs

1use anyhow::Context;
2use serde::{Deserialize, 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)]
73// pub struct BlockRequest {
74//     pub hash: Vec<Hash>,
75//     pub miner: Vec<Address>,
76// }
77
78#[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 topic0: Vec<Topic>,
98    pub topic1: Vec<Topic>,
99    pub topic2: Vec<Topic>,
100    pub topic3: Vec<Topic>,
101    pub include_transactions: bool,
102    pub include_transaction_logs: bool,
103    pub include_transaction_traces: bool,
104    pub include_blocks: bool,
105}
106
107#[derive(Default, Debug, Clone)]
108#[cfg_attr(feature = "pyo3", derive(pyo3::FromPyObject))]
109pub struct TraceRequest {
110    pub from_: Vec<Address>,
111    pub to: Vec<Address>,
112    pub address: Vec<Address>,
113    pub call_type: Vec<String>,
114    pub reward_type: Vec<String>,
115    pub type_: Vec<String>,
116    pub sighash: Vec<Sighash>,
117    pub author: Vec<Address>,
118    pub include_transactions: bool,
119    pub include_transaction_logs: bool,
120    pub include_transaction_traces: bool,
121    pub include_blocks: bool,
122}
123
124#[derive(Deserialize, Serialize, Default, Debug, Clone, Copy)]
125#[serde(default)]
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, Deserialize)]
146#[serde(default)]
147#[cfg_attr(feature = "pyo3", derive(pyo3::FromPyObject))]
148pub struct BlockFields {
149    pub number: bool,
150    pub hash: bool,
151    pub parent_hash: bool,
152    pub nonce: bool,
153    pub sha3_uncles: bool,
154    pub logs_bloom: bool,
155    pub transactions_root: bool,
156    pub state_root: bool,
157    pub receipts_root: bool,
158    pub miner: bool,
159    pub difficulty: bool,
160    pub total_difficulty: bool,
161    pub extra_data: bool,
162    pub size: bool,
163    pub gas_limit: bool,
164    pub gas_used: bool,
165    pub timestamp: bool,
166    pub uncles: bool,
167    pub base_fee_per_gas: bool,
168    pub blob_gas_used: bool,
169    pub excess_blob_gas: bool,
170    pub parent_beacon_block_root: bool,
171    pub withdrawals_root: bool,
172    pub withdrawals: bool,
173    pub l1_block_number: bool,
174    pub send_count: bool,
175    pub send_root: bool,
176    pub mix_hash: bool,
177}
178
179impl BlockFields {
180    pub fn all() -> Self {
181        BlockFields {
182            number: true,
183            hash: true,
184            parent_hash: true,
185            nonce: true,
186            sha3_uncles: true,
187            logs_bloom: true,
188            transactions_root: true,
189            state_root: true,
190            receipts_root: true,
191            miner: true,
192            difficulty: true,
193            total_difficulty: true,
194            extra_data: true,
195            size: true,
196            gas_limit: true,
197            gas_used: true,
198            timestamp: true,
199            uncles: true,
200            base_fee_per_gas: true,
201            blob_gas_used: true,
202            excess_blob_gas: true,
203            parent_beacon_block_root: true,
204            withdrawals_root: true,
205            withdrawals: true,
206            l1_block_number: true,
207            send_count: true,
208            send_root: true,
209            mix_hash: true,
210        }
211    }
212}
213
214#[derive(Default, Debug, Clone, Copy, Serialize, Deserialize)]
215#[serde(default)]
216#[cfg_attr(feature = "pyo3", derive(pyo3::FromPyObject))]
217pub struct TransactionFields {
218    pub block_hash: bool,
219    pub block_number: bool,
220    #[serde(rename = "from")]
221    pub from_: bool,
222    pub gas: bool,
223    pub gas_price: bool,
224    pub hash: bool,
225    pub input: bool,
226    pub nonce: bool,
227    pub to: bool,
228    pub transaction_index: bool,
229    pub value: bool,
230    pub v: bool,
231    pub r: bool,
232    pub s: bool,
233    pub max_priority_fee_per_gas: bool,
234    pub max_fee_per_gas: bool,
235    pub chain_id: bool,
236    pub cumulative_gas_used: bool,
237    pub effective_gas_price: bool,
238    pub gas_used: bool,
239    pub contract_address: bool,
240    pub logs_bloom: bool,
241    #[serde(rename = "type")]
242    pub type_: bool,
243    pub root: bool,
244    pub status: bool,
245    pub sighash: bool,
246    pub y_parity: bool,
247    pub access_list: bool,
248    pub l1_fee: bool,
249    pub l1_gas_price: bool,
250    pub l1_fee_scalar: bool,
251    pub gas_used_for_l1: bool,
252    pub max_fee_per_blob_gas: bool,
253    pub blob_versioned_hashes: bool,
254    pub deposit_nonce: bool,
255    pub blob_gas_price: bool,
256    pub deposit_receipt_version: bool,
257    pub blob_gas_used: bool,
258    pub l1_base_fee_scalar: bool,
259    pub l1_blob_base_fee: bool,
260    pub l1_blob_base_fee_scalar: bool,
261    pub l1_block_number: bool,
262    pub mint: bool,
263    pub source_hash: bool,
264}
265
266impl TransactionFields {
267    pub fn all() -> Self {
268        TransactionFields {
269            block_hash: true,
270            block_number: true,
271            from_: true,
272            gas: true,
273            gas_price: true,
274            hash: true,
275            input: true,
276            nonce: true,
277            to: true,
278            transaction_index: true,
279            value: true,
280            v: true,
281            r: true,
282            s: true,
283            max_priority_fee_per_gas: true,
284            max_fee_per_gas: true,
285            chain_id: true,
286            cumulative_gas_used: true,
287            effective_gas_price: true,
288            gas_used: true,
289            contract_address: true,
290            logs_bloom: true,
291            type_: true,
292            root: true,
293            status: true,
294            sighash: true,
295            y_parity: true,
296            access_list: true,
297            l1_fee: true,
298            l1_gas_price: true,
299            l1_fee_scalar: true,
300            gas_used_for_l1: true,
301            max_fee_per_blob_gas: true,
302            blob_versioned_hashes: true,
303            deposit_nonce: true,
304            blob_gas_price: true,
305            deposit_receipt_version: true,
306            blob_gas_used: true,
307            l1_base_fee_scalar: true,
308            l1_blob_base_fee: true,
309            l1_blob_base_fee_scalar: true,
310            l1_block_number: true,
311            mint: true,
312            source_hash: true,
313        }
314    }
315}
316
317#[derive(Default, Debug, Clone, Copy, Serialize, Deserialize)]
318#[serde(default)]
319#[cfg_attr(feature = "pyo3", derive(pyo3::FromPyObject))]
320pub struct LogFields {
321    pub removed: bool,
322    pub log_index: bool,
323    pub transaction_index: bool,
324    pub transaction_hash: bool,
325    pub block_hash: bool,
326    pub block_number: bool,
327    pub address: bool,
328    pub data: bool,
329    pub topic0: bool,
330    pub topic1: bool,
331    pub topic2: bool,
332    pub topic3: bool,
333}
334
335impl LogFields {
336    pub fn all() -> Self {
337        LogFields {
338            removed: true,
339            log_index: true,
340            transaction_index: true,
341            transaction_hash: true,
342            block_hash: true,
343            block_number: true,
344            address: true,
345            data: true,
346            topic0: true,
347            topic1: true,
348            topic2: true,
349            topic3: true,
350        }
351    }
352}
353
354#[derive(Default, Debug, Clone, Copy, Serialize, Deserialize)]
355#[serde(default)]
356#[cfg_attr(feature = "pyo3", derive(pyo3::FromPyObject))]
357pub struct TraceFields {
358    #[serde(rename = "from")]
359    pub from_: bool,
360    pub to: bool,
361    pub call_type: bool,
362    pub gas: bool,
363    pub input: bool,
364    pub init: bool,
365    pub value: bool,
366    pub author: bool,
367    pub reward_type: bool,
368    pub block_hash: bool,
369    pub block_number: bool,
370    pub address: bool,
371    pub code: bool,
372    pub gas_used: bool,
373    pub output: bool,
374    pub subtraces: bool,
375    pub trace_address: bool,
376    pub transaction_hash: bool,
377    pub transaction_position: bool,
378    #[serde(rename = "type")]
379    pub type_: bool,
380    pub error: bool,
381    pub sighash: bool,
382    pub action_address: bool,
383    pub balance: bool,
384    pub refund_address: bool,
385}
386
387impl TraceFields {
388    pub fn all() -> Self {
389        TraceFields {
390            from_: true,
391            to: true,
392            call_type: true,
393            gas: true,
394            input: true,
395            init: true,
396            value: true,
397            author: true,
398            reward_type: true,
399            block_hash: true,
400            block_number: true,
401            address: true,
402            code: true,
403            gas_used: true,
404            output: true,
405            subtraces: true,
406            trace_address: true,
407            transaction_hash: true,
408            transaction_position: true,
409            type_: true,
410            error: true,
411            sighash: true,
412            action_address: true,
413            balance: true,
414            refund_address: true,
415        }
416    }
417}