1mod builder;
2
3mod either;
4use alloy_consensus::TxEnvelope;
5use alloy_eips::{eip7702::SignedAuthorization, Typed2718};
6use alloy_primitives::{Bytes, ChainId, TxKind, B256, U256};
7pub use either::{AnyTxEnvelope, AnyTypedTransaction};
8
9mod unknowns;
10pub use unknowns::{AnyTxType, UnknownTxEnvelope, UnknownTypedTransaction};
11
12pub use alloy_consensus_any::{AnyHeader, AnyReceiptEnvelope};
13
14use crate::Network;
15use alloy_consensus::{
16 error::ValueError,
17 transaction::{Either, Recovered},
18};
19use alloy_network_primitives::{BlockResponse, TransactionResponse};
20pub use alloy_rpc_types_any::{AnyRpcHeader, AnyTransactionReceipt};
21use alloy_rpc_types_eth::{AccessList, Block, BlockTransactions, Transaction, TransactionRequest};
22use alloy_serde::WithOtherFields;
23use derive_more::From;
24use serde::{Deserialize, Serialize};
25use std::ops::{Deref, DerefMut};
26
27#[derive(Clone, Copy, Debug)]
56pub struct AnyNetwork {
57 _private: (),
58}
59
60impl Network for AnyNetwork {
61 type TxType = AnyTxType;
62
63 type TxEnvelope = AnyTxEnvelope;
64
65 type UnsignedTx = AnyTypedTransaction;
66
67 type ReceiptEnvelope = AnyReceiptEnvelope;
68
69 type Header = AnyHeader;
70
71 type TransactionRequest = WithOtherFields<TransactionRequest>;
72
73 type TransactionResponse = AnyRpcTransaction;
74
75 type ReceiptResponse = AnyTransactionReceipt;
76
77 type HeaderResponse = AnyRpcHeader;
78
79 type BlockResponse = AnyRpcBlock;
80}
81
82#[derive(Clone, Debug, From, PartialEq, Eq, Deserialize, Serialize)]
88pub struct AnyRpcBlock(pub WithOtherFields<Block<AnyRpcTransaction, AnyRpcHeader>>);
89
90impl AnyRpcBlock {
91 pub fn new(inner: WithOtherFields<Block<AnyRpcTransaction, AnyRpcHeader>>) -> Self {
93 Self(inner)
94 }
95
96 pub fn into_inner(self) -> Block<AnyRpcTransaction, AnyRpcHeader> {
98 self.0.into_inner()
99 }
100
101 pub fn try_into_transactions(
105 self,
106 ) -> Result<Vec<AnyRpcTransaction>, ValueError<BlockTransactions<AnyRpcTransaction>>> {
107 self.0.inner.try_into_transactions()
108 }
109
110 pub fn into_transactions_iter(self) -> impl Iterator<Item = AnyRpcTransaction> {
112 self.into_inner().transactions.into_transactions()
113 }
114}
115
116impl BlockResponse for AnyRpcBlock {
117 type Header = AnyRpcHeader;
118 type Transaction = AnyRpcTransaction;
119
120 fn header(&self) -> &Self::Header {
121 &self.0.inner.header
122 }
123
124 fn transactions(&self) -> &BlockTransactions<Self::Transaction> {
125 &self.0.inner.transactions
126 }
127
128 fn transactions_mut(&mut self) -> &mut BlockTransactions<Self::Transaction> {
129 &mut self.0.inner.transactions
130 }
131
132 fn other_fields(&self) -> Option<&alloy_serde::OtherFields> {
133 self.0.other_fields()
134 }
135}
136
137impl AsRef<WithOtherFields<Block<AnyRpcTransaction, AnyRpcHeader>>> for AnyRpcBlock {
138 fn as_ref(&self) -> &WithOtherFields<Block<AnyRpcTransaction, AnyRpcHeader>> {
139 &self.0
140 }
141}
142
143impl Deref for AnyRpcBlock {
144 type Target = WithOtherFields<Block<AnyRpcTransaction, AnyRpcHeader>>;
145
146 fn deref(&self) -> &Self::Target {
147 &self.0
148 }
149}
150
151impl DerefMut for AnyRpcBlock {
152 fn deref_mut(&mut self) -> &mut Self::Target {
153 &mut self.0
154 }
155}
156
157impl From<Block> for AnyRpcBlock {
158 fn from(value: Block) -> Self {
159 let block = value
160 .map_header(|h| h.map(|h| alloy_consensus_any::AnyHeader { ..h.into() }))
161 .map_transactions(|tx| {
162 AnyRpcTransaction::new(WithOtherFields::new(tx.map(AnyTxEnvelope::Ethereum)))
163 });
164
165 Self(WithOtherFields::new(block))
166 }
167}
168
169impl From<AnyRpcBlock> for Block<AnyRpcTransaction, AnyRpcHeader> {
170 fn from(value: AnyRpcBlock) -> Self {
171 value.into_inner()
172 }
173}
174impl From<AnyRpcBlock> for WithOtherFields<Block<AnyRpcTransaction, AnyRpcHeader>> {
175 fn from(value: AnyRpcBlock) -> Self {
176 value.0
177 }
178}
179
180#[derive(Clone, Debug, From, PartialEq, Eq, Deserialize, Serialize)]
182pub struct AnyRpcTransaction(pub WithOtherFields<Transaction<AnyTxEnvelope>>);
183
184impl AnyRpcTransaction {
185 pub fn new(inner: WithOtherFields<Transaction<AnyTxEnvelope>>) -> Self {
187 Self(inner)
188 }
189
190 pub fn into_parts(self) -> (Transaction<AnyTxEnvelope>, alloy_serde::OtherFields) {
192 let WithOtherFields { inner, other } = self.0;
193 (inner, other)
194 }
195
196 pub fn into_inner(self) -> Transaction<AnyTxEnvelope> {
198 self.0.into_inner()
199 }
200
201 pub fn as_envelope(&self) -> Option<&TxEnvelope> {
204 self.inner.inner.as_envelope()
205 }
206
207 pub fn try_into_envelope(self) -> Result<TxEnvelope, ValueError<AnyTxEnvelope>> {
210 self.0.inner.inner.into_inner().try_into_envelope()
211 }
212
213 pub fn try_into_either<T>(self) -> Result<Either<TxEnvelope, T>, T::Error>
219 where
220 T: TryFrom<UnknownTxEnvelope>,
221 {
222 self.0.inner.inner.into_inner().try_into_either()
223 }
224
225 pub fn map<Tx>(self, f: impl FnOnce(AnyTxEnvelope) -> Tx) -> Transaction<Tx> {
230 self.into_inner().map(f)
231 }
232
233 pub fn try_map<Tx, E>(
237 self,
238 f: impl FnOnce(AnyTxEnvelope) -> Result<Tx, E>,
239 ) -> Result<Transaction<Tx>, E> {
240 self.into_inner().try_map(f)
241 }
242
243 pub fn convert<U>(self) -> Transaction<U>
247 where
248 U: From<AnyTxEnvelope>,
249 {
250 self.into_inner().map(U::from)
251 }
252
253 pub fn try_convert<U>(self) -> Result<Transaction<U>, U::Error>
259 where
260 U: TryFrom<AnyTxEnvelope>,
261 {
262 self.into_inner().try_map(U::try_from)
263 }
264}
265
266impl AsRef<AnyTxEnvelope> for AnyRpcTransaction {
267 fn as_ref(&self) -> &AnyTxEnvelope {
268 &self.0.inner.inner
269 }
270}
271
272impl Deref for AnyRpcTransaction {
273 type Target = WithOtherFields<Transaction<AnyTxEnvelope>>;
274
275 fn deref(&self) -> &Self::Target {
276 &self.0
277 }
278}
279
280impl DerefMut for AnyRpcTransaction {
281 fn deref_mut(&mut self) -> &mut Self::Target {
282 &mut self.0
283 }
284}
285
286impl From<Transaction<TxEnvelope>> for AnyRpcTransaction {
287 fn from(tx: Transaction<TxEnvelope>) -> Self {
288 let tx = tx.map(AnyTxEnvelope::Ethereum);
289 Self(WithOtherFields::new(tx))
290 }
291}
292
293impl From<AnyRpcTransaction> for AnyTxEnvelope {
294 fn from(tx: AnyRpcTransaction) -> Self {
295 tx.0.inner.into_inner()
296 }
297}
298
299impl From<AnyRpcTransaction> for Transaction<AnyTxEnvelope> {
300 fn from(tx: AnyRpcTransaction) -> Self {
301 tx.0.inner
302 }
303}
304
305impl From<AnyRpcTransaction> for WithOtherFields<Transaction<AnyTxEnvelope>> {
306 fn from(tx: AnyRpcTransaction) -> Self {
307 tx.0
308 }
309}
310
311impl From<AnyRpcTransaction> for Recovered<AnyTxEnvelope> {
312 fn from(tx: AnyRpcTransaction) -> Self {
313 tx.0.inner.inner
314 }
315}
316
317impl TryFrom<AnyRpcTransaction> for TxEnvelope {
318 type Error = ValueError<AnyTxEnvelope>;
319
320 fn try_from(value: AnyRpcTransaction) -> Result<Self, Self::Error> {
321 value.try_into_envelope()
322 }
323}
324
325impl alloy_consensus::Transaction for AnyRpcTransaction {
326 fn chain_id(&self) -> Option<ChainId> {
327 self.inner.chain_id()
328 }
329
330 fn nonce(&self) -> u64 {
331 self.inner.nonce()
332 }
333
334 fn gas_limit(&self) -> u64 {
335 self.inner.gas_limit()
336 }
337
338 fn gas_price(&self) -> Option<u128> {
339 alloy_consensus::Transaction::gas_price(&self.0.inner)
340 }
341
342 fn max_fee_per_gas(&self) -> u128 {
343 alloy_consensus::Transaction::max_fee_per_gas(&self.inner)
344 }
345
346 fn max_priority_fee_per_gas(&self) -> Option<u128> {
347 self.inner.max_priority_fee_per_gas()
348 }
349
350 fn max_fee_per_blob_gas(&self) -> Option<u128> {
351 self.inner.max_fee_per_blob_gas()
352 }
353
354 fn priority_fee_or_price(&self) -> u128 {
355 self.inner.priority_fee_or_price()
356 }
357
358 fn effective_gas_price(&self, base_fee: Option<u64>) -> u128 {
359 self.inner.effective_gas_price(base_fee)
360 }
361
362 fn is_dynamic_fee(&self) -> bool {
363 self.inner.is_dynamic_fee()
364 }
365
366 fn kind(&self) -> TxKind {
367 self.inner.kind()
368 }
369
370 fn is_create(&self) -> bool {
371 self.inner.is_create()
372 }
373
374 fn value(&self) -> U256 {
375 self.inner.value()
376 }
377
378 fn input(&self) -> &Bytes {
379 self.inner.input()
380 }
381
382 fn access_list(&self) -> Option<&AccessList> {
383 self.inner.access_list()
384 }
385
386 fn blob_versioned_hashes(&self) -> Option<&[B256]> {
387 self.inner.blob_versioned_hashes()
388 }
389
390 fn authorization_list(&self) -> Option<&[SignedAuthorization]> {
391 self.inner.authorization_list()
392 }
393}
394
395impl TransactionResponse for AnyRpcTransaction {
396 fn tx_hash(&self) -> alloy_primitives::TxHash {
397 self.inner.tx_hash()
398 }
399
400 fn block_hash(&self) -> Option<alloy_primitives::BlockHash> {
401 self.0.inner.block_hash
402 }
403
404 fn block_number(&self) -> Option<u64> {
405 self.inner.block_number
406 }
407
408 fn transaction_index(&self) -> Option<u64> {
409 self.inner.transaction_index
410 }
411
412 fn from(&self) -> alloy_primitives::Address {
413 self.inner.from()
414 }
415
416 fn gas_price(&self) -> Option<u128> {
417 self.inner.effective_gas_price
418 }
419}
420
421impl Typed2718 for AnyRpcTransaction {
422 fn ty(&self) -> u8 {
423 self.inner.ty()
424 }
425}