alloy_consensus/transaction/
typed.rs

1use crate::{
2    transaction::{
3        eip4844::{TxEip4844, TxEip4844Variant, TxEip4844WithSidecar},
4        RlpEcdsaEncodableTx,
5    },
6    EthereumTxEnvelope, SignableTransaction, Transaction, TxEip1559, TxEip2930, TxEip7702,
7    TxLegacy, TxType,
8};
9use alloy_eips::{eip2930::AccessList, eip7702::SignedAuthorization, Typed2718};
10use alloy_primitives::{
11    bytes::BufMut, Bytes, ChainId, PrimitiveSignature as Signature, TxHash, TxKind, B256, U256,
12};
13
14/// Basic typed transaction which can contain both [`TxEip4844`] and [`TxEip4844WithSidecar`].
15pub type TypedTransaction = EthereumTypedTransaction<TxEip4844Variant>;
16
17/// The TypedTransaction enum represents all Ethereum transaction request types.
18///
19/// Its variants correspond to specific allowed transactions:
20/// 1. Legacy (pre-EIP2718) [`TxLegacy`]
21/// 2. EIP2930 (state access lists) [`TxEip2930`]
22/// 3. EIP1559 [`TxEip1559`]
23/// 4. EIP4844 [`TxEip4844Variant`]
24///
25/// This type is generic over Eip4844 variant to support the following cases:
26/// 1. Only-[`TxEip4844`] transaction type, such transaction representation is returned by RPC and
27///    stored by nodes internally.
28/// 2. Only-[`TxEip4844WithSidecar`] transactions which are broadcasted over the network, submitted
29///    to RPC and stored in transaction pool.
30/// 3. Dynamic [`TxEip4844Variant`] transactions to support both of the above cases via a single
31///    type.
32#[derive(Clone, Debug, PartialEq, Eq, Hash)]
33#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
34#[cfg_attr(
35    feature = "serde",
36    serde(
37        from = "serde_from::MaybeTaggedTypedTransaction<Eip4844>",
38        into = "serde_from::TaggedTypedTransaction<Eip4844>",
39        bound = "Eip4844: Clone + serde::Serialize + serde::de::DeserializeOwned"
40    )
41)]
42#[cfg_attr(all(any(test, feature = "arbitrary"), feature = "k256"), derive(arbitrary::Arbitrary))]
43#[doc(alias = "TypedTx", alias = "TxTyped", alias = "TransactionTyped")]
44pub enum EthereumTypedTransaction<Eip4844> {
45    /// Legacy transaction
46    #[cfg_attr(feature = "serde", serde(rename = "0x00", alias = "0x0"))]
47    Legacy(TxLegacy),
48    /// EIP-2930 transaction
49    #[cfg_attr(feature = "serde", serde(rename = "0x01", alias = "0x1"))]
50    Eip2930(TxEip2930),
51    /// EIP-1559 transaction
52    #[cfg_attr(feature = "serde", serde(rename = "0x02", alias = "0x2"))]
53    Eip1559(TxEip1559),
54    /// EIP-4844 transaction
55    #[cfg_attr(feature = "serde", serde(rename = "0x03", alias = "0x3"))]
56    Eip4844(Eip4844),
57    /// EIP-7702 transaction
58    #[cfg_attr(feature = "serde", serde(rename = "0x04", alias = "0x4"))]
59    Eip7702(TxEip7702),
60}
61
62impl<Eip4844> From<TxLegacy> for EthereumTypedTransaction<Eip4844> {
63    fn from(tx: TxLegacy) -> Self {
64        Self::Legacy(tx)
65    }
66}
67
68impl<Eip4844> From<TxEip2930> for EthereumTypedTransaction<Eip4844> {
69    fn from(tx: TxEip2930) -> Self {
70        Self::Eip2930(tx)
71    }
72}
73
74impl<Eip4844> From<TxEip1559> for EthereumTypedTransaction<Eip4844> {
75    fn from(tx: TxEip1559) -> Self {
76        Self::Eip1559(tx)
77    }
78}
79
80impl<Eip4844: From<TxEip4844>> From<TxEip4844> for EthereumTypedTransaction<Eip4844> {
81    fn from(tx: TxEip4844) -> Self {
82        Self::Eip4844(tx.into())
83    }
84}
85
86impl<Eip4844: From<TxEip4844WithSidecar>> From<TxEip4844WithSidecar>
87    for EthereumTypedTransaction<Eip4844>
88{
89    fn from(tx: TxEip4844WithSidecar) -> Self {
90        Self::Eip4844(tx.into())
91    }
92}
93
94impl<Eip4844: From<TxEip4844Variant>> From<TxEip4844Variant> for EthereumTypedTransaction<Eip4844> {
95    fn from(tx: TxEip4844Variant) -> Self {
96        Self::Eip4844(tx.into())
97    }
98}
99
100impl<Eip4844> From<TxEip7702> for EthereumTypedTransaction<Eip4844> {
101    fn from(tx: TxEip7702) -> Self {
102        Self::Eip7702(tx)
103    }
104}
105
106impl<Eip4844> From<EthereumTxEnvelope<Eip4844>> for EthereumTypedTransaction<Eip4844> {
107    fn from(envelope: EthereumTxEnvelope<Eip4844>) -> Self {
108        match envelope {
109            EthereumTxEnvelope::Legacy(tx) => Self::Legacy(tx.strip_signature()),
110            EthereumTxEnvelope::Eip2930(tx) => Self::Eip2930(tx.strip_signature()),
111            EthereumTxEnvelope::Eip1559(tx) => Self::Eip1559(tx.strip_signature()),
112            EthereumTxEnvelope::Eip4844(tx) => Self::Eip4844(tx.strip_signature()),
113            EthereumTxEnvelope::Eip7702(tx) => Self::Eip7702(tx.strip_signature()),
114        }
115    }
116}
117
118impl<Eip4844: RlpEcdsaEncodableTx> EthereumTypedTransaction<Eip4844> {
119    /// Return the [`TxType`] of the inner txn.
120    #[doc(alias = "transaction_type")]
121    pub const fn tx_type(&self) -> TxType {
122        match self {
123            Self::Legacy(_) => TxType::Legacy,
124            Self::Eip2930(_) => TxType::Eip2930,
125            Self::Eip1559(_) => TxType::Eip1559,
126            Self::Eip4844(_) => TxType::Eip4844,
127            Self::Eip7702(_) => TxType::Eip7702,
128        }
129    }
130
131    /// Return the inner legacy transaction if it exists.
132    pub const fn legacy(&self) -> Option<&TxLegacy> {
133        match self {
134            Self::Legacy(tx) => Some(tx),
135            _ => None,
136        }
137    }
138
139    /// Return the inner EIP-2930 transaction if it exists.
140    pub const fn eip2930(&self) -> Option<&TxEip2930> {
141        match self {
142            Self::Eip2930(tx) => Some(tx),
143            _ => None,
144        }
145    }
146
147    /// Return the inner EIP-1559 transaction if it exists.
148    pub const fn eip1559(&self) -> Option<&TxEip1559> {
149        match self {
150            Self::Eip1559(tx) => Some(tx),
151            _ => None,
152        }
153    }
154
155    /// Return the inner EIP-7702 transaction if it exists.
156    pub const fn eip7702(&self) -> Option<&TxEip7702> {
157        match self {
158            Self::Eip7702(tx) => Some(tx),
159            _ => None,
160        }
161    }
162
163    /// Calculate the transaction hash for the given signature.
164    pub fn tx_hash(&self, signature: &Signature) -> TxHash {
165        match self {
166            Self::Legacy(tx) => tx.tx_hash(signature),
167            Self::Eip2930(tx) => tx.tx_hash(signature),
168            Self::Eip1559(tx) => tx.tx_hash(signature),
169            Self::Eip4844(tx) => tx.tx_hash(signature),
170            Self::Eip7702(tx) => tx.tx_hash(signature),
171        }
172    }
173}
174
175impl<Eip4844: Transaction> Transaction for EthereumTypedTransaction<Eip4844> {
176    #[inline]
177    fn chain_id(&self) -> Option<ChainId> {
178        match self {
179            Self::Legacy(tx) => tx.chain_id(),
180            Self::Eip2930(tx) => tx.chain_id(),
181            Self::Eip1559(tx) => tx.chain_id(),
182            Self::Eip4844(tx) => tx.chain_id(),
183            Self::Eip7702(tx) => tx.chain_id(),
184        }
185    }
186
187    #[inline]
188    fn nonce(&self) -> u64 {
189        match self {
190            Self::Legacy(tx) => tx.nonce(),
191            Self::Eip2930(tx) => tx.nonce(),
192            Self::Eip1559(tx) => tx.nonce(),
193            Self::Eip4844(tx) => tx.nonce(),
194            Self::Eip7702(tx) => tx.nonce(),
195        }
196    }
197
198    #[inline]
199    fn gas_limit(&self) -> u64 {
200        match self {
201            Self::Legacy(tx) => tx.gas_limit(),
202            Self::Eip2930(tx) => tx.gas_limit(),
203            Self::Eip1559(tx) => tx.gas_limit(),
204            Self::Eip4844(tx) => tx.gas_limit(),
205            Self::Eip7702(tx) => tx.gas_limit(),
206        }
207    }
208
209    #[inline]
210    fn gas_price(&self) -> Option<u128> {
211        match self {
212            Self::Legacy(tx) => tx.gas_price(),
213            Self::Eip2930(tx) => tx.gas_price(),
214            Self::Eip1559(tx) => tx.gas_price(),
215            Self::Eip4844(tx) => tx.gas_price(),
216            Self::Eip7702(tx) => tx.gas_price(),
217        }
218    }
219
220    #[inline]
221    fn max_fee_per_gas(&self) -> u128 {
222        match self {
223            Self::Legacy(tx) => tx.max_fee_per_gas(),
224            Self::Eip2930(tx) => tx.max_fee_per_gas(),
225            Self::Eip1559(tx) => tx.max_fee_per_gas(),
226            Self::Eip4844(tx) => tx.max_fee_per_gas(),
227            Self::Eip7702(tx) => tx.max_fee_per_gas(),
228        }
229    }
230
231    #[inline]
232    fn max_priority_fee_per_gas(&self) -> Option<u128> {
233        match self {
234            Self::Legacy(tx) => tx.max_priority_fee_per_gas(),
235            Self::Eip2930(tx) => tx.max_priority_fee_per_gas(),
236            Self::Eip1559(tx) => tx.max_priority_fee_per_gas(),
237            Self::Eip4844(tx) => tx.max_priority_fee_per_gas(),
238            Self::Eip7702(tx) => tx.max_priority_fee_per_gas(),
239        }
240    }
241
242    #[inline]
243    fn max_fee_per_blob_gas(&self) -> Option<u128> {
244        match self {
245            Self::Legacy(tx) => tx.max_fee_per_blob_gas(),
246            Self::Eip2930(tx) => tx.max_fee_per_blob_gas(),
247            Self::Eip1559(tx) => tx.max_fee_per_blob_gas(),
248            Self::Eip4844(tx) => tx.max_fee_per_blob_gas(),
249            Self::Eip7702(tx) => tx.max_fee_per_blob_gas(),
250        }
251    }
252
253    #[inline]
254    fn priority_fee_or_price(&self) -> u128 {
255        match self {
256            Self::Legacy(tx) => tx.priority_fee_or_price(),
257            Self::Eip2930(tx) => tx.priority_fee_or_price(),
258            Self::Eip1559(tx) => tx.priority_fee_or_price(),
259            Self::Eip4844(tx) => tx.priority_fee_or_price(),
260            Self::Eip7702(tx) => tx.priority_fee_or_price(),
261        }
262    }
263
264    fn effective_gas_price(&self, base_fee: Option<u64>) -> u128 {
265        match self {
266            Self::Legacy(tx) => tx.effective_gas_price(base_fee),
267            Self::Eip2930(tx) => tx.effective_gas_price(base_fee),
268            Self::Eip1559(tx) => tx.effective_gas_price(base_fee),
269            Self::Eip4844(tx) => tx.effective_gas_price(base_fee),
270            Self::Eip7702(tx) => tx.effective_gas_price(base_fee),
271        }
272    }
273
274    #[inline]
275    fn is_dynamic_fee(&self) -> bool {
276        match self {
277            Self::Legacy(tx) => tx.is_dynamic_fee(),
278            Self::Eip2930(tx) => tx.is_dynamic_fee(),
279            Self::Eip1559(tx) => tx.is_dynamic_fee(),
280            Self::Eip4844(tx) => tx.is_dynamic_fee(),
281            Self::Eip7702(tx) => tx.is_dynamic_fee(),
282        }
283    }
284
285    #[inline]
286    fn kind(&self) -> TxKind {
287        match self {
288            Self::Legacy(tx) => tx.kind(),
289            Self::Eip2930(tx) => tx.kind(),
290            Self::Eip1559(tx) => tx.kind(),
291            Self::Eip4844(tx) => tx.kind(),
292            Self::Eip7702(tx) => tx.kind(),
293        }
294    }
295
296    #[inline]
297    fn is_create(&self) -> bool {
298        match self {
299            Self::Legacy(tx) => tx.is_create(),
300            Self::Eip2930(tx) => tx.is_create(),
301            Self::Eip1559(tx) => tx.is_create(),
302            Self::Eip4844(tx) => tx.is_create(),
303            Self::Eip7702(tx) => tx.is_create(),
304        }
305    }
306
307    #[inline]
308    fn value(&self) -> U256 {
309        match self {
310            Self::Legacy(tx) => tx.value(),
311            Self::Eip2930(tx) => tx.value(),
312            Self::Eip1559(tx) => tx.value(),
313            Self::Eip4844(tx) => tx.value(),
314            Self::Eip7702(tx) => tx.value(),
315        }
316    }
317
318    #[inline]
319    fn input(&self) -> &Bytes {
320        match self {
321            Self::Legacy(tx) => tx.input(),
322            Self::Eip2930(tx) => tx.input(),
323            Self::Eip1559(tx) => tx.input(),
324            Self::Eip4844(tx) => tx.input(),
325            Self::Eip7702(tx) => tx.input(),
326        }
327    }
328
329    #[inline]
330    fn access_list(&self) -> Option<&AccessList> {
331        match self {
332            Self::Legacy(tx) => tx.access_list(),
333            Self::Eip2930(tx) => tx.access_list(),
334            Self::Eip1559(tx) => tx.access_list(),
335            Self::Eip4844(tx) => tx.access_list(),
336            Self::Eip7702(tx) => tx.access_list(),
337        }
338    }
339
340    #[inline]
341    fn blob_versioned_hashes(&self) -> Option<&[B256]> {
342        match self {
343            Self::Legacy(tx) => tx.blob_versioned_hashes(),
344            Self::Eip2930(tx) => tx.blob_versioned_hashes(),
345            Self::Eip1559(tx) => tx.blob_versioned_hashes(),
346            Self::Eip4844(tx) => tx.blob_versioned_hashes(),
347            Self::Eip7702(tx) => tx.blob_versioned_hashes(),
348        }
349    }
350
351    #[inline]
352    fn authorization_list(&self) -> Option<&[SignedAuthorization]> {
353        match self {
354            Self::Legacy(tx) => tx.authorization_list(),
355            Self::Eip2930(tx) => tx.authorization_list(),
356            Self::Eip1559(tx) => tx.authorization_list(),
357            Self::Eip4844(tx) => tx.authorization_list(),
358            Self::Eip7702(tx) => tx.authorization_list(),
359        }
360    }
361}
362
363impl<Eip4844: Typed2718> Typed2718 for EthereumTypedTransaction<Eip4844> {
364    fn ty(&self) -> u8 {
365        match self {
366            Self::Legacy(tx) => tx.ty(),
367            Self::Eip2930(tx) => tx.ty(),
368            Self::Eip1559(tx) => tx.ty(),
369            Self::Eip4844(tx) => tx.ty(),
370            Self::Eip7702(tx) => tx.ty(),
371        }
372    }
373}
374
375impl<Eip4844: RlpEcdsaEncodableTx + Typed2718> RlpEcdsaEncodableTx
376    for EthereumTypedTransaction<Eip4844>
377{
378    fn rlp_encoded_fields_length(&self) -> usize {
379        match self {
380            Self::Legacy(tx) => tx.rlp_encoded_fields_length(),
381            Self::Eip2930(tx) => tx.rlp_encoded_fields_length(),
382            Self::Eip1559(tx) => tx.rlp_encoded_fields_length(),
383            Self::Eip4844(tx) => tx.rlp_encoded_fields_length(),
384            Self::Eip7702(tx) => tx.rlp_encoded_fields_length(),
385        }
386    }
387
388    fn rlp_encode_fields(&self, out: &mut dyn alloy_rlp::BufMut) {
389        match self {
390            Self::Legacy(tx) => tx.rlp_encode_fields(out),
391            Self::Eip2930(tx) => tx.rlp_encode_fields(out),
392            Self::Eip1559(tx) => tx.rlp_encode_fields(out),
393            Self::Eip4844(tx) => tx.rlp_encode_fields(out),
394            Self::Eip7702(tx) => tx.rlp_encode_fields(out),
395        }
396    }
397
398    fn eip2718_encode_with_type(&self, signature: &Signature, _ty: u8, out: &mut dyn BufMut) {
399        match self {
400            Self::Legacy(tx) => tx.eip2718_encode_with_type(signature, tx.ty(), out),
401            Self::Eip2930(tx) => tx.eip2718_encode_with_type(signature, tx.ty(), out),
402            Self::Eip1559(tx) => tx.eip2718_encode_with_type(signature, tx.ty(), out),
403            Self::Eip4844(tx) => tx.eip2718_encode_with_type(signature, tx.ty(), out),
404            Self::Eip7702(tx) => tx.eip2718_encode_with_type(signature, tx.ty(), out),
405        }
406    }
407
408    fn eip2718_encode(&self, signature: &Signature, out: &mut dyn BufMut) {
409        match self {
410            Self::Legacy(tx) => tx.eip2718_encode(signature, out),
411            Self::Eip2930(tx) => tx.eip2718_encode(signature, out),
412            Self::Eip1559(tx) => tx.eip2718_encode(signature, out),
413            Self::Eip4844(tx) => tx.eip2718_encode(signature, out),
414            Self::Eip7702(tx) => tx.eip2718_encode(signature, out),
415        }
416    }
417
418    fn network_encode_with_type(&self, signature: &Signature, _ty: u8, out: &mut dyn BufMut) {
419        match self {
420            Self::Legacy(tx) => tx.network_encode_with_type(signature, tx.ty(), out),
421            Self::Eip2930(tx) => tx.network_encode_with_type(signature, tx.ty(), out),
422            Self::Eip1559(tx) => tx.network_encode_with_type(signature, tx.ty(), out),
423            Self::Eip4844(tx) => tx.network_encode_with_type(signature, tx.ty(), out),
424            Self::Eip7702(tx) => tx.network_encode_with_type(signature, tx.ty(), out),
425        }
426    }
427
428    fn network_encode(&self, signature: &Signature, out: &mut dyn BufMut) {
429        match self {
430            Self::Legacy(tx) => tx.network_encode(signature, out),
431            Self::Eip2930(tx) => tx.network_encode(signature, out),
432            Self::Eip1559(tx) => tx.network_encode(signature, out),
433            Self::Eip4844(tx) => tx.network_encode(signature, out),
434            Self::Eip7702(tx) => tx.network_encode(signature, out),
435        }
436    }
437
438    fn tx_hash_with_type(&self, signature: &Signature, _ty: u8) -> TxHash {
439        match self {
440            Self::Legacy(tx) => tx.tx_hash_with_type(signature, tx.ty()),
441            Self::Eip2930(tx) => tx.tx_hash_with_type(signature, tx.ty()),
442            Self::Eip1559(tx) => tx.tx_hash_with_type(signature, tx.ty()),
443            Self::Eip4844(tx) => tx.tx_hash_with_type(signature, tx.ty()),
444            Self::Eip7702(tx) => tx.tx_hash_with_type(signature, tx.ty()),
445        }
446    }
447
448    fn tx_hash(&self, signature: &Signature) -> TxHash {
449        match self {
450            Self::Legacy(tx) => tx.tx_hash(signature),
451            Self::Eip2930(tx) => tx.tx_hash(signature),
452            Self::Eip1559(tx) => tx.tx_hash(signature),
453            Self::Eip4844(tx) => tx.tx_hash(signature),
454            Self::Eip7702(tx) => tx.tx_hash(signature),
455        }
456    }
457}
458
459impl<Eip4844: SignableTransaction<Signature>> SignableTransaction<Signature>
460    for EthereumTypedTransaction<Eip4844>
461{
462    fn set_chain_id(&mut self, chain_id: ChainId) {
463        match self {
464            Self::Legacy(tx) => tx.set_chain_id(chain_id),
465            Self::Eip2930(tx) => tx.set_chain_id(chain_id),
466            Self::Eip1559(tx) => tx.set_chain_id(chain_id),
467            Self::Eip4844(tx) => tx.set_chain_id(chain_id),
468            Self::Eip7702(tx) => tx.set_chain_id(chain_id),
469        }
470    }
471
472    fn encode_for_signing(&self, out: &mut dyn BufMut) {
473        match self {
474            Self::Legacy(tx) => tx.encode_for_signing(out),
475            Self::Eip2930(tx) => tx.encode_for_signing(out),
476            Self::Eip1559(tx) => tx.encode_for_signing(out),
477            Self::Eip4844(tx) => tx.encode_for_signing(out),
478            Self::Eip7702(tx) => tx.encode_for_signing(out),
479        }
480    }
481
482    fn payload_len_for_signature(&self) -> usize {
483        match self {
484            Self::Legacy(tx) => tx.payload_len_for_signature(),
485            Self::Eip2930(tx) => tx.payload_len_for_signature(),
486            Self::Eip1559(tx) => tx.payload_len_for_signature(),
487            Self::Eip4844(tx) => tx.payload_len_for_signature(),
488            Self::Eip7702(tx) => tx.payload_len_for_signature(),
489        }
490    }
491}
492
493#[cfg(feature = "serde")]
494impl<Eip4844, T: From<EthereumTypedTransaction<Eip4844>>> From<EthereumTypedTransaction<Eip4844>>
495    for alloy_serde::WithOtherFields<T>
496{
497    fn from(value: EthereumTypedTransaction<Eip4844>) -> Self {
498        Self::new(value.into())
499    }
500}
501
502#[cfg(feature = "serde")]
503impl<Eip4844, T> From<EthereumTxEnvelope<Eip4844>> for alloy_serde::WithOtherFields<T>
504where
505    T: From<EthereumTxEnvelope<Eip4844>>,
506{
507    fn from(value: EthereumTxEnvelope<Eip4844>) -> Self {
508        Self::new(value.into())
509    }
510}
511
512#[cfg(feature = "serde")]
513mod serde_from {
514    //! NB: Why do we need this?
515    //!
516    //! Because the tag may be missing, we need an abstraction over tagged (with
517    //! type) and untagged (always legacy). This is
518    //! [`MaybeTaggedTypedTransaction`].
519    //!
520    //! The tagged variant is [`TaggedTypedTransaction`], which always has a
521    //! type tag.
522    //!
523    //! We serialize via [`TaggedTypedTransaction`] and deserialize via
524    //! [`MaybeTaggedTypedTransaction`].
525    use crate::{EthereumTypedTransaction, TxEip1559, TxEip2930, TxEip7702, TxLegacy};
526
527    #[derive(Debug, serde::Deserialize)]
528    #[serde(untagged)]
529    pub(crate) enum MaybeTaggedTypedTransaction<Eip4844> {
530        Tagged(TaggedTypedTransaction<Eip4844>),
531        Untagged {
532            #[serde(default, rename = "type", deserialize_with = "alloy_serde::reject_if_some")]
533            _ty: Option<()>,
534            #[serde(flatten)]
535            tx: TxLegacy,
536        },
537    }
538
539    #[derive(Debug, serde::Serialize, serde::Deserialize)]
540    #[serde(tag = "type")]
541    pub(crate) enum TaggedTypedTransaction<Eip4844> {
542        /// Legacy transaction
543        #[serde(rename = "0x00", alias = "0x0")]
544        Legacy(TxLegacy),
545        /// EIP-2930 transaction
546        #[serde(rename = "0x01", alias = "0x1")]
547        Eip2930(TxEip2930),
548        /// EIP-1559 transaction
549        #[serde(rename = "0x02", alias = "0x2")]
550        Eip1559(TxEip1559),
551        /// EIP-4844 transaction
552        #[serde(rename = "0x03", alias = "0x3")]
553        Eip4844(Eip4844),
554        /// EIP-7702 transaction
555        #[serde(rename = "0x04", alias = "0x4")]
556        Eip7702(TxEip7702),
557    }
558
559    impl<Eip4844> From<MaybeTaggedTypedTransaction<Eip4844>> for EthereumTypedTransaction<Eip4844> {
560        fn from(value: MaybeTaggedTypedTransaction<Eip4844>) -> Self {
561            match value {
562                MaybeTaggedTypedTransaction::Tagged(tagged) => tagged.into(),
563                MaybeTaggedTypedTransaction::Untagged { tx, .. } => Self::Legacy(tx),
564            }
565        }
566    }
567
568    impl<Eip4844> From<TaggedTypedTransaction<Eip4844>> for EthereumTypedTransaction<Eip4844> {
569        fn from(value: TaggedTypedTransaction<Eip4844>) -> Self {
570            match value {
571                TaggedTypedTransaction::Legacy(signed) => Self::Legacy(signed),
572                TaggedTypedTransaction::Eip2930(signed) => Self::Eip2930(signed),
573                TaggedTypedTransaction::Eip1559(signed) => Self::Eip1559(signed),
574                TaggedTypedTransaction::Eip4844(signed) => Self::Eip4844(signed),
575                TaggedTypedTransaction::Eip7702(signed) => Self::Eip7702(signed),
576            }
577        }
578    }
579
580    impl<Eip4844> From<EthereumTypedTransaction<Eip4844>> for TaggedTypedTransaction<Eip4844> {
581        fn from(value: EthereumTypedTransaction<Eip4844>) -> Self {
582            match value {
583                EthereumTypedTransaction::Legacy(signed) => Self::Legacy(signed),
584                EthereumTypedTransaction::Eip2930(signed) => Self::Eip2930(signed),
585                EthereumTypedTransaction::Eip1559(signed) => Self::Eip1559(signed),
586                EthereumTypedTransaction::Eip4844(signed) => Self::Eip4844(signed),
587                EthereumTypedTransaction::Eip7702(signed) => Self::Eip7702(signed),
588            }
589        }
590    }
591}