blueprint_tangle_extra/extract/
block_hash.rs

1use blueprint_core::{
2    __composite_rejection as composite_rejection, __define_rejection as define_rejection,
3};
4use blueprint_core::{FromJobCallParts, job::call::Parts as JobCallParts};
5use tangle_subxt::subxt::utils::H256;
6
7/// Extracts the current block hash from the job call.
8#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
9pub struct BlockHash(pub H256);
10
11impl BlockHash {
12    pub const METADATA_KEY: &'static str = "X-TANGLE-BLOCK-HASH";
13}
14
15blueprint_core::__impl_deref!(BlockHash: H256);
16blueprint_core::__impl_from!(H256, BlockHash);
17
18define_rejection! {
19  #[body = "No BlockHash found in the metadata"]
20  /// A Rejection type for [`BlockHash`] when it is missing from the Metadata.
21  pub struct MissingBlockHash;
22}
23
24define_rejection! {
25  #[body = "The block hash in the metadata is not a valid 32 bytes"]
26  /// A Rejection type for [`BlockHash`] when it is not a valid 32 bytes.
27  pub struct InvalidBlockHash;
28}
29
30composite_rejection! {
31    /// Rejection used for [`BlockHash`].
32    ///
33    /// Contains one variant for each way the [`BlockHash`] extractor
34    /// can fail.
35    pub enum BlockHashRejection {
36        MissingBlockHash,
37        InvalidBlockHash,
38    }
39}
40
41impl TryFrom<&mut JobCallParts> for BlockHash {
42    type Error = BlockHashRejection;
43
44    fn try_from(parts: &mut JobCallParts) -> Result<Self, Self::Error> {
45        let block_hash_raw = parts
46            .metadata
47            .get(Self::METADATA_KEY)
48            .ok_or(MissingBlockHash)?;
49        let block_hash = block_hash_raw.as_bytes();
50        if block_hash.len() != 32 {
51            return Err(InvalidBlockHash.into());
52        }
53        Ok(BlockHash(H256::from_slice(block_hash)))
54    }
55}
56
57impl<Ctx> FromJobCallParts<Ctx> for BlockHash
58where
59    Ctx: Send + Sync,
60{
61    type Rejection = BlockHashRejection;
62
63    async fn from_job_call_parts(
64        parts: &mut JobCallParts,
65        _: &Ctx,
66    ) -> Result<Self, Self::Rejection> {
67        Self::try_from(parts)
68    }
69}