blueprint_evm_extra/extract/
block.rs1use alloy_primitives::B256;
6use blueprint_core::{
7 __composite_rejection as composite_rejection, __define_rejection as define_rejection,
8 __impl_deref as impl_deref, FromJobCallParts, job::call::Parts as JobCallParts,
9};
10
11#[derive(Debug, Clone, Copy)]
13pub struct BlockNumber(pub u64);
14
15impl BlockNumber {
16 pub const METADATA_KEY: &'static str = "X-EVM-BLOCK-NUMBER";
18}
19
20impl_deref!(BlockNumber: u64);
21
22define_rejection! {
23 #[body = "No block found in metadata"]
24 pub struct MissingBlock;
26}
27
28define_rejection! {
29 #[body = "Block number must be a valid number"]
30 pub struct InvalidBlockNumber;
32}
33
34define_rejection! {
35 #[body = "Block number must be a valid block hash"]
36 pub struct InvalidBlockHash;
38}
39
40composite_rejection! {
41 pub enum BlockNumberRejection {
43 MissingBlock,
44 InvalidBlockNumber,
45 }
46}
47
48impl TryFrom<&mut JobCallParts> for BlockNumber {
49 type Error = BlockNumberRejection;
50
51 fn try_from(parts: &mut JobCallParts) -> Result<Self, Self::Error> {
52 let block_number = parts
53 .metadata
54 .get(Self::METADATA_KEY)
55 .ok_or(MissingBlock)?
56 .try_into()
57 .map_err(|_| InvalidBlockNumber)?;
58 Ok(BlockNumber(block_number))
59 }
60}
61
62impl<Ctx> FromJobCallParts<Ctx> for BlockNumber
63where
64 Ctx: Send + Sync,
65{
66 type Rejection = BlockNumberRejection;
67
68 async fn from_job_call_parts(
69 parts: &mut JobCallParts,
70 _: &Ctx,
71 ) -> Result<Self, Self::Rejection> {
72 Self::try_from(parts)
73 }
74}
75
76composite_rejection! {
77 pub enum BlockHashRejection {
79 MissingBlock,
80 InvalidBlockHash,
81 }
82}
83
84#[derive(Debug, Clone, Copy)]
86pub struct BlockHash(pub B256);
87
88impl BlockHash {
89 pub const METADATA_KEY: &'static str = "X-EVM-BLOCK-HASH";
91}
92
93impl_deref!(BlockHash: B256);
94
95impl TryFrom<&mut JobCallParts> for BlockHash {
96 type Error = BlockHashRejection;
97
98 fn try_from(parts: &mut JobCallParts) -> Result<Self, Self::Error> {
99 let block_hash = parts
100 .metadata
101 .get(Self::METADATA_KEY)
102 .ok_or(MissingBlock)?
103 .as_bytes();
104
105 let hash = B256::try_from(block_hash).map_err(|_| InvalidBlockHash)?;
106 Ok(BlockHash(hash))
107 }
108}
109
110impl<Ctx> FromJobCallParts<Ctx> for BlockHash
111where
112 Ctx: Send + Sync,
113{
114 type Rejection = BlockHashRejection;
115
116 async fn from_job_call_parts(
117 parts: &mut JobCallParts,
118 _: &Ctx,
119 ) -> Result<Self, Self::Rejection> {
120 Self::try_from(parts)
121 }
122}
123
124#[derive(Debug, Clone, Copy)]
126pub struct BlockTimestamp(pub u64);
127
128impl BlockTimestamp {
129 pub const METADATA_KEY: &'static str = "X-EVM-BLOCK-TIMESTAMP";
131}
132
133impl_deref!(BlockTimestamp: u64);
134
135define_rejection! {
136 #[body = "Block timestamp must be a valid block timestamp"]
137 pub struct InvalidBlockTimestamp;
139}
140
141composite_rejection! {
142 pub enum BlockTimestampRejection {
144 MissingBlock,
145 InvalidBlockTimestamp,
146 }
147}
148
149impl TryFrom<&mut JobCallParts> for BlockTimestamp {
150 type Error = BlockTimestampRejection;
151
152 fn try_from(parts: &mut JobCallParts) -> Result<Self, Self::Error> {
153 let timestamp = parts
154 .metadata
155 .get(Self::METADATA_KEY)
156 .ok_or(MissingBlock)?
157 .try_into()
158 .map_err(|_| InvalidBlockTimestamp)?;
159 Ok(BlockTimestamp(timestamp))
160 }
161}
162
163impl<Ctx> FromJobCallParts<Ctx> for BlockTimestamp
164where
165 Ctx: Send + Sync,
166{
167 type Rejection = BlockTimestampRejection;
168
169 async fn from_job_call_parts(
170 parts: &mut JobCallParts,
171 _: &Ctx,
172 ) -> Result<Self, Self::Rejection> {
173 Self::try_from(parts)
174 }
175}