XXX: Generate Runtime API

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>
This commit is contained in:
Alexandru Vasile
2023-02-07 19:16:19 +02:00
parent 7038902c74
commit cd497aba54
10 changed files with 57231 additions and 27 deletions
File diff suppressed because one or more lines are too long
+18 -8
View File
@@ -7,11 +7,14 @@
mod calls;
mod constants;
mod events;
mod runtime_api;
mod storage;
use scale_info::form::PortableForm;
use subxt_metadata::get_metadata_per_pallet_hash;
use self::runtime_api::generate_runtime_api;
use super::DerivesRegistry;
use crate::{
ir,
@@ -139,7 +142,11 @@ pub fn generate_runtime_api_from_bytes(
type_substitutes: TypeSubstitutes,
crate_path: CratePath,
) -> TokenStream2 {
let metadata = frame_metadata::RuntimeMetadataPrefixed::decode(&mut &bytes[..])
let decoded: Option<frame_metadata::OpaqueMetadata> = Decode::decode(&mut &*bytes)
.unwrap_or_else(|e| abort_call_site!("Failed to decode opaque metadata: {}", e));
let decoded = decoded.unwrap();
let bytes = &decoded.0;
let metadata: RuntimeMetadataPrefixed = Decode::decode(&mut &bytes[..])
.unwrap_or_else(|e| abort_call_site!("Failed to decode metadata: {}", e));
let generator = RuntimeGenerator::new(metadata);
@@ -157,8 +164,6 @@ fn generate_runtime_call_api(
) -> TokenStream2 {
let mut result = quote!();
println!("inside runtime: {:?}", runtime);
for trait_ in runtime {
for method in &trait_.methods {
let trait_name = trait_.name.clone();
@@ -188,8 +193,6 @@ fn generate_runtime_call_api(
}
}
println!("Code gen would generate: {}", result);
result
}
@@ -247,6 +250,10 @@ impl RuntimeGenerator {
})
.collect::<Vec<_>>();
// Generate the runtime API.
let runtime_api =
generate_runtime_api(&self.metadata, &type_gen, types_mod_ident, &crate_path);
// Pallet names and their length are used to create PALLETS array.
// The array is used to identify the pallets composing the metadata for
// validation of just those pallets.
@@ -377,9 +384,9 @@ impl RuntimeGenerator {
TransactionApi
}
pub mod runtime_api {
#runtime_api_fns
}
// pub mod runtime_api {
// #runtime_api_fns
// }
pub struct ConstantsApi;
impl ConstantsApi {
@@ -417,6 +424,9 @@ impl RuntimeGenerator {
Ok(())
}
}
/// Runtime API.
#runtime_api
}
}
}
+106
View File
@@ -0,0 +1,106 @@
// Copyright 2019-2022 Parity Technologies (UK) Ltd.
// This file is dual-licensed as Apache-2.0 or GPL-3.0.
// see LICENSE for license details.
use crate::{
types::TypeGenerator,
CratePath,
};
use frame_metadata::v15::{
RuntimeMetadataV15,
TraitMetadata,
};
use proc_macro2::TokenStream as TokenStream2;
use quote::{
format_ident,
quote,
};
use scale_info::form::PortableForm;
/// Generates the accessor functions for the given trait.
fn generate_trait_api(
trait_: &TraitMetadata<PortableForm>,
type_gen: &TypeGenerator,
types_mod_ident: &syn::Ident,
crate_path: &CratePath,
) -> TokenStream2 {
let trait_name = &trait_.name;
let docs = &trait_.docs;
const VEC_ACC: &'static str = "result";
let vec_acc = format_ident!("{}", VEC_ACC);
let methods: Vec<_> = trait_.methods.iter().map(|method| {
let method_name = format_ident!("{}", &method.name);
let func_name = format!("{}_{}", trait_name, method_name);
let docs = &method.docs;
let inputs: Vec<_> = method.inputs.iter().map(|input| {
let name = format_ident!("{}", &input.name);
let ty = type_gen.resolve_type_path(input.ty.id());
let param = quote!(#name: #ty);
let encoded = quote!(#name.encode_to(&mut #vec_acc));
(param, encoded)
}).collect();
let params = inputs.iter().map(|(param, _)| param);
let encoded = inputs.iter().map(|(_, encoded)| encoded);
quote!(
#( #[doc = #docs ] )*
pub fn #method_name( #( #params, )* ) -> #crate_path::runtime_api::RuntimeAPIPayload {
let mut #vec_acc = Vec::new();
#( #encoded; )*
#crate_path::runtime_api::RuntimeAPIPayload::new(
#func_name,
#vec_acc,
[0; 32],
)
}
)
}).collect();
let trait_name = format_ident!("{}", &trait_.name);
quote!(
#( #[doc = #docs ] )*
pub mod #trait_name {
use super::root_mod;
use super::#types_mod_ident;
use #crate_path::ext::codec::Encode;
#( #methods )*
}
)
}
/// Generate the runtime API.
pub fn generate_runtime_api(
metadata: &RuntimeMetadataV15,
type_gen: &TypeGenerator,
types_mod_ident: &syn::Ident,
crate_path: &CratePath,
) -> TokenStream2 {
let runtime = &metadata.runtime;
if runtime.is_empty() {
return quote!()
}
let runtime_mods = runtime
.iter()
.map(|rt| generate_trait_api(rt, type_gen, &types_mod_ident, crate_path));
quote! {
pub mod runtime_api {
use super::root_mod;
use super::#types_mod_ident;
#( #runtime_mods )*
}
}
}
+20 -2
View File
@@ -63,7 +63,16 @@ async fn fetch_metadata_ws(url: &Uri) -> Result<String, FetchMetadataError> {
.max_notifs_per_subscription(4096)
.build_with_tokio(sender, receiver);
Ok(client.request("state_getMetadata", rpc_params![]).await?)
use codec::Encode;
let bytes = 15u32.encode();
let param = format!("0x{}", hex::encode(&bytes));
Ok(client
.request(
"state_call",
rpc_params!["Metadata_metadata_at_version", &param],
)
.await?)
}
async fn fetch_metadata_http(url: &Uri) -> Result<String, FetchMetadataError> {
@@ -71,7 +80,16 @@ async fn fetch_metadata_http(url: &Uri) -> Result<String, FetchMetadataError> {
.request_timeout(Duration::from_secs(180))
.build(url.to_string())?;
Ok(client.request("state_getMetadata", rpc_params![]).await?)
use codec::Encode;
let bytes = 15u32.encode();
let param = format!("0x{}", hex::encode(&bytes));
Ok(client
.request(
"state_call",
rpc_params!["Metadata_metadata_at_version", &param],
)
.await?)
}
#[derive(Debug)]