boot_contract_derive/
lib.rs

1#![recursion_limit = "128"]
2
3extern crate proc_macro;
4use proc_macro::TokenStream;
5use quote::quote;
6use syn::{parse_macro_input, AttributeArgs, Fields, Item, Meta, NestedMeta, Path};
7
8#[proc_macro_attribute]
9pub fn contract(attrs: TokenStream, input: TokenStream) -> TokenStream {
10    let mut item = parse_macro_input!(input as syn::Item);
11    let attributes = parse_macro_input!(attrs as AttributeArgs);
12
13    let types_in_order: Vec<Path> = attributes
14        .into_iter()
15        .map(|attr| {
16            let NestedMeta::Meta(Meta::Path(type_path)) = attr else {
17            panic!("Expected a contract endpoint type.");
18        };
19            type_path
20        })
21        .collect();
22
23    if types_in_order.len() != 4 {
24        panic!("Expected four endpoint types (InstantiateMsg,ExecuteMsg,QueryMsg,MigrateMsg). Use cosmwasm_std::Empty if not implemented.")
25    }
26
27    let Item::Struct(boot_struct) = &mut item else {
28        panic!("Only works on structs");
29    };
30    let Fields::Unit = &mut boot_struct.fields else {
31        panic!("Struct must be unit-struct");
32    };
33
34    let init = types_in_order[0].clone();
35    let exec = types_in_order[1].clone();
36    let query = types_in_order[2].clone();
37    let migrate = types_in_order[3].clone();
38
39    let name = boot_struct.ident.clone();
40    let struct_def = quote!(
41            #[derive(
42                ::std::clone::Clone,
43            )]
44            pub struct #name<Chain: ::boot_core::CwEnv>(::boot_core::Contract<Chain>);
45
46            impl<Chain: ::boot_core::CwEnv> ::boot_core::ContractInstance<Chain> for #name<Chain> {
47                fn as_instance(&self) -> &::boot_core::Contract<Chain> {
48            &self.0
49        }
50            fn as_instance_mut(&mut self) -> &mut ::boot_core::Contract<Chain> {
51                &mut self.0
52            }
53        }
54
55        impl<Chain: ::boot_core::CwEnv> ::boot_core::CwInterface for #name<Chain> {
56            type InstantiateMsg = #init;
57            type ExecuteMsg = #exec;
58            type QueryMsg = #query;
59            type MigrateMsg = #migrate;
60        }
61    );
62    struct_def.into()
63}