-
Notifications
You must be signed in to change notification settings - Fork 100
Expand file tree
/
Copy pathevents.rs
More file actions
614 lines (567 loc) · 18.4 KB
/
Copy pathevents.rs
File metadata and controls
614 lines (567 loc) · 18.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
use soroban_sdk::{contractevent, contracttype, Address, BytesN, String, Vec};
/// High-level notification category attached to every emitted event.
///
/// Off-chain consumers (listeners, indexers, dashboards) often only care about a
/// subset of the events the contract emits. Each event carries its category as a
/// trailing, indexed event topic so consumers can subscribe to or filter out
/// whole categories without having to decode the event payload first.
///
/// # Backward compatibility
///
/// The category is published as the *last* topic of every event, after the event
/// name and any pre-existing topics. Existing listeners that read the event name
/// (the first topic) and the previously defined topics/data are unaffected: the
/// extra trailing topic is simply ignored by consumers that don't look for it.
#[contracttype]
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub enum NotificationCategory {
/// Lifecycle changes to AutoShare groups: created, updated, activated,
/// deactivated.
Group = 0,
/// Administrative / system actions: pause, unpause, admin transfer.
Admin = 1,
/// Movement of funds: withdrawals.
Financial = 2,
/// Scheduled notification operations: scheduling, expiry, cancellation.
Notification = 3,
/// System testing category
System = 4,
}
/// Severity level attached to every emitted event alongside its category.
///
/// Off-chain consumers (alerting, dashboards, paging) often route notifications
/// by priority rather than (or in addition to) category. Each event carries its
/// priority as a trailing, indexed event topic so consumers can subscribe to
/// or page on high-priority notifications without decoding the payload.
///
/// # Backward compatibility
///
/// The priority is published as the *last* topic of every event, after the
/// event name, the previously defined topics, and the category. Existing
/// listeners that only read the event name (the first topic), the prior topics,
/// or the category will continue to work unchanged: the extra trailing topic is
/// simply ignored by consumers that don't look for it.
#[contracttype]
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub enum NotificationPriority {
/// Informational: routine lifecycle events. No action required.
Low = 0,
/// Standard: day-to-day operational events worth tracking.
Medium = 1,
/// Elevated: events the operator should review promptly.
High = 2,
/// Urgent: security-relevant or funds-moving events that demand
/// immediate attention (e.g. admin transfer, authorization failure).
Critical = 3,
}
// ============================================================================
// Group lifecycle events
// ============================================================================
/// Emitted when a new AutoShare group is created.
#[contractevent(data_format = "single-value")]
#[derive(Clone)]
pub struct AutoshareCreated {
#[topic]
pub creator: Address,
#[topic]
pub category: NotificationCategory,
#[topic]
pub priority: NotificationPriority,
pub id: BytesN<32>,
}
/// Emitted when an AutoShare group's member list is updated.
#[contractevent(data_format = "single-value")]
#[derive(Clone)]
pub struct AutoshareUpdated {
#[topic]
pub updater: Address,
#[topic]
pub category: NotificationCategory,
#[topic]
pub priority: NotificationPriority,
pub id: BytesN<32>,
}
/// Emitted when an AutoShare group is deactivated by its creator.
#[contractevent(data_format = "single-value")]
#[derive(Clone)]
pub struct GroupDeactivated {
#[topic]
pub creator: Address,
#[topic]
pub category: NotificationCategory,
#[topic]
pub priority: NotificationPriority,
pub id: BytesN<32>,
}
/// Emitted when a deactivated AutoShare group is reactivated by its creator.
#[contractevent(data_format = "single-value")]
#[derive(Clone)]
pub struct GroupActivated {
#[topic]
pub creator: Address,
#[topic]
pub category: NotificationCategory,
#[topic]
pub priority: NotificationPriority,
pub id: BytesN<32>,
}
// ============================================================================
// Admin / system events
// ============================================================================
/// Emitted when a notification category is registered on-chain.
#[contractevent]
#[derive(Clone)]
pub struct CategoryRegistered {
#[topic]
pub admin: Address,
#[topic]
pub category: NotificationCategory,
#[topic]
pub priority: NotificationPriority,
}
/// Emitted when a recipient updates a delivery channel preference.
///
/// Off-chain consumers can filter on `recipient` and inspect `channel` /
/// `enabled` in the event data to react to channel configuration changes
/// without decoding full preference storage.
#[contractevent]
#[derive(Clone)]
pub struct ChannelPreferenceUpdated {
#[topic]
pub recipient: Address,
#[topic]
pub category: NotificationCategory,
#[topic]
pub priority: NotificationPriority,
/// Delivery channel that changed (0 = Wallet, 1 = Email, 2 = InApp).
pub channel: u32,
/// Whether the channel is now enabled.
pub enabled: bool,
/// Ledger timestamp when the preference was updated.
pub updated_at: u64,
}
/// Emitted when an AutoShare group is deactivated by its creator.
#[contractevent(data_format = "single-value")]
#[derive(Clone)]
pub struct ContractPaused {
#[topic]
pub admin: Address,
#[topic]
pub category: NotificationCategory,
#[topic]
pub priority: NotificationPriority,
}
/// Emitted when the contract is unpaused by the admin.
#[contractevent]
#[derive(Clone)]
pub struct ContractUnpaused {
#[topic]
pub admin: Address,
#[topic]
pub category: NotificationCategory,
#[topic]
pub priority: NotificationPriority,
}
/// Emitted when the admin rights of the contract are transferred.
#[contractevent(data_format = "single-value")]
#[derive(Clone)]
pub struct AdminTransferred {
#[topic]
pub old_admin: Address,
#[topic]
pub category: NotificationCategory,
#[topic]
pub priority: NotificationPriority,
pub new_admin: Address,
}
/// Emitted when an authorization failure is detected by the contract.
#[contractevent(data_format = "single-value")]
#[derive(Clone)]
pub struct AuthorizationFailure {
#[topic]
pub caller: Address,
#[topic]
pub category: NotificationCategory,
#[topic]
pub priority: NotificationPriority,
pub action: String,
}
// ============================================================================
// Financial events
// ============================================================================
/// Emitted when the admin withdraws collected usage fees from the contract.
#[contractevent(data_format = "single-value")]
#[derive(Clone)]
pub struct Withdrawal {
#[topic]
pub token: Address,
#[topic]
pub recipient: Address,
#[topic]
pub category: NotificationCategory,
#[topic]
pub priority: NotificationPriority,
pub amount: i128,
}
// ============================================================================
// Notification lifecycle events
// ============================================================================
/// Emitted when a notification is scheduled on-chain with a bounded lifetime.
#[contractevent(data_format = "single-value")]
#[derive(Clone)]
pub struct NotificationScheduled {
#[topic]
pub creator: Address,
#[topic]
pub category: NotificationCategory,
#[topic]
pub priority: NotificationPriority,
pub notification_id: BytesN<32>,
}
/// Emitted when a scheduled notification's lifetime elapses and it is expired.
#[contractevent(data_format = "single-value")]
#[derive(Clone)]
pub struct NotificationExpired {
#[topic]
pub notification_id: BytesN<32>,
#[topic]
pub category: NotificationCategory,
#[topic]
pub priority: NotificationPriority,
pub expires_at: u64,
}
/// Emitted when a scheduled notification is cancelled.
#[contractevent(data_format = "single-value")]
#[derive(Clone)]
pub struct ScheduledNotificationCancelled {
#[topic]
pub caller: Address,
#[topic]
pub category: NotificationCategory,
#[topic]
pub priority: NotificationPriority,
pub notification_id: BytesN<32>,
}
/// Emitted when a notification is confirmed as delivered to its intended recipient.
#[contractevent(data_format = "single-value")]
#[derive(Clone)]
pub struct NotificationDelivered {
#[topic]
pub notification_id: BytesN<32>,
#[topic]
pub delivered_by: Address,
#[topic]
pub category: NotificationCategory,
#[topic]
pub priority: NotificationPriority,
pub delivered_at: u64,
}
/// Emitted when a sender recalls a scheduled notification before delivery confirmation.
#[contractevent(data_format = "single-value")]
#[derive(Clone)]
pub struct NotificationRecalled {
#[topic]
pub notification_id: BytesN<32>,
#[topic]
pub recalled_by: Address,
#[topic]
pub category: NotificationCategory,
#[topic]
pub priority: NotificationPriority,
pub recalled_at: u64,
}
/// Emitted when a scheduled notification is revoked by an authorized sender.
#[contractevent(data_format = "single-value")]
#[derive(Clone)]
pub struct NotificationRevoked {
#[topic]
pub notification_id: BytesN<32>,
#[topic]
pub revoked_by: Address,
#[topic]
pub category: NotificationCategory,
#[topic]
pub priority: NotificationPriority,
// GAS: Removed `revoked_at` — derivable from ledger metadata
}
/// Emitted when a scheduled notification's expiry period is extended by an authorized sender.
#[contractevent(data_format = "single-value")]
#[derive(Clone)]
pub struct NotificationExtended {
#[topic]
pub notification_id: BytesN<32>,
#[topic]
pub caller: Address,
#[topic]
pub category: NotificationCategory,
#[topic]
pub priority: NotificationPriority,
pub new_expires_at: u64,
}
/// Emitted when a notification is acknowledged by an authorized user.
#[contractevent(data_format = "single-value")]
#[derive(Clone)]
pub struct NotificationAcknowledged {
#[topic]
pub notification_id: BytesN<32>,
#[topic]
pub acknowledger: Address,
#[topic]
pub category: NotificationCategory,
#[topic]
pub priority: NotificationPriority,
pub timestamp: u64,
}
/// Emitted when a subscriber cancels an active notification subscription.
#[contractevent(data_format = "single-value")]
#[derive(Clone)]
pub struct SubscriptionCancelled {
#[topic]
pub group_id: BytesN<32>,
#[topic]
pub subscriber: Address,
#[topic]
pub category: NotificationCategory,
#[topic]
pub priority: NotificationPriority,
pub cancelled_at: u64,
}
// ============================================================================
// Batch events
// ============================================================================
/// Emitted when a batch of notifications is created in a single transaction.
#[contractevent]
#[derive(Clone)]
pub struct BatchNotificationsCreated {
#[topic]
pub creator: Address,
#[topic]
pub category: NotificationCategory,
#[topic]
pub priority: NotificationPriority,
pub count: u32,
pub ids: Vec<BytesN<32>>,
}
/// Emitted when an off-chain batch of notifications finishes processing.
#[contractevent(data_format = "single-value")]
#[derive(Clone)]
pub struct BatchProcessingCompleted {
#[topic]
pub batch_id: BytesN<32>,
#[topic]
pub category: NotificationCategory,
#[topic]
pub priority: NotificationPriority,
pub processed_count: u32,
}
// ============================================================================
// Audit Logging
// ============================================================================
/// Discriminator for each stage in the notification lifecycle that the audit
/// log tracks. Values are fixed-width integers so they serialise compactly on
/// chain and can be matched exactly by off-chain indexers.
#[contracttype]
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub enum AuditAction {
/// A notification was created (scheduled on-chain).
Created = 0,
/// A delivery attempt was made for a notification.
DeliveryAttempt = 1,
/// A delivery attempt failed.
DeliveryFailed = 2,
/// The recipient acknowledged the notification.
Acknowledged = 3,
/// The notification was cancelled before expiry.
Cancelled = 4,
/// The notification expired naturally.
Expired = 5,
}
/// Emitted when a new audit record is appended to the on-chain log.
#[contractevent]
#[derive(Clone)]
pub struct AuditRecordAppended {
#[topic]
pub notification_id: BytesN<32>,
#[topic]
pub action: AuditAction,
#[topic]
pub category: NotificationCategory,
pub seq: u64,
pub actor: Address,
// GAS: Removed `timestamp` — derivable from ledger metadata
}
// ============================================================================
// Ownership transfer events
// ============================================================================
/// Emitted when the current owner initiates a two-step ownership transfer.
#[contractevent(data_format = "single-value")]
#[derive(Clone)]
pub struct OwnershipTransferInitiated {
#[topic]
pub previous_owner: Address,
#[topic]
pub category: NotificationCategory,
#[topic]
pub priority: NotificationPriority,
pub pending_owner: Address,
}
/// Emitted when a two-step ownership transfer is completed.
#[contractevent(data_format = "single-value")]
#[derive(Clone)]
pub struct OwnershipTransferred {
#[topic]
pub previous_owner: Address,
#[topic]
pub category: NotificationCategory,
#[topic]
pub priority: NotificationPriority,
pub new_owner: Address,
}
// ============================================================================
// Notification Limits Configuration
// ============================================================================
/// Emitted when a sender's reputation score is updated.
/// Triggered by successful or failed notification delivery.
#[contractevent]
#[derive(Clone)]
pub struct ReputationUpdated {
#[topic]
pub sender: Address,
#[topic]
pub category: NotificationCategory,
#[topic]
pub priority: NotificationPriority,
pub new_score: i64,
pub successful_count: u32,
pub failed_count: u32,
}
/// Emitted when protocol-level notification limits are configured or updated.
#[contractevent]
#[derive(Clone)]
pub struct NotificationLimitsConfigured {
#[topic]
pub admin: Address,
#[topic]
pub category: NotificationCategory,
#[topic]
pub priority: NotificationPriority,
pub max_payload_size: u32,
pub max_expiration_seconds: u64,
pub min_expiration_seconds: u64,
pub max_batch_size: u32,
}
/// Emitted when a sender's reputation tier changes (e.g., from Bronze to Silver).
#[contractevent]
#[derive(Clone)]
pub struct ReputationTierChanged {
#[topic]
pub sender: Address,
#[topic]
pub category: NotificationCategory,
#[topic]
pub priority: NotificationPriority,
pub old_tier: u32,
pub new_tier: u32,
pub reputation_score: i64,
}
// ============================================================================
// Schema Version Tracking (Issue #309)
// ============================================================================
/// Emitted when the on-chain notification schema version is set or upgraded.
#[contractevent]
#[derive(Clone)]
pub struct SchemaVersionSet {
#[topic]
pub admin: Address,
#[topic]
pub category: NotificationCategory,
#[topic]
pub priority: NotificationPriority,
/// New schema version number.
pub schema_version: u32,
/// Previous schema version (0 when first set).
pub previous_version: u32,
}
// ============================================================================
// Access Logging (Issue #312)
// ============================================================================
/// Emitted whenever a protected notification record is accessed.
#[contractevent]
#[derive(Clone)]
pub struct NotificationAccessed {
#[topic]
pub notification_id: BytesN<32>,
#[topic]
pub accessor: Address,
#[topic]
pub category: NotificationCategory,
/// Ledger timestamp (seconds) when the access occurred.
pub accessed_at: u64,
}
/// Emitted when an authorized user updates a channel's description or metadata.
///
/// Existing subscribers / members are unaffected — only descriptive metadata changes.
#[contractevent]
#[derive(Clone)]
pub struct ChannelMetadataUpdated {
#[topic]
pub channel_id: BytesN<32>,
#[topic]
pub updater: Address,
#[topic]
pub category: NotificationCategory,
#[topic]
pub priority: NotificationPriority,
pub updated_at: u64,
}
/// Emitted when a processed notification is moved into the on-chain archive.
#[contractevent]
#[derive(Clone)]
pub struct NotificationArchived {
#[topic]
pub notification_id: BytesN<32>,
#[topic]
pub category: NotificationCategory,
#[topic]
pub priority: NotificationPriority,
pub archived_at: u64,
pub archive_reason: String,
}
// ============================================================================
// Template Registry (Issue #352)
// ============================================================================
/// Emitted when a new notification template is registered on-chain.
///
/// Off-chain indexers key off `template_id` to track registered templates.
/// The owner's address is published as an indexed topic for creator-based
/// filtering.
#[contractevent(data_format = "single-value")]
#[derive(Clone)]
pub struct TemplateRegistered {
/// Address that created and owns the template.
#[topic]
pub owner: Address,
#[topic]
pub category: NotificationCategory,
#[topic]
pub priority: NotificationPriority,
/// Unique identifier of the newly registered template.
pub template_id: BytesN<32>,
}
/// Emitted when an existing notification template is updated by its owner.
///
/// Off-chain indexers should use `template_id` to invalidate any cached
/// versions of the template and re-fetch the updated content.
#[contractevent(data_format = "single-value")]
#[derive(Clone)]
pub struct TemplateUpdated {
/// Address that owns (and updated) the template.
#[topic]
pub owner: Address,
#[topic]
pub category: NotificationCategory,
#[topic]
pub priority: NotificationPriority,
/// Unique identifier of the updated template.
pub template_id: BytesN<32>,
}