From 86e304e046ef715f66ab7e1e2ffb4b5e32c056e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Wo=C5=BAniak?= Date: Wed, 25 Oct 2023 10:10:59 +0200 Subject: [PATCH] feat: Hide generated interface types in `sv` module --- examples/Cargo.lock | 14 ++++ examples/Cargo.toml | 1 + examples/contracts/custom/src/contract.rs | 4 +- examples/contracts/cw1-subkeys/Cargo.toml | 1 + .../contracts/cw1-subkeys/src/contract.rs | 1 - .../contracts/cw1-subkeys/src/whitelist.rs | 4 +- examples/contracts/cw1-whitelist/Cargo.toml | 1 + .../contracts/cw1-whitelist/src/contract.rs | 25 +++--- examples/contracts/cw1-whitelist/src/lib.rs | 1 - .../contracts/cw1-whitelist/src/multitest.rs | 5 +- .../contracts/cw1-whitelist/src/whitelist.rs | 20 +---- .../interfaces/custom-and-generic/src/lib.rs | 16 ++-- examples/interfaces/cw1/src/lib.rs | 10 +-- examples/interfaces/cw4/src/lib.rs | 2 +- examples/interfaces/generic/src/lib.rs | 16 ++-- examples/interfaces/whitelist/Cargo.toml | 22 ++++++ examples/interfaces/whitelist/src/lib.rs | 76 +++++++++++++++++++ .../whitelist}/src/responses.rs | 0 sylvia-derive/src/input.rs | 13 ++-- sylvia-derive/src/interfaces.rs | 14 ++-- sylvia-derive/src/message.rs | 13 +++- sylvia-derive/src/multitest.rs | 10 ++- sylvia-derive/src/remote.rs | 4 +- sylvia/examples/basic.rs | 19 +++-- sylvia/tests/custom_msg.rs | 55 +++++++++++--- sylvia/tests/custom_query.rs | 59 +++++++++++--- sylvia/tests/dispatching.rs | 10 +-- sylvia/tests/messages_generation.rs | 16 ++-- sylvia/tests/querier.rs | 11 +-- sylvia/tests/query_returns.rs | 2 +- sylvia/tests/remote.rs | 8 +- 31 files changed, 317 insertions(+), 136 deletions(-) create mode 100644 examples/interfaces/whitelist/Cargo.toml create mode 100644 examples/interfaces/whitelist/src/lib.rs rename examples/{contracts/cw1-whitelist => interfaces/whitelist}/src/responses.rs (100%) diff --git a/examples/Cargo.lock b/examples/Cargo.lock index 720c82bf..0d74b403 100644 --- a/examples/Cargo.lock +++ b/examples/Cargo.lock @@ -327,6 +327,7 @@ dependencies = [ "serde", "sylvia", "thiserror", + "whitelist", ] [[package]] @@ -345,6 +346,7 @@ dependencies = [ "serde", "sylvia", "thiserror", + "whitelist", ] [[package]] @@ -1217,6 +1219,18 @@ version = "0.2.86" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed9d5b4305409d1fc9482fee2d7f9bcbf24b3972bf59817ef757e23982242a93" +[[package]] +name = "whitelist" +version = "0.5.0" +dependencies = [ + "anyhow", + "cosmwasm-schema", + "cosmwasm-std", + "cw-multi-test", + "serde", + "sylvia", +] + [[package]] name = "winnow" version = "0.4.6" diff --git a/examples/Cargo.toml b/examples/Cargo.toml index f5b26b33..0becc451 100644 --- a/examples/Cargo.toml +++ b/examples/Cargo.toml @@ -2,6 +2,7 @@ members = [ # Contract intefaces "interfaces/cw1", + "interfaces/whitelist", "interfaces/cw4", "interfaces/cw20-allowances", "interfaces/cw20-minting", diff --git a/examples/contracts/custom/src/contract.rs b/examples/contracts/custom/src/contract.rs index f4d30075..9e19fd4d 100644 --- a/examples/contracts/custom/src/contract.rs +++ b/examples/contracts/custom/src/contract.rs @@ -1,12 +1,12 @@ use cosmwasm_std::{CosmosMsg, QueryRequest, Response, StdResult}; use sylvia::types::{ExecCtx, InstantiateCtx, QueryCtx}; -use sylvia::{contract, entry_points, schemars}; +use sylvia::{contract, schemars}; use crate::messages::{CountResponse, CounterMsg, CounterQuery}; pub struct CustomContract; -#[cfg_attr(not(feature = "mt"), entry_points)] +#[cfg_attr(not(feature = "mt"), sylvia::entry_points)] #[contract] #[sv::custom(query=CounterQuery, msg=CounterMsg)] impl CustomContract { diff --git a/examples/contracts/cw1-subkeys/Cargo.toml b/examples/contracts/cw1-subkeys/Cargo.toml index 12dc5f70..41f8b087 100644 --- a/examples/contracts/cw1-subkeys/Cargo.toml +++ b/examples/contracts/cw1-subkeys/Cargo.toml @@ -18,6 +18,7 @@ cw-multi-test = { version = "0.16.2", optional = true } cw-storage-plus = "1.0" cw-utils = "1.0" cw1 = { path = "../../interfaces/cw1" } +whitelist = { path = "../../interfaces/whitelist" } cw1-whitelist = { path = "../cw1-whitelist", features = ["library"] } cw2 = "1.0" getrandom = { version = "0.2.8", features = ["js"] } diff --git a/examples/contracts/cw1-subkeys/src/contract.rs b/examples/contracts/cw1-subkeys/src/contract.rs index cd86a338..5bd9b49e 100644 --- a/examples/contracts/cw1-subkeys/src/contract.rs +++ b/examples/contracts/cw1-subkeys/src/contract.rs @@ -3,7 +3,6 @@ use cosmwasm_std::{ StakingMsg, StdResult, }; use cw1_whitelist::contract::Cw1WhitelistContract; -use cw1_whitelist::whitelist; use cw2::set_contract_version; use cw_storage_plus::{Bound, Map}; use cw_utils::Expiration; diff --git a/examples/contracts/cw1-subkeys/src/whitelist.rs b/examples/contracts/cw1-subkeys/src/whitelist.rs index c36556a4..eb29e84c 100644 --- a/examples/contracts/cw1-subkeys/src/whitelist.rs +++ b/examples/contracts/cw1-subkeys/src/whitelist.rs @@ -1,8 +1,8 @@ use cosmwasm_std::{Response, StdResult}; -use cw1_whitelist::responses::AdminListResponse; -use cw1_whitelist::whitelist::{self, Whitelist}; use sylvia::contract; use sylvia::types::{ExecCtx, QueryCtx}; +use whitelist::responses::AdminListResponse; +use whitelist::Whitelist; use crate::contract::Cw1SubkeysContract; use crate::error::ContractError; diff --git a/examples/contracts/cw1-whitelist/Cargo.toml b/examples/contracts/cw1-whitelist/Cargo.toml index c307894e..6718fbec 100644 --- a/examples/contracts/cw1-whitelist/Cargo.toml +++ b/examples/contracts/cw1-whitelist/Cargo.toml @@ -22,6 +22,7 @@ cosmwasm-schema = "1.2" serde = { version = "1.0", default-features = false, features = ["derive"] } sylvia = { path = "../../../sylvia" } cw1 = { path = "../../interfaces/cw1" } +whitelist = { path = "../../interfaces/whitelist" } cw-storage-plus = "1.0" thiserror = { version = "1.0" } cw2 = "1.0" diff --git a/examples/contracts/cw1-whitelist/src/contract.rs b/examples/contracts/cw1-whitelist/src/contract.rs index f27bdd82..9f5ae735 100644 --- a/examples/contracts/cw1-whitelist/src/contract.rs +++ b/examples/contracts/cw1-whitelist/src/contract.rs @@ -1,5 +1,4 @@ use crate::error::ContractError; -use crate::whitelist; use cosmwasm_std::{Addr, Deps, Empty, Response}; use cw2::set_contract_version; @@ -57,11 +56,11 @@ impl Cw1WhitelistContract<'_> { #[cfg(test)] mod tests { use super::*; - use crate::responses::AdminListResponse; - use crate::whitelist::{self, Whitelist}; use cosmwasm_std::testing::{mock_dependencies, mock_env, mock_info}; use cosmwasm_std::{coin, coins, to_binary, BankMsg, CosmosMsg, StakingMsg, SubMsg, WasmMsg}; use cw1::Cw1; + use whitelist::responses::AdminListResponse; + use whitelist::Whitelist; #[test] fn instantiate_and_modify_config() { @@ -182,7 +181,7 @@ mod tests { ) .unwrap(); - let freeze = whitelist::ExecMsg::Freeze {}; + let freeze = whitelist::sv::ExecMsg::Freeze {}; let msgs = vec![ BankMsg::Send { to_address: bob.to_string(), @@ -289,15 +288,13 @@ mod tests { } mod msgs { - use super::*; - use cosmwasm_std::{from_binary, from_slice, to_binary, BankMsg}; use crate::contract::{ContractExecMsg, ContractQueryMsg}; #[test] fn freeze() { - let original = whitelist::ExecMsg::Freeze {}; + let original = whitelist::sv::ExecMsg::Freeze {}; let serialized = to_binary(&original).unwrap(); let deserialized = from_binary(&serialized).unwrap(); @@ -309,14 +306,14 @@ mod tests { let deserialized = from_slice(json).unwrap(); assert_eq!( - ContractExecMsg::Whitelist(whitelist::ExecMsg::Freeze {}), + ContractExecMsg::Whitelist(whitelist::sv::ExecMsg::Freeze {}), deserialized ); } #[test] fn update_admins() { - let original = whitelist::ExecMsg::UpdateAdmins { + let original = whitelist::sv::ExecMsg::UpdateAdmins { admins: vec!["admin1".to_owned(), "admin2".to_owned()], }; let serialized = to_binary(&original).unwrap(); @@ -332,7 +329,7 @@ mod tests { let deserialized = from_slice(json).unwrap(); assert_eq!( - ContractExecMsg::Whitelist(whitelist::ExecMsg::UpdateAdmins { + ContractExecMsg::Whitelist(whitelist::sv::ExecMsg::UpdateAdmins { admins: vec!["admin1".to_owned(), "admin3".to_owned()] }), deserialized @@ -341,7 +338,7 @@ mod tests { #[test] fn admin_list() { - let original = whitelist::QueryMsg::AdminList {}; + let original = whitelist::sv::QueryMsg::AdminList {}; let serialized = to_binary(&original).unwrap(); let deserialized = from_binary(&serialized).unwrap(); @@ -353,14 +350,14 @@ mod tests { let deserialized = from_slice(json).unwrap(); assert_eq!( - ContractQueryMsg::Whitelist(whitelist::QueryMsg::AdminList {}), + ContractQueryMsg::Whitelist(whitelist::sv::QueryMsg::AdminList {}), deserialized ); } #[test] fn execute() { - let original = cw1::ExecMsg::Execute { + let original = cw1::sv::ExecMsg::Execute { msgs: vec![BankMsg::Send { to_address: "admin1".to_owned(), amount: vec![], @@ -374,7 +371,7 @@ mod tests { #[test] fn can_execute() { - let original = cw1::QueryMsg::CanExecute { + let original = cw1::sv::QueryMsg::CanExecute { sender: "admin".to_owned(), msg: BankMsg::Send { to_address: "admin1".to_owned(), diff --git a/examples/contracts/cw1-whitelist/src/lib.rs b/examples/contracts/cw1-whitelist/src/lib.rs index cc023ca4..52af57a5 100644 --- a/examples/contracts/cw1-whitelist/src/lib.rs +++ b/examples/contracts/cw1-whitelist/src/lib.rs @@ -3,5 +3,4 @@ mod cw1; pub mod error; #[cfg(any(test, feature = "tests"))] pub mod multitest; -pub mod responses; pub mod whitelist; diff --git a/examples/contracts/cw1-whitelist/src/multitest.rs b/examples/contracts/cw1-whitelist/src/multitest.rs index 9859b6cf..c45e7c04 100644 --- a/examples/contracts/cw1-whitelist/src/multitest.rs +++ b/examples/contracts/cw1-whitelist/src/multitest.rs @@ -1,12 +1,11 @@ #[cfg(test)] mod test { use cosmwasm_std::{to_binary, WasmMsg}; + use whitelist::responses::AdminListResponse; use crate::contract::multitest_utils::CodeId; use crate::cw1::test_utils::Cw1; use crate::error::ContractError; - use crate::responses::AdminListResponse; - use crate::whitelist; use crate::whitelist::test_utils::Whitelist; use assert_matches::assert_matches; use sylvia::multitest::App; @@ -30,7 +29,7 @@ mod test { .call(owner) .unwrap(); - let freeze = whitelist::ExecMsg::Freeze {}; + let freeze = whitelist::sv::ExecMsg::Freeze {}; let freeze = WasmMsg::Execute { contract_addr: second_contract.contract_addr.to_string(), msg: to_binary(&freeze).unwrap(), diff --git a/examples/contracts/cw1-whitelist/src/whitelist.rs b/examples/contracts/cw1-whitelist/src/whitelist.rs index 68e2a79e..156a4af8 100644 --- a/examples/contracts/cw1-whitelist/src/whitelist.rs +++ b/examples/contracts/cw1-whitelist/src/whitelist.rs @@ -1,26 +1,14 @@ use cosmwasm_std::{Empty, Order, Response, StdResult}; +use sylvia::contract; use sylvia::types::{ExecCtx, QueryCtx}; -use sylvia::{contract, interface, schemars}; +use whitelist::responses::AdminListResponse; +use whitelist::Whitelist; use crate::contract::Cw1WhitelistContract; use crate::error::ContractError; -use crate::responses::AdminListResponse; - -#[interface] -pub trait Whitelist { - type Error: From; - - #[msg(exec)] - fn freeze(&self, ctx: ExecCtx) -> Result; - - #[msg(exec)] - fn update_admins(&self, ctx: ExecCtx, admins: Vec) -> Result; - - #[msg(query)] - fn admin_list(&self, ctx: QueryCtx) -> StdResult; -} #[contract(module=crate::contract)] +#[messages(whitelist as Whitelist)] impl Whitelist for Cw1WhitelistContract<'_> { type Error = ContractError; diff --git a/examples/interfaces/custom-and-generic/src/lib.rs b/examples/interfaces/custom-and-generic/src/lib.rs index 134eb77e..80eb0cfd 100644 --- a/examples/interfaces/custom-and-generic/src/lib.rs +++ b/examples/interfaces/custom-and-generic/src/lib.rs @@ -36,33 +36,33 @@ mod tests { use cosmwasm_std::{Addr, CosmosMsg, Empty, QuerierWrapper}; use sylvia::types::{InterfaceMessages, SvCustomMsg}; - use crate::Querier; + use crate::sv::Querier; #[test] fn construct_messages() { let contract = Addr::unchecked("contract"); // Direct message construction - let _ = super::QueryMsg::<_, Empty>::custom_generic_query(SvCustomMsg {}); - let _ = super::ExecMsg::custom_generic_execute(vec![CosmosMsg::Custom(SvCustomMsg {})]); - let _ = super::ExecMsg::custom_generic_execute(vec![CosmosMsg::Custom(SvCustomMsg {})]); + let _ = super::sv::QueryMsg::<_, Empty>::custom_generic_query(SvCustomMsg {}); + let _ = super::sv::ExecMsg::custom_generic_execute(vec![CosmosMsg::Custom(SvCustomMsg {})]); + let _ = super::sv::ExecMsg::custom_generic_execute(vec![CosmosMsg::Custom(SvCustomMsg {})]); // Querier let deps = mock_dependencies(); let querier_wrapper: QuerierWrapper = QuerierWrapper::new(&deps.querier); - let querier = super::BoundQuerier::borrowed(&contract, &querier_wrapper); + let querier = super::sv::BoundQuerier::borrowed(&contract, &querier_wrapper); let _: Result = - super::Querier::custom_generic_query(&querier, SvCustomMsg {}); + super::sv::Querier::custom_generic_query(&querier, SvCustomMsg {}); let _: Result = querier.custom_generic_query(SvCustomMsg {}); // Construct messages with Interface extension let _ = - as InterfaceMessages>::Query::custom_generic_query( + as InterfaceMessages>::Query::custom_generic_query( SvCustomMsg {}, ); let _= - as InterfaceMessages>::Exec::custom_generic_execute( + as InterfaceMessages>::Exec::custom_generic_execute( vec![ CosmosMsg::Custom(SvCustomMsg{}), ]); } diff --git a/examples/interfaces/cw1/src/lib.rs b/examples/interfaces/cw1/src/lib.rs index 3e12c2e2..46d204b1 100644 --- a/examples/interfaces/cw1/src/lib.rs +++ b/examples/interfaces/cw1/src/lib.rs @@ -36,11 +36,9 @@ pub trait Cw1 { mod tests { use cosmwasm_std::{coins, from_binary, from_slice, to_binary, BankMsg}; - use super::*; - #[test] fn execute() { - let original = ExecMsg::Execute { + let original = super::sv::ExecMsg::Execute { msgs: vec![BankMsg::Send { to_address: "receiver".to_owned(), amount: coins(10, "atom"), @@ -57,12 +55,12 @@ mod tests { #[test] fn execute_from_slice() { let deserialized = from_slice(br#"{"execute": { "msgs": [] }}"#).unwrap(); - assert_eq!(ExecMsg::Execute { msgs: vec![] }, deserialized); + assert_eq!(super::sv::ExecMsg::Execute { msgs: vec![] }, deserialized); } #[test] fn query() { - let original = QueryMsg::CanExecute { + let original = super::sv::QueryMsg::CanExecute { sender: "sender".to_owned(), msg: BankMsg::Send { to_address: "receiver".to_owned(), @@ -99,7 +97,7 @@ mod tests { ) .unwrap(); assert_eq!( - QueryMsg::CanExecute { + super::sv::QueryMsg::CanExecute { sender: "address".to_owned(), msg: BankMsg::Send { to_address: "receiver".to_owned(), diff --git a/examples/interfaces/cw4/src/lib.rs b/examples/interfaces/cw4/src/lib.rs index 4b27dcde..0bb2551a 100644 --- a/examples/interfaces/cw4/src/lib.rs +++ b/examples/interfaces/cw4/src/lib.rs @@ -39,7 +39,7 @@ pub trait Cw4 { mod tests { use cosmwasm_std::{from_binary, from_slice, to_binary}; - use super::*; + use super::sv::*; #[test] fn execute() { diff --git a/examples/interfaces/generic/src/lib.rs b/examples/interfaces/generic/src/lib.rs index 042db389..827067ea 100644 --- a/examples/interfaces/generic/src/lib.rs +++ b/examples/interfaces/generic/src/lib.rs @@ -29,32 +29,32 @@ mod tests { use cosmwasm_std::{testing::mock_dependencies, Addr, CosmosMsg, Empty, QuerierWrapper}; use sylvia::types::{InterfaceMessages, SvCustomMsg}; - use crate::Querier; + use crate::sv::Querier; #[test] fn construct_messages() { let contract = Addr::unchecked("contract"); // Direct message construction - let _ = super::QueryMsg::<_, Empty>::generic_query(SvCustomMsg {}); - let _ = super::ExecMsg::generic_exec(vec![CosmosMsg::Custom(SvCustomMsg {})]); - let _ = super::ExecMsg::generic_exec(vec![CosmosMsg::Custom(SvCustomMsg {})]); + let _ = super::sv::QueryMsg::<_, Empty>::generic_query(SvCustomMsg {}); + let _ = super::sv::ExecMsg::generic_exec(vec![CosmosMsg::Custom(SvCustomMsg {})]); + let _ = super::sv::ExecMsg::generic_exec(vec![CosmosMsg::Custom(SvCustomMsg {})]); // Querier let deps = mock_dependencies(); let querier_wrapper: QuerierWrapper = QuerierWrapper::new(&deps.querier); - let querier = super::BoundQuerier::borrowed(&contract, &querier_wrapper); - let _: Result = super::Querier::generic_query(&querier, SvCustomMsg {}); + let querier = super::sv::BoundQuerier::borrowed(&contract, &querier_wrapper); + let _: Result = super::sv::Querier::generic_query(&querier, SvCustomMsg {}); let _: Result = querier.generic_query(SvCustomMsg {}); // Construct messages with Interface extension let _ = - as InterfaceMessages>::Query::generic_query( + as InterfaceMessages>::Query::generic_query( SvCustomMsg {}, ); let _= - as InterfaceMessages>::Exec::generic_exec(vec![ + as InterfaceMessages>::Exec::generic_exec(vec![ CosmosMsg::Custom(SvCustomMsg{}), ]); } diff --git a/examples/interfaces/whitelist/Cargo.toml b/examples/interfaces/whitelist/Cargo.toml new file mode 100644 index 00000000..5ec641e6 --- /dev/null +++ b/examples/interfaces/whitelist/Cargo.toml @@ -0,0 +1,22 @@ +[package] +name = "whitelist" +version = { workspace = true } +authors = ["Jan Woźniak "] +edition = { workspace = true } +description = "Coverage of whitelist sylvia message generation." +license = "Apache-2.0" +repository = "https://github.com/CosmWasm/sylvia" +homepage = "https://cosmwasm.com" + +[features] +mt = ["sylvia/mt"] + +[dependencies] +cosmwasm-std = { version = "1.3", features = ["staking"] } +cosmwasm-schema = "1.2" +serde = { version = "1.0", default-features = false, features = ["derive"] } +sylvia = { path = "../../../sylvia" } + +[dev-dependencies] +anyhow = "1.0" +cw-multi-test = "0.16" diff --git a/examples/interfaces/whitelist/src/lib.rs b/examples/interfaces/whitelist/src/lib.rs new file mode 100644 index 00000000..34daafe2 --- /dev/null +++ b/examples/interfaces/whitelist/src/lib.rs @@ -0,0 +1,76 @@ +use cosmwasm_std::{Response, StdResult}; +use responses::AdminListResponse; +use sylvia::types::{ExecCtx, QueryCtx}; +use sylvia::{interface, schemars}; + +pub mod responses; + +#[interface] +pub trait Whitelist { + type Error: From; + + #[msg(exec)] + fn freeze(&self, ctx: ExecCtx) -> Result; + + #[msg(exec)] + fn update_admins(&self, ctx: ExecCtx, admins: Vec) -> Result; + + #[msg(query)] + fn admin_list(&self, ctx: QueryCtx) -> StdResult; +} + +#[cfg(test)] +mod tests { + use cosmwasm_std::{from_binary, from_slice, to_binary}; + + use super::*; + + #[test] + fn exec_from_binary() { + let original = sv::ExecMsg::Freeze {}; + + let serialized = to_binary(&original).unwrap(); + let deserialized = from_binary(&serialized).unwrap(); + + assert_eq!(original, deserialized); + + let original = sv::ExecMsg::UpdateAdmins { + admins: vec!["new_admin".to_owned()], + }; + + let serialized = to_binary(&original).unwrap(); + let deserialized = from_binary(&serialized).unwrap(); + + assert_eq!(original, deserialized); + } + + #[test] + fn exec_from_slice() { + let deserialized = from_slice(br#"{"freeze": { }}"#).unwrap(); + assert_eq!(sv::ExecMsg::Freeze {}, deserialized); + + let deserialized = + from_slice(br#"{"update_admins": { "admins": ["new_admin"] }}"#).unwrap(); + assert_eq!( + sv::ExecMsg::UpdateAdmins { + admins: vec!["new_admin".to_owned()] + }, + deserialized + ); + } + + #[test] + fn query_from_binary() { + let original = sv::QueryMsg::AdminList {}; + let serialized = to_binary(&original).unwrap(); + let deserialized = from_binary(&serialized).unwrap(); + + assert_eq!(original, deserialized); + } + + #[test] + fn query_from_slice() { + let deserialized = from_slice(br#"{"admin_list": {}}"#).unwrap(); + assert_eq!(sv::QueryMsg::AdminList {}, deserialized); + } +} diff --git a/examples/contracts/cw1-whitelist/src/responses.rs b/examples/interfaces/whitelist/src/responses.rs similarity index 100% rename from examples/contracts/cw1-whitelist/src/responses.rs rename to examples/interfaces/whitelist/src/responses.rs diff --git a/sylvia-derive/src/input.rs b/sylvia-derive/src/input.rs index 74061b64..7e0ae593 100644 --- a/sylvia-derive/src/input.rs +++ b/sylvia-derive/src/input.rs @@ -82,15 +82,18 @@ impl<'a> TraitInput<'a> { #[cfg(not(tarpaulin_include))] { quote! { - #messages + pub mod sv { + use super::*; + #messages - #multitest_helpers + #multitest_helpers - #remote + #remote - #querier + #querier - #interface_messages + #interface_messages + } } } } diff --git a/sylvia-derive/src/interfaces.rs b/sylvia-derive/src/interfaces.rs index 877edebf..61455b1e 100644 --- a/sylvia-derive/src/interfaces.rs +++ b/sylvia-derive/src/interfaces.rs @@ -46,7 +46,7 @@ impl Interfaces { self.as_modules() .map(|module| { quote! { - impl<'a, C: #sylvia ::cw_std::CustomQuery> From<&'a BoundQuerier<'a, C>> for #module ::BoundQuerier<'a, C> { + impl<'a, C: #sylvia ::cw_std::CustomQuery> From<&'a BoundQuerier<'a, C>> for #module ::sv::BoundQuerier<'a, C> { fn from(querier: &'a BoundQuerier<'a, C>) -> Self { Self::borrowed(querier.contract(), querier.querier()) } @@ -68,8 +68,8 @@ impl Interfaces { ); quote! { - pub fn #method_name (&self) -> #module ::trait_utils:: #proxy_name <'app, #mt_app> { - #module ::trait_utils:: #proxy_name ::new(self.contract_addr.clone(), self.app) + pub fn #method_name (&self) -> #module ::sv::trait_utils:: #proxy_name <'app, #mt_app> { + #module ::sv::trait_utils:: #proxy_name ::new(self.contract_addr.clone(), self.app) } } }) @@ -95,7 +95,7 @@ impl Interfaces { }; let interface_enum = - quote! { <#module ::InterfaceTypes #generics as #sylvia ::types::InterfaceMessages> }; + quote! { <#module ::sv::InterfaceTypes #generics as #sylvia ::types::InterfaceMessages> }; if msg_ty == &MsgType::Query { quote! { #variant ( #interface_enum :: Query) } } else { @@ -114,7 +114,7 @@ impl Interfaces { let ep_name = msg_ty.emit_ep_name(); let messages_fn_name = Ident::new(&format!("{}_messages", ep_name), module.span()); quote! { - &#module :: #messages_fn_name() + &#module ::sv:: #messages_fn_name() } }) .collect() @@ -131,7 +131,7 @@ impl Interfaces { let messages_fn_name = Ident::new(&format!("{}_messages", ep_name), module.span()); quote! { - let msgs = &#module :: #messages_fn_name(); + let msgs = &#module ::sv:: #messages_fn_name(); if msgs.into_iter().any(|msg| msg == &recv_msg_name) { match val.deserialize_into() { Ok(msg) => return Ok(Self:: #variant (msg)), @@ -161,7 +161,7 @@ impl Interfaces { let type_name = msg_ty.as_accessor_name(); quote! { - <#module :: InterfaceTypes #generics as #sylvia ::types::InterfaceMessages> :: #type_name :: response_schemas_impl() + <#module ::sv::InterfaceTypes #generics as #sylvia ::types::InterfaceMessages> :: #type_name :: response_schemas_impl() } }) .collect() diff --git a/sylvia-derive/src/message.rs b/sylvia-derive/src/message.rs index 4af19680..9c299103 100644 --- a/sylvia-derive/src/message.rs +++ b/sylvia-derive/src/message.rs @@ -615,8 +615,13 @@ impl<'a> MsgVariant<'a> { let parameters = fields.iter().map(MsgField::emit_method_field); let fields_names = fields.iter().map(MsgField::name); let variant_name = Ident::new(&name.to_string().to_case(Case::Snake), name.span()); + + // This method is called for `impl Contract` and `impl Trait for Contract` + // In case of first one, `trait_module` will always be `None`. + // In case of the second one, `module` on interface is not an `Option` so it will always be + // `Some` or the compilation will fail earlier. let msg = trait_module - .map(|module| quote! { #module ::QueryMsg }) + .map(|module| quote! { #module ::sv::QueryMsg }) .unwrap_or_else(|| quote! { QueryMsg }); let msg = if !unbonded_generics.is_empty() { @@ -740,7 +745,7 @@ impl<'a> MsgVariant<'a> { let params = fields.iter().map(|field| field.emit_method_field()); let arguments = fields.iter().map(MsgField::name); let bracketed_generics = emit_bracketed_generics(generics); - let interface_enum = quote! { < #module InterfaceTypes #bracketed_generics as #sylvia ::types::InterfaceMessages> }; + let interface_enum = quote! { < #module sv::InterfaceTypes #bracketed_generics as #sylvia ::types::InterfaceMessages> }; let type_name = msg_ty.as_accessor_name(); let name = Ident::new(&name.to_string().to_case(Case::Snake), name.span()); @@ -970,8 +975,8 @@ where .map(|variant| variant.emit_querier_impl(trait_module, used_generics)); let querier = trait_module - .map(|module| quote! { #module ::Querier }) - .unwrap_or_else(|| quote! { Querier }); + .map(|module| quote! { #module ::sv::Querier }) + .unwrap_or_else(|| quote! { sv::Querier }); let bound_querier = contract_module .map(|module| quote! { #module ::BoundQuerier}) .unwrap_or_else(|| quote! { BoundQuerier }); diff --git a/sylvia-derive/src/multitest.rs b/sylvia-derive/src/multitest.rs index b92cac65..3ea3ad8e 100644 --- a/sylvia-derive/src/multitest.rs +++ b/sylvia-derive/src/multitest.rs @@ -17,9 +17,11 @@ fn interface_name(source: &ItemImpl) -> &Ident { unreachable!() }; let (_, Path { segments, .. }, _) = &trait_name; - assert!(!segments.is_empty()); - &segments[0].ident + match segments.last() { + Some(segment) => &segment.ident, + None => unreachable!(), + } } fn extract_contract_name(contract: &Type) -> &Ident { @@ -321,7 +323,7 @@ where }; let bracketed_generics = emit_bracketed_generics(generics); - let interface_enum = quote! { < #module InterfaceTypes #bracketed_generics as #sylvia ::types::InterfaceMessages> }; + let interface_enum = quote! { < #module sv::InterfaceTypes #bracketed_generics as #sylvia ::types::InterfaceMessages> }; let exec_methods = exec_variants.emit_interface_multitest_proxy_methods( &custom_msg, @@ -356,7 +358,7 @@ where #(#exec_methods_declarations)* } - impl #trait_name< #mt_app > for #module trait_utils:: #proxy_name<'_, #mt_app > + impl #trait_name< #mt_app > for #module sv::trait_utils:: #proxy_name<'_, #mt_app > where CustomT: #sylvia ::cw_multi_test::Module, WasmT: #sylvia ::cw_multi_test::Wasm, diff --git a/sylvia-derive/src/remote.rs b/sylvia-derive/src/remote.rs index 4d673f1f..bfe63420 100644 --- a/sylvia-derive/src/remote.rs +++ b/sylvia-derive/src/remote.rs @@ -21,9 +21,9 @@ impl<'a> Remote<'a> { let ContractMessageAttr { module, .. } = interface; quote! { - impl<'a> From<&'a Remote<'a>> for #module ::Remote<'a> { + impl<'a> From<&'a Remote<'a>> for #module ::sv::Remote<'a> { fn from(remote: &'a Remote) -> Self { - #module ::Remote::borrowed(remote.as_ref()) + #module ::sv::Remote::borrowed(remote.as_ref()) } } } diff --git a/sylvia/examples/basic.rs b/sylvia/examples/basic.rs index 07f04d7a..7feb0b98 100644 --- a/sylvia/examples/basic.rs +++ b/sylvia/examples/basic.rs @@ -32,12 +32,11 @@ pub struct MemberResp { } mod group { - use anyhow::Error; use cosmwasm_std::{Response, StdError}; + use sylvia::interface; use sylvia::types::{ExecCtx, QueryCtx}; - use sylvia::{contract, interface}; - use crate::{GroupContract, Member, MemberResp}; + use crate::{Member, MemberResp}; #[interface] pub trait Group { @@ -61,9 +60,19 @@ mod group { #[msg(query)] fn member(&self, ctx: QueryCtx, addr: String) -> Result; } +} + +mod impl_group { + use anyhow::Error; + use cosmwasm_std::Response; + use sylvia::types::{ExecCtx, QueryCtx}; + use sylvia_derive::contract; + + use crate::{GroupContract, MemberResp}; #[contract(module=super)] - impl Group for GroupContract { + #[messages(crate::group as Group)] + impl crate::group::Group for GroupContract { type Error = Error; #[msg(exec)] @@ -80,7 +89,7 @@ mod group { &self, _ctx: ExecCtx, _remove: Vec, - _add: Vec, + _add: Vec, ) -> Result { todo!() } diff --git a/sylvia/tests/custom_msg.rs b/sylvia/tests/custom_msg.rs index 9365ba44..2896b593 100644 --- a/sylvia/tests/custom_msg.rs +++ b/sylvia/tests/custom_msg.rs @@ -21,8 +21,8 @@ pub struct SomeResponse; mod some_interface { use cosmwasm_std::{Response, StdError, StdResult}; + use sylvia::interface; use sylvia::types::{ExecCtx, QueryCtx}; - use sylvia::{contract, interface}; use crate::{MyMsg, SomeResponse}; @@ -39,8 +39,18 @@ mod some_interface { #[msg(exec)] fn interface_exec(&self, ctx: ExecCtx) -> StdResult>; } +} + +mod impl_some_interface { + use cosmwasm_std::{Response, StdError, StdResult}; + use sylvia::contract; + use sylvia::types::{ExecCtx, QueryCtx}; + + use crate::some_interface::SomeInterface; + use crate::{MyMsg, SomeResponse}; #[contract(module=super)] + #[messages(crate::some_interface as SomeInterface)] #[sv::custom(msg=MyMsg)] impl SomeInterface for crate::MyContract { type Error = StdError; @@ -59,10 +69,10 @@ mod some_interface { // Use `#[sv::custom(..)]` if both it and associated type defined mod interface { - use crate::{MyMsg, OtherMsg}; + use crate::MyMsg; use cosmwasm_std::{CustomMsg, Response, StdError, StdResult}; + use sylvia::interface; use sylvia::types::ExecCtx; - use sylvia::{contract, interface}; #[interface] #[sv::custom(msg=MyMsg)] @@ -74,8 +84,16 @@ mod interface { #[msg(exec)] fn exec(&self, ctx: ExecCtx) -> StdResult>; } +} +mod impl_interface { + use crate::interface::Interface; + use crate::{MyMsg, OtherMsg}; + use cosmwasm_std::{Response, StdError, StdResult}; + use sylvia::contract; + use sylvia::types::ExecCtx; #[contract(module=super)] + #[messages(crate::interface as Interface)] #[sv::custom(msg=MyMsg)] impl Interface for crate::MyContract { type Error = StdError; @@ -90,8 +108,8 @@ mod interface { mod other_interface { use cosmwasm_std::{Response, StdError, StdResult}; + use sylvia::interface; use sylvia::types::ExecCtx; - use sylvia::{contract, interface}; #[interface] pub trait OtherInterface { @@ -101,8 +119,15 @@ mod other_interface { #[msg(exec)] fn other_interface_exec(&self, ctx: ExecCtx) -> StdResult; } +} +mod impl_other_interface { + use crate::other_interface::OtherInterface; + use cosmwasm_std::{Response, StdError, StdResult}; + use sylvia::contract; + use sylvia::types::ExecCtx; #[contract(module=super)] + #[messages(crate::other_interface as OtherInterface)] #[sv::custom(msg=crate::MyMsg)] impl OtherInterface for crate::MyContract { type Error = StdError; @@ -115,10 +140,9 @@ mod other_interface { } mod associated_interface { - use crate::MyMsg; use cosmwasm_std::{CustomMsg, Response, StdError, StdResult}; + use sylvia::interface; use sylvia::types::ExecCtx; - use sylvia::{contract, interface}; #[interface] pub trait AssociatedInterface { @@ -129,8 +153,16 @@ mod associated_interface { #[msg(exec)] fn associated_exec(&self, ctx: ExecCtx) -> StdResult>; } +} +mod impl_associated_interface { + use crate::associated_interface::AssociatedInterface; + use crate::MyMsg; + use cosmwasm_std::{Response, StdError, StdResult}; + use sylvia::contract; + use sylvia::types::ExecCtx; #[contract(module=super)] + #[messages(crate::associated_interface as AssociatedInterface)] #[sv::custom(msg=MyMsg)] impl AssociatedInterface for crate::MyContract { type Error = StdError; @@ -179,14 +211,13 @@ impl MyContract { #[cfg(all(test, feature = "mt"))] mod tests { - use crate::interface::test_utils::Interface; + use crate::impl_associated_interface::test_utils::AssociatedInterface; + use crate::impl_interface::test_utils::Interface; + use crate::impl_other_interface::test_utils::OtherInterface; + use crate::impl_some_interface::test_utils::SomeInterface; use crate::MyContract; - use sylvia::multitest::App; - - use crate::associated_interface::test_utils::AssociatedInterface; - use crate::other_interface::test_utils::OtherInterface; - use crate::some_interface::test_utils::SomeInterface; use crate::MyMsg; + use sylvia::multitest::App; #[test] fn test_custom() { diff --git a/sylvia/tests/custom_query.rs b/sylvia/tests/custom_query.rs index cb92e811..8405f873 100644 --- a/sylvia/tests/custom_query.rs +++ b/sylvia/tests/custom_query.rs @@ -20,10 +20,10 @@ pub struct SomeResponse; mod interface { use cosmwasm_std::{CustomQuery, Response, StdError, StdResult}; + use sylvia::interface; use sylvia::types::{ExecCtx, QueryCtx}; - use sylvia::{contract, interface}; - use crate::{MyQuery, OtherQuery, SomeResponse}; + use crate::{MyQuery, SomeResponse}; #[interface] #[sv::custom(query=MyQuery)] @@ -39,10 +39,19 @@ mod interface { #[msg(exec)] fn interface_exec(&self, ctx: ExecCtx) -> StdResult; } +} + +mod impl_interface { + use cosmwasm_std::{Response, StdError, StdResult}; + use sylvia::types::{ExecCtx, QueryCtx}; + use sylvia_derive::contract; + + use crate::{MyQuery, OtherQuery, SomeResponse}; #[contract(module=super)] + #[messages(crate::interface as Interface)] #[sv::custom(query=MyQuery)] - impl Interface for crate::MyContract { + impl crate::interface::Interface for crate::MyContract { type Error = StdError; type QueryC = OtherQuery; @@ -60,8 +69,8 @@ mod interface { mod some_interface { use cosmwasm_std::{Response, StdError, StdResult}; + use sylvia::interface; use sylvia::types::{ExecCtx, QueryCtx}; - use sylvia::{contract, interface}; use crate::{MyQuery, SomeResponse}; @@ -78,10 +87,19 @@ mod some_interface { #[msg(exec)] fn some_interface_exec(&self, ctx: ExecCtx) -> StdResult; } +} + +mod impl_some_interface { + use cosmwasm_std::{Response, StdError, StdResult}; + use sylvia::types::{ExecCtx, QueryCtx}; + use sylvia_derive::contract; + + use crate::{MyQuery, SomeResponse}; #[contract(module=super)] + #[messages(crate::some_interface as SomeInterface)] #[sv::custom(query=MyQuery)] - impl SomeInterface for crate::MyContract { + impl super::some_interface::SomeInterface for crate::MyContract { type Error = StdError; #[msg(query)] @@ -98,10 +116,10 @@ mod some_interface { mod associated_type_interface { use cosmwasm_std::{CustomQuery, Response, StdError, StdResult}; + use sylvia::interface; use sylvia::types::{ExecCtx, QueryCtx}; - use sylvia::{contract, interface}; - use crate::{MyQuery, SomeResponse}; + use crate::SomeResponse; #[interface] pub trait AssociatedTypeInterface { @@ -116,8 +134,16 @@ mod associated_type_interface { #[msg(exec)] fn associated_exec(&self, ctx: ExecCtx) -> StdResult; } +} + +mod impl_associated_type_interface { + use crate::{associated_type_interface::AssociatedTypeInterface, MyQuery, SomeResponse}; + use cosmwasm_std::{Response, StdError, StdResult}; + use sylvia::types::{ExecCtx, QueryCtx}; + use sylvia_derive::contract; #[contract(module=super)] + #[messages(crate::associated_type_interface as AssociatedTypeInterface)] impl AssociatedTypeInterface for crate::MyContract { type Error = StdError; type QueryC = MyQuery; @@ -136,8 +162,8 @@ mod associated_type_interface { mod default_query_interface { use cosmwasm_std::{Response, StdError, StdResult}; + use sylvia::interface; use sylvia::types::{ExecCtx, QueryCtx}; - use sylvia::{contract, interface}; use crate::SomeResponse; @@ -153,8 +179,16 @@ mod default_query_interface { #[msg(exec)] fn default_exec(&self, ctx: ExecCtx) -> StdResult; } +} + +mod impl_default_query_interface { + use crate::{default_query_interface::DefaultQueryInterface, SomeResponse}; + use cosmwasm_std::{Response, StdError, StdResult}; + use sylvia::types::{ExecCtx, QueryCtx}; + use sylvia_derive::contract; #[contract(module=super)] + #[messages(crate::default_query_interface as DefaultQueryInterface)] #[sv::custom(query=MyQuery)] impl DefaultQueryInterface for crate::MyContract { type Error = StdError; @@ -207,10 +241,11 @@ impl MyContract { #[cfg(all(test, feature = "mt"))] mod tests { - use crate::associated_type_interface::test_utils::AssociatedTypeInterface; - use crate::default_query_interface::test_utils::DefaultQueryInterface; - use crate::some_interface::test_utils::SomeInterface; - use crate::{interface::test_utils::Interface, MyContract, MyQuery}; + use crate::impl_associated_type_interface::test_utils::AssociatedTypeInterface; + use crate::impl_default_query_interface::test_utils::DefaultQueryInterface; + use crate::impl_interface::test_utils::Interface; + use crate::impl_some_interface::test_utils::SomeInterface; + use crate::{MyContract, MyQuery}; use cosmwasm_std::Empty; use sylvia::multitest::App; diff --git a/sylvia/tests/dispatching.rs b/sylvia/tests/dispatching.rs index 6858b551..8a1a35b6 100644 --- a/sylvia/tests/dispatching.rs +++ b/sylvia/tests/dispatching.rs @@ -122,12 +122,12 @@ fn dispatch() { let env = mock_env(); let info = mock_info("owner", &[]); - let resp = interface::ExecMsg::NoArgsExecution {} + let resp = interface::sv::ExecMsg::NoArgsExecution {} .dispatch(&contract, (deps.as_mut(), env.clone(), info.clone())) .unwrap(); assert_eq!(resp, Response::new()); - let resp = interface::ExecMsg::ArgumentedExecution { + let resp = interface::sv::ExecMsg::ArgumentedExecution { addr: Addr::unchecked("addr1"), coef: Decimal::percent(30), desc: "True".to_owned(), @@ -136,7 +136,7 @@ fn dispatch() { .unwrap(); assert_eq!(resp, Response::new()); - let resp = interface::ExecMsg::ArgumentedExecution { + let resp = interface::sv::ExecMsg::ArgumentedExecution { addr: Addr::unchecked("addr2"), coef: Decimal::percent(70), desc: "False".to_owned(), @@ -145,12 +145,12 @@ fn dispatch() { .unwrap(); assert_eq!(resp, Response::new()); - let resp = interface::QueryMsg::NoArgsQuery {} + let resp = interface::sv::QueryMsg::NoArgsQuery {} .dispatch(&contract, (deps.as_ref(), env.clone())) .unwrap(); let _resp: EmptyQueryResponse = from_binary(&resp).unwrap(); - let resp = interface::QueryMsg::ArgumentedQuery { + let resp = interface::sv::QueryMsg::ArgumentedQuery { user: Addr::unchecked("addr2"), } .dispatch(&contract, (deps.as_ref(), env)) diff --git a/sylvia/tests/messages_generation.rs b/sylvia/tests/messages_generation.rs index 2495fc69..023c71a5 100644 --- a/sylvia/tests/messages_generation.rs +++ b/sylvia/tests/messages_generation.rs @@ -112,26 +112,26 @@ mod contract { #[test] fn interface_messages_constructible() { - let no_args_exec = interface::ExecMsg::NoArgsExecution {}; - let _argumented_exec = interface::ExecMsg::ArgumentedExecution { + let no_args_exec = interface::sv::ExecMsg::NoArgsExecution {}; + let _argumented_exec = interface::sv::ExecMsg::ArgumentedExecution { addr: Addr::unchecked("owner"), coef: Decimal::percent(10), desc: "Some description".to_owned(), }; - let no_args_query = interface::QueryMsg::NoArgsQuery {}; - let _argumented_query = interface::QueryMsg::ArgumentedQuery { + let no_args_query = interface::sv::QueryMsg::NoArgsQuery {}; + let _argumented_query = interface::sv::QueryMsg::ArgumentedQuery { user: Addr::unchecked("owner"), }; // Ensure no extra variants are generated match no_args_exec { - interface::ExecMsg::NoArgsExecution {} => (), - interface::ExecMsg::ArgumentedExecution { .. } => (), + interface::sv::ExecMsg::NoArgsExecution {} => (), + interface::sv::ExecMsg::ArgumentedExecution { .. } => (), } match no_args_query { - interface::QueryMsg::NoArgsQuery {} => (), - interface::QueryMsg::ArgumentedQuery { .. } => (), + interface::sv::QueryMsg::NoArgsQuery {} => (), + interface::sv::QueryMsg::ArgumentedQuery { .. } => (), } } diff --git a/sylvia/tests/querier.rs b/sylvia/tests/querier.rs index 191e8800..b5c32ed3 100644 --- a/sylvia/tests/querier.rs +++ b/sylvia/tests/querier.rs @@ -14,6 +14,7 @@ pub struct CountResponse { pub mod counter { use cosmwasm_std::{Response, StdError, StdResult}; + use sv::Querier; use sylvia::types::{ExecCtx, QueryCtx}; use sylvia::{contract, interface}; @@ -69,7 +70,7 @@ pub mod counter { #[msg(exec)] fn decrease_by_count(&self, ctx: ExecCtx) -> StdResult { let remote = self.remote.load(ctx.deps.storage)?; - let other_count = BoundQuerier::borrowed(&remote.0, &ctx.deps.querier) + let other_count = sv::BoundQuerier::borrowed(&remote.0, &ctx.deps.querier) .count()? .count; self.count.update(ctx.deps.storage, |count| { @@ -124,16 +125,16 @@ mod tests { let remote_addr = Addr::unchecked("remote"); // Remote generation - let remote = super::counter::Remote::new(remote_addr.clone()); - let _: super::counter::BoundQuerier<_> = remote.querier(&querier_wrapper); + let remote = super::counter::sv::Remote::new(remote_addr.clone()); + let _: super::counter::sv::BoundQuerier<_> = remote.querier(&querier_wrapper); let remote = super::Remote::new(remote_addr.clone()); let _: super::BoundQuerier<_> = remote.querier(&querier_wrapper); // Querier generation - let _ = super::counter::BoundQuerier::borrowed(&remote_addr, &querier_wrapper); + let _ = super::counter::sv::BoundQuerier::borrowed(&remote_addr, &querier_wrapper); let querier = super::BoundQuerier::borrowed(&remote_addr, &querier_wrapper); - let _ = super::counter::BoundQuerier::from(&querier); + let _ = super::counter::sv::BoundQuerier::from(&querier); } #[test] diff --git a/sylvia/tests/query_returns.rs b/sylvia/tests/query_returns.rs index f4dd6d08..9bd63ce9 100644 --- a/sylvia/tests/query_returns.rs +++ b/sylvia/tests/query_returns.rs @@ -62,7 +62,7 @@ mod tests { #[test] fn generate_interface_query() { - let _ = msg::InterfaceQueryMsg::Query { + let _ = msg::sv::InterfaceQueryMsg::Query { name: "some_name".to_owned(), }; } diff --git a/sylvia/tests/remote.rs b/sylvia/tests/remote.rs index 0b61719b..0628e1a9 100644 --- a/sylvia/tests/remote.rs +++ b/sylvia/tests/remote.rs @@ -49,9 +49,9 @@ mod tests { #[test] fn remote_generation() { // interface - let _ = some_interface::Remote::new(Addr::unchecked("some_interface")); + let _ = some_interface::sv::Remote::new(Addr::unchecked("some_interface")); let addr = Addr::unchecked("some_interface"); - let _ = some_interface::Remote::borrowed(&addr); + let _ = some_interface::sv::Remote::borrowed(&addr); // contract let new_remote = crate::Remote::new(Addr::unchecked("some_contract")); @@ -59,7 +59,7 @@ mod tests { let borrowed_remote = crate::Remote::borrowed(&addr); assert_eq!(&Addr::unchecked("some_contract"), borrowed_remote.as_ref()); - let _ = some_interface::Remote::from(&borrowed_remote); - let _ = some_interface::Remote::from(&new_remote); + let _ = some_interface::sv::Remote::from(&borrowed_remote); + let _ = some_interface::sv::Remote::from(&new_remote); } }