diff --git a/contracts/smartdeploy/src/events.rs b/contracts/smartdeploy/src/events.rs new file mode 100644 index 0000000..1198b99 --- /dev/null +++ b/contracts/smartdeploy/src/events.rs @@ -0,0 +1,40 @@ +use crate::{ + metadata::ContractMetadata, + version::{Update, Version}, +}; +use loam_sdk::soroban_sdk::{self, contracttype, Address, Env, IntoVal, String, Val}; +use loam_sdk::IntoKey; + +#[contracttype] +#[derive(IntoKey)] +pub struct Publish { + pub published_name: String, + pub author: Address, + pub hash: soroban_sdk::BytesN<32>, + pub repo: ContractMetadata, + pub kind: Update, +} + +#[contracttype] +#[derive(IntoKey)] +pub struct Deploy { + pub published_name: String, + pub deployed_name: String, + pub version: Version, + pub deployer: Address, + pub contract_id: Address, +} + +pub trait EventPublishable { + /// Publish an event on the blockchain + fn publish_event(self, env: &Env); +} + +impl EventPublishable for T +where + T: soroban_sdk::IntoKey + IntoVal, +{ + fn publish_event(self, env: &Env) { + env.events().publish((T::into_key(),), self); + } +} diff --git a/contracts/smartdeploy/src/lib.rs b/contracts/smartdeploy/src/lib.rs index a44675d..27e4642 100644 --- a/contracts/smartdeploy/src/lib.rs +++ b/contracts/smartdeploy/src/lib.rs @@ -6,6 +6,7 @@ use registry::{ }; pub mod error; +pub mod events; pub mod metadata; pub mod registry; pub mod util; diff --git a/contracts/smartdeploy/src/registry/contract.rs b/contracts/smartdeploy/src/registry/contract.rs index 61aff27..008e486 100644 --- a/contracts/smartdeploy/src/registry/contract.rs +++ b/contracts/smartdeploy/src/registry/contract.rs @@ -5,6 +5,7 @@ use loam_sdk::soroban_sdk::{ use crate::{ error::Error, + events::{Deploy, EventPublishable}, registry::Publishable, util::{hash_string, MAX_BUMP}, version::Version, @@ -24,14 +25,6 @@ loam_sdk::import_contract!(core_riff); // loam_sdk::soroban_sdk::contractimport!(file = "../../target/loam/core_riff.wasm",); // } -#[contracttype] -pub struct DeployEventData { - published_name: String, - deployed_name: String, - version: Version, - deployer: Address, - contract_id: Address, -} #[contracttype(export = false)] pub struct ContractRegistry(pub Map); @@ -91,19 +84,21 @@ impl IsDeployable for ContractRegistry { // Publish a deploy event let version = version.map_or_else( || { - let published_contract = WasmRegistry::get_lazy().unwrap().find_contract(contract_name.clone())?; + let published_contract = WasmRegistry::get_lazy() + .unwrap() + .find_contract(contract_name.clone())?; published_contract.most_recent_version() }, Ok, )?; - let deploy_datas = DeployEventData { + Deploy { published_name: contract_name, deployed_name, version, deployer: owner, contract_id: address.clone(), - }; - env().events().publish((symbol_short!("deploy"),), deploy_datas); + } + .publish_event(env()); Ok(address) } diff --git a/contracts/smartdeploy/src/registry/wasm.rs b/contracts/smartdeploy/src/registry/wasm.rs index c0f89ab..ebde872 100644 --- a/contracts/smartdeploy/src/registry/wasm.rs +++ b/contracts/smartdeploy/src/registry/wasm.rs @@ -4,6 +4,7 @@ use loam_sdk::soroban_sdk::{ use crate::{ error::Error, + events::{EventPublishable, Publish}, metadata::{ContractMetadata, PublishedContract, PublishedWasm}, util::MAX_BUMP, version::{self, Version, INITAL_VERSION}, @@ -77,13 +78,13 @@ impl IsPublishable for WasmRegistry { ) -> Result<(), Error> { let mut contract = self .find_contract(contract_name.clone()) - .unwrap_or_else(|_| PublishedContract::new(author)); + .unwrap_or_else(|_| PublishedContract::new(author.clone())); contract.author.require_auth(); let keys = contract.versions.keys(); let last_version = keys.last().unwrap_or_default(); last_version.log(); - let new_version = last_version.clone().update(&kind.unwrap_or_default()); + let new_version = last_version.clone().update(&kind.clone().unwrap_or_default()); new_version.log(); let metadata = if let Some(repo) = repo { @@ -94,9 +95,20 @@ impl IsPublishable for WasmRegistry { contract.get(Some(last_version))?.metadata }; let hash = env().deployer().upload_contract_wasm(wasm); - let published_binary = PublishedWasm { hash, metadata }; + let published_binary = PublishedWasm { hash: hash.clone(), metadata: metadata.clone() }; contract.versions.set(new_version, published_binary); - self.set_contract(contract_name, contract); + self.set_contract(contract_name.clone(), contract); + + // Publish a publish event + Publish { + published_name: contract_name, + author, + hash, + repo: metadata, + kind: kind.unwrap_or_default(), + } + .publish_event(env()); + Ok(()) } diff --git a/contracts/smartdeploy/src/test.rs b/contracts/smartdeploy/src/test.rs index 1ce1848..98389d3 100644 --- a/contracts/smartdeploy/src/test.rs +++ b/contracts/smartdeploy/src/test.rs @@ -1,6 +1,11 @@ #![cfg(test)] +use super::*; use crate::{error::Error, SorobanContract, SorobanContractClient}; -use loam_sdk::soroban_sdk::{testutils::Address as _, Address, Bytes, Env, String}; +use loam_sdk::soroban_sdk::{ + testutils::{ Address as _, Events }, + Address, Bytes, Env, String, IntoVal, + vec, +}; extern crate std; // The contract that will be deployed by the Publisher contract. @@ -52,6 +57,56 @@ fn handle_error_cases() { // std::println!("{res:?}"); } +#[test] +fn publish_deploy_events() { + + let (env, client, address) = &init(); + env.mock_all_auths(); + + let published_name = String::from_str(env, "contract_a"); + + let bytes = Bytes::from_slice(env, contract::WASM); + + client.publish(&published_name, address, &bytes, &None, &None); + + let publish_data = events::Publish { + published_name: published_name.clone(), + author: address.clone(), + hash: env.deployer().upload_contract_wasm(bytes), + repo: metadata::ContractMetadata::default(), + kind: version::Update::default(), + }; + + let deployed_name = String::from_str(env, "deployed_contract_a"); + + let contract_id = client.deploy(&published_name, &Some(version::INITAL_VERSION), &deployed_name, address, &None, &None); + + let deploy_data = events::Deploy { + published_name, + deployed_name, + version: version::INITAL_VERSION, + deployer: address.clone(), + contract_id, + }; + + assert_eq!( + env.events().all(), + vec![ + &env, + ( + client.address.clone(), + (String::from_str(env, "Publish"),).into_val(env), + publish_data.into_val(env) + ), + ( + client.address.clone(), + (String::from_str(env, "Deploy"),).into_val(env), + deploy_data.into_val(env) + ), + ] + ); +} + // #[test] // fn returns_most_recent_version() { // let (env, client, address) = &init(); diff --git a/contracts/smartdeploy/src/version.rs b/contracts/smartdeploy/src/version.rs index 71977ea..b8e83b4 100644 --- a/contracts/smartdeploy/src/version.rs +++ b/contracts/smartdeploy/src/version.rs @@ -70,7 +70,7 @@ impl Version { } #[contracttype] -#[derive(Default)] +#[derive(Default, Clone)] pub enum Update { #[default] Patch,