eventify_primitives/networks/polygon/
block.rs1use std::{fmt::Debug, hash::Hash};
2
3use alloy_primitives::U256;
4use eyre::Result;
5use redis::AsyncCommands;
6use sqlx::FromRow;
7use utoipa::ToSchema;
8
9use crate::{
10 networks::{core::CoreBlock, NetworkKind, ResourceKind},
11 traits::{Block, Emit, Insert, Stream},
12 PropagateError,
13};
14
15#[derive(
16 Clone,
17 Debug,
18 Default,
19 serde::Deserialize,
20 serde::Serialize,
21 PartialEq,
22 Eq,
23 Hash,
24 FromRow,
25 ToSchema,
26)]
27pub struct PolygonBlock {
28 #[serde(flatten)]
29 core: CoreBlock,
30
31 #[serde(rename = "baseFeePerGas")]
32 pub base_fee: Option<U256>,
33 #[serde(rename = "totalDifficulty")]
34 pub total_difficulty: Option<U256>,
35}
36
37impl Block for PolygonBlock {
38 fn core(&self) -> &CoreBlock {
39 &self.core
40 }
41}
42
43impl Insert for PolygonBlock {
44 async fn insert(
45 &self,
46 pool: &sqlx::PgPool,
47 _: &Option<alloy_primitives::B256>,
48 ) -> Result<(), sqlx::Error> {
49 self.core.insert(pool, NetworkKind::Polygon).await
50 }
51}
52
53impl Emit for PolygonBlock {
54 async fn emit(
55 &self,
56 queue: &redis::Client,
57 network: &NetworkKind,
58 ) -> Result<(), PropagateError> {
59 let mut con = queue.get_async_connection().await?;
60
61 let channel = format!("{}:{}", network, ResourceKind::Block);
62 con.lpush(channel, serde_json::to_string(self)?).await?;
63
64 Ok(())
65 }
66}
67
68impl Stream for PolygonBlock {
69 async fn stream(
70 &self,
71 queue: &redis::Client,
72 network: &NetworkKind,
73 ) -> Result<(), PropagateError> {
74 self.core().stream(queue, network).await
75 }
76}
77
78#[cfg(test)]
79mod tests {
80 use super::*;
81
82 #[test]
83 fn deserialize_polygon_block() {
84 let json = serde_json::json!(
85 {
86 "parentHash": "0x4912fcaf7296fb5bdb46d48e2c0b3cc41cb3aa1850e2a1fbeae6932b455c8d0d",
87 "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
88 "miner": "0x0000000000000000000000000000000000000000",
89 "stateRoot": "0xc935b71945c996e1b01aef1561c07687c4fcec10f93a150da9e33e40a768ffe4",
90 "transactionsRoot": "0x116d6f925a8b3abe7c390ccc7f0fb10b40c4d15d3c28ff3df9816c6c3f91ab4a",
91 "receiptsRoot": "0x4e82db0e69291538acaedc49446154b4fbdf01cf14d97855e5b826f5fd431422",
92 "logsBloom": "0x176f24aae180d2c873b520bebc350e067ac8e17c884185a6bdb6c8ff90a0f9b15210158c6ec791fb461a1b3057157e914845c7ad6b47fc02261a0d9094e62b08295cc9187efb442c56f01c19f1e75affe28194e6bdc6d5b41f47d422823b6e5911771bf75a4a8414537e0c09b7c68ac8534632a32bda762df531d036e04916ebe7fba905a5ac71bc5121ffc53c9380e3d71b37ddab265ece6b5fad4760a40a9d7fd0737655c02e2135a1efbf78f892056fd94c7594d78c87cd889fb21a6a29c9ab8477f3841b6d97e2abeb280f9875dce256e20b539bf41a5f3feb53eacba2c512f58dc829acce8a7b853ddeb082dd6a5fb8c78b91e12a631065d93326b6c99a",
93 "difficulty": "0x16",
94 "number": "0x3412ab0",
95 "gasLimit": "0x1c9c380",
96 "gasUsed": "0xfcf8cb",
97 "timestamp": "0x65f1686f",
98 "extraData": "0xd88301020783626f7289676f312e32302e3134856c696e757800000000000000817c89d9bd2e4714e027a526d7ba90692ffe08dc71fa0831f8f6412f53fa747704a6c45259b8744e88458ea2c839a6c902f944059c0fc0b5610bfea22210874701",
99 "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
100 "nonce": "0x0000000000000000",
101 "baseFeePerGas": "0x112fe5ea31",
102 "withdrawalsRoot": null,
103 "blobGasUsed": null,
104 "excessBlobGas": null,
105 "parentBeaconBlockRoot": null,
106 "hash": "0xf70473275b652c4542cc90e3d6e807679522fc7f8a998d7a4dba6f5420f30463"
107 }
108 );
109
110 assert!(serde_json::from_value::<PolygonBlock>(json.clone()).is_ok());
111 }
112
113 #[test]
114 fn deserialize_empty_polygon_block() {
115 let json = serde_json::json!({});
116
117 assert!(serde_json::from_value::<PolygonBlock>(json).is_err());
118 }
119}