From 0e7ca8cf887669a7674450da78fe09b26ea449d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Noah=20Bayindirli=20=F0=9F=A5=82?= Date: Thu, 16 Jan 2025 13:14:47 -0700 Subject: [PATCH 1/4] feat(stellar-axelar-std-derive): simplify event definition via IntoEvent derive macro --- Cargo.lock | 3 + Cargo.toml | 1 + contracts/axelar-gateway/Cargo.toml | 1 + contracts/axelar-gateway/src/event.rs | 81 ++-------- packages/axelar-std-derive/Cargo.toml | 7 +- packages/axelar-std-derive/src/lib.rs | 221 +++++++++++++++++++++++++- packages/axelar-std/Cargo.toml | 2 +- packages/axelar-std/src/events.rs | 12 +- 8 files changed, 247 insertions(+), 81 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0d5c4e0e..860293c3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1996,6 +1996,7 @@ dependencies = [ "soroban-sdk", "stellar-axelar-gateway", "stellar-axelar-std", + "stellar-axelar-std-derive", ] [[package]] @@ -2021,6 +2022,8 @@ dependencies = [ name = "stellar-axelar-std-derive" version = "0.1.0" dependencies = [ + "heck", + "proc-macro2", "quote", "soroban-sdk", "stellar-axelar-std", diff --git a/Cargo.toml b/Cargo.toml index d6004f5b..a37fe35f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,6 +9,7 @@ rust-version = "1.81.0" [workspace.dependencies] soroban-sdk = { version = "22.0.2" } soroban-token-sdk = { version = "22.0.2" } +proc-macro2 = "1.0" cfg-if = { version = "1.0" } stellar-axelar-std = { version = "^0.1.0", path = "packages/axelar-std", features = ["derive"] } stellar-axelar-std-derive = { version = "^0.1.0", path = "packages/axelar-std-derive" } diff --git a/contracts/axelar-gateway/Cargo.toml b/contracts/axelar-gateway/Cargo.toml index d987a160..123735c0 100644 --- a/contracts/axelar-gateway/Cargo.toml +++ b/contracts/axelar-gateway/Cargo.toml @@ -16,6 +16,7 @@ rand = { version = "0.8.5", optional = true } rand_chacha = "0.3" soroban-sdk = { workspace = true } stellar-axelar-std = { workspace = true } +stellar-axelar-std-derive = { workspace = true } [dev-dependencies] ed25519-dalek = { version = "^2.1" } diff --git a/contracts/axelar-gateway/src/event.rs b/contracts/axelar-gateway/src/event.rs index 34ce2332..3530486f 100644 --- a/contracts/axelar-gateway/src/event.rs +++ b/contracts/axelar-gateway/src/event.rs @@ -1,97 +1,34 @@ use core::fmt::Debug; -use cfg_if::cfg_if; -use soroban_sdk::{Address, Bytes, BytesN, Env, IntoVal, String, Symbol, Topics, Val, Vec}; +#[cfg(any(test, feature = "testutils"))] use stellar_axelar_std::events::Event; +use stellar_axelar_std::IntoEvent; +use soroban_sdk::{Address, Bytes, BytesN, String}; use crate::types::Message; -#[derive(Debug, PartialEq, Eq)] +#[derive(Debug, PartialEq, Eq, IntoEvent)] pub struct ContractCalledEvent { pub caller: Address, pub destination_chain: String, pub destination_address: String, - pub payload: Bytes, pub payload_hash: BytesN<32>, + #[data] + pub payload: Bytes, } -#[derive(Debug, PartialEq, Eq)] +#[derive(Debug, PartialEq, Eq, IntoEvent)] pub struct MessageApprovedEvent { pub message: Message, } -#[derive(Debug, PartialEq, Eq)] +#[derive(Debug, PartialEq, Eq, IntoEvent)] pub struct MessageExecutedEvent { pub message: Message, } -#[derive(Debug, PartialEq, Eq)] +#[derive(Debug, PartialEq, Eq, IntoEvent)] pub struct SignersRotatedEvent { pub epoch: u64, pub signers_hash: BytesN<32>, } - -impl Event for ContractCalledEvent { - fn topics(&self, env: &Env) -> impl Topics + Debug { - ( - Symbol::new(env, "contract_called"), - self.caller.to_val(), - self.destination_chain.to_val(), - self.destination_address.to_val(), - self.payload_hash.to_val(), - ) - } - - fn data(&self, _env: &Env) -> impl IntoVal + Debug { - (self.payload.to_val(),) - } -} - -impl Event for MessageApprovedEvent { - fn topics(&self, env: &Env) -> impl Topics + Debug { - (Symbol::new(env, "message_approved"), self.message.clone()) - } - - fn data(&self, env: &Env) -> impl IntoVal + Debug { - Vec::::new(env) - } -} - -impl Event for MessageExecutedEvent { - fn topics(&self, env: &Env) -> impl Topics + Debug { - (Symbol::new(env, "message_executed"), self.message.clone()) - } - - fn data(&self, env: &Env) -> impl IntoVal + Debug { - Vec::::new(env) - } -} - -impl Event for SignersRotatedEvent { - fn topics(&self, env: &Env) -> impl Topics + Debug { - ( - Symbol::new(env, "signers_rotated"), - self.epoch, - self.signers_hash.to_val(), - ) - } - - fn data(&self, env: &Env) -> impl IntoVal + Debug { - Vec::::new(env) - } -} - -cfg_if! { - if #[cfg(any(test, feature = "testutils"))] { - use stellar_axelar_std::impl_event_testutils; - - impl_event_testutils!( - ContractCalledEvent, - (Symbol, Address, String, String, BytesN<32>), - (Bytes) - ); - impl_event_testutils!(MessageApprovedEvent, (Symbol, Message), ()); - impl_event_testutils!(MessageExecutedEvent, (Symbol, Message), ()); - impl_event_testutils!(SignersRotatedEvent, (Symbol, u64, BytesN<32>), ()); - } -} diff --git a/packages/axelar-std-derive/Cargo.toml b/packages/axelar-std-derive/Cargo.toml index 8572c55e..9f6e1789 100644 --- a/packages/axelar-std-derive/Cargo.toml +++ b/packages/axelar-std-derive/Cargo.toml @@ -9,13 +9,18 @@ publish = true [lib] proc-macro = true +[features] +testutils = [] + [dependencies] +heck = "0.5.0" +proc-macro2 = "1.0" quote = "1.0" syn = { version = "2.0", features = ["full"] } [dev-dependencies] soroban-sdk = { workspace = true, features = ["testutils"] } -stellar-axelar-std = { workspace = true } +stellar-axelar-std = { workspace = true, features = ["testutils"] } [lints] workspace = true diff --git a/packages/axelar-std-derive/src/lib.rs b/packages/axelar-std-derive/src/lib.rs index c7b40ab5..bd1a2806 100644 --- a/packages/axelar-std-derive/src/lib.rs +++ b/packages/axelar-std-derive/src/lib.rs @@ -1,7 +1,8 @@ +use heck::ToSnakeCase; use proc_macro::TokenStream; use quote::quote; use syn::parse::{Parse, ParseStream}; -use syn::{parse_macro_input, DeriveInput, Error, Ident, Token, Type}; +use syn::{parse_macro_input, DeriveInput, Error, Ident, LitStr, Token, Type}; /// Implements the Operatable interface for a Soroban contract. /// @@ -219,3 +220,221 @@ pub fn derive_upgradable(input: TokenStream) -> TokenStream { } }.into() } + +/// Implements the Event and EventTestUtils traits for a Soroban contract event. +/// +/// Fields without a `#[data]` attribute are used as topics, while fields with `#[data]` are used as event data. +/// The event name can be specified with `#[event_name(...)]` or will default to the struct name in snake_case (minus "Event" suffix). +/// +/// # Example +/// ```rust +/// # mod test { +/// use core::fmt::Debug; +/// use stellar_axelar_std::events::Event; +/// use stellar_axelar_std_derive::IntoEvent; +/// use soroban_sdk::{Address, contract, contractimpl, Env, String}; +/// +/// #[derive(Debug, PartialEq, IntoEvent)] +/// pub struct ApproveEvent { +/// pub owner: Address, +/// pub spender: Address, +/// #[data] +/// pub amount: String, +/// } +/// +/// #[derive(Debug, PartialEq, IntoEvent)] +/// #[event_name("transfer")] +/// pub struct TransferEvent { +/// pub from: Address, +/// pub to: Address, +/// #[data] +/// pub amount: String, +/// } +/// +/// #[contract] +/// pub struct TokenContract; +/// +/// #[contractimpl] +/// impl TokenContract { +/// pub fn approve(env: &Env, spender: Address, amount: String) { +/// // ... approval logic ... +/// +/// let event = ApproveEvent { +/// owner: env.current_contract_address(), +/// spender, +/// amount, +/// }; +/// // Generates event with: +/// // - Topics: ["approve", contract_address, spender] +/// // - Data: [amount] +/// env.events().publish(event.topics(env), event.data(env)); +/// } +/// +/// pub fn transfer(env: &Env, to: Address, amount: String) { +/// // ... transfer logic ... +/// +/// let event = TransferEvent { +/// from: env.current_contract_address(), +/// to, +/// amount, +/// }; +/// +/// // Generates event with: +/// // - Topics: ["transfer", contract_address, to] +/// // - Data: [amount] +/// +/// env.events().publish(event.topics(env), event.data(env)); +/// } +/// } +/// } +/// ``` +#[proc_macro_derive(IntoEvent, attributes(data, event_name))] +pub fn derive_into_event(input: TokenStream) -> TokenStream { + let input = parse_macro_input!(input as DeriveInput); + + let event_impl = derive_event_impl(&input); + #[cfg(any(test, feature = "testutils"))] + let test_impl = derive_test_impl(&input); + + #[cfg(not(any(test, feature = "testutils")))] + let test_impl = quote! {}; + + quote! { + #event_impl + #test_impl + } + .into() +} + +fn derive_event_impl(input: &DeriveInput) -> proc_macro2::TokenStream { + let name = &input.ident; + let event_name = event_name_snake_case(input); + let ((topic_idents, _), (data_idents, _)) = event_struct_fields(input); + + quote! { + impl stellar_axelar_std::events::Event for #name { + fn topics(&self, env: &soroban_sdk::Env) -> impl soroban_sdk::Topics + core::fmt::Debug { + ( + soroban_sdk::Symbol::new(env, #event_name), + #(soroban_sdk::IntoVal::::into_val(&self.#topic_idents, env),)* + ) + } + + fn data(&self, env: &soroban_sdk::Env) -> impl soroban_sdk::IntoVal + core::fmt::Debug { + let vec: soroban_sdk::Vec = soroban_sdk::vec![env, #(soroban_sdk::IntoVal::<_, soroban_sdk::Val>::into_val(&self.#data_idents, env))*]; + vec + } + + fn emit(self, env: &soroban_sdk::Env) { + env.events().publish(self.topics(env), self.data(env)); + } + } + } +} +#[cfg(any(test, feature = "testutils"))] +fn derive_test_impl(input: &DeriveInput) -> proc_macro2::TokenStream { + let name = &input.ident; + let ((_, topic_types), (_, data_types)) = event_struct_fields(input); + event_testutils(name, topic_types, data_types) +} + +#[cfg(any(test, feature = "testutils"))] +fn event_testutils( + name: &Ident, + topic_types: Vec<&Type>, + data_types: Vec<&Type>, +) -> proc_macro2::TokenStream { + quote! { + impl stellar_axelar_std::events::EventTestutils for #name { + fn matches(self, env: &soroban_sdk::Env, event: &(soroban_sdk::Address, soroban_sdk::Vec, soroban_sdk::Val)) -> bool { + use soroban_sdk::IntoVal; + Self::standardized_fmt(env, event) == Self::standardized_fmt(env, &(event.0.clone(), self.topics(env).into_val(env), self.data(env).into_val(env))) + } + + #[allow(unused_assignments)] + #[allow(unused_variables)] + #[allow(unused_mut)] + fn standardized_fmt(env: &soroban_sdk::Env, (contract_id, topics, data): &(soroban_sdk::Address, soroban_sdk::Vec, soroban_sdk::Val)) -> std::string::String { + use soroban_sdk::TryFromVal; + + let mut topics_output: std::vec::Vec = std::vec![]; + + let event_name = topics.get(0).expect("event name topic missing"); + topics_output.push(std::format!("{:?}", soroban_sdk::Symbol::try_from_val(env, &event_name) + .expect("event name should be a Symbol"))); + + let mut i = 1; + #( + let topic = topics.get(i).expect("the number of topics does not match this function's definition"); + topics_output.push(std::format!("{:?}", <#topic_types>::try_from_val(env, &topic) + .expect("given topic value does not match the expected type"))); + + i += 1; + )* + + let data = soroban_sdk::Vec::::try_from_val(env, data) + .expect("data should be defined as a vector-compatible type"); + + let mut data_output: std::vec::Vec = std::vec![]; + + let mut i = 0; + #( + let data_entry = data.get(i).expect("the number of data entries does not match this function's definition"); + data_output.push(std::format!("{:?}", <#data_types>::try_from_val(env, &data_entry) + .expect("given data value does not match the expected type"))); + + i += 1; + )* + + std::format!("contract: {:?}\ntopics: ({})\ndata: ({})", + contract_id, + topics_output.join(", "), + data_output.join(", ") + ) + } + } + } +} + +fn event_name_snake_case(input: &DeriveInput) -> String { + input + .attrs + .iter() + .find(|attr| attr.path().is_ident("event_name")) + .map(|attr| attr.parse_args::().unwrap().value()) + .unwrap_or_else(|| { + input + .ident + .to_string() + .strip_suffix("Event") + .unwrap() + .to_snake_case() + }) +} + +fn event_struct_fields( + input: &DeriveInput, +) -> ((Vec<&Ident>, Vec<&Type>), (Vec<&Ident>, Vec<&Type>)) { + let syn::Data::Struct(data_struct) = &input.data else { + panic!("IntoEvent can only be derived for structs"); + }; + + let mut topic_idents = Vec::new(); + let mut topic_types = Vec::new(); + let mut data_idents = Vec::new(); + let mut data_types = Vec::new(); + + for field in data_struct.fields.iter() { + if let Some(ident) = field.ident.as_ref() { + if field.attrs.iter().any(|attr| attr.path().is_ident("data")) { + data_idents.push(ident); + data_types.push(&field.ty); + } else { + topic_idents.push(ident); + topic_types.push(&field.ty); + } + } + } + + ((topic_idents, topic_types), (data_idents, data_types)) +} diff --git a/packages/axelar-std/Cargo.toml b/packages/axelar-std/Cargo.toml index 7611631c..1e8c6eaa 100644 --- a/packages/axelar-std/Cargo.toml +++ b/packages/axelar-std/Cargo.toml @@ -18,7 +18,7 @@ stellar-axelar-std-derive = { workspace = true, optional = true } [dev-dependencies] goldie = { workspace = true } soroban-sdk = { workspace = true, features = ["testutils"] } -stellar-axelar-std-derive = { workspace = true } +stellar-axelar-std-derive = { workspace = true, features = ["testutils"] } [features] testutils = ["soroban-sdk/testutils", "hex"] diff --git a/packages/axelar-std/src/events.rs b/packages/axelar-std/src/events.rs index e932dd23..afd51df1 100644 --- a/packages/axelar-std/src/events.rs +++ b/packages/axelar-std/src/events.rs @@ -4,7 +4,7 @@ use soroban_sdk::{Env, IntoVal, Topics, Val, Vec}; #[cfg(any(test, feature = "testutils"))] pub use testutils::*; -pub trait Event: Debug + PartialEq { +pub trait Event: Debug + PartialEq + Sized { fn topics(&self, env: &Env) -> impl Topics + Debug; /// A default empty tuple/vector is used for event data, since majority of events only use topics. @@ -12,7 +12,7 @@ pub trait Event: Debug + PartialEq { Vec::::new(env) } - fn emit(&self, env: &Env) { + fn emit(self, env: &Env) { env.events().publish(self.topics(env), self.data(env)); } } @@ -25,7 +25,7 @@ mod testutils { use crate::events::Event; pub trait EventTestutils: Event { - fn matches(&self, env: &Env, event: &(Address, Vec, Val)) -> bool; + fn matches(self, env: &Env, event: &(Address, Vec, Val)) -> bool; fn standardized_fmt( env: &Env, @@ -61,7 +61,7 @@ mod testutils { macro_rules! impl_event_testutils { ($event_type:ty, ($($topic_type:ty),*), ($($data_type:ty),*)) => { impl $crate::events::EventTestutils for $event_type { - fn matches(&self, env: &soroban_sdk::Env, event: &(soroban_sdk::Address, soroban_sdk::Vec, soroban_sdk::Val)) -> bool { + fn matches(self, env: &soroban_sdk::Env, event: &(soroban_sdk::Address, soroban_sdk::Vec, soroban_sdk::Val)) -> bool { use soroban_sdk::IntoVal; Self::standardized_fmt(env, event) == Self::standardized_fmt(env, &(event.0.clone(), self.topics(env).into_val(env), self.data(env).into_val(env))) @@ -115,7 +115,7 @@ mod test { use crate::events::{Event, EventTestutils}; use crate::{events, impl_event_testutils}; - #[derive(Debug, PartialEq, Eq)] + #[derive(Debug, PartialEq, Eq, Clone)] struct TestEvent { topic1: Symbol, topic2: String, @@ -152,7 +152,7 @@ mod test { let contract = env.register(Contract, ()); env.as_contract(&contract, || { - expected.emit(&env); + expected.clone().emit(&env); }); assert!(expected.matches(&env, &env.events().all().last().unwrap())); From f99b09d9ab414a97ed8f41680cf4b9d5308025fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Noah=20Bayindirli=20=F0=9F=A5=82?= Date: Thu, 16 Jan 2025 13:36:09 -0700 Subject: [PATCH 2/4] address diff and fmt lints --- contracts/axelar-gateway/src/event.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/axelar-gateway/src/event.rs b/contracts/axelar-gateway/src/event.rs index 3530486f..8f699263 100644 --- a/contracts/axelar-gateway/src/event.rs +++ b/contracts/axelar-gateway/src/event.rs @@ -1,9 +1,9 @@ use core::fmt::Debug; +use soroban_sdk::{Address, Bytes, BytesN, String}; #[cfg(any(test, feature = "testutils"))] use stellar_axelar_std::events::Event; use stellar_axelar_std::IntoEvent; -use soroban_sdk::{Address, Bytes, BytesN, String}; use crate::types::Message; From dd5fd565eb152a31f08981c0d77188196d9f73ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Noah=20Bayindirli=20=F0=9F=A5=82?= Date: Thu, 16 Jan 2025 22:38:40 -0700 Subject: [PATCH 3/4] address comments --- Cargo.lock | 1 - Cargo.toml | 2 +- contracts/axelar-gateway/Cargo.toml | 1 - packages/axelar-std-derive/Cargo.toml | 2 +- packages/axelar-std-derive/src/lib.rs | 67 +++++++++------------------ 5 files changed, 24 insertions(+), 49 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 860293c3..033330a4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1996,7 +1996,6 @@ dependencies = [ "soroban-sdk", "stellar-axelar-gateway", "stellar-axelar-std", - "stellar-axelar-std-derive", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index a37fe35f..920735e1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,7 +9,7 @@ rust-version = "1.81.0" [workspace.dependencies] soroban-sdk = { version = "22.0.2" } soroban-token-sdk = { version = "22.0.2" } -proc-macro2 = "1.0" +proc-macro2 = { version = "1.0" } cfg-if = { version = "1.0" } stellar-axelar-std = { version = "^0.1.0", path = "packages/axelar-std", features = ["derive"] } stellar-axelar-std-derive = { version = "^0.1.0", path = "packages/axelar-std-derive" } diff --git a/contracts/axelar-gateway/Cargo.toml b/contracts/axelar-gateway/Cargo.toml index 123735c0..d987a160 100644 --- a/contracts/axelar-gateway/Cargo.toml +++ b/contracts/axelar-gateway/Cargo.toml @@ -16,7 +16,6 @@ rand = { version = "0.8.5", optional = true } rand_chacha = "0.3" soroban-sdk = { workspace = true } stellar-axelar-std = { workspace = true } -stellar-axelar-std-derive = { workspace = true } [dev-dependencies] ed25519-dalek = { version = "^2.1" } diff --git a/packages/axelar-std-derive/Cargo.toml b/packages/axelar-std-derive/Cargo.toml index 9f6e1789..9f2308e1 100644 --- a/packages/axelar-std-derive/Cargo.toml +++ b/packages/axelar-std-derive/Cargo.toml @@ -14,7 +14,7 @@ testutils = [] [dependencies] heck = "0.5.0" -proc-macro2 = "1.0" +proc-macro2 = { workspace = true } quote = "1.0" syn = { version = "2.0", features = ["full"] } diff --git a/packages/axelar-std-derive/src/lib.rs b/packages/axelar-std-derive/src/lib.rs index bd1a2806..48374a0a 100644 --- a/packages/axelar-std-derive/src/lib.rs +++ b/packages/axelar-std-derive/src/lib.rs @@ -235,14 +235,6 @@ pub fn derive_upgradable(input: TokenStream) -> TokenStream { /// use soroban_sdk::{Address, contract, contractimpl, Env, String}; /// /// #[derive(Debug, PartialEq, IntoEvent)] -/// pub struct ApproveEvent { -/// pub owner: Address, -/// pub spender: Address, -/// #[data] -/// pub amount: String, -/// } -/// -/// #[derive(Debug, PartialEq, IntoEvent)] /// #[event_name("transfer")] /// pub struct TransferEvent { /// pub from: Address, @@ -252,38 +244,21 @@ pub fn derive_upgradable(input: TokenStream) -> TokenStream { /// } /// /// #[contract] -/// pub struct TokenContract; +/// pub struct Token; /// /// #[contractimpl] -/// impl TokenContract { -/// pub fn approve(env: &Env, spender: Address, amount: String) { -/// // ... approval logic ... -/// -/// let event = ApproveEvent { -/// owner: env.current_contract_address(), -/// spender, -/// amount, -/// }; -/// // Generates event with: -/// // - Topics: ["approve", contract_address, spender] -/// // - Data: [amount] -/// env.events().publish(event.topics(env), event.data(env)); -/// } -/// +/// impl Token { /// pub fn transfer(env: &Env, to: Address, amount: String) { /// // ... transfer logic ... /// -/// let event = TransferEvent { -/// from: env.current_contract_address(), -/// to, -/// amount, -/// }; -/// /// // Generates event with: /// // - Topics: ["transfer", contract_address, to] /// // - Data: [amount] -/// -/// env.events().publish(event.topics(env), event.data(env)); +/// TransferEvent { +/// from: env.current_contract_address(), +/// to, +/// amount, +/// }.emit(env); /// } /// } /// } @@ -293,17 +268,17 @@ pub fn derive_into_event(input: TokenStream) -> TokenStream { let input = parse_macro_input!(input as DeriveInput); let event_impl = derive_event_impl(&input); - #[cfg(any(test, feature = "testutils"))] - let test_impl = derive_test_impl(&input); - #[cfg(not(any(test, feature = "testutils")))] - let test_impl = quote! {}; + #[cfg(any(test, feature = "testutils"))] + let event_impl = { + let event_test_impl = derive_event_testutils_impl(&input); + quote! { + #event_impl + #event_test_impl + } + }; - quote! { - #event_impl - #test_impl - } - .into() + event_impl.into() } fn derive_event_impl(input: &DeriveInput) -> proc_macro2::TokenStream { @@ -332,7 +307,7 @@ fn derive_event_impl(input: &DeriveInput) -> proc_macro2::TokenStream { } } #[cfg(any(test, feature = "testutils"))] -fn derive_test_impl(input: &DeriveInput) -> proc_macro2::TokenStream { +fn derive_event_testutils_impl(input: &DeriveInput) -> proc_macro2::TokenStream { let name = &input.ident; let ((_, topic_types), (_, data_types)) = event_struct_fields(input); event_testutils(name, topic_types, data_types) @@ -412,9 +387,11 @@ fn event_name_snake_case(input: &DeriveInput) -> String { }) } -fn event_struct_fields( - input: &DeriveInput, -) -> ((Vec<&Ident>, Vec<&Type>), (Vec<&Ident>, Vec<&Type>)) { +type EventIdent<'a> = Vec<&'a Ident>; +type EventType<'a> = Vec<&'a Type>; +type EventStructFields<'a> = (EventIdent<'a>, EventType<'a>); + +fn event_struct_fields(input: &DeriveInput) -> (EventStructFields, EventStructFields) { let syn::Data::Struct(data_struct) = &input.data else { panic!("IntoEvent can only be derived for structs"); }; From df0784be6fe5af2f9986a4bc645e01b1db06449d Mon Sep 17 00:00:00 2001 From: Milap Sheth Date: Fri, 17 Jan 2025 02:06:34 -0500 Subject: [PATCH 4/4] fix import --- contracts/axelar-gateway/src/event.rs | 2 -- packages/axelar-std-derive/src/lib.rs | 2 ++ 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/contracts/axelar-gateway/src/event.rs b/contracts/axelar-gateway/src/event.rs index 8f699263..264d5b58 100644 --- a/contracts/axelar-gateway/src/event.rs +++ b/contracts/axelar-gateway/src/event.rs @@ -1,8 +1,6 @@ use core::fmt::Debug; use soroban_sdk::{Address, Bytes, BytesN, String}; -#[cfg(any(test, feature = "testutils"))] -use stellar_axelar_std::events::Event; use stellar_axelar_std::IntoEvent; use crate::types::Message; diff --git a/packages/axelar-std-derive/src/lib.rs b/packages/axelar-std-derive/src/lib.rs index 48374a0a..847cea89 100644 --- a/packages/axelar-std-derive/src/lib.rs +++ b/packages/axelar-std-derive/src/lib.rs @@ -323,6 +323,8 @@ fn event_testutils( impl stellar_axelar_std::events::EventTestutils for #name { fn matches(self, env: &soroban_sdk::Env, event: &(soroban_sdk::Address, soroban_sdk::Vec, soroban_sdk::Val)) -> bool { use soroban_sdk::IntoVal; + use stellar_axelar_std::events::Event; + Self::standardized_fmt(env, event) == Self::standardized_fmt(env, &(event.0.clone(), self.topics(env).into_val(env), self.data(env).into_val(env))) }