1use crate::model::message::*;
6use derive_more::Display;
7use kaspa_notify::{
8 events::EventType,
9 notification::{full_featured, Notification as NotificationTrait},
10 subscription::{
11 context::SubscriptionContext,
12 single::{OverallSubscription, UtxosChangedSubscription, VirtualChainChangedSubscription},
13 Subscription,
14 },
15};
16use serde::{Deserialize, Serialize};
17use std::sync::Arc;
18use wasm_bindgen::JsValue;
19use workflow_serializer::prelude::*;
20use workflow_wasm::serde::to_value;
21
22full_featured! {
23#[derive(Clone, Debug, Display, Serialize, Deserialize)]
24pub enum Notification {
25 #[display(fmt = "BlockAdded notification: block hash {}", "_0.block.header.hash")]
26 BlockAdded(BlockAddedNotification),
27
28 #[display(fmt = "VirtualChainChanged notification: {} removed blocks, {} added blocks, {} accepted transactions", "_0.removed_chain_block_hashes.len()", "_0.added_chain_block_hashes.len()", "_0.accepted_transaction_ids.len()")]
29 VirtualChainChanged(VirtualChainChangedNotification),
30
31 #[display(fmt = "FinalityConflict notification: violating block hash {}", "_0.violating_block_hash")]
32 FinalityConflict(FinalityConflictNotification),
33
34 #[display(fmt = "FinalityConflict notification: violating block hash {}", "_0.finality_block_hash")]
35 FinalityConflictResolved(FinalityConflictResolvedNotification),
36
37 #[display(fmt = "UtxosChanged notification: {} removed, {} added", "_0.removed.len()", "_0.added.len()")]
38 UtxosChanged(UtxosChangedNotification),
39
40 #[display(fmt = "SinkBlueScoreChanged notification: virtual selected parent blue score {}", "_0.sink_blue_score")]
41 SinkBlueScoreChanged(SinkBlueScoreChangedNotification),
42
43 #[display(fmt = "VirtualDaaScoreChanged notification: virtual DAA score {}", "_0.virtual_daa_score")]
44 VirtualDaaScoreChanged(VirtualDaaScoreChangedNotification),
45
46 #[display(fmt = "PruningPointUtxoSetOverride notification")]
47 PruningPointUtxoSetOverride(PruningPointUtxoSetOverrideNotification),
48
49 #[display(fmt = "NewBlockTemplate notification")]
50 NewBlockTemplate(NewBlockTemplateNotification),
51}
52}
53
54impl Notification {
55 pub fn to_value(&self) -> std::result::Result<JsValue, serde_wasm_bindgen::Error> {
57 match self {
58 Notification::BlockAdded(v) => to_value(&v),
59 Notification::FinalityConflict(v) => to_value(&v),
60 Notification::FinalityConflictResolved(v) => to_value(&v),
61 Notification::NewBlockTemplate(v) => to_value(&v),
62 Notification::PruningPointUtxoSetOverride(v) => to_value(&v),
63 Notification::UtxosChanged(v) => to_value(&v),
64 Notification::VirtualDaaScoreChanged(v) => to_value(&v),
65 Notification::SinkBlueScoreChanged(v) => to_value(&v),
66 Notification::VirtualChainChanged(v) => to_value(&v),
67 }
68 }
69}
70
71impl NotificationTrait for Notification {
72 fn apply_overall_subscription(&self, subscription: &OverallSubscription, _context: &SubscriptionContext) -> Option<Self> {
73 match subscription.active() {
74 true => Some(self.clone()),
75 false => None,
76 }
77 }
78
79 fn apply_virtual_chain_changed_subscription(
80 &self,
81 subscription: &VirtualChainChangedSubscription,
82 _context: &SubscriptionContext,
83 ) -> Option<Self> {
84 match subscription.active() {
85 true => {
86 if let Notification::VirtualChainChanged(ref payload) = self {
87 if !subscription.include_accepted_transaction_ids() && !payload.accepted_transaction_ids.is_empty() {
88 return Some(Notification::VirtualChainChanged(VirtualChainChangedNotification {
89 removed_chain_block_hashes: payload.removed_chain_block_hashes.clone(),
90 added_chain_block_hashes: payload.added_chain_block_hashes.clone(),
91 accepted_transaction_ids: Arc::new(vec![]),
92 }));
93 }
94 }
95 Some(self.clone())
96 }
97 false => None,
98 }
99 }
100
101 fn apply_utxos_changed_subscription(
102 &self,
103 subscription: &UtxosChangedSubscription,
104 context: &SubscriptionContext,
105 ) -> Option<Self> {
106 match subscription.active() {
107 true => {
108 let Self::UtxosChanged(notification) = self else { return None };
109 notification.apply_utxos_changed_subscription(subscription, context).map(Self::UtxosChanged)
110 }
111 false => None,
112 }
113 }
114
115 fn event_type(&self) -> EventType {
116 self.into()
117 }
118}
119
120impl Serializer for Notification {
121 fn serialize<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> {
122 store!(u16, &1, writer)?;
123 match self {
124 Notification::BlockAdded(notification) => {
125 store!(u16, &0, writer)?;
126 serialize!(BlockAddedNotification, notification, writer)?;
127 }
128 Notification::VirtualChainChanged(notification) => {
129 store!(u16, &1, writer)?;
130 serialize!(VirtualChainChangedNotification, notification, writer)?;
131 }
132 Notification::FinalityConflict(notification) => {
133 store!(u16, &2, writer)?;
134 serialize!(FinalityConflictNotification, notification, writer)?;
135 }
136 Notification::FinalityConflictResolved(notification) => {
137 store!(u16, &3, writer)?;
138 serialize!(FinalityConflictResolvedNotification, notification, writer)?;
139 }
140 Notification::UtxosChanged(notification) => {
141 store!(u16, &4, writer)?;
142 serialize!(UtxosChangedNotification, notification, writer)?;
143 }
144 Notification::SinkBlueScoreChanged(notification) => {
145 store!(u16, &5, writer)?;
146 serialize!(SinkBlueScoreChangedNotification, notification, writer)?;
147 }
148 Notification::VirtualDaaScoreChanged(notification) => {
149 store!(u16, &6, writer)?;
150 serialize!(VirtualDaaScoreChangedNotification, notification, writer)?;
151 }
152 Notification::PruningPointUtxoSetOverride(notification) => {
153 store!(u16, &7, writer)?;
154 serialize!(PruningPointUtxoSetOverrideNotification, notification, writer)?;
155 }
156 Notification::NewBlockTemplate(notification) => {
157 store!(u16, &8, writer)?;
158 serialize!(NewBlockTemplateNotification, notification, writer)?;
159 }
160 }
161 Ok(())
162 }
163}
164
165impl Deserializer for Notification {
166 fn deserialize<R: std::io::Read>(reader: &mut R) -> std::io::Result<Self> {
167 let _version = load!(u16, reader)?;
168 match load!(u16, reader)? {
169 0 => {
170 let notification = deserialize!(BlockAddedNotification, reader)?;
171 Ok(Notification::BlockAdded(notification))
172 }
173 1 => {
174 let notification = deserialize!(VirtualChainChangedNotification, reader)?;
175 Ok(Notification::VirtualChainChanged(notification))
176 }
177 2 => {
178 let notification = deserialize!(FinalityConflictNotification, reader)?;
179 Ok(Notification::FinalityConflict(notification))
180 }
181 3 => {
182 let notification = deserialize!(FinalityConflictResolvedNotification, reader)?;
183 Ok(Notification::FinalityConflictResolved(notification))
184 }
185 4 => {
186 let notification = deserialize!(UtxosChangedNotification, reader)?;
187 Ok(Notification::UtxosChanged(notification))
188 }
189 5 => {
190 let notification = deserialize!(SinkBlueScoreChangedNotification, reader)?;
191 Ok(Notification::SinkBlueScoreChanged(notification))
192 }
193 6 => {
194 let notification = deserialize!(VirtualDaaScoreChangedNotification, reader)?;
195 Ok(Notification::VirtualDaaScoreChanged(notification))
196 }
197 7 => {
198 let notification = deserialize!(PruningPointUtxoSetOverrideNotification, reader)?;
199 Ok(Notification::PruningPointUtxoSetOverride(notification))
200 }
201 8 => {
202 let notification = deserialize!(NewBlockTemplateNotification, reader)?;
203 Ok(Notification::NewBlockTemplate(notification))
204 }
205 _ => Err(std::io::Error::new(std::io::ErrorKind::InvalidData, "Invalid variant")),
206 }
207 }
208}