boot_contract_derive/
lib.rs1#![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}