From a26a68eb7e68dd6360d065d0e4dc4e50982d0bbc Mon Sep 17 00:00:00 2001 From: Tomasz Kulik Date: Mon, 24 Jun 2024 15:53:27 +0200 Subject: [PATCH] chore: Update after review. Simplify Executor Builder type --- sylvia-derive/src/executor.rs | 57 ++++++++++++----------- sylvia-derive/src/input.rs | 8 ++-- sylvia-derive/src/querier.rs | 44 ++++++++---------- sylvia/src/types.rs | 86 +++++++++++++---------------------- 4 files changed, 83 insertions(+), 112 deletions(-) diff --git a/sylvia-derive/src/executor.rs b/sylvia-derive/src/executor.rs index 5cf432f2..9e288751 100644 --- a/sylvia-derive/src/executor.rs +++ b/sylvia-derive/src/executor.rs @@ -10,23 +10,23 @@ use crate::message::{MsgField, MsgVariant, MsgVariants}; use crate::parser::attributes::msg::MsgType; use crate::utils::{emit_bracketed_generics, SvCasing}; -pub struct ExecutorMethods<'a, Generic> { - executor_variants: &'a MsgVariants<'a, Generic>, +pub struct InterfaceExecutor<'a, Generic> { + variants: &'a MsgVariants<'a, Generic>, associated_types: &'a AssociatedTypes<'a>, interface_name: &'a Ident, } -impl<'a, Generic> ExecutorMethods<'a, Generic> +impl<'a, Generic> InterfaceExecutor<'a, Generic> where Generic: GetPath + PartialEq + ToTokens, { pub fn new( - executor_variants: &'a MsgVariants<'a, Generic>, + variants: &'a MsgVariants<'a, Generic>, associated_types: &'a AssociatedTypes, interface_name: &'a Ident, ) -> Self { Self { - executor_variants, + variants, associated_types, interface_name, } @@ -35,7 +35,7 @@ where pub fn emit_executor_trait(&self) -> TokenStream { let sylvia = crate_module(); let Self { - executor_variants, + variants, associated_types, interface_name, } = self; @@ -55,12 +55,12 @@ where let executor_api_path = quote! { < Api #bracketed_generics as #sylvia ::types::InterfaceApi>:: #accessor }; - let executor_methods_trait_impl = executor_variants + let methods_trait_impl = variants .variants() .map(|variant| variant.emit_executor_impl(&executor_api_path)) .collect::>(); - let executor_methods_declaration = executor_variants + let executor_methods_declaration = variants .variants() .map(|variant| variant.emit_executor_method_declaration()); @@ -68,19 +68,21 @@ where let where_clause = associated_types.as_where_clause(); quote! { - pub trait Executor<'sv_executor_lifetime> { + pub trait Executor { #(#types_declaration)* #(#executor_methods_declaration)* } - impl <'sv_executor_lifetime, #(#all_generics,)*> Executor<'sv_executor_lifetime> for #sylvia ::types::ExecutorEmptyBuilder<'sv_executor_lifetime, dyn #interface_name <#( #all_generics = #all_generics,)* > > #where_clause { + impl <#(#all_generics,)*> Executor + for #sylvia ::types::ExecutorBuilder<(#sylvia ::types::EmptyExecutorBuilderState, dyn #interface_name <#( #all_generics = #all_generics,)* > ) > #where_clause { #(type #generics = #generics;)* - #(#executor_methods_trait_impl)* + #(#methods_trait_impl)* } - impl <'sv_executor_lifetime, Contract: #interface_name> Executor<'sv_executor_lifetime> for #sylvia ::types::ExecutorEmptyBuilder<'sv_executor_lifetime, Contract> { + impl Executor + for #sylvia ::types::ExecutorBuilder<( #sylvia ::types::EmptyExecutorBuilderState, Contract )> { #(type #generics = :: #generics;)* - #(#executor_methods_trait_impl)* + #(#methods_trait_impl)* } } } @@ -89,19 +91,15 @@ where pub struct ContractExecutor<'a> { generics: Generics, self_ty: Type, - executor_variants: MsgVariants<'a, GenericParam>, + variants: MsgVariants<'a, GenericParam>, } impl<'a> ContractExecutor<'a> { - pub fn new( - generics: Generics, - self_ty: Type, - executor_variants: MsgVariants<'a, GenericParam>, - ) -> Self { + pub fn new(generics: Generics, self_ty: Type, variants: MsgVariants<'a, GenericParam>) -> Self { Self { generics, self_ty, - executor_variants, + variants, } } @@ -110,7 +108,7 @@ impl<'a> ContractExecutor<'a> { let Self { generics, self_ty, - executor_variants, + variants, .. } = self; @@ -121,11 +119,11 @@ impl<'a> ContractExecutor<'a> { let accessor = MsgType::Exec.as_accessor_name(); let executor_api_path = quote! { < #contract as #sylvia ::types::ContractApi>:: #accessor }; - let executor_methods_impl = executor_variants + let executor_methods_impl = variants .variants() .map(|variant| variant.emit_executor_impl(&executor_api_path)); - let executor_methods_declaration = executor_variants + let executor_methods_declaration = variants .variants() .map(|variant| variant.emit_executor_method_declaration()); @@ -140,12 +138,13 @@ impl<'a> ContractExecutor<'a> { .unwrap_or(vec![]); quote! { - pub trait Executor<'sv_executor_lifetime, #(#generics,)*> #where_clause { + pub trait Executor<#(#generics,)*> #where_clause { #(#types_declaration)* #(#executor_methods_declaration)* } - impl <'sv_executor_lifetime, #(#generics,)*> Executor<'sv_executor_lifetime, #(#generics,)*> for #sylvia ::types::ExecutorEmptyBuilder<'sv_executor_lifetime, #contract > #where_clause { + impl <#(#generics,)*> Executor<#(#generics,)*> + for #sylvia ::types::ExecutorBuilder<( #sylvia ::types::EmptyExecutorBuilderState, #contract )> #where_clause { #(#types_implementation)* #(#executor_methods_impl)* } @@ -169,9 +168,9 @@ impl EmitExecutorMethod for MsgVariant<'_> { let variant_name = name.to_case(Case::Snake); quote! { - fn #variant_name(self, #(#parameters),*) -> Result<#sylvia ::types::ExecutorBuilder<'sv_executor_lifetime>, #sylvia ::cw_std::StdError> { - Ok(#sylvia ::types::ExecutorBuilder::<'sv_executor_lifetime>::new( - self.contract(), + fn #variant_name(self, #(#parameters),*) -> Result<#sylvia ::types::ExecutorBuilder< #sylvia ::types::ReadyExecutorBuilderState >, #sylvia ::cw_std::StdError> { + Ok(#sylvia ::types::ExecutorBuilder::<#sylvia ::types::ReadyExecutorBuilderState>::new( + self.contract().to_owned(), self.funds().to_owned(), #sylvia ::cw_std::to_json_binary( & #api_path :: #variant_name (#(#fields_names),*) )?, )) @@ -190,7 +189,7 @@ impl EmitExecutorMethod for MsgVariant<'_> { let variant_name = name.to_case(Case::Snake); quote! { - fn #variant_name(self, #(#parameters),*) -> Result< #sylvia ::types::ExecutorBuilder<'sv_executor_lifetime>, #sylvia ::cw_std::StdError>; + fn #variant_name(self, #(#parameters),*) -> Result< #sylvia ::types::ExecutorBuilder<#sylvia ::types::ReadyExecutorBuilderState>, #sylvia ::cw_std::StdError>; } } } diff --git a/sylvia-derive/src/input.rs b/sylvia-derive/src/input.rs index 86925b9b..46bf8057 100644 --- a/sylvia-derive/src/input.rs +++ b/sylvia-derive/src/input.rs @@ -4,7 +4,7 @@ use quote::quote; use syn::{GenericParam, Ident, ItemImpl, ItemTrait, TraitItem}; use crate::associated_types::{AssociatedTypes, ItemType, EXEC_TYPE, QUERY_TYPE}; -use crate::executor::{ContractExecutor, ExecutorMethods}; +use crate::executor::{ContractExecutor, InterfaceExecutor}; use crate::interfaces::Interfaces; use crate::message::{ ContractApi, ContractEnumMessage, EnumMessage, GlueMessage, InterfaceApi, MsgVariants, @@ -16,7 +16,7 @@ use crate::parser::{ assert_new_method_defined, ContractErrorAttr, Custom, OverrideEntryPoint, ParsedSylviaAttributes, }; -use crate::querier::{ContractQuerier, QuerierMethods}; +use crate::querier::{ContractQuerier, InterfaceQuerier}; use crate::variant_descs::AsVariantDescs; /// Preprocessed `interface` macro input @@ -96,9 +96,9 @@ impl<'a> TraitInput<'a> { MsgVariants::new(item.as_variants(), MsgType::Exec, &associated_names, &None); let query_variants = MsgVariants::new(item.as_variants(), MsgType::Query, &associated_names, &None); - let executor = ExecutorMethods::new(&executor_variants, associated_types, &item.ident) + let executor = InterfaceExecutor::new(&executor_variants, associated_types, &item.ident) .emit_executor_trait(); - let querier = QuerierMethods::new(&query_variants, associated_types, &item.ident) + let querier = InterfaceQuerier::new(&query_variants, associated_types, &item.ident) .emit_querier_trait(); let interface_messages = InterfaceApi::new(item, associated_types, custom).emit(); diff --git a/sylvia-derive/src/querier.rs b/sylvia-derive/src/querier.rs index 5b0274a1..1bdbbce5 100644 --- a/sylvia-derive/src/querier.rs +++ b/sylvia-derive/src/querier.rs @@ -10,23 +10,23 @@ use crate::message::{MsgField, MsgVariant, MsgVariants}; use crate::parser::attributes::msg::MsgType; use crate::utils::{emit_bracketed_generics, SvCasing}; -pub struct QuerierMethods<'a, Generic> { - querier_variants: &'a MsgVariants<'a, Generic>, +pub struct InterfaceQuerier<'a, Generic> { + variants: &'a MsgVariants<'a, Generic>, associated_types: &'a AssociatedTypes<'a>, interface_name: &'a Ident, } -impl<'a, Generic> QuerierMethods<'a, Generic> +impl<'a, Generic> InterfaceQuerier<'a, Generic> where Generic: GetPath + PartialEq + ToTokens, { pub fn new( - querier_variants: &'a MsgVariants<'a, Generic>, + variants: &'a MsgVariants<'a, Generic>, associated_types: &'a AssociatedTypes, interface_name: &'a Ident, ) -> Self { Self { - querier_variants, + variants, associated_types, interface_name, } @@ -35,7 +35,7 @@ where pub fn emit_querier_trait(&self) -> TokenStream { let sylvia = crate_module(); let Self { - querier_variants, + variants, associated_types, interface_name, } = self; @@ -51,15 +51,15 @@ where .collect(); let bracketed_generics = emit_bracketed_generics(&assoc_types); let accessor = MsgType::Query.as_accessor_name(); - let querier_api_path = + let api_path = quote! { < Api #bracketed_generics as #sylvia ::types::InterfaceApi>:: #accessor }; - let querier_methods_trait_impl = querier_variants + let methods_trait_impl = variants .variants() - .map(|variant| variant.emit_querier_impl(&querier_api_path)) + .map(|variant| variant.emit_querier_impl(&api_path)) .collect::>(); - let querier_methods_declaration = querier_variants + let querier_methods_declaration = variants .variants() .map(|variant| variant.emit_querier_method_declaration()); @@ -74,12 +74,12 @@ where impl <'a, C: #sylvia ::cw_std::CustomQuery, #(#all_generics,)*> Querier for #sylvia ::types::BoundQuerier<'a, C, dyn #interface_name <#( #all_generics = #all_generics,)*> > #where_clause { #(type #generics = #generics;)* - #(#querier_methods_trait_impl)* + #(#methods_trait_impl)* } impl <'a, C: #sylvia ::cw_std::CustomQuery, Contract: #interface_name> Querier for #sylvia ::types::BoundQuerier<'a, C, Contract> { #(type #generics = :: #generics;)* - #(#querier_methods_trait_impl)* + #(#methods_trait_impl)* } } } @@ -88,19 +88,15 @@ where pub struct ContractQuerier<'a> { generics: Generics, self_ty: Type, - querier_variants: MsgVariants<'a, GenericParam>, + variants: MsgVariants<'a, GenericParam>, } impl<'a> ContractQuerier<'a> { - pub fn new( - generics: Generics, - self_ty: Type, - querier_variants: MsgVariants<'a, GenericParam>, - ) -> Self { + pub fn new(generics: Generics, self_ty: Type, variants: MsgVariants<'a, GenericParam>) -> Self { Self { generics, self_ty, - querier_variants, + variants, } } @@ -109,7 +105,7 @@ impl<'a> ContractQuerier<'a> { let Self { generics, self_ty, - querier_variants, + variants, .. } = self; @@ -118,13 +114,13 @@ impl<'a> ContractQuerier<'a> { let contract = &self_ty; let accessor = MsgType::Query.as_accessor_name(); - let querier_api_path = quote! { < #contract as #sylvia ::types::ContractApi>:: #accessor }; + let api_path = quote! { < #contract as #sylvia ::types::ContractApi>:: #accessor }; - let querier_methods_impl = querier_variants + let querier_methods_impl = variants .variants() - .map(|variant| variant.emit_querier_impl(&querier_api_path)); + .map(|variant| variant.emit_querier_impl(&api_path)); - let querier_methods_declaration = querier_variants + let querier_methods_declaration = variants .variants() .map(|variant| variant.emit_querier_method_declaration()); diff --git a/sylvia/src/types.rs b/sylvia/src/types.rs index 8c6308dc..d5a8f078 100644 --- a/sylvia/src/types.rs +++ b/sylvia/src/types.rs @@ -160,10 +160,15 @@ impl<'a, C: cosmwasm_std::CustomQuery, Contract> From<&'a BoundQuerier<'a, C, Co } } +pub struct EmptyExecutorBuilderState; +pub struct ReadyExecutorBuilderState; + /// This structure represents a collection of execution methods for /// a Sylvia contract or interface. An instance of this structure /// should be created using a [Remote] object, obtained through the -/// [Remote::executor] method. ExecutorEmptyBuilder implements the +/// [Remote::executor] method. +/// +/// ExecutorEmptyBuilder implements the /// Executor traits generated by the contract and interface macros, /// encompassing all sv::msg(exec) methods of the specified contracts /// and interfaces. @@ -192,7 +197,7 @@ impl<'a, C: cosmwasm_std::CustomQuery, Contract> From<&'a BoundQuerier<'a, C, Co /// } /// } /// -/// use cosmwasm_std::{Addr, Response, StdResult}; +/// use cosmwasm_std::{coin, Addr, Response, StdResult}; /// use cw_storage_plus::Item; /// use sylvia::contract; /// use sylvia::types::{ExecCtx, InstantiateCtx, Remote}; @@ -223,90 +228,61 @@ impl<'a, C: cosmwasm_std::CustomQuery, Contract> From<&'a BoundQuerier<'a, C, Co /// #[sv::msg(exec)] /// fn call_another_contract(&self, ctx: ExecCtx) -> StdResult { /// let remote = self.remote_contract.load(ctx.deps.storage)?; -/// let exec_method = remote.executor().exec_method()?.build(); +/// let exec_method = remote.executor().with_funds(vec![coin(2345, "atom")]).exec_method()?.build(); /// Ok(Response::new().add_message(exec_method)) /// } /// } /// /// # fn main() {} /// ``` -pub struct ExecutorEmptyBuilder<'a, Contract: ?Sized> { - contract: &'a cosmwasm_std::Addr, +pub struct ExecutorBuilder { + contract: String, funds: Vec, - _phantom: std::marker::PhantomData, + msg: Binary, + _state: std::marker::PhantomData, } -impl<'a, Contract: ?Sized> ExecutorEmptyBuilder<'a, Contract> { - pub fn new(contract: &'a cosmwasm_std::Addr) -> Self { +impl ExecutorBuilder<(EmptyExecutorBuilderState, Contract)> { + /// Creates an instance of the structure based + /// on the destination contract's address. + pub fn new(contract: &cosmwasm_std::Addr) -> Self { Self { - contract, + contract: contract.to_string(), funds: vec![], - _phantom: std::marker::PhantomData, + msg: Binary::default(), + _state: std::marker::PhantomData, } } - pub fn contract(&self) -> &'a cosmwasm_std::Addr { - self.contract - } - + /// Adds the funds to the execution message. pub fn with_funds(self, funds: Vec) -> Self { Self { funds, ..self } } + /// Returns funds set in this builder. pub fn funds(&self) -> &Vec { &self.funds } -} -/// This structure is generated by the methods of the Executor trait, -/// created using Sylvia's contract and interface macros. It can then -/// be used to construct a Cosmos message, which is sent to -/// Sylvia contract via the execute endpoint. -/// -/// ```rust -/// pub mod interface { -/// use cosmwasm_std::{Response, StdResult, StdError}; -/// use sylvia::interface; -/// use sylvia::types::ExecCtx; -/// -/// #[interface] -/// pub trait Interface { -/// type Error: From; -/// -/// #[sv::msg(exec)] -/// fn exec_method(&self, ctx: ExecCtx) -> StdResult; -/// } -/// } -/// -/// use interface::Interface; -/// use interface::sv::Executor; -/// use cosmwasm_std::{Addr, Response, StdError, StdResult}; -/// use sylvia::types::Remote; -/// -/// fn execute_method(remote_addr: Addr) -> StdResult { -/// let remote = Remote::<'_, dyn Interface>::new(remote_addr); -/// let msg = remote.executor().exec_method()?.build(); -/// Ok(Response::new().add_message(msg)) -/// } -/// ``` -pub struct ExecutorBuilder<'a> { - contract: &'a cosmwasm_std::Addr, - funds: Vec, - msg: Binary, + /// Returns contract's address represented as [str]. + pub fn contract(&self) -> &str { + &self.contract + } } -impl<'a> ExecutorBuilder<'a> { - pub fn new(contract: &'a cosmwasm_std::Addr, funds: Vec, msg: Binary) -> Self { +impl ExecutorBuilder { + pub fn new(contract: String, funds: Vec, msg: Binary) -> Self { Self { contract, funds, msg, + _state: std::marker::PhantomData, } } pub fn build(self) -> WasmMsg { WasmMsg::Execute { - contract_addr: self.contract.to_string(), + contract_addr: self.contract, msg: self.msg, funds: self.funds, } @@ -426,8 +402,8 @@ impl<'a, Contract: ?Sized> Remote<'a, Contract> { } } - pub fn executor(&self) -> ExecutorEmptyBuilder { - ExecutorEmptyBuilder::new(&self.addr) + pub fn executor(&self) -> ExecutorBuilder<(EmptyExecutorBuilderState, Contract)> { + ExecutorBuilder::<(EmptyExecutorBuilderState, Contract)>::new(&self.addr) } }