diff --git a/crates/consensus/src/receipt/envelope.rs b/crates/consensus/src/receipt/envelope.rs index 95f9350a66c..202a4beefdc 100644 --- a/crates/consensus/src/receipt/envelope.rs +++ b/crates/consensus/src/receipt/envelope.rs @@ -52,6 +52,31 @@ pub enum ReceiptEnvelope { } impl ReceiptEnvelope { + /// Converts the receipt's log type by applying a function to each log. + /// + /// Returns the receipt with the new log type. + pub fn map_logs(self, f: impl FnMut(T) -> U) -> ReceiptEnvelope { + match self { + Self::Legacy(r) => ReceiptEnvelope::Legacy(r.map_logs(f)), + Self::Eip2930(r) => ReceiptEnvelope::Eip2930(r.map_logs(f)), + Self::Eip1559(r) => ReceiptEnvelope::Eip1559(r.map_logs(f)), + Self::Eip4844(r) => ReceiptEnvelope::Eip4844(r.map_logs(f)), + Self::Eip7702(r) => ReceiptEnvelope::Eip7702(r.map_logs(f)), + } + } + + /// Converts a [`ReceiptEnvelope`] with a custom log type into a [`ReceiptEnvelope`] with the + /// primitives [`Log`] type by converting the logs. + /// + /// This is useful if log types that embed the primitives log type, e.g. the log receipt rpc + /// type. + pub fn into_primitives_receipt(self) -> ReceiptEnvelope + where + T: Into, + { + self.map_logs(Into::into) + } + /// Return the [`TxType`] of the inner receipt. #[doc(alias = "transaction_type")] pub const fn tx_type(&self) -> TxType { diff --git a/crates/consensus/src/receipt/receipts.rs b/crates/consensus/src/receipt/receipts.rs index 850fa5cdf2d..6288843d057 100644 --- a/crates/consensus/src/receipt/receipts.rs +++ b/crates/consensus/src/receipt/receipts.rs @@ -27,6 +27,16 @@ pub struct Receipt { pub logs: Vec, } +impl Receipt { + /// Converts the receipt's log type by applying a function to each log. + /// + /// Returns the receipt with the new log type + pub fn map_logs(self, f: impl FnMut(T) -> U) -> Receipt { + let Self { status, cumulative_gas_used, logs } = self; + Receipt { status, cumulative_gas_used, logs: logs.into_iter().map(f).collect() } + } +} + impl Receipt where T: AsRef, @@ -44,6 +54,20 @@ where } } +impl Receipt +where + T: Into, +{ + /// Converts a [`Receipt`] with a custom log type into a [`Receipt`] with the primitives [`Log`] + /// type by converting the logs. + /// + /// This is useful if log types that embed the primitives log type, e.g. the log receipt rpc + /// type. + pub fn into_primitives_receipt(self) -> Receipt { + self.map_logs(Into::into) + } +} + impl TxReceipt for Receipt where T: AsRef + Clone + fmt::Debug + PartialEq + Eq + Send + Sync, @@ -275,6 +299,14 @@ where } impl ReceiptWithBloom { + /// Converts the receipt type by applying the given closure to it. + /// + /// Returns the type with the new receipt type. + pub fn map_receipt(self, f: impl FnOnce(R) -> U) -> ReceiptWithBloom { + let Self { receipt, logs_bloom } = self; + ReceiptWithBloom { receipt: f(receipt), logs_bloom } + } + /// Create new [ReceiptWithBloom] pub const fn new(receipt: R, logs_bloom: Bloom) -> Self { Self { receipt, logs_bloom } @@ -286,6 +318,28 @@ impl ReceiptWithBloom { } } +impl ReceiptWithBloom> { + /// Converts the receipt's log type by applying a function to each log. + /// + /// Returns the receipt with the new log type. + pub fn map_logs(self, f: impl FnMut(L) -> U) -> ReceiptWithBloom> { + let Self { receipt, logs_bloom } = self; + ReceiptWithBloom { receipt: receipt.map_logs(f), logs_bloom } + } + + /// Converts a [`ReceiptWithBloom`] with a custom log type into a [`ReceiptWithBloom`] with the + /// primitives [`Log`] type by converting the logs. + /// + /// This is useful if log types that embed the primitives log type, e.g. the log receipt rpc + /// type. + pub fn into_primitives_receipt(self) -> ReceiptWithBloom> + where + L: Into, + { + self.map_logs(Into::into) + } +} + impl Encodable for ReceiptWithBloom { fn encode(&self, out: &mut dyn BufMut) { self.receipt.rlp_encode_with_bloom(&self.logs_bloom, out); diff --git a/crates/rpc-types-eth/src/log.rs b/crates/rpc-types-eth/src/log.rs index 93e514b685f..41c24aa2230 100644 --- a/crates/rpc-types-eth/src/log.rs +++ b/crates/rpc-types-eth/src/log.rs @@ -51,6 +51,11 @@ impl Log { pub const fn data(&self) -> &T { &self.inner.data } + + /// Consumes the type and returns the wrapped [`alloy_primitives::Log`] + pub fn into_inner(self) -> alloy_primitives::Log { + self.inner + } } impl Log { @@ -151,6 +156,12 @@ impl AsMut for Log { } } +impl From> for alloy_primitives::Log { + fn from(value: Log) -> Self { + value.into_inner() + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/crates/rpc-types-eth/src/transaction/receipt.rs b/crates/rpc-types-eth/src/transaction/receipt.rs index 61258ae79e3..18537f7ada7 100644 --- a/crates/rpc-types-eth/src/transaction/receipt.rs +++ b/crates/rpc-types-eth/src/transaction/receipt.rs @@ -13,7 +13,7 @@ use alloy_primitives::{Address, BlockHash, TxHash, B256}; #[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))] #[doc(alias = "TxReceipt")] pub struct TransactionReceipt> { - /// The receipt envelope, which contains the consensus receipt data.. + /// The receipt envelope, which contains the consensus receipt data. #[cfg_attr(feature = "serde", serde(flatten))] pub inner: T, /// Transaction Hash. @@ -124,6 +124,32 @@ impl TransactionReceipt { contract_address: self.contract_address, } } + + /// Consumes the type and returns the wrapped receipt. + pub fn into_inner(self) -> T { + self.inner + } +} + +impl TransactionReceipt> { + /// Converts the receipt's log type by applying a function to each log. + /// + /// Returns the receipt with the new log type. + pub fn map_logs(self, f: impl FnMut(L) -> U) -> TransactionReceipt> { + self.map_inner(|inner| inner.map_logs(f)) + } + + /// Converts the transaction receipt's [`ReceiptEnvelope`] with a custom log type into a + /// [`ReceiptEnvelope`] with the primitives [`alloy_primitives::Log`] type by converting the + /// logs. + pub fn into_primitives_receipt( + self, + ) -> TransactionReceipt> + where + L: Into, + { + self.map_logs(Into::into) + } } impl> ReceiptResponse for TransactionReceipt { @@ -184,6 +210,12 @@ impl> ReceiptResponse for TransactionReceipt { } } +impl From for TransactionReceipt> { + fn from(value: TransactionReceipt) -> Self { + value.into_primitives_receipt() + } +} + #[cfg(test)] mod test { use super::*;