1use convert_case::Case;
2use proc_macro2::{Ident, TokenStream};
3use quote::quote;
4use syn::{parse_quote, GenericParam, ItemImpl, Type};
5
6use crate::crate_module;
7use crate::parser::attributes::features::SylviaFeatures;
8use crate::parser::attributes::msg::MsgType;
9use crate::parser::variant_descs::AsVariantDescs;
10use crate::parser::{
11 Custom, FilteredOverrideEntryPoints, OverrideEntryPoint, ParsedSylviaAttributes,
12};
13use crate::types::msg_variant::{MsgVariant, MsgVariants};
14use crate::utils::{emit_bracketed_generics, get_ident_from_type, SvCasing};
15
16pub struct MtHelpers<'a> {
20 error_type: Type,
21 contract_name: &'a Type,
22 source: &'a ItemImpl,
23 generic_params: &'a [&'a GenericParam],
24 where_clause: &'a Option<syn::WhereClause>,
25 custom: &'a Custom,
26 override_entry_points: Vec<OverrideEntryPoint>,
27 sv_features: SylviaFeatures,
28 instantiate_variant: MsgVariants<'a, GenericParam>,
29 exec_variants: MsgVariants<'a, GenericParam>,
30 query_variants: MsgVariants<'a, GenericParam>,
31 migrate_variants: MsgVariants<'a, GenericParam>,
32 reply_variants: MsgVariants<'a, GenericParam>,
33 sudo_variants: MsgVariants<'a, GenericParam>,
34}
35
36impl<'a> MtHelpers<'a> {
37 pub fn new(
38 source: &'a ItemImpl,
39 generic_params: &'a [&'a GenericParam],
40 custom: &'a Custom,
41 override_entry_points: Vec<OverrideEntryPoint>,
42 ) -> Self {
43 let where_clause = &source.generics.where_clause;
44 let instantiate_variant = MsgVariants::new(
45 source.as_variants(),
46 MsgType::Instantiate,
47 generic_params,
48 where_clause,
49 );
50 let exec_variants = MsgVariants::new(
51 source.as_variants(),
52 MsgType::Exec,
53 generic_params,
54 where_clause,
55 );
56 let query_variants = MsgVariants::new(
57 source.as_variants(),
58 MsgType::Query,
59 generic_params,
60 where_clause,
61 );
62 let migrate_variants = MsgVariants::new(
63 source.as_variants(),
64 MsgType::Migrate,
65 generic_params,
66 where_clause,
67 );
68 let reply_variants = MsgVariants::new(
69 source.as_variants(),
70 MsgType::Reply,
71 generic_params,
72 where_clause,
73 );
74 let sudo_variants = MsgVariants::new(
75 source.as_variants(),
76 MsgType::Sudo,
77 generic_params,
78 where_clause,
79 );
80
81 let parsed_attrs = ParsedSylviaAttributes::new(source.attrs.iter());
82 let error_type = parsed_attrs.error_attrs.unwrap_or_default().error;
83 let error_type = parse_quote! { #error_type };
84 let sv_features = parsed_attrs.sv_features;
85
86 let contract_name = &source.self_ty;
87
88 Self {
89 error_type,
90 source,
91 generic_params,
92 where_clause,
93 contract_name,
94 custom,
95 override_entry_points,
96 sv_features,
97 instantiate_variant,
98 exec_variants,
99 query_variants,
100 sudo_variants,
101 migrate_variants,
102 reply_variants,
103 }
104 }
105
106 pub fn emit(&self) -> TokenStream {
107 let Self {
108 error_type,
109 contract_name,
110 custom,
111 exec_variants,
112 query_variants,
113 migrate_variants,
114 sudo_variants,
115 generic_params,
116 where_clause,
117 ..
118 } = self;
119 let sylvia = crate_module();
120
121 let custom_msg = custom.msg_or_default();
122 let mt_app: Type = parse_quote! {
123 #sylvia ::cw_multi_test::App<
124 BankT,
125 ApiT,
126 StorageT,
127 CustomT,
128 WasmT,
129 StakingT,
130 DistrT,
131 IbcT,
132 GovT,
133 >
134 };
135 let api = quote! { < #contract_name as #sylvia ::types::ContractApi> };
136
137 let contract_ident = get_ident_from_type(contract_name);
138 let contract: Type = if !generic_params.is_empty() {
139 parse_quote! { #contract_ident ::< #(#generic_params,)* > }
140 } else {
141 parse_quote! { #contract_ident }
142 };
143 let trait_name = Ident::new(&format!("{}Proxy", contract_ident), contract_ident.span());
144
145 let exec_methods = exec_variants.variants().map(|variant| {
146 variant.emit_mt_method_definition(&custom_msg, &mt_app, error_type, &api)
147 });
148 let query_methods = query_variants.variants().map(|variant| {
149 variant.emit_mt_method_definition(&custom_msg, &mt_app, error_type, &api)
150 });
151 let sudo_methods = sudo_variants.variants().map(|variant| {
152 variant.emit_mt_method_definition(&custom_msg, &mt_app, error_type, &api)
153 });
154 let migrate_methods = migrate_variants.variants().map(|variant| {
155 variant.emit_mt_method_definition(&custom_msg, &mt_app, error_type, &api)
156 });
157
158 let exec_methods_declarations = exec_variants
159 .variants()
160 .map(|variant| variant.emit_mt_method_declaration(&custom_msg, error_type, &api));
161 let query_methods_declarations = query_variants
162 .variants()
163 .map(|variant| variant.emit_mt_method_declaration(&custom_msg, error_type, &api));
164 let sudo_methods_declarations = sudo_variants
165 .variants()
166 .map(|variant| variant.emit_mt_method_declaration(&custom_msg, error_type, &api));
167 let migrate_methods_declarations = migrate_variants
168 .variants()
169 .map(|variant| variant.emit_mt_method_declaration(&custom_msg, error_type, &api));
170
171 let where_predicates = where_clause
172 .as_ref()
173 .map(|where_clause| &where_clause.predicates);
174
175 let impl_contract = self.emit_impl_contract();
176 let code_id = self.emit_code_id();
177 let instantiate_proxy = self.emit_instantiate_proxy(&contract);
178
179 quote! {
180 pub mod mt {
181 use super::*;
182 use #sylvia ::cw_multi_test::Executor;
183
184 pub trait #trait_name <'app, #(#generic_params,)* MtApp >
185 #where_clause
186 {
187 #( #exec_methods_declarations )*
188 #( #migrate_methods_declarations )*
189 #( #query_methods_declarations )*
190 #( #sudo_methods_declarations )*
191 }
192
193 impl<'app, #(#generic_params,)* BankT, ApiT, StorageT, CustomT, WasmT, StakingT, DistrT, IbcT, GovT >
194 #trait_name <'app, #(#generic_params,)* #mt_app >
195 for #sylvia ::multitest::Proxy <'app, #mt_app, #contract_name >
196 where
197 CustomT: #sylvia ::cw_multi_test::Module,
198 CustomT::ExecT: #sylvia::types::CustomMsg + 'static,
199 CustomT::QueryT: #sylvia ::types::CustomQuery + 'static,
200 WasmT: #sylvia ::cw_multi_test::Wasm<CustomT::ExecT, CustomT::QueryT>,
201 BankT: #sylvia ::cw_multi_test::Bank,
202 ApiT: #sylvia ::cw_std::Api,
203 StorageT: #sylvia ::cw_std::Storage,
204 StakingT: #sylvia ::cw_multi_test::Staking,
205 DistrT: #sylvia ::cw_multi_test::Distribution,
206 IbcT: #sylvia ::cw_multi_test::Ibc,
207 GovT: #sylvia ::cw_multi_test::Gov,
208 #mt_app : Executor< #custom_msg >,
209 #where_predicates
210 {
211 #( #exec_methods )*
212 #( #migrate_methods )*
213 #( #query_methods )*
214 #( #sudo_methods )*
215 }
216
217 #impl_contract
218
219 #code_id
220
221 #instantiate_proxy
222 }
223 }
224 }
225
226 fn emit_code_id(&self) -> TokenStream {
227 let sylvia = crate_module();
228 let Self {
229 generic_params,
230 where_clause,
231 contract_name,
232 instantiate_variant,
233 ..
234 } = self;
235
236 let generic_params_lifetimes_replaced =
237 generic_params.iter().cloned().cloned().map(|generic| {
238 if let GenericParam::Lifetime(_) = generic {
239 parse_quote! { '_ }
240 } else {
241 generic
242 }
243 });
244
245 let fields_names = instantiate_variant
246 .get_only_variant()
247 .map(MsgVariant::as_fields_names)
248 .unwrap_or(vec![]);
249
250 let fields = instantiate_variant
251 .get_only_variant()
252 .map(MsgVariant::emit_method_field)
253 .unwrap_or(vec![]);
254
255 let used_generics = instantiate_variant.used_generics();
256
257 let where_predicates = where_clause
258 .as_ref()
259 .map(|where_clause| &where_clause.predicates);
260
261 let contract_ident = get_ident_from_type(contract_name);
262 let contract = if !generic_params.is_empty() {
263 quote! { #contract_ident ::< #(#generic_params,)* > }
264 } else {
265 quote! { #contract_ident }
266 };
267
268 let instantiate_msg = if !used_generics.is_empty() {
269 quote! { InstantiateMsg::< #(#used_generics,)* > }
270 } else {
271 quote! { InstantiateMsg }
272 };
273
274 let custom_msg = self.custom.msg_or_default();
275 let custom_query = self.custom.query_or_default();
276
277 let mt_app = quote! {
278 #sylvia ::cw_multi_test::App<
279 BankT,
280 ApiT,
281 StorageT,
282 CustomT,
283 #sylvia ::cw_multi_test::WasmKeeper< #custom_msg , #custom_query >,
284 StakingT,
285 DistrT,
286 IbcT,
287 GovT,
288 >
289 };
290
291 let code_info = if cfg!(feature = "cosmwasm_1_2") {
292 quote! {
293 pub fn code_info(&self) -> #sylvia ::cw_std::StdResult< #sylvia ::cw_std::CodeInfoResponse> {
294 self.app.querier().query_wasm_code_info(self.code_id)
295 }
296 }
297 } else {
298 quote! {}
299 };
300
301 quote! {
302 pub struct CodeId<'app, Contract, MtApp> {
303 code_id: u64,
304 app: &'app #sylvia ::multitest::App<MtApp>,
305 _phantom: std::marker::PhantomData<Contract>,
306
307 }
308
309 impl<'app, #(#generic_params,)* BankT, ApiT, StorageT, CustomT, StakingT, DistrT, IbcT, GovT > CodeId<'app, #contract, #mt_app >
310 where
311 BankT: #sylvia ::cw_multi_test::Bank,
312 ApiT: #sylvia ::cw_std::Api,
313 StorageT: #sylvia ::cw_std::Storage,
314 CustomT: #sylvia ::cw_multi_test::Module<ExecT = #custom_msg, QueryT = #custom_query >,
315 StakingT: #sylvia ::cw_multi_test::Staking,
316 DistrT: #sylvia ::cw_multi_test::Distribution,
317 IbcT: #sylvia ::cw_multi_test::Ibc,
318 GovT: #sylvia ::cw_multi_test::Gov,
319 #where_predicates
320 {
321 pub fn store_code(app: &'app #sylvia ::multitest::App< #mt_app >) -> Self {
322 let code_id = app
323 .app_mut()
324 .store_code(Box::new( #contract_ident:: < #(#generic_params_lifetimes_replaced),* > ::new() ));
325 Self { code_id, app, _phantom: std::marker::PhantomData::default() }
326 }
327
328 pub fn code_id(&self) -> u64 {
329 self.code_id
330 }
331
332 #code_info
333
334 pub fn instantiate(
335 &self, #(#fields,)*
336 ) -> InstantiateProxy<'_, 'app, #(#generic_params,)* #mt_app > {
337 let msg = #instantiate_msg {#(#fields_names,)*};
338 InstantiateProxy::<'_, 'app, #(#generic_params,)* _> {
339 code_id: self,
340 funds: &[],
341 label: "Contract",
342 admin: None,
343 salt: None,
344 msg,
345 }
346 }
347 }
348 }
349 }
350
351 fn emit_instantiate_proxy(&self, contract: &Type) -> TokenStream {
352 let sylvia = crate_module();
353 let Self {
354 error_type,
355 generic_params,
356 where_clause,
357 contract_name,
358 instantiate_variant,
359 ..
360 } = self;
361
362 let used_generics = instantiate_variant.used_generics();
363 let bracketed_used_generics = emit_bracketed_generics(used_generics);
364
365 let where_predicates = where_clause
366 .as_ref()
367 .map(|where_clause| &where_clause.predicates);
368
369 let custom_msg = self.custom.msg_or_default();
370
371 let instantiate2_body = self.emit_instantiate2_body();
372
373 quote! {
374 pub struct InstantiateProxy<'proxy, 'app, #(#generic_params,)* MtApp> {
375 code_id: &'proxy CodeId <'app, #contract, MtApp>,
376 funds: &'proxy [#sylvia ::cw_std::Coin],
377 label: &'proxy str,
378 admin: Option<String>,
379 salt: Option<&'proxy [u8]>,
380 msg: InstantiateMsg #bracketed_used_generics,
381 }
382
383 impl<'proxy, 'app, #(#generic_params,)* MtApp> InstantiateProxy<'proxy, 'app, #(#generic_params,)* MtApp>
384 where
385 MtApp: Executor< #custom_msg >,
386 #where_predicates
387 {
388 pub fn with_funds(self, funds: &'proxy [#sylvia ::cw_std::Coin]) -> Self {
389 Self { funds, ..self }
390 }
391
392 pub fn with_label(self, label: &'proxy str) -> Self {
393 Self { label, ..self }
394 }
395
396 pub fn with_admin<'sv_admins_lifetime>(self, admin: impl Into<Option<&'sv_admins_lifetime str>>) -> Self {
397 let admin = admin.into().map(str::to_owned);
398 Self { admin, ..self }
399 }
400
401 pub fn with_salt(self, salt: impl Into<Option<&'proxy [u8]>>) -> Self {
402 let salt = salt.into();
403 Self { salt, ..self }
404 }
405
406 #[track_caller]
407 pub fn call(self, sender: &#sylvia ::cw_std::Addr ) -> Result<#sylvia ::multitest::Proxy<'app, MtApp, #contract_name >, #error_type> {
408 let Self {code_id, funds, label, admin, salt, msg} = self;
409
410 match salt {
411 Some(salt) => {
412 #instantiate2_body
413 },
414 None => (*code_id.app)
415 .app_mut()
416 .instantiate_contract(
417 code_id.code_id,
418 sender.clone(),
419 &msg,
420 funds,
421 label,
422 admin,
423 )
424 .map_err(|err| err.downcast().unwrap())
425 .map(|addr| #sylvia ::multitest::Proxy {
426 contract_addr: addr,
427 app: code_id.app,
428 _phantom: std::marker::PhantomData::default(),
429 }),
430 }
431 }
432 }
433 }
434 }
435
436 fn emit_instantiate2_body(&self) -> TokenStream {
437 let Self { error_type, .. } = self;
438 let sylvia = crate_module();
439
440 if cfg!(feature = "cosmwasm_1_2") {
441 quote! {
442 let msg = #sylvia ::cw_std::to_json_binary(&msg)
443 .map_err(Into::< #error_type >::into)?;
444 let sender = #sylvia ::cw_std::Addr::unchecked(sender);
445
446 let msg = #sylvia ::cw_std::WasmMsg::Instantiate2 {
447 admin,
448 code_id: code_id.code_id,
449 msg,
450 funds: funds.to_owned(),
451 label: label.to_owned(),
452 salt: salt.into(),
453 };
454 let app_response = (*code_id.app)
455 .app_mut()
456 .execute(sender.clone(), msg.into())
457 .map_err(|err| err.downcast::< #error_type >().unwrap())?;
458
459 #sylvia:: cw_utils::parse_instantiate_response_data(app_response.data.unwrap().as_slice())
460 .map_err(|err| Into::into( #sylvia ::cw_std::StdError::generic_err(err.to_string())))
461 .map(|data| #sylvia ::multitest::Proxy {
462 contract_addr: #sylvia ::cw_std::Addr::unchecked(data.contract_address),
463 app: code_id.app,
464 _phantom: std::marker::PhantomData::default(),
465 })
466 }
467 } else {
468 quote! {
469 let err = #sylvia ::cw_std::StdError::generic_err(
470 "`with_salt` was called, but it requires `cosmwasm_1_2` feature enabled. Consider removing `with_salt` or adding the `cosmwasm_1_2` feature."
471 );
472 Err(Into::into(err))
473 }
474 }
475 }
476
477 fn emit_impl_contract(&self) -> TokenStream {
478 let Self {
479 source,
480 contract_name,
481 custom,
482 override_entry_points,
483 sv_features,
484 generic_params,
485 migrate_variants,
486 reply_variants,
487 ..
488 } = self;
489 let sylvia = crate_module();
490
491 let bracketed_generics = emit_bracketed_generics(generic_params);
492 let full_where_clause = &source.generics.where_clause;
493
494 let instantiate_body = override_entry_points
495 .get_entry_point(MsgType::Instantiate)
496 .map(OverrideEntryPoint::emit_multitest_dispatch)
497 .unwrap_or_else(|| emit_default_dispatch(&MsgType::Instantiate, contract_name));
498
499 let exec_body = override_entry_points
500 .get_entry_point(MsgType::Exec)
501 .map(OverrideEntryPoint::emit_multitest_dispatch)
502 .unwrap_or_else(|| emit_default_dispatch(&MsgType::Exec, contract_name));
503
504 let query_body = override_entry_points
505 .get_entry_point(MsgType::Query)
506 .map(OverrideEntryPoint::emit_multitest_dispatch)
507 .unwrap_or_else(|| emit_default_dispatch(&MsgType::Query, contract_name));
508
509 let sudo_body = override_entry_points
510 .get_entry_point(MsgType::Sudo)
511 .map(OverrideEntryPoint::emit_multitest_dispatch)
512 .unwrap_or_else(|| emit_default_dispatch(&MsgType::Sudo, contract_name));
513
514 let migrate_body = match override_entry_points.get_entry_point(MsgType::Migrate) {
515 Some(entry_point) => entry_point.emit_multitest_dispatch(),
516 None if migrate_variants.get_only_variant().is_some() => {
517 emit_default_dispatch(&MsgType::Migrate, contract_name)
518 }
519 None => quote! { #sylvia ::anyhow::bail!("migrate not implemented for contract") },
520 };
521
522 let reply_body = match override_entry_points.get_entry_point(MsgType::Reply) {
523 Some(entry_point) => entry_point.emit_multitest_dispatch(),
524 None => reply_variants
525 .get_only_variant()
526 .as_ref()
527 .map(|_reply| {
528 let contract_ident = get_ident_from_type(contract_name);
529 let contract_turbofish = if !generic_params.is_empty() {
530 quote! { #contract_ident ::< #(#generic_params,)* > }
531 } else {
532 quote! { #contract_ident }
533 };
534
535 if sv_features.replies {
536 quote! {
537 let contract = #contract_turbofish ::new();
538 dispatch_reply(deps, env, msg, contract).map_err(Into::into)
539 }
540 } else {
541 let reply_name = _reply.name().to_case(Case::Snake);
542 quote! {
543 self. #reply_name ((deps, env).into(), msg).map_err(Into::into)
544 }
545 }
546 })
547 .unwrap_or_else(|| {
548 quote! {
549 #sylvia ::anyhow::bail!("reply not implemented for contract")
550 }
551 }),
552 };
553
554 let custom_msg = custom.msg_or_default();
555 let custom_query = custom.query_or_default();
556
557 quote! {
558 impl #bracketed_generics #sylvia ::cw_multi_test::Contract<#custom_msg, #custom_query> for #contract_name #full_where_clause {
559 fn execute(
560 &self,
561 deps: #sylvia ::cw_std::DepsMut< #custom_query >,
562 env: #sylvia ::cw_std::Env,
563 info: #sylvia ::cw_std::MessageInfo,
564 msg: Vec<u8>,
565 ) -> #sylvia ::anyhow::Result<#sylvia ::cw_std::Response<#custom_msg>> {
566 #exec_body
567 }
568
569 fn instantiate(
570 &self,
571 deps: #sylvia ::cw_std::DepsMut<#custom_query>,
572 env: #sylvia ::cw_std::Env,
573 info: #sylvia ::cw_std::MessageInfo,
574 msg: Vec<u8>,
575 ) -> #sylvia ::anyhow::Result<#sylvia ::cw_std::Response<#custom_msg>> {
576 #instantiate_body
577 }
578
579 fn query(
580 &self,
581 deps: #sylvia ::cw_std::Deps<#custom_query>,
582 env: #sylvia ::cw_std::Env,
583 msg: Vec<u8>,
584 ) -> #sylvia ::anyhow::Result<#sylvia ::cw_std::Binary> {
585 #query_body
586 }
587
588 fn sudo(
589 &self,
590 deps: #sylvia ::cw_std::DepsMut<#custom_query>,
591 env: #sylvia ::cw_std::Env,
592 msg: Vec<u8>,
593 ) -> #sylvia ::anyhow::Result<#sylvia ::cw_std::Response<#custom_msg>> {
594 #sudo_body
595 }
596
597 fn reply(
598 &self,
599 deps: #sylvia ::cw_std::DepsMut<#custom_query>,
600 env: #sylvia ::cw_std::Env,
601 msg: #sylvia ::cw_std::Reply,
602 ) -> #sylvia ::anyhow::Result<#sylvia ::cw_std::Response<#custom_msg>> {
603 #reply_body
604 }
605
606 fn migrate(
607 &self,
608 deps: #sylvia ::cw_std::DepsMut<#custom_query>,
609 env: #sylvia ::cw_std::Env,
610 msg: Vec<u8>,
611 ) -> #sylvia ::anyhow::Result<#sylvia ::cw_std::Response<#custom_msg>> {
612 #migrate_body
613 }
614 }
615 }
616 }
617}
618
619fn emit_default_dispatch(msg_ty: &MsgType, contract_name: &Type) -> TokenStream {
620 let sylvia = crate_module();
621
622 let values = msg_ty.emit_ctx_values();
623 let msg_name = msg_ty.as_accessor_wrapper_name();
624 let api_msg = quote! { < #contract_name as #sylvia ::types::ContractApi> :: #msg_name };
625
626 quote! {
627 #sylvia ::cw_std::from_json::< #api_msg >(&msg)?
628 .dispatch(self, ( #values ))
629 .map_err(Into::into)
630 }
631}
632
633trait EmitMethods {
634 fn emit_mt_method_definition(
635 &self,
636 custom_msg: &Type,
637 mt_app: &Type,
638 error_type: &Type,
639 api: &TokenStream,
640 ) -> TokenStream;
641
642 fn emit_mt_method_declaration(
643 &self,
644 custom_msg: &Type,
645 error_type: &Type,
646 api: &TokenStream,
647 ) -> TokenStream;
648}
649
650impl EmitMethods for MsgVariant<'_> {
651 fn emit_mt_method_definition(
652 &self,
653 custom_msg: &Type,
654 mt_app: &Type,
655 error_type: &Type,
656 api: &TokenStream,
657 ) -> TokenStream {
658 let sylvia = crate_module();
659
660 let name = self.name();
661 let return_type = self.return_type();
662
663 let params: Vec<_> = self
664 .fields()
665 .iter()
666 .map(|field| field.emit_method_field_folded())
667 .collect();
668 let arguments = self.as_fields_names();
669 let type_name = self.msg_attr().msg_type().as_accessor_name();
670 let name = name.to_case(Case::Snake);
671
672 match self.msg_attr().msg_type() {
673 MsgType::Exec => quote! {
674 #[track_caller]
675 fn #name (&self, #(#params,)* ) -> #sylvia ::multitest::ExecProxy::< #error_type, #api :: #type_name, #mt_app, #custom_msg> {
676 let msg = #api :: #type_name :: #name ( #(#arguments),* );
677
678 #sylvia ::multitest::ExecProxy::new(&self.contract_addr, msg, &self.app)
679 }
680 },
681 MsgType::Query => {
682 quote! {
683 fn #name (&self, #(#params,)* ) -> Result<#return_type, #error_type> {
684 let msg = #api :: #type_name :: #name ( #(#arguments),* );
685
686 (*self.app)
687 .querier()
688 .query_wasm_smart(self.contract_addr.clone(), &msg)
689 .map_err(Into::into)
690 }
691 }
692 }
693 MsgType::Sudo => quote! {
694 fn #name (&self, #(#params,)* ) -> Result< #sylvia ::cw_multi_test::AppResponse, #error_type> {
695 let msg = #api :: #type_name :: #name ( #(#arguments),* );
696
697 (*self.app)
698 .app_mut()
699 .wasm_sudo(self.contract_addr.clone(), &msg)
700 .map_err(|err| err.downcast().unwrap())
701 }
702 },
703 MsgType::Migrate => quote! {
704 #[track_caller]
705 fn #name (&self, #(#params,)* ) -> #sylvia ::multitest::MigrateProxy::< #error_type, #api :: #type_name , #mt_app, #custom_msg> {
706 let msg = #api :: #type_name ::new( #(#arguments),* );
707
708 #sylvia ::multitest::MigrateProxy::new(&self.contract_addr, msg, &self.app)
709 }
710 },
711 _ => quote! {},
712 }
713 }
714
715 fn emit_mt_method_declaration(
716 &self,
717 custom_msg: &Type,
718 error_type: &Type,
719 api: &TokenStream,
720 ) -> TokenStream {
721 let sylvia = crate_module();
722
723 let name = self.name();
724 let return_type = self.return_type();
725
726 let params: Vec<_> = self
727 .fields()
728 .iter()
729 .map(|field| field.emit_method_field_folded())
730 .collect();
731 let type_name = self.msg_attr().msg_type().as_accessor_name();
732 let name = name.to_case(Case::Snake);
733
734 match self.msg_attr().msg_type() {
735 MsgType::Exec => quote! {
736 fn #name (&self, #(#params,)* ) -> #sylvia ::multitest::ExecProxy::< #error_type, #api:: #type_name, MtApp, #custom_msg>;
737 },
738 MsgType::Query => quote! {
739 fn #name (&self, #(#params,)* ) -> Result<#return_type, #error_type>;
740 },
741 MsgType::Sudo => quote! {
742 fn #name (&self, #(#params,)* ) -> Result< #sylvia ::cw_multi_test::AppResponse, #error_type>;
743 },
744 MsgType::Migrate => quote! {
745 #[track_caller]
746 fn #name (&self, #(#params,)* ) -> #sylvia ::multitest::MigrateProxy::< #error_type, #api :: #type_name, MtApp, #custom_msg>;
747 },
748 _ => quote! {},
749 }
750 }
751}