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` and
1286/// `ValidSignatures`, wrapped in `Option`. Defaults to `Option<cosmwasm_std::Binary>`.
1287///
1288/// # Generated Variants
1289///
1290/// - `CanExecute`: Queries if a `CosmosMsg` can be executed.
1291/// - `CanExecuteSigned`: Queries if signed messages can be executed, using provided types.
1292/// - `ValidSignature`: Verifies a single signature against data and optional payload.
1293/// - `ValidSignatures`: Verifies multiple signatures against data and optional payload.
1294///
1295/// # Notes
1296///
1297/// - Apply `#[signed_query]` before `#[cw_serde]` or other derives.
1298/// - Enum must derive `#[derive(QueryResponses)]` from `cosmwasm_schema` for `#[returns(...)]`.
1299/// - Part of the CW84 spec for smart account signed message validation.
1300///
1301/// # Examples
1302///
1303/// ## Basic usage
1304///
1305/// ```rust,ignore
1306/// use cosmwasm_schema::{cw_serde, QueryResponses};
1307/// #[cw_serde]
1308/// pub enum ExecuteMsg { Foo {} }
1309/// #[signed_query(ExecuteMsg)]
1310/// #[cw_serde]
1311/// #[derive(QueryResponses)]
1312/// pub enum QueryMsg { /* User queries */ }
1313/// // Generates `CanExecute`, `CanExecuteSigned` (with `Binary` signed), `ValidSignature`, and
1314/// // `ValidSignatures` with `Option<Binary>` payload.
1315/// ```
1316///
1317/// ## Custom types with generic enum
1318///
1319/// ```rust,ignore
1320/// #[cw_serde]
1321/// pub struct SignedDataMsg { pub data: String, pub signature: String }
1322/// #[cw_serde]
1323/// pub struct CustomPayload { pub metadata: String }
1324/// #[signed_query(ExecuteMsg, SignedDataMsg, CustomPayload)]
1325/// #[cw_serde]
1326/// #[derive(QueryResponses)]
1327/// pub enum QueryMsg<T> { /* User queries */ }
1328/// // Generates variants with `CosmosMsg<T>`, `SignedDataMsg` signed, and `Option<CustomPayload>`.
1329/// ```
1330///
1331/// # Errors
1332///
1333/// - Fails if arguments are invalid (e.g., not a type path or wrong count).
1334/// - Fails if input is not a valid enum or variant merge fails.
1335#[proc_macro_attribute]
1336pub fn signed_query_multi(metadata: TokenStream, input: TokenStream) -> TokenStream {
1337 let cloned = input.clone();
1338 let ast: DeriveInput = parse_macro_input!(cloned as DeriveInput);
1339 let has_t = has_generic_t(&ast.generics);
1340
1341 let msg_type = if has_t {
1342 quote!(::cosmwasm_std::CosmosMsg<T>)
1343 } else {
1344 quote!(::cosmwasm_std::CosmosMsg)
1345 };
1346
1347 let args = parse_macro_input!(metadata as AttributeArgs);
1348
1349 let (act_type, sign_type, pl_type) = match args.len() {
1350 3 => {
1351 let exec = match &args[0] {
1352 NestedMeta::Meta(syn::Meta::Path(path)) => quote!(#path),
1353 other => return comp_err!(other, "Expected a type for the inner action message, like `ExecuteMsg`"),
1354 };
1355 let signed = match &args[1] {
1356 NestedMeta::Meta(syn::Meta::Path(path)) => quote!(#path),
1357 other => return comp_err!(other, "Expected a type for the signed message, like `SignedDataMsg`"),
1358 };
1359 let payload = match &args[2] {
1360 NestedMeta::Meta(syn::Meta::Path(path)) => quote!(Option<#path>),
1361 other => return comp_err!(other, "Expected a type for the payload, like `CustomPayload`"),
1362 };
1363 (exec, signed, payload)
1364 },
1365 2 => {
1366 let exec = match &args[0] {
1367 NestedMeta::Meta(syn::Meta::Path(path)) => quote!(#path),
1368 other => return comp_err!(other, "Expected a type for the inner action message, like `ExecuteMsg`"),
1369 };
1370 let signed = match &args[1] {
1371 NestedMeta::Meta(syn::Meta::Path(path)) => quote!(#path),
1372 other => return comp_err!(other, "Expected a type for the signed message, like `SignedDataMsg`"),
1373 };
1374 (exec, signed, quote!(Option<::cosmwasm_std::Binary>))
1375 },
1376 1 => match &args[0] {
1377 NestedMeta::Meta(syn::Meta::Path(path)) => (
1378 quote!(#path),
1379 quote!(::cosmwasm_std::Binary),
1380 quote!(Option<::cosmwasm_std::Binary>)
1381 ),
1382 other => return comp_err!(other, "Expected a type for the inner action message, like `ExecuteMsg`"),
1383 },
1384 _ => return comp_err!(&args.get(0), "Expected one to three arguments: `#[signed_query(ExecuteMsg[, SignedDataMsg][, CustomPayload])]`"),
1385 };
1386
1387 let right_enum = quote! {
1388 enum Right {
1389 #[returns(::cw84::CanExecuteResponse)]
1390 CanExecute {
1391 sender: String,
1392 msg: #msg_type
1393 },
1394 #[returns(::cw84::CanExecuteSignedResponse)]
1395 CanExecuteSigned {
1396 msgs: Vec<#act_type>,
1397 signed: #sign_type,
1398 },
1399 #[returns(::cw84::ValidSignatureResponse)]
1400 ValidSignature {
1401 data: ::cosmwasm_std::Binary,
1402 signature: ::cosmwasm_std::Binary,
1403 payload: #pl_type
1404 },
1405 #[returns(::cw84::ValidSignaturesResponse)]
1406 ValidSignatures {
1407 data: Vec<::cosmwasm_std::Binary>,
1408 signatures: Vec<::cosmwasm_std::Binary>,
1409 payload: #pl_type
1410 }
1411 }
1412 };
1413 merge_variants(input, right_enum.into())
1414}
1415
1416
1417
1418/// Procedural macro for the CW84 standard that injects query variants for signed message validation
1419/// into a query enum, supporting generic and non-generic `CosmosMsg` types.
1420///
1421/// This macro extends a query enum with CW84-compliant variants for smart accounts. It checks if the
1422/// enum is generic over `T`, using `CosmosMsg<T>` for `CanExecute` if so, or `CosmosMsg` otherwise.
1423/// It supports custom types for the action message, signed data, and payload, enabling validation of
1424/// a single signed message.
1425///
1426/// # Arguments
1427///
1428/// - **First type** (required): Inner action message type (e.g., `ExecuteMsg`) for `CanExecuteSigned`.
1429/// - **Second type** (optional): Signed data type (e.g., `SignedDataMsg`) for `CanExecuteSigned`.
1430/// Defaults to `cosmwasm_std::Binary`.
1431/// - **Third type** (optional): Payload type (e.g., `CustomPayload`) for `ValidSignature`, wrapped in
1432/// `Option`. Defaults to `Option<cosmwasm_std::Binary>`.
1433///
1434/// # Generated Variants
1435///
1436/// - `CanExecute`: Queries if a `CosmosMsg` can be executed.
1437/// - `CanExecuteSigned`: Queries if a single signed message can be executed, using provided types.
1438/// - `ValidSignature`: Verifies a single signature against data and optional payload.
1439///
1440/// # Notes
1441///
1442/// - Apply `#[signed_query]` before `#[cw_serde]` or other derives.
1443/// - Enum must derive `#[derive(QueryResponses)]` from `cosmwasm_schema` for `#[returns(...)]`.
1444/// - Excludes multi-signature `ValidSignatures` variant, unlike `signed_query_multi`.
1445/// - Part of the CW84 spec for smart account signed message validation.
1446///
1447/// # Examples
1448///
1449/// ## Basic usage
1450///
1451/// ```rust,ignore
1452/// use cosmwasm_schema::{cw_serde, QueryResponses};
1453/// #[cw_serde]
1454/// pub enum ExecuteMsg { Foo {} }
1455/// #[signed_query(ExecuteMsg)]
1456/// #[cw_serde]
1457/// #[derive(QueryResponses)]
1458/// pub enum QueryMsg { /* User queries */ }
1459/// // Generates `CanExecute`, `CanExecuteSigned` (with `Binary` signed), and `ValidSignature` with
1460/// // `Option<Binary>` payload.
1461/// ```
1462///
1463/// ## Custom types with generic enum
1464///
1465/// ```rust,ignore
1466/// #[cw_serde]
1467/// pub struct SignedDataMsg { pub data: String, pub signature: String }
1468/// #[cw_serde]
1469/// pub struct CustomPayload { pub metadata: String }
1470/// #[signed_query(ExecuteMsg, SignedDataMsg, CustomPayload)]
1471/// #[cw_serde]
1472/// #[derive(QueryResponses)]
1473/// pub enum QueryMsg<T> { /* User queries */ }
1474/// // Generates variants with `CosmosMsg<T>`, `SignedDataMsg` signed, and `Option<CustomPayload>`.
1475/// ```
1476///
1477/// # Errors
1478///
1479/// - Fails if arguments are invalid (e.g., not a type path or wrong count).
1480/// - Fails if input is not a valid enum or variant merge fails.
1481#[proc_macro_attribute]
1482pub fn signed_query_one(metadata: TokenStream, input: TokenStream) -> TokenStream {
1483 let cloned = input.clone();
1484 let ast: DeriveInput = parse_macro_input!(cloned as DeriveInput);
1485 let has_t = has_generic_t(&ast.generics);
1486
1487 let msg_type = if has_t {
1488 quote!(::cosmwasm_std::CosmosMsg<T>)
1489 } else {
1490 quote!(::cosmwasm_std::CosmosMsg)
1491 };
1492
1493 let args = parse_macro_input!(metadata as AttributeArgs);
1494
1495 let (exec_type, data_type, payload_type) = match args.len() {
1496 3 => {
1497 let exec = match &args[0] {
1498 NestedMeta::Meta(syn::Meta::Path(path)) => quote!(#path),
1499 other => return comp_err!(other, "Expected a type for the inner action message, like `ExecuteMsg`"),
1500 };
1501 let signed = match &args[1] {
1502 NestedMeta::Meta(syn::Meta::Path(path)) => quote!(#path),
1503 other => return comp_err!(other, "Expected a type for the signed message, like `SignedDataMsg`"),
1504 };
1505 let payload = match &args[2] {
1506 NestedMeta::Meta(syn::Meta::Path(path)) => quote!(Option<#path>),
1507 other => return comp_err!(other, "Expected a type for the payload, like `CustomPayload`"),
1508 };
1509 (exec, signed, payload)
1510 },
1511 2 => {
1512 let exec = match &args[0] {
1513 NestedMeta::Meta(syn::Meta::Path(path)) => quote!(#path),
1514 other => return comp_err!(other, "Expected a type for the inner action message, like `ExecuteMsg`"),
1515 };
1516 let signed = match &args[1] {
1517 NestedMeta::Meta(syn::Meta::Path(path)) => quote!(#path),
1518 other => return comp_err!(other, "Expected a type for the signed message, like `SignedDataMsg`"),
1519 };
1520 (exec, signed, quote!(Option<::cosmwasm_std::Binary>))
1521 },
1522 1 => match &args[0] {
1523 NestedMeta::Meta(syn::Meta::Path(path)) => (
1524 quote!(#path),
1525 quote!(::cosmwasm_std::Binary),
1526 quote!(Option<::cosmwasm_std::Binary>)
1527 ),
1528 other => return comp_err!(other, "Expected a type for the inner action message, like `ExecuteMsg`"),
1529 },
1530 _ => return comp_err!(&args.get(0), "Expected one to three arguments: `#[signed_query(ExecuteMsg[, SignedDataMsg][, CustomPayload])]`"),
1531 };
1532
1533 let right_enum = quote! {
1534 enum Right {
1535 #[returns(::cw84::CanExecuteResponse)]
1536 CanExecute {
1537 sender: String,
1538 msg: #msg_type
1539 },
1540 #[returns(::cw84::CanExecuteResponse)]
1541 CanExecuteSigned {
1542 msg: #exec_type,
1543 signed: #data_type,
1544 },
1545 #[returns(::cw84::ValidSignatureResponse)]
1546 ValidSignature {
1547 data: ::cosmwasm_std::Binary,
1548 signature: ::cosmwasm_std::Binary,
1549 payload: #payload_type
1550 },
1551 }
1552 };
1553 merge_variants(input, right_enum.into())
1554}
1555
1556
1557
1558/// Procedural macro for the CW84 standard that injects execute variants for signed message execution
1559/// into an execute enum, supporting both generic and non-generic `CosmosMsg` types.
1560///
1561/// This macro extends an enum with standardized execute variants for smart accounts as defined in the
1562/// CW84 specification. It checks if the input enum is generic over `T` and adjusts the `Execute`
1563/// variant to use `CosmosMsg<T>` or `CosmosMsg` accordingly. The macro supports custom types for the
1564/// inner action message and signed data, enabling execution of signed messages with multiple messages.
1565///
1566/// # Arguments
1567///
1568/// The macro accepts **zero to two type arguments** via the attribute:
1569/// - **First type** (optional): The inner action message type (e.g., `ExecuteMsg`) for the
1570/// `ExecuteSigned` and `Native` variants. Defaults to the enum's own type if not provided.
1571/// - **Second type** (optional): The signed data type (e.g., `SignedDataMsg`) for the
1572/// `ExecuteSigned` variant. Defaults to `cw84::Binary` if not provided.
1573///
1574/// # Generated Variants
1575///
1576/// The macro injects the following execute variants:
1577/// - `Execute`: Executes a list of `CosmosMsg` messages by a smart account.
1578/// - `ExecuteSigned`: Executes a list of signed messages, using the provided action and data types.
1579/// - `Native` (only if `exec_type` is specified): Executes a list of messages of the specified
1580/// `exec_type` directly, without requiring signed data.
1581///
1582/// # Notes
1583/// - The `#[signed_execute]` attribute must be applied **before** `#[cw_serde]` or other derive
1584/// macros.
1585/// - Unlike query macros, this macro does not require `#[derive(QueryResponses)]` since it targets
1586/// execute messages.
1587/// - This macro is designed for the `multi` feature, supporting execution of multiple messages.
1588///
1589/// # Examples
1590///
1591/// ## Example 1: Basic usage with no arguments
1592///
1593/// ```rust,ignore
1594/// use cosmwasm_schema::cw_serde;
1595///
1596/// #[cw_serde]
1597/// #[signed_execute]
1598/// pub enum ExecuteMsg {
1599/// // User-defined execute messages
1600/// }
1601///
1602/// // Generated:
1603/// // pub enum ExecuteMsg {
1604/// // // User-defined execute messages
1605/// //
1606/// // Execute {
1607/// // msgs: Vec<::cosmwasm_std::CosmosMsg>,
1608/// // },
1609/// //
1610/// // ExecuteSigned {
1611/// // msgs: Vec<ExecuteMsg>,
1612/// // signed: ::cw84::Binary,
1613/// // },
1614/// // }
1615/// ```
1616///
1617/// ## Example 2: Usage with a custom execute message type
1618///
1619/// ```rust,ignore
1620/// #[cw_serde]
1621/// pub enum ActionMsg {
1622/// Foo {},
1623/// }
1624///
1625/// #[signed_execute(ActionMsg)]
1626/// #[cw_serde]
1627/// pub enum ExecuteMsg {
1628/// // User-defined execute messages
1629/// }
1630///
1631/// // Generated:
1632/// // pub enum ExecuteMsg {
1633/// // // User-defined execute messages
1634/// //
1635/// // Execute {
1636/// // msgs: Vec<::cosmwasm_std::CosmosMsg>,
1637/// // },
1638/// //
1639/// // ExecuteSigned {
1640/// // msgs: Vec<ActionMsg>,
1641/// // signed: ::cw84::Binary,
1642/// // },
1643/// //
1644/// // ExecuteNative {
1645/// // msgs: Vec<ActionMsg>,
1646/// // },
1647/// // }
1648/// ```
1649///
1650/// ## Example 3: Usage with custom execute and signed data types
1651///
1652/// ```rust,ignore
1653/// #[cw_serde]
1654/// pub struct SignedDataMsg {
1655/// pub data: String,
1656/// pub signature: String,
1657/// }
1658///
1659/// #[signed_execute(ActionMsg, SignedDataMsg)]
1660/// #[cw_serde]
1661/// pub enum ExecuteMsgSigned {
1662/// // User-defined execute messages
1663/// }
1664///
1665/// // Generated:
1666/// // pub enum ExecuteMsgSigned {
1667/// // // User-defined execute messages
1668/// //
1669/// // Execute {
1670/// // msgs: Vec<::cosmwasm_std::CosmosMsg>,
1671/// // },
1672/// //
1673/// // ExecuteSigned {
1674/// // msgs: Vec<ActionMsg>,
1675/// // signed: SignedDataMsg,
1676/// // },
1677/// //
1678/// // ExecuteNative {
1679/// // msgs: Vec<ActionMsg>,
1680/// // },
1681/// // }
1682/// ```
1683///
1684/// ## Example 4: Generic enum with custom types
1685///
1686/// ```rust,ignore
1687/// #[signed_execute(ActionMsg, SignedDataMsg)]
1688/// #[cw_serde]
1689/// pub enum ExecuteMsgCustom<T> {
1690/// // User-defined execute messages
1691/// }
1692///
1693/// // Generated:
1694/// // pub enum ExecuteMsgCustom<T> {
1695/// // // User-defined execute messages
1696/// //
1697/// // Execute {
1698/// // msgs: Vec<::cosmwasm_std::CosmosMsg<T>>,
1699/// // },
1700/// //
1701/// // ExecuteSigned {
1702/// // msgs: Vec<ActionMsg>,
1703/// // signed: SignedDataMsg,
1704/// // },
1705/// //
1706/// // ExecuteNative {
1707/// // msgs: Vec<ActionMsg>,
1708/// // },
1709/// // }
1710/// ```
1711///
1712/// # Errors
1713///
1714/// - Fails with a compile-time error if the attribute arguments are invalid (e.g., not a type path
1715/// or more than two arguments).
1716/// - Fails if the input is not a valid enum or if the merge with generated variants cannot be
1717/// performed.
1718///
1719/// This macro is part of the CW84 specification for smart account signed message execution.
1720#[proc_macro_attribute]
1721pub fn signed_execute_multi(metadata: TokenStream, input: TokenStream) -> TokenStream {
1722 let cloned = input.clone();
1723 let ast: DeriveInput = parse_macro_input!(cloned as DeriveInput);
1724 let has_t = has_generic_t(&ast.generics);
1725
1726 let cms_type = if has_t {
1727 quote!(::cosmwasm_std::CosmosMsg<T>)
1728 } else {
1729 quote!(::cosmwasm_std::CosmosMsg)
1730 };
1731
1732 let args = parse_macro_input!(metadata as AttributeArgs);
1733
1734 let (exec_type, sign_type) = match args.len() {
1735 2 => {
1736 let exec = match &args[0] {
1737 NestedMeta::Meta(syn::Meta::Path(path)) => quote!(#path),
1738 other => return comp_err!(other, "Expected a type for the inner action message, like `ExecuteMsg`"),
1739 };
1740 let signed = match &args[1] {
1741 NestedMeta::Meta(syn::Meta::Path(path)) => quote!(#path),
1742 other => return comp_err!(other, "Expected a type for the signed message, like `SignedMsg`"),
1743 };
1744 (exec, signed)
1745 },
1746 1 => match &args[0] {
1747 NestedMeta::Meta(syn::Meta::Path(path)) => (quote!(#path), quote!(::cw84::Binary)),
1748 other => return comp_err!(other, "Expected a type for the inner action message, like `ExecuteMsg`"),
1749 },
1750 0 => (
1751 // self type
1752 ast.ident.to_token_stream(),
1753 quote!(::cw84::Binary)
1754 ),
1755 _ => return comp_err!(&args[1], "Expected at most 2 arguments"),
1756 };
1757
1758 let right_enum = if args.len() > 0 {
1759 // Include Native variant when exec_type is explicitly specified
1760 quote! {
1761 enum Right {
1762 Execute {
1763 msgs: Vec<#cms_type>,
1764 },
1765 ExecuteSigned {
1766 msgs: Vec<#exec_type>,
1767 signed: #sign_type,
1768 },
1769 ExecuteNative {
1770 msgs: Vec<#exec_type>,
1771 },
1772 }
1773 }
1774 } else {
1775 // Exclude Native variant when exec_type is not specified (uses self type)
1776 quote! {
1777 enum Right {
1778 Execute {
1779 msgs: Vec<#cms_type>,
1780 },
1781 ExecuteSigned {
1782 msgs: Vec<#exec_type>,
1783 signed: #sign_type,
1784 },
1785 }
1786 }
1787 };
1788
1789 merge_variants(input, right_enum.into())
1790}
1791
1792
1793
1794/// Procedural macro for the CW84 standard that injects execute variants for signed message execution
1795/// into an execute enum, supporting both generic and non-generic `CosmosMsg` types.
1796///
1797/// This macro extends an enum with standardized execute variants for smart accounts as defined in the
1798/// CW84 specification. It checks if the input enum is generic over `T` and adjusts the `Execute`
1799/// variant to use `CosmosMsg<T>` or `CosmosMsg` accordingly. The macro supports custom types for the
1800/// inner action message and signed data, enabling execution of a single signed message.
1801///
1802/// # Arguments
1803///
1804/// The macro accepts **zero to two type arguments** via the attribute:
1805/// - **First type** (optional): The inner action message type (e.g., `ExecuteMsg`) for the
1806/// `ExecuteSigned` variant. Defaults to the enum's own type if not provided.
1807/// - **Second type** (optional): The signed data type (e.g., `SignedDataMsg`) for the
1808/// `ExecuteSigned` variant. Defaults to `cosmwasm_std::Binary` if not provided.
1809///
1810/// # Generated Variants
1811///
1812/// The macro injects the following execute variants:
1813/// - `Execute`: Executes a list of `CosmosMsg` messages by a smart account.
1814/// - `ExecuteSigned`: Executes a single signed message, using the provided action and data types.
1815///
1816/// # Notes
1817/// - The `#[signed_execute]` attribute must be applied **before** `#[cw_serde]` or other derive
1818/// macros.
1819/// - Unlike query macros, this macro does not require `#[derive(QueryResponses)]` since it targets
1820/// execute messages.
1821/// - This macro is designed for single-message execution, in contrast to `signed_execute_multi`, which
1822/// supports multiple messages in the `ExecuteSigned` variant.
1823///
1824/// # Examples
1825///
1826/// ## Example 1: Basic usage with no arguments
1827///
1828/// ```rust,ignore
1829/// use cosmwasm_schema::cw_serde;
1830///
1831/// #[cw_serde]
1832/// #[signed_execute]
1833/// pub enum ExecuteMsg {
1834/// // User-defined execute messages
1835/// }
1836///
1837/// // Generated:
1838/// // pub enum ExecuteMsg {
1839/// // // User-defined execute messages
1840/// //
1841/// // Execute {
1842/// // msgs: Vec<::cosmwasm_std::CosmosMsg>,
1843/// // },
1844/// //
1845/// // ExecuteSigned {
1846/// // msg: Box<ExecuteMsg>,
1847/// // signed: ::cosmwasm_std::Binary,
1848/// // },
1849/// // }
1850/// ```
1851///
1852/// ## Example 2: Usage with a custom execute message type
1853///
1854/// ```rust,ignore
1855/// #[cw_serde]
1856/// pub enum InnerActionMsg {
1857/// Foo {},
1858/// }
1859///
1860/// #[signed_execute(InnerActionMsg)]
1861/// #[cw_serde]
1862/// pub enum ExecuteMsg {
1863/// // User-defined execute messages
1864/// }
1865///
1866/// // Generated:
1867/// // pub enum ExecuteMsg {
1868/// // // User-defined execute messages
1869/// //
1870/// // Execute {
1871/// // msgs: Vec<::cosmwasm_std::CosmosMsg>,
1872/// // },
1873/// //
1874/// // ExecuteSigned {
1875/// // msg: InnerActionMsg,
1876/// // signed: ::cosmwasm_std::Binary,
1877/// // },
1878/// // }
1879/// ```
1880///
1881/// ## Example 3: Usage with custom execute and signed data types
1882///
1883/// ```rust,ignore
1884/// #[cw_serde]
1885/// pub struct SignedDataMsg {
1886/// pub data: String,
1887/// pub signature: String,
1888/// }
1889///
1890/// #[signed_execute(InnerActionMsg, SignedDataMsg)]
1891/// #[cw_serde]
1892/// pub enum ExecuteMsgSigned {
1893/// // User-defined execute messages
1894/// }
1895///
1896/// // Generated:
1897/// // pub enum ExecuteMsgSigned {
1898/// // // User-defined execute messages
1899/// //
1900/// // Execute {
1901/// // msgs: Vec<::cosmwasm_std::CosmosMsg>,
1902/// // },
1903/// //
1904/// // ExecuteSigned {
1905/// // msg: InnerActionMsg,
1906/// // signed: SignedDataMsg,
1907/// // },
1908/// // }
1909/// ```
1910///
1911/// ## Example 4: Generic enum with custom types
1912///
1913/// ```rust,ignore
1914/// #[signed_execute(InnerActionMsg, SignedDataMsg)]
1915/// #[cw_serde]
1916/// pub enum ExecuteMsgCustom<T> {
1917/// // User-defined execute messages
1918/// }
1919///
1920/// // Generated:
1921/// // pub enum ExecuteMsgCustom<T> {
1922/// // // User-defined execute messages
1923/// //
1924/// // Execute {
1925/// // msgs: Vec<::cosmwasm_std::CosmosMsg<T>>,
1926/// // },
1927/// //
1928/// // ExecuteSigned {
1929/// // msg: InnerActionMsg,
1930/// // signed: SignedDataMsg,
1931/// // },
1932/// // }
1933/// ```
1934///
1935/// # Errors
1936///
1937/// - Fails with a compile-time error if the attribute arguments are invalid (e.g., not a type path
1938/// or more than two arguments).
1939/// - Fails if the input is not a valid enum or if the merge with generated variants cannot be
1940/// performed.
1941///
1942/// This macro is part of the CW84 specification for smart account signed message execution.
1943#[proc_macro_attribute]
1944pub fn signed_execute_one(metadata: TokenStream, input: TokenStream) -> TokenStream {
1945 let cloned = input.clone();
1946 let ast: DeriveInput = parse_macro_input!(cloned as DeriveInput);
1947 let has_t = has_generic_t(&ast.generics);
1948
1949 let cms_type = if has_t {
1950 quote!(::cosmwasm_std::CosmosMsg<T>)
1951 } else {
1952 quote!(::cosmwasm_std::CosmosMsg)
1953 };
1954
1955 let args = parse_macro_input!(metadata as AttributeArgs);
1956
1957 let (exec_type, sign_type) = match args.len() {
1958 2 => {
1959 let exec = match &args[0] {
1960 NestedMeta::Meta(syn::Meta::Path(path)) => quote!(#path),
1961 other => return comp_err!(other, "Expected a type for the inner action message, like `ExecuteMsg`"),
1962 };
1963 let signed = match &args[1] {
1964 NestedMeta::Meta(syn::Meta::Path(path)) => quote!(#path),
1965 other => return comp_err!(other, "Expected a type for the signed message, like `SignedMsg`"),
1966 };
1967 (exec, signed)
1968 },
1969 1 => match &args[0] {
1970 NestedMeta::Meta(syn::Meta::Path(path)) => (quote!(#path), quote!(::cw84::Binary)),
1971 other => return comp_err!(other, "Expected a type for the inner action message, like `ExecuteMsg`"),
1972 },
1973 0 => (
1974 // self type
1975 ast.ident.to_token_stream(),
1976 quote!(::cw84::Binary)
1977 ),
1978 _ => return comp_err!(&args[1], "Expected at most 2 arguments"),
1979 };
1980
1981 let right_enum = quote! {
1982 enum Right {
1983 Execute {
1984 msgs: Vec<#cms_type>,
1985 },
1986 ExecuteSigned {
1987 msg: Box<#exec_type>,
1988 signed: #sign_type,
1989 },
1990 }
1991 };
1992
1993 merge_variants(input, right_enum.into())
1994}