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
98 changes: 60 additions & 38 deletions contracts/hospital-registry/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,18 @@
#![no_std]
#![allow(deprecated)]

use soroban_sdk::{contract, contractimpl, contracttype, symbol_short, Address, Env, String, Vec};
use soroban_sdk::{
contract, contracterror, contractimpl, contracttype, symbol_short, Address, Env, String, Vec,
};

#[contracterror]
#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
#[repr(u32)]
pub enum ContractError {
HospitalAlreadyRegistered = 1,
HospitalNotFound = 2,
HospitalConfigNotFound = 3,
}

/// --------------------
/// Hospital Structures
Expand Down Expand Up @@ -112,11 +123,12 @@ pub struct HospitalRegistry;

#[contractimpl]
impl HospitalRegistry {
fn assert_hospital_exists(env: &Env, wallet: &Address) {
fn assert_hospital_exists(env: &Env, wallet: &Address) -> Result<(), ContractError> {
let key = DataKey::Hospital(wallet.clone());
if !env.storage().persistent().has(&key) {
panic!("Hospital not found");
return Err(ContractError::HospitalNotFound);
}
Ok(())
}

fn default_config(env: &Env) -> HospitalConfig {
Expand Down Expand Up @@ -149,12 +161,12 @@ impl HospitalRegistry {
name: String,
location: String,
metadata: String,
) {
) -> Result<(), ContractError> {
wallet.require_auth();

let key = DataKey::Hospital(wallet.clone());
if env.storage().persistent().has(&key) {
panic!("Hospital already registered");
return Err(ContractError::HospitalAlreadyRegistered);
}

let hospital = HospitalData {
Expand All @@ -173,22 +185,23 @@ impl HospitalRegistry {
(symbol_short!("reg_hosp"), wallet),
symbol_short!("success"),
);
Ok(())
}

/// Update hospital metadata
///
/// # Arguments
/// * `wallet` - The wallet address of the hospital
/// * `metadata` - Updated metadata information
pub fn update_hospital(env: Env, wallet: Address, metadata: String) {
pub fn update_hospital(env: Env, wallet: Address, metadata: String) -> Result<(), ContractError> {
wallet.require_auth();

let key = DataKey::Hospital(wallet.clone());
let mut hospital: HospitalData = env
.storage()
.persistent()
.get(&key)
.expect("Hospital not found");
.ok_or(ContractError::HospitalNotFound)?;

hospital.metadata = metadata;
env.storage().persistent().set(&key, &hospital);
Expand All @@ -197,6 +210,7 @@ impl HospitalRegistry {
(symbol_short!("upd_hosp"), wallet),
symbol_short!("success"),
);
Ok(())
}

/// Retrieve hospital data by wallet address
Expand All @@ -206,45 +220,45 @@ impl HospitalRegistry {
///
/// # Returns
/// The HospitalData for the given wallet address
pub fn get_hospital(env: Env, wallet: Address) -> HospitalData {
pub fn get_hospital(env: Env, wallet: Address) -> Result<HospitalData, ContractError> {
let key = DataKey::Hospital(wallet);
env.storage()
.persistent()
.get(&key)
.expect("Hospital not found")
.ok_or(ContractError::HospitalNotFound)
}

/// Set full hospital configuration in one call
pub fn set_hospital_config(env: Env, wallet: Address, config: HospitalConfig) {
pub fn set_hospital_config(env: Env, wallet: Address, config: HospitalConfig) -> Result<(), ContractError> {
wallet.require_auth();
Self::assert_hospital_exists(&env, &wallet);
Self::assert_hospital_exists(&env, &wallet)?;

let key = DataKey::HospitalConfig(wallet.clone());
env.storage().persistent().set(&key, &config);

env.events()
.publish((symbol_short!("cfg_set"), wallet), symbol_short!("success"));
Ok(())
}

/// Retrieve hospital configuration
pub fn get_hospital_config(env: Env, wallet: Address) -> HospitalConfig {
pub fn get_hospital_config(env: Env, wallet: Address) -> Result<HospitalConfig, ContractError> {
let key = DataKey::HospitalConfig(wallet);
env.storage()
.persistent()
.get(&key)
.expect("Hospital config not found")
.ok_or(ContractError::HospitalConfigNotFound)
}

pub fn update_departments(env: Env, wallet: Address, departments: Vec<Department>) {
pub fn update_departments(env: Env, wallet: Address, departments: Vec<Department>) -> Result<(), ContractError> {
wallet.require_auth();
Self::assert_hospital_exists(&env, &wallet);
Self::assert_hospital_exists(&env, &wallet)?;

let key = DataKey::HospitalConfig(wallet.clone());
let mut config: HospitalConfig = env
.storage()
.persistent()
.get(&key)
.expect("Hospital config not found");
.ok_or(ContractError::HospitalConfigNotFound)?;

config.departments = departments;
env.storage().persistent().set(&key, &config);
Expand All @@ -253,72 +267,76 @@ impl HospitalRegistry {
(symbol_short!("upd_dept"), wallet),
symbol_short!("success"),
);
Ok(())
}

pub fn update_locations(env: Env, wallet: Address, locations: Vec<Location>) {
pub fn update_locations(env: Env, wallet: Address, locations: Vec<Location>) -> Result<(), ContractError> {
wallet.require_auth();
Self::assert_hospital_exists(&env, &wallet);
Self::assert_hospital_exists(&env, &wallet)?;

let key = DataKey::HospitalConfig(wallet.clone());
let mut config: HospitalConfig = env
.storage()
.persistent()
.get(&key)
.expect("Hospital config not found");
.ok_or(ContractError::HospitalConfigNotFound)?;

config.locations = locations;
env.storage().persistent().set(&key, &config);

env.events()
.publish((symbol_short!("upd_loc"), wallet), symbol_short!("success"));
Ok(())
}

pub fn update_equipment(env: Env, wallet: Address, equipment: Vec<EquipmentResource>) {
pub fn update_equipment(env: Env, wallet: Address, equipment: Vec<EquipmentResource>) -> Result<(), ContractError> {
wallet.require_auth();
Self::assert_hospital_exists(&env, &wallet);
Self::assert_hospital_exists(&env, &wallet)?;

let key = DataKey::HospitalConfig(wallet.clone());
let mut config: HospitalConfig = env
.storage()
.persistent()
.get(&key)
.expect("Hospital config not found");
.ok_or(ContractError::HospitalConfigNotFound)?;

config.equipment = equipment;
env.storage().persistent().set(&key, &config);

env.events()
.publish((symbol_short!("upd_eq"), wallet), symbol_short!("success"));
Ok(())
}

pub fn update_policies(env: Env, wallet: Address, policies: Vec<PolicyProcedure>) {
pub fn update_policies(env: Env, wallet: Address, policies: Vec<PolicyProcedure>) -> Result<(), ContractError> {
wallet.require_auth();
Self::assert_hospital_exists(&env, &wallet);
Self::assert_hospital_exists(&env, &wallet)?;

let key = DataKey::HospitalConfig(wallet.clone());
let mut config: HospitalConfig = env
.storage()
.persistent()
.get(&key)
.expect("Hospital config not found");
.ok_or(ContractError::HospitalConfigNotFound)?;

config.policies = policies;
env.storage().persistent().set(&key, &config);

env.events()
.publish((symbol_short!("upd_pol"), wallet), symbol_short!("success"));
Ok(())
}

pub fn update_alerts(env: Env, wallet: Address, alerts: Vec<AlertSetting>) {
pub fn update_alerts(env: Env, wallet: Address, alerts: Vec<AlertSetting>) -> Result<(), ContractError> {
wallet.require_auth();
Self::assert_hospital_exists(&env, &wallet);
Self::assert_hospital_exists(&env, &wallet)?;

let key = DataKey::HospitalConfig(wallet.clone());
let mut config: HospitalConfig = env
.storage()
.persistent()
.get(&key)
.expect("Hospital config not found");
.ok_or(ContractError::HospitalConfigNotFound)?;

config.alerts = alerts;
env.storage().persistent().set(&key, &config);
Expand All @@ -327,40 +345,42 @@ impl HospitalRegistry {
(symbol_short!("upd_alrt"), wallet),
symbol_short!("success"),
);
Ok(())
}

pub fn update_insurance_providers(
env: Env,
wallet: Address,
insurance_providers: Vec<InsuranceProviderConfig>,
) {
) -> Result<(), ContractError> {
wallet.require_auth();
Self::assert_hospital_exists(&env, &wallet);
Self::assert_hospital_exists(&env, &wallet)?;

let key = DataKey::HospitalConfig(wallet.clone());
let mut config: HospitalConfig = env
.storage()
.persistent()
.get(&key)
.expect("Hospital config not found");
.ok_or(ContractError::HospitalConfigNotFound)?;

config.insurance_providers = insurance_providers;
env.storage().persistent().set(&key, &config);

env.events()
.publish((symbol_short!("upd_ins"), wallet), symbol_short!("success"));
Ok(())
}

pub fn update_billing(env: Env, wallet: Address, billing: BillingConfig) {
pub fn update_billing(env: Env, wallet: Address, billing: BillingConfig) -> Result<(), ContractError> {
wallet.require_auth();
Self::assert_hospital_exists(&env, &wallet);
Self::assert_hospital_exists(&env, &wallet)?;

let key = DataKey::HospitalConfig(wallet.clone());
let mut config: HospitalConfig = env
.storage()
.persistent()
.get(&key)
.expect("Hospital config not found");
.ok_or(ContractError::HospitalConfigNotFound)?;

config.billing = billing;
env.storage().persistent().set(&key, &config);
Expand All @@ -369,28 +389,30 @@ impl HospitalRegistry {
(symbol_short!("upd_bill"), wallet),
symbol_short!("success"),
);
Ok(())
}

pub fn update_emergency_protocols(
env: Env,
wallet: Address,
protocols: Vec<EmergencyProtocol>,
) {
) -> Result<(), ContractError> {
wallet.require_auth();
Self::assert_hospital_exists(&env, &wallet);
Self::assert_hospital_exists(&env, &wallet)?;

let key = DataKey::HospitalConfig(wallet.clone());
let mut config: HospitalConfig = env
.storage()
.persistent()
.get(&key)
.expect("Hospital config not found");
.ok_or(ContractError::HospitalConfigNotFound)?;

config.emergency_protocols = protocols;
env.storage().persistent().set(&key, &config);

env.events()
.publish((symbol_short!("upd_emg"), wallet), symbol_short!("success"));
Ok(())
}
}

Expand Down
18 changes: 7 additions & 11 deletions contracts/hospital-registry/src/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ fn test_register_hospital() {
let client = HospitalRegistryClient::new(&env, &contract_id);

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

env.mock_all_auths();

client.register_hospital(
Expand Down Expand Up @@ -39,7 +38,6 @@ fn test_update_hospital() {
let client = HospitalRegistryClient::new(&env, &contract_id);

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

env.mock_all_auths();

client.register_hospital(
Expand All @@ -64,14 +62,12 @@ fn test_update_hospital() {
}

#[test]
#[should_panic(expected = "Hospital already registered")]
fn test_duplicate_registration() {
let env = Env::default();
let contract_id = env.register_contract(None, HospitalRegistry);
let client = HospitalRegistryClient::new(&env, &contract_id);

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

env.mock_all_auths();

client.register_hospital(
Expand All @@ -81,42 +77,42 @@ fn test_duplicate_registration() {
&String::from_str(&env, "Test Metadata"),
);

// Attempt to register again
client.register_hospital(
let result = client.try_register_hospital(
&hospital_wallet,
&String::from_str(&env, "Test Hospital"),
&String::from_str(&env, "Test Location"),
&String::from_str(&env, "Test Metadata"),
);

assert_eq!(result, Err(Ok(ContractError::HospitalAlreadyRegistered)));
}

#[test]
#[should_panic(expected = "Hospital not found")]
fn test_get_nonexistent_hospital() {
let env = Env::default();
let contract_id = env.register_contract(None, HospitalRegistry);
let client = HospitalRegistryClient::new(&env, &contract_id);

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

client.get_hospital(&hospital_wallet);
let result = client.try_get_hospital(&hospital_wallet);
assert_eq!(result, Err(Ok(ContractError::HospitalNotFound)));
}

#[test]
#[should_panic(expected = "Hospital not found")]
fn test_update_nonexistent_hospital() {
let env = Env::default();
let contract_id = env.register_contract(None, HospitalRegistry);
let client = HospitalRegistryClient::new(&env, &contract_id);

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

env.mock_all_auths();

client.update_hospital(
let result = client.try_update_hospital(
&hospital_wallet,
&String::from_str(&env, "Updated Metadata"),
);
assert_eq!(result, Err(Ok(ContractError::HospitalNotFound)));
}

#[test]
Expand Down
Loading