diff --git a/sylvia-derive/src/input.rs b/sylvia-derive/src/input.rs index fece3234..103f3866 100644 --- a/sylvia-derive/src/input.rs +++ b/sylvia-derive/src/input.rs @@ -241,8 +241,10 @@ impl<'a> ImplInput<'a> { let migrate = self.emit_struct_msg(MsgType::Migrate); let exec_impl = self.emit_enum_msg(MsgType::Exec); let query_impl = self.emit_enum_msg(MsgType::Query); + let sudo_impl = self.emit_enum_msg(MsgType::Sudo); let exec = self.emit_glue_msg(MsgType::Exec); let query = self.emit_glue_msg(MsgType::Query); + let sudo = self.emit_glue_msg(MsgType::Sudo); #[cfg(not(tarpaulin_include))] { @@ -253,11 +255,15 @@ impl<'a> ImplInput<'a> { #query_impl + #sudo_impl + #migrate #exec #query + + #sudo } } } diff --git a/sylvia-derive/src/interfaces.rs b/sylvia-derive/src/interfaces.rs index fbfe9718..1806dc66 100644 --- a/sylvia-derive/src/interfaces.rs +++ b/sylvia-derive/src/interfaces.rs @@ -88,19 +88,17 @@ impl Interfaces { generics, .. } = interface; + let generics = if !generics.is_empty() { quote! { < #generics > } } else { quote! {} }; - let interface_enum = quote! { <#module ::sv::Api #generics as #sylvia ::types::InterfaceApi> }; - if msg_ty == &MsgType::Query { - quote! { #variant ( #interface_enum :: Query) } - } else { - quote! { #variant ( #interface_enum :: Exec)} - } + let type_name = msg_ty.as_accessor_name(false); + + quote! { #variant ( #interface_enum :: #type_name) } }) .collect() } @@ -167,6 +165,30 @@ impl Interfaces { .collect() } + pub fn emit_dispatch_arms(&self, msg_ty: &MsgType) -> Vec { + let sylvia = crate_module(); + let contract_enum_name = msg_ty.emit_msg_name(true); + + self.interfaces.iter().map(|interface| { + let ContractMessageAttr { + variant, + customs, + .. + } = interface; + + let ctx = msg_ty.emit_ctx_dispatch_values(customs); + + match (msg_ty, customs.has_msg) { + (MsgType::Exec, true) | (MsgType::Sudo, true) => quote! { + #contract_enum_name:: #variant(msg) => #sylvia ::into_response::IntoResponse::into_response(msg.dispatch(contract, Into::into( #ctx ))?) + }, + _ => quote! { + #contract_enum_name :: #variant(msg) => msg.dispatch(contract, Into::into( #ctx )) + }, + } + }).collect() + } + pub fn as_modules(&self) -> impl Iterator { self.interfaces.iter().map(|interface| &interface.module) } diff --git a/sylvia-derive/src/message.rs b/sylvia-derive/src/message.rs index a1f76b65..1a0765c9 100644 --- a/sylvia-derive/src/message.rs +++ b/sylvia-derive/src/message.rs @@ -2,8 +2,8 @@ use crate::check_generics::{CheckGenerics, GetPath}; use crate::crate_module; use crate::interfaces::Interfaces; use crate::parser::{ - parse_associated_custom_type, parse_struct_message, ContractErrorAttr, ContractMessageAttr, - Custom, EntryPointArgs, MsgAttr, MsgType, OverrideEntryPoints, + parse_associated_custom_type, parse_struct_message, ContractErrorAttr, Custom, EntryPointArgs, + MsgAttr, MsgType, OverrideEntryPoints, }; use crate::strip_generics::StripGenerics; use crate::utils::{ @@ -1290,32 +1290,7 @@ impl<'a> GlueMessage<'a> { let variants_cnt = messages_call.len(); - let dispatch_arms = interfaces.interfaces().iter().map(|interface| { - let ContractMessageAttr { - variant, - customs, - .. - } = interface; - - let ctx = match (msg_ty, customs.has_query) { - (MsgType::Exec, true )=> quote! { - ( ctx.0.into_empty(), ctx.1, ctx.2) - }, - (MsgType::Query, true )=> quote! { - ( ctx.0.into_empty(), ctx.1) - }, - _=> quote! { ctx }, - }; - - match (msg_ty, customs.has_msg) { - (MsgType::Exec, true) => quote! { - #contract_enum_name:: #variant(msg) => #sylvia ::into_response::IntoResponse::into_response(msg.dispatch(contract, Into::into( #ctx ))?) - }, - _ => quote! { - #contract_enum_name :: #variant(msg) => msg.dispatch(contract, Into::into( #ctx )) - }, - } - }); + let dispatch_arms = interfaces.emit_dispatch_arms(msg_ty); let dispatch_arm = quote! {#contract_enum_name :: #contract_name (msg) => msg.dispatch(contract, ctx)}; @@ -1439,6 +1414,7 @@ pub struct ContractApi<'a> { query_variants: MsgVariants<'a, GenericParam>, instantiate_variants: MsgVariants<'a, GenericParam>, migrate_variants: MsgVariants<'a, GenericParam>, + sudo_variants: MsgVariants<'a, GenericParam>, generics: &'a [&'a GenericParam], custom: &'a Custom<'a>, } @@ -1477,12 +1453,20 @@ impl<'a> ContractApi<'a> { &source.generics.where_clause, ); + let sudo_variants = MsgVariants::new( + source.as_variants(), + MsgType::Sudo, + generics, + &source.generics.where_clause, + ); + Self { source, exec_variants, query_variants, instantiate_variants, migrate_variants, + sudo_variants, generics, custom, } @@ -1496,6 +1480,7 @@ impl<'a> ContractApi<'a> { query_variants, instantiate_variants, migrate_variants, + sudo_variants, generics, custom, } = self; @@ -1505,12 +1490,14 @@ impl<'a> ContractApi<'a> { let query_generics = &query_variants.used_generics; let instantiate_generics = &instantiate_variants.used_generics; let migrate_generics = &migrate_variants.used_generics; + let sudo_generics = &sudo_variants.used_generics; let bracket_generics = emit_bracketed_generics(generics); let exec_bracketed_generics = emit_bracketed_generics(exec_generics); let query_bracketed_generics = emit_bracketed_generics(query_generics); let instantiate_bracketed_generics = emit_bracketed_generics(instantiate_generics); let migrate_bracketed_generics = emit_bracketed_generics(migrate_generics); + let sudo_bracketed_generics = emit_bracketed_generics(sudo_generics); let migrate_type = match !migrate_variants.variants().is_empty() { true => quote! { type Migrate = MigrateMsg #migrate_bracketed_generics; }, @@ -1522,8 +1509,10 @@ impl<'a> ContractApi<'a> { impl #bracket_generics #sylvia ::types::ContractApi for #contract_name { type ContractExec = ContractExecMsg #exec_bracketed_generics; type ContractQuery = ContractQueryMsg #query_bracketed_generics; + type ContractSudo = ContractSudoMsg #sudo_bracketed_generics; type Exec = ExecMsg #exec_bracketed_generics; type Query = QueryMsg #query_bracketed_generics; + type Sudo = SudoMsg #sudo_bracketed_generics; type Instantiate = InstantiateMsg #instantiate_bracketed_generics; #migrate_type type Remote<'remote> = Remote<'remote>; @@ -1536,6 +1525,7 @@ impl<'a> ContractApi<'a> { pub struct InterfaceApi<'a> { exec_variants: MsgVariants<'a, GenericParam>, query_variants: MsgVariants<'a, GenericParam>, + sudo_variants: MsgVariants<'a, GenericParam>, generics: &'a [&'a GenericParam], } @@ -1555,9 +1545,17 @@ impl<'a> InterfaceApi<'a> { &source.generics.where_clause, ); + let sudo_variants = MsgVariants::new( + source.as_variants(), + MsgType::Sudo, + generics, + &source.generics.where_clause, + ); + Self { exec_variants, query_variants, + sudo_variants, generics, } } @@ -1567,15 +1565,18 @@ impl<'a> InterfaceApi<'a> { let Self { exec_variants, query_variants, + sudo_variants, generics, } = self; let exec_generics = &exec_variants.used_generics; let query_generics = &query_variants.used_generics; + let sudo_generics = &sudo_variants.used_generics; let bracket_generics = emit_bracketed_generics(generics); let exec_bracketed_generics = emit_bracketed_generics(exec_generics); let query_bracketed_generics = emit_bracketed_generics(query_generics); + let sudo_bracketed_generics = emit_bracketed_generics(sudo_generics); let phantom = if !generics.is_empty() { quote! { @@ -1593,6 +1594,7 @@ impl<'a> InterfaceApi<'a> { impl #bracket_generics #sylvia ::types::InterfaceApi for Api #bracket_generics { type Exec = ExecMsg #exec_bracketed_generics; type Query = QueryMsg #query_bracketed_generics; + type Sudo = SudoMsg #sudo_bracketed_generics; } } } diff --git a/sylvia-derive/src/parser.rs b/sylvia-derive/src/parser.rs index e7755895..7770c41e 100644 --- a/sylvia-derive/src/parser.rs +++ b/sylvia-derive/src/parser.rs @@ -154,6 +154,20 @@ impl MsgType { } } + pub fn emit_ctx_dispatch_values(self, customs: &Customs) -> TokenStream { + use MsgType::*; + + match (self, customs.has_query) { + (Exec, true) => quote! { + (ctx.0.into_empty(), ctx.1, ctx.2) + }, + (Query, true) | (Sudo, true) => quote! { + (ctx.0.into_empty(), ctx.1) + }, + _ => quote! { ctx }, + } + } + /// Emits type which should be returned by dispatch function for this kind of message pub fn emit_result_type(self, msg_type: &Type, err_type: &Type) -> TokenStream { use MsgType::*; @@ -176,6 +190,7 @@ impl MsgType { match self { MsgType::Exec if is_wrapper => parse_quote! { ContractExecMsg }, MsgType::Query if is_wrapper => parse_quote! { ContractQueryMsg }, + MsgType::Sudo if is_wrapper => parse_quote! { ContractSudoMsg }, MsgType::Exec => parse_quote! { ExecMsg }, MsgType::Query => parse_quote! { QueryMsg }, MsgType::Instantiate => parse_quote! { InstantiateMsg }, @@ -189,6 +204,7 @@ impl MsgType { match self { MsgType::Exec if is_wrapper => Some(parse_quote! { ContractExec }), MsgType::Query if is_wrapper => Some(parse_quote! { ContractQuery }), + MsgType::Sudo if is_wrapper => Some(parse_quote! { ContractSudo }), MsgType::Instantiate => Some(parse_quote! { Instantiate }), MsgType::Exec => Some(parse_quote! { Exec }), MsgType::Query => Some(parse_quote! { Query }), diff --git a/sylvia/src/types.rs b/sylvia/src/types.rs index 6f1ffac0..2d03efd5 100644 --- a/sylvia/src/types.rs +++ b/sylvia/src/types.rs @@ -114,6 +114,7 @@ impl cosmwasm_std::CustomMsg for SvCustomMsg {} pub trait InterfaceApi { type Exec; type Query; + type Sudo; } pub trait ContractApi { @@ -122,7 +123,9 @@ pub trait ContractApi { type Exec; type ContractQuery; type ContractExec; + type ContractSudo; type Migrate; + type Sudo; type Querier<'querier>; type Remote<'remote>; } diff --git a/sylvia/tests/messages_generation.rs b/sylvia/tests/messages_generation.rs index a6b9c705..3b8574e7 100644 --- a/sylvia/tests/messages_generation.rs +++ b/sylvia/tests/messages_generation.rs @@ -54,7 +54,7 @@ mod interface { mod contract { use cosmwasm_std::{Addr, Reply, Response, StdResult}; use sylvia::contract; - use sylvia::types::{ExecCtx, InstantiateCtx, MigrateCtx, QueryCtx, ReplyCtx}; + use sylvia::types::{ExecCtx, InstantiateCtx, MigrateCtx, QueryCtx, ReplyCtx, SudoCtx}; use sylvia_derive::entry_points; use crate::{MyQuery, QueryResult}; @@ -113,6 +113,16 @@ mod contract { fn my_reply(&self, _ctx: ReplyCtx, _reply: Reply) -> StdResult { Ok(Response::new()) } + + #[msg(sudo)] + fn no_args_sudo(&self, _ctx: SudoCtx) -> StdResult { + Ok(Response::new()) + } + + #[msg(sudo)] + fn argumented_sudo(&self, _ctx: SudoCtx, _user: Addr) -> StdResult { + Ok(Response::new()) + } } } @@ -162,6 +172,10 @@ fn contract_messages_constructible() { let _argumented_query = contract::sv::QueryMsg::ArgumentedQuery { _user: Addr::unchecked("owner"), }; + let no_args_sudo = contract::sv::SudoMsg::NoArgsSudo {}; + let _ = contract::sv::SudoMsg::ArgumentedSudo { + _user: Addr::unchecked("owner"), + }; let _ = contract::sv::InstantiateMsg {}; let _ = contract::sv::MigrateMsg {}; @@ -175,6 +189,11 @@ fn contract_messages_constructible() { contract::sv::QueryMsg::NoArgsQuery {} => (), contract::sv::QueryMsg::ArgumentedQuery { .. } => (), } + + match no_args_sudo { + contract::sv::SudoMsg::NoArgsSudo {} => (), + contract::sv::SudoMsg::ArgumentedSudo { .. } => (), + } } #[test]