From 4a1194774421373dab69d59ed8b2a41ba8126e6d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 2 Oct 2023 10:56:33 +0200 Subject: [PATCH 1/7] Bump actions/checkout from 3 to 4 (#1187) Bumps [actions/checkout](https://github.com/actions/checkout) from 3 to 4. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v3...v4) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/rust.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 171152d9b8..43c3104129 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -186,7 +186,7 @@ jobs: runs-on: ubuntu-latest-16-cores steps: - name: Checkout sources - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Use substrate-node binary uses: ./.github/workflows/actions/use-substrate From 850c5e57a8c78f8971851d673c3077c723d7c25d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 2 Oct 2023 13:00:13 +0300 Subject: [PATCH 2/7] Bump Swatinem/rust-cache from 2.6.2 to 2.7.0 (#1186) --- .github/workflows/build-substrate.yml | 2 +- .github/workflows/rust.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-substrate.yml b/.github/workflows/build-substrate.yml index a26a0a4a3d..b400636b7d 100644 --- a/.github/workflows/build-substrate.yml +++ b/.github/workflows/build-substrate.yml @@ -24,7 +24,7 @@ jobs: run: rustup target add wasm32-unknown-unknown - name: Rust Cache - uses: Swatinem/rust-cache@e207df5d269b42b69c8bc5101da26f7d31feddb4 # v2.6.2 + uses: Swatinem/rust-cache@a95ba195448af2da9b00fb742d14ffaaf3c21f43 # v2.7.0 - name: build substrate binary uses: actions-rs/cargo@v1 diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 43c3104129..f9aa7872dc 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -199,7 +199,7 @@ jobs: override: true - name: Rust Cache - uses: Swatinem/rust-cache@e207df5d269b42b69c8bc5101da26f7d31feddb4 # v2.6.2 + uses: Swatinem/rust-cache@a95ba195448af2da9b00fb742d14ffaaf3c21f43 # v2.7.0 - name: Install cargo-nextest run: cargo install cargo-nextest From a724c4e4c0052af56bd587d72d2a3ab4763e06e5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 2 Oct 2023 13:05:55 +0300 Subject: [PATCH 3/7] Bump regex from 1.9.5 to 1.9.6 (#1184) --- Cargo.lock | 10 +++++----- Cargo.toml | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 00a7cbdca0..ae49434db0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3019,13 +3019,13 @@ dependencies = [ [[package]] name = "regex" -version = "1.9.5" +version = "1.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "697061221ea1b4a94a624f67d0ae2bfe4e22b8a17b6a192afb11046542cc8c47" +checksum = "ebee201405406dbf528b8b672104ae6d6d63e6d118cb10e4d51abbc7b58044ff" dependencies = [ "aho-corasick", "memchr", - "regex-automata 0.3.8", + "regex-automata 0.3.9", "regex-syntax 0.7.5", ] @@ -3040,9 +3040,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.3.8" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2f401f4955220693b56f8ec66ee9c78abffd8d1c4f23dc41a23839eb88f0795" +checksum = "59b23e92ee4318893fa3fe3e6fb365258efbfe6ac6ab30f090cdcbb7aa37efa9" dependencies = [ "aho-corasick", "memchr", diff --git a/Cargo.toml b/Cargo.toml index 984108926a..4fa635ad5b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -62,7 +62,7 @@ primitive-types = { version = "0.12.1", default-features = false, features = ["c proc-macro-error = "1.0.4" proc-macro2 = "1.0.67" quote = "1.0.33" -regex = "1.9.5" +regex = "1.9.6" scale-info = "2.9.0" scale-value = "0.12.0" scale-bits = "0.4.0" From 556c2d5047f0ee0d510c0d43e2e01d3a7a4e9291 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 2 Oct 2023 12:49:00 +0200 Subject: [PATCH 4/7] Bump clap from 4.4.5 to 4.4.6 (#1185) Bumps [clap](https://github.com/clap-rs/clap) from 4.4.5 to 4.4.6. - [Release notes](https://github.com/clap-rs/clap/releases) - [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md) - [Commits](https://github.com/clap-rs/clap/compare/v4.4.5...v4.4.6) --- updated-dependencies: - dependency-name: clap dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Tadeo Hepperle <62739623+tadeohepperle@users.noreply.github.com> --- Cargo.lock | 18 +++++++++--------- Cargo.toml | 2 +- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ae49434db0..34a8295301 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -135,9 +135,9 @@ dependencies = [ [[package]] name = "anstream" -version = "0.5.0" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1f58811cfac344940f1a400b6e6231ce35171f614f26439e80f8c1465c5cc0c" +checksum = "2ab91ebe16eb252986481c5b62f6098f3b698a45e34b5b98200cf20dd2484a44" dependencies = [ "anstyle", "anstyle-parse", @@ -173,9 +173,9 @@ dependencies = [ [[package]] name = "anstyle-wincon" -version = "2.1.0" +version = "3.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58f54d10c6dfa51283a066ceab3ec1ab78d13fae00aa49243a45e4571fb79dfd" +checksum = "f0699d10d2f4d628a98ee7b57b289abbc98ff3bad977cb3152709d4bf2330628" dependencies = [ "anstyle", "windows-sys 0.48.0", @@ -736,9 +736,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.4.5" +version = "4.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "824956d0dca8334758a5b7f7e50518d66ea319330cbceedcf76905c2f6ab30e3" +checksum = "d04704f56c2cde07f43e8e2c154b43f216dc5c92fc98ada720177362f953b956" dependencies = [ "clap_builder", "clap_derive", @@ -746,9 +746,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.4.5" +version = "4.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "122ec64120a49b4563ccaedcbea7818d069ed8e9aa6d829b82d8a4128936b2ab" +checksum = "0e231faeaca65ebd1ea3c737966bf858971cd38c3849107aa3ea7de90a804e45" dependencies = [ "anstream", "anstyle", @@ -4262,7 +4262,7 @@ dependencies = [ name = "subxt-cli" version = "0.32.0" dependencies = [ - "clap 4.4.5", + "clap 4.4.6", "color-eyre", "frame-metadata 16.0.0", "hex", diff --git a/Cargo.toml b/Cargo.toml index 4fa635ad5b..fe9d7c70d9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -42,7 +42,7 @@ assert_matches = "1.5.0" base58 = { version = "0.2.0" } bitvec = { version = "1", default-features = false } blake2 = { version = "0.10.4", default-features = false } -clap = { version = "4.4.4", features = ["derive", "cargo"] } +clap = { version = "4.4.6", features = ["derive", "cargo"] } criterion = "0.4" codec = { package = "parity-scale-codec", version = "3.4.0", default-features = false } color-eyre = "0.6.1" From 958ff56596b6520526a9686539fa5d8b513056ce Mon Sep 17 00:00:00 2001 From: yjh Date: Mon, 2 Oct 2023 18:49:10 +0800 Subject: [PATCH 5/7] chore: improve some error messages (#1183) Co-authored-by: Tadeo Hepperle <62739623+tadeohepperle@users.noreply.github.com> --- subxt/src/error/mod.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/subxt/src/error/mod.rs b/subxt/src/error/mod.rs index d3c88ce6c5..a3666b1b68 100644 --- a/subxt/src/error/mod.rs +++ b/subxt/src/error/mod.rs @@ -42,13 +42,13 @@ pub enum Error { #[error("Serde json error: {0}")] Serialization(#[from] serde_json::error::Error), /// Error working with metadata. - #[error("Metadata: {0}")] + #[error("Metadata error: {0}")] Metadata(#[from] MetadataError), /// Error decoding metadata. - #[error("Metadata: {0}")] + #[error("Metadata Decoding error: {0}")] MetadataDecoding(#[from] MetadataTryFromError), /// Runtime error. - #[error("Runtime error: {0:?}")] + #[error("Runtime error: {0}")] Runtime(#[from] DispatchError), /// Error decoding to a [`crate::dynamic::Value`]. #[error("Error decoding into dynamic value: {0}")] @@ -60,7 +60,7 @@ pub enum Error { #[error("Transaction error: {0}")] Transaction(#[from] TransactionError), /// Error constructing the appropriate extrinsic params. - #[error("{0}")] + #[error("Extrinsic params error: {0}")] ExtrinsicParams(#[from] ExtrinsicParamsError), /// Block related error. #[error("Block error: {0}")] @@ -73,7 +73,7 @@ pub enum Error { Unknown(Vec), /// Light client error. #[cfg(feature = "unstable-light-client")] - #[error("An error occurred but it could not be decoded: {0:?}")] + #[error("An error occurred but it could not be decoded: {0}")] LightClient(#[from] LightClientError), /// Other error. #[error("Other error: {0}")] @@ -110,7 +110,7 @@ pub enum RpcError { ClientError(Box), /// This error signals that the request was rejected for some reason. /// The specific reason is provided. - #[error("RPC error: request rejected")] + #[error("RPC error: request rejected: {0}")] RequestRejected(String), /// The RPC subscription dropped. #[error("RPC error: subscription dropped.")] From e91d0c7b37da5deee10892712b55e7a65833f5f9 Mon Sep 17 00:00:00 2001 From: James Wilson Date: Mon, 2 Oct 2023 23:10:34 +0100 Subject: [PATCH 6/7] allow getting account nonce at arbitrary blocks, too (#1182) --- subxt/examples/runtime_apis_dynamic.rs | 3 -- subxt/src/blocks/block_types.rs | 38 +++++++++++++++++++++++++- subxt/src/blocks/mod.rs | 3 ++ subxt/src/tx/tx_client.rs | 21 +------------- 4 files changed, 41 insertions(+), 24 deletions(-) diff --git a/subxt/examples/runtime_apis_dynamic.rs b/subxt/examples/runtime_apis_dynamic.rs index f7e8a894d7..2a02118abd 100644 --- a/subxt/examples/runtime_apis_dynamic.rs +++ b/subxt/examples/runtime_apis_dynamic.rs @@ -2,9 +2,6 @@ use subxt::dynamic::Value; use subxt::{config::PolkadotConfig, OnlineClient}; use subxt_signer::sr25519::dev; -#[subxt::subxt(runtime_metadata_path = "../artifacts/polkadot_metadata_small.scale")] -pub mod polkadot {} - #[tokio::main] async fn main() -> Result<(), Box> { // Create a client to use: diff --git a/subxt/src/blocks/block_types.rs b/subxt/src/blocks/block_types.rs index 25e97d6457..2b160ea2d2 100644 --- a/subxt/src/blocks/block_types.rs +++ b/subxt/src/blocks/block_types.rs @@ -7,12 +7,13 @@ use crate::{ blocks::{extrinsic_types::ExtrinsicPartTypeIds, Extrinsics}, client::{OfflineClientT, OnlineClientT}, config::{Config, Header}, - error::{BlockError, Error}, + error::{BlockError, DecodeError, Error}, events, runtime_api::RuntimeApi, storage::Storage, }; +use codec::{Decode, Encode}; use futures::lock::Mutex as AsyncMutex; use std::sync::Arc; @@ -102,6 +103,11 @@ where pub async fn runtime_api(&self) -> Result, Error> { Ok(RuntimeApi::new(self.client.clone(), self.block_ref.clone())) } + + /// Get the account nonce for a given account ID at this block. + pub async fn account_nonce(&self, account_id: &T::AccountId) -> Result { + get_account_nonce(&self.client, account_id, self.hash()).await + } } // Return Events from the cache, or fetch from the node if needed. @@ -129,3 +135,33 @@ where Ok(events) } + +// Return the account nonce at some block hash for an account ID. +pub(crate) async fn get_account_nonce( + client: &C, + account_id: &T::AccountId, + block_hash: T::Hash, +) -> Result +where + C: OnlineClientT, + T: Config, +{ + let account_nonce_bytes = client + .backend() + .call( + "AccountNonceApi_account_nonce", + Some(&account_id.encode()), + block_hash, + ) + .await?; + + // custom decoding from a u16/u32/u64 into a u64, based on the number of bytes we got back. + let cursor = &mut &account_nonce_bytes[..]; + let account_nonce: u64 = match account_nonce_bytes.len() { + 2 => u16::decode(cursor)?.into(), + 4 => u32::decode(cursor)?.into(), + 8 => u64::decode(cursor)?, + _ => return Err(Error::Decode(DecodeError::custom_string(format!("state call AccountNonceApi_account_nonce returned an unexpected number of bytes: {} (expected 2, 4 or 8)", account_nonce_bytes.len())))) + }; + Ok(account_nonce) +} diff --git a/subxt/src/blocks/mod.rs b/subxt/src/blocks/mod.rs index da99fe22d5..fd06594e60 100644 --- a/subxt/src/blocks/mod.rs +++ b/subxt/src/blocks/mod.rs @@ -14,3 +14,6 @@ pub use crate::backend::BlockRef; pub use block_types::Block; pub use blocks_client::BlocksClient; pub use extrinsic_types::{ExtrinsicDetails, ExtrinsicEvents, Extrinsics, StaticExtrinsic}; + +// We get account nonce info in tx_client, too, so re-use the logic: +pub(crate) use block_types::get_account_nonce; diff --git a/subxt/src/tx/tx_client.rs b/subxt/src/tx/tx_client.rs index ff4e3416e8..5b5df91106 100644 --- a/subxt/src/tx/tx_client.rs +++ b/subxt/src/tx/tx_client.rs @@ -4,7 +4,6 @@ use std::borrow::Cow; -use crate::error::DecodeError; use crate::{ backend::{BackendExt, BlockRef, TransactionStatus}, client::{OfflineClientT, OnlineClientT}, @@ -170,25 +169,7 @@ where /// Get the account nonce for a given account ID. pub async fn account_nonce(&self, account_id: &T::AccountId) -> Result { let block_ref = self.client.backend().latest_finalized_block_ref().await?; - let account_nonce_bytes = self - .client - .backend() - .call( - "AccountNonceApi_account_nonce", - Some(&account_id.encode()), - block_ref.hash(), - ) - .await?; - - // custom decoding from a u16/u32/u64 into a u64, based on the number of bytes we got back. - let cursor = &mut &account_nonce_bytes[..]; - let account_nonce: u64 = match account_nonce_bytes.len() { - 2 => u16::decode(cursor)?.into(), - 4 => u32::decode(cursor)?.into(), - 8 => u64::decode(cursor)?, - _ => return Err(Error::Decode(DecodeError::custom_string(format!("state call AccountNonceApi_account_nonce returned an unexpected number of bytes: {} (expected 2, 4 or 8)", account_nonce_bytes.len())))) - }; - Ok(account_nonce) + crate::blocks::get_account_nonce(&self.client, account_id, block_ref.hash()).await } /// Creates a partial signed extrinsic, without submitting it. From 919b866c0fd14af12e3a6f7b19699a7129a3573c Mon Sep 17 00:00:00 2001 From: James Wilson Date: Thu, 5 Oct 2023 15:16:15 +0200 Subject: [PATCH 7/7] fix for when runtime API field name is _ (#1191) * fix for when runtime API field name is _ * add a test * formatting --------- Co-authored-by: Tadeo hepperle --- codegen/src/api/runtime_apis.rs | 10 +++++++-- testing/ui-tests/src/dispatch_errors.rs | 6 ++--- testing/ui-tests/src/lib.rs | 8 +++++++ testing/ui-tests/src/runtime_apis.rs | 29 +++++++++++++++++++++++++ testing/ui-tests/src/utils/mod.rs | 18 +++++++++++---- 5 files changed, 62 insertions(+), 9 deletions(-) create mode 100644 testing/ui-tests/src/runtime_apis.rs diff --git a/codegen/src/api/runtime_apis.rs b/codegen/src/api/runtime_apis.rs index 9c3e548736..bc363a2cf2 100644 --- a/codegen/src/api/runtime_apis.rs +++ b/codegen/src/api/runtime_apis.rs @@ -36,8 +36,14 @@ fn generate_runtime_api( .then_some(quote! { #( #[doc = #docs ] )* }) .unwrap_or_default(); - let inputs: Vec<_> = method.inputs().map(|input| { - let name = format_ident!("{}", &input.name); + let inputs: Vec<_> = method.inputs().enumerate().map(|(idx, input)| { + // These are method names, which can just be '_', but struct field names can't + // just be an underscore, so fix any such names we find to work in structs. + let name = if input.name == "_" { + format_ident!("_{}", idx) + } else { + format_ident!("{}", &input.name) + }; let ty = type_gen.resolve_type_path(input.ty); let param = quote!(#name: #ty); diff --git a/testing/ui-tests/src/dispatch_errors.rs b/testing/ui-tests/src/dispatch_errors.rs index 81ac746d6f..fea8699402 100644 --- a/testing/ui-tests/src/dispatch_errors.rs +++ b/testing/ui-tests/src/dispatch_errors.rs @@ -11,13 +11,13 @@ use generate_custom_metadata::dispatch_error::{ use frame_metadata::RuntimeMetadataPrefixed; pub fn metadata_array_dispatch_error() -> RuntimeMetadataPrefixed { - generate_metadata_from_pallets_custom_dispatch_error::(vec![]) + generate_metadata_from_pallets_custom_dispatch_error::(vec![], vec![]) } pub fn metadata_legacy_dispatch_error() -> RuntimeMetadataPrefixed { - generate_metadata_from_pallets_custom_dispatch_error::(vec![]) + generate_metadata_from_pallets_custom_dispatch_error::(vec![], vec![]) } pub fn metadata_named_field_dispatch_error() -> RuntimeMetadataPrefixed { - generate_metadata_from_pallets_custom_dispatch_error::(vec![]) + generate_metadata_from_pallets_custom_dispatch_error::(vec![], vec![]) } diff --git a/testing/ui-tests/src/lib.rs b/testing/ui-tests/src/lib.rs index 9476e78a35..06522ff9b0 100644 --- a/testing/ui-tests/src/lib.rs +++ b/testing/ui-tests/src/lib.rs @@ -12,6 +12,7 @@ //! to automatically regenerate `stderr` files, but don't forget to check that new files make sense. mod dispatch_errors; +mod runtime_apis; mod storage; mod utils; @@ -34,6 +35,13 @@ fn ui_tests() { .build(storage::metadata_storage_map_no_keys()), ); + // Check runtime APIs with _ in method names work + t.pass( + m.new_test_case() + .name("runtime_api_underscore_method_name") + .build(runtime_apis::metadata_runtime_api_underscore_method_name()), + ); + // Test that the codegen can handle the different types of DispatchError. t.pass( m.new_test_case() diff --git a/testing/ui-tests/src/runtime_apis.rs b/testing/ui-tests/src/runtime_apis.rs new file mode 100644 index 0000000000..fc16d9e14c --- /dev/null +++ b/testing/ui-tests/src/runtime_apis.rs @@ -0,0 +1,29 @@ +// Copyright 2019-2023 Parity Technologies (UK) Ltd. +// This file is dual-licensed as Apache-2.0 or GPL-3.0. +// see LICENSE for license details. + +use frame_metadata::{ + v15::{RuntimeApiMetadata, RuntimeApiMethodMetadata, RuntimeApiMethodParamMetadata}, + RuntimeMetadataPrefixed, +}; + +use crate::utils::generate_metadata_from_runtime_apis; + +/// Generate metadata which contains a `Map` storage entry with no hashers/values. +/// This is a bit of an odd case, but it was raised in https://github.com/paritytech/subxt/issues/552, +/// and this test will fail before the fix and should pass once the fix is applied. +pub fn metadata_runtime_api_underscore_method_name() -> RuntimeMetadataPrefixed { + generate_metadata_from_runtime_apis(vec![RuntimeApiMetadata { + name: "MyApi".to_owned(), + docs: vec![], + methods: vec![RuntimeApiMethodMetadata { + name: "my_method".to_owned(), + inputs: vec![RuntimeApiMethodParamMetadata { + name: "_".to_owned(), // The important bit we're testing. + ty: 0.into(), // we don't care what type this is. + }], + output: 0.into(), // we don't care what type this is. + docs: vec![], + }], + }]) +} diff --git a/testing/ui-tests/src/utils/mod.rs b/testing/ui-tests/src/utils/mod.rs index e59b48d2d3..4bf0fa65c2 100644 --- a/testing/ui-tests/src/utils/mod.rs +++ b/testing/ui-tests/src/utils/mod.rs @@ -7,12 +7,12 @@ mod metadata_test_runner; use frame_metadata::{ v15::{ CustomMetadata, ExtrinsicMetadata, OuterEnums, PalletMetadata, PalletStorageMetadata, - RuntimeMetadataV15, StorageEntryMetadata, + RuntimeApiMetadata, RuntimeMetadataV15, StorageEntryMetadata, }, RuntimeMetadataPrefixed, }; use generate_custom_metadata::dispatch_error::ArrayDispatchError; -use scale_info::{meta_type, IntoPortable, TypeInfo}; +use scale_info::{form::PortableForm, meta_type, IntoPortable, TypeInfo}; pub use metadata_test_runner::MetadataTestRunner; @@ -21,6 +21,7 @@ pub use metadata_test_runner::MetadataTestRunner; /// type matching the generic type param provided. pub fn generate_metadata_from_pallets_custom_dispatch_error( pallets: Vec, + runtime_apis: Vec>, ) -> RuntimeMetadataPrefixed { // We don't care about the extrinsic type. let extrinsic = ExtrinsicMetadata { @@ -60,7 +61,7 @@ pub fn generate_metadata_from_pallets_custom_dispatch_error) -> RuntimeMetadataPrefixed { - generate_metadata_from_pallets_custom_dispatch_error::(pallets) + generate_metadata_from_pallets_custom_dispatch_error::(pallets, vec![]) +} + +/// Given some runtime API metadata, generate a [`RuntimeMetadataPrefixed`] struct. +/// We default to a useless extrinsic type, and register a fake `DispatchError` +/// type so that codegen is happy with the metadata generated. +pub fn generate_metadata_from_runtime_apis( + runtime_apis: Vec>, +) -> RuntimeMetadataPrefixed { + generate_metadata_from_pallets_custom_dispatch_error::(vec![], runtime_apis) } /// Given some storage entries, generate a [`RuntimeMetadataPrefixed`] struct.