alloy_network_primitives/
traits.rs1use crate::{BlockTransactions, InclusionInfo};
2use alloy_consensus::{BlockHeader, Transaction};
3use alloy_eips::BlockNumHash;
4use alloy_primitives::{Address, BlockHash, TxHash, B256};
5use alloy_serde::WithOtherFields;
6
7#[derive(Debug, Clone, PartialEq, Eq)]
9pub struct TransactionFailedError {
10 pub transaction_hash: TxHash,
12}
13
14impl core::fmt::Display for TransactionFailedError {
15 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
16 write!(f, "Transaction {} failed", self.transaction_hash)
17 }
18}
19
20impl core::error::Error for TransactionFailedError {}
21
22pub trait ReceiptResponse {
24 fn contract_address(&self) -> Option<Address>;
26
27 fn status(&self) -> bool;
36
37 fn block_hash(&self) -> Option<BlockHash>;
39
40 fn block_number(&self) -> Option<u64>;
42
43 fn block_hash_num(&self) -> Option<BlockNumHash> {
47 Some(BlockNumHash::new(self.block_number()?, self.block_hash()?))
48 }
49
50 fn transaction_hash(&self) -> TxHash;
52
53 fn transaction_index(&self) -> Option<u64>;
55
56 fn gas_used(&self) -> u64;
58
59 fn effective_gas_price(&self) -> u128;
61
62 fn cost(&self) -> u128 {
64 self.gas_used() as u128 * self.effective_gas_price()
65 }
66
67 fn blob_gas_used(&self) -> Option<u64>;
69
70 fn blob_gas_price(&self) -> Option<u128>;
72
73 fn from(&self) -> Address;
75
76 fn to(&self) -> Option<Address>;
78
79 fn cumulative_gas_used(&self) -> u64;
81
82 fn state_root(&self) -> Option<B256>;
86
87 fn ensure_success(&self) -> Result<(), TransactionFailedError> {
89 if self.status() {
90 Ok(())
91 } else {
92 Err(TransactionFailedError { transaction_hash: self.transaction_hash() })
93 }
94 }
95}
96
97pub trait TransactionResponse: Transaction {
99 #[doc(alias = "transaction_hash")]
101 fn tx_hash(&self) -> TxHash;
102
103 fn block_hash(&self) -> Option<BlockHash>;
107
108 fn block_number(&self) -> Option<u64>;
112
113 fn block_hash_num(&self) -> Option<BlockNumHash> {
117 Some(BlockNumHash::new(self.block_number()?, self.block_hash()?))
118 }
119
120 fn transaction_index(&self) -> Option<u64>;
122
123 fn from(&self) -> Address;
125
126 fn gas_price(&self) -> Option<u128> {
128 if self.ty() < 2 {
129 return Some(Transaction::max_fee_per_gas(self));
130 }
131 None
132 }
133
134 fn max_fee_per_gas(&self) -> Option<u128> {
137 if self.ty() < 2 {
138 return None;
139 }
140 Some(Transaction::max_fee_per_gas(self))
141 }
142
143 fn transaction_type(&self) -> Option<u8> {
145 match self.ty() {
146 0 => None,
147 ty => Some(ty),
148 }
149 }
150
151 fn inclusion_info(&self) -> Option<InclusionInfo> {
155 Some(InclusionInfo {
156 block_hash: self.block_hash()?,
157 block_number: self.block_number()?,
158 transaction_index: self.transaction_index()?,
159 })
160 }
161}
162
163pub trait HeaderResponse: BlockHeader {
165 fn hash(&self) -> BlockHash;
167}
168
169pub trait BlockResponse {
171 type Header;
173 type Transaction: TransactionResponse;
175
176 fn header(&self) -> &Self::Header;
178
179 fn transactions(&self) -> &BlockTransactions<Self::Transaction>;
181
182 fn transactions_mut(&mut self) -> &mut BlockTransactions<Self::Transaction>;
184
185 fn other_fields(&self) -> Option<&alloy_serde::OtherFields> {
187 None
188 }
189}
190
191impl<T: TransactionResponse> TransactionResponse for WithOtherFields<T> {
192 fn tx_hash(&self) -> TxHash {
193 self.inner.tx_hash()
194 }
195
196 fn block_hash(&self) -> Option<BlockHash> {
197 self.inner.block_hash()
198 }
199
200 fn block_number(&self) -> Option<u64> {
201 self.inner.block_number()
202 }
203
204 fn transaction_index(&self) -> Option<u64> {
205 self.inner.transaction_index()
206 }
207
208 fn from(&self) -> Address {
209 self.inner.from()
210 }
211}
212
213impl<T: ReceiptResponse> ReceiptResponse for WithOtherFields<T> {
214 fn contract_address(&self) -> Option<Address> {
215 self.inner.contract_address()
216 }
217
218 fn status(&self) -> bool {
219 self.inner.status()
220 }
221
222 fn block_hash(&self) -> Option<BlockHash> {
223 self.inner.block_hash()
224 }
225
226 fn block_number(&self) -> Option<u64> {
227 self.inner.block_number()
228 }
229
230 fn transaction_hash(&self) -> TxHash {
231 self.inner.transaction_hash()
232 }
233
234 fn transaction_index(&self) -> Option<u64> {
235 self.inner.transaction_index()
236 }
237
238 fn gas_used(&self) -> u64 {
239 self.inner.gas_used()
240 }
241
242 fn effective_gas_price(&self) -> u128 {
243 self.inner.effective_gas_price()
244 }
245
246 fn blob_gas_used(&self) -> Option<u64> {
247 self.inner.blob_gas_used()
248 }
249
250 fn blob_gas_price(&self) -> Option<u128> {
251 self.inner.blob_gas_price()
252 }
253
254 fn from(&self) -> Address {
255 self.inner.from()
256 }
257
258 fn to(&self) -> Option<Address> {
259 self.inner.to()
260 }
261
262 fn cumulative_gas_used(&self) -> u64 {
263 self.inner.cumulative_gas_used()
264 }
265
266 fn state_root(&self) -> Option<B256> {
267 self.inner.state_root()
268 }
269}
270
271impl<T: BlockResponse> BlockResponse for WithOtherFields<T> {
272 type Header = T::Header;
273 type Transaction = T::Transaction;
274
275 fn header(&self) -> &Self::Header {
276 self.inner.header()
277 }
278
279 fn transactions(&self) -> &BlockTransactions<Self::Transaction> {
280 self.inner.transactions()
281 }
282
283 fn transactions_mut(&mut self) -> &mut BlockTransactions<Self::Transaction> {
284 self.inner.transactions_mut()
285 }
286
287 fn other_fields(&self) -> Option<&alloy_serde::OtherFields> {
288 Some(&self.other)
289 }
290}
291
292impl<T: HeaderResponse> HeaderResponse for WithOtherFields<T> {
293 fn hash(&self) -> BlockHash {
294 self.inner.hash()
295 }
296}