1#![recursion_limit = "128"]
2extern crate proc_macro;
3
4mod core_impl;
5
6use core_impl::{ext::generate_ext_structs, metadata::generate_contract_metadata_method};
7
8use proc_macro::TokenStream;
9
10use self::core_impl::*;
11use darling::ast::NestedMeta;
12use darling::{Error, FromMeta};
13use inflector::Inflector;
14use proc_macro2::{Ident, Span};
15use quote::{quote, ToTokens};
16use syn::{
17 parse_quote, Expr, ImplItem, Item, ItemEnum, ItemImpl, ItemStruct, ItemTrait, WhereClause,
18};
19
20#[derive(Debug, Clone)]
21struct Serializers {
22 vec: Vec<Expr>,
23}
24
25impl FromMeta for Serializers {
26 fn from_expr(expr: &syn::Expr) -> Result<Self, darling::Error> {
27 match expr {
28 syn::Expr::Array(expr_array) => Ok(Serializers {
29 vec: expr_array
30 .elems
31 .iter()
32 .map(<Expr as FromMeta>::from_expr)
33 .map(|x| x.unwrap())
34 .collect::<Vec<_>>(),
35 }),
36 _ => Err(Error::unexpected_expr_type(expr)),
37 }
38 }
39}
40
41#[derive(FromMeta)]
42struct NearMacroArgs {
43 serializers: Option<Serializers>,
44 #[darling(default, flatten)]
45 near_bindgen_args: NearBindgenMacroArgs,
46 inside_nearsdk: Option<bool>,
47}
48
49fn has_nested_near_macros(item: TokenStream) -> bool {
50 syn::parse::<syn::Item>(item)
51 .ok()
52 .and_then(|item_ast| {
53 let attrs = match item_ast {
54 syn::Item::Struct(s) => s.attrs,
55 syn::Item::Enum(e) => e.attrs,
56 syn::Item::Impl(i) => i.attrs,
57 _ => vec![], };
59
60 attrs.into_iter().find(|attr| {
61 let path_str = attr.path().to_token_stream().to_string();
62 path_str == "near" || path_str == "near_bindgen"
63 })
64 })
65 .is_some()
66}
67
68#[proc_macro_attribute]
69pub fn near(attr: TokenStream, item: TokenStream) -> TokenStream {
70 if attr.to_string().contains("event_json") {
71 return core_impl::near_events(attr, item);
72 }
73
74 let meta_list = match NestedMeta::parse_meta_list(attr.into()) {
75 Ok(v) => v,
76 Err(e) => {
77 return TokenStream::from(Error::from(e).write_errors());
78 }
79 };
80
81 let near_macro_args = match NearMacroArgs::from_list(&meta_list) {
82 Ok(v) => v,
83 Err(e) => {
84 return TokenStream::from(e.write_errors());
85 }
86 };
87
88 let near_sdk_crate = if near_macro_args.inside_nearsdk.unwrap_or(false) {
89 quote! {crate}
90 } else {
91 quote! {::near_sdk}
92 };
93
94 if has_nested_near_macros(item.clone()) {
96 return TokenStream::from(
97 syn::Error::new(
98 Span::call_site(),
99 "#[near] or #[near_bindgen] attributes are not allowed to be nested inside of the outmost #[near] attribute. Only a single #[near] attribute is allowed",
100 )
101 .to_compile_error(),
102 );
103 }
104 let string_borsh_crate = quote! {#near_sdk_crate::borsh}.to_string();
105 let string_serde_crate = quote! {#near_sdk_crate::serde}.to_string();
106 let string_serde_with_crate = quote! {#near_sdk_crate::serde_with}.to_string();
107
108 let mut expanded: proc_macro2::TokenStream = quote! {};
109
110 if near_macro_args.near_bindgen_args.contract_state.is_some() {
111 let near_bindgen_args = near_macro_args.near_bindgen_args;
112 expanded = quote! {#[#near_sdk_crate::near_bindgen(#near_bindgen_args)]};
113 };
114
115 let mut has_borsh = false;
116 let mut has_json = false;
117
118 let mut borsh_attr = quote! {};
119
120 match near_macro_args.serializers {
121 Some(serializers) => {
122 let attr2 = serializers.clone();
123
124 attr2.vec.iter().for_each(|old_expr| {
125 let new_expr = &mut old_expr.clone();
126 match &mut *new_expr {
127 Expr::Call(ref mut call_expr) => {
128 if let Expr::Path(ref mut path) = &mut *call_expr.func {
129 if let Some(ident) = path.path.get_ident() {
130 if *ident == "json" {
131 has_json = true;
132 path.path =
133 syn::Path::from(Ident::new("serde", Span::call_site()));
134 call_expr.args.push(parse_quote! {crate=#string_serde_crate});
135 } else if *ident == "borsh" {
136 has_borsh = true;
137 call_expr.args.push(parse_quote! {crate=#string_borsh_crate});
138 }
139 }
140 }
141 borsh_attr = quote! {#[#new_expr]};
142 }
143 Expr::Path(ref mut path_expr) => {
144 if let Some(ident) = path_expr.path.get_ident() {
145 if *ident == "json" {
146 has_json = true;
147 }
148 if *ident == "borsh" {
149 has_borsh = true;
150 borsh_attr = quote! {#[borsh(crate=#string_borsh_crate)]};
151 }
152 }
153 }
154 _ => {}
155 }
156 });
157 }
158 None => {
159 has_borsh = true;
160 borsh_attr = quote! {#[borsh(crate = #string_borsh_crate)]};
161 }
162 }
163
164 if has_json {
168 let enable_schemars = cfg!(feature = "abi").then_some(quote! {schemars = true,});
169 expanded = quote! {
170 #expanded
171 #[#near_sdk_crate::serde_with::serde_as(
172 crate = #string_serde_with_crate,
173 #enable_schemars
174 )]
175 #[derive(#near_sdk_crate::serde::Serialize, #near_sdk_crate::serde::Deserialize)]
176 #[serde(crate = #string_serde_crate)]
177 };
178 }
179
180 #[cfg(feature = "abi")]
181 {
182 let schema_derive: proc_macro2::TokenStream =
183 get_schema_derive(has_json, has_borsh, near_sdk_crate.clone(), false);
184 expanded = quote! {
185 #expanded
186 #schema_derive
187 };
188 }
189
190 if has_borsh {
191 expanded = quote! {
192 #expanded
193 #[derive(#near_sdk_crate::borsh::BorshSerialize, #near_sdk_crate::borsh::BorshDeserialize)]
194 #borsh_attr
195 };
196 }
197
198 if let Ok(input) = syn::parse::<ItemStruct>(item.clone()) {
199 expanded = quote! {
200 #expanded
201 #input
202 };
203 } else if let Ok(input) = syn::parse::<ItemEnum>(item.clone()) {
204 expanded = quote! {
205 #expanded
206 #input
207 };
208 } else if let Ok(input) = syn::parse::<ItemImpl>(item) {
209 expanded = quote! {
210 #[#near_sdk_crate::near_bindgen]
211 #input
212 };
213 } else {
214 return TokenStream::from(
215 syn::Error::new(
216 Span::call_site(),
217 "near macro can only be used on struct or enum definition and impl sections.",
218 )
219 .to_compile_error(),
220 );
221 }
222
223 TokenStream::from(expanded)
224}
225
226#[derive(Default, FromMeta)]
227struct NearBindgenMacroArgs {
228 contract_state: Option<core_impl::state::ContractStateArgs>,
229 #[darling(default)]
230 contract_metadata: core_impl::ContractMetadata,
231}
232
233impl quote::ToTokens for NearBindgenMacroArgs {
234 fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
235 let contract_state = &self.contract_state;
236 let contract_metadata = &self.contract_metadata;
237 tokens.extend(quote! {
238 contract_state(#contract_state),
239 contract_metadata(#contract_metadata),
240 })
241 }
242}
243
244#[proc_macro_attribute]
245pub fn near_bindgen(attr: TokenStream, item: TokenStream) -> TokenStream {
246 if attr.to_string().contains("event_json") {
247 return core_impl::near_events(attr, item);
248 }
249
250 let (ident, generics) = if let Ok(input) = syn::parse::<ItemStruct>(item.clone()) {
251 (input.ident, input.generics)
252 } else if let Ok(input) = syn::parse::<ItemEnum>(item.clone()) {
253 (input.ident, input.generics)
254 } else if let Ok(input) = syn::parse::<ItemImpl>(item) {
255 for method in &input.items {
256 if let ImplItem::Fn(m) = method {
257 let ident = &m.sig.ident;
258 if ident.eq("__contract_abi") || ident.eq("contract_source_metadata") {
259 return TokenStream::from(
260 syn::Error::new_spanned(
261 ident.to_token_stream(),
262 "use of reserved contract method",
263 )
264 .to_compile_error(),
265 );
266 }
267 }
268 }
269 return match process_impl_block(input) {
270 Ok(output) => output,
271 Err(output) => output,
272 }
273 .into();
274 } else {
275 return TokenStream::from(
276 syn::Error::new(
277 Span::call_site(),
278 "near_bindgen can only be used on struct or enum definition and impl sections.",
279 )
280 .to_compile_error(),
281 );
282 };
283
284 let attr_args = match NestedMeta::parse_meta_list(attr.into()) {
285 Ok(v) => v,
286 Err(e) => {
287 return Error::from(e).write_errors().into();
288 }
289 };
290
291 let args = match NearBindgenMacroArgs::from_list(&attr_args) {
292 Ok(v) => v,
293 Err(e) => {
294 return e.write_errors().into();
295 }
296 };
297
298 let impl_contract_state = args.contract_state.map(|s| s.impl_contract_state(&ident, &generics));
299 let metadata = args.contract_metadata.contract_source_metadata_const();
300
301 let metadata_impl_gen = {
302 let metadata_impl_gen = generate_contract_metadata_method(&ident, &generics).into();
303
304 let metadata_impl_gen = syn::parse::<ItemImpl>(metadata_impl_gen)
305 .expect("failed to generate contract metadata");
306 process_impl_block(metadata_impl_gen)
307 };
308
309 let metadata_impl_gen = match metadata_impl_gen {
310 Ok(metadata) => metadata,
311 Err(err) => return err.into(),
312 };
313
314 let ext_gen = generate_ext_structs(&ident, Some(&generics));
315 #[cfg(feature = "__abi-embed-checked")]
316 let abi_embedded = abi::embed();
317 #[cfg(not(feature = "__abi-embed-checked"))]
318 let abi_embedded = quote! {};
319 let item = proc_macro2::TokenStream::from(item);
320 TokenStream::from(quote! {
321 #item
322 #ext_gen
323 #abi_embedded
324 #metadata
325 #metadata_impl_gen
326 #impl_contract_state
327 })
328}
329
330fn process_impl_block(
337 mut input: ItemImpl,
338) -> Result<proc_macro2::TokenStream, proc_macro2::TokenStream> {
339 let item_impl_info = match ItemImplInfo::new(&mut input) {
340 Ok(x) => x,
341 Err(err) => return Err(err.to_compile_error()),
342 };
343
344 #[cfg(not(feature = "__abi-generate"))]
345 let abi_generated = quote! {};
346 #[cfg(feature = "__abi-generate")]
347 let abi_generated = abi::generate(&item_impl_info);
348
349 let generated_code = item_impl_info.wrapper_code();
350
351 let ext_generated_code = item_impl_info.generate_ext_wrapper_code();
353
354 Ok(TokenStream::from(quote! {
355 #ext_generated_code
356 #input
357 #generated_code
358 #abi_generated
359 })
360 .into())
361}
362
363#[proc_macro_attribute]
364pub fn ext_contract(attr: TokenStream, item: TokenStream) -> TokenStream {
365 if let Ok(mut input) = syn::parse::<ItemTrait>(item) {
366 let mod_name: Option<proc_macro2::Ident> = if attr.is_empty() {
367 None
368 } else {
369 match syn::parse(attr) {
370 Ok(x) => x,
371 Err(err) => {
372 return TokenStream::from(
373 syn::Error::new(
374 Span::call_site(),
375 format!("Failed to parse mod name for ext_contract: {err}"),
376 )
377 .to_compile_error(),
378 )
379 }
380 }
381 };
382 let item_trait_info = match ItemTraitInfo::new(&mut input, mod_name) {
383 Ok(x) => x,
384 Err(err) => return TokenStream::from(err.to_compile_error()),
385 };
386 let ext_api = item_trait_info.wrap_trait_ext();
387
388 TokenStream::from(quote! {
389 #input
390 #ext_api
391 })
392 } else {
393 TokenStream::from(
394 syn::Error::new(Span::call_site(), "ext_contract can only be used on traits")
395 .to_compile_error(),
396 )
397 }
398}
399
400#[cfg(feature = "abi")]
401#[derive(darling::FromDeriveInput, Debug)]
402#[darling(attributes(abi), forward_attrs(serde, borsh_skip, schemars, validate))]
403struct DeriveNearSchema {
404 attrs: Vec<syn::Attribute>,
405 json: Option<bool>,
406 borsh: Option<bool>,
407}
408
409#[proc_macro_derive(NearSchema, attributes(abi, serde, borsh, schemars, validate, inside_nearsdk))]
410pub fn derive_near_schema(#[allow(unused)] input: TokenStream) -> TokenStream {
411 #[cfg(not(feature = "abi"))]
412 {
413 TokenStream::from(quote! {})
414 }
415
416 #[cfg(feature = "abi")]
417 {
418 use darling::FromDeriveInput;
419
420 let derive_input = syn::parse_macro_input!(input as syn::DeriveInput);
421 let generics = derive_input.generics.clone();
422 let args = match DeriveNearSchema::from_derive_input(&derive_input) {
423 Ok(v) => v,
424 Err(e) => {
425 return TokenStream::from(e.write_errors());
426 }
427 };
428
429 if args.borsh.is_none()
430 && args.json.is_none()
431 && derive_input.clone().attrs.iter().any(|attr| attr.path().is_ident("abi"))
432 {
433 return TokenStream::from(
434 syn::Error::new_spanned(
435 derive_input.to_token_stream(),
436 "At least one of `json` or `borsh` inside of `#[abi(...)]` must be specified",
437 )
438 .to_compile_error(),
439 );
440 }
441
442 let (json_schema, borsh_schema) = (args.json.unwrap_or(false), args.borsh.unwrap_or(false));
444 let mut input = derive_input.clone();
445 input.attrs = args.attrs;
446
447 let strip_unknown_attr = |attrs: &mut Vec<syn::Attribute>| {
448 attrs.retain(|attr| {
449 ["serde", "schemars", "validate", "borsh"]
450 .iter()
451 .any(|&path| attr.path().is_ident(path))
452 });
453 };
454
455 match &mut input.data {
456 syn::Data::Struct(data) => {
457 for field in &mut data.fields {
458 strip_unknown_attr(&mut field.attrs);
459 }
460 }
461 syn::Data::Enum(data) => {
462 for variant in &mut data.variants {
463 strip_unknown_attr(&mut variant.attrs);
464 for field in &mut variant.fields {
465 strip_unknown_attr(&mut field.attrs);
466 }
467 }
468 }
469 syn::Data::Union(_) => {
470 return TokenStream::from(
471 syn::Error::new_spanned(
472 input.to_token_stream(),
473 "`NearSchema` does not support derive for unions",
474 )
475 .to_compile_error(),
476 )
477 }
478 }
479
480 let near_sdk_crate =
481 if derive_input.attrs.iter().any(|attr| attr.path().is_ident("inside_nearsdk")) {
482 quote! {crate}
483 } else {
484 quote! {::near_sdk}
485 };
486
487 let json_schema = json_schema || !borsh_schema;
489
490 let derive = get_schema_derive(json_schema, borsh_schema, near_sdk_crate.clone(), true);
491
492 let input_ident = &input.ident;
493
494 let input_ident_proxy = quote::format_ident!("{}__NEAR_SCHEMA_PROXY", input_ident);
495
496 let json_impl = if json_schema {
497 let where_clause = get_where_clause(
498 &generics,
499 input_ident,
500 quote! {#near_sdk_crate::schemars::JsonSchema},
501 );
502 quote! {
503 #[automatically_derived]
504 impl #generics #near_sdk_crate::schemars::JsonSchema for #input_ident_proxy #generics #where_clause {
505 fn schema_name() -> ::std::string::String {
506 <#input_ident #generics as #near_sdk_crate::schemars::JsonSchema>::schema_name()
507 }
508
509 fn json_schema(gen: &mut #near_sdk_crate::schemars::gen::SchemaGenerator) -> #near_sdk_crate::schemars::schema::Schema {
510 <#input_ident #generics as #near_sdk_crate::schemars::JsonSchema>::json_schema(gen)
511 }
512 }
513 }
514 } else {
515 quote! {}
516 };
517
518 let borsh_impl = if borsh_schema {
519 let where_clause = get_where_clause(
520 &generics,
521 input_ident,
522 quote! {#near_sdk_crate::borsh::BorshSchema},
523 );
524 quote! {
525 #[automatically_derived]
526 impl #generics #near_sdk_crate::borsh::BorshSchema for #input_ident_proxy #generics #where_clause {
527 fn declaration() -> #near_sdk_crate::borsh::schema::Declaration {
528 <#input_ident #generics as #near_sdk_crate::borsh::BorshSchema>::declaration()
529 }
530
531 fn add_definitions_recursively(
532 definitions: &mut #near_sdk_crate::borsh::__private::maybestd::collections::BTreeMap<
533 #near_sdk_crate::borsh::schema::Declaration,
534 #near_sdk_crate::borsh::schema::Definition
535 >,
536 ) {
537 <#input_ident #generics as #near_sdk_crate::borsh::BorshSchema>::add_definitions_recursively(definitions);
538 }
539 }
540 }
541 } else {
542 quote! {}
543 };
544
545 TokenStream::from(quote! {
546 #[cfg(not(target_arch = "wasm32"))]
547 const _: () = {
548 #[allow(non_camel_case_types)]
549 type #input_ident_proxy #generics = #input_ident #generics;
550 {
551 #derive
552 #[allow(dead_code)]
553 #input
554
555 #json_impl
556 #borsh_impl
557 };
558 };
559 })
560 }
561}
562
563#[allow(dead_code)]
564fn get_schema_derive(
565 json_schema: bool,
566 borsh_schema: bool,
567 near_sdk_crate: proc_macro2::TokenStream,
568 need_borsh_crate: bool,
569) -> proc_macro2::TokenStream {
570 let string_borsh_crate = quote! {#near_sdk_crate::borsh}.to_string();
571 let string_schemars_crate = quote! {#near_sdk_crate::schemars}.to_string();
572
573 let mut derive = quote! {};
574 if borsh_schema {
575 derive = quote! {
576 #[cfg_attr(not(target_arch = "wasm32"), derive(#near_sdk_crate::borsh::BorshSchema))]
577 };
578 if need_borsh_crate {
579 derive = quote! {
580 #derive
581 #[cfg_attr(not(target_arch = "wasm32"), borsh(crate = #string_borsh_crate))]
582 };
583 }
584 }
585 if json_schema {
586 derive = quote! {
587 #derive
588 #[cfg_attr(not(target_arch = "wasm32"), derive(#near_sdk_crate::schemars::JsonSchema))]
589 #[cfg_attr(not(target_arch = "wasm32"), schemars(crate = #string_schemars_crate))]
590 };
591 }
592 derive
593}
594
595#[cfg(feature = "abi")]
596fn get_where_clause(
597 generics: &syn::Generics,
598 input_ident: &syn::Ident,
599 trait_name: proc_macro2::TokenStream,
600) -> WhereClause {
601 let (_, ty_generics, where_clause) = generics.split_for_impl();
602
603 let predicate = parse_quote!(#input_ident #ty_generics: #trait_name);
604
605 let where_clause: WhereClause = if let Some(mut w) = where_clause.cloned() {
606 w.predicates.push(predicate);
607 w
608 } else {
609 parse_quote!(where #predicate)
610 };
611 where_clause
612}
613
614#[proc_macro_derive(PanicOnDefault)]
615pub fn derive_no_default(item: TokenStream) -> TokenStream {
616 match syn::parse::<Item>(item) {
617 Ok(Item::Enum(ItemEnum { ident, .. })) | Ok(Item::Struct(ItemStruct { ident, .. })) => {
618 TokenStream::from(quote! {
619 const _: () = {
620 #[automatically_derived]
621 impl ::std::default::Default for #ident {
622 fn default() -> Self {
623 ::near_sdk::env::panic_str("The contract is not initialized");
624 }
625 }
626 };
627 })
628 }
629 _ => TokenStream::from(
630 syn::Error::new(
631 Span::call_site(),
632 "PanicOnDefault can only be used on type declarations sections.",
633 )
634 .to_compile_error(),
635 ),
636 }
637}
638
639#[proc_macro_derive(BorshStorageKey)]
640pub fn borsh_storage_key(item: TokenStream) -> TokenStream {
641 let (name, generics) = if let Ok(input) = syn::parse::<ItemEnum>(item.clone()) {
642 (input.ident, input.generics)
643 } else if let Ok(input) = syn::parse::<ItemStruct>(item) {
644 (input.ident, input.generics)
645 } else {
646 return TokenStream::from(
647 syn::Error::new(
648 Span::call_site(),
649 "BorshStorageKey can only be used as a derive on enums or structs.",
650 )
651 .to_compile_error(),
652 );
653 };
654 let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
655 let predicate = parse_quote!(#name #ty_generics: ::near_sdk::borsh::BorshSerialize);
656 let where_clause: WhereClause = if let Some(mut w) = where_clause.cloned() {
657 w.predicates.push(predicate);
658 w
659 } else {
660 parse_quote!(where #predicate)
661 };
662 TokenStream::from(quote! {
663 impl #impl_generics ::near_sdk::__private::BorshIntoStorageKey for #name #ty_generics #where_clause {}
664 })
665}
666
667#[proc_macro_derive(FunctionError)]
668pub fn function_error(item: TokenStream) -> TokenStream {
669 let name = if let Ok(input) = syn::parse::<ItemEnum>(item.clone()) {
670 input.ident
671 } else if let Ok(input) = syn::parse::<ItemStruct>(item) {
672 input.ident
673 } else {
674 return TokenStream::from(
675 syn::Error::new(
676 Span::call_site(),
677 "FunctionError can only be used as a derive on enums or structs.",
678 )
679 .to_compile_error(),
680 );
681 };
682 TokenStream::from(quote! {
683 impl ::near_sdk::FunctionError for #name {
684 fn panic(&self) -> ! {
685 ::near_sdk::env::panic_str(&::std::string::ToString::to_string(&self))
686 }
687 }
688 })
689}
690
691#[proc_macro_derive(EventMetadata, attributes(event_version))]
692pub fn derive_event_attributes(item: TokenStream) -> TokenStream {
693 if let Ok(input) = syn::parse::<ItemEnum>(item) {
694 let name = &input.ident;
695 let standard_name = format!("{name}_event_standard");
697 let standard_ident = syn::Ident::new(&standard_name, Span::call_site());
698 let mut event_meta: Vec<proc_macro2::TokenStream> = vec![];
700 let mut version_arms: Vec<proc_macro2::TokenStream> = vec![];
701 let mut event_name_arms: Vec<proc_macro2::TokenStream> = vec![];
702 for var in &input.variants {
703 if let Some(version) = core_impl::get_event_version(var) {
704 let var_ident = &var.ident;
705 event_meta.push(quote! {
706 #name::#var_ident { .. } => {(::std::string::ToString::to_string(&#standard_ident), ::std::string::ToString::to_string(#version))}
707 });
708 version_arms.push(quote! {
709 #name::#var_ident { .. } => ::std::borrow::Cow::Borrowed(#version)
710 });
711 let event_name =
712 proc_macro2::Literal::string(&var.ident.to_string().to_snake_case());
713 event_name_arms.push(quote! {
714 #name::#var_ident { .. } => ::std::borrow::Cow::Borrowed(#event_name)
715 });
716 } else {
717 return TokenStream::from(
718 syn::Error::new(
719 Span::call_site(),
720 "Near events must have `event_version`. Must have a single string literal value.",
721 )
722 .to_compile_error(),
723 );
724 }
725 }
726
727 let (impl_generics, type_generics, where_clause) = &input.generics.split_for_impl();
729 let mut generics = input.generics.clone();
731 let event_lifetime = syn::Lifetime::new("'near_event", Span::call_site());
732 generics.params.insert(
733 0,
734 syn::GenericParam::Lifetime(syn::LifetimeParam::new(event_lifetime.clone())),
735 );
736
737 TokenStream::from(quote! {
738 impl #impl_generics #name #type_generics #where_clause {
739 pub fn emit(&self) {
740 use ::near_sdk::AsNep297Event;
741 ::near_sdk::env::log_str(&self.to_nep297_event().to_event_log());
742 }
743
744 pub fn to_json(&self) -> ::near_sdk::serde_json::Value {
745 use ::near_sdk::AsNep297Event;
746 self.to_nep297_event().to_json()
747 }
748
749 pub fn standard(&self) -> ::std::borrow::Cow<'_, str> {
750 ::std::borrow::Cow::Borrowed(#standard_ident)
751 }
752
753 pub fn version(&self) -> ::std::borrow::Cow<'_, str> {
754 match self {
755 #(#version_arms),*
756 }
757 }
758
759 pub fn event(&self) -> ::std::borrow::Cow<'_, str> {
760 match self {
761 #(#event_name_arms),*
762 }
763 }
764 }
765
766 impl #impl_generics ::near_sdk::events::AsNep297Event for #name #type_generics #where_clause{
767 fn to_nep297_event(&self) -> ::near_sdk::events::Nep297Event<'_, Self> {
768 ::near_sdk::events::Nep297Event::new(
769 ::std::borrow::Cow::Borrowed(#standard_ident),
770 match self {
771 #(#version_arms),*
772 },
773 match self {
774 #(#event_name_arms),*
775 },
776 self,
777 )
778 }
779 }
780
781
782 })
783 } else {
784 TokenStream::from(
785 syn::Error::new(
786 Span::call_site(),
787 "EventMetadata can only be used as a derive on enums.",
788 )
789 .to_compile_error(),
790 )
791 }
792}