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}