Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 3 additions & 13 deletions contract/contracts/hello-world/src/autoshare_logic.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
use crate::base::errors::Error;
use crate::base::events::{
AdminTransferred, AuthorizationFailure, AutoshareCreated, AutoshareUpdated, ContractPaused,
ContractUnpaused, GroupActivated, GroupDeactivated, NotificationCategory,
ScheduledNotificationCancelled, Withdrawal,
ContractUnpaused, GroupActivated, GroupDeactivated, NotificationCategory, NotificationPriority,
Withdrawal,
ScheduledNotificationCancelled, Withdrawal,
};
use crate::base::types::{AutoShareDetails, GroupMember, PaymentHistory};
use soroban_sdk::{contracttype, token, Address, BytesN, Env, String, Vec};
Expand Down Expand Up @@ -76,7 +74,7 @@ pub fn create_autoshare(
id: id.clone(),
name,
creator: creator.clone(),
priority: NotificationPriority::Standard,
priority: NotificationPriority::Medium,
usage_count,
total_usages_paid: usage_count,
members: Vec::new(&env),
Expand Down Expand Up @@ -112,7 +110,6 @@ pub fn create_autoshare(

AutoshareCreated {
creator: creator.clone(),
priority: details.priority,
category: NotificationCategory::Group,
priority: NotificationPriority::Medium,
id: id.clone(),
Expand Down Expand Up @@ -264,7 +261,6 @@ pub fn initialize_admin(env: Env, admin: Address) {
fn publish_authorization_failure(env: &Env, caller: &Address, action: &str) {
AuthorizationFailure {
caller: caller.clone(),
priority: NotificationPriority::High,
category: NotificationCategory::Admin,
priority: NotificationPriority::Critical,
action: String::from_str(env, action),
Expand Down Expand Up @@ -302,7 +298,6 @@ pub fn transfer_admin(env: Env, current_admin: Address, new_admin: Address) -> R
env.storage().persistent().set(&DataKey::Admin, &new_admin);
AdminTransferred {
old_admin: current_admin,
priority: NotificationPriority::High,
category: NotificationCategory::Admin,
priority: NotificationPriority::Critical,
new_admin,
Expand All @@ -328,7 +323,6 @@ pub fn pause(env: Env, admin: Address) -> Result<(), Error> {

env.storage().persistent().set(&pause_key, &true);
ContractPaused {
priority: NotificationPriority::High,
category: NotificationCategory::Admin,
priority: NotificationPriority::High,
}
Expand All @@ -349,7 +343,6 @@ pub fn unpause(env: Env, admin: Address) -> Result<(), Error> {

env.storage().persistent().set(&pause_key, &false);
ContractUnpaused {
priority: NotificationPriority::High,
category: NotificationCategory::Admin,
priority: NotificationPriority::High,
}
Expand Down Expand Up @@ -688,7 +681,6 @@ pub fn update_members(

AutoshareUpdated {
updater: caller,
priority: details.priority,
category: NotificationCategory::Group,
priority: NotificationPriority::Medium,
id: id.clone(),
Expand Down Expand Up @@ -726,7 +718,6 @@ pub fn deactivate_group(env: Env, id: BytesN<32>, caller: Address) -> Result<(),

GroupDeactivated {
creator: caller,
priority: details.priority,
category: NotificationCategory::Group,
priority: NotificationPriority::Low,
id: id.clone(),
Expand Down Expand Up @@ -764,7 +755,6 @@ pub fn activate_group(env: Env, id: BytesN<32>, caller: Address) -> Result<(), E

GroupActivated {
creator: caller,
priority: details.priority,
category: NotificationCategory::Group,
priority: NotificationPriority::Low,
id: id.clone(),
Expand Down Expand Up @@ -814,7 +804,6 @@ pub fn withdraw(
Withdrawal {
token,
recipient,
priority: NotificationPriority::Critical,
category: NotificationCategory::Financial,
priority: NotificationPriority::High,
amount,
Expand Down Expand Up @@ -849,6 +838,7 @@ pub fn cancel_notification(
ScheduledNotificationCancelled {
caller,
category: NotificationCategory::Notification,
priority: NotificationPriority::Low,
notification_id,
}
.publish(&env);
Expand Down
36 changes: 5 additions & 31 deletions contract/contracts/hello-world/src/base/events.rs
Original file line number Diff line number Diff line change
@@ -1,20 +1,10 @@
use soroban_sdk::{contractevent, contracttype, Address, BytesN, String};

/// Priority metadata attached to notifications emitted by the contract.
#[contracttype]
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub enum NotificationPriority {
Low = 0,
Standard = 1,
High = 2,
Critical = 3,
}

/// 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
/// trailing, indexed event topic so consumers can subscribe to or filter out
/// whole categories without having to decode the event payload first.
///
/// # Backward compatibility
Expand All @@ -41,8 +31,8 @@ pub enum NotificationCategory {
///
/// 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.
/// priority as a trailing, indexed event topic so consumers can subscribe to
/// or page on high-priority notifications without decoding the payload.
///
/// # Backward compatibility
///
Expand Down Expand Up @@ -72,8 +62,6 @@ pub struct AutoshareCreated {
#[topic]
pub creator: Address,
#[topic]
pub priority: NotificationPriority,
#[topic]
pub category: NotificationCategory,
#[topic]
pub priority: NotificationPriority,
Expand All @@ -84,8 +72,6 @@ pub struct AutoshareCreated {
#[contractevent]
#[derive(Clone)]
pub struct ContractPaused {
#[topic]
pub priority: NotificationPriority,
#[topic]
pub category: NotificationCategory,
#[topic]
Expand All @@ -96,8 +82,6 @@ pub struct ContractPaused {
#[contractevent]
#[derive(Clone)]
pub struct ContractUnpaused {
#[topic]
pub priority: NotificationPriority,
#[topic]
pub category: NotificationCategory,
#[topic]
Expand All @@ -111,8 +95,6 @@ pub struct AutoshareUpdated {
#[topic]
pub updater: Address,
#[topic]
pub priority: NotificationPriority,
#[topic]
pub category: NotificationCategory,
#[topic]
pub priority: NotificationPriority,
Expand All @@ -126,8 +108,6 @@ pub struct GroupDeactivated {
#[topic]
pub creator: Address,
#[topic]
pub priority: NotificationPriority,
#[topic]
pub category: NotificationCategory,
#[topic]
pub priority: NotificationPriority,
Expand All @@ -141,8 +121,6 @@ pub struct GroupActivated {
#[topic]
pub creator: Address,
#[topic]
pub priority: NotificationPriority,
#[topic]
pub category: NotificationCategory,
#[topic]
pub priority: NotificationPriority,
Expand All @@ -156,8 +134,6 @@ pub struct AdminTransferred {
#[topic]
pub old_admin: Address,
#[topic]
pub priority: NotificationPriority,
#[topic]
pub category: NotificationCategory,
#[topic]
pub priority: NotificationPriority,
Expand All @@ -173,8 +149,6 @@ pub struct Withdrawal {
#[topic]
pub recipient: Address,
#[topic]
pub priority: NotificationPriority,
#[topic]
pub category: NotificationCategory,
#[topic]
pub priority: NotificationPriority,
Expand All @@ -188,8 +162,6 @@ pub struct AuthorizationFailure {
#[topic]
pub caller: Address,
#[topic]
pub priority: NotificationPriority,
#[topic]
pub category: NotificationCategory,
#[topic]
pub priority: NotificationPriority,
Expand All @@ -208,5 +180,7 @@ pub struct ScheduledNotificationCancelled {
pub caller: Address,
#[topic]
pub category: NotificationCategory,
#[topic]
pub priority: NotificationPriority,
pub notification_id: BytesN<32>,
}
56 changes: 17 additions & 39 deletions contract/contracts/hello-world/src/tests/notification_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,16 +63,6 @@ fn priority_of(env: &soroban_sdk::Env, event_name: &str) -> Option<NotificationP
NotificationPriority::try_from_val(env, &last).ok()
}

/// Extracts priority metadata for the latest event named `event_name`.
fn priority_of(env: &soroban_sdk::Env, event_name: &str) -> Option<NotificationPriority> {
let topics = topics_of(env, event_name)?;
if topics.len() < 2 {
return None;
}
let priority = topics.get(topics.len() - 2)?;
NotificationPriority::try_from_val(env, &priority).ok()
}

/// Returns the category of the most recently emitted event — i.e. the metadata a
/// streaming consumer would read off the event as it arrives.
///
Expand All @@ -90,11 +80,8 @@ fn latest_category(env: &soroban_sdk::Env) -> Option<NotificationCategory> {

fn latest_priority(env: &soroban_sdk::Env) -> Option<NotificationPriority> {
let (_addr, topics, _data) = env.events().all().last()?;
if topics.len() < 2 {
return None;
}
let priority = topics.get(topics.len() - 2)?;
NotificationPriority::try_from_val(env, &priority).ok()
let last = topics.last()?;
NotificationPriority::try_from_val(env, &last).ok()
}

#[test]
Expand All @@ -118,7 +105,7 @@ fn test_created_event_has_group_category() {
);
assert_eq!(
priority_of(&test_env.env, "autoshare_created"),
Some(NotificationPriority::Standard)
Some(NotificationPriority::Medium)
);
}

Expand All @@ -139,9 +126,7 @@ fn test_created_group_stores_standard_priority() {
);

let details = client.get(&id);
assert_eq!(details.priority, NotificationPriority::Standard);
Some(NotificationPriority::Medium)
);
assert_eq!(details.priority, NotificationPriority::Medium);
}

#[test]
Expand Down Expand Up @@ -173,7 +158,6 @@ fn test_updated_event_has_group_category() {
);
assert_eq!(
priority_of(&test_env.env, "autoshare_updated"),
Some(NotificationPriority::Standard)
Some(NotificationPriority::Medium)
);
}
Expand Down Expand Up @@ -201,7 +185,6 @@ fn test_deactivate_and_activate_events_have_group_category() {
);
assert_eq!(
priority_of(&test_env.env, "group_deactivated"),
Some(NotificationPriority::Standard)
Some(NotificationPriority::Low)
);

Expand All @@ -212,7 +195,6 @@ fn test_deactivate_and_activate_events_have_group_category() {
);
assert_eq!(
priority_of(&test_env.env, "group_activated"),
Some(NotificationPriority::Standard)
Some(NotificationPriority::Low)
);
}
Expand Down Expand Up @@ -256,7 +238,6 @@ fn test_admin_transfer_event_has_admin_category() {
);
assert_eq!(
priority_of(&test_env.env, "admin_transferred"),
Some(NotificationPriority::High)
Some(NotificationPriority::Critical)
);
}
Expand Down Expand Up @@ -286,7 +267,6 @@ fn test_withdrawal_event_has_financial_category() {
);
assert_eq!(
priority_of(&test_env.env, "withdrawal"),
Some(NotificationPriority::Critical)
Some(NotificationPriority::High)
);
}
Expand Down Expand Up @@ -333,7 +313,7 @@ fn test_events_can_be_filtered_by_category() {
);
assert_eq!(
latest_priority(&test_env.env),
Some(NotificationPriority::Standard)
Some(NotificationPriority::Medium)
);
route();

Expand All @@ -359,7 +339,7 @@ fn test_events_can_be_filtered_by_category() {
);
assert_eq!(
latest_priority(&test_env.env),
Some(NotificationPriority::Critical)
Some(NotificationPriority::High)
);
route();

Expand Down Expand Up @@ -454,8 +434,8 @@ fn test_cancellation_event_topic_shape() {
let topics = topics_of(&test_env.env, "scheduled_notification_cancelled")
.expect("event must be emitted");

// Topics: [0] event name, [1] caller address, [2] category
assert_eq!(topics.len(), 3);
// Topics: [0] event name, [1] caller address, [2] category, [3] priority
assert_eq!(topics.len(), 4);

let name = Symbol::try_from_val(&test_env.env, &topics.get(0).unwrap()).unwrap();
assert_eq!(
Expand All @@ -469,6 +449,10 @@ fn test_cancellation_event_topic_shape() {
let category =
NotificationCategory::try_from_val(&test_env.env, &topics.get(2).unwrap()).unwrap();
assert_eq!(category, NotificationCategory::Notification);

let priority =
NotificationPriority::try_from_val(&test_env.env, &topics.get(3).unwrap()).unwrap();
assert_eq!(priority, NotificationPriority::Low);
}

#[test]
Expand All @@ -484,7 +468,10 @@ fn test_cancellation_blocked_when_contract_paused() {
let notification_id = BytesN::from_array(&test_env.env, &id_bytes);

let result = client.try_cancel_notification(&notification_id, &caller);
assert!(result.is_err(), "cancellation should be rejected while contract is paused");
assert!(
result.is_err(),
"cancellation should be rejected while contract is paused"
);
}

/// Verifies that each call to `cancel_notification` emits a
Expand Down Expand Up @@ -556,9 +543,6 @@ fn test_created_event_backward_compatible_shape() {
);

let topics = topics_of(&test_env.env, "autoshare_created").expect("event emitted");
// [0] event name, [1] creator (unchanged), [2] priority, [3] category.
// [0] event name, [1] creator (unchanged), [2] category (now second-to-last),
// [3] priority (new trailing topic).
assert_eq!(topics.len(), 4);

let name = Symbol::try_from_val(&test_env.env, &topics.get(0).unwrap()).unwrap();
Expand All @@ -567,20 +551,14 @@ fn test_created_event_backward_compatible_shape() {
let topic_creator = Address::try_from_val(&test_env.env, &topics.get(1).unwrap()).unwrap();
assert_eq!(topic_creator, creator);

let priority =
NotificationPriority::try_from_val(&test_env.env, &topics.get(2).unwrap()).unwrap();
assert_eq!(priority, NotificationPriority::Standard);

let category =
NotificationCategory::try_from_val(&test_env.env, &topics.get(3).unwrap()).unwrap();
NotificationCategory::try_from_val(&test_env.env, &topics.get(2).unwrap()).unwrap();
assert_eq!(category, NotificationCategory::Group);

// The newly added trailing topic is the priority.
let priority =
NotificationPriority::try_from_val(&test_env.env, &topics.get(3).unwrap()).unwrap();
assert_eq!(priority, NotificationPriority::Medium);

// Data payload is still the group id.
let data = test_env
.env
.events()
Expand Down
Loading