subxt-core crate (#1466)

* start migrating, broken

* first iteration of updating

* fmt and clippy

* add Composite<u32> decoding via scale value patch

* bump scale type gen versions

* fix decoding with new scale decode

* compiling with changed deps

* core utils, condig, client, metadata

* core crate compiling

* signer crate no once lock

* add core to no-std-tests, change imports

* broken commit, start pulling everything together in subxt

* port more things to subxt

* events in core crate, extrinsics sadly much more difficult

* almost all examples pass again

* dynamic values fix in examples

* fix no std issue and fmt

* remove unused dependencies

* fix lightclient impl

* runtime version refactor

* formatting and addressing nits

* more comments addressed

* update wasm example and no-std-signer tests

* other nits and error impl on signer errors

* fix feature flag

* fix runtime version refactor

* fix doc links

* fix integration tests

* fix feature flag gated client state

* fix native feature in CI

* fix lightclient utils

* make imports more lean in subxt-core

* integrate changes from subxt-core imports into subxt

* other changes in subxt simplify imports more

* fix  and docs

* doc false for cli

* fix clippy

* remove events block hash in tests

* codegen no-std support in generated code

* export alloc crate for no-std codegen

* fix doc test

* implement James comments

* remove std traits, use core traits instead

* address nits

* remove unusued dep in no-std tests

* fix Box import in no_std

* sp-crypto-hashing instead of sp-core-hashing

* bump scale-typegen, add no std codegen tests

* fix some things

* replace unmaintained derivative with derive_where to remove non-canonical warnings

* fmt

* remove unused dep

* fix deps

* update artifacts to fix type ID mismatches

* bump to latest scale-typegen

---------

Co-authored-by: James Wilson <james@jsdw.me>
This commit is contained in:
Tadeo Hepperle
2024-03-27 09:55:08 +01:00
committed by GitHub
parent 92c1ba7f66
commit a0cb14aa4f
106 changed files with 24329 additions and 26882 deletions
+10 -5
View File
@@ -6,6 +6,7 @@ use super::CodegenError;
use heck::{ToSnakeCase as _, ToUpperCamelCase as _};
use proc_macro2::TokenStream as TokenStream2;
use quote::{format_ident, quote};
use scale_typegen::typegen::ir::ToTokensWithSettings;
use scale_typegen::{typegen::ir::type_ir::CompositeIRKind, TypeGenerator};
use subxt_metadata::PalletMetadata;
@@ -16,7 +17,7 @@ use subxt_metadata::PalletMetadata;
///
/// - `type_gen` - [`scale_typegen::TypeGenerator`] that contains settings and all types from the runtime metadata.
/// - `pallet` - Pallet metadata from which the calls are generated.
/// - `crate_path` - The crate path under which subxt is located, e.g. `::subxt` when using subxt as a dependency.
/// - `crate_path` - The crate path under which the `subxt-core` crate is located, e.g. `::subxt::ext::subxt_core` when using subxt as a dependency.
pub fn generate_calls(
type_gen: &TypeGenerator,
pallet: &PalletMetadata,
@@ -41,9 +42,9 @@ pub fn generate_calls(
.iter()
.map(|(name, field)| {
// Note: fn_arg_type this is relative the type path of the type alias when prefixed with `types::`, e.g. `set_max_code_size::New`
let fn_arg_type = &field.type_path;
let fn_arg_type = field.type_path.to_token_stream(type_gen.settings());
let call_arg = if field.is_boxed {
quote! { #name: ::std::boxed::Box::new(#name) }
quote! { #name: #crate_path::alloc::boxed::Box::new(#name) }
} else {
quote! { #name }
};
@@ -71,7 +72,9 @@ pub fn generate_calls(
let docs = &var.composite.docs;
// this converts the composite into a full struct type. No Type Parameters needed here.
let struct_def = type_gen.upcast_composite(&var.composite);
let struct_def = type_gen
.upcast_composite(&var.composite)
.to_token_stream(type_gen.settings());
let alias_mod = var.type_alias_mod;
// The call structure's documentation was stripped above.
let call_struct = quote! {
@@ -105,7 +108,9 @@ pub fn generate_calls(
.into_iter()
.unzip();
let call_type = type_gen.resolve_type_path(call_ty)?;
let call_type = type_gen
.resolve_type_path(call_ty)?
.to_token_stream(type_gen.settings());
let call_ty = type_gen.resolve_type(call_ty)?;
let docs = type_gen.docs_from_scale_info(&call_ty.docs);
+5 -2
View File
@@ -5,6 +5,7 @@
use heck::ToSnakeCase as _;
use proc_macro2::TokenStream as TokenStream2;
use quote::{format_ident, quote};
use scale_typegen::typegen::ir::ToTokensWithSettings;
use scale_typegen::TypeGenerator;
use subxt_metadata::PalletMetadata;
@@ -31,7 +32,7 @@ use super::CodegenError;
///
/// - `type_gen` - [`scale_typegen::TypeGenerator`] that contains settings and all types from the runtime metadata.
/// - `pallet` - Pallet metadata from which the constants are generated.
/// - `crate_path` - The crate path under which subxt is located, e.g. `::subxt` when using subxt as a dependency.
/// - `crate_path` - The crate path under which the `subxt-core` crate is located, e.g. `::subxt::ext::subxt_core` when using subxt as a dependency.
pub fn generate_constants(
type_gen: &TypeGenerator,
pallet: &PalletMetadata,
@@ -55,7 +56,9 @@ pub fn generate_constants(
));
};
let return_ty = type_gen.resolve_type_path(constant.ty())?;
let return_ty = type_gen
.resolve_type_path(constant.ty())?
.to_token_stream(type_gen.settings());
let docs = constant.docs();
let docs = type_gen
.settings()
+4 -3
View File
@@ -3,12 +3,13 @@
// see LICENSE for license details.
use heck::ToSnakeCase as _;
use scale_typegen::typegen::ir::ToTokensWithSettings;
use scale_typegen::TypeGenerator;
use std::collections::HashSet;
use subxt_metadata::{CustomValueMetadata, Metadata};
use proc_macro2::TokenStream as TokenStream2;
use quote::{quote, ToTokens};
use quote::quote;
/// Generate the custom values mod, if there are any custom values in the metadata. Else returns None.
pub fn generate_custom_values(
@@ -60,8 +61,8 @@ fn generate_custom_value_fn(
let return_ty = type_gen
.resolve_type_path(custom_value.type_id())
.expect("type is in metadata; qed")
.to_token_stream();
let decodable = quote!(#crate_path::custom_values::Yes);
.to_token_stream(type_gen.settings());
let decodable = quote!(#crate_path::utils::Yes);
(return_ty, decodable)
} else {
// if type registry does not contain the type, we can just return the Encoded scale bytes.
+4 -1
View File
@@ -8,6 +8,7 @@ use scale_typegen::TypeGenerator;
use subxt_metadata::PalletMetadata;
use super::CodegenError;
use scale_typegen::typegen::ir::ToTokensWithSettings;
/// Generate error type alias from the provided pallet metadata.
pub fn generate_error_type_alias(
@@ -18,7 +19,9 @@ pub fn generate_error_type_alias(
return Ok(quote!());
};
let error_type = type_gen.resolve_type_path(error_ty)?;
let error_type = type_gen
.resolve_type_path(error_ty)?
.to_token_stream(type_gen.settings());
let error_ty = type_gen.resolve_type(error_ty)?;
let docs = &error_ty.docs;
let docs = type_gen
+9 -5
View File
@@ -2,13 +2,13 @@
// This file is dual-licensed as Apache-2.0 or GPL-3.0.
// see LICENSE for license details.
use super::CodegenError;
use proc_macro2::TokenStream as TokenStream2;
use quote::quote;
use scale_typegen::typegen::ir::ToTokensWithSettings;
use scale_typegen::TypeGenerator;
use subxt_metadata::PalletMetadata;
use super::CodegenError;
/// Generate events from the provided pallet metadata.
///
/// The function creates a new module named `events` under the pallet's module.
@@ -37,7 +37,7 @@ use super::CodegenError;
///
/// - `type_gen` - [`scale_typegen::TypeGenerator`] that contains settings and all types from the runtime metadata.
/// - `pallet` - Pallet metadata from which the events are generated.
/// - `crate_path` - The crate path under which subxt is located, e.g. `::subxt` when using subxt as a dependency.
/// - `crate_path` - The crate path under which the `subxt-core` crate is located, e.g. `::subxt::ext::subxt_core` when using subxt as a dependency.
pub fn generate_events(
type_gen: &TypeGenerator,
pallet: &PalletMetadata,
@@ -56,7 +56,9 @@ pub fn generate_events(
let event_struct_name = &var.composite.name;
let event_name = var.variant_name;
let alias_mod = var.type_alias_mod;
let struct_def = type_gen.upcast_composite(&var.composite);
let struct_def = type_gen
.upcast_composite(&var.composite)
.to_token_stream(type_gen.settings());
quote! {
#struct_def
#alias_mod
@@ -68,7 +70,9 @@ pub fn generate_events(
}
});
let event_type = type_gen.resolve_type_path(event_ty)?;
let event_type = type_gen
.resolve_type_path(event_ty)?
.to_token_stream(type_gen.settings());
let event_ty = type_gen.resolve_type(event_ty)?;
let docs = &event_ty.docs;
let docs = type_gen
+18 -7
View File
@@ -13,6 +13,7 @@ mod runtime_apis;
mod storage;
use scale_typegen::typegen::ir::type_ir::{CompositeFieldIR, CompositeIR, CompositeIRKind};
use scale_typegen::typegen::ir::ToTokensWithSettings;
use scale_typegen::typegen::type_params::TypeParameters;
use scale_typegen::typegen::type_path::TypePath;
use scale_typegen::TypeGenerator;
@@ -44,7 +45,7 @@ impl RuntimeGenerator {
///
/// Supported versions: v14 and v15.
pub fn new(mut metadata: Metadata) -> Self {
metadata.ensure_unique_type_paths();
scale_typegen::utils::ensure_unique_type_paths(metadata.types_mut());
RuntimeGenerator { metadata }
}
@@ -72,7 +73,9 @@ impl RuntimeGenerator {
subxt_type_gen_settings(derives, type_substitutes, &crate_path, should_gen_docs);
let type_gen = TypeGenerator::new(self.metadata.types(), &settings);
let types_mod = type_gen.generate_types_mod()?;
let types_mod = type_gen
.generate_types_mod()?
.to_token_stream(type_gen.settings());
let mod_ident = &item_mod_ir.ident;
let rust_items = item_mod_ir.rust_items();
@@ -121,7 +124,9 @@ impl RuntimeGenerator {
subxt_type_gen_settings(derives, type_substitutes, &crate_path, should_gen_docs);
let type_gen = TypeGenerator::new(self.metadata.types(), &settings);
let types_mod = type_gen.generate_types_mod()?;
let types_mod = type_gen
.generate_types_mod()?
.to_token_stream(type_gen.settings());
let types_mod_ident = type_gen.types_mod_ident();
let pallets_with_mod_names = self
.metadata
@@ -214,9 +219,15 @@ impl RuntimeGenerator {
// Fetch the paths of the outer enums.
// Substrate exposes those under `kitchensink_runtime`, while Polkadot under `polkadot_runtime`.
let call_path = type_gen.resolve_type_path(self.metadata.outer_enums().call_enum_ty())?;
let event_path = type_gen.resolve_type_path(self.metadata.outer_enums().event_enum_ty())?;
let error_path = type_gen.resolve_type_path(self.metadata.outer_enums().error_enum_ty())?;
let call_path = type_gen
.resolve_type_path(self.metadata.outer_enums().call_enum_ty())?
.to_token_stream(type_gen.settings());
let event_path = type_gen
.resolve_type_path(self.metadata.outer_enums().event_enum_ty())?
.to_token_stream(type_gen.settings());
let error_path = type_gen
.resolve_type_path(self.metadata.outer_enums().error_enum_ty())?
.to_token_stream(type_gen.settings());
let custom_values = generate_custom_values(&self.metadata, &type_gen, &crate_path);
@@ -399,7 +410,7 @@ pub fn generate_type_alias_mod(
.expect("composite name in snake_case should be a valid identifier");
let mut modify_field_to_be_type_alias = |field: &mut CompositeFieldIR, alias_name: Ident| {
let type_path = &field.type_path;
let type_path = field.type_path.to_token_stream(type_gen.settings());
aliases.push(quote!(pub type #alias_name = #type_path;));
let type_alias_path: syn::Path = parse_quote!(#alias_mod_name::#alias_name);
+3 -2
View File
@@ -7,6 +7,7 @@ use std::collections::HashSet;
use heck::ToSnakeCase as _;
use heck::ToUpperCamelCase as _;
use scale_typegen::typegen::ir::ToTokensWithSettings;
use scale_typegen::TypeGenerator;
use subxt_metadata::{Metadata, RuntimeApiMetadata};
@@ -77,7 +78,7 @@ fn generate_runtime_api(
// Generate alias for runtime type.
let ty = type_gen
.resolve_type_path(input.ty)
.expect("runtime api input type is in metadata; qed");
.expect("runtime api input type is in metadata; qed").to_token_stream(type_gen.settings());
let aliased_param = quote!( pub type #alias_name = #ty; );
// Structures are placed on the same level as the alias module.
@@ -96,7 +97,7 @@ fn generate_runtime_api(
let type_aliases = inputs.iter().map(|(_, _, _, aliased_param)| aliased_param);
let types_mod_ident = type_gen.types_mod_ident();
let output = type_gen.resolve_type_path(method.output_ty())?;
let output = type_gen.resolve_type_path(method.output_ty())?.to_token_stream(type_gen.settings());
let aliased_module = quote!(
pub mod #method_name {
use super::#types_mod_ident;
+17 -10
View File
@@ -13,6 +13,8 @@ use subxt_metadata::{
use super::CodegenError;
use scale_typegen::typegen::ir::ToTokensWithSettings;
/// Generate functions which create storage addresses from the provided pallet's metadata.
/// These addresses can be used to access and iterate over storage values.
///
@@ -20,7 +22,7 @@ use super::CodegenError;
///
/// - `type_gen` - [`scale_typegen::TypeGenerator`] that contains settings and all types from the runtime metadata.
/// - `pallet` - Pallet metadata from which the storage items are generated.
/// - `crate_path` - The crate path under which subxt is located, e.g. `::subxt` when using subxt as a dependency.
/// - `crate_path` - The crate path under which the `subxt-core` crate is located, e.g. `::subxt::ext::subxt_core` when using subxt as a dependency.
pub fn generate_storage(
type_gen: &TypeGenerator,
pallet: &PalletMetadata,
@@ -69,7 +71,8 @@ fn generate_storage_entry_fns(
let storage_entry_ty = storage_entry.entry_type().value_ty();
let storage_entry_value_ty = type_gen
.resolve_type_path(storage_entry_ty)
.expect("storage type is in metadata; qed");
.expect("storage type is in metadata; qed")
.to_token_stream(type_gen.settings());
let alias_name = format_ident!("{}", storage_entry.name().to_upper_camel_case());
let alias_module_name = format_ident!("{snake_case_name}");
@@ -89,7 +92,7 @@ fn generate_storage_entry_fns(
.expect("type is in metadata; qed");
let alias_name = format_ident!("Param{}", idx);
let alias_type = primitive_type_alias(&ty_path);
let alias_type = primitive_type_alias(&ty_path, type_gen.settings());
let alias_type_def = quote!( pub type #alias_name = #alias_type; );
let alias_type_path = quote!( types::#alias_module_name::#alias_name );
@@ -169,7 +172,7 @@ fn generate_storage_entry_fns(
.unwrap_or_default();
let is_defaultable_type = match storage_entry.modifier() {
StorageEntryModifier::Default => quote!(#crate_path::storage::address::Yes),
StorageEntryModifier::Default => quote!(#crate_path::utils::Yes),
StorageEntryModifier::Optional => quote!(()),
};
@@ -191,10 +194,10 @@ fn generate_storage_entry_fns(
(fn_name, false, true)
};
let is_fetchable_type = is_fetchable
.then_some(quote!(#crate_path::storage::address::Yes))
.then_some(quote!(#crate_path::utils::Yes))
.unwrap_or(quote!(()));
let is_iterable_type = is_iterable
.then_some(quote!(#crate_path::storage::address::Yes))
.then_some(quote!(#crate_path::utils::Yes))
.unwrap_or(quote!(()));
let (keys, keys_type) = match keys_slice.len() {
@@ -247,7 +250,7 @@ fn generate_storage_entry_fns(
arg_name,
alias_type_path,
..
}| quote!( #arg_name: impl ::std::borrow::Borrow<#alias_type_path> ),
}| quote!( #arg_name: impl ::core::borrow::Borrow<#alias_type_path> ),
);
quote!(
@@ -297,16 +300,20 @@ fn generate_storage_entry_fns(
))
}
fn primitive_type_alias(type_path: &TypePath) -> TokenStream {
fn primitive_type_alias(
type_path: &TypePath,
settings: &scale_typegen::TypeGeneratorSettings,
) -> TokenStream {
// Vec<T> is cast to [T]
if let Some(ty) = type_path.vec_type_param() {
let ty = ty.to_token_stream(settings);
return quote!([#ty]);
}
// String is cast to str
if type_path.is_string() {
return quote!(::core::primitive::str);
}
quote!(#type_path)
type_path.to_token_stream(settings)
}
#[cfg(test)]
@@ -424,7 +431,7 @@ mod tests {
let expected_storage_constructor = quote!(
fn #name_ident(
&self,
_0: impl ::std::borrow::Borrow<types::#name_ident::Param0>,
_0: impl ::core::borrow::Borrow<types::#name_ident::Param0>,
)
);
dbg!(&generated_str);