Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Generate SudoMsg in contract #257

Merged
merged 1 commit into from
Nov 23, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
feat: Generate SudoMsg in contract
jawoznia committed Nov 16, 2023
commit abc54832b93a797921e021cf85d443d1bac33f9f
6 changes: 6 additions & 0 deletions sylvia-derive/src/input.rs
Original file line number Diff line number Diff line change
@@ -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
}
}
}
34 changes: 28 additions & 6 deletions sylvia-derive/src/interfaces.rs
Original file line number Diff line number Diff line change
@@ -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<TokenStream> {
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<Item = &Path> {
self.interfaces.iter().map(|interface| &interface.module)
}
58 changes: 30 additions & 28 deletions sylvia-derive/src/message.rs
Original file line number Diff line number Diff line change
@@ -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;
}
}
}
16 changes: 16 additions & 0 deletions sylvia-derive/src/parser.rs
Original file line number Diff line number Diff line change
@@ -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 }),
3 changes: 3 additions & 0 deletions sylvia/src/types.rs
Original file line number Diff line number Diff line change
@@ -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>;
}
21 changes: 20 additions & 1 deletion sylvia/tests/messages_generation.rs
Original file line number Diff line number Diff line change
@@ -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<MyQuery>, _reply: Reply) -> StdResult<Response> {
Ok(Response::new())
}

#[msg(sudo)]
fn no_args_sudo(&self, _ctx: SudoCtx<MyQuery>) -> StdResult<Response> {
Ok(Response::new())
}

#[msg(sudo)]
fn argumented_sudo(&self, _ctx: SudoCtx<MyQuery>, _user: Addr) -> StdResult<Response> {
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]