mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-31 11:01:01 +00:00
Merge branch 'master' into jsdw-subxt-new
This commit is contained in:
Generated
+1
-1
@@ -5739,7 +5739,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "subxt-historic"
|
name = "subxt-historic"
|
||||||
version = "0.0.7"
|
version = "0.0.8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"frame-decode",
|
"frame-decode",
|
||||||
"frame-metadata 23.0.0",
|
"frame-metadata 23.0.0",
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -4,6 +4,10 @@ This is separate from the Subxt changelog as subxt-historic is currently releasa
|
|||||||
|
|
||||||
Eventually this project will merge with Subxt and no longer exist, but until then it's being maintained and updated where needed.
|
Eventually this project will merge with Subxt and no longer exist, but until then it's being maintained and updated where needed.
|
||||||
|
|
||||||
|
## 0.0.8 (2025-12-04)
|
||||||
|
|
||||||
|
Expose `ClientAtBlock::resolver()`. This hands back a type resolver which is capable of resolving type IDs given by the `.visit()` methods on extrinsic fields and storage values. The extrinsics example has been modified to show how this can be used.
|
||||||
|
|
||||||
## 0.0.7 (2025-12-03)
|
## 0.0.7 (2025-12-03)
|
||||||
|
|
||||||
Expose `OfflineClientAtBlock`, `OfflineClientAtBlockT`, `OnlinelientAtBlock`, `OnlineClientAtBlockT`.
|
Expose `OfflineClientAtBlock`, `OfflineClientAtBlockT`, `OnlinelientAtBlock`, `OnlineClientAtBlockT`.
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "subxt-historic"
|
name = "subxt-historic"
|
||||||
version = "0.0.7"
|
version = "0.0.8"
|
||||||
authors.workspace = true
|
authors.workspace = true
|
||||||
edition.workspace = true
|
edition.workspace = true
|
||||||
rust-version.workspace = true
|
rust-version.workspace = true
|
||||||
|
|||||||
@@ -48,7 +48,8 @@ async fn main() -> Result<(), Box<dyn core::error::Error + Send + Sync + 'static
|
|||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
|
|
||||||
// When visiting fields we can also decode into a custom shape like so:
|
// When visiting fields we can also decode into a custom shape like so:
|
||||||
let _custom_value = field.visit(value::GetValue::new())?;
|
let _custom_value =
|
||||||
|
field.visit(value::GetValue::new(&client_at_block.resolver()))?;
|
||||||
|
|
||||||
// We can also obtain and decode things without the complexity of the above:
|
// We can also obtain and decode things without the complexity of the above:
|
||||||
println!(
|
println!(
|
||||||
@@ -183,7 +184,8 @@ mod value {
|
|||||||
I256([u8; 32]),
|
I256([u8; 32]),
|
||||||
U256([u8; 32]),
|
U256([u8; 32]),
|
||||||
Struct(HashMap<String, Value>),
|
Struct(HashMap<String, Value>),
|
||||||
Variant(String, VariantFields),
|
VariantWithoutData(String),
|
||||||
|
VariantWithData(String, VariantFields),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum VariantFields {
|
pub enum VariantFields {
|
||||||
@@ -198,23 +200,23 @@ mod value {
|
|||||||
Decode(#[from] scale_decode::visitor::DecodeError),
|
Decode(#[from] scale_decode::visitor::DecodeError),
|
||||||
#[error("Cannot decode bit sequence: {0}")]
|
#[error("Cannot decode bit sequence: {0}")]
|
||||||
CannotDecodeBitSequence(codec::Error),
|
CannotDecodeBitSequence(codec::Error),
|
||||||
|
#[error("Cannot resolve variant type information: {0}")]
|
||||||
|
CannotResolveVariantType(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This is a visitor which obtains type names.
|
/// This is a visitor which obtains type names.
|
||||||
pub struct GetValue<R> {
|
pub struct GetValue<'r, R> {
|
||||||
marker: core::marker::PhantomData<R>,
|
resolver: &'r R,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<R> GetValue<R> {
|
impl<'r, R> GetValue<'r, R> {
|
||||||
/// Construct our TypeName visitor.
|
/// Construct our TypeName visitor.
|
||||||
pub fn new() -> Self {
|
pub fn new(resolver: &'r R) -> Self {
|
||||||
GetValue {
|
GetValue { resolver }
|
||||||
marker: core::marker::PhantomData,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<R: TypeResolver> Visitor for GetValue<R> {
|
impl<'r, R: TypeResolver> Visitor for GetValue<'r, R> {
|
||||||
type Value<'scale, 'resolver> = Value;
|
type Value<'scale, 'resolver> = Value;
|
||||||
type Error = ValueError;
|
type Error = ValueError;
|
||||||
type TypeResolver = R;
|
type TypeResolver = R;
|
||||||
@@ -346,7 +348,11 @@ mod value {
|
|||||||
values: &mut Array<'scale, 'resolver, Self::TypeResolver>,
|
values: &mut Array<'scale, 'resolver, Self::TypeResolver>,
|
||||||
_type_id: TypeIdFor<Self>,
|
_type_id: TypeIdFor<Self>,
|
||||||
) -> Result<Self::Value<'scale, 'resolver>, Self::Error> {
|
) -> Result<Self::Value<'scale, 'resolver>, Self::Error> {
|
||||||
Ok(Value::Array(to_array(values.remaining(), values)?))
|
Ok(Value::Array(to_array(
|
||||||
|
self.resolver,
|
||||||
|
values.remaining(),
|
||||||
|
values,
|
||||||
|
)?))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_sequence<'scale, 'resolver>(
|
fn visit_sequence<'scale, 'resolver>(
|
||||||
@@ -354,7 +360,11 @@ mod value {
|
|||||||
values: &mut Sequence<'scale, 'resolver, Self::TypeResolver>,
|
values: &mut Sequence<'scale, 'resolver, Self::TypeResolver>,
|
||||||
_type_id: TypeIdFor<Self>,
|
_type_id: TypeIdFor<Self>,
|
||||||
) -> Result<Self::Value<'scale, 'resolver>, Self::Error> {
|
) -> Result<Self::Value<'scale, 'resolver>, Self::Error> {
|
||||||
Ok(Value::Array(to_array(values.remaining(), values)?))
|
Ok(Value::Array(to_array(
|
||||||
|
self.resolver,
|
||||||
|
values.remaining(),
|
||||||
|
values,
|
||||||
|
)?))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_str<'scale, 'resolver>(
|
fn visit_str<'scale, 'resolver>(
|
||||||
@@ -370,7 +380,11 @@ mod value {
|
|||||||
values: &mut Tuple<'scale, 'resolver, Self::TypeResolver>,
|
values: &mut Tuple<'scale, 'resolver, Self::TypeResolver>,
|
||||||
_type_id: TypeIdFor<Self>,
|
_type_id: TypeIdFor<Self>,
|
||||||
) -> Result<Self::Value<'scale, 'resolver>, Self::Error> {
|
) -> Result<Self::Value<'scale, 'resolver>, Self::Error> {
|
||||||
Ok(Value::Array(to_array(values.remaining(), values)?))
|
Ok(Value::Array(to_array(
|
||||||
|
self.resolver,
|
||||||
|
values.remaining(),
|
||||||
|
values,
|
||||||
|
)?))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_bitsequence<'scale, 'resolver>(
|
fn visit_bitsequence<'scale, 'resolver>(
|
||||||
@@ -401,7 +415,7 @@ mod value {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Reuse logic for decoding variant fields:
|
// Reuse logic for decoding variant fields:
|
||||||
match to_variant_fieldish(value)? {
|
match to_variant_fieldish(self.resolver, value)? {
|
||||||
VariantFields::Named(s) => Ok(Value::Struct(s)),
|
VariantFields::Named(s) => Ok(Value::Struct(s)),
|
||||||
VariantFields::Unnamed(a) => Ok(Value::Array(a)),
|
VariantFields::Unnamed(a) => Ok(Value::Array(a)),
|
||||||
}
|
}
|
||||||
@@ -410,20 +424,50 @@ mod value {
|
|||||||
fn visit_variant<'scale, 'resolver>(
|
fn visit_variant<'scale, 'resolver>(
|
||||||
self,
|
self,
|
||||||
value: &mut Variant<'scale, 'resolver, Self::TypeResolver>,
|
value: &mut Variant<'scale, 'resolver, Self::TypeResolver>,
|
||||||
_type_id: TypeIdFor<Self>,
|
type_id: TypeIdFor<Self>,
|
||||||
) -> Result<Self::Value<'scale, 'resolver>, Self::Error> {
|
) -> Result<Self::Value<'scale, 'resolver>, Self::Error> {
|
||||||
|
// Because we have access to a type resolver on self, we can
|
||||||
|
// look up the type IDs we're given back and base decode decisions
|
||||||
|
// on them. here we see whether the enum type has any data attached:
|
||||||
|
let has_data_visitor = scale_type_resolver::visitor::new((), |_, _| false)
|
||||||
|
.visit_variant(|_, _, variants| {
|
||||||
|
for mut variant in variants {
|
||||||
|
if variant.fields.next().is_some() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
false
|
||||||
|
});
|
||||||
|
|
||||||
|
// Do any variants have data in this enum type?
|
||||||
|
let has_data = self
|
||||||
|
.resolver
|
||||||
|
.resolve_type(type_id, has_data_visitor)
|
||||||
|
.map_err(|e| ValueError::CannotResolveVariantType(e.to_string()))?;
|
||||||
|
|
||||||
let name = value.name().to_owned();
|
let name = value.name().to_owned();
|
||||||
let fields = to_variant_fieldish(value.fields())?;
|
|
||||||
Ok(Value::Variant(name, fields))
|
// base our decoding on whether any data in enum type.
|
||||||
|
if has_data {
|
||||||
|
let fields = to_variant_fieldish(self.resolver, value.fields())?;
|
||||||
|
Ok(Value::VariantWithData(name, fields))
|
||||||
|
} else {
|
||||||
|
Ok(Value::VariantWithoutData(name))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_variant_fieldish<'scale, 'resolver, R: TypeResolver>(
|
fn to_variant_fieldish<'r, 'scale, 'resolver, R: TypeResolver>(
|
||||||
|
resolver: &'r R,
|
||||||
value: &mut Composite<'scale, 'resolver, R>,
|
value: &mut Composite<'scale, 'resolver, R>,
|
||||||
) -> Result<VariantFields, ValueError> {
|
) -> Result<VariantFields, ValueError> {
|
||||||
// If fields are unnamed, treat as array:
|
// If fields are unnamed, treat as array:
|
||||||
if value.fields().iter().all(|f| f.name.is_none()) {
|
if value.fields().iter().all(|f| f.name.is_none()) {
|
||||||
return Ok(VariantFields::Unnamed(to_array(value.remaining(), value)?));
|
return Ok(VariantFields::Unnamed(to_array(
|
||||||
|
resolver,
|
||||||
|
value.remaining(),
|
||||||
|
value,
|
||||||
|
)?));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise object:
|
// Otherwise object:
|
||||||
@@ -431,18 +475,19 @@ mod value {
|
|||||||
for field in value {
|
for field in value {
|
||||||
let field = field?;
|
let field = field?;
|
||||||
let name = field.name().unwrap().to_string();
|
let name = field.name().unwrap().to_string();
|
||||||
let value = field.decode_with_visitor(GetValue::new())?;
|
let value = field.decode_with_visitor(GetValue::new(resolver))?;
|
||||||
out.insert(name, value);
|
out.insert(name, value);
|
||||||
}
|
}
|
||||||
Ok(VariantFields::Named(out))
|
Ok(VariantFields::Named(out))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_array<'scale, 'resolver, R: TypeResolver>(
|
fn to_array<'r, 'scale, 'resolver, R: TypeResolver>(
|
||||||
|
resolver: &'r R,
|
||||||
len: usize,
|
len: usize,
|
||||||
mut values: impl scale_decode::visitor::DecodeItemIterator<'scale, 'resolver, R>,
|
mut values: impl scale_decode::visitor::DecodeItemIterator<'scale, 'resolver, R>,
|
||||||
) -> Result<Vec<Value>, ValueError> {
|
) -> Result<Vec<Value>, ValueError> {
|
||||||
let mut out = Vec::with_capacity(len);
|
let mut out = Vec::with_capacity(len);
|
||||||
while let Some(value) = values.decode_item(GetValue::new()) {
|
while let Some(value) = values.decode_item(GetValue::new(resolver)) {
|
||||||
out.push(value?);
|
out.push(value?);
|
||||||
}
|
}
|
||||||
Ok(out)
|
Ok(out)
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ mod online_client;
|
|||||||
use crate::config::Config;
|
use crate::config::Config;
|
||||||
use crate::extrinsics::ExtrinsicsClient;
|
use crate::extrinsics::ExtrinsicsClient;
|
||||||
use crate::storage::StorageClient;
|
use crate::storage::StorageClient;
|
||||||
|
use crate::utils::AnyResolver;
|
||||||
use frame_metadata::RuntimeMetadata;
|
use frame_metadata::RuntimeMetadata;
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
@@ -45,4 +46,28 @@ where
|
|||||||
pub fn metadata(&self) -> &RuntimeMetadata {
|
pub fn metadata(&self) -> &RuntimeMetadata {
|
||||||
self.client.metadata()
|
self.client.metadata()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Return something which implements [`scale_type_resolver::TypeResolver`] and
|
||||||
|
/// can be used in conjnction with type IDs in `.visit` methods.
|
||||||
|
pub fn resolver(&self) -> AnyResolver<'_, 'client> {
|
||||||
|
match self.client.metadata() {
|
||||||
|
RuntimeMetadata::V0(_)
|
||||||
|
| RuntimeMetadata::V1(_)
|
||||||
|
| RuntimeMetadata::V2(_)
|
||||||
|
| RuntimeMetadata::V3(_)
|
||||||
|
| RuntimeMetadata::V4(_)
|
||||||
|
| RuntimeMetadata::V5(_)
|
||||||
|
| RuntimeMetadata::V6(_)
|
||||||
|
| RuntimeMetadata::V7(_)
|
||||||
|
| RuntimeMetadata::V8(_)
|
||||||
|
| RuntimeMetadata::V9(_)
|
||||||
|
| RuntimeMetadata::V10(_)
|
||||||
|
| RuntimeMetadata::V11(_)
|
||||||
|
| RuntimeMetadata::V12(_)
|
||||||
|
| RuntimeMetadata::V13(_) => AnyResolver::B(self.client.legacy_types()),
|
||||||
|
RuntimeMetadata::V14(m) => AnyResolver::A(&m.types),
|
||||||
|
RuntimeMetadata::V15(m) => AnyResolver::A(&m.types),
|
||||||
|
RuntimeMetadata::V16(m) => AnyResolver::A(&m.types),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ impl<'extrinsics, 'atblock> ExtrinsicCall<'extrinsics, 'atblock> {
|
|||||||
pub struct ExtrinsicCallFields<'extrinsics, 'atblock> {
|
pub struct ExtrinsicCallFields<'extrinsics, 'atblock> {
|
||||||
all_bytes: &'extrinsics [u8],
|
all_bytes: &'extrinsics [u8],
|
||||||
info: &'extrinsics AnyExtrinsicInfo<'atblock>,
|
info: &'extrinsics AnyExtrinsicInfo<'atblock>,
|
||||||
resolver: AnyResolver<'atblock>,
|
resolver: AnyResolver<'atblock, 'atblock>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'extrinsics, 'atblock> ExtrinsicCallFields<'extrinsics, 'atblock> {
|
impl<'extrinsics, 'atblock> ExtrinsicCallFields<'extrinsics, 'atblock> {
|
||||||
@@ -135,7 +135,7 @@ impl<'extrinsics, 'atblock> ExtrinsicCallFields<'extrinsics, 'atblock> {
|
|||||||
pub struct ExtrinsicCallField<'fields, 'extrinsics, 'atblock> {
|
pub struct ExtrinsicCallField<'fields, 'extrinsics, 'atblock> {
|
||||||
field_bytes: &'extrinsics [u8],
|
field_bytes: &'extrinsics [u8],
|
||||||
info: AnyExtrinsicCallFieldInfo<'extrinsics, 'atblock>,
|
info: AnyExtrinsicCallFieldInfo<'extrinsics, 'atblock>,
|
||||||
resolver: &'fields AnyResolver<'atblock>,
|
resolver: &'fields AnyResolver<'atblock, 'atblock>,
|
||||||
}
|
}
|
||||||
|
|
||||||
enum AnyExtrinsicCallFieldInfo<'extrinsics, 'atblock> {
|
enum AnyExtrinsicCallFieldInfo<'extrinsics, 'atblock> {
|
||||||
@@ -172,7 +172,9 @@ impl<'fields, 'extrinsics, 'atblock> ExtrinsicCallField<'fields, 'extrinsics, 'a
|
|||||||
/// Visit the given field with a [`scale_decode::visitor::Visitor`]. This is like a lower level
|
/// Visit the given field with a [`scale_decode::visitor::Visitor`]. This is like a lower level
|
||||||
/// version of [`ExtrinsicCallField::decode_as`], as the visitor is able to preserve lifetimes
|
/// version of [`ExtrinsicCallField::decode_as`], as the visitor is able to preserve lifetimes
|
||||||
/// and has access to more type information than is available via [`ExtrinsicCallField::decode_as`].
|
/// and has access to more type information than is available via [`ExtrinsicCallField::decode_as`].
|
||||||
pub fn visit<V: scale_decode::visitor::Visitor<TypeResolver = AnyResolver<'atblock>>>(
|
pub fn visit<
|
||||||
|
V: scale_decode::visitor::Visitor<TypeResolver = AnyResolver<'atblock, 'atblock>>,
|
||||||
|
>(
|
||||||
&self,
|
&self,
|
||||||
visitor: V,
|
visitor: V,
|
||||||
) -> Result<V::Value<'extrinsics, 'fields>, V::Error> {
|
) -> Result<V::Value<'extrinsics, 'fields>, V::Error> {
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ use std::sync::Arc;
|
|||||||
pub struct StorageValue<'atblock> {
|
pub struct StorageValue<'atblock> {
|
||||||
pub(crate) info: Arc<AnyStorageInfo<'atblock>>,
|
pub(crate) info: Arc<AnyStorageInfo<'atblock>>,
|
||||||
bytes: Cow<'atblock, [u8]>,
|
bytes: Cow<'atblock, [u8]>,
|
||||||
resolver: AnyResolver<'atblock>,
|
resolver: AnyResolver<'atblock, 'atblock>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'atblock> StorageValue<'atblock> {
|
impl<'atblock> StorageValue<'atblock> {
|
||||||
@@ -41,7 +41,9 @@ impl<'atblock> StorageValue<'atblock> {
|
|||||||
/// Visit the given field with a [`scale_decode::visitor::Visitor`]. This is like a lower level
|
/// Visit the given field with a [`scale_decode::visitor::Visitor`]. This is like a lower level
|
||||||
/// version of [`StorageValue::decode_as`], as the visitor is able to preserve lifetimes
|
/// version of [`StorageValue::decode_as`], as the visitor is able to preserve lifetimes
|
||||||
/// and has access to more type information than is available via [`StorageValue::decode_as`].
|
/// and has access to more type information than is available via [`StorageValue::decode_as`].
|
||||||
pub fn visit<V: scale_decode::visitor::Visitor<TypeResolver = AnyResolver<'atblock>>>(
|
pub fn visit<
|
||||||
|
V: scale_decode::visitor::Visitor<TypeResolver = AnyResolver<'atblock, 'atblock>>,
|
||||||
|
>(
|
||||||
&self,
|
&self,
|
||||||
visitor: V,
|
visitor: V,
|
||||||
) -> Result<V::Value<'_, '_>, V::Error> {
|
) -> Result<V::Value<'_, '_>, V::Error> {
|
||||||
|
|||||||
@@ -3,10 +3,8 @@ use scale_info_legacy::LookupName;
|
|||||||
use scale_type_resolver::ResolvedTypeVisitor;
|
use scale_type_resolver::ResolvedTypeVisitor;
|
||||||
|
|
||||||
/// A type resolver which could either be for modern or historic resolving.
|
/// A type resolver which could either be for modern or historic resolving.
|
||||||
pub type AnyResolver<'resolver> = Either<
|
pub type AnyResolver<'a, 'b> =
|
||||||
&'resolver scale_info::PortableRegistry,
|
Either<&'a scale_info::PortableRegistry, &'a scale_info_legacy::TypeRegistrySet<'b>>;
|
||||||
&'resolver scale_info_legacy::TypeRegistrySet<'resolver>,
|
|
||||||
>;
|
|
||||||
|
|
||||||
/// A type ID which is either a modern or historic ID.
|
/// A type ID which is either a modern or historic ID.
|
||||||
pub type AnyTypeId = Either<u32, scale_info_legacy::LookupName>;
|
pub type AnyTypeId = Either<u32, scale_info_legacy::LookupName>;
|
||||||
@@ -60,7 +58,7 @@ pub enum AnyResolverError {
|
|||||||
ScaleInfoLegacy(scale_info_legacy::type_registry::TypeRegistryResolveError),
|
ScaleInfoLegacy(scale_info_legacy::type_registry::TypeRegistryResolveError),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'resolver> scale_type_resolver::TypeResolver for AnyResolver<'resolver> {
|
impl<'a, 'b> scale_type_resolver::TypeResolver for AnyResolver<'a, 'b> {
|
||||||
type TypeId = AnyTypeId;
|
type TypeId = AnyTypeId;
|
||||||
type Error = AnyResolverError;
|
type Error = AnyResolverError;
|
||||||
|
|
||||||
|
|||||||
+19
-6
@@ -212,6 +212,22 @@ fn validate_type_path(path: &syn::Path, metadata: &Metadata) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Resolves a path, handling the $OUT_DIR placeholder if present.
|
||||||
|
/// If $OUT_DIR is present in the path, it's replaced with the actual OUT_DIR environment variable.
|
||||||
|
/// Otherwise, the path is resolved relative to CARGO_MANIFEST_DIR.
|
||||||
|
fn resolve_path(path_str: &str) -> std::path::PathBuf {
|
||||||
|
if path_str.contains("$OUT_DIR") {
|
||||||
|
let out_dir = std::env::var("OUT_DIR").unwrap_or_else(|_| {
|
||||||
|
abort_call_site!("$OUT_DIR is used in path but OUT_DIR environment variable is not set")
|
||||||
|
});
|
||||||
|
std::path::Path::new(&path_str.replace("$OUT_DIR", &out_dir)).into()
|
||||||
|
} else {
|
||||||
|
let root = std::env::var("CARGO_MANIFEST_DIR").unwrap_or_else(|_| ".".into());
|
||||||
|
let root_path = std::path::Path::new(&root);
|
||||||
|
root_path.join(path_str)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Fetches metadata in a blocking manner, from a url or file path.
|
/// Fetches metadata in a blocking manner, from a url or file path.
|
||||||
fn fetch_metadata(args: &RuntimeMetadataArgs) -> Result<subxt_codegen::Metadata, TokenStream> {
|
fn fetch_metadata(args: &RuntimeMetadataArgs) -> Result<subxt_codegen::Metadata, TokenStream> {
|
||||||
// Do we want to fetch unstable metadata? This only works if fetching from a URL.
|
// Do we want to fetch unstable metadata? This only works if fetching from a URL.
|
||||||
@@ -224,9 +240,7 @@ fn fetch_metadata(args: &RuntimeMetadataArgs) -> Result<subxt_codegen::Metadata,
|
|||||||
"Only one of 'runtime_metadata_path', 'runtime_metadata_insecure_url' or `runtime_path` must be provided"
|
"Only one of 'runtime_metadata_path', 'runtime_metadata_insecure_url' or `runtime_path` must be provided"
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
let root = std::env::var("CARGO_MANIFEST_DIR").unwrap_or_else(|_| ".".into());
|
let path = resolve_path(path);
|
||||||
let root_path = std::path::Path::new(&root);
|
|
||||||
let path = root_path.join(path);
|
|
||||||
|
|
||||||
let metadata = wasm_loader::from_wasm_file(&path).map_err(|e| e.into_compile_error())?;
|
let metadata = wasm_loader::from_wasm_file(&path).map_err(|e| e.into_compile_error())?;
|
||||||
return Ok(metadata);
|
return Ok(metadata);
|
||||||
@@ -243,9 +257,8 @@ fn fetch_metadata(args: &RuntimeMetadataArgs) -> Result<subxt_codegen::Metadata,
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
let root = std::env::var("CARGO_MANIFEST_DIR").unwrap_or_else(|_| ".".into());
|
let path = resolve_path(rest_of_path);
|
||||||
let root_path = std::path::Path::new(&root);
|
|
||||||
let path = root_path.join(rest_of_path);
|
|
||||||
subxt_utils_fetchmetadata::from_file_blocking(&path)
|
subxt_utils_fetchmetadata::from_file_blocking(&path)
|
||||||
.and_then(|b| subxt_codegen::Metadata::decode(&mut &*b).map_err(Into::into))
|
.and_then(|b| subxt_codegen::Metadata::decode(&mut &*b).map_err(Into::into))
|
||||||
.map_err(|e| CodegenError::Other(e.to_string()).into_compile_error())?
|
.map_err(|e| CodegenError::Other(e.to_string()).into_compile_error())?
|
||||||
|
|||||||
@@ -146,6 +146,15 @@ pub mod ext {
|
|||||||
/// mod polkadot {}
|
/// mod polkadot {}
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
|
/// You can use the `$OUT_DIR` placeholder in the path to reference metadata generated at build time:
|
||||||
|
///
|
||||||
|
/// ```rust,ignore
|
||||||
|
/// #[subxt::subxt(
|
||||||
|
/// runtime_metadata_path = "$OUT_DIR/metadata.scale",
|
||||||
|
/// )]
|
||||||
|
/// mod polkadot {}
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
/// ## Using a WASM runtime via `runtime_path = "..."`
|
/// ## Using a WASM runtime via `runtime_path = "..."`
|
||||||
///
|
///
|
||||||
/// This requires the `runtime-wasm-path` feature flag.
|
/// This requires the `runtime-wasm-path` feature flag.
|
||||||
@@ -159,6 +168,15 @@ pub mod ext {
|
|||||||
/// mod polkadot {}
|
/// mod polkadot {}
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
|
/// You can also use the `$OUT_DIR` placeholder in the path to reference WASM files generated at build time:
|
||||||
|
///
|
||||||
|
/// ```rust,ignore
|
||||||
|
/// #[subxt::subxt(
|
||||||
|
/// runtime_path = "$OUT_DIR/runtime.wasm",
|
||||||
|
/// )]
|
||||||
|
/// mod polkadot {}
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
/// ## Connecting to a node to download metadata via `runtime_metadata_insecure_url = "..."`
|
/// ## Connecting to a node to download metadata via `runtime_metadata_insecure_url = "..."`
|
||||||
///
|
///
|
||||||
/// This will, at compile time, connect to the JSON-RPC interface for some node at the URL given,
|
/// This will, at compile time, connect to the JSON-RPC interface for some node at the URL given,
|
||||||
|
|||||||
@@ -99,12 +99,18 @@ fn interface_docs(should_gen_docs: bool) -> Vec<String> {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn check_documentation() {
|
fn check_documentation() {
|
||||||
// Inspect metadata recursively and obtain all associated documentation.
|
// Inspect metadata and obtain all associated documentation.
|
||||||
let raw_docs = metadata_docs();
|
let raw_docs = metadata_docs();
|
||||||
// Obtain documentation from the generated API.
|
// Obtain documentation from the generated API.
|
||||||
let runtime_docs = interface_docs(true);
|
let runtime_docs = interface_docs(true);
|
||||||
|
|
||||||
for raw in raw_docs.iter() {
|
for raw in raw_docs.iter() {
|
||||||
|
if raw.contains(|c: char| !c.is_ascii()) {
|
||||||
|
// Ignore lines containing on-ascii chars; they are encoded currently
|
||||||
|
// as "\u{nn}" which doesn't match their input which is the raw non-ascii
|
||||||
|
// char.
|
||||||
|
continue;
|
||||||
|
}
|
||||||
assert!(
|
assert!(
|
||||||
runtime_docs.contains(raw),
|
runtime_docs.contains(raw),
|
||||||
"Documentation not present in runtime API: {raw}"
|
"Documentation not present in runtime API: {raw}"
|
||||||
@@ -114,7 +120,7 @@ fn check_documentation() {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn check_no_documentation() {
|
fn check_no_documentation() {
|
||||||
// Inspect metadata recursively and obtain all associated documentation.
|
// Inspect metadata and obtain all associated documentation.
|
||||||
let raw_docs = metadata_docs();
|
let raw_docs = metadata_docs();
|
||||||
// Obtain documentation from the generated API.
|
// Obtain documentation from the generated API.
|
||||||
let runtime_docs = interface_docs(false);
|
let runtime_docs = interface_docs(false);
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user