diff --git a/sylvia-derive/src/input.rs b/sylvia-derive/src/input.rs index 839702cc..fece3234 100644 --- a/sylvia-derive/src/input.rs +++ b/sylvia-derive/src/input.rs @@ -1,4 +1,4 @@ -use proc_macro2::{Span, TokenStream}; +use proc_macro2::TokenStream; use proc_macro_error::emit_error; use quote::{quote, ToTokens}; use syn::parse::{Parse, Parser}; @@ -109,8 +109,9 @@ impl<'a> TraitInput<'a> { } fn emit_messages(&self) -> TokenStream { - let exec = self.emit_msg(&Ident::new("ExecMsg", Span::mixed_site()), MsgType::Exec); - let query = self.emit_msg(&Ident::new("QueryMsg", Span::mixed_site()), MsgType::Query); + let exec = self.emit_msg(MsgType::Exec); + let query = self.emit_msg(MsgType::Query); + let sudo = self.emit_msg(MsgType::Sudo); #[cfg(not(tarpaulin_include))] { @@ -118,12 +119,14 @@ impl<'a> TraitInput<'a> { #exec #query + + #sudo } } } - fn emit_msg(&self, name: &Ident, msg_ty: MsgType) -> TokenStream { - EnumMessage::new(name, self.item, msg_ty, &self.generics, &self.custom).emit() + fn emit_msg(&self, msg_ty: MsgType) -> TokenStream { + EnumMessage::new(self.item, msg_ty, &self.generics, &self.custom).emit() } } diff --git a/sylvia-derive/src/message.rs b/sylvia-derive/src/message.rs index 9a67a37f..a1f76b65 100644 --- a/sylvia-derive/src/message.rs +++ b/sylvia-derive/src/message.rs @@ -147,7 +147,6 @@ impl<'a> StructMessage<'a> { /// Representation of single enum message pub struct EnumMessage<'a> { - name: &'a Ident, trait_name: &'a Ident, variants: Vec>, generics: Vec<&'a GenericParam>, @@ -162,7 +161,6 @@ pub struct EnumMessage<'a> { impl<'a> EnumMessage<'a> { pub fn new( - name: &'a Ident, source: &'a ItemTrait, ty: MsgType, generics: &'a [&'a GenericParam], @@ -212,7 +210,6 @@ impl<'a> EnumMessage<'a> { let wheres = filter_wheres(&source.generics.where_clause, generics, &used_generics); Self { - name, trait_name, variants, generics: used_generics, @@ -230,7 +227,6 @@ impl<'a> EnumMessage<'a> { let sylvia = crate_module(); let Self { - name, trait_name, variants, generics, @@ -243,6 +239,7 @@ impl<'a> EnumMessage<'a> { query_type, } = self; + let msg_name = msg_ty.emit_msg_name(false); let match_arms = variants.iter().map(|variant| variant.emit_dispatch_leg()); let mut msgs: Vec = variants .iter() @@ -292,13 +289,13 @@ impl<'a> EnumMessage<'a> { let generics = emit_bracketed_generics(generics); - let unique_enum_name = Ident::new(&format!("{}{}", trait_name, name), name.span()); + let unique_enum_name = Ident::new(&format!("{}{}", trait_name, msg_name), msg_name.span()); let ep_name = msg_ty.emit_ep_name(); - let messages_fn_name = Ident::new(&format!("{}_messages", ep_name), name.span()); + let messages_fn_name = Ident::new(&format!("{}_messages", ep_name), msg_name.span()); #[cfg(not(tarpaulin_include))] - let enum_declaration = match name.to_string().as_str() { + let enum_declaration = match msg_name.to_string().as_str() { "QueryMsg" => { quote! { #[allow(clippy::derive_partial_eq_without_eq)] @@ -308,7 +305,7 @@ impl<'a> EnumMessage<'a> { #(#variants,)* #phantom } - pub type #name #generics = #unique_enum_name #generics; + pub type #msg_name #generics = #unique_enum_name #generics; } } _ => { @@ -320,7 +317,7 @@ impl<'a> EnumMessage<'a> { #(#variants,)* #phantom } - pub type #name #generics = #unique_enum_name #generics; + pub type #msg_name #generics = #unique_enum_name #generics; } } }; @@ -562,7 +559,7 @@ impl<'a> MsgVariant<'a> { #[cfg(not(tarpaulin_include))] match msg_type { - Exec => quote! { + Exec | Sudo => quote! { #name { #(#fields,)* } => contract.#function_name(Into::into(ctx), #(#args),*).map_err(Into::into) @@ -572,8 +569,8 @@ impl<'a> MsgVariant<'a> { #(#fields,)* } => #sylvia ::cw_std::to_binary(&contract.#function_name(Into::into(ctx), #(#args),*)?).map_err(Into::into) }, - Instantiate | Migrate | Reply | Sudo => { - emit_error!(name.span(), "Instantiation, Reply, Migrate and Sudo messages not supported on traits, they should be defined on contracts directly"); + Instantiate | Migrate | Reply => { + emit_error!(name.span(), "Instantiation, Reply and Migrate messages not supported on traits, they should be defined on contracts directly"); quote! {} } } diff --git a/sylvia-derive/src/parser.rs b/sylvia-derive/src/parser.rs index 569e9f83..e7755895 100644 --- a/sylvia-derive/src/parser.rs +++ b/sylvia-derive/src/parser.rs @@ -90,6 +90,7 @@ pub enum MsgAttr { Instantiate { name: Ident }, Migrate { name: Ident }, Reply, + Sudo, } impl MsgType { @@ -171,7 +172,7 @@ impl MsgType { } } - pub fn emit_msg_name(&self, is_wrapper: bool) -> Type { + pub fn emit_msg_name(&self, is_wrapper: bool) -> Ident { match self { MsgType::Exec if is_wrapper => parse_quote! { ContractExecMsg }, MsgType::Query if is_wrapper => parse_quote! { ContractQueryMsg }, @@ -180,7 +181,7 @@ impl MsgType { MsgType::Instantiate => parse_quote! { InstantiateMsg }, MsgType::Migrate => parse_quote! { MigrateMsg }, MsgType::Reply => parse_quote! { ReplyMsg }, - MsgType::Sudo => todo!(), + MsgType::Sudo => parse_quote! { SudoMsg }, } } @@ -226,6 +227,7 @@ impl MsgAttr { Instantiate { .. } => MsgType::Instantiate, Migrate { .. } => MsgType::Migrate, Reply => MsgType::Reply, + Sudo => MsgType::Sudo, } } } @@ -248,10 +250,12 @@ impl Parse for MsgAttr { Ok(Self::Migrate { name }) } else if ty == "reply" { Ok(Self::Reply) + } else if ty == "sudo" { + Ok(Self::Sudo) } else { Err(Error::new( ty.span(), - "Invalid message type, expected one of: `exec`, `query`, `instantiate`, `migrate`", + "Invalid message type, expected one of: `exec`, `query`, `instantiate`, `migrate`, `reply` or `sudo`.", )) } } diff --git a/sylvia/src/types.rs b/sylvia/src/types.rs index d5c3d330..6f1ffac0 100644 --- a/sylvia/src/types.rs +++ b/sylvia/src/types.rs @@ -96,6 +96,12 @@ impl<'a, C: CustomQuery> From<(Deps<'a, C>, Env)> for QueryCtx<'a, C> { } } +impl<'a, C: CustomQuery> From<(DepsMut<'a, C>, Env)> for SudoCtx<'a, C> { + fn from((deps, env): (DepsMut<'a, C>, Env)) -> Self { + Self { deps, env } + } +} + pub trait CustomMsg: cosmwasm_std::CustomMsg + DeserializeOwned {} impl CustomMsg for T where T: cosmwasm_std::CustomMsg + DeserializeOwned {} diff --git a/sylvia/tests/messages_generation.rs b/sylvia/tests/messages_generation.rs index 6fe0b947..a6b9c705 100644 --- a/sylvia/tests/messages_generation.rs +++ b/sylvia/tests/messages_generation.rs @@ -16,7 +16,7 @@ mod interface { use cosmwasm_std::{Addr, Decimal, Response, StdError}; use sylvia::{ interface, - types::{ExecCtx, QueryCtx}, + types::{ExecCtx, QueryCtx, SudoCtx}, }; use crate::QueryResult; @@ -42,6 +42,12 @@ mod interface { #[msg(query)] fn argumented_query(&self, ctx: QueryCtx, user: Addr) -> Result; + + #[msg(sudo)] + fn no_args_sudo(&self, ctx: SudoCtx) -> Result; + + #[msg(sudo)] + fn argumented_sudo(&self, ctx: SudoCtx, user: Addr) -> Result; } } @@ -113,13 +119,17 @@ mod contract { #[test] fn interface_messages_constructible() { let no_args_exec = interface::sv::ExecMsg::NoArgsExecution {}; - let _argumented_exec = interface::sv::ExecMsg::ArgumentedExecution { + let _ = interface::sv::ExecMsg::ArgumentedExecution { addr: Addr::unchecked("owner"), coef: Decimal::percent(10), desc: "Some description".to_owned(), }; let no_args_query = interface::sv::QueryMsg::NoArgsQuery {}; - let _argumented_query = interface::sv::QueryMsg::ArgumentedQuery { + let _ = interface::sv::QueryMsg::ArgumentedQuery { + user: Addr::unchecked("owner"), + }; + let no_args_sudo = interface::sv::SudoMsg::NoArgsSudo {}; + let _ = interface::sv::SudoMsg::ArgumentedSudo { user: Addr::unchecked("owner"), }; @@ -133,6 +143,11 @@ fn interface_messages_constructible() { interface::sv::QueryMsg::NoArgsQuery {} => (), interface::sv::QueryMsg::ArgumentedQuery { .. } => (), } + + match no_args_sudo { + interface::sv::SudoMsg::NoArgsSudo {} => (), + interface::sv::SudoMsg::ArgumentedSudo { .. } => (), + } } #[test]