kaspa_notify/
notification.rs1use crate::subscription::context::SubscriptionContext;
2
3use super::{
4 events::EventType,
5 subscription::{
6 single::{OverallSubscription, UtxosChangedSubscription, VirtualChainChangedSubscription},
7 Single,
8 },
9};
10use std::fmt::{Debug, Display};
11
12pub trait Notification: Clone + Debug + Display + Send + Sync + 'static {
14 fn apply_overall_subscription(&self, subscription: &OverallSubscription, context: &SubscriptionContext) -> Option<Self>;
15
16 fn apply_virtual_chain_changed_subscription(
17 &self,
18 subscription: &VirtualChainChangedSubscription,
19 context: &SubscriptionContext,
20 ) -> Option<Self>;
21
22 fn apply_utxos_changed_subscription(&self, subscription: &UtxosChangedSubscription, context: &SubscriptionContext)
23 -> Option<Self>;
24
25 fn apply_subscription(&self, subscription: &dyn Single, context: &SubscriptionContext) -> Option<Self> {
26 match subscription.event_type() {
27 EventType::VirtualChainChanged => self.apply_virtual_chain_changed_subscription(
28 subscription.as_any().downcast_ref::<VirtualChainChangedSubscription>().unwrap(),
29 context,
30 ),
31 EventType::UtxosChanged => self
32 .apply_utxos_changed_subscription(subscription.as_any().downcast_ref::<UtxosChangedSubscription>().unwrap(), context),
33 _ => self.apply_overall_subscription(subscription.as_any().downcast_ref::<OverallSubscription>().unwrap(), context),
34 }
35 }
36
37 fn event_type(&self) -> EventType;
38}
39
40#[macro_export]
41macro_rules! full_featured {
42 ($(#[$meta:meta])* $vis:vis enum $name:ident {
43 $($(#[$variant_meta:meta])* $variant_name:ident($field_name:path),)*
44 }) => {
45 paste::paste! {
46 $(#[$meta])*
47 $vis enum $name {
48 $($(#[$variant_meta])* $variant_name($field_name)),*
49 }
50
51 impl std::convert::From<&$name> for kaspa_notify::events::EventType {
52 fn from(value: &$name) -> Self {
53 match value {
54 $($name::$variant_name(_) => kaspa_notify::events::EventType::$variant_name),*
55 }
56 }
57 }
58
59 impl std::convert::From<&$name> for kaspa_notify::scope::Scope {
60 fn from(value: &$name) -> Self {
61 match value {
62 $($name::$variant_name(_) => kaspa_notify::scope::Scope::$variant_name(kaspa_notify::scope::[<$variant_name Scope>]::default())),*
63 }
64 }
65 }
66
67 impl AsRef<$name> for $name {
68 fn as_ref(&self) -> &Self {
69 self
70 }
71 }
72 }
73 }
74}
75
76pub use full_featured;
77
78pub mod test_helpers {
79 use crate::subscription::{context::SubscriptionContext, Subscription};
80
81 use super::*;
82 use derive_more::Display;
83 use kaspa_addresses::Address;
84 use kaspa_core::trace;
85 use std::sync::Arc;
86
87 #[derive(Clone, Debug, Default, PartialEq, Eq)]
88 pub struct BlockAddedNotification {
89 pub data: u64,
90 }
91
92 #[derive(Clone, Debug, Default, PartialEq, Eq)]
93 pub struct VirtualChainChangedNotification {
94 pub data: u64,
95 pub accepted_transaction_ids: Option<u64>,
96 }
97
98 #[derive(Clone, Debug, Default, PartialEq, Eq)]
99 pub struct UtxosChangedNotification {
100 pub data: u64,
101 pub addresses: Arc<Vec<Address>>,
102 }
103
104 full_featured! {
105 #[derive(Clone, Debug, Display, PartialEq, Eq)]
106 pub enum TestNotification {
107 #[display(fmt = "BlockAdded #{}", "_0.data")]
108 BlockAdded(BlockAddedNotification),
109 #[display(fmt = "VirtualChainChanged #{}", "_0.data")]
110 VirtualChainChanged(VirtualChainChangedNotification),
111 #[display(fmt = "UtxosChanged #{}", "_0.data")]
112 UtxosChanged(UtxosChangedNotification),
113 }
114 }
115
116 impl Notification for TestNotification {
117 fn apply_overall_subscription(&self, subscription: &OverallSubscription, _: &SubscriptionContext) -> Option<Self> {
118 trace!("apply_overall_subscription: {self:?}, {subscription:?}");
119 match subscription.active() {
120 true => Some(self.clone()),
121 false => None,
122 }
123 }
124
125 fn apply_virtual_chain_changed_subscription(
126 &self,
127 subscription: &VirtualChainChangedSubscription,
128 _: &SubscriptionContext,
129 ) -> Option<Self> {
130 match subscription.active() {
131 true => {
132 if let TestNotification::VirtualChainChanged(ref payload) = self {
133 if !subscription.include_accepted_transaction_ids() && payload.accepted_transaction_ids.is_some() {
134 return Some(TestNotification::VirtualChainChanged(VirtualChainChangedNotification {
135 data: payload.data,
136 accepted_transaction_ids: None,
137 }));
138 }
139 }
140 Some(self.clone())
141 }
142 false => None,
143 }
144 }
145
146 fn apply_utxos_changed_subscription(
147 &self,
148 subscription: &UtxosChangedSubscription,
149 context: &SubscriptionContext,
150 ) -> Option<Self> {
151 match subscription.active() {
152 true => {
153 if let TestNotification::UtxosChanged(ref payload) = self {
154 let subscription = subscription.data();
155 if !subscription.to_all() {
156 let addresses = payload
160 .addresses
161 .iter()
162 .filter(|x| subscription.contains_address(x, context))
163 .cloned()
164 .collect::<Vec<_>>();
165 if !addresses.is_empty() {
166 return Some(TestNotification::UtxosChanged(UtxosChangedNotification {
167 data: payload.data,
168 addresses: Arc::new(addresses),
169 }));
170 } else {
171 return None;
172 }
173 }
174 }
175 Some(self.clone())
176 }
177 false => None,
178 }
179 }
180
181 fn event_type(&self) -> EventType {
182 self.into()
183 }
184 }
185
186 pub trait Data {
188 fn data(&self) -> u64;
189 fn data_mut(&mut self) -> &mut u64;
190 }
191 impl Data for BlockAddedNotification {
192 fn data(&self) -> u64 {
193 self.data
194 }
195
196 fn data_mut(&mut self) -> &mut u64 {
197 &mut self.data
198 }
199 }
200 impl Data for VirtualChainChangedNotification {
201 fn data(&self) -> u64 {
202 self.data
203 }
204
205 fn data_mut(&mut self) -> &mut u64 {
206 &mut self.data
207 }
208 }
209 impl Data for UtxosChangedNotification {
210 fn data(&self) -> u64 {
211 self.data
212 }
213
214 fn data_mut(&mut self) -> &mut u64 {
215 &mut self.data
216 }
217 }
218 impl Data for TestNotification {
219 fn data(&self) -> u64 {
220 match self {
221 TestNotification::BlockAdded(n) => n.data(),
222 TestNotification::VirtualChainChanged(n) => n.data(),
223 TestNotification::UtxosChanged(n) => n.data(),
224 }
225 }
226
227 fn data_mut(&mut self) -> &mut u64 {
228 match self {
229 TestNotification::BlockAdded(n) => n.data_mut(),
230 TestNotification::VirtualChainChanged(n) => n.data_mut(),
231 TestNotification::UtxosChanged(n) => n.data_mut(),
232 }
233 }
234 }
235}