Skip to main content

nectar_postage/
events.rs

1//! Batch event types for monitoring blockchain events.
2//!
3//! This module provides types for handling postage batch events from the blockchain.
4//! Any node that maintains a batch store (for stamp validation) needs to handle
5//! these events to keep their batch state synchronized with on-chain state.
6
7use crate::{Batch, BatchId};
8
9/// Events emitted by the postage stamp contract.
10///
11/// These events represent state changes to batches on-chain.
12#[derive(Debug, Clone, PartialEq, Eq)]
13pub enum BatchEvent {
14    /// A new batch was created.
15    Created {
16        /// The batch that was created.
17        batch: Batch,
18    },
19
20    /// A batch was topped up with additional funds.
21    TopUp {
22        /// The batch ID.
23        batch_id: BatchId,
24        /// The new normalized balance.
25        new_value: u128,
26    },
27
28    /// A batch was diluted (depth increased).
29    DepthIncrease {
30        /// The batch ID.
31        batch_id: BatchId,
32        /// The new depth.
33        new_depth: u8,
34    },
35
36    /// A batch expired.
37    Expired {
38        /// The batch ID.
39        batch_id: BatchId,
40    },
41}
42
43impl BatchEvent {
44    /// Returns the batch ID associated with this event.
45    pub const fn batch_id(&self) -> BatchId {
46        match self {
47            Self::Created { batch } => batch.id(),
48            Self::TopUp { batch_id, .. } => *batch_id,
49            Self::DepthIncrease { batch_id, .. } => *batch_id,
50            Self::Expired { batch_id } => *batch_id,
51        }
52    }
53}
54
55/// A handler for batch events.
56///
57/// Implementations receive events as they are processed from the blockchain
58/// and update internal state accordingly.
59pub trait BatchEventHandler {
60    /// The error type returned when handling fails.
61    type Error;
62
63    /// Handles a batch event.
64    ///
65    /// Implementations should update any internal state (e.g., batch store)
66    /// based on the event.
67    fn handle_event(&mut self, event: BatchEvent) -> Result<(), Self::Error>;
68
69    /// Handles a batch of events atomically.
70    ///
71    /// The default implementation calls `handle_event` for each event,
72    /// but implementations may override this for better performance
73    /// or transactional semantics.
74    fn handle_events(&mut self, events: Vec<BatchEvent>) -> Result<(), Self::Error> {
75        for event in events {
76            self.handle_event(event)?;
77        }
78        Ok(())
79    }
80}
81
82#[cfg(test)]
83mod tests {
84    use super::*;
85    use alloy_primitives::{Address, B256};
86
87    #[test]
88    fn test_batch_event_batch_id() {
89        let batch = Batch::new(
90            B256::repeat_byte(1),
91            1000,
92            100,
93            Address::ZERO,
94            20,
95            16,
96            false,
97        );
98        let batch_id = batch.id();
99
100        let created = BatchEvent::Created { batch };
101        assert_eq!(created.batch_id(), batch_id);
102
103        let topup = BatchEvent::TopUp {
104            batch_id,
105            new_value: 2000,
106        };
107        assert_eq!(topup.batch_id(), batch_id);
108
109        let depth = BatchEvent::DepthIncrease {
110            batch_id,
111            new_depth: 21,
112        };
113        assert_eq!(depth.batch_id(), batch_id);
114
115        let expired = BatchEvent::Expired { batch_id };
116        assert_eq!(expired.batch_id(), batch_id);
117    }
118}