stratus/eth/primitives/
log_mined.rs1use display_json::DebugAsJson;
2use jsonrpsee::SubscriptionMessage;
3
4use super::TransactionExecution;
5use crate::alias::AlloyLog;
6use crate::alias::AlloyLogData;
7use crate::alias::AlloyLogPrimitive;
8use crate::alias::JsonValue;
9use crate::eth::primitives::Address;
10use crate::eth::primitives::BlockNumber;
11use crate::eth::primitives::Hash;
12use crate::eth::primitives::Index;
13use crate::eth::primitives::Log;
14use crate::eth::primitives::LogTopic;
15use crate::ext::to_json_value;
16
17#[derive(DebugAsJson, Clone, PartialEq, Eq, fake::Dummy, serde::Serialize, serde::Deserialize)]
19pub struct LogMined {
20 pub log: Log,
22
23 pub transaction_hash: Hash,
25
26 pub transaction_index: Index,
28
29 pub log_index: Index,
31
32 pub block_number: BlockNumber,
34
35 pub block_hash: Hash,
37}
38
39impl LogMined {
40 pub fn address(&self) -> Address {
42 self.log.address
43 }
44
45 pub fn topics_non_empty(&self) -> Vec<LogTopic> {
47 self.log.topics_non_empty()
48 }
49
50 pub fn to_json_rpc_log(self) -> JsonValue {
52 let alloy_log: AlloyLog = self.into();
53 to_json_value(alloy_log)
54 }
55
56 pub fn mine_log(
57 mined_log: Log,
58 block_number: BlockNumber,
59 block_hash: Hash,
60 tx: &TransactionExecution,
61 log_index: Index,
62 transaction_index: Index,
63 ) -> Self {
64 LogMined {
65 log: mined_log,
66 transaction_hash: tx.input.hash,
67 transaction_index,
68 log_index,
69 block_number,
70 block_hash,
71 }
72 }
73}
74
75impl TryFrom<AlloyLog> for LogMined {
79 type Error = anyhow::Error;
80 fn try_from(value: AlloyLog) -> Result<Self, Self::Error> {
81 let transaction_hash = value
82 .transaction_hash
83 .ok_or_else(|| anyhow::anyhow!("log must have transaction_hash"))
84 .map(|bytes| Hash::from(bytes.0))?;
85 let transaction_index = Index::from(value.transaction_index.ok_or_else(|| anyhow::anyhow!("log must have transaction_index"))?);
86 let log_index = Index::from(value.log_index.ok_or_else(|| anyhow::anyhow!("log must have log_index"))?);
87 let block_number = BlockNumber::from(value.block_number.ok_or_else(|| anyhow::anyhow!("log must have block_number"))?);
88 let block_hash = value
89 .block_hash
90 .ok_or_else(|| anyhow::anyhow!("log must have block_hash"))
91 .map(|bytes| Hash::from(bytes.0))?;
92
93 Ok(Self {
94 transaction_hash,
95 transaction_index,
96 log_index,
97 block_number,
98 block_hash,
99 log: value.into(),
100 })
101 }
102}
103
104impl From<LogMined> for AlloyLog {
108 fn from(value: LogMined) -> Self {
109 Self {
110 inner: AlloyLogPrimitive {
111 address: value.log.address.into(),
112 data: AlloyLogData::new_unchecked(value.topics_non_empty().into_iter().map(Into::into).collect(), value.log.data.into()),
114 },
115 block_hash: Some(value.block_hash.into()),
116 block_number: Some(value.block_number.as_u64()),
117 block_timestamp: None,
118 transaction_hash: Some(value.transaction_hash.into()),
119 transaction_index: Some(value.transaction_index.into()),
120 log_index: Some(value.log_index.into()),
121 removed: false,
122 }
123 }
124}
125
126impl TryFrom<LogMined> for SubscriptionMessage {
127 type Error = serde_json::Error;
128
129 fn try_from(value: LogMined) -> Result<Self, Self::Error> {
130 Ok(serde_json::value::RawValue::from_string(serde_json::to_string(&Into::<AlloyLog>::into(value))?)?.into())
131 }
132}