foundry_blob_explorers/
request.rs

1//! Request types for the Blobscan API.
2
3use serde::{ser::SerializeStruct, Deserialize, Serialize};
4
5/// Additional query parameters for the `blocks` endpoint.
6///
7/// By default all fields are requested.
8#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
9pub struct GetBlockQuery {
10    /// What kind of block to fetch.
11    pub expand: BlockExpansion,
12    /// What kind of block to fetch.
13    pub kind: BlockKind,
14}
15
16impl GetBlockQuery {
17    /// Create a new request with the given expansion options.
18    pub const fn new(expand: BlockExpansion) -> Self {
19        Self { expand, kind: BlockKind::Canonical }
20    }
21
22    /// Request transaction, blob and blob data in the response.
23    pub const fn with_all(self) -> Self {
24        Self { expand: BlockExpansion::all(), ..self }
25    }
26
27    /// Exclude transactions, blob and blob data in the response.
28    pub const fn with_none(self) -> Self {
29        Self { expand: BlockExpansion::none(), ..self }
30    }
31
32    /// Request a reorged block.
33    pub const fn reorged(self) -> Self {
34        Self { kind: BlockKind::Reorged, ..self }
35    }
36
37    /// Include the transactions in the response.
38    pub const fn with_transaction(self) -> Self {
39        Self { expand: self.expand.with_transaction(), ..self }
40    }
41
42    /// Exclude the transactions from the response.
43    pub const fn no_transactions(self) -> Self {
44        Self { expand: self.expand.no_transactions(), ..self }
45    }
46
47    /// Include the blob in the response.
48    pub const fn with_blob(self) -> Self {
49        Self { expand: self.expand.with_blob(), ..self }
50    }
51
52    /// Exclude the blob from the response.
53    pub const fn no_blob(self) -> Self {
54        Self { expand: self.expand.no_blob(), ..self }
55    }
56
57    /// Include the blob in the response.
58    pub const fn with_blob_data(self) -> Self {
59        Self { expand: self.expand.with_blob_data(), ..self }
60    }
61
62    /// Exclude the blob data from the response.
63    pub const fn no_blob_data(self) -> Self {
64        Self { expand: self.expand.no_blob_data(), ..self }
65    }
66}
67
68impl Serialize for GetBlockQuery {
69    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
70    where
71        S: serde::Serializer,
72    {
73        let mut s = serializer.serialize_struct("GetBlockQuery", 2)?;
74        let expand = self.expand.query_string();
75        if !expand.is_empty() {
76            s.serialize_field("expand", &expand)?;
77        }
78        s.serialize_field("type", &self.kind)?;
79        s.end()
80    }
81}
82
83/// What kind of block to fetch.
84#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
85pub enum BlockKind {
86    /// Fetch the canonical block.
87    #[default]
88    #[serde(rename = "canonical")]
89    Canonical,
90    /// Fetch a reorged block.
91    #[serde(rename = "reorged")]
92    Reorged,
93}
94
95/// What to include in the block response.
96///
97/// By default all fields are requested.
98#[derive(Clone, Copy, Debug, PartialEq, Eq)]
99pub struct BlockExpansion {
100    /// Include the transaction in the response
101    pub transaction: bool,
102    /// Include the blob in the response
103    pub blob: bool,
104    /// Include the blob_data in the response
105    pub blob_data: bool,
106}
107
108impl BlockExpansion {
109    /// Build a `BlockExpansion` that includes everything.
110    pub const fn all() -> Self {
111        Self { transaction: true, blob: true, blob_data: true }
112    }
113
114    /// Build a `BlockExpansion` that excludes everything.
115    pub const fn none() -> Self {
116        Self { transaction: false, blob: false, blob_data: false }
117    }
118
119    /// Returns the query string for the block expansion.
120    pub fn query_string(self) -> String {
121        let Self { transaction, blob, blob_data } = self;
122        transaction
123            .then_some("transaction")
124            .into_iter()
125            .chain(blob.then_some("blob"))
126            .chain(blob_data.then_some("blob_data"))
127            .collect::<Vec<_>>()
128            .join(",")
129    }
130
131    /// Exclude the blob data from the response
132    pub const fn no_blob_data(self) -> Self {
133        Self { blob_data: false, ..self }
134    }
135
136    /// Exclude the transactions data from the response
137    pub const fn no_transactions(self) -> Self {
138        Self { transaction: false, ..self }
139    }
140
141    /// Exclude the blob  from the response
142    pub const fn no_blob(self) -> Self {
143        Self { blob: false, ..self }
144    }
145
146    /// Include the transactions in the response.
147    pub const fn with_transaction(self) -> Self {
148        Self { transaction: true, ..self }
149    }
150
151    /// Include the blob in the response.
152    pub const fn with_blob(self) -> Self {
153        Self { blob: true, ..self }
154    }
155
156    /// Include the blob in the response.
157    pub const fn with_blob_data(self) -> Self {
158        Self { blob_data: true, ..self }
159    }
160}
161
162impl Default for BlockExpansion {
163    fn default() -> Self {
164        Self::all()
165    }
166}
167
168/// What to include in the transaction response.
169///
170/// By default all fields are requested.
171#[derive(Clone, Copy, Debug, PartialEq, Eq)]
172pub struct GetTransactionQuery {
173    /// Include the block in the response
174    pub block: bool,
175    /// Include the blob in the response
176    pub blob: bool,
177    /// Include the blob_data in the response
178    pub blob_data: bool,
179}
180
181impl GetTransactionQuery {
182    /// Build a `TransactionExpansion` that includes everything.
183    pub const fn all() -> Self {
184        Self { block: true, blob: true, blob_data: true }
185    }
186
187    /// Build a `TransactionExpansion` that excludes everything.
188    pub const fn none() -> Self {
189        Self { block: false, blob: false, blob_data: false }
190    }
191
192    /// Returns the query string for the transaction expansion.
193    pub fn query_string(self) -> String {
194        let Self { block, blob, blob_data } = self;
195        block
196            .then_some("block")
197            .into_iter()
198            .chain(blob.then_some("blob"))
199            .chain(blob_data.then_some("blob_data"))
200            .collect::<Vec<_>>()
201            .join(",")
202    }
203
204    /// Exclude the blob data from the response
205    pub const fn no_blob_data(self) -> Self {
206        Self { blob_data: false, ..self }
207    }
208
209    /// Exclude the block data from the response
210    pub const fn no_block(self) -> Self {
211        Self { block: false, ..self }
212    }
213
214    /// Exclude the blob  from the response
215    pub const fn no_blob(self) -> Self {
216        Self { blob: false, ..self }
217    }
218}
219
220impl Default for GetTransactionQuery {
221    fn default() -> Self {
222        Self::all()
223    }
224}
225
226impl Serialize for GetTransactionQuery {
227    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
228    where
229        S: serde::Serializer,
230    {
231        let mut s = serializer.serialize_struct("GetTransactionQuery", 1)?;
232        let expand = self.query_string();
233        if !expand.is_empty() {
234            s.serialize_field("expand", &expand)?;
235        }
236        s.end()
237    }
238}