1extern crate proc_macro2;
2use proc_macro::TokenStream;
3use quote::quote;
4use syn::{parse_macro_input, AttributeArgs, Fields, Item};
5
6const DELIMITER: &str = ",";
7
8#[proc_macro]
10pub fn with_abstract_event(input: TokenStream) -> TokenStream {
11 let input = input.to_string();
12 let mut input = input.split(DELIMITER);
13 let base_response = input.next().unwrap().trim();
14 let contract_name = input.next().unwrap().trim();
15 let action = input.next().unwrap().trim();
16 let attrs = input.collect::<Vec<&str>>().join(DELIMITER);
18
19 let attribute_addition = if attrs.is_empty() {
20 "".to_string()
21 } else if attrs.starts_with('[') && attrs.ends_with(']') {
22 format!(".add_attributes(vec!{attrs})")
23 } else {
24 format!(".add_attributes({attrs})")
25 };
26 let output = format!(
27 "{base_response}
28 .add_event(
29 cosmwasm_std::Event::new(\"abstract\")
30 .add_attribute(\"contract\", {contract_name})
31 .add_attribute(\"action\", {action})
32 {attribute_addition}
33 )"
34 );
35
36 output.parse().unwrap()
37}
38
39#[proc_macro_attribute]
40pub fn abstract_response(attrs: TokenStream, input: TokenStream) -> TokenStream {
41 let mut item = parse_macro_input!(input as syn::Item);
42 let attributes = parse_macro_input!(attrs as AttributeArgs);
43
44 let Item::Struct(resp_struct) = &mut item else {
45 panic!("Only works on structs");
46 };
47 let Fields::Unit = &mut resp_struct.fields else {
48 panic!("Struct must be unit-struct");
49 };
50 let visibility = resp_struct.vis.clone();
51 let resp_name = resp_struct.ident.clone();
52
53 let contract_name = attributes[0].clone();
54
55 let struct_def = quote!(
56 #visibility struct #resp_name;
57 impl #resp_name {
58 #visibility fn new<T: Into<String>, A: Into<cosmwasm_std::Attribute>>(
59 action: T,
60 attrs: impl IntoIterator<Item = A>,
61 ) -> cosmwasm_std::Response {
62 cosmwasm_std::Response::new().add_event(
63 cosmwasm_std::Event::new("abstract")
64 .add_attributes(vec![("contract", #contract_name)])
65 .add_attributes(vec![("action", action)])
66 .add_attributes(attrs),
67 )
68 }
69 #visibility fn action<T: Into<String>>(action: T) -> cosmwasm_std::Response {
70 #resp_name::new(action, Vec::<cosmwasm_std::Attribute>::new())
71 }
72 }
73 );
74
75 struct_def.into()
76}