ethers_provider/
types.rs

1use ethers_primitives::*;
2use serde::{Deserialize, Deserializer, Serialize, Serializer};
3
4use crate::error::ProviderError;
5
6pub use ethers_eip2718::AccessList;
7
8macro_rules! from_json {
9    ($name: ident) => {
10        impl TryFrom<&str> for $name {
11            type Error = serde_json::Error;
12
13            fn try_from(value: &str) -> Result<Self, Self::Error> {
14                serde_json::from_str(value)
15            }
16        }
17
18        impl TryFrom<String> for $name {
19            type Error = serde_json::Error;
20            fn try_from(value: String) -> Result<Self, Self::Error> {
21                Self::try_from(value.as_ref())
22            }
23        }
24
25        impl TryFrom<serde_json::Value> for $name {
26            type Error = serde_json::Error;
27            fn try_from(value: serde_json::Value) -> Result<Self, Self::Error> {
28                serde_json::from_value(value)
29            }
30        }
31    };
32}
33
34/// When a Contract creates a log, it can include up to 4 pieces of data to be indexed by.
35/// The indexed data is hashed and included in a Bloom Filter, which is a data structure
36/// that allows for efficient filtering.
37///
38/// So, a filter may correspondingly have up to 4 topic-sets, where each topic-set refers
39/// to a condition that must match the indexed log topic in that position
40/// (i.e. each condition is AND-ed together).
41///
42/// If a topic-set is null, a log topic in that position is not filtered at all and any
43/// value matches.
44///
45/// If a topic-set is a single topic, a log topic in that position must match that topic.
46///
47/// If a topic-set is an array of topics, a log topic in that position must match any one
48/// of the topics (i.e. the topic in this position are OR-ed).
49#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq, Eq, Hash)]
50pub struct TopicFilter(Topic, Topic, Topic, Topic);
51
52/// Topic filter expr
53#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
54pub enum Topic {
55    /// Not filtered at all and any value matches
56    Unset,
57    /// Match any of the hashes.
58    OneOf(Vec<H256>),
59    /// Match only this hash.
60    This(H256),
61}
62
63impl Default for Topic {
64    fn default() -> Self {
65        Self::Unset
66    }
67}
68
69#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Hash)]
70#[serde(untagged)]
71pub enum AddressFilter {
72    Address(Address),
73    Addresses(Vec<Address>),
74}
75
76impl From<Address> for AddressFilter {
77    fn from(value: Address) -> Self {
78        AddressFilter::Address(value)
79    }
80}
81
82impl From<Vec<Address>> for AddressFilter {
83    fn from(value: Vec<Address>) -> Self {
84        AddressFilter::Addresses(value)
85    }
86}
87
88from_json!(AddressFilter);
89
90/// Filter argument for events
91#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Hash)]
92#[serde(rename_all = "camelCase")]
93pub struct Filter {
94    /// The lowest number block of returned range.
95    pub from_block: Option<U256>,
96    /// The highest number block of returned range.
97    pub to_block: Option<U256>,
98
99    pub address: Option<AddressFilter>,
100
101    pub topics: Option<TopicFilter>,
102}
103
104impl From<(Address, TopicFilter)> for Filter {
105    fn from(value: (Address, TopicFilter)) -> Self {
106        Filter {
107            from_block: None,
108            to_block: None,
109            address: Some(AddressFilter::Address(value.0)),
110            topics: Some(value.1),
111        }
112    }
113}
114
115impl From<(Vec<Address>, TopicFilter)> for Filter {
116    fn from(value: (Vec<Address>, TopicFilter)) -> Self {
117        Filter {
118            from_block: None,
119            to_block: None,
120            address: Some(AddressFilter::Addresses(value.0)),
121            topics: Some(value.1),
122        }
123    }
124}
125
126from_json!(Filter);
127
128/// eth_getBlockByNumber parameter `Block`
129#[derive(Serialize, Deserialize, PartialEq, Debug)]
130#[serde(untagged)]
131pub enum BlockNumberOrTag {
132    U256(U256),
133    Tag(BlockTag),
134}
135
136impl From<U256> for BlockNumberOrTag {
137    fn from(v: U256) -> Self {
138        BlockNumberOrTag::U256(v)
139    }
140}
141
142impl From<BlockTag> for BlockNumberOrTag {
143    fn from(v: BlockTag) -> Self {
144        BlockNumberOrTag::Tag(v)
145    }
146}
147
148impl Default for BlockNumberOrTag {
149    fn default() -> Self {
150        BlockNumberOrTag::Tag(BlockTag::Latest)
151    }
152}
153
154/// eth_getBlockByNumber parameter `Block` valid tag enum
155#[derive(Serialize, Deserialize, PartialEq, Debug)]
156#[serde(rename_all = "lowercase")]
157pub enum BlockTag {
158    Earliest,
159    Finalized,
160    Safe,
161    Latest,
162    Pending,
163}
164
165impl<'a> TryFrom<&'a str> for BlockNumberOrTag {
166    type Error = anyhow::Error;
167    fn try_from(value: &'a str) -> Result<Self, Self::Error> {
168        if value.starts_with("0x") {
169            Ok(BlockNumberOrTag::U256(serde_json::from_str(&format!(
170                "\"{}\"",
171                value
172            ))?))
173        } else {
174            Ok(BlockNumberOrTag::Tag(serde_json::from_str(&format!(
175                "\"{}\"",
176                value
177            ))?))
178        }
179    }
180}
181
182#[derive(Serialize, Deserialize)]
183#[serde(rename_all = "camelCase")]
184pub struct FeeHistory {
185    /// The lowest number block of returned range.
186    pub oldest_block: U256,
187
188    pub base_fee_per_gas: Vec<U256>,
189
190    pub reward: Vec<Vec<U256>>,
191}
192
193#[derive(Serialize, Deserialize, Debug)]
194#[serde(rename_all = "camelCase")]
195pub struct Log {
196    pub removed: bool,
197
198    pub log_index: U256,
199
200    pub transaction_index: U256,
201
202    pub transaction_hash: U256,
203
204    pub block_hash: H256,
205
206    pub block_number: U256,
207
208    pub address: Address,
209
210    pub data: Bytes,
211
212    pub topics: Vec<H256>,
213}
214
215#[derive(Serialize, Deserialize, Debug)]
216#[serde(untagged)]
217pub enum FilterEvents {
218    BlocksOrTransactions(Vec<H256>),
219
220    Logs(Vec<Log>),
221}
222
223#[derive(Debug, Serialize, Deserialize, PartialEq)]
224#[serde(untagged)]
225pub enum SyncingStatus {
226    Syncing(Syncing),
227
228    #[serde(deserialize_with = "from_bool", serialize_with = "as_bool")]
229    False,
230}
231
232impl Default for SyncingStatus {
233    fn default() -> Self {
234        SyncingStatus::False
235    }
236}
237
238fn from_bool<'de, D>(d: D) -> std::result::Result<(), D::Error>
239where
240    D: Deserializer<'de>,
241{
242    bool::deserialize(d).and_then(|flag| {
243        if !flag {
244            Ok(())
245        } else {
246            Err(ProviderError::Syncing).map_err(serde::de::Error::custom)
247        }
248    })
249}
250
251fn as_bool<S>(serializer: S) -> std::result::Result<S::Ok, S::Error>
252where
253    S: Serializer,
254{
255    serializer.serialize_bool(false)
256}
257
258#[derive(Debug, Serialize, Deserialize, PartialEq)]
259#[serde(rename_all = "camelCase")]
260pub struct Syncing {
261    /// Starting block
262    starting_block: U256,
263
264    /// Current block
265    current_block: U256,
266
267    /// Highest block
268    highest_block: U256,
269}
270
271#[derive(Serialize, Deserialize, Debug)]
272#[serde(rename_all = "camelCase")]
273pub struct TransactionReceipt {
274    /// From address
275    pub from: Address,
276    /// To address
277    pub to: Option<Address>,
278    /// Contract address created by this transaction.
279    pub contract_address: Option<Address>,
280    /// Gas used
281    pub gas_used: U256,
282    /// Gas used
283    pub cumulative_gas_used: U256,
284
285    pub effective_gas_price: U256,
286
287    transaction_index: U256,
288    /// Block hash
289    pub block_hash: H256,
290    /// Block number
291    pub block_number: U256,
292    /// 1 for success, 0 for failure.
293    pub status: Option<Status>,
294    /// Logs
295    pub logs: Vec<Log>,
296    /// Logs bloom filter string
297    pub logs_bloom: Bytes,
298    /// Only include before the Byzantium upgrade
299    pub root: Option<H256>,
300}
301
302#[derive(Debug, Clone, Serialize, Deserialize)]
303pub enum Status {
304    // 0x00
305    #[serde(rename = "0x1")]
306    Success,
307    // 0x01
308    #[serde(rename = "0x0")]
309    Failure,
310}
311
312#[derive(Serialize, Deserialize)]
313#[serde(rename_all = "camelCase")]
314pub struct Block {
315    /// Current block hash value
316    pub hash: Option<H256>,
317    /// Parent block hash
318    #[serde(rename = "parentHash")]
319    pub parent_hash: H256,
320
321    /// Ommers hash
322    #[serde(rename = "sha3Uncles")]
323    pub sha3_uncles: Option<H256>,
324
325    /// Coinbase
326    pub miner: Address,
327
328    /// State root
329    #[serde(rename = "stateRoot")]
330    pub state_root: H256,
331
332    /// Transactions root
333    #[serde(rename = "transactionsRoot")]
334    pub transactions_root: H256,
335
336    /// Receipts root
337    #[serde(rename = "receiptsRoot")]
338    pub receipts_root: H256,
339
340    /// Bloom filter
341    #[serde(rename = "logsBloom")]
342    #[serde(skip_serializing_if = "Option::is_none")]
343    pub logs_bloom: Option<Bytes>,
344
345    /// Difficulty
346    #[serde(skip_serializing_if = "Option::is_none")]
347    pub difficulty: Option<Bytes>,
348
349    /// U256
350    pub number: Option<U256>,
351
352    /// Gas limit
353
354    #[serde(rename = "gasLimit")]
355    pub gas_limit: U256,
356
357    /// Gas used
358    #[serde(rename = "gasUsed")]
359    pub gas_used: U256,
360
361    /// Timestamp
362    pub timestamp: U256,
363
364    /// Extra data
365    #[serde(rename = "extraData")]
366    pub extra_data: Bytes,
367
368    /// Mix hash
369    #[serde(rename = "mixHash")]
370    pub mix_hash: Option<H256>,
371
372    /// Nonce
373    pub nonce: Option<U256>,
374
375    /// Total difficult
376    #[serde(rename = "totalDeffficult")]
377    #[serde(skip_serializing_if = "Option::is_none")]
378    pub total_deffficult: Option<Bytes>,
379
380    /// Base fee per gas
381    #[serde(rename = "baseFeePerGas")]
382    #[serde(skip_serializing_if = "Option::is_none")]
383    pub base_fee_per_gas: Option<U256>,
384
385    /// Block size
386    pub size: U256,
387
388    /// transactions
389    pub transactions: Vec<TransactionOrHash>,
390
391    /// Uncles
392    pub uncles: Vec<H256>,
393}
394
395#[derive(Serialize, Deserialize)]
396#[serde(untagged)]
397pub enum TransactionOrHash {
398    Null,
399    Hash(H256),
400    Transaction(Transaction),
401}
402
403#[derive(Debug, Clone, Serialize, Deserialize)]
404pub enum TransactionType {
405    // 0x00
406    #[serde(rename = "0x00")]
407    Legacy,
408    // 0x01
409    #[serde(rename = "0x01")]
410    Eip2930,
411    // 0x02
412    #[serde(rename = "0x02")]
413    Eip1559,
414}
415
416#[derive(Serialize, Deserialize, Debug, Clone)]
417pub struct Transaction {
418    /// transaction type
419    ///
420    /// 1. Legacy (pre-EIP2718) `0x00`
421    /// 2. EIP2930 (state access lists) `0x01`
422    /// 3. EIP1559 0x02
423    #[serde(skip_serializing_if = "Option::is_none")]
424    pub r#type: Option<TransactionType>,
425    /// transaction nonce
426    #[serde(skip_serializing_if = "Option::is_none")]
427    pub nonce: Option<U256>,
428    /// To address
429    pub to: Address,
430    /// Gas limit
431    #[serde(skip_serializing_if = "Option::is_none")]
432    pub gas: Option<U256>,
433
434    /// Transaction index in block
435    #[serde(rename = "transactionIndex")]
436    #[serde(skip_serializing_if = "Option::is_none")]
437    transaction_index: Option<U256>,
438    /// Block hash
439    #[serde(rename = "blockHash")]
440    #[serde(skip_serializing_if = "Option::is_none")]
441    pub block_hash: Option<H256>,
442    /// Block number
443    #[serde(rename = "blockNumber")]
444    #[serde(skip_serializing_if = "Option::is_none")]
445    pub block_number: Option<U256>,
446    /// Gas limit
447    #[serde(rename = "gasPrice")]
448    #[serde(skip_serializing_if = "Option::is_none")]
449    pub gas_price: Option<U256>,
450    /// Transaction hash
451    #[serde(skip_serializing_if = "Option::is_none")]
452    pub hash: Option<H256>,
453    /// Transfer eth value
454    #[serde(skip_serializing_if = "Option::is_none")]
455    pub value: Option<U256>,
456    /// Input data to call contract.
457    pub input: Bytes,
458    /// Maximum fee per gas the sender is willing to pay to miners in wei
459    #[serde(rename = "maxPriorityFeePerGas")]
460    #[serde(skip_serializing_if = "Option::is_none")]
461    pub max_priority_fee_per_gas: Option<U256>,
462    /// Maximum total fee per gas the sender is willing to
463    /// pay(includes the network/base fee and miner/ priority fee) in wei
464    #[serde(rename = "maxFeePerGas")]
465    #[serde(skip_serializing_if = "Option::is_none")]
466    pub max_fee_per_gas: Option<U256>,
467    /// EIP-2930 access list
468    #[serde(skip_serializing_if = "Option::is_none")]
469    pub access_list: Option<AccessList>,
470    /// Chain ID tha this transaction is valid on
471    #[serde(rename = "chainId")]
472    #[serde(skip_serializing_if = "Option::is_none")]
473    pub chain_id: Option<U256>,
474    /// The parity(0 for even, 1 for odd) of the y-value of the secp256k1 signature.
475    #[serde(skip_serializing_if = "Option::is_none")]
476    pub v: Option<U256>,
477    /// r-value of the secp256k1
478    #[serde(skip_serializing_if = "Option::is_none")]
479    pub r: Option<U256>,
480    /// s-value of the secp256k1
481    #[serde(skip_serializing_if = "Option::is_none")]
482    pub s: Option<U256>,
483}
484
485from_json!(Transaction);