Repository: paritytech/polkadot-sdk (language: rust)

Issue:
Metadata V16: Add version number to Runtime API trait information
It would be useful in some cases to expose the version of each Runtime API that a runtime supports in the metadata.

ie we should take this struct https://github.com/paritytech/frame-metadata/blob/0fc0539c2def93b5ca2d71deb5fa1c9d87c9b7c3/frame-metadata/src/v16.rs#L94:

```rust
pub struct RuntimeApiMetadata<T: Form = MetaForm> {
	/// Trait name.
	pub name: T::String,
	/// Trait methods.
	pub methods: Vec<RuntimeApiMethodMetadata<T>>,
	/// Trait documentation.
	pub docs: Vec<T::String>,
	/// Deprecation info
	pub deprecation_info: DeprecationStatus<T>,
}
```

And add something like `pub version: Compact<u32>` which would be the version of a given Runtime API trait that is being implemented.

Knowing this version can help callers understand which runtime calls they will need to make to obtain some data.

### Alternative Approach

The `System.version` constant also contains this information against hashes of the Runtime API trait names. Constants are already added to the Metadata, so we could use this instead, though it is less accessible/usable/obvious than the suggested addition.


Discussion / hints:

Fix patch:
diff --git a/Cargo.lock b/Cargo.lock
index 837629a6e70cd..0dbf45f629580 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -6636,9 +6636,9 @@ dependencies = [
 
 [[package]]
 name = "frame-metadata"
-version = "19.0.0"
+version = "20.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "835a2e736d544b98dab966b4b9541f15af416288a86c3738fdd67bd9fbc4696e"
+checksum = "26de808fa6461f2485dc51811aefed108850064994fb4a62b3ac21ffa62ac8df"
 dependencies = [
  "cfg-if",
  "parity-scale-codec",
@@ -6653,7 +6653,7 @@ dependencies = [
  "array-bytes",
  "const-hex",
  "docify",
- "frame-metadata 19.0.0",
+ "frame-metadata 20.0.0",
  "frame-support",
  "frame-system",
  "log",
@@ -6722,7 +6722,7 @@ dependencies = [
  "bitflags 1.3.2",
  "docify",
  "environmental",
- "frame-metadata 19.0.0",
+ "frame-metadata 20.0.0",
  "frame-support-procedural",
  "frame-system",
  "impl-trait-for-tuples",
@@ -6814,7 +6814,7 @@ version = "3.0.0"
 dependencies = [
  "frame-benchmarking",
  "frame-executive",
- "frame-metadata 19.0.0",
+ "frame-metadata 20.0.0",
  "frame-support",
  "frame-support-test-pallet",
  "frame-system",
@@ -9962,13 +9962,13 @@ dependencies = [
 
 [[package]]
 name = "merkleized-metadata"
-version = "0.3.0"
+version = "0.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e656ca4a152e892cbbf4b621c242b070136643b797709007d4861881d71ff4c9"
+checksum = "dc9b7ac0ce054412d9a85ff39bac27aec27483b06cef8756b57d9c29d448d081"
 dependencies = [
  "array-bytes",
  "blake3",
- "frame-metadata 19.0.0",
+ "frame-metadata 20.0.0",
  "parity-scale-codec",
  "scale-decode 0.13.1",
  "scale-info",
@@ -12129,7 +12129,7 @@ name = "pallet-example-view-functions"
 version = "1.0.0"
 dependencies = [
  "frame-benchmarking",
- "frame-metadata 19.0.0",
+ "frame-metadata 20.0.0",
  "frame-support",
  "frame-system",
  "log",
@@ -22900,7 +22900,7 @@ dependencies = [
 name = "sp-metadata-ir"
 version = "0.6.0"
 dependencies = [
- "frame-metadata 19.0.0",
+ "frame-metadata 20.0.0",
  "parity-scale-codec",
  "scale-info",
 ]
@@ -24655,7 +24655,7 @@ dependencies = [
  "cargo_metadata",
  "console",
  "filetime",
- "frame-metadata 19.0.0",
+ "frame-metadata 20.0.0",
  "jobserver",
  "merkleized-metadata",
  "parity-scale-codec",
diff --git a/Cargo.toml b/Cargo.toml
index b73e87d9bac26..b197e632782d7 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -787,7 +787,7 @@ frame-benchmarking-pallet-pov = { default-features = false, path = "substrate/fr
 frame-election-provider-solution-type = { path = "substrate/frame/election-provider-support/solution-type", default-features = false }
 frame-election-provider-support = { path = "substrate/frame/election-provider-support", default-features = false }
 frame-executive = { path = "substrate/frame/executive", default-features = false }
-frame-metadata = { version = "19.0.0", default-features = false }
+frame-metadata = { version = "20.0.0", default-features = false }
 frame-metadata-hash-extension = { path = "substrate/frame/metadata-hash-extension", default-features = false }
 frame-support = { path = "substrate/frame/support", default-features = false }
 frame-support-procedural = { path = "substrate/frame/support/procedural", default-features = false }
@@ -862,7 +862,7 @@ macro_magic = { version = "0.5.1" }
 maplit = { version = "1.0.2" }
 memmap2 = { version = "0.9.3" }
 memory-db = { version = "0.32.0", default-features = false }
-merkleized-metadata = { version = "0.3.0" }
+merkleized-metadata = { version = "0.4.0" }
 merlin = { version = "3.0", default-features = false }
 messages-relay = { path = "bridges/relays/messages" }
 metered = { version = "0.6.1", default-features = false, package = "prioritized-metered-channel" }
diff --git a/prdoc/pr_7607.prdoc b/prdoc/pr_7607.prdoc
new file mode 100644
index 0000000000000..0048ac8e9538e
--- /dev/null
+++ b/prdoc/pr_7607.prdoc
@@ -0,0 +1,20 @@
+title: Add Runtime Api version to metadata
+doc:
+- audience: Runtime Dev
+  description: |-
+    The runtime API implemented version is not explicitly shown in metadata, so here we add it to improve developer experience.
+
+    This closes #7352 .
+crates:
+- name: sp-api-proc-macro
+  bump: patch
+- name: sp-metadata-ir
+  bump: major
+- name: frame-support
+  bump: minor
+- name: frame-support-procedural
+  bump: patch
+- name: substrate-wasm-builder
+  bump: minor
+- name: pallet-example-view-functions
+  bump: minor
diff --git a/substrate/frame/support/procedural/src/pallet/expand/view_functions.rs b/substrate/frame/support/procedural/src/pallet/expand/view_functions.rs
index 0222301852c9b..d856b8c05d8bb 100644
--- a/substrate/frame/support/procedural/src/pallet/expand/view_functions.rs
+++ b/substrate/frame/support/procedural/src/pallet/expand/view_functions.rs
@@ -214,7 +214,7 @@ fn impl_view_function_metadata(
 					let pat = &typed.pat;
 					let ty = &typed.ty;
 					Some(quote::quote! {
-						#frame_support::__private::metadata_ir::PalletViewFunctionMethodParamMetadataIR {
+						#frame_support::__private::metadata_ir::PalletViewFunctionParamMetadataIR {
 							name: ::core::stringify!(#pat),
 							ty: #frame_support::__private::scale_info::meta_type::<#ty>(),
 						}
@@ -235,7 +235,7 @@ fn impl_view_function_metadata(
 		};
 
 		quote::quote! {
-			#frame_support::__private::metadata_ir::PalletViewFunctionMethodMetadataIR {
+			#frame_support::__private::metadata_ir::PalletViewFunctionMetadataIR {
 				name: ::core::stringify!(#name),
 				id: <#view_function_struct_ident<#type_use_gen> as #frame_support::view_functions::ViewFunction>::id().into(),
 				inputs: #frame_support::__private::sp_std::vec![ #( #inputs ),* ],
@@ -252,7 +252,7 @@ fn impl_view_function_metadata(
 		impl<#type_impl_gen> #pallet_ident<#type_use_gen> #where_clause {
 			#[doc(hidden)]
 			pub fn pallet_view_functions_metadata()
-				-> #frame_support::__private::Vec<#frame_support::__private::metadata_ir::PalletViewFunctionMethodMetadataIR> {
+				-> #frame_support::__private::Vec<#frame_support::__private::metadata_ir::PalletViewFunctionMetadataIR> {
 				#frame_support::__private::vec![ #( #view_functions ),* ]
 			}
 		}
diff --git a/substrate/primitives/api/proc-macro/src/runtime_metadata.rs b/substrate/primitives/api/proc-macro/src/runtime_metadata.rs
index 1706f8ca6fbb4..e68da53bef557 100644
--- a/substrate/primitives/api/proc-macro/src/runtime_metadata.rs
+++ b/substrate/primitives/api/proc-macro/src/runtime_metadata.rs
@@ -184,6 +184,7 @@ pub fn generate_decl_runtime_metadata<'a>(
 						.collect(),
 					docs: #docs,
 					deprecation_info: #deprecation,
+					version: impl_version.into(),
 				}
 			}
 		}
diff --git a/substrate/primitives/metadata-ir/src/types.rs b/substrate/primitives/metadata-ir/src/types.rs
index 986925e6f5168..c048733647d89 100644
--- a/substrate/primitives/metadata-ir/src/types.rs
+++ b/substrate/primitives/metadata-ir/src/types.rs
@@ -52,8 +52,10 @@ pub struct RuntimeApiMetadataIR<T: Form = MetaForm> {
 	pub methods: Vec<RuntimeApiMethodMetadataIR<T>>,
 	/// Trait documentation.
 	pub docs: Vec<T::String>,
-	/// Deprecation info
+	/// Deprecation info.
 	pub deprecation_info: DeprecationStatusIR<T>,
+	/// Runtime API version.
+	pub version: Compact<u32>,
 }
 
 impl IntoPortable for RuntimeApiMetadataIR {
@@ -65,6 +67,7 @@ impl IntoPortable for RuntimeApiMetadataIR {
 			methods: registry.map_into_portable(self.methods),
 			docs: registry.map_into_portable(self.docs),
 			deprecation_info: self.deprecation_info.into_portable(registry),
+			version: self.version,
 		}
 	}
 }
@@ -120,13 +123,13 @@ impl IntoPortable for RuntimeApiMethodParamMetadataIR {
 
 /// Metadata of a pallet view function method.
 #[derive(Clone, PartialEq, Eq, Encode, Decode, Debug)]
-pub struct PalletViewFunctionMethodMetadataIR<T: Form = MetaForm> {
+pub struct PalletViewFunctionMetadataIR<T: Form = MetaForm> {
 	/// Method name.
 	pub name: T::String,
 	/// Method id.
 	pub id: [u8; 32],
 	/// Method parameters.
-	pub inputs: Vec<PalletViewFunctionMethodParamMetadataIR<T>>,
+	pub inputs: Vec<PalletViewFunctionParamMetadataIR<T>>,
 	/// Method output.
 	pub output: T::Type,
 	/// Method documentation.
@@ -135,11 +138,11 @@ pub struct PalletViewFunctionMethodMetadataIR<T: Form = MetaForm> {
 	pub deprecation_info: DeprecationStatusIR<T>,
 }
 
-impl IntoPortable for PalletViewFunctionMethodMetadataIR {
-	type Output = PalletViewFunctionMethodMetadataIR<PortableForm>;
+impl IntoPortable for PalletViewFunctionMetadataIR {
+	type Output = PalletViewFunctionMetadataIR<PortableForm>;
 
 	fn into_portable(self, registry: &mut Registry) -> Self::Output {
-		PalletViewFunctionMethodMetadataIR {
+		PalletViewFunctionMetadataIR {
 			name: self.name.into_portable(registry),
 			id: self.id,
 			inputs: registry.map_into_portable(self.inputs),
@@ -152,18 +155,18 @@ impl IntoPortable for PalletViewFunctionMethodMetadataIR {
 
 /// Metadata of a pallet view function method argument.
 #[derive(Clone, PartialEq, Eq, Encode, Decode, Debug)]
-pub struct PalletViewFunctionMethodParamMetadataIR<T: Form = MetaForm> {
+pub struct PalletViewFunctionParamMetadataIR<T: Form = MetaForm> {
 	/// Parameter name.
 	pub name: T::String,
 	/// Parameter type.
 	pub ty: T::Type,
 }
 
-impl IntoPortable for PalletViewFunctionMethodParamMetadataIR {
-	type Output = PalletViewFunctionMethodParamMetadataIR<PortableForm>;
+impl IntoPortable for PalletViewFunctionParamMetadataIR {
+	type Output = PalletViewFunctionParamMetadataIR<PortableForm>;
 
 	fn into_portable(self, registry: &mut Registry) -> Self::Output {
-		PalletViewFunctionMethodParamMetadataIR {
+		PalletViewFunctionParamMetadataIR {
 			name: self.name.into_portable(registry),
 			ty: registry.register_type(&self.ty),
 		}
@@ -180,7 +183,7 @@ pub struct PalletMetadataIR<T: Form = MetaForm> {
 	/// Pallet calls metadata.
 	pub calls: Option<PalletCallMetadataIR<T>>,
 	/// Pallet view functions metadata.
-	pub view_functions: Vec<PalletViewFunctionMethodMetadataIR<T>>,
+	pub view_functions: Vec<PalletViewFunctionMetadataIR<T>>,
 	/// Pallet event metadata.
 	pub event: Option<PalletEventMetadataIR<T>>,
 	/// Pallet constants metadata.
diff --git a/substrate/primitives/metadata-ir/src/unstable.rs b/substrate/primitives/metadata-ir/src/unstable.rs
index d03a7ddad2685..60e3ebf6389f3 100644
--- a/substrate/primitives/metadata-ir/src/unstable.rs
+++ b/substrate/primitives/metadata-ir/src/unstable.rs
@@ -20,8 +20,8 @@
 use crate::{
 	DeprecationInfoIR, DeprecationStatusIR, OuterEnumsIR, PalletAssociatedTypeMetadataIR,
 	PalletCallMetadataIR, PalletConstantMetadataIR, PalletErrorMetadataIR, PalletEventMetadataIR,
-	PalletStorageMetadataIR, PalletViewFunctionMethodMetadataIR,
-	PalletViewFunctionMethodParamMetadataIR, StorageEntryMetadataIR,
+	PalletStorageMetadataIR, PalletViewFunctionMetadataIR, PalletViewFunctionParamMetadataIR,
+	StorageEntryMetadataIR,
 };
 
 use super::types::{
@@ -59,6 +59,7 @@ impl From<RuntimeApiMetadataIR> for RuntimeApiMetadata {
 			methods: ir.methods.into_iter().map(Into::into).collect(),
 			docs: ir.docs,
 			deprecation_info: ir.deprecation_info.into(),
+			version: ir.version.into(),
 		}
 	}
 }
@@ -145,8 +146,8 @@ impl From<PalletCallMetadataIR> for PalletCallMetadata {
 	}
 }
 
-impl From<PalletViewFunctionMethodMetadataIR> for PalletViewFunctionMetadata {
-	fn from(ir: PalletViewFunctionMethodMetadataIR) -> Self {
+impl From<PalletViewFunctionMetadataIR> for PalletViewFunctionMetadata {
+	fn from(ir: PalletViewFunctionMetadataIR) -> Self {
 		PalletViewFunctionMetadata {
 			name: ir.name,
 			id: ir.id,
@@ -158,8 +159,8 @@ impl From<PalletViewFunctionMethodMetadataIR> for PalletViewFunctionMetadata {
 	}
 }
 
-impl From<PalletViewFunctionMethodParamMetadataIR> for PalletViewFunctionParamMetadata {
-	fn from(ir: PalletViewFunctionMethodParamMetadataIR) -> Self {
+impl From<PalletViewFunctionParamMetadataIR> for PalletViewFunctionParamMetadata {
+	fn from(ir: PalletViewFunctionParamMetadataIR) -> Self {
 		PalletViewFunctionParamMetadata { name: ir.name, ty: ir.ty }
 	}
 }


Test patch:
diff --git a/substrate/frame/examples/view-functions/src/tests.rs b/substrate/frame/examples/view-functions/src/tests.rs
index 01a2d15dc6cde..e4d0642b3ed05 100644
--- a/substrate/frame/examples/view-functions/src/tests.rs
+++ b/substrate/frame/examples/view-functions/src/tests.rs
@@ -28,8 +28,7 @@ use scale_info::meta_type;
 use frame_support::{derive_impl, pallet_prelude::PalletInfoAccess, view_functions::ViewFunction};
 use sp_io::hashing::twox_128;
 use sp_metadata_ir::{
-	DeprecationStatusIR, PalletViewFunctionMethodMetadataIR,
-	PalletViewFunctionMethodParamMetadataIR,
+	DeprecationStatusIR, PalletViewFunctionMetadataIR, PalletViewFunctionParamMetadataIR,
 };
 use sp_runtime::testing::TestXt;
 
@@ -139,7 +138,7 @@ fn metadata_ir_definitions() {
 		pretty_assertions::assert_eq!(
 			pallet1.view_functions,
 			vec![
-				PalletViewFunctionMethodMetadataIR {
+				PalletViewFunctionMetadataIR {
 					name: "get_value",
 					id: get_value_id,
 					inputs: vec![],
@@ -147,10 +146,10 @@ fn metadata_ir_definitions() {
 					docs: vec![" Query value with no input args."],
 					deprecation_info: DeprecationStatusIR::NotDeprecated,
 				},
-				PalletViewFunctionMethodMetadataIR {
+				PalletViewFunctionMetadataIR {
 					name: "get_value_with_arg",
 					id: get_value_with_arg_id,
-					inputs: vec![PalletViewFunctionMethodParamMetadataIR {
+					inputs: vec![PalletViewFunctionParamMetadataIR {
 						name: "key",
 						ty: meta_type::<u32>()
 					},],
diff --git a/substrate/frame/support/test/tests/runtime_metadata.rs b/substrate/frame/support/test/tests/runtime_metadata.rs
index a098643abb911..8a791d5ad793a 100644
--- a/substrate/frame/support/test/tests/runtime_metadata.rs
+++ b/substrate/frame/support/test/tests/runtime_metadata.rs
@@ -200,6 +200,7 @@ fn runtime_metadata() {
 				" Documentation on multiline.",
 			]),
 			deprecation_info: DeprecationStatusIR::DeprecatedWithoutNote,
+			version: codec::Compact(1),
 
 		},
 		RuntimeApiMetadataIR {
@@ -238,6 +239,7 @@ fn runtime_metadata() {
 				" The `Core` runtime api that every Substrate runtime needs to implement.",
 			]),
 			deprecation_info: DeprecationStatusIR::NotDeprecated,
+			version: codec::Compact(5),
 		},
 	];