Skip to content

Commit 64ff439

Browse files
authored
Subscribe "Publish" and "Deploy" events when deploying smartdeploy (#46)
* feat: Create a 'publish' event feat: Add events module feat: Enhance events module, usage of IntoKey trait fix: Fix the "publish" event bug ResourceLimitExceeded: Must put the wasm_hash instead of the wasm_binary in the event data * feat: Subscribe to events automatically when deploying smartdeploy
1 parent 8467f6e commit 64ff439

File tree

11 files changed

+163
-25
lines changed

11 files changed

+163
-25
lines changed

.env

-4
This file was deleted.

.env.example

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
SOROBAN_NETWORK=testnet
2+
SOROBAN_ACCOUNT=default
3+
CONFIG_DIR=.
4+
SOROBAN_FEE=10000000
5+
MERCURY_BACKEND_ENDPOINT=https://api.mercurydata.app:8443
6+
MERCURY_JWT_TOKEN=request-access-to-mercury-team

.gitignore

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
/target/
22
.soroban
3-
3+
.env

contracts/smartdeploy/src/events.rs

+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
use crate::{
2+
metadata::ContractMetadata,
3+
version::{Update, Version},
4+
};
5+
use loam_sdk::soroban_sdk::{self, contracttype, Address, Env, IntoVal, String, Val};
6+
use loam_sdk::IntoKey;
7+
8+
#[contracttype]
9+
#[derive(IntoKey)]
10+
pub struct Publish {
11+
pub published_name: String,
12+
pub author: Address,
13+
pub hash: soroban_sdk::BytesN<32>,
14+
pub repo: ContractMetadata,
15+
pub kind: Update,
16+
}
17+
18+
#[contracttype]
19+
#[derive(IntoKey)]
20+
pub struct Deploy {
21+
pub published_name: String,
22+
pub deployed_name: String,
23+
pub version: Version,
24+
pub deployer: Address,
25+
pub contract_id: Address,
26+
}
27+
28+
pub trait EventPublishable {
29+
/// Publish an event on the blockchain
30+
fn publish_event(self, env: &Env);
31+
}
32+
33+
impl<T> EventPublishable for T
34+
where
35+
T: soroban_sdk::IntoKey + IntoVal<Env, Val>,
36+
{
37+
fn publish_event(self, env: &Env) {
38+
env.events().publish((T::into_key(),), self);
39+
}
40+
}

contracts/smartdeploy/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use registry::{
66
};
77

88
pub mod error;
9+
pub mod events;
910
pub mod metadata;
1011
pub mod registry;
1112
pub mod util;

contracts/smartdeploy/src/registry/contract.rs

+7-14
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use loam_sdk::soroban_sdk::{
55

66
use crate::{
77
error::Error,
8+
events::{Deploy, EventPublishable},
89
registry::Publishable,
910
util::{hash_string, MAX_BUMP},
1011
version::Version,
@@ -23,16 +24,6 @@ loam_sdk::import_contract!(core_riff);
2324
// loam_sdk::soroban_sdk::contractimport!(file = "../../target/loam/core_riff.wasm",);
2425
// }
2526

26-
#[contracttype]
27-
pub struct DeployEventData {
28-
published_name: String,
29-
deployed_name: String,
30-
version: Version,
31-
deployer: Address,
32-
contract_id: Address,
33-
}
34-
#[contracttype(export = false)]
35-
pub struct ContractRegistry(pub Map<String, ContractType>);
3627

3728
#[contracttype(export = false)]
3829
#[derive(Clone)]
@@ -103,19 +94,21 @@ impl IsDeployable for ContractRegistry {
10394
// Publish a deploy event
10495
let version = version.map_or_else(
10596
|| {
106-
let published_contract = WasmRegistry::get_lazy().unwrap().find_contract(contract_name.clone())?;
97+
let published_contract = WasmRegistry::get_lazy()
98+
.unwrap()
99+
.find_contract(contract_name.clone())?;
107100
published_contract.most_recent_version()
108101
},
109102
Ok,
110103
)?;
111-
let deploy_datas = DeployEventData {
104+
Deploy {
112105
published_name: contract_name,
113106
deployed_name,
114107
version,
115108
deployer: owner,
116109
contract_id: address.clone(),
117-
};
118-
env().events().publish((symbol_short!("deploy"),), deploy_datas);
110+
}
111+
.publish_event(env());
119112

120113
Ok(address)
121114
}

contracts/smartdeploy/src/registry/wasm.rs

+16-4
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use loam_sdk::soroban_sdk::{
44

55
use crate::{
66
error::Error,
7+
events::{EventPublishable, Publish},
78
metadata::{ContractMetadata, PublishedContract, PublishedWasm},
89
util::MAX_BUMP,
910
version::{self, Version, INITAL_VERSION},
@@ -77,13 +78,13 @@ impl IsPublishable for WasmRegistry {
7778
) -> Result<(), Error> {
7879
let mut contract = self
7980
.find_contract(contract_name.clone())
80-
.unwrap_or_else(|_| PublishedContract::new(author));
81+
.unwrap_or_else(|_| PublishedContract::new(author.clone()));
8182
contract.author.require_auth();
8283
let keys = contract.versions.keys();
8384
let last_version = keys.last().unwrap_or_default();
8485

8586
last_version.log();
86-
let new_version = last_version.clone().update(&kind.unwrap_or_default());
87+
let new_version = last_version.clone().update(&kind.clone().unwrap_or_default());
8788
new_version.log();
8889

8990
let metadata = if let Some(repo) = repo {
@@ -94,9 +95,20 @@ impl IsPublishable for WasmRegistry {
9495
contract.get(Some(last_version))?.metadata
9596
};
9697
let hash = env().deployer().upload_contract_wasm(wasm);
97-
let published_binary = PublishedWasm { hash, metadata };
98+
let published_binary = PublishedWasm { hash: hash.clone(), metadata: metadata.clone() };
9899
contract.versions.set(new_version, published_binary);
99-
self.set_contract(contract_name, contract);
100+
self.set_contract(contract_name.clone(), contract);
101+
102+
// Publish a publish event
103+
Publish {
104+
published_name: contract_name,
105+
author,
106+
hash,
107+
repo: metadata,
108+
kind: kind.unwrap_or_default(),
109+
}
110+
.publish_event(env());
111+
100112
Ok(())
101113
}
102114

contracts/smartdeploy/src/test.rs

+56-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
#![cfg(test)]
2+
use super::*;
23
use crate::{error::Error, SorobanContract, SorobanContractClient};
3-
use loam_sdk::soroban_sdk::{testutils::Address as _, Address, Bytes, Env, String};
4+
use loam_sdk::soroban_sdk::{
5+
testutils::{ Address as _, Events },
6+
Address, Bytes, Env, String, IntoVal,
7+
vec,
8+
};
49
extern crate std;
510

611
// The contract that will be deployed by the Publisher contract.
@@ -52,6 +57,56 @@ fn handle_error_cases() {
5257
// std::println!("{res:?}");
5358
}
5459

60+
#[test]
61+
fn publish_deploy_events() {
62+
63+
let (env, client, address) = &init();
64+
env.mock_all_auths();
65+
66+
let published_name = String::from_str(env, "contract_a");
67+
68+
let bytes = Bytes::from_slice(env, contract::WASM);
69+
70+
client.publish(&published_name, address, &bytes, &None, &None);
71+
72+
let publish_data = events::Publish {
73+
published_name: published_name.clone(),
74+
author: address.clone(),
75+
hash: env.deployer().upload_contract_wasm(bytes),
76+
repo: metadata::ContractMetadata::default(),
77+
kind: version::Update::default(),
78+
};
79+
80+
let deployed_name = String::from_str(env, "deployed_contract_a");
81+
82+
let contract_id = client.deploy(&published_name, &Some(version::INITAL_VERSION), &deployed_name, address, &None, &None);
83+
84+
let deploy_data = events::Deploy {
85+
published_name,
86+
deployed_name,
87+
version: version::INITAL_VERSION,
88+
deployer: address.clone(),
89+
contract_id,
90+
};
91+
92+
assert_eq!(
93+
env.events().all(),
94+
vec![
95+
&env,
96+
(
97+
client.address.clone(),
98+
(String::from_str(env, "Publish"),).into_val(env),
99+
publish_data.into_val(env)
100+
),
101+
(
102+
client.address.clone(),
103+
(String::from_str(env, "Deploy"),).into_val(env),
104+
deploy_data.into_val(env)
105+
),
106+
]
107+
);
108+
}
109+
55110
// #[test]
56111
// fn returns_most_recent_version() {
57112
// let (env, client, address) = &init();

contracts/smartdeploy/src/version.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ impl Version {
7070
}
7171

7272
#[contracttype]
73-
#[derive(Default)]
73+
#[derive(Default, Clone)]
7474
pub enum Update {
7575
#[default]
7676
Patch,

deploy.sh

+2
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ if test "$ID" = ""; then
4242
fi
4343
echo $ID
4444

45+
./subscribe_events.sh $ID
46+
4547
# smartdeploy="soroban --quiet contract invoke --id $ID"
4648

4749
if test "$FILE_HASH" = ""; then

subscribe_events.sh

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
#!/bin/bash
2+
3+
# Load the .env variables
4+
if [ -f .env ]; then
5+
source .env
6+
else
7+
echo "The file .env doesn't exist"
8+
exit 1
9+
fi
10+
11+
# Subscribe to the "Publish" event
12+
# XDR built with JS: sorobanClient.xdr.ScVal.scvString("Publish").toXDR("base64")
13+
curl -X POST \
14+
-H "Content-Type: application/json" \
15+
-H "Authorization: Bearer $MERCURY_JWT_TOKEN" \
16+
-d '{
17+
"contract_id": "'"$1"'",
18+
"topic1": "AAAADgAAAAdQdWJsaXNoAA=="
19+
}' \
20+
$MERCURY_BACKEND_ENDPOINT/event
21+
22+
# Subscribe to the "Deploy" event
23+
# XDR built with JS: sorobanClient.xdr.ScVal.scvString("Deploy").toXDR("base64")
24+
curl -X POST \
25+
-H "Content-Type: application/json" \
26+
-H "Authorization: Bearer $MERCURY_JWT_TOKEN" \
27+
-d '{
28+
"contract_id": "'"$1"'",
29+
"topic1": "AAAADgAAAAZEZXBsb3kAAA=="
30+
}' \
31+
$MERCURY_BACKEND_ENDPOINT/event
32+
33+
echo "\n\nSuccessfully subscribed to the events"

0 commit comments

Comments
 (0)