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 const 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 const 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<Self>,
221 {
222 if self.0.inner.inner.inner().is_ethereum() {
223 Ok(Either::Left(self.0.inner.inner.into_inner().try_into_envelope().unwrap()))
224 } else {
225 T::try_from(self).map(Either::Right)
226 }
227 }
228
229 pub fn try_unknown_into_either<T>(self) -> Result<Either<TxEnvelope, T>, T::Error>
235 where
236 T: TryFrom<UnknownTxEnvelope>,
237 {
238 self.0.inner.inner.into_inner().try_into_either()
239 }
240
241 pub fn map<Tx>(self, f: impl FnOnce(AnyTxEnvelope) -> Tx) -> Transaction<Tx> {
246 self.into_inner().map(f)
247 }
248
249 pub fn try_map<Tx, E>(
253 self,
254 f: impl FnOnce(AnyTxEnvelope) -> Result<Tx, E>,
255 ) -> Result<Transaction<Tx>, E> {
256 self.into_inner().try_map(f)
257 }
258
259 pub fn convert<U>(self) -> Transaction<U>
263 where
264 U: From<AnyTxEnvelope>,
265 {
266 self.into_inner().map(U::from)
267 }
268
269 pub fn try_convert<U>(self) -> Result<Transaction<U>, U::Error>
275 where
276 U: TryFrom<AnyTxEnvelope>,
277 {
278 self.into_inner().try_map(U::try_from)
279 }
280}
281
282impl AsRef<AnyTxEnvelope> for AnyRpcTransaction {
283 fn as_ref(&self) -> &AnyTxEnvelope {
284 &self.0.inner.inner
285 }
286}
287
288impl Deref for AnyRpcTransaction {
289 type Target = WithOtherFields<Transaction<AnyTxEnvelope>>;
290
291 fn deref(&self) -> &Self::Target {
292 &self.0
293 }
294}
295
296impl DerefMut for AnyRpcTransaction {
297 fn deref_mut(&mut self) -> &mut Self::Target {
298 &mut self.0
299 }
300}
301
302impl From<Transaction<TxEnvelope>> for AnyRpcTransaction {
303 fn from(tx: Transaction<TxEnvelope>) -> Self {
304 let tx = tx.map(AnyTxEnvelope::Ethereum);
305 Self(WithOtherFields::new(tx))
306 }
307}
308
309impl From<AnyRpcTransaction> for AnyTxEnvelope {
310 fn from(tx: AnyRpcTransaction) -> Self {
311 tx.0.inner.into_inner()
312 }
313}
314
315impl From<AnyRpcTransaction> for Transaction<AnyTxEnvelope> {
316 fn from(tx: AnyRpcTransaction) -> Self {
317 tx.0.inner
318 }
319}
320
321impl From<AnyRpcTransaction> for WithOtherFields<Transaction<AnyTxEnvelope>> {
322 fn from(tx: AnyRpcTransaction) -> Self {
323 tx.0
324 }
325}
326
327impl From<AnyRpcTransaction> for Recovered<AnyTxEnvelope> {
328 fn from(tx: AnyRpcTransaction) -> Self {
329 tx.0.inner.inner
330 }
331}
332
333impl TryFrom<AnyRpcTransaction> for TxEnvelope {
334 type Error = ValueError<AnyTxEnvelope>;
335
336 fn try_from(value: AnyRpcTransaction) -> Result<Self, Self::Error> {
337 value.try_into_envelope()
338 }
339}
340
341impl alloy_consensus::Transaction for AnyRpcTransaction {
342 fn chain_id(&self) -> Option<ChainId> {
343 self.inner.chain_id()
344 }
345
346 fn nonce(&self) -> u64 {
347 self.inner.nonce()
348 }
349
350 fn gas_limit(&self) -> u64 {
351 self.inner.gas_limit()
352 }
353
354 fn gas_price(&self) -> Option<u128> {
355 alloy_consensus::Transaction::gas_price(&self.0.inner)
356 }
357
358 fn max_fee_per_gas(&self) -> u128 {
359 alloy_consensus::Transaction::max_fee_per_gas(&self.inner)
360 }
361
362 fn max_priority_fee_per_gas(&self) -> Option<u128> {
363 self.inner.max_priority_fee_per_gas()
364 }
365
366 fn max_fee_per_blob_gas(&self) -> Option<u128> {
367 self.inner.max_fee_per_blob_gas()
368 }
369
370 fn priority_fee_or_price(&self) -> u128 {
371 self.inner.priority_fee_or_price()
372 }
373
374 fn effective_gas_price(&self, base_fee: Option<u64>) -> u128 {
375 self.inner.effective_gas_price(base_fee)
376 }
377
378 fn is_dynamic_fee(&self) -> bool {
379 self.inner.is_dynamic_fee()
380 }
381
382 fn kind(&self) -> TxKind {
383 self.inner.kind()
384 }
385
386 fn is_create(&self) -> bool {
387 self.inner.is_create()
388 }
389
390 fn value(&self) -> U256 {
391 self.inner.value()
392 }
393
394 fn input(&self) -> &Bytes {
395 self.inner.input()
396 }
397
398 fn access_list(&self) -> Option<&AccessList> {
399 self.inner.access_list()
400 }
401
402 fn blob_versioned_hashes(&self) -> Option<&[B256]> {
403 self.inner.blob_versioned_hashes()
404 }
405
406 fn authorization_list(&self) -> Option<&[SignedAuthorization]> {
407 self.inner.authorization_list()
408 }
409}
410
411impl TransactionResponse for AnyRpcTransaction {
412 fn tx_hash(&self) -> alloy_primitives::TxHash {
413 self.inner.tx_hash()
414 }
415
416 fn block_hash(&self) -> Option<alloy_primitives::BlockHash> {
417 self.0.inner.block_hash
418 }
419
420 fn block_number(&self) -> Option<u64> {
421 self.inner.block_number
422 }
423
424 fn transaction_index(&self) -> Option<u64> {
425 self.inner.transaction_index
426 }
427
428 fn from(&self) -> alloy_primitives::Address {
429 self.inner.from()
430 }
431
432 fn gas_price(&self) -> Option<u128> {
433 self.inner.effective_gas_price
434 }
435}
436
437impl Typed2718 for AnyRpcTransaction {
438 fn ty(&self) -> u8 {
439 self.inner.ty()
440 }
441}