cw_extra_protos/lib.rs
1mod utils;
2use quote::{quote, ToTokens};
3use proc_macro::TokenStream;
4use proc_macro2::TokenStream as TokenStream2;
5use syn::{parse_macro_input, AttributeArgs, DeriveInput, NestedMeta};
6use utils::{comp_err, has_generic_t, merge_variants};
7
8
9
10
11
12/// Procedural macro to extend an enum with standardized signature validation variants.
13///
14/// This macro inserts additional variants into a `QueryMsg` enum for signature validation in smart
15/// contracts, as defined in the CW81 specification. It supports an optional custom payload type to
16/// override the default `Binary` type for the `payload` field, which remains wrapped in `Option`.
17///
18/// # Arguments
19///
20/// The macro accepts **zero or one type argument** via the attribute:
21/// - **Payload type** (optional): The type for the `payload` field in the `ValidSignature` and
22/// `ValidSignatures` variants (e.g., `CustomPayload`), wrapped in `Option`. Defaults to
23/// `Option<cosmwasm_std::Binary>` if not provided.
24///
25/// # Generated Variants
26///
27/// The macro inserts the following query variants:
28/// - `ValidSignature`: Verifies a single signature against provided data and an optional payload.
29/// - `ValidSignatures`: Verifies multiple signatures against a list of data and an optional payload
30/// (included due to the `multi` feature).
31///
32/// # Notes
33/// - This is the `multi` feature version, which includes the `ValidSignatures` variant for batch
34/// verification.
35/// - The `#[valid_signature_multi]` attribute must be applied **before** `#[cw_serde]` or other
36/// derive macros.
37/// - The enum must derive `#[derive(QueryResponses)]` from `cosmwasm_schema` to support the
38/// `#[returns(...)]` attributes used in the generated variants.
39///
40/// # Examples
41///
42/// ## Example 1: Basic usage with default payload type
43///
44/// ```rust,ignore
45/// use cw81::valid_signature_multi;
46/// use cosmwasm_schema::{cw_serde, QueryResponses};
47/// use cosmwasm_std::Binary;
48///
49/// #[valid_signature_multi]
50/// #[cw_serde]
51/// #[derive(QueryResponses)]
52/// pub enum QueryMsg {
53/// // User-defined queries
54/// }
55///
56/// // Generated:
57/// // pub enum QueryMsg {
58/// // // User-defined queries
59/// //
60/// // #[returns(::cw81::ValidSignatureResponse)]
61/// // ValidSignature {
62/// // data: ::cosmwasm_std::Binary,
63/// // signature: ::cosmwasm_std::Binary,
64/// // payload: Option<::cosmwasm_std::Binary>,
65/// // },
66/// //
67/// // #[returns(::cw81::ValidSignaturesResponse)]
68/// // ValidSignatures {
69/// // data: Vec<::cosmwasm_std::Binary>,
70/// // signatures: Vec<::cosmwasm_std::Binary>,
71/// // payload: Option<::cosmwasm_std::Binary>,
72/// // },
73/// // }
74/// ```
75///
76/// ## Example 2: Usage with a custom payload type
77///
78/// ```rust,ignore
79/// #[cw_serde]
80/// pub struct CustomPayload {
81/// pub metadata: String,
82/// }
83///
84/// #[valid_signature_multi(CustomPayload)]
85/// #[cw_serde]
86/// #[derive(QueryResponses)]
87/// pub enum QueryMsg {
88/// // User-defined queries
89/// }
90///
91/// // Generated:
92/// // pub enum QueryMsg {
93/// // // User-defined queries
94/// //
95/// // #[returns(::cw81::ValidSignatureResponse)]
96/// // ValidSignature {
97/// // data: ::cosmwasm_std::Binary,
98/// // signature: ::cosmwasm_std::Binary,
99/// // payload: Option<CustomPayload>,
100/// // },
101/// //
102/// // #[returns(::cw81::ValidSignaturesResponse)]
103/// // ValidSignatures {
104/// // data: Vec<::cosmwasm_std::Binary>,
105/// // signatures: Vec<::cosmwasm_std::Binary>,
106/// // payload: Option<CustomPayload>,
107/// // },
108/// // }
109/// ```
110///
111/// # Errors
112///
113/// - Fails with a compile-time error if the attribute argument is invalid (e.g., not a type path or
114/// more than one argument).
115/// - Fails if the input is not a valid enum or if the merge with generated variants cannot be
116/// performed.
117///
118/// This macro is part of the CW81 specification for signature validation.
119#[proc_macro_attribute]
120pub fn valid_signature_multi(metadata: TokenStream, input: TokenStream) -> TokenStream {
121 let args = parse_macro_input!(metadata as AttributeArgs);
122
123 let payload_type = match args.len() {
124 0 => quote!(Option<::cosmwasm_std::Binary>),
125 1 => match &args[0] {
126 NestedMeta::Meta(syn::Meta::Path(path)) => quote!(Option<#path>),
127 other => return comp_err!(other, "Expected a type for the payload, like `CustomPayload`"),
128 },
129 _ => return comp_err!(&args[1], "Expected at most 1 argument"),
130 };
131
132 merge_variants(
133 input,
134 quote! {
135 enum Right {
136 #[returns(::cw81::ValidSignatureResponse)]
137 ValidSignature {
138 data: ::cosmwasm_std::Binary,
139 signature: ::cosmwasm_std::Binary,
140 payload: #payload_type
141 },
142 #[returns(::cw81::ValidSignaturesResponse)]
143 ValidSignatures {
144 data: Vec<::cosmwasm_std::Binary>,
145 signatures: Vec<::cosmwasm_std::Binary>,
146 payload: #payload_type
147 }
148 }
149 }
150 .into(),
151 )
152}
153
154
155/// Procedural macro to extend an enum with a standardized signature validation variant.
156///
157/// This macro inserts a single variant into a `QueryMsg` enum for signature validation in smart
158/// contracts, as defined in the CW81 specification. It supports an optional custom payload type to
159/// override the default `Binary` type for the `payload` field, which remains wrapped in `Option`.
160///
161/// # Arguments
162///
163/// The macro accepts **zero or one type argument** via the attribute:
164/// - **Payload type** (optional): The type for the `payload` field in the `ValidSignature` variant
165/// (e.g., `CustomPayload`), wrapped in `Option`. Defaults to `Option<cosmwasm_std::Binary>` if not
166/// provided.
167///
168/// # Generated Variants
169///
170/// The macro inserts the following query variant:
171/// - `ValidSignature`: Verifies a single signature against provided data and an optional payload.
172///
173/// # Notes
174/// - The `#[valid_signature_one]` attribute must be applied **before** `#[cw_serde]` or other derive
175/// macros.
176/// - The enum must derive `#[derive(QueryResponses)]` from `cosmwasm_schema` to support the
177/// `#[returns(...)]` attributes used in the generated variant.
178/// - This macro is designed for single-signature validation, excluding the `ValidSignatures` variant
179/// included in the `multi` version.
180///
181/// # Examples
182///
183/// ## Example 1: Basic usage with default payload type
184///
185/// ```rust,ignore
186/// use cw81::valid_signature_one;
187/// use cosmwasm_schema::{cw_serde, QueryResponses};
188/// use cosmwasm_std::Binary;
189///
190/// #[valid_signature_one]
191/// #[cw_serde]
192/// #[derive(QueryResponses)]
193/// pub enum QueryMsg {
194/// // User-defined queries
195/// }
196///
197/// // Generated:
198/// // pub enum QueryMsg {
199/// // // User-defined queries
200/// //
201/// // #[returns(::cw81::ValidSignatureResponse)]
202/// // ValidSignature {
203/// // data: ::cosmwasm_std::Binary,
204/// // signature: ::cosmwasm_std::Binary,
205/// // payload: Option<::cosmwasm_std::Binary>,
206/// // },
207/// // }
208/// ```
209///
210/// ## Example 2: Usage with a custom payload type
211///
212/// ```rust,ignore
213/// #[cw_serde]
214/// pub struct CustomPayload {
215/// pub metadata: String,
216/// }
217///
218/// #[valid_signature_one(CustomPayload)]
219/// #[cw_serde]
220/// #[derive(QueryResponses)]
221/// pub enum QueryMsg {
222/// // User-defined queries
223/// }
224///
225/// // Generated:
226/// // pub enum QueryMsg {
227/// // // User-defined queries
228/// //
229/// // #[returns(::cw81::ValidSignatureResponse)]
230/// // ValidSignature {
231/// // data: ::cosmwasm_std::Binary,
232/// // signature: ::cosmwasm_std::Binary,
233/// // payload: Option<CustomPayload>,
234/// // },
235/// // }
236/// ```
237///
238/// # Errors
239///
240/// - Fails with a compile-time error if the attribute argument is invalid (e.g., not a type path or
241/// more than one argument).
242/// - Fails if the input is not a valid enum or if the merge with generated variants cannot be
243/// performed.
244///
245/// This macro is part of the CW81 specification for signature validation.
246#[proc_macro_attribute]
247pub fn valid_signature_one(metadata: TokenStream, input: TokenStream) -> TokenStream {
248 let args = parse_macro_input!(metadata as AttributeArgs);
249
250 let payload_type = match args.len() {
251 0 => quote!(Option<::cosmwasm_std::Binary>),
252 1 => match &args[0] {
253 NestedMeta::Meta(syn::Meta::Path(path)) => quote!(Option<#path>),
254 other => return comp_err!(other, "Expected a type for the payload, like `CustomPayload`"),
255 },
256 _ => return comp_err!(&args[1], "Expected at most 1 argument"),
257 };
258
259 merge_variants(
260 input,
261 quote! {
262 enum Right {
263 #[returns(::cw81::ValidSignatureResponse)]
264 ValidSignature {
265 data: ::cosmwasm_std::Binary,
266 signature: ::cosmwasm_std::Binary,
267 payload: #payload_type
268 },
269 }
270 }
271 .into(),
272 )
273}
274
275
276
277/// Procedural macro to extend an enum with standardized smart account query variants.
278///
279/// This macro checks whether the input enum is generic over `T` and inserts variants accordingly. If
280/// the enum is generic over `T`, the `CanExecute` variant uses `CosmosMsg<T>`; otherwise, it uses the
281/// non-generic `CosmosMsg`. It supports an optional custom payload type to override the default
282/// `Binary` type for the `payload` field, which remains wrapped in `Option`.
283///
284/// This is the `multi` feature version, which includes an additional `ValidSignatures` variant.
285///
286/// # Arguments
287///
288/// The macro accepts **zero or one type argument** via the attribute:
289/// - **Payload type** (optional): The type for the `payload` field in the `ValidSignature` and
290/// `ValidSignatures` variants (e.g., `CustomPayload`), wrapped in `Option`. Defaults to
291/// `Option<cosmwasm_std::Binary>` if not provided.
292///
293/// # Generated Variants
294///
295/// The macro inserts the following query variants:
296/// - `CanExecute`: Queries whether a message can be executed by a smart account.
297/// - `ValidSignature`: Verifies a single signature against provided data and an optional payload.
298/// - `ValidSignatures`: Verifies multiple signatures against a list of data and an optional payload.
299///
300/// # Notes
301/// - The `#[account_query_multi]` attribute must be applied **before** `#[cw_serde]` or other derive
302/// macros.
303/// - The enum must derive `#[derive(QueryResponses)]` from `cosmwasm_schema` to support the
304/// `#[returns(...)]` attributes used in the generated variants.
305/// - This macro is part of the CW82 specification for smart accounts.
306///
307/// # Examples
308///
309/// ## Example 1: Basic usage with default payload type
310///
311/// ```rust,ignore
312/// use cw82::account_query_multi;
313/// use cosmwasm_schema::{cw_serde, QueryResponses};
314/// use cosmwasm_std::{Binary, Empty};
315///
316/// #[account_query_multi]
317/// #[cw_serde]
318/// #[derive(QueryResponses)]
319/// pub enum QueryMsg {
320/// // User-defined queries
321/// }
322///
323/// // Generated:
324/// // pub enum QueryMsg {
325/// // // User-defined queries
326/// //
327/// // #[returns(::cw82::CanExecuteResponse)]
328/// // CanExecute {
329/// // sender: String,
330/// // msg: ::cosmwasm_std::CosmosMsg,
331/// // },
332/// //
333/// // #[returns(::cw82::ValidSignatureResponse)]
334/// // ValidSignature {
335/// // data: ::cosmwasm_std::Binary,
336/// // signature: ::cosmwasm_std::Binary,
337/// // payload: Option<::cosmwasm_std::Binary>,
338/// // },
339/// //
340/// // #[returns(::cw82::ValidSignaturesResponse)]
341/// // ValidSignatures {
342/// // data: Vec<::cosmwasm_std::Binary>,
343/// // signatures: Vec<::cosmwasm_std::Binary>,
344/// // payload: Option<::cosmwasm_std::Binary>,
345/// // },
346/// // }
347/// ```
348///
349/// ## Example 2: Usage with a custom payload type
350///
351/// ```rust,ignore
352/// #[cw_serde]
353/// pub struct CustomPayload {
354/// pub metadata: String,
355/// }
356///
357/// #[account_query_multi(CustomPayload)]
358/// #[cw_serde]
359/// #[derive(QueryResponses)]
360/// pub enum QueryMsg {
361/// // User-defined queries
362/// }
363///
364/// // Generated:
365/// // pub enum QueryMsg {
366/// // // User-defined queries
367/// //
368/// // #[returns(::cw82::CanExecuteResponse)]
369/// // CanExecute {
370/// // sender: String,
371/// // msg: ::cosmwasm_std::CosmosMsg,
372/// // },
373/// //
374/// // #[returns(::cw82::ValidSignatureResponse)]
375/// // ValidSignature {
376/// // data: ::cosmwasm_std::Binary,
377/// // signature: ::cosmwasm_std::Binary,
378/// // payload: Option<CustomPayload>,
379/// // },
380/// //
381/// // #[returns(::cw82::ValidSignaturesResponse)]
382/// // ValidSignatures {
383/// // data: Vec<::cosmwasm_std::Binary>,
384/// // signatures: Vec<::cosmwasm_std::Binary>,
385/// // payload: Option<CustomPayload>,
386/// // },
387/// // }
388/// ```
389///
390/// ## Example 3: Generic enum with custom payload type
391///
392/// ```rust,ignore
393/// #[account_query_multi(CustomPayload)]
394/// #[cw_serde]
395/// #[derive(QueryResponses)]
396/// pub enum QueryMsgCustom<T> {
397/// // User-defined queries
398/// }
399///
400/// // Generated:
401/// // pub enum QueryMsgCustom<T> {
402/// // // User-defined queries
403/// //
404/// // #[returns(::cw82::CanExecuteResponse)]
405/// // CanExecute {
406/// // sender: String,
407/// // msg: ::cosmwasm_std::CosmosMsg<T>,
408/// // },
409/// //
410/// // #[returns(::cw82::ValidSignatureResponse)]
411/// // ValidSignature {
412/// // data: ::cosmwasm_std::Binary,
413/// // signature: ::cosmwasm_std::Binary,
414/// // payload: Option<CustomPayload>,
415/// // },
416/// //
417/// // #[returns(::cw82::ValidSignaturesResponse)]
418/// // ValidSignatures {
419/// // data: Vec<::cosmwasm_std::Binary>,
420/// // signatures: Vec<::cosmwasm_std::Binary>,
421/// // payload: Option<CustomPayload>,
422/// // },
423/// // }
424/// ```
425///
426/// # Errors
427///
428/// - Fails with a compile-time error if the attribute argument is invalid (e.g., not a type path or
429/// more than one argument).
430/// - Fails if the input is not a valid enum or if the merge with generated variants cannot be
431/// performed.
432///
433/// This macro is part of the CW82 specification for smart accounts.
434#[proc_macro_attribute]
435pub fn account_query_multi(metadata: TokenStream, input: TokenStream) -> TokenStream {
436 let args = parse_macro_input!(metadata as AttributeArgs);
437
438 let payload_type = match args.len() {
439 0 => quote!(Option<::cosmwasm_std::Binary>),
440 1 => match &args[0] {
441 NestedMeta::Meta(syn::Meta::Path(path)) => quote!(Option<#path>),
442 other => return comp_err!(other, "Expected a type for the payload, like `CustomPayload`"),
443 },
444 _ => return comp_err!(&args[1], "Expected at most 1 argument"),
445 };
446
447 let cloned = input.clone();
448 let ast: DeriveInput = parse_macro_input!(cloned as DeriveInput);
449 let has_t = has_generic_t(&ast.generics);
450 let msg_type = if has_t {
451 quote!(::cosmwasm_std::CosmosMsg<T>)
452 } else {
453 quote!(::cosmwasm_std::CosmosMsg)
454 };
455
456 let right_enum = quote! {
457 enum Right {
458 #[returns(::cw82::CanExecuteResponse)]
459 CanExecute {
460 sender: String,
461 msg: #msg_type
462 },
463 #[returns(::cw82::ValidSignatureResponse)]
464 ValidSignature {
465 data: ::cosmwasm_std::Binary,
466 signature: ::cosmwasm_std::Binary,
467 payload: #payload_type
468 },
469 #[returns(::cw82::ValidSignaturesResponse)]
470 ValidSignatures {
471 data: Vec<::cosmwasm_std::Binary>,
472 signatures: Vec<::cosmwasm_std::Binary>,
473 payload: #payload_type
474 }
475 }
476 };
477
478 merge_variants(input, right_enum.into())
479}
480
481
482/// Procedural macro to extend an enum with standardized smart account query variants.
483///
484/// This macro checks whether the input enum is generic over `T` and inserts variants accordingly. If
485/// the enum is generic over `T`, the `CanExecute` variant uses `CosmosMsg<T>`; otherwise, it uses the
486/// non-generic `CosmosMsg`. It supports an optional custom payload type to override the default
487/// `Binary` type for the `payload` field, which remains wrapped in `Option`.
488///
489/// # Arguments
490///
491/// The macro accepts **zero or one type argument** via the attribute:
492/// - **Payload type** (optional): The type for the `payload` field in the `ValidSignature` variant
493/// (e.g., `CustomPayload`), wrapped in `Option`. Defaults to `Option<cosmwasm_std::Binary>` if not
494/// provided.
495///
496/// # Generated Variants
497///
498/// The macro inserts the following query variants:
499/// - `CanExecute`: Queries whether a message can be executed by a smart account.
500/// - `ValidSignature`: Verifies a single signature against provided data and an optional payload.
501///
502/// # Notes
503/// - The `#[account_query_one]` attribute must be applied **before** `#[cw_serde]` or other derive
504/// macros.
505/// - The enum must derive `#[derive(QueryResponses)]` from `cosmwasm_schema` to support the
506/// `#[returns(...)]` attributes used in the generated variants.
507/// - This macro is designed for single-signature validation, excluding the `ValidSignatures` variant
508/// included in the `multi` version.
509///
510/// # Examples
511///
512/// ## Example 1: Basic usage with default payload type
513///
514/// ```rust,ignore
515/// use cw82::account_query_one;
516/// use cosmwasm_schema::{cw_serde, QueryResponses};
517/// use cosmwasm_std::{Binary, Empty};
518///
519/// #[account_query_one]
520/// #[cw_serde]
521/// #[derive(QueryResponses)]
522/// pub enum QueryMsg {
523/// // User-defined queries
524/// }
525///
526/// // Generated:
527/// // pub enum QueryMsg {
528/// // // User-defined queries
529/// //
530/// // #[returns(::cw82::CanExecuteResponse)]
531/// // CanExecute {
532/// // sender: String,
533/// // msg: ::cosmwasm_std::CosmosMsg,
534/// // },
535/// //
536/// // #[returns(::cw82::ValidSignatureResponse)]
537/// // ValidSignature {
538/// // data: ::cosmwasm_std::Binary,
539/// // signature: ::cosmwasm_std::Binary,
540/// // payload: Option<::cosmwasm_std::Binary>,
541/// // },
542/// // }
543/// ```
544///
545/// ## Example 2: Usage with a custom payload type
546///
547/// ```rust,ignore
548/// #[cw_serde]
549/// pub struct CustomPayload {
550/// pub metadata: String,
551/// }
552///
553/// #[account_query_one(CustomPayload)]
554/// #[cw_serde]
555/// #[derive(QueryResponses)]
556/// pub enum QueryMsg {
557/// // User-defined queries
558/// }
559///
560/// // Generated:
561/// // pub enum QueryMsg {
562/// // // User-defined queries
563/// //
564/// // #[returns(::cw82::CanExecuteResponse)]
565/// // CanExecute {
566/// // sender: String,
567/// // msg: ::cosmwasm_std::CosmosMsg,
568/// // },
569/// //
570/// // #[returns(::cw82::ValidSignatureResponse)]
571/// // ValidSignature {
572/// // data: ::cosmwasm_std::Binary,
573/// // signature: ::cosmwasm_std::Binary,
574/// // payload: Option<CustomPayload>,
575/// // },
576/// // }
577/// ```
578///
579/// ## Example 3: Generic enum with custom payload type
580///
581/// ```rust,ignore
582/// #[account_query_one(CustomPayload)]
583/// #[cw_serde]
584/// #[derive(QueryResponses)]
585/// pub enum QueryMsgCustom<T> {
586/// // User-defined queries
587/// }
588///
589/// // Generated:
590/// // pub enum QueryMsgCustom<T> {
591/// // // User-defined queries
592/// //
593/// // #[returns(::cw82::CanExecuteResponse)]
594/// // CanExecute {
595/// // sender: String,
596/// // msg: ::cosmwasm_std::CosmosMsg<T>,
597/// // },
598/// //
599/// // #[returns(::cw82::ValidSignatureResponse)]
600/// // ValidSignature {
601/// // data: ::cosmwasm_std::Binary,
602/// // signature: ::cosmwasm_std::Binary,
603/// // payload: Option<CustomPayload>,
604/// // },
605/// // }
606/// ```
607///
608/// # Errors
609///
610/// - Fails with a compile-time error if the attribute argument is invalid (e.g., not a type path or
611/// more than one argument).
612/// - Fails if the input is not a valid enum or if the merge with generated variants cannot be
613/// performed.
614///
615/// This macro is part of the CW82 specification for smart accounts.
616#[proc_macro_attribute]
617pub fn account_query_one(metadata: TokenStream, input: TokenStream) -> TokenStream {
618 let args = parse_macro_input!(metadata as AttributeArgs);
619
620 let payload_type = match args.len() {
621 0 => quote!(Option<::cosmwasm_std::Binary>),
622 1 => match &args[0] {
623 NestedMeta::Meta(syn::Meta::Path(path)) => quote!(Option<#path>),
624 other => return comp_err!(other, "Expected a type for the payload, like `CustomPayload`"),
625 },
626 _ => return comp_err!(&args[1], "Expected at most 1 argument"),
627 };
628
629 let cloned = input.clone();
630 let ast: DeriveInput = parse_macro_input!(cloned as DeriveInput);
631 let has_t = has_generic_t(&ast.generics);
632 let msg_type = if has_t {
633 quote!(::cosmwasm_std::CosmosMsg<T>)
634 } else {
635 quote!(::cosmwasm_std::CosmosMsg)
636 };
637
638 let right_enum = quote! {
639 enum Right {
640 #[returns(::cw82::CanExecuteResponse)]
641 CanExecute {
642 sender: String,
643 msg: #msg_type
644 },
645 #[returns(::cw82::ValidSignatureResponse)]
646 ValidSignature {
647 data: ::cosmwasm_std::Binary,
648 signature: ::cosmwasm_std::Binary,
649 payload: #payload_type
650 }
651 }
652 };
653
654 merge_variants(input, right_enum.into())
655}
656
657
658/// Procedural macro to extend an enum with a standardized smart account execution variant.
659///
660/// This macro checks whether the input enum is generic over `T` and inserts a variant accordingly. If
661/// the enum is generic over `T`, the `Execute` variant uses `CosmosMsg<T>`; otherwise, it uses the
662/// non-generic `CosmosMsg`. The macro is part of the CW82 specification for smart accounts and is
663/// designed to standardize execution interfaces for smart accounts.
664///
665/// # Arguments
666///
667/// The macro does not accept any type arguments via the attribute.
668///
669/// # Generated Variants
670///
671/// The macro inserts the following execute variant:
672/// - `Execute`: Executes a list of `CosmosMsg` messages by a smart account.
673///
674/// # Notes
675/// - The `#[account_execute]` attribute must be applied **before** `#[cw_serde]` or other derive
676/// macros.
677/// - Unlike query macros, this macro does not require `#[derive(QueryResponses)]` since it targets
678/// execute messages.
679/// - This macro is designed for executing multiple `CosmosMsg` messages, suitable for batch
680/// operations in smart accounts.
681///
682/// # Examples
683///
684/// ## Example 1: Basic usage with non-generic enum
685///
686/// ```rust,ignore
687/// use cw82::account_execute;
688/// use cosmwasm_schema::cw_serde;
689///
690/// #[account_execute]
691/// #[cw_serde]
692/// pub enum ExecuteMsg {
693/// // User-defined execute messages
694/// }
695///
696/// // Generated:
697/// // pub enum ExecuteMsg {
698/// // // User-defined execute messages
699/// //
700/// // Execute {
701/// // msgs: Vec<::cosmwasm_std::CosmosMsg>,
702/// // },
703/// // }
704/// ```
705///
706/// ## Example 2: Usage with a generic enum
707///
708/// ```rust,ignore
709/// #[account_execute]
710/// #[cw_serde]
711/// pub enum ExecuteMsgCustom<T> {
712/// // User-defined execute messages
713/// }
714///
715/// // Generated:
716/// // pub enum ExecuteMsgCustom<T> {
717/// // // User-defined execute messages
718/// //
719/// // Execute {
720/// // msgs: Vec<::cosmwasm_std::CosmosMsg<T>>,
721/// // },
722/// // }
723/// ```
724///
725/// # Errors
726///
727/// - Fails with a compile-time error if the input is not a valid enum or if the merge with the
728/// generated variant cannot be performed.
729///
730/// This macro is part of the CW82 specification for smart account execution.
731#[proc_macro_attribute]
732pub fn account_execute(_metadata: TokenStream, input: TokenStream) -> TokenStream {
733 let cloned = input.clone();
734 let ast: DeriveInput = parse_macro_input!(cloned as DeriveInput);
735 let has_t = has_generic_t(&ast.generics);
736 let msg_type = if has_t {
737 quote!(::cosmwasm_std::CosmosMsg<T>)
738 } else {
739 quote!(::cosmwasm_std::CosmosMsg)
740 };
741 let right_enum = quote! {
742 enum Right {
743 Execute {
744 msgs: Vec<#msg_type>,
745 },
746 }
747 };
748 merge_variants(input, right_enum.into())
749}
750
751
752/// Procedural macro to extend an enum with a standardized `CreateAccount` execute variant
753/// for registry-based smart accounts.
754///
755/// This macro injects a `CreateAccount(...)` variant into your execute enum,
756/// where the inner value is `CreateAccountMsg<T>`, a message that allows
757/// creating a smart account with optional registration metadata.
758///
759/// You can optionally specify a single type argument to customize the metadata payload (`T`).
760/// If omitted, the type defaults to `Binary`.
761///
762/// # Examples
763///
764/// ```rust,ignore
765/// use cw83::registry_execute;
766/// use cosmwasm_schema::cw_serde;
767/// use cosmwasm_std::Binary;
768///
769/// #[registry_execute]
770/// #[cw_serde]
771/// pub enum ExecuteMsg {
772/// //
773/// // // user-defined variants
774/// //
775/// }
776///
777/// // Generated:
778/// //
779/// // pub struct CreateAccountMsg {
780/// // pub code_id : u64,
781/// // pub chain_id : String,
782/// // pub account_data : Binary
783/// // }
784///
785/// // pub enum ExecuteMsg {
786/// //
787/// // // user-defined variants
788/// //
789/// //
790/// // CreateAccount(CreateAccountMsg),
791/// // }
792///
793///
794/// // With a custom metadata type:
795///
796/// // types taken from
797/// // pub use smart_account_auth::{CredentialData, Credential};
798///
799/// // mock type
800/// pub struct Credential;
801///
802/// pub struct CredentialData {
803/// pub credentials : Vec<Credential>,
804/// pub with_native : Option<bool>,
805/// pub primary_index : Option<u8>,
806/// }
807///
808/// #[registry_execute(CredentialData)]
809/// #[cw_serde]
810/// pub enum ExecuteMsgData {
811/// //
812/// // // user-defined variants
813/// //
814/// }
815///
816/// // Generated:
817///
818/// // pub struct CreateAccountMsgData {
819/// // pub code_id : u64,
820/// // pub chain_id : String,
821/// // pub account_data : CredentialData
822/// // }
823/// //
824/// // pub enum ExecuteMsgData {
825/// //
826/// // // user-defined variants
827/// //
828/// //
829/// // CreateAccount(CreateAccountMsgData),
830/// // }
831/// ```
832///
833/// This macro is part of the CW83 spec for account registries.
834#[proc_macro_attribute]
835pub fn registry_execute(metadata: TokenStream, input: TokenStream) -> TokenStream {
836 use syn::{parse_macro_input, AttributeArgs, NestedMeta};
837
838 // ✅ Clone first
839 let metadata_clone = metadata.clone();
840
841 // ✅ Then parse using the clone
842 let args = parse_macro_input!(metadata_clone as AttributeArgs);
843
844 // 🧠Extract the custom type or fallback to Binary
845 let custom_type: proc_macro2::TokenStream = if args.is_empty() {
846 quote!(::cosmwasm_std::Binary)
847 } else if args.len() == 1 {
848 match &args[0] {
849 NestedMeta::Meta(syn::Meta::Path(path)) => {
850 quote!(#path)
851 }
852 other => {
853 return syn::Error::new_spanned(
854 other,
855 "Expected a single type name like `CredentialData`",
856 )
857 .to_compile_error()
858 .into();
859 }
860 }
861 } else {
862 return syn::Error::new_spanned(
863 &args[1],
864 "Expected at most one type argument",
865 )
866 .to_compile_error()
867 .into();
868 };
869
870 // ✅ Inject the right variant
871 let right_enum = quote! {
872 enum Right {
873 CreateAccount(::cw83::CreateAccountMsg<#custom_type>)
874 }
875 };
876
877 // ✅ Use original metadata if needed
878 merge_variants( input, right_enum.into())
879}
880
881
882
883
884
885/// Procedural macro for the CW83 standard that injects query variants for account registries into an enum.
886///
887/// # Notes
888/// - This is a version with enabled `multi` flag that adds an additional variant and `Accounts { ... }`
889/// - Requires `#[registry_query]` to be applied applied **before** `#[cw_serde]` or any other derive expressions.
890/// - Your enum must derive `#[derive(QueryResponses)]` so that `#[returns(...)]` are recognized.
891///
892/// # Behavior
893/// This macro generates two Query variants:
894///
895/// ```rust,ignore
896/// #[returns(AccountResponse<T>)]
897/// AccountInfo(QueryType),
898///
899/// #[returns(AccountsResponse<U>)]
900/// Accounts {
901/// query: QueryMultiType,
902/// start_after: Option<String>,
903/// skip: Option<u32>,
904/// limit: Option<u32>,
905/// }
906/// ```
907///
908/// ## Type Parameters
909///
910/// The macro accepts **up to four optional positional type arguments**:
911///
912/// 1. **QueryType** - used as the type for the `AccountInfo(...)` variant
913/// _Defaults to `Binary`_
914///
915/// 2. **InfoType** - used inside `AccountResponse<InfoType>`
916/// _Defaults to `Option<Empty>`_
917///
918/// 3. **QueryMultiType** - used as the query object for `Accounts { query, ... }`
919/// _Defaults to `Option<QueryType>` if `QueryType` is not an `Option<_>`_ and same as `QueryType` otherwise_
920///
921/// 4. **InfoMultiType** - used inside `AccountsResponse<InfoMultiType>`
922/// _Defaults to same as `InfoType`_
923///
924/// ---
925///
926/// ## Example 1: Only a custom query type
927///
928/// ```rust,ignore
929/// pub struct QueryParams {
930/// pub custom_pubkey: Option<Binary>,
931/// }
932///
933/// #[registry_query_multi(QueryParams)]
934/// #[cw_serde]
935/// #[derive(QueryResponses)]
936/// pub enum RegistryQueryMsg {
937/// // custom user-defined queries
938/// }
939/// ```
940///
941/// ### Generated:
942/// ```rust,ignore
943/// #[returns(AccountResponse<Option<Empty>>)]
944/// AccountInfo(QueryParams),
945///
946/// #[returns(AccountsResponse<Option<Empty>>)]
947/// Accounts {
948/// query: Option<QueryParams>,
949/// start_after: Option<String>,
950/// skip: Option<u32>,
951/// limit: Option<u32>,
952/// }
953/// ```
954///
955/// ---
956///
957/// ## Example 2: Custom query and info types
958///
959/// ```rust,ignore
960/// pub struct CustomInfo {
961/// pub eth_address: String,
962/// pub balances: Vec<cosmwasm_std::Coin>,
963/// }
964///
965/// #[registry_query_multi(QueryParams, CustomInfo)]
966/// #[cw_serde]
967/// #[derive(QueryResponses)]
968/// pub enum RegistryQueryMsg {
969/// // custom user-defined queries
970/// }
971/// ```
972///
973/// ### Generated:
974/// ```rust,ignore
975/// #[returns(AccountResponse<CustomInfo>)]
976/// AccountInfo(QueryParams),
977///
978/// #[returns(AccountsResponse<CustomInfo>)]
979/// Accounts {
980/// query: Option<QueryParams>,
981/// start_after: Option<String>,
982/// skip: Option<u32>,
983/// limit: Option<u32>,
984/// }
985/// ```
986///
987/// ---
988///
989/// ## Example 3: Fully customized query & response for single and multi account queries
990///
991/// ```rust,ignore
992/// #[registry_query_multi(QueryParams, CustomInfo, MultiParams, MultiInfo)]
993/// #[cw_serde]
994/// #[derive(QueryResponses)]
995/// pub enum RegistryQueryMsg {
996/// // user-defined queries
997/// }
998/// ```
999///
1000/// ### Generated:
1001/// ```rust,ignore
1002/// #[returns(AccountResponse<CustomInfo>)]
1003/// AccountInfo(QueryParams),
1004///
1005/// #[returns(AccountsResponse<MultiInfo>)]
1006/// Accounts {
1007/// query: MultiParams,
1008/// start_after: Option<String>,
1009/// skip: Option<u32>,
1010/// limit: Option<u32>,
1011/// }
1012/// ```
1013///
1014/// This macro is part of the `CW83` registry spec and can be used to standardize query interfaces across smart accounts.
1015#[proc_macro_attribute]
1016pub fn registry_query_multi(attr: TokenStream, input: TokenStream) -> TokenStream {
1017 let args = parse_macro_input!(attr as AttributeArgs);
1018
1019
1020 // Helper to extract type paths from attributes
1021 let parse_type = |meta: &NestedMeta| {
1022 if let NestedMeta::Meta(syn::Meta::Path(path)) = meta {
1023 Ok(quote!(#path))
1024 } else {
1025 Err(syn::Error::new_spanned(meta, "Expected a type name").to_compile_error())
1026 }
1027 };
1028
1029 let opt_empty = quote!(Option<::cosmwasm_std::Empty>);
1030
1031 let (query_type, res_info_type, query_multi_type, res_info_multi_type) = match args.len() {
1032 0 => (
1033 quote!(::cosmwasm_std::Binary),
1034 opt_empty.clone(),
1035 quote!(Option<::cosmwasm_std::Binary>),
1036 opt_empty
1037 ),
1038 1 => match parse_type(&args[0]) {
1039 Ok(qt) => {
1040 let qt_string = qt.to_string();
1041 let is_option = qt_string.trim_start().starts_with("Option <") || qt_string.trim_start().starts_with("Option<");
1042 let qmt = if is_option {
1043 qt.clone()
1044 } else {
1045 quote!(Option<#qt>)
1046 };
1047 (qt, opt_empty.clone(), qmt, opt_empty)
1048 }
1049 Err(e) => return e.into(),
1050 },
1051 2 => match (parse_type(&args[0]), parse_type(&args[1])) {
1052 (Ok(qt), Ok(rt)) => {
1053 let qt_string = qt.to_string();
1054 let is_option = qt_string.trim_start().starts_with("Option <") || qt_string.trim_start().starts_with("Option<");
1055 let qmt = if is_option {
1056 qt.clone()
1057 } else {
1058 quote!(Option<#qt>)
1059 };
1060 (qt, rt.clone(), qmt, rt)
1061 }
1062 (Err(e1), Err(e2)) => return quote! { #e1 #e2 }.into(),
1063 (Err(e), _) | (_, Err(e)) => return e.into(),
1064 },
1065 3 => match (parse_type(&args[0]), parse_type(&args[1]), parse_type(&args[2])) {
1066 (Ok(qt), Ok(rt), Ok(qmt)) => (qt, rt.clone(), qmt, rt),
1067 _ => return quote! { #( #args.iter().map(parse_type).collect::<Result<Vec<_>, _>>().unwrap_err() )* }.into(),
1068 },
1069 4 => match (
1070 parse_type(&args[0]),
1071 parse_type(&args[1]),
1072 parse_type(&args[2]),
1073 parse_type(&args[3]),
1074 ) {
1075 (Ok(qt), Ok(qmt), Ok(rt), Ok(rmt)) => (qt, qmt, rt, rmt),
1076 (Err(e1), Err(e2), Err(e3), Err(e4)) => return quote! { #e1 #e2 #e3 #e4 }.into(),
1077 (Err(e), ..) | (_, Err(e), ..) | (_, _, Err(e), _) | (_, _, _, Err(e)) => return e.into(),
1078 },
1079 _ => {
1080 return syn::Error::new_spanned(
1081 &args[4],
1082 "Expected at most 4 type arguments: #[registry_query_multi(QueryType, QueryMultiType, InfoType, InfoMultiType)]"
1083 )
1084 .to_compile_error()
1085 .into();
1086 }
1087 };
1088
1089 merge_variants(
1090 input,
1091 quote! {
1092 enum Right {
1093 #[returns(::cw83::AccountResponse<#res_info_type>)]
1094 AccountInfo(#query_type),
1095
1096 #[returns(::cw83::AccountsResponse<#res_info_multi_type>)]
1097 Accounts {
1098 query: #query_multi_type,
1099 start_after: Option<String>,
1100 skip: Option<u32>,
1101 limit: Option<u32>,
1102 }
1103 }
1104 }
1105 .into(),
1106 )
1107}
1108
1109
1110/// Procedural macro for cw83 standard that automatically needed variants for query messages of account registries.
1111///
1112/// # Notes
1113/// - `#[registry_query]` must be applied *before* `#[cw_serde]` or other derives.
1114/// - Enum must have `#[derive(QueryResponses)]` applied to make #[returns] properties valid.
1115///
1116/// This macro injects a `QueryMsg::AccountInfo(...)` variant into your query enum,
1117/// returning an `AccountResponse<T>` that contains metadata about a smart account.
1118///
1119/// Macto takes two optional arguments:
1120/// - The **first type** (optional) is used as the inner query type (e.g., `QueryParams`). Defaults to `Option<Binary>`.
1121/// - The **second type** (optional) is used as the info payload returned by `AccountResponse`. Must be serializable Defaults to `Option<Empty>`.
1122///
1123/// # Examples
1124///
1125/// ```rust,ignore
1126/// use cw83::registry_query;
1127/// use cosmwasm_schema::{cw_serde, QueryResponses};
1128/// use cosmwasm_std::{Binary, Empty};
1129///
1130/// #[registry_query]
1131/// #[cw_serde]
1132/// #[derive(QueryResponses)]
1133/// pub enum RegQuery {
1134/// //
1135/// // // user-defined queries
1136/// //
1137/// }
1138///
1139/// // Generated:
1140/// // pub struct AccountResponse<T> {
1141/// // pub address: String,
1142/// // pub info: Option<T>,
1143/// // }
1144/// //
1145/// // pub enum RegQuery {
1146/// //
1147/// // // user-defined queries
1148/// //
1149/// //
1150/// // #[returns(AccountResponse)]
1151/// // AccountInfo(Option<Empty>),
1152/// // }
1153///
1154///
1155/// // With a custom query type:
1156///
1157/// pub struct QueryParams {
1158/// pub custom_pubkey: Option<Binary>,
1159/// }
1160///
1161/// #[registry_query(QueryParams)]
1162/// #[cw_serde]
1163/// #[derive(QueryResponses)]
1164/// pub enum RegQueryParams {
1165/// //
1166/// // // user-defined queries
1167/// //
1168/// }
1169///
1170/// // Generated:
1171/// // pub enum RegQueryParams {
1172/// //
1173/// // // user-defined queries
1174/// //
1175/// //
1176/// // #[returns(AccountResponse)] // same as above
1177/// // AccountInfo(QueryParams),
1178/// // }
1179///
1180/// // With custom query type and custom info payload:
1181///
1182/// // the macro call requires name only and doesn't support syntax of generics
1183/// type OptionalBin = Option<Binary>;
1184///
1185/// #[registry_query(QueryParams, OptionalBin)]
1186/// #[cw_serde]
1187/// #[derive(QueryResponses)]
1188/// pub enum RegQueryCustom {
1189/// //
1190/// // // user-defined queries
1191/// //
1192/// }
1193///
1194/// // Generated:
1195/// // pub struct AccountResponse {
1196/// // pub address: String,
1197/// // pub info: Option<Binary>, // Binary instead of Empty
1198/// // }
1199/// //
1200/// // pub enum RegQueryCustom {
1201/// //
1202/// // // user-defined queries
1203/// //
1204/// // #[returns(AccountResponse)]
1205/// // AccountInfo(QueryParams),
1206/// // }
1207/// ```
1208///
1209/// This macro is part of the CW83 spec for account registries.
1210#[proc_macro_attribute]
1211pub fn registry_query_one(attr: TokenStream, input: TokenStream) -> TokenStream {
1212 let args = parse_macro_input!(attr as AttributeArgs);
1213
1214 let (query_type, info_type): (TokenStream2, TokenStream2) = match args.len() {
1215 0 => (
1216 quote!(Option<::cosmwasm_std::Binary>),
1217 quote!(Option<::cosmwasm_std::Empty>)
1218 ),
1219 1 => match &args[0] {
1220 NestedMeta::Meta(syn::Meta::Path(path)) => (
1221 quote!(#path),
1222 quote!(Option<::cosmwasm_std::Empty>),
1223 ),
1224 other => {
1225 return syn::Error::new_spanned(other, "Expected a type name")
1226 .to_compile_error()
1227 .into();
1228 }
1229 },
1230 2 => {
1231 let get_path = |meta: &NestedMeta| {
1232 if let NestedMeta::Meta(syn::Meta::Path(path)) = meta {
1233 Ok(quote!(#path))
1234 } else {
1235 Err(syn::Error::new_spanned(meta, "Expected a type name").to_compile_error())
1236 }
1237 };
1238
1239 match (get_path(&args[0]), get_path(&args[1])) {
1240 (Ok(qt), Ok(it)) => (quote!(#qt), quote!(#it)),
1241 (Err(e1), Err(e2)) => return quote! { #e1 #e2 }.into(),
1242 (Err(e), _) | (_, Err(e)) => return e.into(),
1243 }
1244 }
1245 _ => {
1246 return syn::Error::new_spanned(
1247 &args[2],
1248 "Expected at most two type arguments: `#[registry_query(QueryType, InfoType)]`",
1249 )
1250 .to_compile_error()
1251 .into();
1252 }
1253 };
1254
1255 merge_variants(input,
1256 quote! {
1257 enum Right {
1258 #[returns(::cw83::AccountResponse<#info_type>)]
1259 AccountInfo(#query_type)
1260 }
1261 }
1262 .into()
1263 )
1264
1265}
1266
1267
1268
1269
1270
1271
1272/// Procedural macro for the CW84 standard that injects query variants for signed message validation
1273/// into a query enum, supporting generic and non-generic `CosmosMsg` types.
1274///
1275/// This macro extends a query enum with CW84-compliant variants for smart accounts. It checks if the
1276/// enum is generic over `T`, using `CosmosMsg<T>` for `CanExecute` if so, or `CosmosMsg` otherwise.
1277/// It supports custom types for the action message, signed data, and payload, enabling flexible
1278/// signed message validation with the `multi` feature for batch signature verification.
1279///
1280/// # Arguments
1281///
1282/// - **First type** (required): Inner action message type (e.g., `ExecuteMsg`) for `CanExecuteSigned`.
1283/// - **Second type** (optional): Signed data type (e.g., `SignedDataMsg`) for `CanExecuteSigned`.
1284/// Defaults to `cosmwasm_std::Binary`.
1285/// - **Third type** (optional): Payload type (e.g., `CustomPayload`) for `ValidSignature`, wrapped in
1286/// `Option`. Defaults to `Option<cosmwasm_std::Binary>`.
1287/// - **Fourth type** (optional): Payload type (e.g., `CustomMultiPayload`) for `ValidSignatures`,
1288/// wrapped in `Option`. Defaults to the same as the third argument if not provided.
1289///
1290/// # Generated Variants
1291///
1292/// - `CanExecute`: Queries if a `CosmosMsg` can be executed.
1293/// - `CanExecuteSigned`: Queries if signed messages can be executed, using provided types.
1294/// - `ValidSignature`: Verifies a single signature against data and optional payload.
1295/// - `ValidSignatures`: Verifies multiple signatures against data and optional payload (may use different payload type).
1296///
1297/// # Notes
1298///
1299/// - Apply `#[signed_query]` before `#[cw_serde]` or other derives.
1300/// - Enum must derive `#[derive(QueryResponses)]` from `cosmwasm_schema` for `#[returns(...)]`.
1301/// - Part of the CW84 spec for smart account signed message validation.
1302///
1303/// # Examples
1304///
1305/// ## Basic usage
1306///
1307/// ```rust,ignore
1308/// use cosmwasm_schema::{cw_serde, QueryResponses};
1309/// #[cw_serde]
1310/// pub enum ExecuteMsg { Foo {} }
1311/// #[signed_query(ExecuteMsg)]
1312/// #[cw_serde]
1313/// #[derive(QueryResponses)]
1314/// pub enum QueryMsg { /* User queries */ }
1315/// // Generates `CanExecute`, `CanExecuteSigned` (with `Binary` signed), `ValidSignature`, and
1316/// // `ValidSignatures` with `Option<Binary>` payload.
1317/// ```
1318///
1319/// ## Custom types with generic enum
1320///
1321/// ```rust,ignore
1322/// #[cw_serde]
1323/// pub struct SignedDataMsg { pub data: String, pub signature: String }
1324/// #[cw_serde]
1325/// pub struct CustomPayload { pub metadata: String }
1326/// #[signed_query(ExecuteMsg, SignedDataMsg, CustomPayload)]
1327/// #[cw_serde]
1328/// #[derive(QueryResponses)]
1329/// pub enum QueryMsg<T> { /* User queries */ }
1330/// // Generates variants with `CosmosMsg<T>`, `SignedDataMsg` signed, and `Option<CustomPayload>`.
1331/// ```
1332///
1333/// # Errors
1334///
1335/// - Fails if arguments are invalid (e.g., not a type path or wrong count).
1336/// - Fails if input is not a valid enum or variant merge fails.
1337#[proc_macro_attribute]
1338pub fn signed_query_multi(metadata: TokenStream, input: TokenStream) -> TokenStream {
1339 let cloned = input.clone();
1340 let ast: DeriveInput = parse_macro_input!(cloned as DeriveInput);
1341 let has_t = has_generic_t(&ast.generics);
1342
1343 let msg_type = if has_t {
1344 quote!(::cosmwasm_std::CosmosMsg<T>)
1345 } else {
1346 quote!(::cosmwasm_std::CosmosMsg)
1347 };
1348
1349 let args = parse_macro_input!(metadata as AttributeArgs);
1350
1351 let (act_type, sign_type, pl_type, pl_multi_type) = match args.len() {
1352 4 => {
1353 let exec = match &args[0] {
1354 NestedMeta::Meta(syn::Meta::Path(path)) => quote!(#path),
1355 other => return comp_err!(other, "Expected a type for the inner action message, like `ExecuteMsg`"),
1356 };
1357 let signed = match &args[1] {
1358 NestedMeta::Meta(syn::Meta::Path(path)) => quote!(#path),
1359 other => return comp_err!(other, "Expected a type for the signed message, like `SignedDataMsg`"),
1360 };
1361 let payload = match &args[2] {
1362 NestedMeta::Meta(syn::Meta::Path(path)) => quote!(Option<#path>),
1363 other => return comp_err!(other, "Expected a type for the payload, like `CustomPayload`"),
1364 };
1365 let payload_multi = match &args[3] {
1366 NestedMeta::Meta(syn::Meta::Path(path)) => quote!(Option<#path>),
1367 other => return comp_err!(other, "Expected a type for the multi payload, like `CustomMultiPayload`"),
1368 };
1369 (exec, signed, payload, payload_multi)
1370 },
1371 3 => {
1372 let exec = match &args[0] {
1373 NestedMeta::Meta(syn::Meta::Path(path)) => quote!(#path),
1374 other => return comp_err!(other, "Expected a type for the inner action message, like `ExecuteMsg`"),
1375 };
1376 let signed = match &args[1] {
1377 NestedMeta::Meta(syn::Meta::Path(path)) => quote!(#path),
1378 other => return comp_err!(other, "Expected a type for the signed message, like `SignedDataMsg`"),
1379 };
1380 let payload = match &args[2] {
1381 NestedMeta::Meta(syn::Meta::Path(path)) => quote!(Option<#path>),
1382 other => return comp_err!(other, "Expected a type for the payload, like `CustomPayload`"),
1383 };
1384 (exec, signed, payload.clone(), payload)
1385 },
1386 2 => {
1387 let exec = match &args[0] {
1388 NestedMeta::Meta(syn::Meta::Path(path)) => quote!(#path),
1389 other => return comp_err!(other, "Expected a type for the inner action message, like `ExecuteMsg`"),
1390 };
1391 let signed = match &args[1] {
1392 NestedMeta::Meta(syn::Meta::Path(path)) => quote!(#path),
1393 other => return comp_err!(other, "Expected a type for the signed message, like `SignedDataMsg`"),
1394 };
1395 let default_payload = quote!(Option<::cosmwasm_std::Binary>);
1396 (exec, signed, default_payload.clone(), default_payload)
1397 },
1398 1 => match &args[0] {
1399 NestedMeta::Meta(syn::Meta::Path(path)) => {
1400 let default_payload = quote!(Option<::cosmwasm_std::Binary>);
1401 (
1402 quote!(#path),
1403 quote!(::cosmwasm_std::Binary),
1404 default_payload.clone(),
1405 default_payload
1406 )
1407 },
1408 other => return comp_err!(other, "Expected a type for the inner action message, like `ExecuteMsg`"),
1409 },
1410 _ => return comp_err!(&args.get(0), "Expected one to four arguments: `#[signed_query(ExecuteMsg[, SignedDataMsg][, CustomPayload][, CustomMultiPayload])]`"),
1411 };
1412
1413 let right_enum = quote! {
1414 enum Right {
1415 #[returns(::cw84::CanExecuteResponse)]
1416 CanExecute {
1417 sender: String,
1418 msg: #msg_type
1419 },
1420 #[returns(::cw84::CanExecuteResponse)]
1421 CanExecuteNative {
1422 sender: String,
1423 msg: #msg_type
1424 },
1425 #[returns(::cw84::CanExecuteSignedResponse)]
1426 CanExecuteSigned {
1427 msgs: Vec<#act_type>,
1428 signed: #sign_type,
1429 nonce: Option<::cosmwasm_std::Uint64>,
1430 },
1431 #[returns(::cw84::ValidSignatureResponse)]
1432 ValidSignature {
1433 data: ::cosmwasm_std::Binary,
1434 signature: ::cosmwasm_std::Binary,
1435 payload: #pl_type
1436 },
1437 #[returns(::cw84::ValidSignaturesResponse)]
1438 ValidSignatures {
1439 data: Vec<::cosmwasm_std::Binary>,
1440 signatures: Vec<::cosmwasm_std::Binary>,
1441 payload: #pl_multi_type
1442 }
1443 }
1444 };
1445 merge_variants(input, right_enum.into())
1446}
1447
1448
1449
1450/// Procedural macro for the CW84 standard that injects query variants for signed message validation
1451/// into a query enum, supporting generic and non-generic `CosmosMsg` types.
1452///
1453/// This macro extends a query enum with CW84-compliant variants for smart accounts. It checks if the
1454/// enum is generic over `T`, using `CosmosMsg<T>` for `CanExecute` if so, or `CosmosMsg` otherwise.
1455/// It supports custom types for the action message, signed data, and payload, enabling validation of
1456/// a single signed message.
1457///
1458/// # Arguments
1459///
1460/// - **First type** (required): Inner action message type (e.g., `ExecuteMsg`) for `CanExecuteSigned`.
1461/// - **Second type** (optional): Signed data type (e.g., `SignedDataMsg`) for `CanExecuteSigned`.
1462/// Defaults to `cosmwasm_std::Binary`.
1463/// - **Third type** (optional): Payload type (e.g., `CustomPayload`) for `ValidSignature`, wrapped in
1464/// `Option`. Defaults to `Option<cosmwasm_std::Binary>`.
1465///
1466/// # Generated Variants
1467///
1468/// - `CanExecute`: Queries if a `CosmosMsg` can be executed.
1469/// - `CanExecuteSigned`: Queries if a single signed message can be executed, using provided types.
1470/// - `ValidSignature`: Verifies a single signature against data and optional payload.
1471///
1472/// # Notes
1473///
1474/// - Apply `#[signed_query]` before `#[cw_serde]` or other derives.
1475/// - Enum must derive `#[derive(QueryResponses)]` from `cosmwasm_schema` for `#[returns(...)]`.
1476/// - Excludes multi-signature `ValidSignatures` variant, unlike `signed_query_multi`.
1477/// - Part of the CW84 spec for smart account signed message validation.
1478///
1479/// # Examples
1480///
1481/// ## Basic usage
1482///
1483/// ```rust,ignore
1484/// use cosmwasm_schema::{cw_serde, QueryResponses};
1485/// #[cw_serde]
1486/// pub enum ExecuteMsg { Foo {} }
1487/// #[signed_query(ExecuteMsg)]
1488/// #[cw_serde]
1489/// #[derive(QueryResponses)]
1490/// pub enum QueryMsg { /* User queries */ }
1491/// // Generates `CanExecute`, `CanExecuteSigned` (with `Binary` signed), and `ValidSignature` with
1492/// // `Option<Binary>` payload.
1493/// ```
1494///
1495/// ## Custom types with generic enum
1496///
1497/// ```rust,ignore
1498/// #[cw_serde]
1499/// pub struct SignedDataMsg { pub data: String, pub signature: String }
1500/// #[cw_serde]
1501/// pub struct CustomPayload { pub metadata: String }
1502/// #[signed_query(ExecuteMsg, SignedDataMsg, CustomPayload)]
1503/// #[cw_serde]
1504/// #[derive(QueryResponses)]
1505/// pub enum QueryMsg<T> { /* User queries */ }
1506/// // Generates variants with `CosmosMsg<T>`, `SignedDataMsg` signed, and `Option<CustomPayload>`.
1507/// ```
1508///
1509/// # Errors
1510///
1511/// - Fails if arguments are invalid (e.g., not a type path or wrong count).
1512/// - Fails if input is not a valid enum or variant merge fails.
1513#[proc_macro_attribute]
1514pub fn signed_query_one(metadata: TokenStream, input: TokenStream) -> TokenStream {
1515 let cloned = input.clone();
1516 let ast: DeriveInput = parse_macro_input!(cloned as DeriveInput);
1517 let has_t = has_generic_t(&ast.generics);
1518
1519 let msg_type = if has_t {
1520 quote!(::cosmwasm_std::CosmosMsg<T>)
1521 } else {
1522 quote!(::cosmwasm_std::CosmosMsg)
1523 };
1524
1525 let args = parse_macro_input!(metadata as AttributeArgs);
1526
1527 let (exec_type, data_type, payload_type) = match args.len() {
1528 3 => {
1529 let exec = match &args[0] {
1530 NestedMeta::Meta(syn::Meta::Path(path)) => quote!(#path),
1531 other => return comp_err!(other, "Expected a type for the inner action message, like `ExecuteMsg`"),
1532 };
1533 let signed = match &args[1] {
1534 NestedMeta::Meta(syn::Meta::Path(path)) => quote!(#path),
1535 other => return comp_err!(other, "Expected a type for the signed message, like `SignedDataMsg`"),
1536 };
1537 let payload = match &args[2] {
1538 NestedMeta::Meta(syn::Meta::Path(path)) => quote!(Option<#path>),
1539 other => return comp_err!(other, "Expected a type for the payload, like `CustomPayload`"),
1540 };
1541 (exec, signed, payload)
1542 },
1543 2 => {
1544 let exec = match &args[0] {
1545 NestedMeta::Meta(syn::Meta::Path(path)) => quote!(#path),
1546 other => return comp_err!(other, "Expected a type for the inner action message, like `ExecuteMsg`"),
1547 };
1548 let signed = match &args[1] {
1549 NestedMeta::Meta(syn::Meta::Path(path)) => quote!(#path),
1550 other => return comp_err!(other, "Expected a type for the signed message, like `SignedDataMsg`"),
1551 };
1552 (exec, signed, quote!(Option<::cosmwasm_std::Binary>))
1553 },
1554 1 => match &args[0] {
1555 NestedMeta::Meta(syn::Meta::Path(path)) => (
1556 quote!(#path),
1557 quote!(::cosmwasm_std::Binary),
1558 quote!(Option<::cosmwasm_std::Binary>)
1559 ),
1560 other => return comp_err!(other, "Expected a type for the inner action message, like `ExecuteMsg`"),
1561 },
1562 _ => return comp_err!(&args.get(0), "Expected one to three arguments: `#[signed_query(ExecuteMsg[, SignedDataMsg][, CustomPayload])]`"),
1563 };
1564
1565 let right_enum = quote! {
1566 enum Right {
1567 #[returns(::cw84::CanExecuteResponse)]
1568 CanExecute {
1569 sender: String,
1570 msg: #msg_type
1571 },
1572 #[returns(::cw84::CanExecuteResponse)]
1573 CanExecuteNative {
1574 sender: String,
1575 msg: #msg_type
1576 },
1577 #[returns(::cw84::CanExecuteResponse)]
1578 CanExecuteSigned {
1579 msg: #exec_type,
1580 signed: #data_type,
1581 nonce: Option<::cosmwasm_std::Uint64>,
1582 },
1583 #[returns(::cw84::ValidSignatureResponse)]
1584 ValidSignature {
1585 data: ::cosmwasm_std::Binary,
1586 signature: ::cosmwasm_std::Binary,
1587 payload: #payload_type
1588 },
1589 }
1590 };
1591 merge_variants(input, right_enum.into())
1592}
1593
1594
1595
1596/// Procedural macro for the CW84 standard that injects execute variants for signed message execution
1597/// into an execute enum, supporting both generic and non-generic `CosmosMsg` types.
1598///
1599/// This macro extends an enum with standardized execute variants for smart accounts as defined in the
1600/// CW84 specification. It checks if the input enum is generic over `T` and adjusts the `Execute`
1601/// variant to use `CosmosMsg<T>` or `CosmosMsg` accordingly. The macro supports custom types for the
1602/// inner action message and signed data, enabling execution of signed messages with multiple messages.
1603///
1604/// # Arguments
1605///
1606/// The macro accepts **zero to two type arguments** via the attribute:
1607/// - **First type** (optional): The inner action message type (e.g., `ExecuteMsg`) for the
1608/// `ExecuteSigned` and `Native` variants. Defaults to the enum's own type if not provided.
1609/// - **Second type** (optional): The signed data type (e.g., `SignedDataMsg`) for the
1610/// `ExecuteSigned` variant. Defaults to `cw84::Binary` if not provided.
1611///
1612/// # Generated Variants
1613///
1614/// The macro injects the following execute variants:
1615/// - `Execute`: Executes a list of `CosmosMsg` messages by a smart account.
1616/// - `ExecuteSigned`: Executes a list of signed messages, using the provided action and data types.
1617/// - `Native` (only if `exec_type` is specified): Executes a list of messages of the specified
1618/// `exec_type` directly, without requiring signed data.
1619///
1620/// # Notes
1621/// - The `#[signed_execute]` attribute must be applied **before** `#[cw_serde]` or other derive
1622/// macros.
1623/// - Unlike query macros, this macro does not require `#[derive(QueryResponses)]` since it targets
1624/// execute messages.
1625/// - This macro is designed for the `multi` feature, supporting execution of multiple messages.
1626///
1627/// # Examples
1628///
1629/// ## Example 1: Basic usage with no arguments
1630///
1631/// ```rust,ignore
1632/// use cosmwasm_schema::cw_serde;
1633///
1634/// #[cw_serde]
1635/// #[signed_execute]
1636/// pub enum ExecuteMsg {
1637/// // User-defined execute messages
1638/// }
1639///
1640/// // Generated:
1641/// // pub enum ExecuteMsg {
1642/// // // User-defined execute messages
1643/// //
1644/// // Execute {
1645/// // msgs: Vec<::cosmwasm_std::CosmosMsg>,
1646/// // },
1647/// //
1648/// // ExecuteSigned {
1649/// // msgs: Vec<ExecuteMsg>,
1650/// // signed: ::cw84::Binary,
1651/// // nonce: Option<::cosmwasm_std::Uint64>,
1652/// // },
1653/// // }
1654/// ```
1655///
1656/// ## Example 2: Usage with a custom execute message type
1657///
1658/// ```rust,ignore
1659/// #[cw_serde]
1660/// pub enum ActionMsg {
1661/// Foo {},
1662/// }
1663///
1664/// #[signed_execute(ActionMsg)]
1665/// #[cw_serde]
1666/// pub enum ExecuteMsg {
1667/// // User-defined execute messages
1668/// }
1669///
1670/// // Generated:
1671/// // pub enum ExecuteMsg {
1672/// // // User-defined execute messages
1673/// //
1674/// // Execute {
1675/// // msgs: Vec<::cosmwasm_std::CosmosMsg>,
1676/// // },
1677/// //
1678/// // ExecuteSigned {
1679/// // msgs: Vec<ActionMsg>,
1680/// // signed: ::cw84::Binary,
1681/// // nonce: Option<::cosmwasm_std::Uint64>,
1682/// // },
1683/// //
1684/// // ExecuteNative {
1685/// // msgs: Vec<ActionMsg>,
1686/// // },
1687/// // }
1688/// ```
1689///
1690/// ## Example 3: Usage with custom execute and signed data types
1691///
1692/// ```rust,ignore
1693/// #[cw_serde]
1694/// pub struct SignedDataMsg {
1695/// pub data: String,
1696/// pub signature: String,
1697/// }
1698///
1699/// #[signed_execute(ActionMsg, SignedDataMsg)]
1700/// #[cw_serde]
1701/// pub enum ExecuteMsgSigned {
1702/// // User-defined execute messages
1703/// }
1704///
1705/// // Generated:
1706/// // pub enum ExecuteMsgSigned {
1707/// // // User-defined execute messages
1708/// //
1709/// // Execute {
1710/// // msgs: Vec<::cosmwasm_std::CosmosMsg>,
1711/// // },
1712/// //
1713/// // ExecuteSigned {
1714/// // msgs: Vec<ActionMsg>,
1715/// // signed: SignedDataMsg,
1716/// // nonce: Option<::cosmwasm_std::Uint64>,
1717/// // },
1718/// //
1719/// // ExecuteNative {
1720/// // msgs: Vec<ActionMsg>,
1721/// // },
1722/// // }
1723/// ```
1724///
1725/// ## Example 4: Generic enum with custom types
1726///
1727/// ```rust,ignore
1728/// #[signed_execute(ActionMsg, SignedDataMsg)]
1729/// #[cw_serde]
1730/// pub enum ExecuteMsgCustom<T> {
1731/// // User-defined execute messages
1732/// }
1733///
1734/// // Generated:
1735/// // pub enum ExecuteMsgCustom<T> {
1736/// // // User-defined execute messages
1737/// //
1738/// // Execute {
1739/// // msgs: Vec<::cosmwasm_std::CosmosMsg<T>>,
1740/// // },
1741/// //
1742/// // ExecuteSigned {
1743/// // msgs: Vec<ActionMsg>,
1744/// // signed: SignedDataMsg,
1745/// // nonce: Option<::cosmwasm_std::Uint64>,
1746/// // },
1747/// //
1748/// // ExecuteNative {
1749/// // msgs: Vec<ActionMsg>,
1750/// // },
1751/// // }
1752/// ```
1753///
1754/// # Errors
1755///
1756/// - Fails with a compile-time error if the attribute arguments are invalid (e.g., not a type path
1757/// or more than two arguments).
1758/// - Fails if the input is not a valid enum or if the merge with generated variants cannot be
1759/// performed.
1760///
1761/// This macro is part of the CW84 specification for smart account signed message execution.
1762#[proc_macro_attribute]
1763pub fn signed_execute_multi(metadata: TokenStream, input: TokenStream) -> TokenStream {
1764 let cloned = input.clone();
1765 let ast: DeriveInput = parse_macro_input!(cloned as DeriveInput);
1766 let has_t = has_generic_t(&ast.generics);
1767
1768 let cms_type = if has_t {
1769 quote!(::cosmwasm_std::CosmosMsg<T>)
1770 } else {
1771 quote!(::cosmwasm_std::CosmosMsg)
1772 };
1773
1774 let args = parse_macro_input!(metadata as AttributeArgs);
1775
1776 let (exec_type, sign_type) = match args.len() {
1777 2 => {
1778 let exec = match &args[0] {
1779 NestedMeta::Meta(syn::Meta::Path(path)) => quote!(#path),
1780 other => return comp_err!(other, "Expected a type for the inner action message, like `ExecuteMsg`"),
1781 };
1782 let signed = match &args[1] {
1783 NestedMeta::Meta(syn::Meta::Path(path)) => quote!(#path),
1784 other => return comp_err!(other, "Expected a type for the signed message, like `SignedMsg`"),
1785 };
1786 (exec, signed)
1787 },
1788 1 => match &args[0] {
1789 NestedMeta::Meta(syn::Meta::Path(path)) => (quote!(#path), quote!(::cw84::Binary)),
1790 other => return comp_err!(other, "Expected a type for the inner action message, like `ExecuteMsg`"),
1791 },
1792 0 => (
1793 // self type
1794 ast.ident.to_token_stream(),
1795 quote!(::cw84::Binary)
1796 ),
1797 _ => return comp_err!(&args[1], "Expected at most 2 arguments"),
1798 };
1799
1800 let right_enum = if args.len() > 0 {
1801 // Include Native variant when exec_type is explicitly specified
1802 quote! {
1803 enum Right {
1804 Execute {
1805 msgs: Vec<#cms_type>,
1806 signed: Option<#sign_type>,
1807 },
1808 ExecuteSigned {
1809 msgs: Vec<#exec_type>,
1810 signed: #sign_type,
1811 nonce: Option<::cosmwasm_std::Uint64>,
1812 },
1813 ExecuteNative {
1814 msgs: Vec<#exec_type>,
1815 },
1816 }
1817 }
1818 } else {
1819 // Exclude Native variant when exec_type is not specified (uses self type)
1820 quote! {
1821 enum Right {
1822 Execute {
1823 msgs: Vec<#cms_type>,
1824 signed: Option<#sign_type>,
1825 },
1826 ExecuteSigned {
1827 msgs: Vec<#exec_type>,
1828 signed: #sign_type,
1829 nonce: Option<::cosmwasm_std::Uint64>,
1830 },
1831 }
1832 }
1833 };
1834
1835 merge_variants(input, right_enum.into())
1836}
1837
1838
1839
1840/// Procedural macro for the CW84 standard that injects execute variants for signed message execution
1841/// into an execute enum, supporting both generic and non-generic `CosmosMsg` types.
1842///
1843/// This macro extends an enum with standardized execute variants for smart accounts as defined in the
1844/// CW84 specification. It checks if the input enum is generic over `T` and adjusts the `Execute`
1845/// variant to use `CosmosMsg<T>` or `CosmosMsg` accordingly. The macro supports custom types for the
1846/// inner action message and signed data, enabling execution of a single signed message.
1847///
1848/// # Arguments
1849///
1850/// The macro accepts **zero to two type arguments** via the attribute:
1851/// - **First type** (optional): The inner action message type (e.g., `ExecuteMsg`) for the
1852/// `ExecuteSigned` variant. Defaults to the enum's own type if not provided.
1853/// - **Second type** (optional): The signed data type (e.g., `SignedDataMsg`) for the
1854/// `ExecuteSigned` variant. Defaults to `cosmwasm_std::Binary` if not provided.
1855///
1856/// # Generated Variants
1857///
1858/// The macro injects the following execute variants:
1859/// - `Execute`: Executes a list of `CosmosMsg` messages by a smart account.
1860/// - `ExecuteSigned`: Executes a single signed message, using the provided action and data types.
1861///
1862/// # Notes
1863/// - The `#[signed_execute]` attribute must be applied **before** `#[cw_serde]` or other derive
1864/// macros.
1865/// - Unlike query macros, this macro does not require `#[derive(QueryResponses)]` since it targets
1866/// execute messages.
1867/// - This macro is designed for single-message execution, in contrast to `signed_execute_multi`, which
1868/// supports multiple messages in the `ExecuteSigned` variant.
1869///
1870/// # Examples
1871///
1872/// ## Example 1: Basic usage with no arguments
1873///
1874/// ```rust,ignore
1875/// use cosmwasm_schema::cw_serde;
1876///
1877/// #[cw_serde]
1878/// #[signed_execute]
1879/// pub enum ExecuteMsg {
1880/// // User-defined execute messages
1881/// }
1882///
1883/// // Generated:
1884/// // pub enum ExecuteMsg {
1885/// // // User-defined execute messages
1886/// //
1887/// // Execute {
1888/// // msgs: Vec<::cosmwasm_std::CosmosMsg>,
1889/// // },
1890/// //
1891/// // ExecuteSigned {
1892/// // msg: Box<ExecuteMsg>,
1893/// // signed: ::cosmwasm_std::Binary,
1894/// // nonce: Option<::cosmwasm_std::Uint64>,
1895/// // },
1896/// // }
1897/// ```
1898///
1899/// ## Example 2: Usage with a custom execute message type
1900///
1901/// ```rust,ignore
1902/// #[cw_serde]
1903/// pub enum InnerActionMsg {
1904/// Foo {},
1905/// }
1906///
1907/// #[signed_execute(InnerActionMsg)]
1908/// #[cw_serde]
1909/// pub enum ExecuteMsg {
1910/// // User-defined execute messages
1911/// }
1912///
1913/// // Generated:
1914/// // pub enum ExecuteMsg {
1915/// // // User-defined execute messages
1916/// //
1917/// // Execute {
1918/// // msgs: Vec<::cosmwasm_std::CosmosMsg>,
1919/// // },
1920/// //
1921/// // ExecuteSigned {
1922/// // msg: InnerActionMsg,
1923/// // signed: ::cosmwasm_std::Binary,
1924/// // nonce: Option<::cosmwasm_std::Uint64>,
1925/// // },
1926/// // }
1927/// ```
1928///
1929/// ## Example 3: Usage with custom execute and signed data types
1930///
1931/// ```rust,ignore
1932/// #[cw_serde]
1933/// pub struct SignedDataMsg {
1934/// pub data: String,
1935/// pub signature: String,
1936/// }
1937///
1938/// #[signed_execute(InnerActionMsg, SignedDataMsg)]
1939/// #[cw_serde]
1940/// pub enum ExecuteMsgSigned {
1941/// // User-defined execute messages
1942/// }
1943///
1944/// // Generated:
1945/// // pub enum ExecuteMsgSigned {
1946/// // // User-defined execute messages
1947/// //
1948/// // Execute {
1949/// // msgs: Vec<::cosmwasm_std::CosmosMsg>,
1950/// // },
1951/// //
1952/// // ExecuteSigned {
1953/// // msg: InnerActionMsg,
1954/// // signed: SignedDataMsg,
1955/// // nonce: Option<::cosmwasm_std::Uint64>,
1956/// // },
1957/// // }
1958/// ```
1959///
1960/// ## Example 4: Generic enum with custom types
1961///
1962/// ```rust,ignore
1963/// #[signed_execute(InnerActionMsg, SignedDataMsg)]
1964/// #[cw_serde]
1965/// pub enum ExecuteMsgCustom<T> {
1966/// // User-defined execute messages
1967/// }
1968///
1969/// // Generated:
1970/// // pub enum ExecuteMsgCustom<T> {
1971/// // // User-defined execute messages
1972/// //
1973/// // Execute {
1974/// // msgs: Vec<::cosmwasm_std::CosmosMsg<T>>,
1975/// // },
1976/// //
1977/// // ExecuteSigned {
1978/// // msg: InnerActionMsg,
1979/// // signed: SignedDataMsg,
1980/// // nonce: Option<::cosmwasm_std::Uint64>,
1981/// // },
1982/// // }
1983/// ```
1984///
1985/// # Errors
1986///
1987/// - Fails with a compile-time error if the attribute arguments are invalid (e.g., not a type path
1988/// or more than two arguments).
1989/// - Fails if the input is not a valid enum or if the merge with generated variants cannot be
1990/// performed.
1991///
1992/// This macro is part of the CW84 specification for smart account signed message execution.
1993#[proc_macro_attribute]
1994pub fn signed_execute_one(metadata: TokenStream, input: TokenStream) -> TokenStream {
1995 let cloned = input.clone();
1996 let ast: DeriveInput = parse_macro_input!(cloned as DeriveInput);
1997 let has_t = has_generic_t(&ast.generics);
1998
1999 let cms_type = if has_t {
2000 quote!(::cosmwasm_std::CosmosMsg<T>)
2001 } else {
2002 quote!(::cosmwasm_std::CosmosMsg)
2003 };
2004
2005 let args = parse_macro_input!(metadata as AttributeArgs);
2006
2007 let (exec_type, sign_type) = match args.len() {
2008 2 => {
2009 let exec = match &args[0] {
2010 NestedMeta::Meta(syn::Meta::Path(path)) => quote!(#path),
2011 other => return comp_err!(other, "Expected a type for the inner action message, like `ExecuteMsg`"),
2012 };
2013 let signed = match &args[1] {
2014 NestedMeta::Meta(syn::Meta::Path(path)) => quote!(#path),
2015 other => return comp_err!(other, "Expected a type for the signed message, like `SignedMsg`"),
2016 };
2017 (exec, signed)
2018 },
2019 1 => match &args[0] {
2020 NestedMeta::Meta(syn::Meta::Path(path)) => (quote!(#path), quote!(::cw84::Binary)),
2021 other => return comp_err!(other, "Expected a type for the inner action message, like `ExecuteMsg`"),
2022 },
2023 0 => (
2024 // self type
2025 ast.ident.to_token_stream(),
2026 quote!(::cw84::Binary)
2027 ),
2028 _ => return comp_err!(&args[1], "Expected at most 2 arguments"),
2029 };
2030
2031 let right_enum = quote! {
2032 enum Right {
2033 Execute {
2034 msgs: Vec<#cms_type>,
2035 signed: Option<#sign_type>,
2036 },
2037 ExecuteSigned {
2038 msg: Box<#exec_type>,
2039 signed: #sign_type,
2040 nonce: Option<::cosmwasm_std::Uint64>,
2041 },
2042 }
2043 };
2044
2045 merge_variants(input, right_enum.into())
2046}