use crate::construct_runtime::{parse::PalletPath, Pallet};
use proc_macro2::TokenStream;
use quote::quote;
use std::str::FromStr;
use syn::Ident;
pub fn expand_runtime_metadata(
runtime: &Ident,
pallet_declarations: &[Pallet],
scrate: &TokenStream,
extrinsic: &TokenStream,
system_path: &PalletPath,
) -> TokenStream {
let pallets = pallet_declarations
.iter()
.filter_map(|pallet_declaration| {
pallet_declaration.find_part("Pallet").map(|_| {
let filtered_names: Vec<_> = pallet_declaration
.pallet_parts()
.iter()
.filter(|part| part.name() != "Pallet")
.map(|part| part.name())
.collect();
(pallet_declaration, filtered_names)
})
})
.map(|(decl, filtered_names)| {
let name = &decl.name;
let index = &decl.index;
let storage = expand_pallet_metadata_storage(&filtered_names, runtime, decl);
let calls = expand_pallet_metadata_calls(&filtered_names, runtime, decl);
let event = expand_pallet_metadata_events(&filtered_names, runtime, decl);
let constants = expand_pallet_metadata_constants(runtime, decl);
let errors = expand_pallet_metadata_errors(runtime, decl);
let docs = expand_pallet_metadata_docs(runtime, decl);
let attr = decl.cfg_pattern.iter().fold(TokenStream::new(), |acc, pattern| {
let attr = TokenStream::from_str(&format!("#[cfg({})]", pattern.original()))
.expect("was successfully parsed before; qed");
quote! {
#acc
#attr
}
});
let deprecation_info = expand_pallet_metadata_deprecation(runtime, decl);
quote! {
#attr
#scrate::__private::metadata_ir::PalletMetadataIR {
name: stringify!(#name),
index: #index,
storage: #storage,
calls: #calls,
event: #event,
constants: #constants,
error: #errors,
docs: #docs,
deprecation_info: #deprecation_info,
}
}
})
.collect::<Vec<_>>();
quote! {
impl #runtime {
fn metadata_ir() -> #scrate::__private::metadata_ir::MetadataIR {
let rt = #runtime;
let ty = #scrate::__private::scale_info::meta_type::<#extrinsic>();
let address_ty = #scrate::__private::scale_info::meta_type::<
<<#extrinsic as #scrate::sp_runtime::traits::Extrinsic>::SignaturePayload as #scrate::sp_runtime::traits::SignaturePayload>::SignatureAddress
>();
let call_ty = #scrate::__private::scale_info::meta_type::<
<#extrinsic as #scrate::sp_runtime::traits::Extrinsic>::Call
>();
let signature_ty = #scrate::__private::scale_info::meta_type::<
<<#extrinsic as #scrate::sp_runtime::traits::Extrinsic>::SignaturePayload as #scrate::sp_runtime::traits::SignaturePayload>::Signature
>();
let extra_ty = #scrate::__private::scale_info::meta_type::<
<<#extrinsic as #scrate::sp_runtime::traits::Extrinsic>::SignaturePayload as #scrate::sp_runtime::traits::SignaturePayload>::SignatureExtra
>();
#scrate::__private::metadata_ir::MetadataIR {
pallets: #scrate::__private::vec![ #(#pallets),* ],
extrinsic: #scrate::__private::metadata_ir::ExtrinsicMetadataIR {
ty,
version: <#extrinsic as #scrate::sp_runtime::traits::ExtrinsicMetadata>::VERSION,
address_ty,
call_ty,
signature_ty,
extra_ty,
signed_extensions: <
<
#extrinsic as #scrate::sp_runtime::traits::ExtrinsicMetadata
>::SignedExtensions as #scrate::sp_runtime::traits::SignedExtension
>::metadata()
.into_iter()
.map(|meta| #scrate::__private::metadata_ir::SignedExtensionMetadataIR {
identifier: meta.identifier,
ty: meta.ty,
additional_signed: meta.additional_signed,
})
.collect(),
},
ty: #scrate::__private::scale_info::meta_type::<#runtime>(),
apis: (&rt).runtime_metadata(),
outer_enums: #scrate::__private::metadata_ir::OuterEnumsIR {
call_enum_ty: #scrate::__private::scale_info::meta_type::<
<#runtime as #system_path::Config>::RuntimeCall
>(),
event_enum_ty: #scrate::__private::scale_info::meta_type::<RuntimeEvent>(),
error_enum_ty: #scrate::__private::scale_info::meta_type::<RuntimeError>(),
}
}
}
pub fn metadata() -> #scrate::__private::metadata::RuntimeMetadataPrefixed {
#scrate::__private::metadata_ir::into_v14(#runtime::metadata_ir())
}
pub fn metadata_at_version(version: u32) -> Option<#scrate::__private::OpaqueMetadata> {
#scrate::__private::metadata_ir::into_version(#runtime::metadata_ir(), version).map(|prefixed| {
#scrate::__private::OpaqueMetadata::new(prefixed.into())
})
}
pub fn metadata_versions() -> #scrate::__private::Vec<u32> {
#scrate::__private::metadata_ir::supported_versions()
}
}
}
}
fn expand_pallet_metadata_storage(
filtered_names: &[&'static str],
runtime: &Ident,
decl: &Pallet,
) -> TokenStream {
if filtered_names.contains(&"Storage") {
let instance = decl.instance.as_ref().into_iter();
let path = &decl.path;
quote! {
Some(#path::Pallet::<#runtime #(, #path::#instance)*>::storage_metadata())
}
} else {
quote!(None)
}
}
fn expand_pallet_metadata_calls(
filtered_names: &[&'static str],
runtime: &Ident,
decl: &Pallet,
) -> TokenStream {
if filtered_names.contains(&"Call") {
let instance = decl.instance.as_ref().into_iter();
let path = &decl.path;
quote! {
Some(#path::Pallet::<#runtime #(, #path::#instance)*>::call_functions())
}
} else {
quote!(None)
}
}
fn expand_pallet_metadata_events(
filtered_names: &[&'static str],
runtime: &Ident,
decl: &Pallet,
) -> TokenStream {
if filtered_names.contains(&"Event") {
let path = &decl.path;
let part_is_generic = !decl
.find_part("Event")
.expect("Event part exists; qed")
.generics
.params
.is_empty();
let pallet_event = match (decl.instance.as_ref(), part_is_generic) {
(Some(inst), true) => quote!(#path::Event::<#runtime, #path::#inst>),
(Some(inst), false) => quote!(#path::Event::<#path::#inst>),
(None, true) => quote!(#path::Event::<#runtime>),
(None, false) => quote!(#path::Event),
};
quote! {
Some(
#pallet_event::event_metadata::<#pallet_event>()
)
}
} else {
quote!(None)
}
}
fn expand_pallet_metadata_deprecation(runtime: &Ident, decl: &Pallet) -> TokenStream {
let path = &decl.path;
let instance = decl.instance.as_ref().into_iter();
quote! { #path::Pallet::<#runtime #(, #path::#instance)*>::deprecation_info() }
}
fn expand_pallet_metadata_constants(runtime: &Ident, decl: &Pallet) -> TokenStream {
let path = &decl.path;
let instance = decl.instance.as_ref().into_iter();
quote! {
#path::Pallet::<#runtime #(, #path::#instance)*>::pallet_constants_metadata()
}
}
fn expand_pallet_metadata_errors(runtime: &Ident, decl: &Pallet) -> TokenStream {
let path = &decl.path;
let instance = decl.instance.as_ref().into_iter();
quote! {
#path::Pallet::<#runtime #(, #path::#instance)*>::error_metadata()
}
}
fn expand_pallet_metadata_docs(runtime: &Ident, decl: &Pallet) -> TokenStream {
let path = &decl.path;
let instance = decl.instance.as_ref().into_iter();
quote! {
#path::Pallet::<#runtime #(, #path::#instance)*>::pallet_documentation_metadata()
}
}