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
121 changes: 121 additions & 0 deletions soroban-contract/contracts/event_manager/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
#![no_std]
use soroban_sdk::{contract, contractimpl, contracttype, symbol_short, Address, Env, Symbol};

/// Storage keys for the contract
#[derive(Clone)]
#[contracttype]
pub enum DataKey {
EventCount,
Event(u32),
}

/// Event data structure
#[derive(Clone)]
#[contracttype]
pub struct Event {
pub id: u32,
pub theme: Symbol,
pub organizer: Address,
pub event_type: Symbol,
pub total_tickets: u128,
pub tickets_sold: u128,
pub ticket_price: u128,
pub start_date: u64,
pub end_date: u64,
pub is_canceled: bool,
pub event_ticket_addr: Address,
}

#[contract]
pub struct EventManagerContract;

#[contractimpl]
impl EventManagerContract {
/// Reschedule an existing event with new start and end dates.
///
/// # Arguments
/// * `env` - The contract environment
/// * `event_id` - The ID of the event to reschedule
/// * `start_date` - The new start date (unix timestamp)
/// * `end_date` - The new end date (unix timestamp)
///
/// # Panics
/// * If the event does not exist
/// * If the caller is not the event organizer
/// * If the event has already ended
pub fn reschedule_event(env: Env, event_id: u32, start_date: u64, end_date: u64) {
// Get the event count to verify event exists
let event_count: u32 = env
.storage()
.instance()
.get(&DataKey::EventCount)
.unwrap_or(0);

// Check that event exists
if event_id == 0 || event_id > event_count {
panic!("Event does not exist");
}

// Get the event from storage
let event: Event = env
.storage()
.instance()
.get(&DataKey::Event(event_id))
.expect("Event not found");

// Verify the organizer is authorized to reschedule
// require_auth ensures only the organizer can call this function
event.organizer.require_auth();

// Check that the event has not ended yet
let current_timestamp = env.ledger().timestamp();
if event.end_date <= current_timestamp {
panic!("Event has already ended");
}

// Create updated event with new dates
let updated_event = Event {
id: event.id,
theme: event.theme,
organizer: event.organizer,
event_type: event.event_type,
total_tickets: event.total_tickets,
tickets_sold: event.tickets_sold,
ticket_price: event.ticket_price,
start_date,
end_date,
is_canceled: false,
event_ticket_addr: event.event_ticket_addr,
};

// Store the updated event
env.storage()
.instance()
.set(&DataKey::Event(event_id), &updated_event);

// Emit EventRescheduled event
env.events().publish(
(symbol_short!("resched"), event_id),
(start_date, end_date),
);
}

/// Get an event by its ID
pub fn get_event(env: Env, event_id: u32) -> Event {
env.storage()
.instance()
.get(&DataKey::Event(event_id))
.expect("Event not found")
}

/// Get the total number of events
pub fn get_event_count(env: Env) -> u32 {
env.storage()
.instance()
.get(&DataKey::EventCount)
.unwrap_or(0)
}
}

#[cfg(test)]
mod test;
115 changes: 115 additions & 0 deletions soroban-contract/contracts/event_manager/src/test.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
#![cfg(test)]

use super::*;
use soroban_sdk::{testutils::Address as _, testutils::Ledger, Address, Env, Symbol};

/// Helper function to create a test event in storage
fn setup_test_event(env: &Env, organizer: &Address, event_id: u32, end_date: u64) {
let ticket_addr = Address::generate(env);

let event = Event {
id: event_id,
theme: Symbol::new(env, "test_theme"),
organizer: organizer.clone(),
event_type: Symbol::new(env, "conference"),
total_tickets: 100,
tickets_sold: 0,
ticket_price: 1000,
start_date: 1000,
end_date,
is_canceled: false,
event_ticket_addr: ticket_addr,
};

env.storage()
.instance()
.set(&DataKey::EventCount, &event_id);
env.storage()
.instance()
.set(&DataKey::Event(event_id), &event);
}

#[test]
fn test_reschedule_event_success() {
let env = Env::default();
env.mock_all_auths();

let contract_id = env.register(EventManagerContract, ());
let client = EventManagerContractClient::new(&env, &contract_id);

let organizer = Address::generate(&env);

// Set up a test event with end_date in the future
env.ledger().set_timestamp(500);
env.as_contract(&contract_id, || {
setup_test_event(&env, &organizer, 1, 2000);
});

// Reschedule the event
let new_start_date: u64 = 1500;
let new_end_date: u64 = 3000;
client.reschedule_event(&1, &new_start_date, &new_end_date);

// Verify the event was updated
let updated_event = client.get_event(&1);
assert_eq!(updated_event.start_date, new_start_date);
assert_eq!(updated_event.end_date, new_end_date);
assert_eq!(updated_event.is_canceled, false);
}

#[test]
#[should_panic(expected = "Event does not exist")]
fn test_reschedule_nonexistent_event() {
let env = Env::default();
env.mock_all_auths();

let contract_id = env.register(EventManagerContract, ());
let client = EventManagerContractClient::new(&env, &contract_id);

// Try to reschedule an event that doesn't exist
client.reschedule_event(&999, &1500, &3000);
}

#[test]
#[should_panic(expected = "Event has already ended")]
fn test_reschedule_ended_event() {
let env = Env::default();
env.mock_all_auths();

let contract_id = env.register(EventManagerContract, ());
let client = EventManagerContractClient::new(&env, &contract_id);

let organizer = Address::generate(&env);

// Set up a test event with end_date in the past
env.as_contract(&contract_id, || {
setup_test_event(&env, &organizer, 1, 1000);
});

// Set current timestamp after the event end
env.ledger().set_timestamp(2000);

// Try to reschedule - should fail because event has ended
client.reschedule_event(&1, &2500, &3500);
}

#[test]
fn test_get_event_count() {
let env = Env::default();

let contract_id = env.register(EventManagerContract, ());
let client = EventManagerContractClient::new(&env, &contract_id);

// Initially should be 0
assert_eq!(client.get_event_count(), 0);

let organizer = Address::generate(&env);

// Add an event
env.as_contract(&contract_id, || {
setup_test_event(&env, &organizer, 1, 2000);
});

// Should now be 1
assert_eq!(client.get_event_count(), 1);
}
Loading